-
Notifications
You must be signed in to change notification settings - Fork 4
/
markermodel.h
416 lines (345 loc) · 19 KB
/
markermodel.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
#ifndef MARKERMODEL_H
#define MARKERMODEL_H
#include <QObject>
#include <QQmlListProperty>
#include <QThread>
#include <QDebug>
#include <QQuaternion>
#include <QVector4D>
#include <QDateTime>
#include <QFile>
#include <QDir>
#include <chrono>
#include <unordered_map>
#include <list>
#include "thymio-ar/vision-video-filter.h"
#include "transmem/transmem.h"
/*! \typedef rotAndTransPair
* \brief Represents a transformation consisting of a quaternion representing
* the rotation and a vector representing the translation.
*/
typedef std::pair<QQuaternion, QVector3D> rotAndTransPair;
/*! \def USE_MONITORING_FUNCTIONALITY
* \brief If defined the monitoring functionality of the marker model is compiled and
* can be used. It allows to write transformation updates received from the tracker as well
* as calculated output transformations to files.
*/
#define USE_MONITORING_FUNCTIONALITY
Q_DECLARE_METATYPE(Timestamp)
Q_DECLARE_METATYPE(rotAndTransPair)
Q_DECLARE_METATYPE(std::string)
#ifdef USE_MONITORING_FUNCTIONALITY
class MarkerModelMonitor;
#endif
/*! \class MarkerModel
* \brief Creates a new relationship between multiple markers. For every marker added to the model
* the marker model allows to calculate the position of this marker relativ to the special world
* center marker. The behavior of the marker model is determined through different parameter which
* for example specify whether a marker is visible or not.
*/
class MarkerModel : public QObject, public TransMem {
Q_OBJECT
public:
// Destructor, just need to specify it explictly when we use the monitoring functionality.
#ifdef USE_MONITORING_FUNCTIONALITY
MarkerModel();
~MarkerModel(){
stopMonitoring();
monitorThread.quit();
monitorThread.wait();
}
#endif
/*! Part of the qt-QML interface to set the world center marker. */
Q_PROPERTY(Landmark* worldCenterMarker READ getWorldCenterMarker WRITE setWorldCenterMarker)
/*! Part of the qt-QML interface to set the relative markers. */
Q_PROPERTY(QQmlListProperty<Landmark> worldCenterRelativeMarkers READ worldCenterRelativeMarkers)
/*! Part of the qt-QML interface to set the visibility threshold thConfVisible. */
Q_PROPERTY(double thConfVisible READ getThConfVisible WRITE setThConfVisible)
/*! Part of the qt-QML interface to set the update threshold thConfUpdate. */
Q_PROPERTY(double thConfUpdate READ getThConfUpdate WRITE setThConfUpdate)
/*! Part of the qt-QML interface to set the threshold thLastUpdate. */
Q_PROPERTY(double thLastUpdate READ getThLastUpdate WRITE setThLastUpdate)
/*! Part of the qt-QML interface to set the threshold thFixUpdate. */
Q_PROPERTY(double thFixUpdate READ getThFixUpdate WRITE setThFixUpdate)
/*! Part of the qt-QML interface to set the useTransMem. */
Q_PROPERTY(bool useTransMem READ getUseTransMem WRITE setUseTransMem)
#ifdef USE_MONITORING_FUNCTIONALITY
// QML Interface for the monitoring
Q_INVOKABLE void startMonitoring();
Q_INVOKABLE void stopMonitoring();
#endif
/*! \fn void updateModel()
* \brief Triggers the calculation of the output, i.e. the calculation of the
* transformation mapping from the world center marker to each markers as well
* as the calculation mapping from the world center marker to the camera.
*/
Q_INVOKABLE void updateModel();
/*! Interface for qt-QML. */
QQmlListProperty<Landmark> worldCenterRelativeMarkers();
void appendWorldCenterRelativeMarker(Landmark* worldCenterRelativeMarker);
int worldCenterRelativeMarkersCount() const;
Landmark* worldCenterRelativeMarker(int i) const;
void clearWorldCenterRelativeMarkers();
/*! \var double thConfVisible
* \brief Threshold for the visiblity of a marker. If the confidence
* of a marker is below this threshold then the marker is set to be
* not visible. Value can be set through the qt-QML interface.
*/
double thConfVisible{0.3};
double getThConfVisible(){ return thConfVisible; } void setThConfVisible(double th){ thConfVisible = th; }
/*! \var double thConfUpdate
* \brief Threshold for the update. If the current confidence of a marker
* is above this threshold then the transformation is stored in TransMem.
* Value can be set through the qt-QML interface.
*/
double thConfUpdate{0.45};
double getThConfUpdate(){ return thConfUpdate; } void setThConfUpdate(double th){ thConfUpdate = th; }
/*! \var double thLastUpdate
* \brief If TransMem was updated within the time specified by this
* threshold then the marker is visible.
* Value can be set through the qt-QML interface.
*/
double thLastUpdate{250}; double getThLastUpdate(){ return thLastUpdate; } void setThLastUpdate(double th){ thLastUpdate = th; }
/*! \var double thFixUpdate
* \brief If two markers are seen together within the time specified through this
* threshold then the fix transformation between these two markers is updated.
* Value can be set through the qt-QML interface.
*/
double thFixUpdate{250}; double getThFixUpdate(){ return thFixUpdate; } void setThFixUpdate(double th){ thFixUpdate = th; }
/*! \var bool useTransMem
* \brief Determines whether should be TransMem used or not.
* This functionality is implemented to demonstrate the functionality
* of TransMem.
*/
bool useTransMem{true}; bool getUseTransMem(){ return useTransMem; } void setUseTransMem(bool b) { useTransMem = b; }
public slots:
/*! \fn void markerPositionUpdated()
* \brief Invoked whenever the pose of a marker is updated through the tracker.
*/
void markerPositionUpdated();
private:
/*! \var Landmark* worldCenterMarker
* \brief The marker model calculates the mapping between this special world center marker
* and all relative markers every time void updateModel() is triggered. Additionally the position
* of this marker relative to the camera is updated.
*/
Landmark* worldCenterMarker;
/*! \var QVector<Landmark*> relativeMarkers
* \brief Stores all the relative marker whose position relative to the world center marker
* is calculated whenever void updateModel() is triggered.
*/
QVector<Landmark*> relativeMarkers;
/*! \fn StampedTransformationWithConfidence multiplySTWC( const StampedTransformationWithConfidence &lhs, const StampedTransformationWithConfidence &rhs)
* \brief Multiplies the transformations encoded in the two arguments \a lhs and \a rhs. If \a lhs encodes a mapping from B to C and \a rhs encodes a mapping
* from A to B then the returned StampedTransformationWithConfidence object encodes a mapping from A to C. The time field of the returned object is set to the
* time field of \a lhs. For the confidence and the max distance to entry fields the larger value of the corresponding field from either \a lhs or \a rhs is chosen.
* \return StampedTransformationWithConfidence object which encodes the multiplied transformation.
*/
StampedTransformationWithConfidence multiplySTWC( const StampedTransformationWithConfidence &lhs, const StampedTransformationWithConfidence &rhs);
/*! \fn StampedTransformationWithConfidence averageSTWCifEqual(StampedTransformationWithConfidence &lhs, StampedTransformationWithConfidence &rhs)
* \brief Compares the transformations encoded through \a lhs and \a rhs. The comparison is done with
* QVector4D compareRotAndTransPair(). The two StampedTransformationWithConfidence objects are averaged
* if this is the case. The averaging is done component-wise (\see QQuaternion avgAndNormalizeQuaternions(..)
* and QVector3D avgVector3D(..)). The time and maxDistanceToEntry for the result is chosen from \a lhs.
* The confidence of the result is set to the average of the confidence value of \a lhs and \a rhs.
* If the two transformations are not equal then the \a lhs is returned as a result.
*/
StampedTransformationWithConfidence averageSTWCifEqual(StampedTransformationWithConfidence &lhs, StampedTransformationWithConfidence &rhs);
/*! \fn StampedTransformationWithConfidence invertSTCW(StampedTransformationWithConfidence &lhs)
* \brief Inverts the transformation submitted in the argument. The other fields: time, confidence and max distance to
* entry remain untouched.
* \param lhs StampedTransforamtionWithConfidence which encode the transformation which is inverted by the function.
* \return StampedTransformationWithConfidence object which encodes inverted tranformation.
*/
StampedTransformationWithConfidence invertSTCW(StampedTransformationWithConfidence &lhs);
/*! \var const std::string camID
* \brief Identifier of the camera frame. (Coordinate system)
*/
const std::string camID {"cam"};
/*! \var std::string worldID
* \brief Identifier of the world center marker. Set through
* void setWorldCenterMarker( Landmark* worldCenterMarker).
*/
std::string worldID;
/*! \fn void setWorldCenterMarker(Landmark* worldCenterMarker)
* \brief Sets the world center marker and its identifier worldID.
* \param worldCenterMarker Pointer to the world center marker.
*/
void setWorldCenterMarker( Landmark* worldCenterMarker);
/*! \fn Landmark* getWorldCenterMarker
* \brief Returns a pointer to the world center marker
* \return Pointer to the world center marker. Returns null pointer if the world center
* marker is not set.
*/
Landmark* getWorldCenterMarker();
static void appendWorldCenterRelativeMarker(QQmlListProperty<Landmark>*, Landmark*);
static int worldCenterRelativeMarkersCount(QQmlListProperty<Landmark>*);
static Landmark* worldCenterRelativeMarker(QQmlListProperty<Landmark>*, int);
static void clearWorldCenterRelativeMarkers(QQmlListProperty<Landmark>*);
#ifdef USE_MONITORING_FUNCTIONALITY
// Thread which runs the monitoring.
QThread monitorThread;
#endif
// Signals used for the monitoring.
#ifdef USE_MONITORING_FUNCTIONALITY
signals:
// Object emits this signal everytime it received an update for a tranformation through
// updateLinkNow(..) from the QML model to inform the monitor also about the update.
/*! \fn void linkUpdate(const std::string &srcFrame, const std::string &dstFrame, const Timestamp &ts,
* const rotAndTransPair &transf, const float &conf)
* \brief This signal is emited every time the position of a marker is updated through the function
* updateLinkNow(..). It is used to inform the monitor about the update.
* \param srcFrame Identifier of the source coordinate system.
* \param dstFrame Identifier of the destination coordinate system.
* \param ts Timestamp when the update occured.
* \param transf Transformation mapping from srcFrame to dstFrame.
* \param conf Confidence value as an indication how good the updated transformation is.
*/
void linkUpdate(const std::string &srcFrame, const std::string &dstFrame, const Timestamp &ts,
const rotAndTransPair &transf, const float &conf);
// Object can emit this signal whenever a calculated transformation (result, output to QML model) was updated.
void transformationUpdate(const std::string &transID, const Timestamp &ts, const QMatrix4x4 &trans,
const float &avgLinkConfidence, const float &avgDistanceToEntry);
void registerLinkUpdateToMonitor(const std::string &srcFrame, const std::string &destFrame);
void registerTransformationToMonitor(const std::string &transID);
/*! \fn startMonitor()
* \brief Starts the monitoring. All registered links (LinkUpdate) and transformations are stored
* until void stopMonitor() is called or the maximal number of entries (MAX_NUMBER_OF_MONITORED_UPDATES_PER_LINK,
* MAX_NUMBER_OF_MONITORED_UPDATES_PER_TRANFORMATION) is reached.
*/
void startMonitor();
/*! \fn stopMonitor()
* \brief Stops the monitoring. For each registered link or transformation a seperate file is generated
* containing the corresponding transformations as well as additional information such as confidence or
* timestamp.
*/
void stopMonitor();
#endif
};
#ifdef USE_MONITORING_FUNCTIONALITY
/*! \struct LinkUpdate
* \brief Stores a single update of a link direct from the tracker.
*/
struct LinkUpdate {
Timestamp time;
rotAndTransPair transformation;
double confidence;
double timeSinceFirstRecordedUpdate;
QString srcFrame;
QString dstFrame;
};
/*! \struct TransformationUpdate
* \brief Stores as single transformation calculated as output of
* the marker model.
*/
struct TransformationUpdate {
Timestamp time;
rotAndTransPair transformation;
float avgerageLinkConfidence;
float maxDistanceToEntry;
double timeSinceFirstRecordedUpdate;
QString transformationID;
};
#endif
#ifdef USE_MONITORING_FUNCTIONALITY
/*! \class MarkerModelMonitor
* \brief Implements the monitoring functionality to monitor link updates
* as well as the transformations calculated as output of the marker model.
*/
class MarkerModelMonitor : public QObject{
Q_OBJECT
public slots:
/*! \fn void monitorLinkUpdate(const std::string &srcFrame, const std::string &destFrame, const Timestamp &ts,
* const rotAndTransPair &transf, const float &conf)
* \brief Slot triggered whenever the signal MarkerModel::linkUpdate(const std::string &srcFrame, const std::string
* &dstFrame, const Timestamp &ts, const rotAndTransPair &transf, const float &conf) is emitted. For more information
* see documentation of this signal.
*/
void monitorLinkUpdate(const std::string &srcFrame, const std::string &destFrame, const Timestamp &ts,
const rotAndTransPair &transf, const float &conf);
/*! \fn void monitorTransformationUpdate(const std::string &transID, const Timestamp &ts, const QMatrix4x4 &trans,
* const float &avgLinkConfidence, const float &maxDistanceToEntry)
* \brief Slot triggered whenever the signal MarkerModel::transformationUpdate(const std::string &transID, const Timestamp
* &ts, const QMatrix4x4 &trans, const float &avgLinkConfidence, const float &avgDistanceToEntry) is emitted. For more
* information see documentation of this signal.
*/
void monitorTransformationUpdate(const std::string &transID, const Timestamp &ts, const QMatrix4x4 &trans,
const float &avgLinkConfidence, const float &maxDistanceToEntry);
/*! \fn void registerLinkUpdateToMonitor(const std::string &srcFrame, const std::string &destFrame)
* \brief After registration the monitor records the link updates from \a srcFrame to \a destFrame
* as soon as the monitoring is started through startMonitoring().
*/
void registerLinkUpdateToMonitor(const std::string &srcFrame, const std::string &destFrame);
/*! \fn void registerTransformationToMonitor(const std::string &transID)
* \brief After registration the monitor records the transformation update with the
* identifier \transID as soon as the monitoring is started through startMonitoring().
*/
void registerTransformationToMonitor(const std::string &transID);
/*! \fn void startMonitoring()
* Starts the monitoring. For more information \see MarkerModel::startMonitor().
*/
void startMonitoring();
/*! \fn void stopMonitoring()
* Stops the monitoring. For more information \see MarkerModel::stopMonitor().
*/
void stopMonitoring();
protected:
/*! \var std::unordered_map<std::string, std::list<LinkUpdate> > monitoredLinkUpdates
* \brief Container which sotres the monitred link updates.
*/
std::unordered_map<std::string, std::list<LinkUpdate> > monitoredLinkUpdates;
/*! \var std::unordered_map<std::string, std::pair<std::string, std::string> > monitoredLinkIdentifier
* \brief Stores for each monitored link the identifier of the source and the destination.
*/
std::unordered_map<std::string, std::pair<std::string, std::string> > monitoredLinkIdentifier;
/*! \var std::unordered_map<std::string, std::list<TransformationUpdate> > monitoredTransformation
* \brief Container which stores the monitored transformations.
*/
std::unordered_map<std::string, std::list<TransformationUpdate> > monitoredTransformation;
/*! \var const unsigned int MAX_NUMBER_OF_MONITORED_UPDATES_PER_LINK
* \brief Maximal number of link updates the monitor can store. No more link updates
* are recorded if reached.
*/
const unsigned int MAX_NUMBER_OF_MONITORED_UPDATES_PER_LINK = 1000000;
/*! \var const unsigned int MAX_NUMBER_OF_MONITORED_UPDATES_PER_TRANFORMATION
* \brief Maximal number of transformation updates the monitor can store. No more
* transformation updates are stored if reached.
*/
const unsigned int MAX_NUMBER_OF_MONITORED_UPDATES_PER_TRANFORMATION = 1000000;
/*! \var const QString PATH
* \brief Location where the files containing the recorded transformations are dumped
* when the monitoring is stopped.
*/
const QString PATH = "..";
/*! \var Timestamp monitoringStartedAt
* \brief Time when the monitoring was triggered through startMonitoring().
*/
Timestamp monitoringStartedAt;
/*! \var bool currentlyMonitoring
* \brief True if the monitor is currently monitoring, false otherwise.
*/
bool currentlyMonitoring = false;
/*! \fn void writeAllTransformationUpateRecordsToFile(const QString &path)
* \brief Creates for each registered transformation a file which contains all recorded updates.
* The file is dumped at the location specified by \a path.
*/
void writeAllTransformationUpateRecordsToFile(const QString &path);
/*! \fn void writeAllLinkUpateRecordsToFile(const QString &path)
* \brief Creates for each registered link a file which contains all recorded link updates.
* The file is dumped at the location specified by \a path.
*/
void writeAllLinkUpateRecordsToFile(const QString &path);
/*! \fn void writeSingleLinkUpdateRecordToFile(std::list<LinkUpdate>& output, const QString &path, bool appenSRCandDST)
* \brief Writes all LinkUpdates stored in \a output into a file which is dumped at the location
* specified by \a path. If \a appendSRCandDST is true, then the identifier of the source and the destination connected through
* the monitored link is appended to each record.
*/
void writeSingleLinkUpdateRecordToFile(std::list<LinkUpdate>& output, const QString &path, bool appendSRCandDST);
/*! \fn void writeSingleTransforamtionUpdateRecordToFile(std::list<TransformationUpdate>& output, const QString &path)
* \brief Writes all TransformationUpdates stored in \a output into a file which is dumped at the location
* specified by \a path.
*/
void writeSingleTransforamtionUpdateRecordToFile(std::list<TransformationUpdate>& output, const QString &path);
};
#endif
#endif // MARKERMODEL_H