MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
mitkOptitrackTrackingDevice.cpp
Go to the documentation of this file.
1/*============================================================================
2
3The Medical Imaging Interaction Toolkit (MITK)
4
5Copyright (c) German Cancer Research Center (DKFZ)
6All rights reserved.
7
8Use of this source code is governed by a 3-clause BSD license that can be
9found in the LICENSE file.
10
11============================================================================*/
14
15#ifdef MITK_USE_OPTITRACK_TRACKER
16
17
18
22#include <NPTrackingTools.h>
23
24//=======================================================
25// Static method: IsDeviceInstalled
26//=======================================================
28{
29 return true;
30}
31
32//=======================================================
33// Constructor
34//=======================================================
36 : mitk::TrackingDevice(),
37 m_initialized(false)
38{
39 //Set the mitk device information
40 SetData(mitk::DeviceDataNPOptitrack);
41
42 //Clear List of tools
43 this->m_AllTools.clear();
44}
45
46//=======================================================
47// Destructor
48//=======================================================
50{
51 MITK_DEBUG << "Deleting OptitrackTrackingDevice";
52 int result;
53
54 // If device is in Tracking mode, stop the Tracking firts
56 {
57 MITK_DEBUG << "OptitrackTrackingDevice in Tracking State -> Stopping Tracking";
58 result = this->StopTracking();
59
60 if(result == NPRESULT_SUCCESS){
61 MITK_INFO << "OptitrackTrackingDevice Stopped";
62 }
63 else
64 {
65 MITK_INFO << "Error during Stopping";
67 }
68 }
69
70 // If device is Ready, Close the connection to device and release the memory
72 {
73 MITK_DEBUG << "OptitrackTrackingDevice in Ready State -> Closing the Connection";
74 result = this->CloseConnection();
75
76 if(result)
77 {
78 MITK_INFO << "OptitrackTrackingDevice Connection closed";
79 }
80 else
81 {
82 MITK_DEBUG << "Error during Closing Connection";
84 }
85 }
86
87 // Set the device off
88 m_initialized = false;
89 // Change State to Setup
91 MITK_DEBUG <<"OptitrackTrackingDevice deleted successfully";
92}
93
94//=======================================================
95// OpenConnection
96//=======================================================
98{
99 // Not initialize the system twice.
100 if(!m_initialized)
101 {
102 MITK_DEBUG << "Initialize Optitrack Tracking System";
103
104 if( this->InitializeCameras() )
105 {
106 m_initialized = true; // Set the initialized variable to true
107 this->SetState(mitk::TrackingDevice::Ready);
108 if(this->m_calibrationPath.empty()){
109 MITK_INFO << "Numer of connected cameras = " << TT_CameraCount();
110 MITK_WARN << "Attention: No calibration File defined !!";
111 return m_initialized;
112 }
113 else
114 {
115 this->LoadCalibration();
116 }
117 }
118 else
119 {
120 m_initialized = false; // Set the initialized variable to false
121 this->SetState(mitk::TrackingDevice::Setup); // Set the State to Setup
122 MITK_INFO << "Device initialization failed. Device is still in setup state";
123 mitkThrowException(mitk::IGTException) << "Device initialization failed. Device is still in setup state";
124 }
125 }
126 //this->LoadCalibration();
127 return m_initialized;
128}
129
130//=======================================================
131// InitializeCameras
132//=======================================================
134{
135 MITK_DEBUG << "Initialize Optitrack";
136 int result;
137
138 result = TT_Initialize(); // Initialize the cameras
139
140 if(result == NPRESULT_SUCCESS)
141 {
142 MITK_DEBUG << "Optitrack Initialization Succeed";
143 return true;
144 }
145 else
146 {
148 // If not succeed after OPTITRACK_ATTEMPTS times launch exception
149 MITK_INFO << "Optitrack Tracking System cannot be initialized \n" << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(result);
150 mitkThrowException(mitk::IGTException) << "Optitrack Tracking System cannot be initialized \n" << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(result);
151 return false;
152 }
153}
154
155//=======================================================
156// LoadCalibration
157//=======================================================
159{
160 MITK_DEBUG << "Loading System Calibration";
161 int resultLoadCalibration;
162
163 // Check the file path
164 if(this->m_calibrationPath.empty()){
165 MITK_INFO << "Calibration Path is empty";
166 mitkThrowException(mitk::IGTException) << "Calibration Path is empty";
167 return false;
168 }
169
170 // Once the system is ready and Initialized , a calibration file is loaded.
171 if(this->m_initialized)
172 {
173
174 for( int i=OPTITRACK_ATTEMPTS; i>0; i--)
175 {
176 resultLoadCalibration = TT_LoadCalibration(this->m_calibrationPath.c_str());
177
178 if(resultLoadCalibration != NPRESULT_SUCCESS)
179 {
180 MITK_DEBUG << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(resultLoadCalibration);
181 MITK_DEBUG << "Trying again...";
182 }
183 else
184 {
185 MITK_DEBUG << "Calibration file has been loaded successfully";
186 return true;
187 }
188
189 }
190
191 MITK_INFO << "System cannot load a calibration file";
192 mitkThrowException(mitk::IGTException) << "System cannot load a calibration file";
193
194 }
195 else
196 {
197 MITK_INFO << "System is not ready for load a calibration file because it has not been initialized yet";
198 mitkThrowException(mitk::IGTException) << "System is not ready for load a calibration file because it has not been initialized yet";
199 return false;
200 }
201
202 // Never reach this point
203 return false;
204}
205
206//=======================================================
207// SetCalibrationPath
208//=======================================================
209void mitk::OptitrackTrackingDevice::SetCalibrationPath(std::string calibrationPath){
210
211 MITK_DEBUG << "SetcalibrationPath";
212 MITK_DEBUG << calibrationPath;
213
214 // Check the file path
215 if(calibrationPath.empty())
216 {
217 MITK_INFO << "Calibration Path is empty";
218 //mitkThrowException(mitk::IGTException) << "Calibration Path is empty";
219 return;
220 }
221
222 this->m_calibrationPath = calibrationPath;
223 MITK_INFO << "Calibration Path has been updated to: " << this->m_calibrationPath;
224 return;
225}
226
227//=======================================================
228// CloseConnection
229//=======================================================
231{
232 MITK_DEBUG << "CloseConnection";
233 int resultStop, resultShutdown;
234
235 if(m_initialized) // Close connection if the System was initialized first
236 {
237 if(this->GetState() == mitk::TrackingDevice::Tracking)
238 {
239 MITK_DEBUG << "Device state: Tracking -> Stoping the Tracking";
240 resultStop = this->StopTracking(); //Stop tracking on close
241 }
242
244
245 for( int i=OPTITRACK_ATTEMPTS; i>0; i--)
246 {
247
248 TT_ClearTrackableList();
249 resultShutdown = TT_Shutdown();
250
251 if(resultShutdown == NPRESULT_SUCCESS)
252 {
253 MITK_DEBUG << "System has been Shutdown Correctly";
254 Sleep(2000);
255 return true;
256 }
257 else
258 {
259 MITK_DEBUG << "System cannot ShutDown now. Trying again...";
260 }
261 }
262
263 MITK_INFO << "System cannot ShutDown now";
265 return false;
266 }
267 else
268 {
269 MITK_INFO << "System has not been initialized. Close connection cannot be done";
270 mitkThrowException(mitk::IGTException) << "System has not been initialized. Close connection cannot be done";
271 return false;
272 }
273
274 return false;
275}
276
277//=======================================================
278// StartTracking
279//=======================================================
281{
282 MITK_DEBUG << "StartTracking";
283 bool resultIsTrackableTracked;
284
285 if (this->GetState() != mitk::TrackingDevice::Ready)
286 {
287 MITK_INFO << "System is not in State Ready -> Cannot StartTracking";
288 mitkThrowException(mitk::IGTException) << "System is not in State Ready -> Cannot StartTracking";
289 return false;
290 }
291
292 this->SetState(mitk::TrackingDevice::Tracking);
293
294 // Change the m_StopTracking Variable to false
295 this->m_StopTrackingMutex.lock();
296 this->m_StopTracking = false;
297 this->m_StopTrackingMutex.unlock();
298
299 /******************************************************************************
300 ###############################################################################
301 TODO: check the timestamp from the Optitrack API
302 ###############################################################################
303 ******************************************************************************/
305
306 // Launch multiThreader using the Function ThreadStartTracking that executes the TrackTools() method
307 m_Thread = std::thread(&OptitrackTrackingDevice::ThreadStartTracking, this); // start a new thread that executes the TrackTools() method
308
309 // Information for the user
310 if(GetToolCount() == 0) MITK_INFO << "No tools are defined";
311
312 for ( int i = 0; i < GetToolCount(); ++i) // use mutexed methods to access tool container
313 {
314 resultIsTrackableTracked = TT_IsTrackableTracked(i);
315 if(resultIsTrackableTracked)
316 {
317 MITK_DEBUG << "Trackable " << i << " is inside the Tracking Volume and it is Tracked";
318 }
319 else
320 {
321 MITK_DEBUG << "Trackable " << i << " is not been tracked. Check if it is inside the Tracking volume";
322 }
323
324 }
325
326 return true;
327}
328
329//=======================================================
330// StopTracking
331//=======================================================
333{
334 MITK_DEBUG << "StopTracking";
335
336 if (this->GetState() == mitk::TrackingDevice::Tracking) // Only if the object is in the correct state
337 {
338 //Change the StopTracking value
339 m_StopTrackingMutex.lock(); // m_StopTracking is used by two threads, so we have to ensure correct thread handling
340 m_StopTrackingMutex.unlock();
341 this->SetState(mitk::TrackingDevice::Ready);
342 }
343 else
344 {
345 m_TrackingFinishedMutex.unlock();
346 MITK_INFO << "System is not in State Tracking -> Cannot StopTracking";
347 mitkThrowException(mitk::IGTException) << "System is not in State Tracking -> Cannot StopTracking";
348 return false;
349 }
350
351 /******************************************************************************
352 ###############################################################################
353 TODO: check the timestamp from the Optitrack API
354 ###############################################################################
355 ******************************************************************************/
357
358 m_TrackingFinishedMutex.unlock();
359 return true;
360}
361
362//=======================================================
363// ThreadStartTracking
364//=======================================================
366{
367 MITK_DEBUG << "ThreadStartTracking";
368 this->TrackTools();
369}
370
371//=======================================================
372// GetOptitrackTool
373//=======================================================
375{
376 MITK_DEBUG << "ThreadStartTracking";
377 OptitrackTrackingTool* t = nullptr;
378
379 std::lock_guard<std::mutex> toolsMutexLockHolder(m_ToolsMutex); // lock and unlock the mutex
380 if(toolNumber < m_AllTools.size())
381 {
382 t = m_AllTools.at(toolNumber);
383 }
384 else
385 {
386 MITK_INFO << "The tool numbered " << toolNumber << " does not exist";
387 mitkThrowException(mitk::IGTException) << "The tool numbered " << toolNumber << " does not exist";
388 }
389 return t;
390}
391
392//=======================================================
393// GetToolCount
394//=======================================================
396{
397 MITK_DEBUG << "GetToolCount";
398 std::lock_guard<std::mutex> lock(m_ToolsMutex); // lock and unlock the mutex
399 return ( int)(this->m_AllTools.size());
400}
401
402//=======================================================
403// TrackTools
404//=======================================================
406{
407 MITK_DEBUG << "TrackTools";
408
409 Point3D position;
410 ScalarType t = 0.0;
411
412 try
413 {
414 bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here
415 this->m_StopTrackingMutex.lock(); // update the local copy of m_StopTracking
416 localStopTracking = this->m_StopTracking;
417
418 /* lock the TrackingFinishedMutex to signal that the execution rights are now transfered to the tracking thread */
419 if (!localStopTracking)
420 {
421 m_TrackingFinishedMutex.lock();
422 }
423
424 this->m_StopTrackingMutex.unlock();
425 while ((this->GetState() == mitk::TrackingDevice::Tracking) && (localStopTracking == false))
426 {
427 // For each Tracked Tool update the position and orientation
428 for ( int i = 0; i < GetToolCount(); ++i) // use mutexed methods to access tool container
429 {
430 OptitrackTrackingTool* currentTool = this->GetOptitrackTool(i);
431 if(currentTool != nullptr)
432 {
433 currentTool->updateTool();
434 MITK_DEBUG << "Tool number " << i << " updated position";
435 }
436 else
437 {
438 MITK_DEBUG << "Get data from tool number " << i << " failed";
439 mitkThrowException(mitk::IGTException) << "Get data from tool number " << i << " failed";
440 }
441 }
442
443 /* Update the local copy of m_StopTracking */
444 this->m_StopTrackingMutex.lock();
445 localStopTracking = m_StopTracking;
446 this->m_StopTrackingMutex.unlock();
448 } // tracking ends if we pass this line
449
450 m_TrackingFinishedMutex.unlock(); // transfer control back to main thread
451 }
452 catch(...)
453 {
454 m_TrackingFinishedMutex.unlock();
455 this->StopTracking();
456 mitkThrowException(mitk::IGTException) << "Error while trying to track tools. Thread stopped.";
457 }
458}
459
460//=======================================================
461// SetCameraParams
462//=======================================================
463bool mitk::OptitrackTrackingDevice::SetCameraParams(int exposure, int threshold , int intensity, int videoType )
464{
465 MITK_DEBUG << "SetCameraParams";
466
467 if(this->m_initialized)
468 {
469 int num_cams = 0;
470 int resultUpdate;
471 bool resultSetCameraSettings;
472
473 for( int i=OPTITRACK_ATTEMPTS; i>0; i--)
474 {
475 resultUpdate = TT_Update(); // Get Update for the Optitrack API
476 if(resultUpdate == NPRESULT_SUCCESS)
477 {
478 MITK_DEBUG << "Update Succeed";
479 num_cams = TT_CameraCount();
480 i = 0;
481 }
482 else
483 {
485 MITK_DEBUG << "Trying again...";
486 Sleep(30);
487 }
488 }
489
490 // If no cameras are connected
491 if(num_cams == 0)
492 {
493 MITK_DEBUG << "No cameras are connected to the device";
494 return false;
495 mitkThrowException(mitk::IGTException) << "No cameras are connected to the device";
496 }
497
498 for(int cam = 0; cam < num_cams; cam++) // for all connected cameras
499 {
500 for( int i=OPTITRACK_ATTEMPTS; i>0; i--)
501 {
502 resultUpdate = TT_Update(); // Get Update for the Optitrack API
503
504 if(resultUpdate == NPRESULT_SUCCESS)
505 {
506 MITK_DEBUG << "Update Succeed for camera number " << cam;
507 resultSetCameraSettings = TT_SetCameraSettings(cam,videoType,exposure,threshold,intensity);
508
509 if(resultSetCameraSettings)
510 {
511 MITK_INFO << "Camera # "<<cam<< " params are set";
512 i = 0; // End attempts for camera #cam
513 }
514 else
515 {
516 MITK_DEBUG << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(resultSetCameraSettings);
517 if(i == 1)
518 mitkThrowException(mitk::IGTException) << "Camera number " << cam << " failed during setting the params. Error: " << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(resultSetCameraSettings);
519 }
520 }
521 else
522 {
524 MITK_DEBUG << "Update: Trying again...";
525 }
526 }
527 }
528 }
529 else
530 {
531 MITK_INFO << "System is not Initialized -> System is not ready to perform the Camera Parameters Setting";
532 mitkThrowException(mitk::IGTException) << "System is not Initialized -> System is not ready to perform the Camera Parameters Setting";
533 return false;
534 }
535 return true;
536}
537
538//=======================================================
539// GetTool
540//=======================================================
542{
543 return static_cast<mitk::TrackingTool*>(GetOptitrackTool(toolNumber));
544}
545
546//=======================================================
547// AddToolByFileName
548//=======================================================
550{
551 bool resultSetToolByFileName;
552 if(m_initialized)
553 {
554 OptitrackTrackingTool::Pointer t = OptitrackTrackingTool::New();
555 resultSetToolByFileName= t->SetToolByFileName(fileName);
556
557 if(resultSetToolByFileName)
558 {
559 this->m_AllTools.push_back(t);
560 MITK_INFO << "Added tool "<<t->GetToolName()<< ". Tool vector size is now: "<<m_AllTools.size();
561 return true;
562 }
563 else
564 {
565 MITK_INFO << "Tool could not be added";
566 mitkThrowException(mitk::IGTException) << "Tool could not be added";
567 return false;
568 }
569 }
570 else
571 {
572 MITK_INFO << "System is not Initialized -> Cannot Add tools";
573 mitkThrowException(mitk::IGTException) << "System is not Initialized -> Cannot Add tools";
574 return false;
575 }
576}
577
578
579//=======================================================
580// IF Optitrack is not installed set functions to warnings
581//=======================================================
582
583#else
584
585//=======================================================
586// Static method: IsDeviceInstalled
587//=======================================================
589{
590 return false;
591}
592
593//=======================================================
594// Constructor
595//=======================================================
597 : mitk::TrackingDevice(),
598 m_initialized(false)
599{
600 MITK_WARN("IGT") << "Error: " << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(100);
601}
602
603//=======================================================
604// Destructor
605//=======================================================
610
611//=======================================================
612// OpenConnection
613//=======================================================
615{
616 MITK_WARN("IGT") << "Error: " << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(100);
617 return false;
618}
619
620//=======================================================
621// InitializeCameras
622//=======================================================
624{
625 MITK_WARN("IGT") << "Error: " << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(100);
626 return false;
627}
628
629//=======================================================
630// LoadCalibration
631//=======================================================
633{
634 MITK_WARN("IGT") << "Error: " << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(100);
635 return false;
636}
637
638//=======================================================
639// SetcalibrationPath
640//=======================================================
641void mitk::OptitrackTrackingDevice::SetCalibrationPath(std::string /*calibrationPath*/)
642{
643 MITK_WARN("IGT") << "Error: " << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(100);
644}
645
646//=======================================================
647// CloseConnection
648//=======================================================
650{
651 MITK_WARN("IGT") << "Error: " << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(100);
652 return false;
653}
654
655//=======================================================
656// StartTracking
657//=======================================================
659{
660 MITK_WARN("IGT") << "Error: " << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(100);
661 return false;
662}
663
664//=======================================================
665// StopTracking
666//=======================================================
668{
669 MITK_WARN("IGT") << "Error: " << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(100);
670 return false;
671}
672
673//=======================================================
674// ThreadStartTracking
675//=======================================================
680
681//=======================================================
682// GetOptitrackTool
683//=======================================================
685{
686 MITK_WARN("IGT") << "Error: " << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(100);
687 return nullptr;
688}
689
690//=======================================================
691// GetToolCount
692//=======================================================
694{
695 MITK_WARN("IGT") << "Error: " << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(100);
696 return 0;
697}
698
699//=======================================================
700// TrackTools
701//=======================================================
706
707//=======================================================
708// SetCameraParams
709//=======================================================
711{
712 MITK_WARN("IGT") << "Error: " << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(100);
713 return false;
714}
715
716//=======================================================
717// GetTool
718//=======================================================
720{
721 MITK_WARN("IGT") << "Error: " << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(100);
722 return nullptr;
723}
724
725//=======================================================
726// AddToolByFileName
727//=======================================================
729{
730 MITK_WARN("IGT") << "Error: " << mitk::OptitrackErrorMessages::GetOptitrackErrorMessage(100);
731 return false;
732}
733
734#endif
An object of this class represents an exception of the MITK-IGT module.
static IGTTimeStamp * GetInstance()
returns a pointer to the current instance of mitkTimeStamp
void Start(itk::Object::Pointer device)
starts the time-acquisition
void Stop(itk::Object::Pointer device)
stops the time-acqusition
static std::string GetOptitrackErrorMessage(int result)
Helper function to get the error messages from Optitrack API.
bool AddToolByDefinitionFile(std::string fileName)
Add a new tool using a text file which described the tool. The file must to have the next structure T...
bool StartTracking() override
Start to Track the tools already defined. If no tools are defined for this tracker,...
bool StopTracking() override
Stop the Tracking Thread and tools will not longer be updated.
TrackingTool * GetTool(unsigned int toolNumber) const override
Return the tool pointer of the tool number toolNumber.
OptitrackTrackingTool * GetOptitrackTool(unsigned int toolNumber) const
Return the tool pointer of the tool number toolNumber.
void ThreadStartTracking()
Start the Tracking Thread for the tools.
bool InitializeCameras()
Initialize the Optitrack System.
void SetCalibrationPath(std::string calibrationPath)
Sets the file where the calibration of the OptitrackTracker can be found.
bool SetCameraParams(int exposure, int threshold, int intensity, int videoType=4)
Set the Cameras Exposure, Threshold and Intensity of IR LEDs. By Default it set the Video type to 4: ...
void TrackTools()
Update each tool location in the list m_AllTools.
unsigned int GetToolCount() const override
Returns the number of defined tools.
bool CloseConnection() override
Close the Connection with the Tracker. Also CleanUp the Optitrack variables using the API: TT_CleanUp...
bool LoadCalibration()
Load the Calibration file to the Optitrack System and set the cameras in calibrated locations.
bool OpenConnection() override
Open the Connection with the Tracker. Calls LoadCalibration function and set the system up with the c...
An object of this class represents the a Tool tracked by Optitrack System. You can define the tool by...
Interface for all Tracking Devices.
void SetState(TrackingDeviceState state)
change object state
TrackingDeviceState GetState() const
return current object state (Setup, Ready or Tracking)
Interface for all Tracking Tools.
#define OPTITRACK_ATTEMPTS
Maximum number of attempts for Initialization, Shutdown and CleanUp.
#define OPTITRACK_FRAME_RATE
Time to refresh the tools location (ms)
IGT Exceptions.