00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "mitkNDITrackingDevice.h"
00019 #include "mitkTimeStamp.h"
00020 #include <stdio.h>
00021
00022 #include <itksys/SystemTools.hxx>
00023 #include <itkMutexLockHolder.h>
00024
00025 typedef itk::MutexLockHolder<itk::FastMutexLock> MutexLockHolder;
00026
00027
00028 const unsigned char CR = 0xD;
00029 const unsigned char LF = 0xA;
00030
00031
00032 mitk::NDITrackingDevice::NDITrackingDevice() :
00033 TrackingDevice(),m_DeviceName(""), m_PortNumber(mitk::SerialCommunication::COM5), m_BaudRate(mitk::SerialCommunication::BaudRate9600),
00034 m_DataBits(mitk::SerialCommunication::DataBits8), m_Parity(mitk::SerialCommunication::None), m_StopBits(mitk::SerialCommunication::StopBits1),
00035 m_HardwareHandshake(mitk::SerialCommunication::HardwareHandshakeOff), m_NDITrackingVolume(Standard),
00036 m_IlluminationActivationRate(Hz20), m_DataTransferMode(TX), m_6DTools(), m_ToolsMutex(NULL),
00037 m_SerialCommunication(NULL), m_SerialCommunicationMutex(NULL), m_DeviceProtocol(NULL),
00038 m_MultiThreader(NULL), m_ThreadID(0), m_OperationMode(ToolTracking6D), m_MarkerPointsMutex(NULL), m_MarkerPoints()
00039 {
00040 this->m_Type = TrackingSystemNotSpecified;
00041 m_6DTools.clear();
00042 m_SerialCommunicationMutex = itk::FastMutexLock::New();
00043 m_DeviceProtocol = NDIProtocol::New();
00044 m_DeviceProtocol->SetTrackingDevice(this);
00045 m_DeviceProtocol->UseCRCOn();
00046 m_MultiThreader = itk::MultiThreader::New();
00047 m_ToolsMutex = itk::FastMutexLock::New();
00048 m_MarkerPointsMutex = itk::FastMutexLock::New();
00049 m_MarkerPoints.reserve(50);
00050 }
00051
00052
00053 bool mitk::NDITrackingDevice::UpdateTool(mitk::TrackingTool* tool)
00054 {
00055 if (this->GetState() != Setup)
00056 {
00057 mitk::NDIPassiveTool* ndiTool = dynamic_cast<mitk::NDIPassiveTool*>(tool);
00058 if (ndiTool == NULL)
00059 return false;
00060
00061 std::string portHandle = ndiTool->GetPortHandle();
00062
00063
00064 if (ndiTool->GetSROMData() == NULL)
00065 return false;
00066
00067 NDIErrorCode returnvalue;
00068 returnvalue = m_DeviceProtocol->PVWR(&portHandle, ndiTool->GetSROMData(), ndiTool->GetSROMDataLength());
00069 if (returnvalue != NDIOKAY)
00070 return false;
00071 returnvalue = m_DeviceProtocol->PINIT(&portHandle);
00072 if (returnvalue != NDIOKAY)
00073 return false;
00074 returnvalue = m_DeviceProtocol->PENA(&portHandle, ndiTool->GetTrackingPriority());
00075 if (returnvalue != NDIOKAY)
00076 return false;
00077
00078 return true;
00079 }
00080 else
00081 {
00082 return false;
00083 }
00084 }
00085
00086
00087 mitk::NDITrackingDevice::~NDITrackingDevice()
00088 {
00089
00090 if (GetState() == Tracking)
00091 {
00092 this->StopTracking();
00093 }
00094 if (GetState() == Ready)
00095 {
00096 this->CloseConnection();
00097 }
00098
00099 if ((m_ThreadID != 0) && (m_MultiThreader.IsNotNull()))
00100 {
00101 m_MultiThreader->TerminateThread(m_ThreadID);
00102 }
00103 m_MultiThreader = NULL;
00104
00105 if (m_SerialCommunication.IsNotNull())
00106 {
00107 m_SerialCommunication->ClearReceiveBuffer();
00108 m_SerialCommunication->ClearSendBuffer();
00109 m_SerialCommunication->CloseConnection();
00110 m_SerialCommunication = NULL;
00111 }
00112 }
00113
00114
00115 void mitk::NDITrackingDevice::SetPortNumber(const PortNumber _arg)
00116 {
00117 if (this->GetState() != Setup)
00118 return;
00119 itkDebugMacro("setting PortNumber to " << _arg);
00120 if (this->m_PortNumber != _arg)
00121 {
00122 this->m_PortNumber = _arg;
00123 this->Modified();
00124 }
00125 }
00126
00127
00128 void mitk::NDITrackingDevice::SetDeviceName(std::string _arg)
00129 {
00130 if (this->GetState() != Setup)
00131 return;
00132 itkDebugMacro("setting eviceName to " << _arg);
00133 if (this->m_DeviceName != _arg)
00134 {
00135 this->m_DeviceName = _arg;
00136 this->Modified();
00137 }
00138 }
00139
00140
00141 void mitk::NDITrackingDevice::SetBaudRate(const BaudRate _arg)
00142 {
00143 if (this->GetState() != Setup)
00144 return;
00145 itkDebugMacro("setting BaudRate to " << _arg);
00146 if (this->m_BaudRate != _arg)
00147 {
00148 this->m_BaudRate = _arg;
00149 this->Modified();
00150 }
00151 }
00152
00153
00154 void mitk::NDITrackingDevice::SetDataBits(const DataBits _arg)
00155 {
00156 if (this->GetState() != Setup)
00157 return;
00158 itkDebugMacro("setting DataBits to " << _arg);
00159 if (this->m_DataBits != _arg)
00160 {
00161 this->m_DataBits = _arg;
00162 this->Modified();
00163 }
00164 }
00165
00166
00167 void mitk::NDITrackingDevice::SetParity(const Parity _arg)
00168 {
00169 if (this->GetState() != Setup)
00170 return;
00171 itkDebugMacro("setting Parity to " << _arg);
00172 if (this->m_Parity != _arg)
00173 {
00174 this->m_Parity = _arg;
00175 this->Modified();
00176 }
00177 }
00178
00179
00180 void mitk::NDITrackingDevice::SetStopBits(const StopBits _arg)
00181 {
00182 if (this->GetState() != Setup)
00183 return;
00184 itkDebugMacro("setting StopBits to " << _arg);
00185 if (this->m_StopBits != _arg)
00186 {
00187 this->m_StopBits = _arg;
00188 this->Modified();
00189 }
00190 }
00191
00192
00193 void mitk::NDITrackingDevice::SetHardwareHandshake(const HardwareHandshake _arg)
00194 {
00195 if (this->GetState() != Setup)
00196 return;
00197 itkDebugMacro("setting HardwareHandshake to " << _arg);
00198 if (this->m_HardwareHandshake != _arg)
00199 {
00200 this->m_HardwareHandshake = _arg;
00201 this->Modified();
00202 }
00203 }
00204
00205
00206 void mitk::NDITrackingDevice::SetIlluminationActivationRate(const IlluminationActivationRate _arg)
00207 {
00208 if (this->GetState() == Tracking)
00209 return;
00210 itkDebugMacro("setting IlluminationActivationRate to " << _arg);
00211 if (this->m_IlluminationActivationRate != _arg)
00212 {
00213 this->m_IlluminationActivationRate = _arg;
00214 this->Modified();
00215 if (this->GetState() == Ready)
00216 m_DeviceProtocol->IRATE(this->m_IlluminationActivationRate);
00217 }
00218 }
00219
00220
00221 void mitk::NDITrackingDevice::SetDataTransferMode(const DataTransferMode _arg)
00222 {
00223 itkDebugMacro("setting DataTransferMode to " << _arg);
00224 if (this->m_DataTransferMode != _arg)
00225 {
00226 this->m_DataTransferMode = _arg;
00227 this->Modified();
00228 }
00229 }
00230
00231
00232 mitk::NDIErrorCode mitk::NDITrackingDevice::Send(const std::string* input, bool addCRC)
00233 {
00234 if (input == NULL)
00235 return SERIALSENDERROR;
00236
00237 std::string message;
00238
00239 if (addCRC == true)
00240 message = *input + CalcCRC(input) + std::string(1, CR);
00241 else
00242 message = *input + std::string(1, CR);
00243
00244
00245
00246
00247 this->ClearSendBuffer();
00248
00249 MutexLockHolder lock(*m_SerialCommunicationMutex);
00250 long returnvalue = m_SerialCommunication->Send(message);
00251
00252 if (returnvalue == 0)
00253 return SERIALSENDERROR;
00254 else
00255 return NDIOKAY;
00256 }
00257
00258
00259 mitk::NDIErrorCode mitk::NDITrackingDevice::Receive(std::string* answer, unsigned int numberOfBytes)
00260 {
00261 if (answer == NULL)
00262 return SERIALRECEIVEERROR;
00263
00264 MutexLockHolder lock(*m_SerialCommunicationMutex);
00265 long returnvalue = m_SerialCommunication->Receive(*answer, numberOfBytes);
00266
00267 if (returnvalue == 0)
00268 return SERIALRECEIVEERROR;
00269 else
00270 return NDIOKAY;
00271 }
00272
00273
00274 mitk::NDIErrorCode mitk::NDITrackingDevice::ReceiveByte(char* answer)
00275 {
00276 if (answer == NULL)
00277 return SERIALRECEIVEERROR;
00278
00279 std::string m;
00280
00281 MutexLockHolder lock(*m_SerialCommunicationMutex);
00282
00283 long returnvalue = m_SerialCommunication->Receive(m, 1);
00284
00285 if ((returnvalue == 0) ||(m.size() != 1))
00286 return SERIALRECEIVEERROR;
00287
00288 *answer = m.at(0);
00289 return NDIOKAY;
00290 }
00291
00292
00293 mitk::NDIErrorCode mitk::NDITrackingDevice::ReceiveLine(std::string* answer)
00294 {
00295 if (answer == NULL)
00296 return SERIALRECEIVEERROR;
00297
00298 std::string m;
00299
00300 MutexLockHolder lock(*m_SerialCommunicationMutex);
00301
00302 do
00303 {
00304 long returnvalue = m_SerialCommunication->Receive(m, 1);
00305 if ((returnvalue == 0) ||(m.size() != 1))
00306 return SERIALRECEIVEERROR;
00307 *answer += m;
00308 } while (m.at(0) != LF);
00309 return NDIOKAY;
00310 }
00311
00312
00313 void mitk::NDITrackingDevice::ClearSendBuffer()
00314 {
00315 MutexLockHolder lock(*m_SerialCommunicationMutex);
00316 m_SerialCommunication->ClearSendBuffer();
00317 }
00318
00319
00320 void mitk::NDITrackingDevice::ClearReceiveBuffer()
00321 {
00322 MutexLockHolder lock(*m_SerialCommunicationMutex);
00323 m_SerialCommunication->ClearReceiveBuffer();
00324 }
00325
00326
00327 const std::string mitk::NDITrackingDevice::CalcCRC(const std::string* input)
00328 {
00329
00330 if (input == NULL)
00331 return "";
00332
00333 static int oddparity[16] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0};
00334 unsigned int data;
00335 unsigned int crcValue = 0;
00336 unsigned int* puCRC16 = &crcValue;
00337 for (unsigned int i = 0; i < input->length(); i++)
00338 {
00339 data = (*input)[i];
00340 data = (data ^ (*(puCRC16) & 0xff)) & 0xff;
00341 *puCRC16 >>= 8;
00342 if (oddparity[data & 0x0f] ^ oddparity[data >> 4])
00343 {
00344 *(puCRC16) ^= 0xc001;
00345 }
00346 data <<= 6;
00347 *puCRC16 ^= data;
00348 data <<= 1;
00349 *puCRC16 ^= data;
00350 }
00351
00352 char returnvalue[13];
00353 sprintf(returnvalue,"%04X", crcValue);
00354 return std::string(returnvalue);
00355 }
00356
00357
00358 bool mitk::NDITrackingDevice::OpenConnection()
00359 {
00360
00361
00362 if (this->GetState() != Setup)
00363 {
00364 this->SetErrorMessage("Can only try to open the connection if in setup mode");
00365 return false;
00366 }
00367
00368
00369
00370 m_SerialCommunication = mitk::SerialCommunication::New();
00371
00372
00373
00374
00375 if (m_DeviceName.empty())
00376 m_SerialCommunication->SetPortNumber(m_PortNumber);
00377 else
00378 m_SerialCommunication->SetDeviceName(m_DeviceName);
00379 m_SerialCommunication->SetBaudRate(mitk::SerialCommunication::BaudRate9600);
00380 m_SerialCommunication->SetDataBits(mitk::SerialCommunication::DataBits8);
00381 m_SerialCommunication->SetParity(mitk::SerialCommunication::None);
00382 m_SerialCommunication->SetStopBits(mitk::SerialCommunication::StopBits1);
00383 m_SerialCommunication->SetSendTimeout(5000);
00384 m_SerialCommunication->SetReceiveTimeout(5000);
00385 if (m_SerialCommunication->OpenConnection() == 0)
00386 {
00387 this->SetErrorMessage("Can not open serial port");
00388 m_SerialCommunication->CloseConnection();
00389 m_SerialCommunication = NULL;
00390 return false;
00391 }
00392
00393
00394 m_SerialCommunication->SendBreak(400);
00395
00396
00397 static const std::string reset("RESETBE6F\r");
00398 std::string answer = "";
00399 this->Receive(&answer, reset.length());
00400 this->ClearReceiveBuffer();
00401 if (reset.compare(answer) != 0)
00402 {
00403 this->SetErrorMessage("Hardware Reset of tracking device did not work");
00404 if (m_SerialCommunication.IsNotNull())
00405 {
00406 m_SerialCommunication->CloseConnection();
00407 m_SerialCommunication = NULL;
00408 }
00409 return false;
00410 }
00411
00412
00413 NDIErrorCode returnvalue;
00414
00415
00416 returnvalue = m_DeviceProtocol->COMM(m_BaudRate, m_DataBits, m_Parity, m_StopBits, m_HardwareHandshake);
00417
00418 if (returnvalue != NDIOKAY)
00419 {
00420 this->SetErrorMessage("Could not set comm settings in trackingdevice");
00421 return false;
00422 }
00423
00424
00425 itksys::SystemTools::Delay(500);
00426
00427
00428 m_SerialCommunication->CloseConnection();
00429 m_SerialCommunication->SetBaudRate(m_BaudRate);
00430 m_SerialCommunication->SetDataBits(m_DataBits);
00431 m_SerialCommunication->SetParity(m_Parity);
00432 m_SerialCommunication->SetStopBits(m_StopBits);
00433 m_SerialCommunication->SetHardwareHandshake(m_HardwareHandshake);
00434 m_SerialCommunication->SetSendTimeout(5000);
00435 m_SerialCommunication->SetReceiveTimeout(5000);
00436 m_SerialCommunication->OpenConnection();
00437
00438 returnvalue = m_DeviceProtocol->INIT();
00439 if (returnvalue != NDIOKAY)
00440 {
00441 this->SetErrorMessage("Could not initialize the tracking device");
00442 return false;
00443 }
00444
00445 if (this->GetType() == mitk::TrackingSystemNotSpecified)
00446 {
00447 mitk::TrackingDeviceType deviceType;
00448 returnvalue = m_DeviceProtocol->VER(deviceType);
00449 if ((returnvalue != NDIOKAY) || (deviceType == mitk::TrackingSystemNotSpecified))
00450 {
00451 this->SetErrorMessage("Could not determine tracking device type. Please set manually and try again.");
00452 return false;
00453 }
00454 this->SetType(deviceType);
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00499
00500 returnvalue = FreePortHandles();
00501
00502
00506 {
00507
00508 MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex);
00509 std::string portHandle;
00510 Tool6DContainerType::iterator endIt = m_6DTools.end();
00511 for(Tool6DContainerType::iterator it = m_6DTools.begin(); it != endIt; ++it)
00512 {
00513
00514 returnvalue = m_DeviceProtocol->PHRQ(&portHandle);
00515 if (returnvalue == NDIOKAY)
00516 {
00517 (*it)->SetPortHandle(portHandle.c_str());
00518
00519 if (this->m_Type == NDIPolaris)
00520 {
00521 returnvalue = m_DeviceProtocol->PVWR(&portHandle, (*it)->GetSROMData(), (*it)->GetSROMDataLength());
00522 if (returnvalue != NDIOKAY)
00523 {
00524 this->SetErrorMessage((std::string("Could not write SROM file for tool '") + (*it)->GetToolName() + std::string("' to tracking device")).c_str());
00525 return false;
00526 }
00527 returnvalue = m_DeviceProtocol->PINIT(&portHandle);
00528 if (returnvalue != NDIOKAY)
00529 {
00530 this->SetErrorMessage((std::string("Could not initialize tool '") + (*it)->GetToolName()).c_str());
00531 return false;
00532 }
00533 if ((*it)->IsEnabled() == true)
00534 {
00535 returnvalue = m_DeviceProtocol->PENA(&portHandle, (*it)->GetTrackingPriority());
00536 if (returnvalue != NDIOKAY)
00537 {
00538 this->SetErrorMessage((std::string("Could not enable port '") + portHandle +
00539 std::string("' for tool '")+ (*it)->GetToolName() + std::string("'")).c_str());
00540 return false;
00541 }
00542 }
00543 }
00544 }
00545 }
00546 }
00547
00548
00549 if (this->DiscoverWiredTools() == false)
00550 return false;
00551
00552
00553
00554 if (this->m_Type == NDIPolaris)
00555 {
00556 returnvalue = m_DeviceProtocol->IRATE(this->m_IlluminationActivationRate);
00557 if (returnvalue != NDIOKAY)
00558 {
00559 this->SetErrorMessage("Could not set the illuminator activation rate");
00560 return false;
00561 }
00562 }
00563
00564 this->SetState(Ready);
00565 this->SetErrorMessage("");
00566 return true;
00567 }
00568
00569 bool mitk::NDITrackingDevice::InitializeWiredTools()
00570 {
00571 NDIErrorCode returnvalue;
00572 std::string portHandle;
00573 returnvalue = m_DeviceProtocol->PHSR(OCCUPIED, &portHandle);
00574
00575 if (returnvalue != NDIOKAY)
00576 {
00577 this->SetErrorMessage("Could not obtain a list of port handles that are connected");
00578 return false;
00579 }
00580
00581
00582 std::string ph;
00583
00584 for (unsigned int i = 0; i < portHandle.size(); i += 2)
00585 {
00586 ph = portHandle.substr(i, 2);
00587 mitk::NDIPassiveTool* pt = this->GetInternalTool(ph);
00588 if ( pt == NULL)
00589 continue;
00590
00591 if (pt->GetSROMData() == NULL)
00592 continue;
00593
00594 returnvalue = m_DeviceProtocol->PVWR(&ph, pt->GetSROMData(), pt->GetSROMDataLength());
00595 if (returnvalue != NDIOKAY)
00596 {
00597 this->SetErrorMessage((std::string("Could not write SROM file for tool '") + pt->GetToolName() + std::string("' to tracking device")).c_str());
00598 return false;
00599 }
00600 returnvalue = m_DeviceProtocol->PINIT(&ph);
00601 if (returnvalue != NDIOKAY)
00602 {
00603 this->SetErrorMessage((std::string("Could not initialize tool '") + pt->GetToolName()).c_str());
00604 return false;
00605 }
00606 if (pt->IsEnabled() == true)
00607 {
00608 returnvalue = m_DeviceProtocol->PENA(&ph, pt->GetTrackingPriority());
00609 if (returnvalue != NDIOKAY)
00610 {
00611 this->SetErrorMessage((std::string("Could not enable port '") + portHandle +
00612 std::string("' for tool '")+ pt->GetToolName() + std::string("'")).c_str());
00613 return false;
00614 }
00615 }
00616 }
00617 return true;
00618 }
00619
00620
00621 mitk::TrackingDeviceType mitk::NDITrackingDevice::TestConnection()
00622 {
00623 if (this->GetState() != Setup)
00624 {
00625 return mitk::TrackingSystemNotSpecified;
00626 }
00627
00628 m_SerialCommunication = mitk::SerialCommunication::New();
00629
00630
00631
00632
00633
00634
00635 if (m_DeviceName.empty())
00636 m_SerialCommunication->SetPortNumber(m_PortNumber);
00637 else
00638 m_SerialCommunication->SetDeviceName(m_DeviceName);
00639
00640 m_SerialCommunication->SetBaudRate(mitk::SerialCommunication::BaudRate9600);
00641 m_SerialCommunication->SetDataBits(mitk::SerialCommunication::DataBits8);
00642 m_SerialCommunication->SetParity(mitk::SerialCommunication::None);
00643 m_SerialCommunication->SetStopBits(mitk::SerialCommunication::StopBits1);
00644 m_SerialCommunication->SetSendTimeout(5000);
00645 m_SerialCommunication->SetReceiveTimeout(5000);
00646 if (m_SerialCommunication->OpenConnection() == 0)
00647 {
00648 m_SerialCommunication = NULL;
00649 return mitk::TrackingSystemNotSpecified;
00650 }
00651
00652
00653 m_SerialCommunication->SendBreak(400);
00654
00655
00656 static const std::string reset("RESETBE6F\r");
00657 std::string answer = "";
00658 this->Receive(&answer, reset.length());
00659 this->ClearReceiveBuffer();
00660 if (reset.compare(answer) != 0)
00661 {
00662 this->SetErrorMessage("Hardware Reset of tracking device did not work");
00663 m_SerialCommunication->CloseConnection();
00664 m_SerialCommunication = NULL;
00665 return mitk::TrackingSystemNotSpecified;
00666 }
00667
00668
00669 NDIErrorCode returnvalue;
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680 mitk::TrackingDeviceType deviceType;
00681 returnvalue = m_DeviceProtocol->VER(deviceType);
00682 if ((returnvalue != NDIOKAY) || (deviceType == mitk::TrackingSystemNotSpecified))
00683 {
00684 m_SerialCommunication = NULL;
00685 return mitk::TrackingSystemNotSpecified;
00686 }
00687 m_SerialCommunication = NULL;
00688 return deviceType;
00689 }
00690
00691
00692 bool mitk::NDITrackingDevice::CloseConnection()
00693 {
00694 if (this->GetState() != Setup)
00695 {
00696
00697 m_DeviceProtocol->INIT();
00698
00699 m_SerialCommunication->CloseConnection();
00700
00701 this->InvalidateAll();
00702
00703 this->SetState(Setup);
00704 this->SetErrorMessage("");
00705 m_SerialCommunication = NULL;
00706 }
00707 return true;
00708 }
00709
00710
00711 ITK_THREAD_RETURN_TYPE mitk::NDITrackingDevice::ThreadStartTracking(void* pInfoStruct)
00712 {
00713
00714 struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
00715 if (pInfo == NULL)
00716 {
00717 return ITK_THREAD_RETURN_VALUE;
00718 }
00719 if (pInfo->UserData == NULL)
00720 {
00721 return ITK_THREAD_RETURN_VALUE;
00722 }
00723 NDITrackingDevice *trackingDevice = (NDITrackingDevice*)pInfo->UserData;
00724 if (trackingDevice != NULL)
00725 {
00726 if (trackingDevice->GetOperationMode() == ToolTracking6D)
00727 trackingDevice->TrackTools();
00728 else if (trackingDevice->GetOperationMode() == MarkerTracking3D)
00729 trackingDevice->TrackMarkerPositions();
00730 else if (trackingDevice->GetOperationMode() == ToolTracking5D)
00731 trackingDevice->TrackMarkerPositions();
00732 else if (trackingDevice->GetOperationMode() == HybridTracking)
00733 {
00734 trackingDevice->TrackToolsAndMarkers();
00735 }
00736 }
00737 trackingDevice->m_ThreadID = 0;
00738 return ITK_THREAD_RETURN_VALUE;
00739 }
00740
00741
00742 bool mitk::NDITrackingDevice::StartTracking()
00743 {
00744 if (this->GetState() != Ready)
00745 return false;
00746
00747 this->SetState(Tracking);
00748 this->m_StopTrackingMutex->Lock();
00749 this->m_StopTracking = false;
00750 this->m_StopTrackingMutex->Unlock();
00751
00752 m_TrackingFinishedMutex->Unlock();
00753
00754 m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this);
00755 mitk::TimeStamp::GetInstance()->Start(this);
00756 return true;
00757 }
00758
00759
00760 void mitk::NDITrackingDevice::TrackTools()
00761 {
00762 if (this->GetState() != Tracking)
00763 return;
00764
00765 NDIErrorCode returnvalue;
00766 returnvalue = m_DeviceProtocol->TSTART();
00767 if (returnvalue != NDIOKAY)
00768 return;
00769
00770
00771 MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex);
00772
00773 bool localStopTracking;
00774 this->m_StopTrackingMutex->Lock();
00775 localStopTracking = this->m_StopTracking;
00776 this->m_StopTrackingMutex->Unlock();
00777 while ((this->GetState() == Tracking) && (localStopTracking == false))
00778 {
00779 if (this->m_DataTransferMode == TX)
00780 {
00781 returnvalue = this->m_DeviceProtocol->TX();
00782 if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH)))
00783 break;
00784 }
00785 else
00786 {
00787 returnvalue = this->m_DeviceProtocol->BX();
00788 if (returnvalue != NDIOKAY)
00789 break;
00790 }
00791
00792 this->m_StopTrackingMutex->Lock();
00793 localStopTracking = m_StopTracking;
00794 this->m_StopTrackingMutex->Unlock();
00795 }
00796
00797
00798 returnvalue = m_DeviceProtocol->TSTOP();
00799 if (returnvalue != NDIOKAY)
00800 {
00801
00802 ;
00803 }
00804 return;
00805 }
00806
00807
00808 void mitk::NDITrackingDevice::TrackMarkerPositions()
00809 {
00810 if (m_OperationMode == ToolTracking6D)
00811 return;
00812
00813 if (this->GetState() != Tracking)
00814 return;
00815
00816 NDIErrorCode returnvalue;
00817
00818 returnvalue = m_DeviceProtocol->DSTART();
00819 if (returnvalue != NDIOKAY)
00820 return;
00821
00822 MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex);
00823
00824 bool localStopTracking;
00825 this->m_StopTrackingMutex->Lock();
00826 localStopTracking = this->m_StopTracking;
00827 this->m_StopTrackingMutex->Unlock();
00828 while ((this->GetState() == Tracking) && (localStopTracking == false))
00829 {
00830 m_MarkerPointsMutex->Lock();
00831 returnvalue = this->m_DeviceProtocol->POS3D(&m_MarkerPoints);
00832 m_MarkerPointsMutex->Unlock();
00833 if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH)))
00834 {
00835 std::cout << "Error in POS3D: could not read data. Possibly no markers present." << std::endl;
00836 }
00837
00838 this->m_StopTrackingMutex->Lock();
00839 localStopTracking = m_StopTracking;
00840 this->m_StopTrackingMutex->Unlock();
00841 }
00842
00843 returnvalue = m_DeviceProtocol->DSTOP();
00844 if (returnvalue != NDIOKAY)
00845 return;
00846
00847 this->SetState(Ready);
00848 return;
00849 }
00850
00851
00852 void mitk::NDITrackingDevice::TrackToolsAndMarkers()
00853 {
00854 if (m_OperationMode != HybridTracking)
00855 return;
00856
00857 NDIErrorCode returnvalue;
00858
00859 returnvalue = m_DeviceProtocol->TSTART();
00860 if (returnvalue != NDIOKAY)
00861 return;
00862
00863 MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex);
00864
00865 bool localStopTracking;
00866 this->m_StopTrackingMutex->Lock();
00867 localStopTracking = this->m_StopTracking;
00868 this->m_StopTrackingMutex->Unlock();
00869 while ((this->GetState() == Tracking) && (localStopTracking == false))
00870 {
00871 m_MarkerPointsMutex->Lock();
00872 returnvalue = this->m_DeviceProtocol->TX(true, &m_MarkerPoints);
00873 m_MarkerPointsMutex->Unlock();
00874 if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH)))
00875 {
00876 std::cout << "Error in TX: could not read data. Possibly no markers present." << std::endl;
00877 }
00878
00879 this->m_StopTrackingMutex->Lock();
00880 localStopTracking = m_StopTracking;
00881 this->m_StopTrackingMutex->Unlock();
00882 }
00883
00884
00885 returnvalue = m_DeviceProtocol->TSTOP();
00886 if (returnvalue != NDIOKAY)
00887 return;
00888
00889 this->SetState(Ready);
00890 return;
00891 }
00892
00893
00894 mitk::TrackingTool* mitk::NDITrackingDevice::GetTool(unsigned int toolNumber) const
00895 {
00896 MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex);
00897 if (toolNumber < m_6DTools.size())
00898 return m_6DTools.at(toolNumber);
00899 return NULL;
00900 }
00901
00902
00903 mitk::TrackingTool* mitk::NDITrackingDevice::GetToolByName(std::string name) const
00904 {
00905 MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex);
00906 Tool6DContainerType::const_iterator end = m_6DTools.end();
00907 for (Tool6DContainerType::const_iterator iterator = m_6DTools.begin(); iterator != end; ++iterator)
00908 if (name.compare((*iterator)->GetToolName()) == 0)
00909 return *iterator;
00910 return NULL;
00911 }
00912
00913
00914 mitk::NDIPassiveTool* mitk::NDITrackingDevice::GetInternalTool(std::string portHandle)
00915 {
00916 MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex);
00917 Tool6DContainerType::iterator end = m_6DTools.end();
00918 for (Tool6DContainerType::iterator iterator = m_6DTools.begin(); iterator != end; ++iterator)
00919 if (portHandle.compare((*iterator)->GetPortHandle()) == 0)
00920 return *iterator;
00921 return NULL;
00922 }
00923
00924
00925 unsigned int mitk::NDITrackingDevice::GetToolCount() const
00926 {
00927 MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex);
00928 return m_6DTools.size();
00929 }
00930
00931
00932 bool mitk::NDITrackingDevice::Beep(unsigned char count)
00933 {
00934 if (this->GetState() != Setup)
00935 {
00936 return (m_DeviceProtocol->BEEP(count) == NDIOKAY);
00937 }
00938 else
00939 {
00940 return false;
00941 }
00942 }
00943
00944 mitk::TrackingTool* mitk::NDITrackingDevice::AddTool( const char* toolName, const char* fileName, TrackingPriority p )
00945 {
00946 mitk::NDIPassiveTool::Pointer t = mitk::NDIPassiveTool::New();
00947 if (t->LoadSROMFile(fileName) == false)
00948 return NULL;
00949 t->SetToolName(toolName);
00950 t->SetTrackingPriority(p);
00951 if (this->InternalAddTool(t) == false)
00952 return NULL;
00953 return t.GetPointer();
00954 }
00955
00956
00957 bool mitk::NDITrackingDevice::InternalAddTool(mitk::NDIPassiveTool* tool)
00958 {
00959 if (tool == NULL)
00960 return false;
00961 NDIPassiveTool::Pointer p = tool;
00962
00963 if (this->GetState() == Ready)
00964 {
00965
00966 std::string newPortHandle;
00967 NDIErrorCode returnvalue;
00968 returnvalue = m_DeviceProtocol->PHRQ(&newPortHandle);
00969 if (returnvalue == NDIOKAY)
00970 {
00971 p->SetPortHandle(newPortHandle.c_str());
00972
00973 returnvalue = m_DeviceProtocol->PVWR(&newPortHandle, p->GetSROMData(), p->GetSROMDataLength());
00974 if (returnvalue != NDIOKAY)
00975 {
00976 this->SetErrorMessage((std::string("Could not write SROM file for tool '") + p->GetToolName() + std::string("' to tracking device")).c_str());
00977 return false;
00978 }
00979
00980 returnvalue = m_DeviceProtocol->PINIT(&newPortHandle);
00981 if (returnvalue != NDIOKAY)
00982 {
00983 this->SetErrorMessage((std::string("Could not initialize port '") + newPortHandle +
00984 std::string("' for tool '")+ p->GetToolName() + std::string("'")).c_str());
00985 return false;
00986 }
00987
00988 if (p->IsEnabled() == true)
00989 {
00990 returnvalue = m_DeviceProtocol->PENA(&newPortHandle, p->GetTrackingPriority());
00991 if (returnvalue != NDIOKAY)
00992 {
00993 this->SetErrorMessage((std::string("Could not enable port '") + newPortHandle +
00994 std::string("' for tool '")+ p->GetToolName() + std::string("'")).c_str());
00995 return false;
00996 }
00997 }
00998 }
00999
01000 m_ToolsMutex->Lock();
01001 this->m_6DTools.push_back(p);
01002 m_ToolsMutex->Unlock();
01003 this->Modified();
01004 return true;
01005 }
01006 else if (this->GetState() == Setup)
01007 {
01008
01009 m_ToolsMutex->Lock();
01010 this->m_6DTools.push_back(p);
01011 m_ToolsMutex->Unlock();
01012 this->Modified();
01013 return true;
01014 }
01015 else
01016 return false;
01017 }
01018
01019
01020 bool mitk::NDITrackingDevice::RemoveTool(mitk::TrackingTool* tool)
01021 {
01022 mitk::NDIPassiveTool* ndiTool = dynamic_cast<mitk::NDIPassiveTool*>(tool);
01023 if (ndiTool == NULL)
01024 return false;
01025
01026 std::string portHandle = ndiTool->GetPortHandle();
01027
01028
01029
01030 if ((portHandle.length() == 2) && (this->GetState() == Ready))
01031 {
01032 NDIErrorCode returnvalue;
01033 returnvalue = m_DeviceProtocol->PHF(&portHandle);
01034 if (returnvalue != NDIOKAY)
01035 return false;
01036
01037 MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex);
01038 Tool6DContainerType::iterator end = m_6DTools.end();
01039 for (Tool6DContainerType::iterator iterator = m_6DTools.begin(); iterator != end; ++iterator)
01040 {
01041 if (iterator->GetPointer() == ndiTool)
01042 {
01043 m_6DTools.erase(iterator);
01044 this->Modified();
01045 return true;
01046 }
01047 }
01048 return false;
01049 }
01050 else if (this->GetState() == Setup)
01051 {
01052 MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex);
01053 Tool6DContainerType::iterator end = m_6DTools.end();
01054 for (Tool6DContainerType::iterator iterator = m_6DTools.begin(); iterator != end; ++iterator)
01055 {
01056 if ((*iterator).GetPointer() == ndiTool)
01057 {
01058 m_6DTools.erase(iterator);
01059 this->Modified();
01060 return true;
01061 }
01062 }
01063 return false;
01064 }
01065 return false;
01066 }
01067
01068
01069 void mitk::NDITrackingDevice::InvalidateAll()
01070 {
01071 MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex);
01072 Tool6DContainerType::iterator end = m_6DTools.end();
01073 for (Tool6DContainerType::iterator iterator = m_6DTools.begin(); iterator != end; ++iterator)
01074 (*iterator)->SetDataValid(false);
01075 }
01076
01077
01078 bool mitk::NDITrackingDevice::SetOperationMode(OperationMode mode)
01079 {
01080 if (GetState() == Tracking)
01081 return false;
01082
01083 m_OperationMode = mode;
01084 return true;
01085 }
01086
01087
01088 mitk::OperationMode mitk::NDITrackingDevice::GetOperationMode()
01089 {
01090 return m_OperationMode;
01091 }
01092
01093
01094 bool mitk::NDITrackingDevice::GetMarkerPositions(MarkerPointContainerType* markerpositions)
01095 {
01096 m_MarkerPointsMutex->Lock();
01097 *markerpositions = m_MarkerPoints;
01098 m_MarkerPointsMutex->Unlock();
01099 return (markerpositions->size() != 0) ;
01100 }
01101
01102
01103 bool mitk::NDITrackingDevice::DiscoverWiredTools()
01104 {
01105
01106 this->FreePortHandles();
01107
01108
01109 NDIErrorCode returnvalue;
01110 std::string portHandle;
01111 returnvalue = m_DeviceProtocol->PHSR(OCCUPIED, &portHandle);
01112
01113 if (returnvalue != NDIOKAY)
01114 {
01115 this->SetErrorMessage("Could not obtain a list of port handles that are connected");
01116 return false;
01117 }
01118
01119
01120 std::string ph;
01121
01123
01124
01125 for (unsigned int i = 0; i < portHandle.size(); i += 2)
01126 {
01127 ph = portHandle.substr(i, 2);
01128 if (this->GetInternalTool(ph) != NULL)
01129 continue;
01130
01131
01132 mitk::NDIPassiveTool::Pointer newTool = mitk::NDIPassiveTool::New();
01133 newTool->SetPortHandle(ph.c_str());
01134 newTool->SetTrackingPriority(mitk::NDIPassiveTool::Dynamic);
01135
01136
01137
01138
01139 newTool->SetToolName((std::string("Port ") + ph).c_str());
01140
01141 returnvalue = m_DeviceProtocol->PINIT(&ph);
01142 if (returnvalue != NDIINITIALIZATIONFAILED)
01143 {
01144 if (returnvalue != NDIOKAY)
01145 {
01146 this->SetErrorMessage((std::string("Could not initialize port '") + ph +
01147 std::string("' for tool '")+ newTool->GetToolName() + std::string("'")).c_str());
01148 return false;
01149 }
01150
01151 returnvalue = m_DeviceProtocol->PENA(&ph, newTool->GetTrackingPriority());
01152 if (returnvalue != NDIOKAY)
01153 {
01154 this->SetErrorMessage((std::string("Could not enable port '") + ph +
01155 std::string("' for tool '")+ newTool->GetToolName() + std::string("'")).c_str());
01156 return false;
01157 }
01158 }
01159
01160 if (this->InternalAddTool(newTool) == false)
01161 this->SetErrorMessage("Error while adding new tool");
01162
01163 }
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175 return true;
01176 }
01177
01178
01179 mitk::NDIErrorCode mitk::NDITrackingDevice::FreePortHandles()
01180 {
01181
01182 NDIErrorCode returnvalue = NDIOKAY;
01183 std::string portHandle;
01184 returnvalue = m_DeviceProtocol->PHSR(FREED, &portHandle);
01185 if (returnvalue != NDIOKAY)
01186 {
01187 this->SetErrorMessage("Could not obtain a list of port handles that need to be freed");
01188 return returnvalue;
01189 }
01190
01191
01192 if (portHandle.empty() == true)
01193 return returnvalue;
01194
01195 std::string ph;
01196 for (unsigned int i = 0; i < portHandle.size(); i += 2)
01197 {
01198 ph = portHandle.substr(i, 2);
01199
01200 mitk::NDIPassiveTool* t = this->GetInternalTool(ph);
01201 if (t != NULL)
01202 {
01203 if (this->RemoveTool(t) == false)
01204 returnvalue = NDIERROR;
01205 }
01206 else
01207 {
01208 returnvalue = m_DeviceProtocol->PHF(&ph);
01209
01210 if (returnvalue != NDIOKAY)
01211 {
01212 this->SetErrorMessage("Could not free all port handles");
01213
01214 }
01215 }
01216 }
01217 return returnvalue;
01218 }
01219
01220
01221 int mitk::NDITrackingDevice::GetMajorFirmwareRevisionNumber()
01222 {
01223 std::string revision;
01224 if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9) )
01225 {
01226 this->SetErrorMessage("Could not receive firmware revision number!");
01227 return 0;
01228 }
01229
01230 const std::string majrevno = revision.substr(2,3);
01231
01232 return std::atoi(majrevno.c_str());
01233 }
01234
01235 const char* mitk::NDITrackingDevice::GetFirmwareRevisionNumber()
01236 {
01237 static std::string revision;
01238 if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9) )
01239 {
01240 this->SetErrorMessage("Could not receive firmware revision number!");
01241 revision = "";
01242 return revision.c_str();
01243 }
01244 return revision.c_str();
01245 }
01246
01247 bool mitk::NDITrackingDevice::GetSupportedVolumes(unsigned int* numberOfVolumes, mitk::NDITrackingDevice::NDITrackingVolumeContainerType* volumes, mitk::NDITrackingDevice::TrackingVolumeDimensionType* volumesDimensions)
01248 {
01249 if (numberOfVolumes == NULL || volumes == NULL || volumesDimensions == NULL)
01250 return false;
01251
01252 static std::string info;
01253 if (m_DeviceProtocol->SFLIST(&info) != mitk::NDIOKAY || info.empty())
01254 {
01255 this->SetErrorMessage("Could not receive tracking volume information of tracking system!");
01256 return false;
01257 }
01258
01259
01260
01261
01262 (*numberOfVolumes) = (unsigned int) std::atoi(info.substr(0,1).c_str());
01263
01264 for (unsigned int i=0; i<(*numberOfVolumes); i++)
01265 {
01266
01267
01268
01269 std::string::size_type offset, end;
01270 offset = (i*73)+1;
01271 end = 73+(i*73);
01272 std::string currentVolume = info.substr(offset, end);
01273
01274 if (i>0)
01275 currentVolume = currentVolume.substr(1, currentVolume.size());
01276
01277 std::string standard = "0";
01278 std::string pyramid = "4";
01279 std::string spectraPyramid = "5";
01280 std::string vicraVolume = "7";
01281 std::string cube = "9";
01282 std::string dome = "A";
01283 if (currentVolume.compare(0,1,standard)==0)
01284 volumes->push_back(mitk::Standard);
01285 if (currentVolume.compare(0,1,pyramid)==0)
01286 volumes->push_back(mitk::Pyramid);
01287 if (currentVolume.compare(0,1,spectraPyramid)==0)
01288 volumes->push_back(mitk::SpectraPyramid);
01289 if (currentVolume.compare(0,1,vicraVolume)==0)
01290 volumes->push_back(mitk::VicraVolume);
01291 else if (currentVolume.compare(0,1,cube)==0)
01292 volumes->push_back(mitk::Cube);
01293 else if (currentVolume.compare(0,1,dome)==0)
01294 volumes->push_back(mitk::Dome);
01295
01296
01297 for (unsigned int index = 0; index < 10; index++)
01298 {
01299 std::string::size_type offD, endD;
01300 offD = 1+(index*7);
01301 endD = offD+7;
01302 int dimension = std::atoi(currentVolume.substr(offD, endD).c_str());
01303 dimension /= 100;
01304 volumesDimensions->push_back(dimension);
01305 }
01306 }
01307
01308 return true;
01309 }
01310
01311 bool mitk::NDITrackingDevice::SetVolume(NDITrackingVolume volume)
01312 {
01313 if (m_DeviceProtocol->VSEL(volume) != mitk::NDIOKAY)
01314 {
01315 this->SetErrorMessage("Could not set volume!");
01316 return false;
01317 }
01318 return true;
01319 }
01320