Medical Imaging Interaction Toolkit  2018.4.99-f51274ea
Medical Imaging Interaction Toolkit
mitkNDITrackingDevice.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkNDITrackingDevice.h"
14 #include "mitkIGTTimeStamp.h"
15 #include "mitkIGTHardwareException.h"
16 #include <cstdio>
17 
18 #include <itksys/SystemTools.hxx>
19 #include <itkMutexLockHolder.h>
20 
22 
25 
26 // vtk
27 #include <vtkSphereSource.h>
28 
30 
31 const unsigned char CR = 0xD; // == '\r' - carriage return
32 const unsigned char LF = 0xA; // == '\n' - line feed
33 
35 TrackingDevice(), m_DeviceName(""), m_PortNumber(mitk::SerialCommunication::COM5), m_BaudRate(mitk::SerialCommunication::BaudRate9600),
36 m_DataBits(mitk::SerialCommunication::DataBits8), m_Parity(mitk::SerialCommunication::None), m_StopBits(mitk::SerialCommunication::StopBits1),
37 m_HardwareHandshake(mitk::SerialCommunication::HardwareHandshakeOff),
38 m_IlluminationActivationRate(Hz20), m_DataTransferMode(TX), m_6DTools(), m_ToolsMutex(nullptr),
39 m_SerialCommunication(nullptr), m_SerialCommunicationMutex(nullptr), m_DeviceProtocol(nullptr),
40 m_MultiThreader(nullptr), m_ThreadID(0), m_OperationMode(ToolTracking6D), m_MarkerPointsMutex(nullptr), m_MarkerPoints()
41 {
43  m_6DTools.clear();
44  m_SerialCommunicationMutex = itk::FastMutexLock::New();
46  m_DeviceProtocol->SetTrackingDevice(this);
47  m_DeviceProtocol->UseCRCOn();
48  m_MultiThreader = itk::MultiThreader::New();
49  m_ToolsMutex = itk::FastMutexLock::New();
50  m_MarkerPointsMutex = itk::FastMutexLock::New();
51  m_MarkerPoints.reserve(50); // a maximum of 50 marker positions can be reported by the tracking device
52 }
53 
55 {
56  if (this->GetState() != Setup)
57  {
58  mitk::NDIPassiveTool* ndiTool = dynamic_cast<mitk::NDIPassiveTool*>(tool);
59  if (ndiTool == nullptr)
60  return false;
61 
62  std::string portHandle = ndiTool->GetPortHandle();
63 
64  //return false if the SROM Data has not been set
65  if (ndiTool->GetSROMData() == nullptr)
66  return false;
67 
68  NDIErrorCode returnvalue;
69  returnvalue = m_DeviceProtocol->PVWR(&portHandle, ndiTool->GetSROMData(), ndiTool->GetSROMDataLength());
70  if (returnvalue != NDIOKAY)
71  return false;
72  returnvalue = m_DeviceProtocol->PINIT(&portHandle);
73  if (returnvalue != NDIOKAY)
74  return false;
75  returnvalue = m_DeviceProtocol->PENA(&portHandle, ndiTool->GetTrackingPriority()); // Enable tool
76  if (returnvalue != NDIOKAY)
77  return false;
78 
79  return true;
80  }
81  else
82  {
83  return false;
84  }
85 }
86 
88 {
89  m_RotationMode = r;
90 }
91 
93 {
94  /* stop tracking and disconnect from tracking device */
95  if (GetState() == Tracking)
96  {
97  this->StopTracking();
98  }
99  if (GetState() == Ready)
100  {
101  this->CloseConnection();
102  }
103  /* cleanup tracking thread */
104  if ((m_ThreadID != 0) && (m_MultiThreader.IsNotNull()))
105  {
106  m_MultiThreader->TerminateThread(m_ThreadID);
107  }
108  m_MultiThreader = nullptr;
109  /* free serial communication interface */
110  if (m_SerialCommunication.IsNotNull())
111  {
112  m_SerialCommunication->ClearReceiveBuffer();
113  m_SerialCommunication->ClearSendBuffer();
114  m_SerialCommunication->CloseConnection();
115  m_SerialCommunication = nullptr;
116  }
117 }
118 
120 {
121  if (this->GetState() != Setup)
122  return;
123  itkDebugMacro("setting PortNumber to " << _arg);
124  if (this->m_PortNumber != _arg)
125  {
126  this->m_PortNumber = _arg;
127  this->Modified();
128  }
129 }
130 
132 {
133  if (this->GetState() != Setup)
134  return;
135  itkDebugMacro("setting eviceName to " << _arg);
136  if (this->m_DeviceName != _arg)
137  {
138  this->m_DeviceName = _arg;
139  this->Modified();
140  }
141 }
142 
144 {
145  if (this->GetState() != Setup)
146  return;
147  itkDebugMacro("setting BaudRate to " << _arg);
148  if (this->m_BaudRate != _arg)
149  {
150  this->m_BaudRate = _arg;
151  this->Modified();
152  }
153 }
154 
156 {
157  if (this->GetState() != Setup)
158  return;
159  itkDebugMacro("setting DataBits to " << _arg);
160  if (this->m_DataBits != _arg)
161  {
162  this->m_DataBits = _arg;
163  this->Modified();
164  }
165 }
166 
168 {
169  if (this->GetState() != Setup)
170  return;
171  itkDebugMacro("setting Parity to " << _arg);
172  if (this->m_Parity != _arg)
173  {
174  this->m_Parity = _arg;
175  this->Modified();
176  }
177 }
178 
180 {
181  if (this->GetState() != Setup)
182  return;
183  itkDebugMacro("setting StopBits to " << _arg);
184  if (this->m_StopBits != _arg)
185  {
186  this->m_StopBits = _arg;
187  this->Modified();
188  }
189 }
190 
192 {
193  if (this->GetState() != Setup)
194  return;
195  itkDebugMacro("setting HardwareHandshake to " << _arg);
196  if (this->m_HardwareHandshake != _arg)
197  {
198  this->m_HardwareHandshake = _arg;
199  this->Modified();
200  }
201 }
202 
204 {
205  if (this->GetState() == Tracking)
206  return;
207  itkDebugMacro("setting IlluminationActivationRate to " << _arg);
208  if (this->m_IlluminationActivationRate != _arg)
209  {
210  this->m_IlluminationActivationRate = _arg;
211  this->Modified();
212  if (this->GetState() == Ready) // if the connection to the tracking system is established, send the new rate to the tracking device too
214  }
215 }
216 
218 {
219  itkDebugMacro("setting DataTransferMode to " << _arg);
220  if (this->m_DataTransferMode != _arg)
221  {
222  this->m_DataTransferMode = _arg;
223  this->Modified();
224  }
225 }
226 
227 mitk::NDIErrorCode mitk::NDITrackingDevice::Send(const std::string* input, bool addCRC)
228 {
229  if (input == nullptr)
230  return SERIALSENDERROR;
231 
232  std::string message;
233 
234  if (addCRC == true)
235  message = *input + CalcCRC(input) + std::string(1, CR);
236  else
237  message = *input + std::string(1, CR);
238 
239  //unsigned int messageLength = message.length() + 1; // +1 for CR
240 
241  // Clear send buffer
242  this->ClearSendBuffer();
243  // Send the date to the device
244  MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex
245  long returnvalue = m_SerialCommunication->Send(message);
246 
247  if (returnvalue == 0)
248  return SERIALSENDERROR;
249  else
250  return NDIOKAY;
251 }
252 
253 mitk::NDIErrorCode mitk::NDITrackingDevice::Receive(std::string* answer, unsigned int numberOfBytes)
254 {
255  if (answer == nullptr)
256  return SERIALRECEIVEERROR;
257 
258  MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex
259  long returnvalue = m_SerialCommunication->Receive(*answer, numberOfBytes); // never read more bytes than the device has send, the function will block until enough bytes are send...
260 
261  if (returnvalue == 0)
262  return SERIALRECEIVEERROR;
263  else
264  return NDIOKAY;
265 }
266 
268 {
269  if (answer == nullptr)
270  return SERIALRECEIVEERROR;
271 
272  std::string m;
273 
274  MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex
275 
276  long returnvalue = m_SerialCommunication->Receive(m, 1);
277 
278  if ((returnvalue == 0) || (m.size() != 1))
279  return SERIALRECEIVEERROR;
280 
281  *answer = m.at(0);
282  return NDIOKAY;
283 }
284 
286 {
287  if (answer == nullptr)
288  return SERIALRECEIVEERROR;
289 
290  std::string m;
291 
292  MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex
293 
294  do
295  {
296  long returnvalue = m_SerialCommunication->Receive(m, 1);
297  if ((returnvalue == 0) || (m.size() != 1))
298  return SERIALRECEIVEERROR;
299  *answer += m;
300  } while (m.at(0) != LF);
301  return NDIOKAY;
302 }
303 
305 {
306  MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex
307  m_SerialCommunication->ClearSendBuffer();
308 }
309 
311 {
312  MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex
313  m_SerialCommunication->ClearReceiveBuffer();
314 }
315 
316 const std::string mitk::NDITrackingDevice::CalcCRC(const std::string* input)
317 {
318  if (input == nullptr)
319  return "";
320  /* the crc16 calculation code is taken from the NDI API guide example code section */
321  static int oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
322  unsigned int data; // copy of the input string's current character
323  unsigned int crcValue = 0; // the crc value is stored here
324  unsigned int* puCRC16 = &crcValue; // the algorithm uses a pointer to crcValue, so it's easier to provide that than to change the algorithm
325  for (unsigned int i = 0; i < input->length(); i++)
326  {
327  data = (*input)[i];
328  data = (data ^ (*(puCRC16)& 0xff)) & 0xff;
329  *puCRC16 >>= 8;
330  if (oddparity[data & 0x0f] ^ oddparity[data >> 4])
331  {
332  *(puCRC16) ^= 0xc001;
333  }
334  data <<= 6;
335  *puCRC16 ^= data;
336  data <<= 1;
337  *puCRC16 ^= data;
338  }
339  // crcValue contains now the CRC16 value. Convert it to a string and return it
340  char returnvalue[13];
341  sprintf(returnvalue, "%04X", crcValue); // 4 hexadecimal digit with uppercase format
342  return std::string(returnvalue);
343 }
344 
346 {
347  //this->m_ModeMutex->Lock();
348  if (this->GetState() != Setup)
349  {
350  mitkThrowException(mitk::IGTException) << "Can only try to open the connection if in setup mode";
351  }
352 
354 
355  /* init local com port to standard com settings for a NDI tracking device:
356  9600 baud, 8 data bits, no parity, 1 stop bit, no hardware handshake */
357  if (m_DeviceName.empty())
358  m_SerialCommunication->SetPortNumber(m_PortNumber);
359  else
360  m_SerialCommunication->SetDeviceName(m_DeviceName);
365  m_SerialCommunication->SetSendTimeout(5000);
366  m_SerialCommunication->SetReceiveTimeout(5000);
367  if (m_SerialCommunication->OpenConnection() == 0) // 0 == ERROR_VALUE
368  {
369  m_SerialCommunication->CloseConnection();
370  m_SerialCommunication = nullptr;
371  mitkThrowException(mitk::IGTHardwareException) << "Can not open serial port";
372  }
373 
374  /* Reset Tracking device by sending a serial break for 500ms */
375  m_SerialCommunication->SendBreak(400);
376 
377  /* Read answer from tracking device (RESETBE6F) */
378  static const std::string reset("RESETBE6F\r");
379  std::string answer = "";
380  this->Receive(&answer, reset.length()); // read answer (should be RESETBE6F)
381  this->ClearReceiveBuffer(); // flush the receive buffer of all remaining data (carriage return, strings other than reset
382  if (reset.compare(answer) != 0) // check for RESETBE6F
383  {
384  if (m_SerialCommunication.IsNotNull())
385  {
386  m_SerialCommunication->CloseConnection();
387  m_SerialCommunication = nullptr;
388  }
389  mitkThrowException(mitk::IGTHardwareException) << "Hardware Reset of tracking device did not work";
390  }
391 
392  /* Now the tracking device isSetData reset, start initialization */
393  NDIErrorCode returnvalue;
394 
395  /* set device com settings to new values and wait for the device to change them */
397 
398  if (returnvalue != NDIOKAY)
399  {
400  mitkThrowException(mitk::IGTHardwareException) << "Could not set comm settings in trackingdevice";
401  }
402 
403  //after changing COMM wait at least 100ms according to NDI Api documentation page 31
404  itksys::SystemTools::Delay(500);
405 
406  /* now change local com settings accordingly */
407  m_SerialCommunication->CloseConnection();
408  m_SerialCommunication->SetBaudRate(m_BaudRate);
409  m_SerialCommunication->SetDataBits(m_DataBits);
410  m_SerialCommunication->SetParity(m_Parity);
411  m_SerialCommunication->SetStopBits(m_StopBits);
412  m_SerialCommunication->SetHardwareHandshake(m_HardwareHandshake);
413  m_SerialCommunication->SetSendTimeout(5000);
414  m_SerialCommunication->SetReceiveTimeout(5000);
415  m_SerialCommunication->OpenConnection();
416 
417  /* initialize the tracking device */
418  returnvalue = m_DeviceProtocol->INIT();
419  if (returnvalue != NDIOKAY)
420  {
421  mitkThrowException(mitk::IGTHardwareException) << "Could not initialize the tracking device";
422  }
423 
424  if (this->GetType() == mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName()) // if the type of tracking device is not specified, try to query the connected device
425  {
426  mitk::TrackingDeviceType deviceType;
427  returnvalue = m_DeviceProtocol->VER(deviceType);
428  if ((returnvalue != NDIOKAY) || (deviceType == mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName()))
429  {
430  mitkThrowException(mitk::IGTHardwareException) << "Could not determine tracking device type. Please set manually and try again.";
431  }
432  this->SetType(deviceType);
433  }
434 
435  /**** Optional Polaris specific code, Work in progress
436  // start diagnostic mode
437  returnvalue = m_DeviceProtocol->DSTART();
438  if (returnvalue != NDIOKAY)
439  {
440  this->SetErrorMessage("Could not start diagnostic mode");
441  return false;
442  }
443  else // we are in diagnostic mode
444  {
445  // initialize extensive IR checking
446  returnvalue = m_DeviceProtocol->IRINIT();
447  if (returnvalue != NDIOKAY)
448  {
449  this->SetErrorMessage("Could not initialize intense infrared light checking");
450  return false;
451  }
452  bool intenseIR = false;
453  returnvalue = m_DeviceProtocol->IRCHK(&intenseIR);
454  if (returnvalue != NDIOKAY)
455  {
456  this->SetErrorMessage("Could not execute intense infrared light checking");
457  return false;
458  }
459  if (intenseIR == true)
460  // do something - warn the user, raise exception, write to protocol or similar
461  std::cout << "Warning: Intense infrared light detected. Accurate tracking will probably not be possible.\n";
462 
463  // stop diagnictic mode
464  returnvalue = m_DeviceProtocol->DSTOP();
465  if (returnvalue != NDIOKAY)
466  {
467  this->SetErrorMessage("Could not stop diagnostic mode");
468  return false;
469  }
470  }
471  *** end of optional polaris code ***/
472 
477  /* First, check if the tracking device has port handles that need to be freed and free them */
478  returnvalue = FreePortHandles();
479  // non-critical, therefore no error handling
480 
484  {
485  MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
486  std::string portHandle;
487  auto endIt = m_6DTools.end();
488  for (auto it = m_6DTools.begin(); it != endIt; ++it)
489  {
490  /* get a port handle for the tool */
491  returnvalue = m_DeviceProtocol->PHRQ(&portHandle);
492  if (returnvalue == NDIOKAY)
493  {
494  (*it)->SetPortHandle(portHandle.c_str());
495  /* now write the SROM file of the tool to the tracking system using PVWR */
497  {
498  returnvalue = m_DeviceProtocol->PVWR(&portHandle, (*it)->GetSROMData(), (*it)->GetSROMDataLength());
499  if (returnvalue != NDIOKAY)
500  {
501  mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + (*it)->GetToolName() + std::string("' to tracking device")).c_str();
502  }
503 
504  returnvalue = m_DeviceProtocol->PINIT(&portHandle);
505  if (returnvalue != NDIOKAY)
506  {
507  mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize tool '") + (*it)->GetToolName()).c_str();
508  }
509 
510  if ((*it)->IsEnabled() == true)
511  {
512  returnvalue = m_DeviceProtocol->PENA(&portHandle, (*it)->GetTrackingPriority()); // Enable tool
513  if (returnvalue != NDIOKAY)
514  {
515  mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + portHandle +
516  std::string("' for tool '") + (*it)->GetToolName() + std::string("'")).c_str();
517  }
518  }
519  }
520  }
521  }
522  } // end of toolsmutexlockholder scope
523 
524  /* check for wired tools and add them too */
525  if (this->DiscoverWiredTools() == false) // query the tracking device for wired tools and add them to our tool list
526  return false; // \TODO: could we continue anyways?
527 
528  /*POLARIS: set the illuminator activation rate */
530  {
531  returnvalue = m_DeviceProtocol->IRATE(this->m_IlluminationActivationRate);
532  if (returnvalue != NDIOKAY)
533  {
534  mitkThrowException(mitk::IGTHardwareException) << "Could not set the illuminator activation rate";
535  }
536  }
537  /* finish - now all tools should be added, initialized and enabled, so that tracking can be started */
538  this->SetState(Ready);
539  try
540  {
541  SetVolume(this->m_Data);
542  }
543  catch (const mitk::IGTHardwareException& e)
544  {
545  MITK_WARN << e.GetDescription();
546  }
547 
548  return true;
549 }
550 
552 {
553  NDIErrorCode returnvalue;
554  std::string portHandle;
555  returnvalue = m_DeviceProtocol->PHSR(OCCUPIED, &portHandle);
556 
557  if (returnvalue != NDIOKAY)
558  {
559  mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that are connected";
560  }
561 
562  /* if there are port handles that need to be initialized, initialize them. Furthermore instantiate tools for each handle that has no tool yet. */
563  std::string ph;
564 
565  for (unsigned int i = 0; i < portHandle.size(); i += 2)
566  {
567  ph = portHandle.substr(i, 2);
568  mitk::NDIPassiveTool* pt = this->GetInternalTool(ph);
569  if (pt == nullptr) // if we don't have a tool, something is wrong. Tools should be discovered first by calling DiscoverWiredTools()
570  continue;
571 
572  if (pt->GetSROMData() == nullptr)
573  continue;
574 
575  returnvalue = m_DeviceProtocol->PVWR(&ph, pt->GetSROMData(), pt->GetSROMDataLength());
576  if (returnvalue != NDIOKAY)
577  {
578  mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + pt->GetToolName() + std::string("' to tracking device")).c_str();
579  }
580 
581  returnvalue = m_DeviceProtocol->PINIT(&ph);
582  if (returnvalue != NDIOKAY)
583  {
584  mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize tool '") + pt->GetToolName()).c_str();
585  }
586 
587  if (pt->IsEnabled() == true)
588  {
589  returnvalue = m_DeviceProtocol->PENA(&ph, pt->GetTrackingPriority()); // Enable tool
590  if (returnvalue != NDIOKAY)
591  {
592  mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + portHandle +
593  std::string("' for tool '") + pt->GetToolName() + std::string("'")).c_str();
594  }
595  }
596  }
597  return true;
598 }
599 
601 {
602  if (this->GetState() != Setup)
603  {
605  }
606 
608  //m_DeviceProtocol = mitk::NDIProtocol::New();
609  //m_DeviceProtocol->SetTrackingDevice(this);
610  //m_DeviceProtocol->UseCRCOn();
611  /* init local com port to standard com settings for a NDI tracking device:
612  9600 baud, 8 data bits, no parity, 1 stop bit, no hardware handshake
613  */
614  if (m_DeviceName.empty())
615  m_SerialCommunication->SetPortNumber(m_PortNumber);
616  else
617  m_SerialCommunication->SetDeviceName(m_DeviceName);
618 
623  m_SerialCommunication->SetSendTimeout(5000);
624  m_SerialCommunication->SetReceiveTimeout(5000);
625  if (m_SerialCommunication->OpenConnection() == 0) // error
626  {
627  m_SerialCommunication = nullptr;
629  }
630 
631  /* Reset Tracking device by sending a serial break for 500ms */
632  m_SerialCommunication->SendBreak(400);
633 
634  /* Read answer from tracking device (RESETBE6F) */
635  static const std::string reset("RESETBE6F\r");
636  std::string answer = "";
637  this->Receive(&answer, reset.length()); // read answer (should be RESETBE6F)
638  this->ClearReceiveBuffer(); // flush the receive buffer of all remaining data (carriage return, strings other than reset
639  if (reset.compare(answer) != 0) // check for RESETBE6F
640  {
641  m_SerialCommunication->CloseConnection();
642  m_SerialCommunication = nullptr;
643  mitkThrowException(mitk::IGTHardwareException) << "Hardware Reset of tracking device did not work";
644  }
645 
646  /* Now the tracking device is reset, start initialization */
647  NDIErrorCode returnvalue;
648 
649  /* initialize the tracking device */
650  //returnvalue = m_DeviceProtocol->INIT();
651  //if (returnvalue != NDIOKAY)
652  //{
653  // this->SetErrorMessage("Could not initialize the tracking device");
654  // return mitk::TrackingSystemNotSpecified;
655  //}
656 
657  mitk::TrackingDeviceType deviceType;
658  returnvalue = m_DeviceProtocol->VER(deviceType);
659  if ((returnvalue != NDIOKAY) || (deviceType == mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName()))
660  {
661  m_SerialCommunication = nullptr;
663  }
664  m_SerialCommunication = nullptr;
665  return deviceType;
666 }
667 
669 {
670  if (this->GetState() != Setup)
671  {
672  //init before closing to force the field generator from aurora to switch itself off
673  m_DeviceProtocol->INIT();
674  /* close the serial connection */
675  m_SerialCommunication->CloseConnection();
676  /* invalidate all tools */
677  this->InvalidateAll();
678  /* return to setup mode */
679  this->SetState(Setup);
680  m_SerialCommunication = nullptr;
681  }
682  return true;
683 }
684 
685 ITK_THREAD_RETURN_TYPE mitk::NDITrackingDevice::ThreadStartTracking(void* pInfoStruct)
686 {
687  /* extract this pointer from Thread Info structure */
688  struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
689  if (pInfo == nullptr)
690  {
691  return ITK_THREAD_RETURN_VALUE;
692  }
693  if (pInfo->UserData == nullptr)
694  {
695  return ITK_THREAD_RETURN_VALUE;
696  }
697  NDITrackingDevice *trackingDevice = (NDITrackingDevice*)pInfo->UserData;
698  if (trackingDevice != nullptr)
699  {
700  if (trackingDevice->GetOperationMode() == ToolTracking6D)
701  trackingDevice->TrackTools(); // call TrackTools() from the original object
702  else if (trackingDevice->GetOperationMode() == MarkerTracking3D)
703  trackingDevice->TrackMarkerPositions(); // call TrackMarkerPositions() from the original object
704  else if (trackingDevice->GetOperationMode() == ToolTracking5D)
705  trackingDevice->TrackMarkerPositions(); // call TrackMarkerPositions() from the original object
706  else if (trackingDevice->GetOperationMode() == HybridTracking)
707  {
708  trackingDevice->TrackToolsAndMarkers();
709  }
710  }
711  trackingDevice->m_ThreadID = 0; // erase thread id, now that this thread will end.
712  return ITK_THREAD_RETURN_VALUE;
713 }
714 
716 {
717  if (this->GetState() != Ready)
718  return false;
719 
720  this->SetState(Tracking); // go to mode Tracking
721  this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking
722  this->m_StopTracking = false;
723  this->m_StopTrackingMutex->Unlock();
724 
725  m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this); // start a new thread that executes the TrackTools() method
727  return true;
728 }
729 
731 {
732  /* lock the TrackingFinishedMutex to signal that the execution rights are now transfered to the tracking thread */
733  MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope
734 
735  if (this->GetState() != Tracking)
736  return;
737 
738  NDIErrorCode returnvalue;
739  returnvalue = m_DeviceProtocol->TSTART();
740  if (returnvalue != NDIOKAY)
741  return;
742 
743  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
744  this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking
745  localStopTracking = this->m_StopTracking;
746  this->m_StopTrackingMutex->Unlock();
747  while ((this->GetState() == Tracking) && (localStopTracking == false))
748  {
749  if (this->m_DataTransferMode == TX)
750  {
751  returnvalue = this->m_DeviceProtocol->TX();
752  if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors
753  break;
754  }
755  else
756  {
757  returnvalue = this->m_DeviceProtocol->BX();
758  if (returnvalue != NDIOKAY)
759  break;
760  }
761  /* Update the local copy of m_StopTracking */
762  this->m_StopTrackingMutex->Lock();
763  localStopTracking = m_StopTracking;
764  this->m_StopTrackingMutex->Unlock();
765  }
766  /* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */
767 
768  returnvalue = m_DeviceProtocol->TSTOP();
769  if (returnvalue != NDIOKAY)
770  {
771  mitkThrowException(mitk::IGTHardwareException) << "An error occured while tracking tools.";
772  }
773 
774  return; // returning from this function (and ThreadStartTracking()) this will end the thread and transfer control back to main thread by releasing trackingFinishedLockHolder
775 }
776 
778 {
779  MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope
780 
782  return;
783 
784  if (this->GetState() != Tracking)
785  return;
786 
787  NDIErrorCode returnvalue;
788 
789  returnvalue = m_DeviceProtocol->DSTART(); // Start Diagnostic Mode
790  if (returnvalue != NDIOKAY)
791  return;
792 
793  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
794  this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking
795  localStopTracking = this->m_StopTracking;
796  this->m_StopTrackingMutex->Unlock();
797  while ((this->GetState() == Tracking) && (localStopTracking == false))
798  {
799  m_MarkerPointsMutex->Lock(); // lock points data structure
800  returnvalue = this->m_DeviceProtocol->POS3D(&m_MarkerPoints); // update points data structure with new position data from tracking device
801  m_MarkerPointsMutex->Unlock();
802  if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors
803  {
804  std::cout << "Error in POS3D: could not read data. Possibly no markers present." << std::endl;
805  }
806  /* Update the local copy of m_StopTracking */
807  this->m_StopTrackingMutex->Lock();
808  localStopTracking = m_StopTracking;
809  this->m_StopTrackingMutex->Unlock();
810 
811  itksys::SystemTools::Delay(1);
812  }
813  /* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */
814  returnvalue = m_DeviceProtocol->DSTOP();
815  if (returnvalue != NDIOKAY)
816  return; // how can this thread tell the application, that an error has occured?
817 
818  this->SetState(Ready);
819  return; // returning from this function (and ThreadStartTracking()) this will end the thread
820 }
821 
823 {
824  MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope
826  return;
827 
828  NDIErrorCode returnvalue;
829 
830  returnvalue = m_DeviceProtocol->TSTART(); // Start Diagnostic Mode
831  if (returnvalue != NDIOKAY)
832  return;
833 
834  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
835  this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking
836  localStopTracking = this->m_StopTracking;
837  this->m_StopTrackingMutex->Unlock();
838  while ((this->GetState() == Tracking) && (localStopTracking == false))
839  {
840  m_MarkerPointsMutex->Lock(); // lock points data structure
841  returnvalue = this->m_DeviceProtocol->TX(true, &m_MarkerPoints); // update points data structure with new position data from tracking device
842  m_MarkerPointsMutex->Unlock();
843  if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors
844  {
845  std::cout << "Error in TX: could not read data. Possibly no markers present." << std::endl;
846  }
847  /* Update the local copy of m_StopTracking */
848  this->m_StopTrackingMutex->Lock();
849  localStopTracking = m_StopTracking;
850  this->m_StopTrackingMutex->Unlock();
851  }
852  /* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */
853 
854  returnvalue = m_DeviceProtocol->TSTOP();
855  if (returnvalue != NDIOKAY)
856  return; // how can this thread tell the application, that an error has occurred?
857 
858  this->SetState(Ready);
859  return; // returning from this function (and ThreadStartTracking()) this will end the thread
860 }
861 
863 {
864  MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
865  if (toolNumber < m_6DTools.size())
866  return m_6DTools.at(toolNumber);
867  return nullptr;
868 }
869 
871 {
872  MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
873  auto end = m_6DTools.end();
874  for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator)
875  if (name.compare((*iterator)->GetToolName()) == 0)
876  return *iterator;
877  return nullptr;
878 }
879 
881 {
882  MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
883  auto end = m_6DTools.end();
884  for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator)
885  if (portHandle.compare((*iterator)->GetPortHandle()) == 0)
886  return *iterator;
887  return nullptr;
888 }
889 
891 {
892  MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
893  return m_6DTools.size();
894 }
895 
896 bool mitk::NDITrackingDevice::Beep(unsigned char count)
897 {
898  if (this->GetState() != Setup)
899  {
900  return (m_DeviceProtocol->BEEP(count) == NDIOKAY);
901  }
902  else
903  {
904  return false;
905  }
906 }
907 
908 mitk::TrackingTool* mitk::NDITrackingDevice::AddTool(const char* toolName, const char* fileName, TrackingPriority p /*= NDIPassiveTool::Dynamic*/)
909 {
910  mitk::NDIPassiveTool::Pointer t = mitk::NDIPassiveTool::New();
911  if (t->LoadSROMFile(fileName) == false)
912  return nullptr;
913  t->SetToolName(toolName);
914  t->SetTrackingPriority(p);
915  if (this->InternalAddTool(t) == false)
916  return nullptr;
917  return t.GetPointer();
918 }
919 
921 {
922  if (tool == nullptr)
923  return false;
924  NDIPassiveTool::Pointer p = tool;
925  /* if the connection to the tracking device is already established, add the new tool to the device now */
926  if (this->GetState() == Ready)
927  {
928  /* get a port handle for the tool */
929  std::string newPortHandle;
930  NDIErrorCode returnvalue;
931  returnvalue = m_DeviceProtocol->PHRQ(&newPortHandle);
932  if (returnvalue == NDIOKAY)
933  {
934  p->SetPortHandle(newPortHandle.c_str());
935  /* now write the SROM file of the tool to the tracking system using PVWR */
936  returnvalue = m_DeviceProtocol->PVWR(&newPortHandle, p->GetSROMData(), p->GetSROMDataLength());
937  if (returnvalue != NDIOKAY)
938  {
939  mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + p->GetToolName() + std::string("' to tracking device")).c_str();
940  }
941  /* initialize the port handle */
942  returnvalue = m_DeviceProtocol->PINIT(&newPortHandle);
943  if (returnvalue != NDIOKAY)
944  {
945  mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize port '") + newPortHandle +
946  std::string("' for tool '") + p->GetToolName() + std::string("'")).c_str();
947  }
948  /* enable the port handle */
949  if (p->IsEnabled() == true)
950  {
951  returnvalue = m_DeviceProtocol->PENA(&newPortHandle, p->GetTrackingPriority()); // Enable tool
952  if (returnvalue != NDIOKAY)
953  {
954  mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + newPortHandle +
955  std::string("' for tool '") + p->GetToolName() + std::string("'")).c_str();
956  }
957  }
958  }
959  /* now that the tool is added to the device, add it to list too */
960  m_ToolsMutex->Lock();
961  this->m_6DTools.push_back(p);
962  m_ToolsMutex->Unlock();
963  this->Modified();
964  return true;
965  }
966  else if (this->GetState() == Setup)
967  {
968  /* In Setup mode, we only add it to the list, so that OpenConnection() can add it later */
969  m_ToolsMutex->Lock();
970  this->m_6DTools.push_back(p);
971  m_ToolsMutex->Unlock();
972  this->Modified();
973  return true;
974  }
975  else // in Tracking mode, no tools can be added
976  return false;
977 }
978 
980 {
981  mitk::NDIPassiveTool* ndiTool = dynamic_cast<mitk::NDIPassiveTool*>(tool);
982  if (ndiTool == nullptr)
983  return false;
984 
985  std::string portHandle = ndiTool->GetPortHandle();
986  /* a valid portHandle has length 2. If a valid handle exists, the tool is already added to the tracking device, so we have to remove it there
987  if the connection to the tracking device has already been established.
988  */
989  if ((portHandle.length() == 2) && (this->GetState() == Ready)) // do not remove a tool in tracking mode
990  {
991  NDIErrorCode returnvalue;
992  returnvalue = m_DeviceProtocol->PHF(&portHandle);
993  if (returnvalue != NDIOKAY)
994  return false;
995  /* Now that the tool is removed from the tracking device, remove it from our tool list too */
996  MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex (scope is inside the if-block
997  auto end = m_6DTools.end();
998  for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator)
999  {
1000  if (iterator->GetPointer() == ndiTool)
1001  {
1002  m_6DTools.erase(iterator);
1003  this->Modified();
1004  return true;
1005  }
1006  }
1007  return false;
1008  }
1009  else if (this->GetState() == Setup) // in Setup Mode, we are not connected to the tracking device, so we can just remove the tool from the tool list
1010  {
1011  MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
1012  auto end = m_6DTools.end();
1013  for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator)
1014  {
1015  if ((*iterator).GetPointer() == ndiTool)
1016  {
1017  m_6DTools.erase(iterator);
1018  this->Modified();
1019  return true;
1020  }
1021  }
1022  return false;
1023  }
1024  return false;
1025 }
1026 
1028 {
1029  MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
1030  auto end = m_6DTools.end();
1031  for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator)
1032  (*iterator)->SetDataValid(false);
1033 }
1034 
1036 {
1037  if (GetState() == Tracking)
1038  return false;
1039 
1040  m_OperationMode = mode;
1041  return true;
1042 }
1043 
1045 {
1046  return m_OperationMode;
1047 }
1048 
1050 {
1051  m_MarkerPointsMutex->Lock();
1052  *markerpositions = m_MarkerPoints; // copy the internal vector to the one provided
1053  m_MarkerPointsMutex->Unlock();
1054  return (markerpositions->size() != 0);
1055 }
1056 
1058 {
1059  /* First, check for disconnected tools and remove them */
1060  this->FreePortHandles();
1061 
1062  //NDI handling (PHSR 02, PINIT, PHSR 02, PHSR 00) => all initialized and all handles available
1063  //creation of MITK tools
1064  //NDI enable all tools (PENA)
1065  //NDI get all serial numbers (PHINF)
1066 
1071  /* check for occupied port handles on channel 0 */
1072  std::string portHandle;
1073  NDIErrorCode returnvalue = m_DeviceProtocol->PHSR(OCCUPIED, &portHandle);
1074 
1075  if (returnvalue != NDIOKAY)
1076  {
1077  mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that are connected on channel 0.";
1078  }
1079 
1080  /* Initialize all port handles on channel 0 */
1081  for (unsigned int i = 0; i < portHandle.size(); i += 2)
1082  {
1083  std::string ph = portHandle.substr(i, 2);
1084  returnvalue = m_DeviceProtocol->PINIT(&ph);
1085 
1086  if (returnvalue != NDIOKAY)
1087  {
1088  mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize port '") + ph + std::string("."));
1089  }
1090  }
1091 
1092  /* check for occupied port handles on channel 1 (initialize automatically, portHandle is empty although additional tools were detected) */
1093  //For a split port on a dual 5DOF tool, the first PHSR sent will report only one port handle. After the port handle is
1094  //initialized, it is assigned to channel 0. You must then use PHSR again to assign a port handle to channel 1. The
1095  //port handle for channel 1 is initialized automatically.
1096  returnvalue = m_DeviceProtocol->PHSR(OCCUPIED, &portHandle);
1097 
1098  if (returnvalue != NDIOKAY)
1099  {
1100  mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that are connected on channel 1.";
1101  }
1102 
1103  /* read all port handles */
1104  returnvalue = m_DeviceProtocol->PHSR(ALL, &portHandle);
1105 
1106  if (returnvalue != NDIOKAY)
1107  {
1108  mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that are connected on all channels.";
1109  }
1110 
1116  for (unsigned int i = 0; i < portHandle.size(); i += 2)
1117  {
1118  std::string ph = portHandle.substr(i, 2);
1119  if (this->GetInternalTool(ph) != nullptr) // if we already have a tool with this handle
1120  continue; // then skip the initialization
1121 
1122  //define tracking priority
1123  auto trackingPriority = mitk::NDIPassiveTool::Dynamic;
1124 
1125  //instantiate an object for each tool that is connected
1126  mitk::NDIPassiveTool::Pointer newTool = mitk::NDIPassiveTool::New();
1127  newTool->SetPortHandle(ph.c_str());
1128  newTool->SetTrackingPriority(trackingPriority);
1129 
1130  //set a name for identification
1131  newTool->SetToolName((std::string("Port ") + ph).c_str());
1132 
1133  /* enable the port handle */
1134  returnvalue = m_DeviceProtocol->PENA(&ph, trackingPriority); // Enable tool
1135 
1136  if (returnvalue != NDIOKAY)
1137  {
1138  mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + ph +
1139  std::string("' for tool '") + newTool->GetToolName() + std::string("'")).c_str();
1140  }
1141 
1142  //we have to temporarily unlock m_ModeMutex here to avoid a deadlock with another lock inside InternalAddTool()
1143  if (this->InternalAddTool(newTool) == false)
1144  {
1145  mitkThrowException(mitk::IGTException) << "Error while adding new tool";
1146  }
1147  }
1148 
1153  // after initialization readout serial numbers of automatically detected tools
1154  for (unsigned int i = 0; i < portHandle.size(); i += 2)
1155  {
1156  std::string ph = portHandle.substr(i, 2);
1157 
1158  std::string portInfo;
1159  NDIErrorCode returnvaluePort = m_DeviceProtocol->PHINF(ph, &portInfo);
1160  if ((returnvaluePort == NDIOKAY) && (portInfo.size() > 31))
1161  dynamic_cast<mitk::NDIPassiveTool*>(this->GetInternalTool(ph))->SetSerialNumber(portInfo.substr(23, 8));
1162  MITK_INFO << "portInfo: " << portInfo;
1163  itksys::SystemTools::Delay(10);
1164  }
1165 
1166  return true;
1167 }
1168 
1170 {
1171  /* first search for port handles that need to be freed: e.g. because of a reset of the tracking system */
1172  NDIErrorCode returnvalue = NDIOKAY;
1173  std::string portHandle;
1174  returnvalue = m_DeviceProtocol->PHSR(FREED, &portHandle);
1175  if (returnvalue != NDIOKAY)
1176  {
1177  mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that need to be freed";
1178  }
1179 
1180  /* if there are port handles that need to be freed, free them */
1181  if (portHandle.empty() == true)
1182  return returnvalue;
1183 
1184  std::string ph;
1185  for (unsigned int i = 0; i < portHandle.size(); i += 2)
1186  {
1187  ph = portHandle.substr(i, 2);
1188 
1189  mitk::NDIPassiveTool* t = this->GetInternalTool(ph);
1190  if (t != nullptr) // if we have a tool for the port handle that needs to be freed
1191  {
1192  if (this->RemoveTool(t) == false) // remove it (this will free the port too)
1193  returnvalue = NDIERROR;
1194  }
1195  else // we don't have a tool, the port handle exists only in the tracking device
1196  {
1197  returnvalue = m_DeviceProtocol->PHF(&ph); // free it there
1198  // What to do if port handle could not be freed? This seems to be a non critical error
1199  if (returnvalue != NDIOKAY)
1200  {
1201  mitkThrowException(mitk::IGTHardwareException) << "Could not free all port handles";
1202  }
1203  }
1204  }
1205  return returnvalue;
1206 }
1207 
1209 {
1210  std::string revision;
1211  if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9))
1212  {
1213  MITK_ERROR << "Could not receive firmware revision number!";
1214  return 0;
1215  }
1216 
1217  const std::string majrevno = revision.substr(2, 3); //cut out "004" from "D.004.001"
1218 
1219  return std::atoi(majrevno.c_str());
1220 }
1221 
1223 {
1224  static std::string revision;
1225  if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9))
1226  {
1227  MITK_ERROR << "Could not receive firmware revision number!";
1228  revision = "";
1229  return revision.c_str();
1230  }
1231  return revision.c_str();
1232 }
1233 
1235 {
1236  if (this->GetType() == mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) { return true; }
1237  else { return false; }
1238 }
1239 
1241 {
1242  //For Aurora, only AutoDetecion or loading of toolStorage should be used. It is not possible to add a single tool.
1243  if (this->GetType() == mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) { return false; }
1244  //For Polaris, a single tool can be added, there is no autoDetection.
1245  else { return true; }
1246 }
1247 
1248 mitk::NavigationToolStorage::Pointer mitk::NDITrackingDevice::AutoDetectTools()
1249 {
1250  mitk::NavigationToolStorage::Pointer autoDetectedStorage = mitk::NavigationToolStorage::New();
1252  {
1253  try
1254  {
1255  this->OpenConnection();
1256  this->StartTracking();
1257  }
1258  catch (mitk::Exception& e)
1259  {
1260  MITK_WARN << "Warning, can not auto-detect tools! (" << e.GetDescription() << ")";
1261  return autoDetectedStorage;
1262  }
1263 
1264  for (unsigned int i = 0; i < this->GetToolCount(); i++)
1265  {
1266  //create a navigation tool with sphere as surface
1267  std::stringstream toolname;
1268  toolname << "AutoDetectedTool" << i;
1269  mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New();
1270  newTool->SetSerialNumber(dynamic_cast<mitk::NDIPassiveTool*>(this->GetTool(i))->GetSerialNumber());
1271  newTool->SetIdentifier(toolname.str());
1272  newTool->SetTrackingDeviceType(mitk::NDIAuroraTypeInformation::GetTrackingDeviceName());
1273  newTool->GetDataNode()->SetName(toolname.str());
1274  autoDetectedStorage->AddTool(newTool);
1275  }
1276  this->StopTracking();
1277  this->CloseConnection();
1278  }
1279  return autoDetectedStorage;
1280 }
1281 
1283 {
1284  if (numberOfVolumes == nullptr || volumes == nullptr || volumesDimensions == nullptr)
1285  return false;
1286 
1287  static std::string info;
1288  if (m_DeviceProtocol->SFLIST(&info) != mitk::NDIOKAY || info.empty())
1289  {
1290  MITK_ERROR << "Could not receive tracking volume information of tracking system!";
1291  return false;
1292  }
1293 
1294  /*info contains the following:
1295  <HEX:number of volumes> (+n times:) <HEX:shape type> <shape parameters D1-D10> <HEX:reserved / number of wavelength supported> <metal resistant / supported wavelength>
1296  */
1297  (*numberOfVolumes) = (unsigned int)std::atoi(info.substr(0, 1).c_str());
1298 
1299  for (unsigned int i = 0; i < (*numberOfVolumes); i++)
1300  {
1301  //e.g. for cube: "9-025000+025000-025000+025000-055000-005000+000000+000000+000000+00000011"
1302  //for dome: "A+005000+048000+005000+066000+000000+000000+000000+000000+000000+00000011"
1303 
1304  std::string::size_type offset, end;
1305  offset = (i * 73) + 1;
1306  end = 73 + (i * 73);
1307  std::string currentVolume = info.substr(offset, end);//i=0: from 1 to 73 characters; i=1: from 75 to 148 char;
1308  // if i>0 then we have a return statement <LF> infront
1309  if (i > 0)
1310  currentVolume = currentVolume.substr(1, currentVolume.size());
1311  if (currentVolume.compare(0, 1, NDIPolarisTypeInformation::GetDeviceDataPolarisOldModel().HardwareCode) == 0)
1313  if (currentVolume.compare(0, 3, NDIPolarisTypeInformation::GetDeviceDataPolarisSpectra().HardwareCode) == 0)
1315  if (currentVolume.compare(1, 3, NDIPolarisTypeInformation::GetDeviceDataSpectraExtendedPyramid().HardwareCode) == 0)
1316  {
1317  currentVolume = currentVolume.substr(1, currentVolume.size());
1319  }
1320  if (currentVolume.compare(0, 1, NDIPolarisTypeInformation::GetDeviceDataPolarisVicra().HardwareCode) == 0)
1322  else if (currentVolume.compare(0, 1, mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarCube().HardwareCode) == 0)
1323  volumes->push_back(mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarCube().Model);//alias cube
1324  else if (currentVolume.compare(0, 1, mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarDome().HardwareCode) == 0)
1326 
1327  //fill volumesDimensions
1328  for (unsigned int index = 0; index < 10; index++)
1329  {
1330  std::string::size_type offD, endD;
1331  offD = 1 + (index * 7); //7 digits per dimension and the first is the type of volume
1332  endD = offD + 7;
1333  int dimension = std::atoi(currentVolume.substr(offD, endD).c_str());
1334  dimension /= 100; //given in mm. 7 digits are xxxx.xx according to NDI //strange, the last two digits (11) also for the metal flag get read also...
1335  volumesDimensions->push_back(dimension);
1336  }
1337  }
1338 
1339  return true;
1340 }
1341 
1343 {
1344  if (m_DeviceProtocol->VSEL(volume) != mitk::NDIOKAY)
1345  {
1346  mitkThrowException(mitk::IGTHardwareException) << "Could not set volume!";
1347  }
1348  return true;
1349 }
NDIProtocol::Pointer m_DeviceProtocol
create and parse NDI protocol strings
NDIErrorCode ReceiveByte(char *answer)
lightweight receive function, that reads just one byte
An object of this class represents an exception of the MITK-IGT module which are releated to the hard...
itk::MutexLockHolder< itk::FastMutexLock > MutexLockHolder
RotationMode m_RotationMode
defines the rotation mode Standard or Transposed, Standard is default
HardwareHandshake m_HardwareHandshake
which tracking volume is currently used (if device supports multiple volumes) (
virtual bool GetMarkerPositions(MarkerPointContainerType *markerpositions)
Get 3D marker positions (operation mode must be set to MarkerTracking3D or HybridTracking) ...
Interface for all Tracking Tools.
NDIPassiveTool * GetInternalTool(std::string portHandle)
returns the tool object that has been assigned the port handle or nullptr if no tool can be found ...
NDIErrorCode FreePortHandles()
free all port handles that need to be freed
virtual const char * GetPortHandle() const
get port handle under which the tool is registered in the tracking device
std::vector< std::string > NDITrackingVolumeContainerType
vector of tracking volumes
virtual bool InternalAddTool(NDIPassiveTool *tool)
Add a passive 6D tool to the list of tracked tools. This method is used by AddTool.
virtual bool UpdateTool(mitk::TrackingTool *tool)
reloads the srom file and reinitializes the tool
bool OpenConnection() override
Set the type of the NDI Tracking Device because it can not jet handle this itself.
#define MITK_INFO
Definition: mitkLogMacros.h:18
static Pointer New()
OperationMode
Error codes of NDI tracking devices.
virtual int GetMajorFirmwareRevisionNumber()
Get major revision number from tracking device should not be called directly after starting to track...
itk::FastMutexLock::Pointer m_TrackingFinishedMutex
mutex to manage control flow of StopTracking()
virtual void SetBaudRate(const BaudRate _arg)
returns the device name for serial communication
NDIErrorCode Send(const std::string *message, bool addCRC=true)
Send message to tracking device.
#define MITK_ERROR
Definition: mitkLogMacros.h:20
int m_ThreadID
ID of tracking thread.
IlluminationActivationRate m_IlluminationActivationRate
update rate of IR illuminator for Polaris
IlluminationActivationRate
activation rate of IR illuminator for NDI Polaris tracking device
NDIErrorCode Receive(std::string *answer, unsigned int numberOfBytes)
receive numberOfBytes bytes from tracking device
An object of this class represents an exception of the MITK-IGT module.
const unsigned char LF
virtual bool RemoveTool(TrackingTool *tool)
Remove a passive 6D tool from the list of tracked tools.
virtual void TrackTools()
TrackTools() continuously polls serial interface for new 6d tool positions until StopTracking is call...
DataCollection - Class to facilitate loading/accessing structured data.
virtual void SetDataBits(const DataBits _arg)
returns the baud rate for serial communication
static TrackingDeviceData GetDeviceDataSpectraExtendedPyramid()
virtual void SetDataTransferMode(const DataTransferMode _arg)
returns the activation rate of IR illumator for polaris
Tool6DContainerType m_6DTools
list of 6D tools
PortNumber m_PortNumber
COM Port Number.
virtual void TrackToolsAndMarkers()
continuously polls serial interface for new 3D marker positions and 6D tool positions until StopTrack...
static TrackingDeviceData GetDeviceDataAuroraPlanarDome()
virtual bool GetSupportedVolumes(unsigned int *numberOfVolumes, NDITrackingVolumeContainerType *volumes, TrackingVolumeDimensionType *volumesDimensions)
Get number of supported tracking volumes, a vector containing the supported volumes and a vector cont...
TrackingDeviceType Line
static ITK_THREAD_RETURN_TYPE ThreadStartTracking(void *data)
static start method for the tracking thread.
virtual void InvalidateAll()
invalidate all tools
virtual void SetIlluminationActivationRate(const IlluminationActivationRate _arg)
returns the hardware handshake setting
static void info(const char *fmt,...)
Definition: svm.cpp:86
TrackingDeviceState GetState() const
return current object state (Setup, Ready or Tracking)
virtual OperationMode GetOperationMode()
get current operation mode
itk::MultiThreader::Pointer m_MultiThreader
creates tracking thread that continuously polls serial interface for new tracking data ...
NDIErrorCode ReceiveLine(std::string *answer)
receive characters until the first LF (The LF is included in the answer string)
virtual bool SetVolume(mitk::TrackingDeviceData volume)
Sets the desired tracking volume. Returns true if the volume type could be set. It is set in the Open...
static Pointer New()
virtual void SetStopBits(const StopBits _arg)
returns the parity mode
bool DiscoverWiredTools()
retrieves all wired tools from the tracking device
static Vector3D offset
const std::string CalcCRC(const std::string *input)
returns the CRC16 for input as a std::string
DataTransferMode m_DataTransferMode
use TX (text) or BX (binary) (
virtual void SetParity(const Parity _arg)
returns the data bits for serial communication
static TrackingDeviceData GetDeviceDataAuroraPlanarCube()
std::vector< int > TrackingVolumeDimensionType
List of the supported tracking volume dimensions.
static Pointer New()
get file from which this tool was loaded
mitk::SerialCommunication::Pointer m_SerialCommunication
serial communication interface
#define MITK_WARN
Definition: mitkLogMacros.h:19
std::string m_DeviceName
Device Name.
virtual bool StopTracking()
stop retrieving tracking data from the device. stop retrieving tracking data from the device...
void ClearReceiveBuffer()
empty receive buffer of serial communication interface
An object of this class represents an exception of MITK. Please don&#39;t instantiate exceptions manually...
Definition: mitkException.h:45
mitk::NavigationToolStorage::Pointer AutoDetectTools() override
static TrackingDeviceData GetDeviceDataPolarisSpectra()
bool m_StopTracking
signal stop to tracking thread
Interface for all Tracking Devices.
virtual mitk::TrackingDeviceType TestConnection()
TestConnection() tries to connect to a NDI tracking device on the current port/device and returns whi...
static IGTTimeStamp * GetInstance()
returns a pointer to the current instance of mitkTimeStamp
const unsigned char CR
std::vector< MarkerPointType > MarkerPointContainerType
virtual void TrackMarkerPositions()
continuously polls serial interface for new 3D marker positions until StopTracking is called...
static TrackingDeviceData GetDeviceDataPolarisVicra()
itk::FastMutexLock::Pointer m_MarkerPointsMutex
mutex for marker point data container
void Start(itk::Object::Pointer device)
starts the time-acquisition
virtual void SetHardwareHandshake(const HardwareHandshake _arg)
returns the number of stop bits
static Pointer New()
Constructs a NavigationToolStorage without reference to a DataStorage. The Data Nodes of tools have t...
OperationMode m_OperationMode
tracking mode (6D tool tracking, 3D marker tracking,...)
TrackingTool * GetTool(unsigned int toolNumber) const override
return the tool with index toolNumber
virtual const char * GetFirmwareRevisionNumber()
Get revision number from tracking device as string should not be called directly after starting to tr...
serial communication interface
static Pointer New()
void ClearSendBuffer()
empty send buffer of serial communication interface
Implementation of a passive NDI optical tool.
Parity m_Parity
Parity mode for communication.
virtual void SetPortNumber(const PortNumber _arg)
set port number for serial communication
TrackingDeviceData m_Data
current device Data
wbAdvisor reset(new berry::WorkbenchAdvisor)
#define mitkThrowException(classname)
std::string TrackingDeviceType
virtual bool IsEnabled() const
returns whether the tool is enabled or disabled
itk::FastMutexLock::Pointer m_StopTrackingMutex
mutex to control access to m_StopTracking
unsigned int GetToolCount() const override
return current number of tools
mitk::TrackingTool * AddTool(const char *toolName, const char *fileName, TrackingPriority p=NDIPassiveTool::Dynamic)
Create a passive 6D tool with toolName and fileName and add it to the list of tools.
virtual const unsigned char * GetSROMData() const
get loaded srom file as unsigned char array
void SetRotationMode(RotationMode r) override
BaudRate m_BaudRate
COM Port Baud Rate.
superclass for specific NDI tracking Devices that use serial communication.
virtual TrackingPriority GetTrackingPriority() const
set tracking priority that the ndi tracking device should use
DataBits m_DataBits
Number of Data Bits per token.
TrackingPriority
tracking priority for NDI tracking devices
virtual bool Beep(unsigned char count)
returns the data transfer mode
NDIErrorCode
Error codes of NDI tracking devices.
~NDITrackingDevice() override
Destructor.
MarkerPointContainerType m_MarkerPoints
container for markers (3D point tracking mode)
DataTransferMode
Data transfer mode for NDI tracking devices.
virtual void SetDeviceName(std::string _arg)
returns the port number for serial communication
bool CloseConnection() override
Closes the connection.
virtual bool SetOperationMode(OperationMode mode)
set operation mode to 6D tool tracking, 3D marker tracking or 6D&3D hybrid tracking (see OperationMod...
StopBits m_StopBits
number of stop bits per token
void SetState(TrackingDeviceState state)
change object state
itk::FastMutexLock::Pointer m_SerialCommunicationMutex
mutex for coordinated access of serial communication interface
TrackingDeviceType GetType() const
Deprecated! Use the more specific getData or GetTrackingDeviceName instead. return device type identi...
virtual unsigned int GetSROMDataLength() const
get length of SROMData char array
bool StartTracking() override
Start the tracking.
virtual const char * GetToolName() const
every tool has a name thatgit can be used to identify it.
itk::FastMutexLock::Pointer m_ToolsMutex
mutex for coordinated access of tool container
mitk::TrackingTool * GetToolByName(std::string name) const override
Returns the tool with the given tool name.
static TrackingDeviceData GetDeviceDataPolarisOldModel()
void SetType(TrackingDeviceType type)
Deprecated! Use the more specific setDeviceData instead. set device type.