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