LARS
LARS (Light Augmented Reality System) is an open-source framework for light-based interaction and real-time tracking in multi-robot experiments. Inspired by ARK, LARS extends the augmented reality paradigm to robotic collectives by projecting dynamic visual cues and environments onto the arena, enabling new experimental possibilities for collective robotics research, education, and outreach. LARS features integrated tracking, light projection, and modular experiment control with a user-friendly Qt GUI.
Loading...
Searching...
No Matches
kilobottracker_copy.h
1
7
8#ifndef CALIBRATEARENA_H
9#define CALIBRATEARENA_H
10#include <ios>
11#include <vector>
12
13#define USE_CUDA true
14
15
16
17#ifndef USE_OPENCV3
18
19
20// OpenCV 2 includes
21#include <opencv2/highgui/highgui.hpp>
22#include <opencv2/video/video.hpp>
23#include <opencv2/imgproc/imgproc.hpp>
24#include <opencv2/videostab.hpp>
25#include <opencv2/features2d/features2d.hpp>
26#include <opencv2/stitching.hpp>//stitching/stitcher.hpp>
27#include <opencv2/opencv.hpp>
28//GPU stuff
29#include <opencv2/core/cuda.hpp>
30
31#ifdef USE_CUDA
32 #define MAT_TYPE cuda::GpuMat
33 #define CV_NS cv::cuda::
34#else
35 #define MAT_TYPE Mat
36 #define CV_NS cv::
37#endif
38
39#else
40
41using namespace std;
42
43// OpenCV 3 :
44#include <opencv2/highgui.hpp>
45#include <opencv2/video.hpp>
46#include <opencv2/imgproc.hpp>
47#include <opencv2/videostab.hpp>
48#include <opencv2/features2d.hpp>
49#include <opencv2/stitching.hpp>
50#include <opencv2/opencv.hpp>
51#include <opencv2/core/core.hpp>
52#include <opencv2/imgcodecs.hpp>
53#include <opencv2/videoio.hpp>
54#include <opencv2/core/ocl.hpp>
55#include <opencv2/cudaarithm.hpp>
56#include <opencv2/cudaimgproc.hpp>
57#include <opencv2/cudafilters.hpp>
58#include <opencv2/cudafeatures2d.hpp>
59#include <opencv2/cudawarping.hpp>
60
61#ifdef USE_CUDA
62#define MAT_TYPE cuda::GpuMat
63#define CV_NS cv::cuda::
64#else
65#define MAT_TYPE UMat
66#define CV_NS cv::
67#endif
68
69#endif
70
71// allow easy addressing of OpenCV functions
72using namespace cv;
73
74// Qt base include
75#include <QObject>
76#include <QPoint>
77#include <QPixmap>
78// for thread buffer communication
79#include <QSemaphore>
80#include <QTimer>
81#include <QElapsedTimer>
82#include <QTime>
83//#include <QColor>
84#include <QDebug>
85
86#include "kilobot.h"
87
88// buffers and semaphores
89struct srcBuffer {
90 MAT_TYPE full_warped_image;
91};
92
93#define BUFF_SIZE 2
94
95#define IM_WIDTH 1920 // 2304
96#define IM_HEIGHT 1200 //1536
97
98#define IDENTIFY_TIMEOUT 10
99
100
101enum srcDataType {
102 IMAGES,
103 VIDEO,
104 CAMERA
105};
106
107enum trackerType {
108 NO_TRACK,
109 CIRCLES_NAIVE,
110 CIRCLES_LOCAL,
111 MY_HAPPY_OTHER_TRACKER,
112};
113
114struct indexPair {
115 int a;
116 int b;
117};
118
119struct kiloLight {
120 lightColour col;
121 Point pos;
122};
123
124enum experimentType {
125 IDENTIFY,
126 ID_ASSIGNMENT,
127 CALIBRATION,
128 USER_EXP,
129 M_EXP
130};
131
132
133
134// DRAWABLES:
135
137 Point pos;
138 int r;
139 QColor col;
140 int thickness;
141 std::string text;
142 bool transparent;
143};
144
145struct drawnLine {
146 std::vector<Point> pos;
147 QColor col;
148 int thickness;
149 std::string text;
150 bool transparent;
151};
152
153class acquireThread;
155
162class KilobotTracker : public QObject
163{
164 Q_OBJECT
165
166public:
167 explicit KilobotTracker(QPoint smallImageSize = QPoint(300,300), QObject *parent = 0);
168 ~KilobotTracker();
169
170 KilobotExperiment * expt;
171
172 int dummyVar2000 = 1000; // MOHSEN! << just to check what is this value!
173
174 //Default tracking parameters and identification parameters
175// int kbMinSize = 5;//3;
176// int kbMaxSize = 16;//22;
177// int houghAcc = 19; // 27;
178// int cannyThresh = 61; //40;
179
180 int kbMinSize = 8;//10;//3;
181 int kbMaxSize = 12;//18;//22;
182 int houghAcc = 13;//12; // 27;
183 int cannyThresh = 90;//112; //40;
184
185 int kbLEDMinSize = kbMinSize/7;//3;
186 int kbLEDMaxSize = kbMinSize*10/7;//22; << !!
187 int LEDhoughAcc = houghAcc; // 27;
188 int LEDcannyThresh = cannyThresh; //40;
189
190 int maxIDtoCheck = 100;
191 uint manualID;
192 // camera parameters
193 int height_x_adj = 10;
194 int height_y_adj = 10;
195
196 //Default color threshold detection parameters
197 float redLThreshold = 0.75; //0.6
198 float redHThreshold = 0.0;
199 float greenLThreshold = 0.56;
200 float greenHThreshold = 0.75;
201 float blueLThreshold = 0.65;
202 float blueHThreshold = 0.0;
203
204 QList<Vec3f> detectedCircles;
205
206 bool debugBool = false;
207
208signals:
213 void errorMessage(QString);
214
215 void setStitchedImage(QPixmap);
216
217 void capturedImage(cv::Mat);
218
219 void identifyKilo(uint8_t);
220
221 void broadcastMessage(kilobot_broadcast);
222
223 void clearMsgQueue();
224
225 void startExperiment(bool);
226
227 void stopExperiment();
228
229 void toggleExpButton(int);
230
231 void activateExpButtons(int);
232
233 void setRuntimeIdentificationLock(bool);
234
235 void kiloList(QVector<Kilobot *>);
236
237 void circlesToDrawSig(QVector < drawnCircle >);
238
239
240public slots:
246 void LOOPstartstop(int stage);
247
252 void LOOPiterate();
253
259
260
261 // MOHSEN
262 bool RUNcapture();
263
268 void SETUPfindKilobots();
269
274 void identifyKilobots();
275
276
277 // MOHSEN
278
279 void updateCropPoints(QRect cropRect);
280
281 QSize getImageSize();
282
283// void drawOverlayPub(Mat &);
284
285// void getCircles(QVector < drawnCircle >);
286
287
288
289 // drawing slots
290 void drawCircle(QPointF pos, float r, QColor col, int thickness = 2, std::string text ="", bool transparent = false) {
291 int r_int = r;
292 this->circsToDraw.push_back(drawnCircle {Point(pos.x(),pos.y()), r_int, col, thickness, text, transparent});
293 }
294
295 void drawLine(std::vector<cv::Point> pos, QColor col, int thickness = 2, std::string text ="", bool transparent = false) {
296 this->linesToDraw.push_back(drawnLine {pos, col, thickness, text, transparent});
297 }
298
299 void clearDrawings() {
300 this->circsToDraw.clear();
301 this->linesToDraw.clear();
302 }
303
304 void drawCircleOnRecordedImage(QPointF pos, float r, QColor col, int thickness = 2, std::string text = "") {
305 int r_int = r;
306 this->circsToDrawFinal.push_back(drawnCircle {Point(pos.x(),pos.y()), r_int, col, thickness, text});
307 }
308
309 void clearDrawingsOnRecordedImage() {
310 this->circsToDrawFinal.clear();
311 }
312
313 void saveImage(QString file) {
314 if (!finalImageCol.empty()) {
315 // before saving I draw what I need to draw on the FinalImage
316 for (int i = 0; i < this->circsToDrawFinal.size(); ++i) {
317 cv::circle(finalImageCol,this->circsToDrawFinal[i].pos, this->circsToDrawFinal[i].r,
318 Scalar(this->circsToDrawFinal[i].col.blue(),this->circsToDrawFinal[i].col.green(),this->circsToDrawFinal[i].col.red(),0.5),
319 this->circsToDrawFinal[i].thickness);
320 }
321 cv::imwrite(file.toStdString(),finalImageCol);
322 }
323 }
324
325 void saveVideoFrames(QString file, unsigned int numofframes) {
326 savecamerasframes = true;
327 savecamerasframesdir=file;
328 numberofframes=numofframes;
329 }
330
331 // accessors - docs not required??
332 void setSourceType(bool val) {if (val) this->srcType = CAMERA; else this->srcType = VIDEO;}
333
334 void setKbMin(int val){this->kbMinSize = val;}
335 void setKbMax(int val) {this->kbMaxSize = val;}
336 void setCannyThresh(int val) {this->cannyThresh = val;}
337 void setHoughAcc(int val) {this->houghAcc = val;}
338
339 void setKbLMin(int val){this->kbLEDMinSize = val;}
340 void setKbLMax(int val) {this->kbLEDMaxSize = val;}
341 void setLEDCannyThresh(int val) {this->LEDcannyThresh = val;}
342 void setLEDHoughAcc(int val) {this->LEDhoughAcc = val;}
343
344
345 void setLowRLED(int val){this->redLThreshold = (double) val/100.0;}// qDebug() << "value: " << this->redLThreshold;}
346 void setLowGLED(int val) {this->greenLThreshold = (double) val/100.0;}
347 void setLowBLED(int val) {this->blueLThreshold = (double) val/100.0;}
348 void setHiRLED(int val){this->redHThreshold = (double) val/100.0;}
349 void setHiGLED(int val) {this->greenHThreshold = (double) val/100.0;}
350 void setHiBLED(int val) {this->blueHThreshold = (double) val/100.0;}
351
352
353 void setHeightXSlider(int val) {this->height_x_adj = val;}
354 void setHeightYSlider(int val) {this->height_y_adj = val;}
355
356 void manuallyassignID(QPoint position);
357
363 void setVideoDir(QString dir) {this->videoPath = dir;}
364
365 void updateKilobotStates();
366
367 void getInitialKilobotStates();
368
369 void setTrackingType(int t_type) {this->t_type = t_type;}
370 void updateExperimentBroadcastingState(bool BroadcastingState)
371 {
372 experimentIsBroadcasting=BroadcastingState;
373 }
374
381 void showIds(bool toggle) {this->showIDs = toggle;}
382 void detectred(bool toggle) {this->m_detectred = toggle;}
383 void detectgreen(bool toggle) {this->m_detectgreen = toggle;}
384 void detectblue(bool toggle) {this->m_detectblue = toggle;}
385 void manualIDassignment(bool toggle) {this->m_assignIDmanually = toggle;}
386 void enableRuntimeIdentification(bool toggle) {this->m_runtimeIDenabled = toggle;}
387
388
389 void maxIDtoTry(QString maxIdStr) {this->maxIDtoCheck = maxIdStr.toInt();}
390 void setManualID(QString manID) {this->manualID = manID.toUInt();}
391 void setFlipangle(double angle);
392
398
399private:
400
401 // PRIVATE METHODS
402
403
408 void trackKilobots();
409
414 void SETUPstitcher();
415
420 void showMat(Mat &);
421
429
430#ifdef USE_CUDA
431 kiloLight getKiloBotLight(cuda::GpuMat channels[3], Point centreOfBox, int index);
432 kiloLight getKiloBotLightAdaptive(cuda::GpuMat channels[3], Point centreOfBox, int index);
433 void getKiloBotLights(Mat &display);
434#else
435 kiloLight getKiloBotLight(Mat channels[3], Point centreOfBox, int index);
436 kiloLight getKiloBotLightAdaptive(Mat channels[3], Point centreOfBox, int index);
437#endif
438
447 Rect getKiloBotBoundingBox(int index, float scale);
448
453 void THREADSlaunch();
454
455 void THREADSstop();
456
457 void identifyKilobot(int);
458 void identifyKilobot(int,bool);
459
460 void runtimeIdentify();
461
462 void drawOverlay(Mat &);
463
464 void getDetectedCircles();
465
466
467 // INTERNAL VARIABLES
468
469 int t_type = POS | ADAPTIVE_LED | ROT;
470
471 bool experimentIsBroadcasting=false;
472
473 Mat finalImageCol;
474
475#ifdef USE_CUDA
476 cuda::GpuMat finalImageB;
477 cuda::GpuMat finalImageG;
478 cuda::GpuMat finalImageR;
479 cuda::GpuMat fullImages[3];
480 cuda::GpuMat grayImage;
481 // make thread safe
482 cuda::Stream stream;
483#else
484 Mat finalImage;
485 Mat fullImages[3];
486#endif
487
488 MAT_TYPE warpedImages;
489 MAT_TYPE warpedMasks;
490 Point corners;
491 Size sizes;
492
493 vector < Mat > Ks;
494 vector < Mat > Rs;
495 Point2f arenaCorners[4];
496 bool haveCalibration = false;
497 QTimer tick;
498
499 acquireThread * threads = NULL;
500
501 int time = 0;
506 QPoint smallImageSize;
507
508 Ptr<detail::ExposureCompensator> compensator;
509 Ptr<detail::Blender> blender;
510
511 QElapsedTimer timer;
512
513 bool loadFirstIm = false;
514
515 srcDataType srcType = CAMERA;
516 QString videoPath;
517
518 trackerType trackType = CIRCLES_NAIVE;// CIRCLES_LOCAL; // CIRCLES_LOCAL;
519
520 QVector < Kilobot * > kilos;
521
522 QVector < float > kiloHeadings;
523
524 QVector < QPointF > kiloOldPos;
525
526 QVector < QVector < int > > exclusionTestsIndices;
527
528 float last_time = 0.0f;
529
530 Size fullSize;
531 Point fullCorner;
532
533 int currentID = 0;
534 uint found = IDENTIFY_TIMEOUT;
535 QVector < uint > foundIDs;
536 QVector < int > assignedCircles;
537
538 experimentType expType = USER_EXP; // M_EXP;//;
539
540 Mat testAdap;
541
542 QVector < drawnCircle > circsToDraw;
543 QVector < drawnLine > linesToDraw;
544 QVector < drawnCircle > circsToDrawFinal;
545
546// QList<Vec3f> detectedCircles;
547
548#ifdef USE_CUDA
549 Ptr<cuda::HoughCirclesDetector> hough;
550 // RGB Hough
551 Ptr<cuda::HoughCirclesDetector> hough2;
552 cuda::GpuMat kbLocs;
553
554 Ptr<cuda::CLAHE> clahe;
555 Mat element = cv::getStructuringElement(MORPH_ELLIPSE,Size(7,7));
556 Ptr<cuda::Filter> dilateFilter;
557#endif
558
559 bool showIDs = true;
560 int flipangle = 0;
561 bool m_detectred=true;
562 bool m_detectgreen=true;
563 bool m_detectblue=true;
564 bool m_assignIDmanually=false;
565 bool m_runtimeIDenabled=true;
566
567 QVector <int> lost_count;
568
569 int m_runtimeIdentificationTimer = 0;
570 bool m_ongoingRuntimeIdentification = false;
571 QVector <int> pendingRuntimeIdentification;
572 QElapsedTimer runtimeIDtimer;
573
574 //video saving
575 bool savecamerasframes=false;
576 unsigned int numberofframes;
577 QString savecamerasframesdir;
578
579
580};
581
582
583
584#endif // CALIBRATEARENA_H
Definition kilobotexperiment.h:13
void SETUPloadCalibration()
loadCalibration Load the calibration matrices from an OpenCV FileStorage format
Definition kilobottracker_copy.cpp:3277
void showIds(bool toggle)
showIds
Definition kilobottracker_copy.h:381
void errorMessage(QString)
errorMessage Qt signal to update the UI message QLabel
void LOOPiterate()
iterateTracker Use the existing feature matches to stitch the images and track the kilobots
Definition kilobottracker_copy.cpp:431
void LOOPstartstop(int stage)
startLoop This slot is the target of the timeout on the QTimer tick, and fetches warped images from t...
Definition kilobottracker_copy.cpp:325
void RefreshDisplayedImage()
RefreshDisplayedImage Refresh the displayed image on the GUI.
Definition kilobottracker_copy.cpp:3397
void setVideoDir(QString dir)
setVideoDir
Definition kilobottracker_copy.h:363
void identifyKilobots()
identifyKilobots Find out what IDs the Kilobots have
Definition kilobottracker_copy.cpp:845
void SETUPfindKilobots()
findKilobots Find the locations of Kilobots in the stitched image
Definition kilobottracker_copy.cpp:745
The acquireThread class This thread acquires input data from a source, applies the local warps to the...
Definition kilobottracker_copy.cpp:42
Definition voronoii.cpp:9
Definition kilobottracker_copy.h:136
Definition kilobottracker_copy.h:145
Definition kilobottracker_copy.h:114
Definition kilobottracker_copy.h:119
Definition kilobot.h:31
Definition kilobottracker_copy.h:89