MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
mitkNDIProtocol.cpp
Go to the documentation of this file.
1/*============================================================================
2
3The Medical Imaging Interaction Toolkit (MITK)
4
5Copyright (c) German Cancer Research Center (DKFZ)
6All rights reserved.
7
8Use of this source code is governed by a 3-clause BSD license that can be
9found in the LICENSE file.
10
11============================================================================*/
12
13#include "mitkNDIProtocol.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
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)
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
213mitk::NDIErrorCode mitk::NDIProtocol::PHSR(PHSRQueryType queryType, std::string* portHandles)
214{
215 NDIErrorCode returnValue = NDIUNKNOWNERROR;
216
217 if (m_TrackingDevice == nullptr)
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)
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
359mitk::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)
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)
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;
484 m_TrackingDevice->ReceiveByte(&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
503mitk::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 {
511 m_TrackingDevice->ClearReceiveBuffer();
512 m_TrackingDevice->Receive(portInfo, 33);
513 m_TrackingDevice->ClearReceiveBuffer();
514 }
515 else m_TrackingDevice->ClearReceiveBuffer();
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)
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
643mitk::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
650mitk::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)
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
824 if (m_TrackingDevice->GetRotationMode() == mitk::NDITrackingDevice::RotationTransposed)
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 {
865 m_TrackingDevice->ReceiveByte(&c);
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 */
910 m_TrackingDevice->InvalidateAll();
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)
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 {
1110 m_TrackingDevice->ReceiveByte(&c);
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();
1158 m_TrackingDevice->InvalidateAll();
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
1231 m_TrackingDevice->ClearReceiveBuffer();
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
1280 m_TrackingDevice->ClearReceiveBuffer();
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};
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
1404mitk::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
1447unsigned 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)
1548 else if (input->compare("11") == 0)
1550 else if (input->compare("12") == 0)
1552 else if (input->compare("13") == 0)
1554 else if (input->compare("14") == 0)
1556 else if (input->compare("16") == 0)
1558 else if (input->compare("1B") == 0)
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;
1651 m_TrackingDevice->ClearReceiveBuffer();
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;
1740 m_TrackingDevice->ReceiveLine(&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
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;
1791 m_TrackingDevice->ClearReceiveBuffer();
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 }
1889 m_TrackingDevice->ClearReceiveBuffer();
1890 return returnValue;
1891}
static TrackingDeviceData GetDeviceDataAuroraPlanarDome()
static TrackingDeviceData GetDeviceDataAuroraPlanarCube()
Implementation of a passive NDI optical tool.
TrackingPriority
tracking priority for NDI tracking devices
static TrackingDeviceData GetDeviceDataPolarisSpectra()
static TrackingDeviceData GetDeviceDataPolarisOldModel()
static TrackingDeviceData GetDeviceDataPolarisVicra()
static TrackingDeviceData GetDeviceDataSpectraExtendedPyramid()
NDIErrorCode INIT()
Initialize the Measurement System.
NDIErrorCode TX1000(MarkerPointContainerType *markerPositions)
Report transformations in text mode.
NDIErrorCode PHSR(PHSRQueryType queryType, std::string *portHandles)
Port Handle Search. Will write returned port handles to the string portHandles.
NDIErrorCode APIREV(std::string *revision)
Gives information about the tool which is assosiated with the port handle. Writes portInfo to the str...
NDIErrorCode PENA(std::string *portHandle, TrackingPriority prio)
Port Enable. Will enable a port that has been initialized with PINIT.
NDIErrorCode PHINF(std::string portHandle, std::string *portInfo)
NDIErrorCode POS3D(MarkerPointContainerType *markerPositions)
Report 3D Positions of single markers. can only be used in diagnostics mode.
NDIErrorCode IRINIT()
Initialize the System to Check for Infrared.
NDIErrorCode PSOUT(std::string portHandle, std::string state)
Set GPIO Output (Aurora)
NDIErrorCode DSTART()
Start 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 ParseOkayError()
NDIErrorCode TX(bool trackIndividualMarkers=false, MarkerPointContainerType *markerPositions=nullptr)
Report transformations in text mode. Optionally, individual markers can be tracked.
NDIErrorCode DSTOP()
Stop the Diagnostic Mode.
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 SFLIST(std::string *info)
Returns information about the supported feature of the tracking system.
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.
NDIErrorCode TSTOP()
Stop Tracking Mode. The tracking system must be in Tracking mode.
NDIErrorCode GenericCommand(const std::string command, const std::string *parameter=nullptr)
NDIErrorCode PVWR(std::string *portHandle, const unsigned char *sromData, unsigned int sromDataLength)
Port Virtual Write. Writes an SROM Image data to a tool.
NDIErrorCode PINIT(std::string *portHandle)
Port Initialize. Will initialize a Port that has been acquired with PHRQ and has been assigned a SROM...
NDIErrorCode PHF(std::string *portHandle)
Port Handle Free. Frees the port handle.
NDIErrorCode PDIS(std::string *portHandle)
Port Disable. Will disable a port that has been enabled with PENA.
NDIErrorCode GetErrorCode(const std::string *input)
returns the error code for an Error String returned from the NDI tracking device
NDIErrorCode TSTART(bool resetFrameCounter=false)
Start Tracking Mode. The tracking system must be in setup mode and must be initialized.
NDIErrorCode PHRQ(std::string *portHandle)
Port Handle Request. Will request a Port Handle for a wireless tool and return it in the string portH...
NDIErrorCode BX()
Report transformations in binary mode.
NDIErrorCode IRATE(IlluminationActivationRate rate)
Setting the illuminator rate. Will set the refresh rate for the illuminator for wireless tools.
NDIErrorCode BEEP(unsigned char count)
Sounding the measurement system beeper. The tracking system will beep one to nine times.
NDIErrorCode VER(mitk::TrackingDeviceType &t)
returns if the tracking device is a Polaris or an Aurora system
std::vector< int > TrackingVolumeDimensionType
List of the supported tracking volume dimensions.
std::vector< std::string > NDITrackingVolumeContainerType
vector of tracking volumes
Interface for all Tracking Tools.
itk::Point< double > MarkerPointType
IlluminationActivationRate
activation rate of IR illuminator for NDI Polaris tracking device
std::vector< MarkerPointType > MarkerPointContainerType
std::string TrackingDeviceType
NDIErrorCode
Error codes of NDI tracking devices.
@ NDICANTINITIRDIAGNOSTICS
@ NDIINCORRECTNUMBEROFPARAMETERS
@ NDIINVALIDLED
@ NDIINVALIDOPERATIONFORDEVICE
@ NDIINVALIDPORTDESCRIPTION
@ NDICOMMANDTOOSHORT
@ SROMFILETOOLARGE
@ NDIINVALIDVOLUMEPARAMETERS
@ SROMFILETOOSMALL
@ NDIOUTOFHANDLES
@ NDIINVALIDLEDSTATE
@ NDICOMMANDPARAMETEROUTOFRANGE
@ NDIFAILURETOWRITESROM
@ NDIINVALIDPORTHANDLE
@ NDISYSTEMNOTINITIALIZED
@ NDIINCOMPATIBLEFIRMWAREVERSIONS
@ NDICOMMANDTOOLONG
@ NDICANTSTARTDIAGNOSTICMODE
@ NDICRCDOESNOTMATCH
@ NDIINVALIDCOMMAND
@ NDINOMEMORYAVAILABLE
@ NDIINITIALIZATIONFAILED
@ NDIUNABLETOSTARTTRACKING
@ NDIUNABLETOSETNEWCOMMPARAMETERS
@ NDIPORTNOTINITIALIZED
@ NDIUNABLETOSTOPTRACKING
@ NDIPORTHASBECOMEUNOCCUPIED
@ UNKNOWNHANDLERETURNED
@ NDICOMMANDINVALIDINCURRENTMODE
@ NDIPORTHANDLENOTALLOCATED
@ NDIUNKNOWNERROR
@ NDIENABLEDTOOLSNOTSUPPORTED
@ NDIUNEXPECTEDREPLY
@ TRACKINGDEVICENOTSET
@ NDIINVALIDTRACKINGPRIORITY
@ NDINOTOOLFORPORT
PHSRQueryType
Query mode for NDI tracking devices.