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