Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkNDIProtocol.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 "mitkNDIProtocol.h"
18 #include "mitkNDITrackingDevice.h"
22 #include <string>
23 #include <algorithm>
24 #include <sstream>
25 #include <itksys/SystemTools.hxx>
26 #include <stdio.h>
27 
29 : itk::Object(), m_TrackingDevice(nullptr), m_UseCRC(true)
30 {
31 }
32 
33 
35 {
36 }
37 
38 
40 {
41  /* Build parameter string */
42  std::string param;
43  switch (baudRate)
44  {
46  param += "1";
47  break;
49  param += "2";
50  break;
52  param += "3";
53  break;
55  param += "4";
56  break;
58  param += "5";
59  break;
61  default: // assume 9600 Baud as default
62  param += "0";
63  break;
64  }
65  switch (dataBits)
66  {
68  param += "1";
69  break;
71  default: // set 8 data bits as default
72  param += "0";
73  break;
74  }
75  switch (parity)
76  {
78  param += "1";
79  break;
81  param += "2";
82  break;
84  default: // set no parity as default
85  param += "0";
86  break;
87  }
88  switch (stopBits)
89  {
91  param += "1";
92  break;
94  default: // set 1 stop bit as default
95  param += "0";
96  break;
97  }
98  switch (hardwareHandshake)
99  {
101  param += "1";
102  break;
104  default: // set no hardware handshake as default
105  param += "0";
106  break;
107  }
108  return GenericCommand("COMM", &param);
109 }
110 
111 
113 {
114  return GenericCommand("INIT");
115 }
116 
117 
119 {
120  return GenericCommand("DSTART");
121 }
122 
123 
125 {
126  return GenericCommand("DSTOP");
127 }
128 
129 
131 {
132  return GenericCommand("IRINIT");
133 }
134 
135 
137 {
138  NDIErrorCode returnValue = NDIUNKNOWNERROR; // return code for this function. Will be set according to reply from trackingsystem
139 
140  if (m_TrackingDevice == nullptr)
141  return TRACKINGDEVICENOTSET;
142 
143  /* send command */
144  std::string fullcommand;
145  if (m_UseCRC == true)
146  fullcommand = "IRCHK:0001"; // command string format 1: with crc
147  else
148  fullcommand = "IRCHK 0001"; // command string format 2: without crc
149 
150  returnValue = m_TrackingDevice->Send(&fullcommand, m_UseCRC);
151 
152  if (returnValue != NDIOKAY) // check for send error
153  {
154  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove any reply
155  return returnValue;
156  }
157  /* wait for the trackingsystem to process the command */
158  itksys::SystemTools::Delay(100);
159  /* read and parse the reply from tracking device */
160  // the reply for IRCHK can be either Infrared Source Information or ERROR##
161  // because we use the simple reply format, the answer will be only one char:
162  // "0" - no IR detected
163  // "1" - IR detected
164  std::string reply;
165  char b;
166  m_TrackingDevice->ReceiveByte(&b);// read the first byte
167  reply = b;
168  if ((b == '0') || (b == '1')) // normal answer
169  {
170  /* perform CRC checking */
171  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
172  std::string readCRC; // read attached crc value
173  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
174  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
175  {
176  if ( b == '0')
177  *IRdetected = false;
178  else
179  *IRdetected = true;
180  returnValue = NDIOKAY;
181  }
182  else // return error in CRC
183  {
184  returnValue = NDICRCERROR;
185  *IRdetected = false; // IRdetected is only valid if return code of this function is NDIOKAY
186  }
187  }
188  else if (b =='E') // expect ERROR##
189  {
190  std::string errorstring;
191  m_TrackingDevice->Receive(&errorstring, 4); // read the remaining 4 characters of ERROR
192  reply += errorstring;
193  static const std::string error("ERROR");
194  if (error.compare(0, 5, reply) == 0) // check for "ERROR"
195  {
196  std::string errorcode;
197  m_TrackingDevice->Receive(&errorcode, 2); // now read 2 bytes error code
198  /* perform CRC checking */
199  reply += errorcode; // build complete reply string
200  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
201  std::string readCRC; // read attached crc value
202  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
203  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
204  returnValue = this->GetErrorCode(&errorcode);
205  else
206  returnValue = NDICRCERROR; // return error in CRC
207  }
208  } else // something else, that we do not expect
209  returnValue = NDIUNEXPECTEDREPLY;
210 
211  /* cleanup and return */
212  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
213  return returnValue;
214 }
215 
216 
217 mitk::NDIErrorCode mitk::NDIProtocol::PHSR(PHSRQueryType queryType, std::string* portHandles)
218 {
219  NDIErrorCode returnValue = NDIUNKNOWNERROR;
220 
221  if (m_TrackingDevice == nullptr)
222  return TRACKINGDEVICENOTSET;
223 
224  /* send command */
225  std::string command;
226  char stringQueryType[3];
227  sprintf(stringQueryType, "%02X", queryType);// convert numerical queryType to string in hexadecimal format
228 
229  if (m_UseCRC == true)
230  command = std::string("PHSR:") + std::string(stringQueryType);
231  else //if (m_UseCRC != true)
232  command = std::string("PHSR ") + std::string(stringQueryType); // command string format 2: without crc
233 
234  returnValue = m_TrackingDevice->Send(&command, m_UseCRC);
235 
236  if (returnValue != NDIOKAY) // check for send error
237  {
238  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove any reply
239  return returnValue;
240  }
241 
242  itksys::SystemTools::Delay(100);
243 
244  std::string reply;
245  m_TrackingDevice->Receive(&reply, 2); // read first 2 characters of reply ("Number of Handles" as a 2 digit hexadecimal number)
246  static const std::string error("ERROR");
247  if (error.compare(0, 2, reply) == 0) // check for "ERROR" (compare for "ER" because we can not be sure that the reply is more than 2 characters (in case of 0 port handles returned)
248  {
249  std::string ror;
250  m_TrackingDevice->Receive(&ror, 3); // read rest of ERROR (=> "ROR")
251  reply += ror; // build complete reply string
252  std::string errorcode;
253  m_TrackingDevice->Receive(&errorcode, 2); // now read 2 bytes error code
254  reply += errorcode; // build complete reply string
255  /* perform CRC checking */
256  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
257  std::string readCRC; // read attached crc value
258  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
259  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
260  returnValue = this->GetErrorCode(&errorcode);
261  else // return error in CRC
262  returnValue = NDICRCERROR;
263  }
264  else // No error, expect number of handles as a 2 character hexadecimal value
265  {
266  unsigned int numberOfHandles = 0;
267  // convert the hexadecimal string representation to a numerical using a stringstream
268  std::stringstream s;
269  s << reply;
270  s >> numberOfHandles;
271  if (numberOfHandles > 16) // there can not be more than 16 handles ToDo: exact maximum number depend on tracking device and firmware revision. these data could be read with VER and used here
272  {
273  returnValue = NDIUNKNOWNERROR;
274  }
275  else
276  {
277  std::string handleInformation;
278  portHandles->clear();
279  for (unsigned int i = 0; i < numberOfHandles; i++) // read 5 characters for each handle and extract port handle
280  {
281  m_TrackingDevice->Receive(&handleInformation, 5);
282  *portHandles += handleInformation.substr(0, 2); // Append the port handle to the portHandles string
283  reply += handleInformation; // build complete reply string for crc checking
284  }
285  /* perform CRC checking */
286  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
287  std::string readCRC; // read attached crc value
288  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
289  if (expectedCRC == readCRC) // if the read CRC is correct, return okay
290  returnValue = NDIOKAY;
291  else // return error in CRC
292  returnValue = NDICRCERROR;
293  }
294  }
295  /* cleanup and return */
296  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
297  return returnValue;
298 }
299 
300 
302 {
303  NDIErrorCode returnValue = NDIUNKNOWNERROR; // return code for this function. Will be set according to reply from tracking device
304 
305  if (m_TrackingDevice == nullptr)
306  return TRACKINGDEVICENOTSET;
307 
308  /* send command */
309  std::string command;
310  if (m_UseCRC == true)
311  command = "PHRQ:*********1****"; // command string format 1: with crc
312  else
313  command = "PHRQ *********1****"; // command string format 2: without crc
314 
315  returnValue = m_TrackingDevice->Send(&command, m_UseCRC);
316 
317  if (returnValue != NDIOKAY) // check for send error
318  {
319  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove any reply
320  return returnValue;
321  }
322 
323  itksys::SystemTools::Delay(100); // give the tracking device some time to process the command
324 
325  std::string reply;
326  m_TrackingDevice->Receive(&reply, 2); // read first 2 characters of reply ("Number of Handles" as a 2 digit hexadecimal number)
327  static const std::string error("ERROR");
328  if (error.compare(0, 2, reply) == 0) // check for "ERROR" (compare for "ER" because we can not be sure that the reply is more than 2 characters (in case of 0 port handles returned)
329  {
330  std::string ror;
331  m_TrackingDevice->Receive(&ror, 3); // read rest of ERROR (=> "ROR")
332  reply += ror; // build complete reply string
333  std::string errorcode;
334  m_TrackingDevice->Receive(&errorcode, 2); // now read 2 bytes error code
335  reply += errorcode; // build complete reply string
336  /* perform CRC checking */
337  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
338  std::string readCRC; // read attached crc value
339  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
340  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
341  returnValue = this->GetErrorCode(&errorcode);
342  else // return error in CRC
343  returnValue = NDICRCERROR;
344  }
345  else // No error, expect port handle as a 2 character hexadecimal value
346  {
347  *portHandle = reply; // assign the port handle to the return string
348  /* perform CRC checking */
349  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
350  std::string readCRC; // read attached crc value
351  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
352  if (expectedCRC == readCRC) // if the read CRC is correct, return okay
353  returnValue = NDIOKAY;
354  else // else return error in CRC
355  returnValue = NDICRCERROR;
356  }
357  /* cleanup and return */
358  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
359  return returnValue;
360 }
361 
362 
363 mitk::NDIErrorCode mitk::NDIProtocol::PVWR(std::string* portHandle, const unsigned char* sromData, unsigned int sromDataLength)
364 {
365  NDIErrorCode returnValue = NDIUNKNOWNERROR; // return code for this function. Will be set according to reply from trackingsystem
366 
367  if (m_TrackingDevice == nullptr)
368  return TRACKINGDEVICENOTSET;
369 
370  if (sromDataLength > 1024)
371  return SROMFILETOOLARGE;
372 
373  if (sromDataLength == 0)
374  return SROMFILETOOSMALL;
375 
376  /* build send commands */
377  std::string basecommand;
378  if (m_UseCRC == true)
379  basecommand = "PVWR:"; // command string format 1: with crc
380  else
381  basecommand = "PVWR "; // command string format 2: without crc
382 
383  std::string hexSROMData;
384  hexSROMData.reserve(2 * sromDataLength);
385  char hexcharacter[20]; // 7 bytes should be enough (in send loop)
386  for (unsigned int i = 0; i < sromDataLength; i++)
387  {
388  sprintf(hexcharacter, "%02X", sromData[i]); // convert srom byte to string in hexadecimal format
389  //hexSROMData += "12";
390  hexSROMData += hexcharacter; // append hex string to srom data in hex format
391  }
392  /* data must be written in chunks of 64 byte (128 hex characters). To ensure 64 byte chunks the last chunk must be padded with 00 */
393  unsigned int zerosToPad = 128 - (hexSROMData.size() % 128); // hexSROMData must be a multiple of 128
394  if (zerosToPad > 0)
395  hexSROMData.append(zerosToPad, '0');
396  /* now we have all the data, send it in 128 character chunks */
397  std::string fullcommand;
398  for (unsigned int j = 0; j < hexSROMData.size(); j += 128)
399  {
400  sprintf(hexcharacter, "%s%04X", portHandle->c_str(), j/2); // build the first two parameters: PortHandle and SROM device adress (not in hex characters, but in bytes)
401  fullcommand = basecommand + hexcharacter + hexSROMData.substr(j, 128); // build complete command string
402  returnValue = m_TrackingDevice->Send(&fullcommand, m_UseCRC); // send command
403  itksys::SystemTools::Delay(50); // Wait for trackingsystem to process the data
404  if (returnValue != NDIOKAY) // check for send error
405  break;
406  returnValue = this->ParseOkayError(); // parse answer
407  if (returnValue != NDIOKAY) // check for error returned from tracking device
408  break;
409  }
410  /* cleanup and return */
411  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
412  return returnValue;
413 }
414 
415 
417 {
418  NDIErrorCode returnValue = NDIUNKNOWNERROR; // return code for this function. Will be set according to reply from trackingsystem
419 
420  if (m_TrackingDevice == nullptr)
421  return TRACKINGDEVICENOTSET;
422 
423  /* send command */
424  std::string fullcommand;
425  if (m_UseCRC == true)
426  fullcommand = std::string("PINIT:") + *portHandle; // command string format 1: with crc
427  else
428  fullcommand = std::string("PINIT ") + *portHandle; // command string format 2: without crc
429 
430  returnValue = m_TrackingDevice->Send(&fullcommand, m_UseCRC);
431 
432  if (returnValue != NDIOKAY) // check for send error
433  {
434  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove any reply
435  return returnValue;
436  }
437 
438  /* wait for the trackingsystem to process the command */
439  itksys::SystemTools::Delay(100);
440  std::string reply;
441  m_TrackingDevice->Receive(&reply, 4); // read first 4 characters of reply
442 
443  /* Parse reply from tracking device */
444  static const std::string okay("OKAYA896"); // OKAY is static, so we can perform a static crc check
445  static const std::string error("ERROR");
446  static const std::string warning("WARNING7423"); // WARNING has a static crc too
447 
448  if (okay.compare(0, 4, reply) == 0) // check for "OKAY": compare first 4 characters from okay with reply
449  {
450  // OKAY was found, now check the CRC16 too
451  m_TrackingDevice->Receive(&reply, 4); // read 4 hexadecimal characters for CRC16
452  if (okay.compare(4, 4, reply, 0, 4) == 0) // first 4 from new reply should match last 4 from okay
453  returnValue = NDIOKAY;
454  else
455  returnValue = NDICRCERROR;
456  }
457  else if (warning.compare(0, 4, reply) == 0) // check for "WARNING"
458  {
459  // WARN was found, now check remaining characters and CRC16
460  m_TrackingDevice->Receive(&reply, 4); // read 4 hexadecimal characters for CRC16
461  if (warning.compare(4, 7, reply, 0, 7) == 0) // first 7 from new reply should match last 7 from okay
462  returnValue = NDIWARNING;
463  else
464  returnValue = NDICRCERROR;
465  }
466  else if (error.compare(0, 4, reply) == 0) // check for "ERRO"
467  {
468  char b; // The ERROR reply is not static, so we can not use a static crc check.
469  m_TrackingDevice->ReceiveByte(&b); // read next character ("R" from ERROR)
470  reply += b; // to build complete reply string
471  std::string errorcode;
472  m_TrackingDevice->Receive(&errorcode, 2); // now read 2 bytes error code
473  reply += errorcode; // build complete reply string
474  /* perform CRC checking */
475  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
476  std::string readCRC; // read attached crc value
477  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
478  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
479  returnValue = this->GetErrorCode(&errorcode);
480  else // return error in CRC
481  returnValue = NDICRCERROR;
482  } else // else it is something else, that we do not expect
483  returnValue = NDIUNEXPECTEDREPLY;
484 
485 
486  //read cr carriage return
487  char b;
488  m_TrackingDevice->ReceiveByte(&b);
489 
490  /* cleanup and return */
491  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
492  return returnValue;
493 }
494 
495 
497 {
498  std::string param;
499  if (portHandle != nullptr)
500  param = *portHandle + (char) prio;
501  else
502  param = "";
503  return this->GenericCommand("PENA", &param);
504 }
505 
506 
507 mitk::NDIErrorCode mitk::NDIProtocol::PHINF(std::string portHandle, std::string* portInfo)
508 {
509  std::string command;
510  if (m_UseCRC) command = "PHINF:" + portHandle;
511  else command = "PHINF " + portHandle;
512  mitk::NDIErrorCode returnValue = m_TrackingDevice->Send(&command, m_UseCRC);
513  if (returnValue==NDIOKAY)
514  {
515  m_TrackingDevice->ClearReceiveBuffer();
516  m_TrackingDevice->Receive(portInfo, 33);
517  m_TrackingDevice->ClearReceiveBuffer();
518  }
519  else m_TrackingDevice->ClearReceiveBuffer();
520  return returnValue;
521 }
522 
523 
525 {
526  return this->GenericCommand("PDIS", portHandle);
527 }
528 
529 
531 {
532  return this->GenericCommand("PHF", portHandle);
533 }
534 
535 
537 {
538  std::string param;
539  switch (rate)
540  {
541  case Hz60:
542  param = "2";
543  break;
544  case Hz30:
545  param = "1";
546  break;
547  case Hz20:
548  default:
549  param = "0";
550  break;
551  }
552  return this->GenericCommand("IRATE", &param);
553 }
554 
555 
557 {
558  NDIErrorCode returnValue = NDIUNKNOWNERROR; // return code for this function. Will be set according to reply from trackingsystem
559 
560  if (m_TrackingDevice == nullptr)
561  return TRACKINGDEVICENOTSET;
562 
563  std::string p;
564  if ((count >= 1) && (count <= 9))
565  p = (count + '0'); // convert the number count to a character representation
566  else
568 
569  /* send command */
570  std::string fullcommand;
571  if (m_UseCRC == true)
572  fullcommand = "BEEP:" + p; // command string format 1: with crc
573  else
574  fullcommand = "BEEP " + p; // command string format 2: without crc
575 
576  returnValue = m_TrackingDevice->Send(&fullcommand, m_UseCRC);
577 
578  if (returnValue != NDIOKAY) // check for send error
579  {
580  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove any reply
581  return returnValue;
582  }
583 
584  /* wait for the trackingsystem to process the command */
585  itksys::SystemTools::Delay(100);
586 
587  std::string reply;
588  char b;
589  m_TrackingDevice->ReceiveByte(&b); // read the first byte
590  reply = b;
591  if ((b == '0') || (b == '1')) // normal answer
592  {
593  /* perform CRC checking */
594  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
595  std::string readCRC; // read attached crc value
596  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
597  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
598  returnValue = NDIOKAY;
599  else // return error in CRC
600  returnValue = NDICRCERROR;
601  }
602  else if (b =='E') // expect ERROR##
603  {
604  std::string errorstring;
605  m_TrackingDevice->Receive(&errorstring, 4); // read the remaining 4 characters of ERROR
606  reply += errorstring;
607  static const std::string error("ERROR");
608  if (error.compare(0, 5, reply) == 0) // check for "ERROR"
609  {
610  std::string errorcode;
611  m_TrackingDevice->Receive(&errorcode, 2); // now read 2 bytes error code
612  /* perform CRC checking */
613  reply += errorcode; // build complete reply string
614  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
615  std::string readCRC; // read attached crc value
616  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
617  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
618  returnValue = this->GetErrorCode(&errorcode);
619  else
620  returnValue = NDICRCERROR; // return error in CRC
621  }
622  } else // something else, that we do not expect
623  returnValue = NDIUNEXPECTEDREPLY;
624 
625  /* cleanup and return */
626  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
627  return returnValue;
628 }
629 
630 
632 {
633  std::string param = "80";
634  if (resetFrameCounter == true)
635  return this->GenericCommand("TSTART", &param);
636  else
637  return this->GenericCommand("TSTART");
638 }
639 
640 
642 {
643  return this->GenericCommand("TSTOP");
644 }
645 
646 
647 mitk::NDIErrorCode mitk::NDIProtocol::PSOUT(std::string portHandle, std::string state)
648 {
649  std::string param = portHandle + state;
650  return this->GenericCommand("PSOUT", &param);
651 }
652 
653 
654 mitk::NDIErrorCode mitk::NDIProtocol::TX(bool trackIndividualMarkers, MarkerPointContainerType* markerPositions)
655 {
656  NDIErrorCode returnValue = NDIUNKNOWNERROR; // return code for this function. Will be set according to reply from tracking device
657 
658  if(trackIndividualMarkers)
659  markerPositions->clear();
660 
661  if (m_TrackingDevice == nullptr)
662  return TRACKINGDEVICENOTSET;
663 
664  /* send command */
665  std::string fullcommand;
666  if (trackIndividualMarkers)
667  {
668  if (m_UseCRC == true)
669  fullcommand = "TX:1001"; // command string format 1: with crc
670  else
671  fullcommand = "TX 1001"; // command string format 2: without crc
672  } else
673  {
674  if (m_UseCRC == true)
675  fullcommand = "TX:"; // command string format 1: with crc
676  else
677  fullcommand = "TX "; // command string format 2: without crc
678  }
679 
680  returnValue = m_TrackingDevice->Send(&fullcommand, m_UseCRC);
681  if (returnValue != NDIOKAY)
682  {
683  /* cleanup and return */
684  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
685  return returnValue;
686  }
687  /* read number of handles returned */
688  std::string reply;
689  std::string s;
690  m_TrackingDevice->Receive(&reply, 2); // read first 2 characters of reply (error or number of handles returned)
691  //printf("%d",reply);
692  static const std::string error("ERROR");
693  if (error.compare(0, 2, reply) == 0)
694  {
695  m_TrackingDevice->Receive(&s, 3); // read next characters ("ROR" from ERROR)
696  reply += s; // to build complete reply string
697  std::string errorcode;
698  m_TrackingDevice->Receive(&errorcode, 2); // now read 2 bytes error code
699  reply += errorcode; // build complete reply string
700  /* perform CRC checking */
701  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
702  std::string readCRC; // read attached crc value
703  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
704  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
705  {
706  returnValue = this->GetErrorCode(&errorcode);
707  }
708  else // return error in CRC
709  {
710  returnValue = NDICRCERROR;
711  }
712  }
713  else // transformation data is returned
714  {
715  /* parse number of handles from first 2 characters */
716  std::stringstream converter;
717  unsigned int numberOfHandles = 0;
718  converter << std::hex << reply; // insert reply into stringstream
719  converter >> numberOfHandles; // extract number of handles as unsigned byte
720  converter.clear(); // converter must be cleared to be reused
721  converter.str("");
722 
723  /* read and parse transformation data for each handle */
724  for (unsigned int i = 0; i < numberOfHandles; i++) // for each handle
725  {
726  /* Read port handle */
727  m_TrackingDevice->Receive(&s, 2); // read port handle
728  reply += s; // build complete command string
729  NDIPassiveTool::Pointer tool = m_TrackingDevice->GetInternalTool(s); // get tool object for that handle
730  if (tool.IsNull())
731  {
732  returnValue = UNKNOWNHANDLERETURNED;
733  break; // if we do not know the handle, we can not assume anything about the remaining data, so we better abort (we could read up to the next LF)
734  }
735  /* Parse reply from tracking device */
736  static const std::string missing("MISSING");
737  static const std::string disabled("DISABLED");
738  static const std::string unoccupied("UNOCCUPIED");
739 
740  m_TrackingDevice->Receive(&s, 6); // read next 6 characters: either an error message or part of the transformation data
741  reply += s; // build complete command string
742  if (missing.compare(0, 6, s) == 0)
743  {
744  tool->SetErrorMessage("Tool is reported as 'missing'.");
745  tool->SetDataValid(false);
746  m_TrackingDevice->Receive(&s, 18); // after 'missin', 1 character for 'g', 8 characters for port status, 8 characters for frame number and one for line feed are send
747  reply += s; // build complete command string
748  }
749  else if (disabled.compare(0, 6, s) == 0)
750  {
751  tool->SetErrorMessage("Tool is reported as 'disabled'.");
752  tool->SetDataValid(false);
753  m_TrackingDevice->Receive(&s, 3); // read last characters of disabled plus 8 characters for port status, 8 characters for frame number and one for line feed
754  reply += s; // build complete command string
755  }
756  else if (unoccupied.compare(0, 6, s) == 0)
757  {
758  tool->SetErrorMessage("Tool is reported as 'unoccupied'.");
759  tool->SetDataValid(false);
760  m_TrackingDevice->Receive(&s, 21); // read remaining characters of UNOCCUPIED
761  reply += s; // build complete command string
762  }
763  else // transformation data
764  {
765  /* define local copies */
766  signed int number = 0;
767  float localPos[3] = {0.0, 0.0, 0.0};
768  float localQuat[4] = {0.0, 0.0, 0.0, 0.0};
769  float localError = 0.0;
770  unsigned long localPortStatus = 0;
771  unsigned int localFrameNumber = 0;
772  /* read and parse the four 6 character quaternion values */
773  //std::cout << "s = " << s << std::endl;
774  converter << std::dec << s; // insert string with first number into stringstream
775  converter >> number; // extract first number as integer
776  converter.clear(); // converter must be cleared to be reused
777  converter.str("");
778  //std::cout << "number = " << number << std::endl;
779  localQuat[0] = number / 10000.0; // the value is send with an implied decimal point with 4 digits to the right
780  for (unsigned int i = 1; i < 4; i++)// read the next 3 numbers
781  {
782  m_TrackingDevice->Receive(&s, 6); // read the next number
783  reply += s; // build complete command string
784  converter << std::dec << s; // insert string with first number into stringstream
785  converter >> number; // extract first number as integer
786  converter.clear(); // converter must be cleared to be reused
787  converter.str("");
788  localQuat[i] = number / 10000.0; // the value is send with an implied decimal point with 4 digits to the right
789  }
790  /* read and parse the three 7 character translation values */
791  for (auto & localPo : localPos)
792  {
793  m_TrackingDevice->Receive(&s, 7); // read the next position vector number
794  reply += s; // build complete command string
795  converter << std::dec << s; // insert string with number into stringstream
796  converter >> number; // extract first number as integer
797  converter.clear(); // converter must be cleared to be reused
798  converter.str("");
799  localPo = number / 100.0; // the value is send with an implied decimal point with 2 digits to the right
800  }
801  /* read and parse 6 character error value */
802  m_TrackingDevice->Receive(&s, 6); // read the error value
803  reply += s; // build complete command string
804  converter << std::dec << s; // insert string with number into stringstream
805  converter >> number; // extract the number as integer
806  converter.clear(); // converter must be cleared to be reused
807  converter.str("");
808  localError = number / 10000.0; // the error value is send with an implied decimal point with 4 digits to the right
809  /* read and parse 8 character port status */
810  m_TrackingDevice->Receive(&s, 8); // read the port status value
811  reply += s; // build complete command string
812  converter << std::hex << s; // insert string into stringstream
813  converter >> localPortStatus; // extract the number as unsigned long
814  converter.clear(); // converter must be cleared to be reused
815  converter.str("");
816  /* read and parse 8 character frame number as hexadecimal */
817  m_TrackingDevice->Receive(&s, 8); // read the frame number value
818  reply += s; // build complete command string
819  converter << std::hex << s; // insert string with hex value encoded number into stringstream
820  converter >> localFrameNumber; // extract the number as unsigned long
821  converter.clear(); // converter must be cleared to be reused
822  converter.str("");
823 
824  /* copy local values to the tool */
825  mitk::Quaternion orientation(localQuat[1], localQuat[2], localQuat[3], localQuat[0]);
826 
827  //If the rotation mode is vnlTransposed we have to transpose the quaternion
828  if (m_TrackingDevice->GetRotationMode() == mitk::NDITrackingDevice::RotationTransposed)
829  {
830  orientation[0] *= -1; //qx
831  orientation[1] *= -1; //qy
832  orientation[2] *= -1; //qz
833  //qr is not inverted
834  }
835 
836  tool->SetOrientation(orientation);
837  mitk::Point3D position;
838  position[0] = localPos[0];
839  position[1] = localPos[1];
840  position[2] = localPos[2];
841  tool->SetPosition(position);
842  tool->SetTrackingError(localError);
843  tool->SetErrorMessage("");
844  tool->SetDataValid(true);
845  m_TrackingDevice->Receive(&s, 1); // read the line feed character, that terminates each handle data
846  reply += s; // build complete command string
847  }
848  } // for
849 
850 
851  //Read Reply Option 1000 data
852  if(trackIndividualMarkers)
853  {
854  /* parse number of markers from first 2 characters */
855  m_TrackingDevice->Receive(&s, 2);
856  reply += s;
857  unsigned int numberOfMarkers = 0;
858  converter << std::hex << s; // insert reply into stringstream
859  converter >> numberOfMarkers; // extract number of markers as unsigned byte
860  converter.clear(); // converter must be cleared to be reused
861  converter.str("");
862 
863  unsigned int oovReplySize = (unsigned int)ceil((double)numberOfMarkers/4.0);
864  unsigned int nbMarkersInVolume = 0;
865  char c;
866  // parse oov data to find out how many marker positions were recorded
867  for (unsigned int i = 0; i < oovReplySize; i++)
868  {
869  m_TrackingDevice->ReceiveByte(&c);
870  reply += c;
871  nbMarkersInVolume += ByteToNbBitsOn(c);
872  }
873 
874  nbMarkersInVolume = numberOfMarkers-nbMarkersInVolume;
875 
876  /* read and parse position data for each marker */
877  for (unsigned int i = 0; i < nbMarkersInVolume; i++)
878  {
879  /* define local copies */
880  signed int number = 0;
881  MarkerPointType markerPosition;
882  /* read and parse the three 7 character translation values */
883  for (unsigned int i = 0; i < 3; i++)
884  {
885  m_TrackingDevice->Receive(&s, 7); // read the next position vector number
886  reply += s; // build complete command string
887  converter << std::dec << s; // insert string with number into stringstream
888  converter >> number; // extract first number as integer
889  converter.clear(); // converter must be cleared to be reused
890  converter.str("");
891  markerPosition[i] = number / 100.0; // the value is send with an implied decimal point with 2 digits to the right
892  }
893  markerPositions->push_back(markerPosition);
894  } // end for all markers
895  }
896  //END read Reply Option 1000 data
897 
898 
899  /* Read System Status */
900  m_TrackingDevice->Receive(&s, 4); // read system status
901  reply += s; // build complete command string
902  /* now the reply string is complete, perform crc checking */
903  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
904  std::string readCRC; // read attached crc value
905  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
906  if (expectedCRC == readCRC) // if the read CRC is correct, return okay
907  {
908  returnValue = NDIOKAY;
909  }
910  else // return error in CRC
911  {
912  returnValue = NDICRCERROR;
913  /* Invalidate all tools because the received data contained an error */
914  m_TrackingDevice->InvalidateAll();
915  if(trackIndividualMarkers)
916  markerPositions->clear();
917  }
918  } // else
919 
920  /* cleanup and return */
921  m_TrackingDevice->Receive(&s, 1); // read the last linde feed (because the tracking system device is sometimes to slow to send it before we clear the buffer. In this case, the LF would remain in the receive buffer and be read as the first character of the next command
922  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
923  return returnValue;
924 }
925 
926 
928 {
929  NDIErrorCode returnValue = NDIUNKNOWNERROR; // return code for this function. Will be set according to reply from trackingsystem
930 
931  markerPositions->clear();
932 
933  if (m_TrackingDevice == nullptr)
934  return TRACKINGDEVICENOTSET;
935 
936  /* send command */
937  std::string fullcommand;
938  if (m_UseCRC == true)
939  fullcommand = "TX:1001"; // command string format 1: with crc
940  else
941  fullcommand = "TX 1001"; // command string format 2: without crc
942 
943  returnValue = m_TrackingDevice->Send(&fullcommand, m_UseCRC);
944 
945  /* read number of handles returned */
946  std::string reply;
947  std::string s;
948  m_TrackingDevice->Receive(&reply, 2); // read first 2 characters of reply (error or number of handles returned)
949 
950  static const std::string error("ERROR");
951  if (error.compare(0, 2, reply) == 0)
952  {
953  m_TrackingDevice->Receive(&s, 3); // read next characters ("ROR" from ERROR)
954  reply += s; // to build complete reply string
955  std::string errorcode;
956  m_TrackingDevice->Receive(&errorcode, 2); // now read 2 bytes error code
957  reply += errorcode; // build complete reply string
958  /* perform CRC checking */
959  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
960  std::string readCRC; // read attached crc value
961  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
962  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
963  {
964  returnValue = this->GetErrorCode(&errorcode);
965  }
966  else // return error in CRC
967  {
968  returnValue = NDICRCERROR;
969  }
970  }
971  else // transformation data is returned
972  {
973  /* parse number of handles from first 2 characters */
974  std::stringstream converter;
975  unsigned int numberOfHandles = 0;
976  converter << std::hex << reply; // insert reply into stringstream
977  converter >> numberOfHandles; // extract number of handles as unsigned byte
978  converter.clear(); // converter must be cleared to be reused
979  converter.str("");
980 
981  /* read and parse transformation data for each handle */
982  for (unsigned int i = 0; i < numberOfHandles; i++) // for each handle
983  {
984  /* Read port handle */
985  m_TrackingDevice->Receive(&s, 2); // read port handle
986  reply += s; // build complete command string
987  NDIPassiveTool::Pointer tool = m_TrackingDevice->GetInternalTool(s); // get tool object for that handle
988  if (tool.IsNull())
989  {
990  returnValue = UNKNOWNHANDLERETURNED;
991  break; // if we do not know the handle, we can not assume anything about the remaining data, so we better abort (we could read up to the next LF)
992  }
993  /* Parse reply from tracking device */
994  static const std::string missing("MISSING");
995  static const std::string disabled("DISABLED");
996  static const std::string unoccupied("UNOCCUPIED");
997 
998  m_TrackingDevice->Receive(&s, 6); // read next 6 characters: either an error message or part of the transformation data
999  reply += s; // build complete command string
1000  if (missing.compare(0, 6, s) == 0)
1001  {
1002  tool->SetErrorMessage("Tool is reported as 'missing'.");
1003  tool->SetDataValid(false);
1004  m_TrackingDevice->Receive(&s, 18); // after 'missin', 1 character for 'g', 8 characters for port status, 8 characters for frame number and one for line feed are send
1005  reply += s; // build complete command string
1006  }
1007  else if (disabled.compare(0, 6, s) == 0)
1008  {
1009  tool->SetErrorMessage("Tool is reported as 'disabled'.");
1010  tool->SetDataValid(false);
1011  m_TrackingDevice->Receive(&s, 19); // read last characters of disabled plus 8 characters for port status, 8 characters for frame number and one for line feed
1012  reply += s; // build complete command string
1013  }
1014  else if (unoccupied.compare(0, 6, s) == 0)
1015  {
1016  tool->SetErrorMessage("Tool is reported as 'unoccupied'.");
1017  tool->SetDataValid(false);
1018  m_TrackingDevice->Receive(&s, 21); // read remaining characters of UNOCCUPIED
1019  reply += s; // build complete command string
1020  }
1021  else // transformation data
1022  {
1023  /* define local copies */
1024  signed int number = 0;
1025  float localPos[3] = {0.0, 0.0, 0.0};
1026  float localQuat[4] = {0.0, 0.0, 0.0, 0.0};
1027  float localError = 0.0;
1028  unsigned long localPortStatus = 0;
1029  unsigned int localFrameNumber = 0;
1030  /* read and parse the four 6 character quaternion values */
1031  //std::cout << "s = " << s << std::endl;
1032  converter << std::dec << s; // insert string with first number into stringstream
1033  converter >> number; // extract first number as integer
1034  converter.clear(); // converter must be cleared to be reused
1035  converter.str("");
1036  //std::cout << "number = " << number << std::endl;
1037  localQuat[0] = number / 10000.0; // the value is send with an implied decimal point with 4 digits to the right
1038  for (unsigned int i = 1; i < 4; i++)// read the next 3 numbers
1039  {
1040  m_TrackingDevice->Receive(&s, 6); // read the next number
1041  reply += s; // build complete command string
1042  converter << std::dec << s; // insert string with first number into stringstream
1043  converter >> number; // extract first number as integer
1044  converter.clear(); // converter must be cleared to be reused
1045  converter.str("");
1046  localQuat[i] = number / 10000.0; // the value is send with an implied decimal point with 4 digits to the right
1047  }
1048  /* read and parse the three 7 character translation values */
1049  for (auto & localPo : localPos)
1050  {
1051  m_TrackingDevice->Receive(&s, 7); // read the next position vector number
1052  reply += s; // build complete command string
1053  converter << std::dec << s; // insert string with number into stringstream
1054  converter >> number; // extract first number as integer
1055  converter.clear(); // converter must be cleared to be reused
1056  converter.str("");
1057  localPo = number / 100.0; // the value is send with an implied decimal point with 2 digits to the right
1058  }
1059  /* read and parse 6 character error value */
1060  m_TrackingDevice->Receive(&s, 6); // read the error value
1061  reply += s; // build complete command string
1062  converter << std::dec << s; // insert string with number into stringstream
1063  converter >> number; // extract the number as integer
1064  converter.clear(); // converter must be cleared to be reused
1065  converter.str("");
1066  localError = number / 10000.0; // the error value is send with an implied decimal point with 4 digits to the right
1067  /* read and parse 8 character port status */
1068  m_TrackingDevice->Receive(&s, 8); // read the port status value
1069  reply += s; // build complete command string
1070  converter << std::hex << s; // insert string into stringstream
1071  converter >> localPortStatus; // extract the number as unsigned long
1072  converter.clear(); // converter must be cleared to be reused
1073  converter.str("");
1074  /* read and parse 8 character frame number as hexadecimal */
1075  m_TrackingDevice->Receive(&s, 8); // read the frame number value
1076  reply += s; // build complete command string
1077  converter << std::hex << s; // insert string with hex value encoded number into stringstream
1078  converter >> localFrameNumber; // extract the number as unsigned long
1079  converter.clear(); // converter must be cleared to be reused
1080  converter.str("");
1081 
1082  /* copy local values to the tool */
1083  mitk::Quaternion orientation(localQuat[1], localQuat[2], localQuat[3], localQuat[0]);
1084  tool->SetOrientation(orientation);
1085  mitk::Point3D position;
1086  position[0] = localPos[0];
1087  position[1] = localPos[1];
1088  position[2] = localPos[2];
1089  tool->SetPosition(position);
1090  tool->SetTrackingError(localError);
1091  tool->SetErrorMessage("");
1092  tool->SetDataValid(true);
1093  m_TrackingDevice->Receive(&s, 1); // read the line feed character, that terminates each handle data
1094  reply += s; // build complete command string
1095  }
1096  }
1097  //Read Reply Option 1000 data
1098 
1099  /* parse number of markers from first 2 characters */
1100  m_TrackingDevice->Receive(&s, 2);
1101  reply += s;
1102  unsigned int numberOfMarkers = 0;
1103  converter << std::hex << s; // insert reply into stringstream
1104  converter >> numberOfMarkers; // extract number of markers as unsigned byte
1105  converter.clear(); // converter must be cleared to be reused
1106  converter.str("");
1107 
1108  unsigned int oovReplySize = (unsigned int)ceil((double)numberOfMarkers/4.0);
1109  unsigned int nbMarkersInVolume = 0;
1110  char c;
1111  // parse oov data to find out how many marker positions were recorded
1112  for (unsigned int i = 0; i < oovReplySize; i++)
1113  {
1114  m_TrackingDevice->ReceiveByte(&c);
1115  reply += c;
1116  nbMarkersInVolume += ByteToNbBitsOn(c);
1117  }
1118 
1119  nbMarkersInVolume = numberOfMarkers-nbMarkersInVolume;
1120 
1121  /* read and parse position data for each marker */
1122  for (unsigned int i = 0; i < nbMarkersInVolume; i++)
1123  {
1124  /* define local copies */
1125  signed int number = 0;
1126  MarkerPointType markerPosition;
1127  /* read and parse the three 7 character translation values */
1128  for (unsigned int i = 0; i < 3; i++)
1129  {
1130  m_TrackingDevice->Receive(&s, 7); // read the next position vector number
1131  reply += s; // build complete command string
1132  converter << std::dec << s; // insert string with number into stringstream
1133  converter >> number; // extract first number as integer
1134  converter.clear(); // converter must be cleared to be reused
1135  converter.str("");
1136  markerPosition[i] = number / 100.0; // the value is send with an implied decimal point with 2 digits to the right
1137  }
1138  markerPositions->push_back(markerPosition);
1139  } // end for all markers
1140  //m_TrackingDevice->Receive(&s, 1); // read the line feed character, that terminates each handle data
1141  //reply += s; // build complete command string
1142  //
1143 
1144  //END read Reply Option 1000 data
1145 
1146 
1147  m_TrackingDevice->Receive(&s, 4); // read system status
1148  reply += s; // build complete command string
1149  /* now the reply string is complete, perform crc checking */
1150  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
1151  std::string readCRC; // read attached crc value
1152  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
1153  if (expectedCRC == readCRC) // if the read CRC is correct, return okay
1154  {
1155  returnValue = NDIOKAY;
1156  }
1157  else // return error in CRC
1158  {
1159  returnValue = NDICRCERROR;
1160  /* Invalidate all tools because the received data contained an error */
1161  markerPositions->clear();
1162  m_TrackingDevice->InvalidateAll();
1163  }
1164  } // else
1165 
1166  /* cleanup and return */
1167  m_TrackingDevice->Receive(&s, 1); // read the last linde feed (because the tracking system device is sometimes to slow to send it before we clear the buffer. In this case, the LF would remain in the receive buffer and be read as the first character of the next command
1168  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
1169  return returnValue;
1170 }
1171 
1172 
1174 {
1175  std::cout << "BX() not implemented yet, using TX() instead." << std::endl;
1176  return this->TX();
1177 }
1178 
1179 
1181 {
1182  if (m_TrackingDevice == nullptr)
1183  return TRACKINGDEVICENOTSET;
1184 
1185  NDIErrorCode returnValue = NDIUNKNOWNERROR; // return code for this function. Will be set according to reply from tracking system
1186  /* send command */
1187  std::string fullcommand;
1188  if (m_UseCRC == true)
1189  fullcommand = "VER:4"; // command string format 1: with crc
1190  else
1191  fullcommand = "VER 4"; // command string format 2: without crc
1192 
1193  returnValue = m_TrackingDevice->Send(&fullcommand, m_UseCRC);
1194  if (returnValue != NDIOKAY)
1195  {
1196  /* cleanup and return */
1197  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
1198  return returnValue;
1199  }
1200  /* read number of handles returned */
1201  std::string reply;
1202  m_TrackingDevice->Receive(&reply, 5); // read first 5 characters of reply (error beginning of version information)
1203  static const std::string error("ERROR");
1204  if (error.compare(0, 6, reply) == 0) // ERROR case
1205  {
1206  std::string errorcode;
1207  m_TrackingDevice->Receive(&errorcode, 2); // now read 2 bytes error code
1208  reply += errorcode; // build complete reply string
1209  /* perform CRC checking */
1210  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
1211  std::string readCRC; // read attached crc value
1212  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
1213  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
1214  returnValue = this->GetErrorCode(&errorcode);
1215  else // return error in CRC
1216  returnValue = NDICRCERROR;
1217  }
1218  else // no error, valid reply
1219  {
1220  std::string s;
1221  m_TrackingDevice->ReceiveLine(&s); // read until first LF character
1222  reply += s;
1223  std::string upperCaseReply;
1224  upperCaseReply.resize(reply.size());
1225  std::transform (reply.begin(), reply.end(), upperCaseReply.begin(), toupper); // convert reply to uppercase to ease finding
1226  if (upperCaseReply.find("POLARIS") != std::string::npos)
1228  else if (upperCaseReply.find("AURORA") != std::string::npos)
1230  else
1232  // check for "VICRA", "SPECTRA", "ACCEDO"
1233  /* do not check for remaining reply, do not check for CRC, just delete remaining reply */
1234  itksys::SystemTools::Delay(500); // wait until reply should be finished
1235  m_TrackingDevice->ClearReceiveBuffer();
1236  returnValue = NDIOKAY;
1237  }
1238  return returnValue;
1239 }
1240 
1241 
1243 {
1244  NDIErrorCode returnValue = NDIUNKNOWNERROR; // return code for this function. Will be set according to reply from trackingsystem
1245 
1246  if (m_TrackingDevice == nullptr)
1247  {
1248  return TRACKINGDEVICENOTSET;
1249  }
1250  if (markerPositions == nullptr)
1251  {
1252  std::cout << "ERROR: markerPositions==NULL" << std::endl;
1253  return NDIUNKNOWNERROR;
1254  }
1255 
1256  markerPositions->clear(); // empty point container
1257  /* try to obtain a porthandle */
1258  if (m_TrackingDevice->GetToolCount() == 0)
1259  {
1260  std::cout << "ERROR: no tools present" << std::endl;
1261  return NDIUNKNOWNERROR;
1262  }
1263  const TrackingTool* t = m_TrackingDevice->GetTool(static_cast<unsigned int>(0));
1264  const NDIPassiveTool* t2 = dynamic_cast<const NDIPassiveTool*>(t);
1265  if (t2 == nullptr)
1266  {
1267  std::cout << "ERROR: no tool present" << std::endl;
1268  return NDIUNKNOWNERROR;
1269  }
1270  std::string portHandle = t2->GetPortHandle();
1271  if (portHandle.size() == 0)
1272  {
1273  std::cout << "ERROR: no port handle" << std::endl;
1274  return NDIUNKNOWNERROR;
1275  }
1276 
1277  /* send command */
1278  std::string fullcommand;
1279  if (m_UseCRC == true)
1280  fullcommand = "3D:" + portHandle + "5"; // command string format 1: with crc
1281  else
1282  fullcommand = "3D " + portHandle + "5"; // command string format 2: without crc
1283 
1284  m_TrackingDevice->ClearReceiveBuffer();
1285  returnValue = m_TrackingDevice->Send(&fullcommand, m_UseCRC);
1286 
1287  /* read number of markers returned */
1288  std::string reply;
1289  std::string s;
1290 
1291  mitk::NDIErrorCode receivevalue = m_TrackingDevice->Receive(&reply, 3); // read first 3 characters of reply (error or number of markers returned)
1292  if(receivevalue != NDIOKAY)
1293  {
1294  std::cout << "ERROR: receive_value != NDIOKAY" << std::endl;
1295  return receivevalue;
1296  }
1297 
1298  static const std::string error("ERROR");
1299  if (error.compare(0, 3, reply) == 0)
1300  {
1301  m_TrackingDevice->Receive(&s, 2); // read next characters ("OR" from ERROR)
1302  reply += s; // to build complete reply string
1303  std::string errorcode;
1304  m_TrackingDevice->Receive(&errorcode, 2); // now read 2 bytes error code
1305  reply += errorcode; // build complete reply string
1306  /* perform CRC checking */
1307  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
1308  std::string readCRC; // read attached crc value
1309  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
1310  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
1311  {
1312  returnValue = this->GetErrorCode(&errorcode);
1313  }
1314  else // return error in CRC
1315  {
1316  returnValue = NDICRCERROR;
1317  }
1318  }
1319  else // transformation data is returned
1320  {
1321  signed int number = 0;
1322  //float localPos[3] = {0.0, 0.0, 0.0};
1323  MarkerPointType p;
1324  //float lineSeparation = 0.0;
1325 
1326  /* parse number of markers from first 3 characters */
1327  std::stringstream converter;
1328  unsigned int numberOfMarkers = 0;
1329  converter << std::dec << reply; // insert reply into stringstream
1330  converter >> numberOfMarkers; // extract number of handles as unsigned byte
1331  converter.clear(); // converter must be cleared to be reused
1332  converter.str("");
1333  /* read and parse 3D data for each marker */
1334  for (unsigned int markerID = 0; markerID < numberOfMarkers; markerID++) // for each marker
1335  {
1336  m_TrackingDevice->Receive(&s, 1); // read line feed
1337  reply += s; // build complete command string
1338  /* read and parse the three 9 character translation values */
1339  for (unsigned int i = 0; i < 3; i++)
1340  {
1341  receivevalue = m_TrackingDevice->Receive(&s, 9); // read the next position vector number
1342  if(receivevalue != NDIOKAY)
1343  {
1344  markerPositions->clear();
1345  std::cout << "ERROR: receive_value != NDIOKAY" << std::endl;
1346  return receivevalue;
1347  }
1348  reply += s; // build complete command string
1349  converter << std::dec << s; // insert string with number into stringstream
1350  converter >> number; // extract the number as integer
1351  converter.clear(); // converter must be cleared to be reused
1352  converter.str("");
1353  p[i] = number / 10000.0; // the value is send with an implied decimal point with 4 digits to the right
1354  }
1355  /* read and parse 4 character line separation value */
1356  receivevalue = m_TrackingDevice->Receive(&s, 4); // read the line separation value
1357  if(receivevalue != NDIOKAY)
1358  {
1359  markerPositions->clear();
1360  std::cout << "ERROR: receive_value != NDIOKAY" << std::endl;
1361  return receivevalue;
1362  }
1363  reply += s; // build complete command string
1364  converter << std::dec << s; // insert string with number into stringstream
1365  converter >> number; // extract the number as integer
1366  converter.clear(); // converter must be cleared to be reused
1367  converter.str("");
1368  //lineSeparation = number / 100.0; // the line separation value is send with an implied decimal point with 2 digits to the right
1369  /* read and parse 1 character out of volume value */
1370  receivevalue = m_TrackingDevice->Receive(&s, 1); // read the port status value
1371  if(receivevalue != NDIOKAY)
1372  {
1373  markerPositions->clear();
1374  std::cout << std::endl << std::endl << std::endl << "ERROR: POS3D != NDIOKAY" << std::endl;
1375  return receivevalue;
1376  }
1377  reply += s; // build complete command string
1378  /* store the marker positions in the point container */
1379  markerPositions->push_back(p);
1380  }
1381  //std::cout << "INFO: Found " << markerPositions->size() << " markers." << std::endl;
1382 
1383  /* now the reply string is complete, perform crc checking */
1384  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
1385  std::string readCRC; // read attached crc value
1386  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
1387  if (expectedCRC == readCRC) // if the read CRC is correct, return okay
1388  {
1389  returnValue = NDIOKAY;
1390  }
1391  else // return error in CRC
1392  {
1393  returnValue = NDICRCERROR;
1394  std::cout << "ERROR: receive_value != NDIOKAY" << std::endl;
1395  /* delete all marker positions because the received data contained an error */
1396  markerPositions->clear();
1397  }
1398  } // else
1399 
1400  /* cleanup and return */
1401  m_TrackingDevice->Receive(&s, 1); // read the last linde feed (because the tracking system device is sometimes to slow to send it before we clear the buffer. In this case, the LF would remain in the receive buffer and be read as the first character of the next command
1402  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
1403 
1404  return returnValue;
1405 }
1406 
1407 
1408 mitk::NDIErrorCode mitk::NDIProtocol::GenericCommand(const std::string command, const std::string* parameter)
1409 {
1410  NDIErrorCode returnValue = NDIUNKNOWNERROR; // return code for this function. Will be set according to reply from trackingsystem
1411 
1412  if (m_TrackingDevice == nullptr)
1413  return TRACKINGDEVICENOTSET;
1414 
1415  std::string p;
1416  if (parameter != nullptr)
1417  p = *parameter;
1418  else
1419  p = "";
1420 
1421  /* send command */
1422  std::string fullcommand;
1423  if (m_UseCRC == true)
1424  fullcommand = command + ":" + p; // command string format 1: with crc
1425  else
1426  fullcommand = command + " " + p; // command string format 2: without crc
1427 
1428 
1429  m_TrackingDevice->ClearReceiveBuffer(); // This is a workaround for a linux specific issue:
1430  // after sending the TSTART command and expecting an "okay" there are some unexpected bytes left in the buffer.
1431  // this issue is explained in bug 11825
1432 
1433  returnValue = m_TrackingDevice->Send(&fullcommand, m_UseCRC);
1434 
1435  if (returnValue != NDIOKAY) // check for send error
1436  {
1437  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove any reply
1438  return returnValue;
1439  }
1440  /* wait for the trackingsystem to process the command */
1441  itksys::SystemTools::Delay(100);
1442 
1443  /* read and parse the reply from tracking device */
1444  // the reply for a generic command can be OKAY or ERROR##
1445  // so we can use the generic parse method for these replies
1446  this->ParseOkayError();
1447  return returnValue;
1448 }
1449 
1450 
1451 unsigned int mitk::NDIProtocol::ByteToNbBitsOn(char& c) const
1452 {
1453  if(c == '0')
1454  return 0;
1455  else if (c == '1' || c == '2' || c == '4' || c == '8')
1456  return 1;
1457  else if (c == '3' || c == '5' || c == '9' || c == '6' || c == 'A' || c == 'C')
1458  return 2;
1459  else if (c == '7' || c == 'B' || c == 'D' || c == 'E')
1460  return 3;
1461  else if (c == 'F')
1462  return 4;
1463  else
1464  return 0;
1465 }
1466 
1467 
1469 {
1470  NDIErrorCode returnValue = NDIUNKNOWNERROR;
1471  /* read reply from tracking device */
1472  // the reply is expected to be OKAY or ERROR##
1473  // define reply strings
1474  std::string reply;
1475  m_TrackingDevice->Receive(&reply, 4); // read first 4 characters of reply
1476 
1477  /* Parse reply from tracking device */
1478  static const std::string okay("OKAYA896"); // OKAY is static, so we can perform a static crc check
1479  static const std::string error("ERROR");
1480 
1481  if (okay.compare(0, 4, reply) == 0) // check for "OKAY": compare first 4 characters from okay with reply
1482  {
1483  // OKAY was found, now check the CRC16 too
1484  m_TrackingDevice->Receive(&reply, 4); // read 4 hexadecimal characters for CRC16
1485  if (okay.compare(4, 4, reply, 0, 4) == 0) // first 4 from new reply should match last 4 from okay
1486  returnValue = NDIOKAY;
1487  else
1488  returnValue = NDICRCERROR;
1489  }
1490  else if (error.compare(0, 4, reply) == 0) // check for "ERRO"
1491  {
1492  char b; // The ERROR reply is not static, so we can not use a static crc check.
1493  m_TrackingDevice->ReceiveByte(&b); // read next character ("R" from ERROR)
1494  reply += b; // to build complete reply string
1495  std::string errorcode;
1496  m_TrackingDevice->Receive(&errorcode, 2); // now read 2 bytes error code
1497  reply += errorcode; // build complete reply string
1498  /* perform CRC checking */
1499  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
1500  std::string readCRC; // read attached crc value
1501  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
1502  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
1503  returnValue = this->GetErrorCode(&errorcode);
1504  else // return error in CRC
1505  returnValue = NDICRCERROR;
1506  }
1507  else // something else, that we do not expect
1508  returnValue = NDIUNEXPECTEDREPLY;
1509 
1510  /* cleanup and return */
1511  char b;
1512  m_TrackingDevice->ReceiveByte(&b); // read CR character
1513  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
1514  return returnValue;
1515 }
1516 
1517 
1519 {
1520  if (input->compare("01") == 0)
1521  return NDIINVALIDCOMMAND;
1522  else if (input->compare("02") == 0)
1523  return NDICOMMANDTOOLONG;
1524  else if (input->compare("03") == 0)
1525  return NDICOMMANDTOOSHORT;
1526  else if (input->compare("04") == 0)
1527  return NDICRCDOESNOTMATCH;
1528  else if (input->compare("05") == 0)
1529  return NDITIMEOUT;
1530  else if (input->compare("06") == 0)
1532  else if (input->compare("07") == 0)
1534  else if (input->compare("08") == 0)
1535  return NDIINVALIDPORTHANDLE;
1536  else if (input->compare("09") == 0)
1538  else if (input->compare("0A") == 0)
1539  return NDIINVALIDLED;
1540  else if (input->compare("0B") == 0)
1541  return NDIINVALIDLEDSTATE;
1542  else if (input->compare("0C") == 0)
1544  else if (input->compare("0D") == 0)
1545  return NDINOTOOLFORPORT;
1546  else if (input->compare("0E") == 0)
1547  return NDIPORTNOTINITIALIZED;
1548 
1549  // ...
1550  else if (input->compare("10") == 0)
1551  return NDISYSTEMNOTINITIALIZED;
1552  else if (input->compare("11") == 0)
1553  return NDIUNABLETOSTOPTRACKING;
1554  else if (input->compare("12") == 0)
1555  return NDIUNABLETOSTARTTRACKING;
1556  else if (input->compare("13") == 0)
1557  return NDIINITIALIZATIONFAILED;
1558  else if (input->compare("14") == 0)
1560  else if (input->compare("16") == 0)
1562  else if (input->compare("1B") == 0)
1563  return NDICANTINITIRDIAGNOSTICS;
1564  else if (input->compare("1F") == 0)
1565  return NDIFAILURETOWRITESROM;
1566  else if (input->compare("22") == 0)
1568  else if (input->compare("23") == 0)
1570  else if (input->compare("2A") == 0)
1571  return NDINOMEMORYAVAILABLE;
1572  else if (input->compare("2B") == 0)
1574  else if (input->compare("2C") == 0)
1576  else if (input->compare("2D") == 0)
1577  return NDIOUTOFHANDLES;
1578  else if (input->compare("2E") == 0)
1580  else if (input->compare("2F") == 0)
1582  else if (input->compare("32") == 0)
1584  // ...
1585  else
1586  return NDIUNKNOWNERROR;
1587 }
1588 
1590 {
1591  if (m_TrackingDevice == nullptr)
1592  return TRACKINGDEVICENOTSET;
1593 
1594  NDIErrorCode returnValue = NDIUNKNOWNERROR; // return code for this function. Will be set according to reply from tracking system
1595 
1596  /* send command */
1597  std::string command;
1598  if (m_UseCRC)
1599  command = "APIREV:";
1600  else
1601  command = "APIREV ";
1602 
1603  returnValue = m_TrackingDevice->Send(&command, m_UseCRC);
1604  if (returnValue != NDIOKAY)
1605  {
1606  /* cleanup and return */
1607  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
1608  return returnValue;
1609  }
1610 
1611  //wait for tracking system to compute the output
1612  //itksys::SystemTools::Delay(100);
1613 
1614  /* read number of handles returned */
1615  std::string reply;
1616  m_TrackingDevice->Receive(&reply, 5); //look for ERROR
1617 
1618  // read first 5 characters of reply (error beginning of version information)
1619  static const std::string error("ERROR");
1620  if (error.compare(0, 6, reply) == 0) // ERROR case
1621  {
1622  std::string errorcode;
1623  m_TrackingDevice->Receive(&errorcode, 2); // now read 2 bytes error code
1624  reply += errorcode; // build complete reply string
1625 
1626  /* perform CRC checking */
1627  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
1628  std::string readCRC; // read attached crc value
1629  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
1630 
1631  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
1632  returnValue = this->GetErrorCode(&errorcode);
1633  else // return error in CRC
1634  returnValue = NDICRCERROR;
1635  }
1636  else // no error, valid reply: expect something like: D.001.00450D4 (<Family>.<Major revision number>.<Minor revision number><CRC16><CR>
1637  {
1638  std::string s;
1639 
1640  m_TrackingDevice->Receive(&s, 4); // read further
1641  reply += s;
1642 
1643  /* perform CRC checking */
1644  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
1645  std::string readCRC; // read attached crc value
1646  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
1647 
1648  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
1649  returnValue = NDIOKAY;
1650  else // return error in CRC
1651  returnValue = NDICRCERROR;
1652  }
1653 
1654  *revision = reply;
1655  m_TrackingDevice->ClearReceiveBuffer();
1656  return returnValue;
1657 }
1658 
1659 
1661 {
1662  if (m_TrackingDevice == nullptr)
1663  return TRACKINGDEVICENOTSET;
1664 
1665  NDIErrorCode returnValue = NDIUNKNOWNERROR; // return code for this function. Will be set according to reply from tracking system
1666 
1667  /* send command */
1668  std::string command;
1669  if (m_UseCRC)
1670  command = "SFLIST:03";
1671  else
1672  command = "SFLIST 03";
1673 
1674  returnValue = m_TrackingDevice->Send(&command, m_UseCRC);
1675  if (returnValue != NDIOKAY)
1676  {
1677  /* cleanup and return */
1678  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
1679  return returnValue;
1680  }
1681 
1682  /* read number of handles returned */
1683  std::string reply;
1684  m_TrackingDevice->Receive(&reply, 5); //look for "ERROR"
1685 
1686  static const std::string error("ERROR");
1687  if (error.compare(0,6,reply) == 0) // ERROR case
1688  {
1689  std::string errorcode;
1690  m_TrackingDevice->Receive(&errorcode, 2); // now read 2 bytes error code
1691  reply += errorcode; // build complete reply string
1692 
1693  /* perform CRC checking */
1694  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
1695  std::string readCRC; // read attached crc value
1696  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
1697 
1698  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
1699  returnValue = this->GetErrorCode(&errorcode);
1700  else // return error in CRC
1701  returnValue = NDICRCERROR;
1702  }
1703 
1704  else // no error, valid reply: expect numbers of devices in hex, and then info of each featured tracking volume <CRC16><CR>
1705  {
1706  /* parse number of volumes from first character in hex */
1707  std::stringstream converter;
1708  unsigned int numberOfVolumes = 0;
1709  converter << std::hex << reply[0]; // insert reply into stringstream
1710  converter >> numberOfVolumes; // extract number of handles as unsigned byte
1711  converter.clear(); // converter must be cleared to be reused
1712  converter.str("");
1713 
1714  if ( numberOfVolumes > 9 )
1715  {
1716  MITK_WARN << "Number of volumes (" << numberOfVolumes
1717  << ") is not smaller then ten as it was expected. Cannot get supported volumes.";
1718  numberOfVolumes = 0;
1719  reply[0] = numberOfVolumes;
1720  }
1721 
1722  //reply currently contains the first 5 elements
1723  if (numberOfVolumes>0)
1724  {
1725  //for each featured volume
1726  for (unsigned int i = 0; i<numberOfVolumes; i++)
1727  {
1728  std::string currentVolume;
1729  if (i==0)
1730  {
1731  //already read the first 4 bytes of the volume info
1732  currentVolume.append(reply,1,4);
1733  std::string s;
1734  m_TrackingDevice->Receive(&s, 69);// 69 characters to get all dimensions plus two characters at the end: one reserved and one for metal resistance.
1735  reply += s;
1736  currentVolume += s;
1737  }
1738  else
1739  {
1740  //read to the end of the line from the last volume
1741  //(needed here, because if only one volume is supported,
1742  //then there is no lineending <LF> before CRC checksum
1743  std::string l;
1744  m_TrackingDevice->ReceiveLine(&l);
1745  reply += l;
1746 
1747  std::string s;
1748  m_TrackingDevice->Receive(&s, 73); //need total of 73 bytes for a volume
1749  reply += s;
1750  currentVolume += s;
1751 
1752  if ( s.empty() )
1753  {
1754  MITK_INFO << "Cannot get information of tracking volume " << i << ". Abort getting of tracking volumes.";
1755  numberOfVolumes = 0;
1756  reply[0] = numberOfVolumes;
1757  break;
1758  }
1759  }
1760  //analyze volume here
1761 
1762  if (currentVolume.compare(0, 1, mitk::NDIPolarisTypeInformation::GetDeviceDataPolarisOldModel().HardwareCode) == 0)
1763  MITK_INFO<<"Standard volume supported \n";
1764  else if (currentVolume.compare(0, 3, mitk::NDIPolarisTypeInformation::GetDeviceDataPolarisSpectra().HardwareCode) == 0)
1765  MITK_INFO<<"Spectra pyramid volume supported \n";
1767  MITK_INFO<<"Spectra extended pyramid volume supported \n";
1768  else if (currentVolume.compare(0, 1, mitk::NDIPolarisTypeInformation::GetDeviceDataPolarisVicra().HardwareCode) == 0)
1769  MITK_INFO<<"Vicra volume supported \n";
1770  else if (currentVolume.compare(0, 1, mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarCube().HardwareCode) == 0)
1771  MITK_INFO<<"Cube volume supported \n";
1772  else if (currentVolume.compare(0, 1, mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarDome().HardwareCode) == 0)
1773  MITK_INFO<<"Dome volume supported \n";
1774  else
1775  MITK_WARN<<"Message not understood!\n";
1776  }
1777  }
1778 
1779  /* perform CRC checking */
1780  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
1781  std::string readCRC; // read attached crc value
1782  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
1783 
1784  /* CRC check is commented out at the moment, because there is a bug (see bug 16285 for more information)
1785  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
1786  returnValue = NDIOKAY;
1787  else // return error in CRC
1788  returnValue = NDICRCERROR;
1789  */
1790 
1791  returnValue = NDIOKAY;
1792  }
1793 
1794  *info = reply;
1795  m_TrackingDevice->ClearReceiveBuffer();
1796  return returnValue;
1797 }
1798 
1800 {
1801  if (m_TrackingDevice == nullptr)
1802  return TRACKINGDEVICENOTSET;
1803 
1804  NDIErrorCode returnValue = NDIUNKNOWNERROR; // return code for this function. Will be set according to reply from tracking system
1805 
1806 
1807  //get information about the order of volumes from tracking device. Then choose the number needed for VSEL by the output and parameter "device"
1808  unsigned int numberOfVolumes;
1811  if (!m_TrackingDevice->GetSupportedVolumes(&numberOfVolumes, &volumes, &volumesDimensions))
1812  return returnValue;
1813 
1814  //interested in volumes(!)
1815  if (volumes.empty())
1816  return returnValue;
1817  //with the order within volumes we can define our needed parameter for VSEL
1818  //find the index where volumes[n] == device
1819 
1820  unsigned int index = 1; //the index for VSEL starts at 1
1821  auto it = volumes.begin();
1822  while (it != volumes.end())
1823  {
1824  if ((*it) == deviceData.Model)
1825  {
1826  MITK_INFO << deviceData.Model << " selected.";
1827  break;
1828  }
1829  it++, index++;
1830  }
1831  if (it == volumes.end() || index > numberOfVolumes) //not found / volume not supported
1833 
1834  //index now contains the information on which position the desired volume is situated
1835 
1836  /* send command */
1837  std::string command;
1838  if (m_UseCRC)
1839  command = "VSEL:";
1840  else
1841  command = "VSEL ";
1842 
1843  //add index to command
1844  std::stringstream s;
1845  s << index;
1846  command += s.str();
1847 
1848  returnValue = m_TrackingDevice->Send(&command, m_UseCRC);
1849  if (returnValue != NDIOKAY)
1850  {
1851  /* cleanup and return */
1852  m_TrackingDevice->ClearReceiveBuffer(); // flush the buffer to remove the remaining carriage return or unknown/unexpected reply
1853  return returnValue;
1854  }
1855 
1856  /* read number of handles returned */
1857  std::string reply;
1858  m_TrackingDevice->Receive(&reply, 4); //look for "ERROR" or "OKAY"
1859 
1860  static const std::string error("ERRO");
1861  if (error.compare(reply) == 0) // ERROR case
1862  {
1863  std::string s;
1864  m_TrackingDevice->Receive(&s, 1); //get the last "R" in "ERROR"
1865  reply += s;
1866 
1867  std::string errorcode;
1868  m_TrackingDevice->Receive(&errorcode, 2); // now read 2 bytes error code
1869  reply += errorcode; // build complete reply string
1870 
1871  /* perform CRC checking */
1872  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
1873  std::string readCRC; // read attached crc value
1874  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
1875 
1876  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
1877  returnValue = this->GetErrorCode(&errorcode);
1878  else // return error in CRC
1879  returnValue = NDICRCERROR;
1880  }
1881  else
1882  {
1883  /* perform CRC checking */
1884  std::string expectedCRC = m_TrackingDevice->CalcCRC(&reply); // calculate crc for received reply string
1885  std::string readCRC; // read attached crc value
1886  m_TrackingDevice->Receive(&readCRC, 4); // CRC16 is 2 bytes long, which is transmitted as 4 hexadecimal digits
1887 
1888  if (expectedCRC == readCRC) // if the read CRC is correct, return normal error code
1889  returnValue = NDIOKAY;
1890  else // return error in CRC
1891  returnValue = NDICRCERROR;
1892  }
1893  m_TrackingDevice->ClearReceiveBuffer();
1894  return returnValue;
1895 }
NDIErrorCode TSTART(bool resetFrameCounter=false)
Start Tracking Mode. The tracking system must be in setup mode and must be initialized.
NDIErrorCode TX(bool trackIndividualMarkers=false, MarkerPointContainerType *markerPositions=nullptr)
Report transformations in text mode. Optionally, individual markers can be tracked.
Interface for all Tracking Tools.
NDIErrorCode INIT()
Initialize the Measurement System.
itk::SmartPointer< Self > Pointer
std::vector< std::string > NDITrackingVolumeContainerType
vector of tracking volumes
#define MITK_INFO
Definition: mitkLogMacros.h:22
NDIErrorCode PDIS(std::string *portHandle)
Port Disable. Will disable a port that has been enabled with PENA.
IlluminationActivationRate
activation rate of IR illuminator for NDI Polaris tracking device
NDIErrorCode POS3D(MarkerPointContainerType *markerPositions)
Report 3D Positions of single markers. can only be used in diagnostics mode.
virtual const char * GetPortHandle() const
get port handle under which the tool is registered in the tracking device
NDIErrorCode IRINIT()
Initialize the System to Check for Infrared.
static TrackingDeviceData GetDeviceDataSpectraExtendedPyramid()
static TrackingDeviceData GetDeviceDataAuroraPlanarDome()
itk::Point< double > MarkerPointType
PHSRQueryType
Query mode for NDI tracking devices.
NDIErrorCode VER(mitk::TrackingDeviceType &t)
returns if the tracking device is a Polaris or an Aurora system
static void info(const char *fmt,...)
Definition: svm.cpp:100
NDIErrorCode TX1000(MarkerPointContainerType *markerPositions)
Report transformations in text mode.
NDIErrorCode BX()
Report transformations in binary mode.
static TrackingDeviceData GetDeviceDataAuroraPlanarCube()
std::vector< int > TrackingVolumeDimensionType
List of the supported tracking volume dimensions.
NDIErrorCode TSTOP()
Stop Tracking Mode. The tracking system must be in Tracking mode.
unsigned int ByteToNbBitsOn(char &c) const
NDIErrorCode VSEL(mitk::TrackingDeviceData deviceData)
Sets the tracking volume to the given type. Check available tracking volumes with SFLIST first...
#define MITK_WARN
Definition: mitkLogMacros.h:23
NDIErrorCode PENA(std::string *portHandle, TrackingPriority prio)
Port Enable. Will enable a port that has been initialized with PINIT.
static TrackingDeviceData GetDeviceDataPolarisSpectra()
NDIErrorCode DSTOP()
Stop the Diagnostic Mode.
NDIErrorCode IRCHK(bool *IRdetected)
This version of IRCHK uses only the simple "presence of infrared light" call, that returns a binary "...
NDIErrorCode GenericCommand(const std::string command, const std::string *parameter=nullptr)
std::vector< MarkerPointType > MarkerPointContainerType
vnl_quaternion< ScalarType > Quaternion
static TrackingDeviceData GetDeviceDataPolarisVicra()
NDIErrorCode COMM(mitk::SerialCommunication::BaudRate baudRate, mitk::SerialCommunication::DataBits dataBits, mitk::SerialCommunication::Parity parity, mitk::SerialCommunication::StopBits stopBits, mitk::SerialCommunication::HardwareHandshake hardwareHandshake)
Change Serial Communication Parameters.
NDIErrorCode PHRQ(std::string *portHandle)
Port Handle Request. Will request a Port Handle for a wireless tool and return it in the string portH...
Implementation of a passive NDI optical tool.
NDIProtocol()
Set whether to append a CRC16 checksum to each message.
NDIErrorCode BEEP(unsigned char count)
Sounding the measurement system beeper. The tracking system will beep one to nine times...
NDIErrorCode PVWR(std::string *portHandle, const unsigned char *sromData, unsigned int sromDataLength)
Port Virtual Write. Writes an SROM Image data to a tool.
std::string TrackingDeviceType
NDIErrorCode PHF(std::string *portHandle)
Port Handle Free. Frees the port handle.
NDIErrorCode ParseOkayError()
NDIErrorCode PHSR(PHSRQueryType queryType, std::string *portHandles)
Port Handle Search. Will write returned port handles to the string portHandles.
NDIErrorCode GetErrorCode(const std::string *input)
returns the error code for an Error String returned from the NDI tracking device
TrackingPriority
tracking priority for NDI tracking devices
NDIErrorCode
Error codes of NDI tracking devices.
NDIErrorCode PHINF(std::string portHandle, std::string *portInfo)
NDIErrorCode DSTART()
Start the Diagnostic Mode.
NDIErrorCode APIREV(std::string *revision)
Gives information about the tool which is assosiated with the port handle. Writes portInfo to the str...
NDIErrorCode PINIT(std::string *portHandle)
Port Initialize. Will initialize a Port that has been acquired with PHRQ and has been assigned a SROM...
NDIErrorCode PSOUT(std::string portHandle, std::string state)
Set GPIO Output (Aurora)
NDIErrorCode SFLIST(std::string *info)
Returns information about the supported feature of the tracking system.
static TrackingDeviceData GetDeviceDataPolarisOldModel()
NDIErrorCode IRATE(IlluminationActivationRate rate)
Setting the illuminator rate. Will set the refresh rate for the illuminator for wireless tools...