diff --git a/Modules/IGT/CMakeLists.txt b/Modules/IGT/CMakeLists.txt index 6e5613a720..8246566077 100644 --- a/Modules/IGT/CMakeLists.txt +++ b/Modules/IGT/CMakeLists.txt @@ -1,59 +1,67 @@ include(MITKIGTHardware.cmake) if(MITK_USE_MICRON_TRACKER) - set(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_MICRON_TRACKER_INCLUDE_DIR}) + set(ADDITIONAL_INCLUDE_DIRS ${ADDITIONAL_INCLUDE_DIRS} ${MITK_MICRON_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_MICRON_TRACKER_LIB}) endif(MITK_USE_MICRON_TRACKER) if(MITK_USE_OPTITRACK_TRACKER) - set(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_OPTITRACK_TRACKER_INCLUDE_DIR}) + set(ADDITIONAL_INCLUDE_DIRS ${ADDITIONAL_INCLUDE_DIRS} ${MITK_OPTITRACK_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_OPTITRACK_TRACKER_LIB}) add_definitions( -DMITK_USE_OPTITRACK_TRACKER ) endif(MITK_USE_OPTITRACK_TRACKER) if(MITK_USE_MICROBIRD_TRACKER) - set(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_USE_MICROBIRD_TRACKER_INCLUDE_DIR}) + set(ADDITIONAL_INCLUDE_DIRS ${ADDITIONAL_INCLUDE_DIRS} ${MITK_USE_MICROBIRD_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_USE_MICROBIRD_TRACKER_LIB}) endif(MITK_USE_MICROBIRD_TRACKER) +if(MITK_USE_POLHEMUS_TRACKER) + set(ADDITIONAL_INCLUDE_DIRS ${ADDITIONAL_INCLUDE_DIRS} ${MITK_POLHEMUS_TRACKER_INCLUDE_DIR}) + set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_POLHEMUS_TRACKER_LIB}) +endif(MITK_USE_POLHEMUS_TRACKER) + +message(STATUS "ADDITIONAL_INCLUDE_DIRS" ${ADDITIONAL_INCLUDE_DIRS}) +message(STATUS "ADDITIONAL_LIBS" ${ADDITIONAL_LIBS}) + MITK_CREATE_MODULE( SUBPROJECTS MITK-IGT - INCLUDE_DIRS Algorithms Common DataManagement ExceptionHandling IO Rendering TrackingDevices TestingHelper - INTERNAL_INCLUDE_DIRS ${INCLUDE_DIRS_INTERNAL} + INCLUDE_DIRS Algorithms Common DataManagement ExceptionHandling IO Rendering TrackingDevices TestingHelper + INTERNAL_INCLUDE_DIRS ${ADDITIONAL_INCLUDE_DIRS} DEPENDS MitkImageStatistics MitkSceneSerialization MitkIGTBase MitkOpenIGTLink PACKAGE_DEPENDS ITK|ITKRegistrationCommon tinyxml OpenIGTLink - ADDITIONAL_LIBS "${ADDITIONAL_LIBS}" + ADDITIONAL_LIBS ${ADDITIONAL_LIBS} #WARNINGS_AS_ERRORS disabled for release 2014-03 because of bug 17463 ) if(MitkIGT_IS_ENABLED) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/ClaronMicron.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/IntuitiveDaVinci.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAurora.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAurora_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraCompactFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraPlanarFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraTabletopFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraTabletopFG_Prototype_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisOldModel.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisSpectra.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisSpectraExtendedPyramid.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisVicra.stl ) endif() if(NOT MODULE_IS_ENABLED) message(STATUS "IGTTutorialStep1 won't be built. Missing: ${_RESULT}") else() ## create IGT config configure_file(mitkIGTConfig.h.in ${PROJECT_BINARY_DIR}/mitkIGTConfig.h @ONLY) # add test programm for serial communication classADD_EXECUTABLE(SerialCommunicationTest IGTTrackingDevices/mitkSerialCommunicationTest.cpp)target_link_libraries(SerialCommunicationTest mitkIGT Mitk tinyxml PocoXML) add_subdirectory(autoload/DeviceRegistry) add_subdirectory(Tutorial) add_subdirectory(Testing) endif() diff --git a/Modules/IGT/MITKIGTHardware.cmake b/Modules/IGT/MITKIGTHardware.cmake index a7f4ad4eea..21c9309de8 100644 --- a/Modules/IGT/MITKIGTHardware.cmake +++ b/Modules/IGT/MITKIGTHardware.cmake @@ -1,42 +1,49 @@ #Begin MicronTracker Hardware option(MITK_USE_MICRON_TRACKER "Enable support for micron tracker hardware" OFF) #Begin Optitrack Hardware option(MITK_USE_OPTITRACK_TRACKER "Enable support for Optitrack tracker hardware" OFF) +option(MITK_USE_POLHEMUS_TRACKER "Enable support for Polhemus tracker hardware" OFF) + # only if MicronTracker is enabled if(MITK_USE_MICRON_TRACKER) find_library(MITK_MICRON_TRACKER_LIB MTC DOC "Path which contains the MT2 library.") get_filename_component(MICRON_TRACKER_SDK_DIR ${MITK_MICRON_TRACKER_LIB} PATH) find_path(MITK_MICRON_TRACKER_INCLUDE_DIR MTC.h ${MICRON_TRACKER_SDK_DIR} DOC "Include directory of the MT2.") find_path(MITK_MICRON_TRACKER_TEMP_DIR . DOC "Any temporary directory which can be used by the MicronTracker2.") MITK_INSTALL(FILES ${MICRON_TRACKER_SDK_DIR}/MTC.dll CONFIGURATIONS Release) MITK_INSTALL(FILES ${MICRON_TRACKER_SDK_DIR}/MTInterfaceDotNet.dll CONFIGURATIONS Release) MITK_INSTALL(FILES ${MICRON_TRACKER_SDK_DIR}/PGRFlyCapture.dll CONFIGURATIONS Release) ENDIF(MITK_USE_MICRON_TRACKER) #End MicronTracker Hardware #only if Optitrack is enabled if(MITK_USE_OPTITRACK_TRACKER) find_library(MITK_OPTITRACK_TRACKER_LIB NPTrackingTools DOC "Path which contains the Optitrack library. Please choose 32/64 bit version depending on your build.") find_path(MITK_OPTITRACK_TRACKER_INCLUDE_DIR NPTrackinTools.h DOC "Include directory of the Optitrack library.") find_path(MITK_OPTITRACK_TRACKER_LIB_DIR NPTrackingTools.dll) MITK_INSTALL(FILES ${MITK_OPTITRACK_TRACKER_LIB_DIR}/NPTrackingTools.dll CONFIGURATIONS Release) MITK_INSTALL(FILES ${MITK_OPTITRACK_TRACKER_LIB_DIR}/NPTrackingToolsx64.dll CONFIGURATIONS Release) ENDIF(MITK_USE_OPTITRACK_TRACKER) #End Optitrack Hardware +if(MITK_USE_POLHEMUS_TRACKER) + find_library(MITK_POLHEMUS_TRACKER_LIB PDI DOC "Path which contains the Polhemus library.") + find_path(MITK_POLHEMUS_TRACKER_INCLUDE_DIR PDI.h DOC "Include directory of the Polhemus library.") +ENDIF(MITK_USE_POLHEMUS_TRACKER) + # only on Win32 if(WIN32) #Begin Ascension MicroBird Hardware option(MITK_USE_MICROBIRD_TRACKER "Enable support for Ascension MicroBird tracker hardware" OFF) if(MITK_USE_MICROBIRD_TRACKER) add_definitions(-DMITK_USE_MICROBIRD_TRACKER) find_library(MITK_USE_MICROBIRD_TRACKER_LIB PCIBird3) get_filename_component(MICROBIRD_TRACKER_API_DIR ${MITK_USE_MICROBIRD_TRACKER_LIB} PATH) find_path(MITK_USE_MICROBIRD_TRACKER_INCLUDE_DIR PCIBird3.h ${MICROBIRD_TRACKER_API_DIR}) endif(MITK_USE_MICROBIRD_TRACKER) #End MicroBird Hardware endif(WIN32) diff --git a/Modules/IGT/Testing/CMakeLists.txt b/Modules/IGT/Testing/CMakeLists.txt index b4271e69c1..94d9fef6af 100644 --- a/Modules/IGT/Testing/CMakeLists.txt +++ b/Modules/IGT/Testing/CMakeLists.txt @@ -1,31 +1,35 @@ if(BUILD_TESTING) include(MITKIGTTrackingDeviceHardwareTesting.cmake) endif(BUILD_TESTING) MITK_CREATE_MODULE_TESTS() if(MITK_TRACKING_DEVICES_HARDWARE_TESTS_ENABLED) if(MITK_NDI_AURORA_CONNECTED) mitkAddCustomModuleTest(mitkNDIAuroraHardwareTest mitkNDIAuroraHardwareTest ${MITK_NDI_AURORA_COM_PORT}) endif(MITK_NDI_AURORA_CONNECTED) if(MITK_NDI_POLARIS_CONNECTED) mitkAddCustomModuleTest(mitkNDIPolarisHardwareTest mitkNDIPolarisHardwareTest ${MITK_NDI_POLARIS_COM_PORT}) endif(MITK_NDI_POLARIS_CONNECTED) if(MITK_CLARON_MICRONTRACKER_CONNECTED) mitkAddCustomModuleTest(mitkClaronTrackingDeviceHardwareTest mitkClaronTrackingDeviceHardwareTest ${MITK_DATA_DIR}/IGT-Data/MicronTrackerToolfiles/Tool_11 ${MITK_DATA_DIR}/IGT-Data/MicronTrackerToolfiles/Tool_12 ${MITK_DATA_DIR}/IGT-Data/MicronTrackerToolfiles/Tool_13) endif(MITK_CLARON_MICRONTRACKER_CONNECTED) + if(MITK_POLHEMUS_CONNECTED) + mitkAddCustomModuleTest(mitkPolhemusTrackingDeviceHardwareTest mitkPolhemusTrackingDeviceHardwareTest) + endif(MITK_POLHEMUS_CONNECTED) + endif(MITK_TRACKING_DEVICES_HARDWARE_TESTS_ENABLED) option(MITK_IGT_READER_WRITER_TESTS_ENABLED "Enable additional reader/writer tests of the IGT module." OFF) mark_as_advanced(MITK_IGT_READER_WRITER_TESTS_ENABLED) if(MITK_IGT_READER_WRITER_TESTS_ENABLED) mitkAddCustomModuleTest(mitkNavigationToolReaderAndWriterTest mitkNavigationToolReaderAndWriterTest) mitkAddCustomModuleTest(mitkNavigationToolStorageDeserializerTest mitkNavigationToolStorageDeserializerTest) mitkAddCustomModuleTest(mitkNavigationToolStorageSerializerAndDeserializerIntegrationTest mitkNavigationToolStorageSerializerAndDeserializerIntegrationTest) mitkAddCustomModuleTest(mitkNavigationToolStorageSerializerTest mitkNavigationToolStorageSerializerTest) endif(MITK_IGT_READER_WRITER_TESTS_ENABLED) diff --git a/Modules/IGT/Testing/MITKIGTTrackingDeviceHardwareTesting.cmake b/Modules/IGT/Testing/MITKIGTTrackingDeviceHardwareTesting.cmake index 90986ca608..43565a7593 100644 --- a/Modules/IGT/Testing/MITKIGTTrackingDeviceHardwareTesting.cmake +++ b/Modules/IGT/Testing/MITKIGTTrackingDeviceHardwareTesting.cmake @@ -1,31 +1,32 @@ option(MITK_TRACKING_DEVICES_HARDWARE_TESTS_ENABLED "Enable support for testing tracking device hardware (this hardware must be connected to the system)" OFF) mark_as_advanced(MITK_TRACKING_DEVICES_HARDWARE_TESTS_ENABLED) if(MITK_TRACKING_DEVICES_HARDWARE_TESTS_ENABLED) option(MITK_NDI_AURORA_CONNECTED "Turn on if an Aurora system is connected and should be tested." OFF) option(MITK_NDI_POLARIS_CONNECTED "Turn on if a Polaris system is connected and should be tested." OFF) + option(MITK_POLHEMUS_CONNECTED "Turn on if a Polhemus system is connected and should be tested." OFF) option(MITK_CLARON_MICRONTRACKER_CONNECTED "Turn on if a MicronTracker system is connected and should be tested." OFF) mark_as_advanced(MITK_NDI_AURORA_CONNECTED MITK_NDI_POLARIS_CONNECTED MITK_CLARON_MICRONTRACKER_CONNECTED MITK_CLARON_MICRONTRACKER_CONNECTED) endif(MITK_TRACKING_DEVICES_HARDWARE_TESTS_ENABLED) if(MITK_NDI_AURORA_CONNECTED) if(WIN32) set(MITK_NDI_AURORA_COM_PORT "1" CACHE STRING "Serial port where the system is connected.") else(WIN32) set(MITK_NDI_AURORA_COM_PORT "/dev/ttyS1" CACHE STRING "Device path where the system is connected. (e.g. /dev/ttyS6 or /dev/ttyUSB1)") endif(WIN32) endif(MITK_NDI_AURORA_CONNECTED) if(MITK_NDI_POLARIS_CONNECTED) if(WIN32) set(MITK_NDI_POLARIS_COM_PORT "1" CACHE STRING "Serial port where the system is connected.") else(WIN32) set(MITK_NDI_POLARIS_COM_PORT "/dev/ttyS1" CACHE STRING "Device path where the system is connected. (e.g. /dev/ttyS6 or /dev/ttyUSB1)") endif(WIN32) endif(MITK_NDI_POLARIS_CONNECTED) if(MITK_CLARON_MICRONTRACKER_CONNECTED) if(WIN32) find_path(MITK_MICRON_TRACKER_CALIBRATION_DIR BumbleBee_6400420.calib DOC "Path which contains the MT2 calibration file.") endif(WIN32) endif(MITK_CLARON_MICRONTRACKER_CONNECTED) diff --git a/Modules/IGT/Testing/files.cmake b/Modules/IGT/Testing/files.cmake index 3f3bb46b60..4be7accede 100644 --- a/Modules/IGT/Testing/files.cmake +++ b/Modules/IGT/Testing/files.cmake @@ -1,67 +1,75 @@ set(MODULE_TESTS # IMPORTANT: If you plan to deactivate / comment out a test please write a bug number to the commented out line of code. # # Example: #mitkMyTest #this test is commented out because of bug 12345 # # It is important that the bug is open and that the test will be activated again before the bug is closed. This assures that # no test is forgotten after it was commented out. If there is no bug for your current problem, please add a new one and # mark it as critical. ################## ON THE FENCE TESTS ################################################# # none ################## DISABLED TESTS ##################################################### ################# RUNNING TESTS ####################################################### mitkCameraVisualizationTest.cpp mitkClaronInterfaceTest.cpp mitkClaronToolTest.cpp mitkClaronTrackingDeviceTest.cpp mitkInternalTrackingToolTest.cpp mitkNavigationDataDisplacementFilterTest.cpp mitkNavigationDataLandmarkTransformFilterTest.cpp mitkNavigationDataObjectVisualizationFilterTest.cpp mitkNavigationDataSetTest.cpp mitkNavigationDataTest.cpp mitkNavigationDataRecorderTest.cpp mitkNavigationDataReferenceTransformFilterTest.cpp mitkNavigationDataSequentialPlayerTest.cpp mitkNavigationDataSetReaderWriterXMLTest.cpp mitkNavigationDataSetReaderWriterCSVTest.cpp mitkNavigationDataSourceTest.cpp mitkNavigationDataToMessageFilterTest.cpp mitkNavigationDataToNavigationDataFilterTest.cpp mitkNavigationDataToPointSetFilterTest.cpp mitkNavigationDataToIGTLMessageFilterTest.cpp mitkNavigationDataTransformFilterTest.cpp mitkNDIPassiveToolTest.cpp mitkNDIProtocolTest.cpp mitkNDITrackingDeviceTest.cpp mitkTimeStampTest.cpp mitkTrackingVolumeGeneratorTest.cpp mitkTrackingDeviceTest.cpp mitkTrackingToolTest.cpp mitkVirtualTrackingDeviceTest.cpp # mitkNavigationDataPlayerTest.cpp # random fails see bug 16485. # We decided to won't fix because of complete restructuring via bug 15959. mitkTrackingDeviceSourceTest.cpp mitkTrackingDeviceSourceConfiguratorTest.cpp mitkNavigationDataEvaluationFilterTest.cpp mitkTrackingTypesTest.cpp mitkOpenIGTLinkTrackingDeviceTest.cpp # ------------------ Navigation Tool Management Tests ------------------- mitkNavigationToolStorageDeserializerTest.cpp # Activated experimentally on dart clients, see task T17303 for details. mitkNavigationToolStorageTest.cpp mitkNavigationToolTest.cpp # ----------------------------------------------------------------------- ) set(MODULE_CUSTOM_TESTS mitkNDIAuroraHardwareTest.cpp mitkNDIPolarisHardwareTest.cpp mitkClaronTrackingDeviceHardwareTest.cpp mitkNavigationToolReaderAndWriterTest.cpp #deactivated because of bug 18835 mitkNavigationToolStorageSerializerAndDeserializerIntegrationTest.cpp # This test was disabled because of bug 17181. mitkNavigationToolStorageSerializerTest.cpp # This test was disabled because of bug 18671 + #mitkPolhemusTrackingDeviceHardwareTest.cpp ) + +if(MITK_USE_POLHEMUS_TRACKER) +set(MODULE_CUSTOM_TESTS + ${MODULE_CUSTOM_TESTS} + mitkPolhemusTrackingDeviceHardwareTest.cpp +) +endif(MITK_USE_POLHEMUS_TRACKER) diff --git a/Modules/IGT/Testing/mitkPolhemusTrackingDeviceHardwareTest.cpp b/Modules/IGT/Testing/mitkPolhemusTrackingDeviceHardwareTest.cpp new file mode 100644 index 0000000000..5538870444 --- /dev/null +++ b/Modules/IGT/Testing/mitkPolhemusTrackingDeviceHardwareTest.cpp @@ -0,0 +1,65 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkPolhemusInterface.h" +#include "mitkTestingMacros.h" +#include "mitkStandardFileLocations.h" +#include + +// Testing +#include "mitkTestingMacros.h" +#include "mitkTestFixture.h" + +class mitkPolhemusTrackingDeviceHardwareTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkPolhemusTrackingDeviceHardwareTestSuite); + // Test the append method + MITK_TEST(testInterface); + CPPUNIT_TEST_SUITE_END(); + + +public: + void setUp() override + { + + } + void tearDown() override + { + + } + + void testInterface() + { + mitk::PolhemusInterface::Pointer myInterface = mitk::PolhemusInterface::New(); + CPPUNIT_ASSERT_MESSAGE("Testing connection.", myInterface->Connect()); + CPPUNIT_ASSERT_MESSAGE("Start tracking.", myInterface->StartTracking()); + + CPPUNIT_ASSERT_MESSAGE("Tracking 20 frames ...", true); + for (int i = 0; i < 20; i++) + { + std::vector lastFrame = myInterface->GetLastFrame(); + MITK_INFO << "Frame " << i; + for (int j = 0; j < lastFrame.size(); j++) + { + MITK_INFO << "[" << j << "]" << " Pos:" << lastFrame.at(j).pos << " Rot:" << lastFrame.at(j).rot; + } + } + + } + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkPolhemusTrackingDeviceHardware) diff --git a/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.cpp b/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.cpp index f8c8292534..04a190ddaa 100644 --- a/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.cpp +++ b/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.cpp @@ -1,1282 +1,1335 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNDITrackingDevice.h" #include "mitkIGTTimeStamp.h" #include "mitkIGTHardwareException.h" #include #include #include #include #include #include +// vtk +#include + typedef itk::MutexLockHolder MutexLockHolder; const unsigned char CR = 0xD; // == '\r' - carriage return const unsigned char LF = 0xA; // == '\n' - line feed mitk::NDITrackingDevice::NDITrackingDevice() : TrackingDevice(),m_DeviceName(""), m_PortNumber(mitk::SerialCommunication::COM5), m_BaudRate(mitk::SerialCommunication::BaudRate9600), m_DataBits(mitk::SerialCommunication::DataBits8), m_Parity(mitk::SerialCommunication::None), m_StopBits(mitk::SerialCommunication::StopBits1), m_HardwareHandshake(mitk::SerialCommunication::HardwareHandshakeOff), m_IlluminationActivationRate(Hz20), m_DataTransferMode(TX), m_6DTools(), m_ToolsMutex(nullptr), m_SerialCommunication(nullptr), m_SerialCommunicationMutex(nullptr), m_DeviceProtocol(nullptr), m_MultiThreader(nullptr), m_ThreadID(0), m_OperationMode(ToolTracking6D), m_MarkerPointsMutex(nullptr), m_MarkerPoints() { m_Data = mitk::UnspecifiedTrackingTypeInformation::GetDeviceDataUnspecified(); m_6DTools.clear(); m_SerialCommunicationMutex = itk::FastMutexLock::New(); m_DeviceProtocol = NDIProtocol::New(); m_DeviceProtocol->SetTrackingDevice(this); m_DeviceProtocol->UseCRCOn(); m_MultiThreader = itk::MultiThreader::New(); m_ToolsMutex = itk::FastMutexLock::New(); m_MarkerPointsMutex = itk::FastMutexLock::New(); m_MarkerPoints.reserve(50); // a maximum of 50 marker positions can be reported by the tracking device } bool mitk::NDITrackingDevice::UpdateTool(mitk::TrackingTool* tool) { if (this->GetState() != Setup) { mitk::NDIPassiveTool* ndiTool = dynamic_cast(tool); if (ndiTool == nullptr) return false; std::string portHandle = ndiTool->GetPortHandle(); //return false if the SROM Data has not been set if (ndiTool->GetSROMData() == nullptr) return false; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->PVWR(&portHandle, ndiTool->GetSROMData(), ndiTool->GetSROMDataLength()); if (returnvalue != NDIOKAY) return false; returnvalue = m_DeviceProtocol->PINIT(&portHandle); if (returnvalue != NDIOKAY) return false; returnvalue = m_DeviceProtocol->PENA(&portHandle, ndiTool->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) return false; return true; } else { return false; } } void mitk::NDITrackingDevice::SetRotationMode(RotationMode r) { m_RotationMode = r; } mitk::NDITrackingDevice::~NDITrackingDevice() { /* stop tracking and disconnect from tracking device */ if (GetState() == Tracking) { this->StopTracking(); } if (GetState() == Ready) { this->CloseConnection(); } /* cleanup tracking thread */ if ((m_ThreadID != 0) && (m_MultiThreader.IsNotNull())) { m_MultiThreader->TerminateThread(m_ThreadID); } m_MultiThreader = nullptr; /* free serial communication interface */ if (m_SerialCommunication.IsNotNull()) { m_SerialCommunication->ClearReceiveBuffer(); m_SerialCommunication->ClearSendBuffer(); m_SerialCommunication->CloseConnection(); m_SerialCommunication = nullptr; } } void mitk::NDITrackingDevice::SetPortNumber(const PortNumber _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting PortNumber to " << _arg); if (this->m_PortNumber != _arg) { this->m_PortNumber = _arg; this->Modified(); } } void mitk::NDITrackingDevice::SetDeviceName(std::string _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting eviceName to " << _arg); if (this->m_DeviceName != _arg) { this->m_DeviceName = _arg; this->Modified(); } } void mitk::NDITrackingDevice::SetBaudRate(const BaudRate _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting BaudRate to " << _arg); if (this->m_BaudRate != _arg) { this->m_BaudRate = _arg; this->Modified(); } } void mitk::NDITrackingDevice::SetDataBits(const DataBits _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting DataBits to " << _arg); if (this->m_DataBits != _arg) { this->m_DataBits = _arg; this->Modified(); } } void mitk::NDITrackingDevice::SetParity(const Parity _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting Parity to " << _arg); if (this->m_Parity != _arg) { this->m_Parity = _arg; this->Modified(); } } void mitk::NDITrackingDevice::SetStopBits(const StopBits _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting StopBits to " << _arg); if (this->m_StopBits != _arg) { this->m_StopBits = _arg; this->Modified(); } } void mitk::NDITrackingDevice::SetHardwareHandshake(const HardwareHandshake _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting HardwareHandshake to " << _arg); if (this->m_HardwareHandshake != _arg) { this->m_HardwareHandshake = _arg; this->Modified(); } } void mitk::NDITrackingDevice::SetIlluminationActivationRate(const IlluminationActivationRate _arg) { if (this->GetState() == Tracking) return; itkDebugMacro("setting IlluminationActivationRate to " << _arg); if (this->m_IlluminationActivationRate != _arg) { this->m_IlluminationActivationRate = _arg; this->Modified(); if (this->GetState() == Ready) // if the connection to the tracking system is established, send the new rate to the tracking device too m_DeviceProtocol->IRATE(this->m_IlluminationActivationRate); } } void mitk::NDITrackingDevice::SetDataTransferMode(const DataTransferMode _arg) { itkDebugMacro("setting DataTransferMode to " << _arg); if (this->m_DataTransferMode != _arg) { this->m_DataTransferMode = _arg; this->Modified(); } } mitk::NDIErrorCode mitk::NDITrackingDevice::Send(const std::string* input, bool addCRC) { if (input == nullptr) return SERIALSENDERROR; std::string message; if (addCRC == true) message = *input + CalcCRC(input) + std::string(1, CR); else message = *input + std::string(1, CR); //unsigned int messageLength = message.length() + 1; // +1 for CR // Clear send buffer this->ClearSendBuffer(); // Send the date to the device MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex long returnvalue = m_SerialCommunication->Send(message); if (returnvalue == 0) return SERIALSENDERROR; else return NDIOKAY; } mitk::NDIErrorCode mitk::NDITrackingDevice::Receive(std::string* answer, unsigned int numberOfBytes) { if (answer == nullptr) return SERIALRECEIVEERROR; MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex long returnvalue = m_SerialCommunication->Receive(*answer, numberOfBytes); // never read more bytes than the device has send, the function will block until enough bytes are send... if (returnvalue == 0) return SERIALRECEIVEERROR; else return NDIOKAY; } mitk::NDIErrorCode mitk::NDITrackingDevice::ReceiveByte(char* answer) { if (answer == nullptr) return SERIALRECEIVEERROR; std::string m; MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex long returnvalue = m_SerialCommunication->Receive(m, 1); if ((returnvalue == 0) ||(m.size() != 1)) return SERIALRECEIVEERROR; *answer = m.at(0); return NDIOKAY; } mitk::NDIErrorCode mitk::NDITrackingDevice::ReceiveLine(std::string* answer) { if (answer == nullptr) return SERIALRECEIVEERROR; std::string m; MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex do { long returnvalue = m_SerialCommunication->Receive(m, 1); if ((returnvalue == 0) ||(m.size() != 1)) return SERIALRECEIVEERROR; *answer += m; } while (m.at(0) != LF); return NDIOKAY; } void mitk::NDITrackingDevice::ClearSendBuffer() { MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex m_SerialCommunication->ClearSendBuffer(); } void mitk::NDITrackingDevice::ClearReceiveBuffer() { MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex m_SerialCommunication->ClearReceiveBuffer(); } const std::string mitk::NDITrackingDevice::CalcCRC(const std::string* input) { if (input == nullptr) return ""; /* the crc16 calculation code is taken from the NDI API guide example code section */ static int oddparity[16] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0}; unsigned int data; // copy of the input string's current character unsigned int crcValue = 0; // the crc value is stored here unsigned int* puCRC16 = &crcValue; // the algorithm uses a pointer to crcValue, so it's easier to provide that than to change the algorithm for (unsigned int i = 0; i < input->length(); i++) { data = (*input)[i]; data = (data ^ (*(puCRC16) & 0xff)) & 0xff; *puCRC16 >>= 8; if (oddparity[data & 0x0f] ^ oddparity[data >> 4]) { *(puCRC16) ^= 0xc001; } data <<= 6; *puCRC16 ^= data; data <<= 1; *puCRC16 ^= data; } // crcValue contains now the CRC16 value. Convert it to a string and return it char returnvalue[13]; sprintf(returnvalue,"%04X", crcValue); // 4 hexadecimal digit with uppercase format return std::string(returnvalue); } bool mitk::NDITrackingDevice::OpenConnection() { //this->m_ModeMutex->Lock(); if (this->GetState() != Setup) {mitkThrowException(mitk::IGTException) << "Can only try to open the connection if in setup mode";} m_SerialCommunication = mitk::SerialCommunication::New(); /* init local com port to standard com settings for a NDI tracking device: 9600 baud, 8 data bits, no parity, 1 stop bit, no hardware handshake */ if (m_DeviceName.empty()) m_SerialCommunication->SetPortNumber(m_PortNumber); else m_SerialCommunication->SetDeviceName(m_DeviceName); m_SerialCommunication->SetBaudRate(mitk::SerialCommunication::BaudRate9600); m_SerialCommunication->SetDataBits(mitk::SerialCommunication::DataBits8); m_SerialCommunication->SetParity(mitk::SerialCommunication::None); m_SerialCommunication->SetStopBits(mitk::SerialCommunication::StopBits1); m_SerialCommunication->SetSendTimeout(5000); m_SerialCommunication->SetReceiveTimeout(5000); if (m_SerialCommunication->OpenConnection() == 0) // 0 == ERROR_VALUE { m_SerialCommunication->CloseConnection(); m_SerialCommunication = nullptr; mitkThrowException(mitk::IGTHardwareException) << "Can not open serial port"; } /* Reset Tracking device by sending a serial break for 500ms */ m_SerialCommunication->SendBreak(400); /* Read answer from tracking device (RESETBE6F) */ static const std::string reset("RESETBE6F\r"); std::string answer = ""; this->Receive(&answer, reset.length()); // read answer (should be RESETBE6F) this->ClearReceiveBuffer(); // flush the receive buffer of all remaining data (carriage return, strings other than reset if (reset.compare(answer) != 0) // check for RESETBE6F { if (m_SerialCommunication.IsNotNull()) { m_SerialCommunication->CloseConnection(); m_SerialCommunication = nullptr; } mitkThrowException(mitk::IGTHardwareException) << "Hardware Reset of tracking device did not work"; } /* Now the tracking device isSetData reset, start initialization */ NDIErrorCode returnvalue; /* set device com settings to new values and wait for the device to change them */ returnvalue = m_DeviceProtocol->COMM(m_BaudRate, m_DataBits, m_Parity, m_StopBits, m_HardwareHandshake); if (returnvalue != NDIOKAY) {mitkThrowException(mitk::IGTHardwareException) << "Could not set comm settings in trackingdevice";} //after changing COMM wait at least 100ms according to NDI Api documentation page 31 itksys::SystemTools::Delay(500); /* now change local com settings accordingly */ m_SerialCommunication->CloseConnection(); m_SerialCommunication->SetBaudRate(m_BaudRate); m_SerialCommunication->SetDataBits(m_DataBits); m_SerialCommunication->SetParity(m_Parity); m_SerialCommunication->SetStopBits(m_StopBits); m_SerialCommunication->SetHardwareHandshake(m_HardwareHandshake); m_SerialCommunication->SetSendTimeout(5000); m_SerialCommunication->SetReceiveTimeout(5000); m_SerialCommunication->OpenConnection(); /* initialize the tracking device */ returnvalue = m_DeviceProtocol->INIT(); if (returnvalue != NDIOKAY) {mitkThrowException(mitk::IGTHardwareException) << "Could not initialize the tracking device";} if (this->GetType() == mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName()) // if the type of tracking device is not specified, try to query the connected device { mitk::TrackingDeviceType deviceType; returnvalue = m_DeviceProtocol->VER(deviceType); if ((returnvalue != NDIOKAY) || (deviceType == mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName())) {mitkThrowException(mitk::IGTHardwareException) << "Could not determine tracking device type. Please set manually and try again.";} this->SetType(deviceType); } /**** Optional Polaris specific code, Work in progress // start diagnostic mode returnvalue = m_DeviceProtocol->DSTART(); if (returnvalue != NDIOKAY) { this->SetErrorMessage("Could not start diagnostic mode"); return false; } else // we are in diagnostic mode { // initialize extensive IR checking returnvalue = m_DeviceProtocol->IRINIT(); if (returnvalue != NDIOKAY) { this->SetErrorMessage("Could not initialize intense infrared light checking"); return false; } bool intenseIR = false; returnvalue = m_DeviceProtocol->IRCHK(&intenseIR); if (returnvalue != NDIOKAY) { this->SetErrorMessage("Could not execute intense infrared light checking"); return false; } if (intenseIR == true) // do something - warn the user, raise exception, write to protocol or similar std::cout << "Warning: Intense infrared light detected. Accurate tracking will probably not be possible.\n"; // stop diagnictic mode returnvalue = m_DeviceProtocol->DSTOP(); if (returnvalue != NDIOKAY) { this->SetErrorMessage("Could not stop diagnostic mode"); return false; } } *** end of optional polaris code ***/ /** * now add tools to the tracking system **/ /* First, check if the tracking device has port handles that need to be freed and free them */ returnvalue = FreePortHandles(); // non-critical, therefore no error handling /** * POLARIS: initialize the tools that were added manually **/ { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex std::string portHandle; auto endIt = m_6DTools.end(); for(auto it = m_6DTools.begin(); it != endIt; ++it) { /* get a port handle for the tool */ returnvalue = m_DeviceProtocol->PHRQ(&portHandle); if (returnvalue == NDIOKAY) { (*it)->SetPortHandle(portHandle.c_str()); /* now write the SROM file of the tool to the tracking system using PVWR */ if (this->m_Data.Line == mitk::NDIPolarisTypeInformation::GetTrackingDeviceName()) { returnvalue = m_DeviceProtocol->PVWR(&portHandle, (*it)->GetSROMData(), (*it)->GetSROMDataLength()); if (returnvalue != NDIOKAY) {mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + (*it)->GetToolName() + std::string("' to tracking device")).c_str();} returnvalue = m_DeviceProtocol->PINIT(&portHandle); if (returnvalue != NDIOKAY) {mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize tool '") + (*it)->GetToolName()).c_str();} if ((*it)->IsEnabled() == true) { returnvalue = m_DeviceProtocol->PENA(&portHandle, (*it)->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + portHandle + std::string("' for tool '")+ (*it)->GetToolName() + std::string("'")).c_str(); } } } } } } // end of toolsmutexlockholder scope /* check for wired tools and add them too */ if (this->DiscoverWiredTools() == false) // query the tracking device for wired tools and add them to our tool list return false; // \TODO: could we continue anyways? /*POLARIS: set the illuminator activation rate */ if (this->m_Data.Line == mitk::NDIPolarisTypeInformation::GetTrackingDeviceName()) { returnvalue = m_DeviceProtocol->IRATE(this->m_IlluminationActivationRate); if (returnvalue != NDIOKAY) {mitkThrowException(mitk::IGTHardwareException) << "Could not set the illuminator activation rate";} } /* finish - now all tools should be added, initialized and enabled, so that tracking can be started */ this->SetState(Ready); try { SetVolume(this->m_Data); } catch (mitk::IGTHardwareException e) { MITK_WARN<PHSR(OCCUPIED, &portHandle); if (returnvalue != NDIOKAY) {mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that are connected";} /* if there are port handles that need to be initialized, initialize them. Furthermore instantiate tools for each handle that has no tool yet. */ std::string ph; for (unsigned int i = 0; i < portHandle.size(); i += 2) { ph = portHandle.substr(i, 2); mitk::NDIPassiveTool* pt = this->GetInternalTool(ph); if ( pt == nullptr) // if we don't have a tool, something is wrong. Tools should be discovered first by calling DiscoverWiredTools() continue; if (pt->GetSROMData() == nullptr) continue; returnvalue = m_DeviceProtocol->PVWR(&ph, pt->GetSROMData(), pt->GetSROMDataLength()); if (returnvalue != NDIOKAY) {mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + pt->GetToolName() + std::string("' to tracking device")).c_str();} returnvalue = m_DeviceProtocol->PINIT(&ph); if (returnvalue != NDIOKAY) {mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize tool '") + pt->GetToolName()).c_str();} if (pt->IsEnabled() == true) { returnvalue = m_DeviceProtocol->PENA(&ph, pt->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + portHandle + std::string("' for tool '")+ pt->GetToolName() + std::string("'")).c_str(); } } } return true; } mitk::TrackingDeviceType mitk::NDITrackingDevice::TestConnection() { if (this->GetState() != Setup) { return mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName(); } m_SerialCommunication = mitk::SerialCommunication::New(); //m_DeviceProtocol = mitk::NDIProtocol::New(); //m_DeviceProtocol->SetTrackingDevice(this); //m_DeviceProtocol->UseCRCOn(); /* init local com port to standard com settings for a NDI tracking device: 9600 baud, 8 data bits, no parity, 1 stop bit, no hardware handshake */ if (m_DeviceName.empty()) m_SerialCommunication->SetPortNumber(m_PortNumber); else m_SerialCommunication->SetDeviceName(m_DeviceName); m_SerialCommunication->SetBaudRate(mitk::SerialCommunication::BaudRate9600); m_SerialCommunication->SetDataBits(mitk::SerialCommunication::DataBits8); m_SerialCommunication->SetParity(mitk::SerialCommunication::None); m_SerialCommunication->SetStopBits(mitk::SerialCommunication::StopBits1); m_SerialCommunication->SetSendTimeout(5000); m_SerialCommunication->SetReceiveTimeout(5000); if (m_SerialCommunication->OpenConnection() == 0) // error { m_SerialCommunication = nullptr; return mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName(); } /* Reset Tracking device by sending a serial break for 500ms */ m_SerialCommunication->SendBreak(400); /* Read answer from tracking device (RESETBE6F) */ static const std::string reset("RESETBE6F\r"); std::string answer = ""; this->Receive(&answer, reset.length()); // read answer (should be RESETBE6F) this->ClearReceiveBuffer(); // flush the receive buffer of all remaining data (carriage return, strings other than reset if (reset.compare(answer) != 0) // check for RESETBE6F { m_SerialCommunication->CloseConnection(); m_SerialCommunication = nullptr; mitkThrowException(mitk::IGTHardwareException) << "Hardware Reset of tracking device did not work"; } /* Now the tracking device is reset, start initialization */ NDIErrorCode returnvalue; /* initialize the tracking device */ //returnvalue = m_DeviceProtocol->INIT(); //if (returnvalue != NDIOKAY) //{ // this->SetErrorMessage("Could not initialize the tracking device"); // return mitk::TrackingSystemNotSpecified; //} mitk::TrackingDeviceType deviceType; returnvalue = m_DeviceProtocol->VER(deviceType); if ((returnvalue != NDIOKAY) || (deviceType == mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName())) { m_SerialCommunication = nullptr; return mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName(); } m_SerialCommunication = nullptr; return deviceType; } bool mitk::NDITrackingDevice::CloseConnection() { if (this->GetState() != Setup) { //init before closing to force the field generator from aurora to switch itself off m_DeviceProtocol->INIT(); /* close the serial connection */ m_SerialCommunication->CloseConnection(); /* invalidate all tools */ this->InvalidateAll(); /* return to setup mode */ this->SetState(Setup); m_SerialCommunication = nullptr; } return true; } ITK_THREAD_RETURN_TYPE mitk::NDITrackingDevice::ThreadStartTracking(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == nullptr) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == nullptr) { return ITK_THREAD_RETURN_VALUE; } NDITrackingDevice *trackingDevice = (NDITrackingDevice*)pInfo->UserData; if (trackingDevice != nullptr) { if (trackingDevice->GetOperationMode() == ToolTracking6D) trackingDevice->TrackTools(); // call TrackTools() from the original object else if (trackingDevice->GetOperationMode() == MarkerTracking3D) trackingDevice->TrackMarkerPositions(); // call TrackMarkerPositions() from the original object else if (trackingDevice->GetOperationMode() == ToolTracking5D) trackingDevice->TrackMarkerPositions(); // call TrackMarkerPositions() from the original object else if (trackingDevice->GetOperationMode() == HybridTracking) { trackingDevice->TrackToolsAndMarkers(); } } trackingDevice->m_ThreadID = 0; // erase thread id, now that this thread will end. return ITK_THREAD_RETURN_VALUE; } bool mitk::NDITrackingDevice::StartTracking() { if (this->GetState() != Ready) return false; this->SetState(Tracking); // go to mode Tracking this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking this->m_StopTracking = false; this->m_StopTrackingMutex->Unlock(); m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this); // start a new thread that executes the TrackTools() method mitk::IGTTimeStamp::GetInstance()->Start(this); return true; } void mitk::NDITrackingDevice::TrackTools() { /* lock the TrackingFinishedMutex to signal that the execution rights are now transfered to the tracking thread */ MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope if (this->GetState() != Tracking) return; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->TSTART(); if (returnvalue != NDIOKAY) return; bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking localStopTracking = this->m_StopTracking; this->m_StopTrackingMutex->Unlock(); while ((this->GetState() == Tracking) && (localStopTracking == false)) { if (this->m_DataTransferMode == TX) { returnvalue = this->m_DeviceProtocol->TX(); if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors break; } else { returnvalue = this->m_DeviceProtocol->BX(); if (returnvalue != NDIOKAY) break; } /* Update the local copy of m_StopTracking */ this->m_StopTrackingMutex->Lock(); localStopTracking = m_StopTracking; this->m_StopTrackingMutex->Unlock(); } /* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */ returnvalue = m_DeviceProtocol->TSTOP(); if (returnvalue != NDIOKAY) {mitkThrowException(mitk::IGTHardwareException) << "An error occured while tracking tools.";} return; // returning from this function (and ThreadStartTracking()) this will end the thread and transfer control back to main thread by releasing trackingFinishedLockHolder } void mitk::NDITrackingDevice::TrackMarkerPositions() { MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope if (m_OperationMode == ToolTracking6D) return; if (this->GetState() != Tracking) return; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->DSTART(); // Start Diagnostic Mode if (returnvalue != NDIOKAY) return; bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking localStopTracking = this->m_StopTracking; this->m_StopTrackingMutex->Unlock(); while ((this->GetState() == Tracking) && (localStopTracking == false)) { m_MarkerPointsMutex->Lock(); // lock points data structure returnvalue = this->m_DeviceProtocol->POS3D(&m_MarkerPoints); // update points data structure with new position data from tracking device m_MarkerPointsMutex->Unlock(); if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors { std::cout << "Error in POS3D: could not read data. Possibly no markers present." << std::endl; } /* Update the local copy of m_StopTracking */ this->m_StopTrackingMutex->Lock(); localStopTracking = m_StopTracking; this->m_StopTrackingMutex->Unlock(); itksys::SystemTools::Delay(1); } /* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */ returnvalue = m_DeviceProtocol->DSTOP(); if (returnvalue != NDIOKAY) return; // how can this thread tell the application, that an error has occured? this->SetState(Ready); return; // returning from this function (and ThreadStartTracking()) this will end the thread } void mitk::NDITrackingDevice::TrackToolsAndMarkers() { MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope if (m_OperationMode != HybridTracking) return; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->TSTART(); // Start Diagnostic Mode if (returnvalue != NDIOKAY) return; bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking localStopTracking = this->m_StopTracking; this->m_StopTrackingMutex->Unlock(); while ((this->GetState() == Tracking) && (localStopTracking == false)) { m_MarkerPointsMutex->Lock(); // lock points data structure returnvalue = this->m_DeviceProtocol->TX(true, &m_MarkerPoints); // update points data structure with new position data from tracking device m_MarkerPointsMutex->Unlock(); if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors { std::cout << "Error in TX: could not read data. Possibly no markers present." << std::endl; } /* Update the local copy of m_StopTracking */ this->m_StopTrackingMutex->Lock(); localStopTracking = m_StopTracking; this->m_StopTrackingMutex->Unlock(); } /* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */ returnvalue = m_DeviceProtocol->TSTOP(); if (returnvalue != NDIOKAY) return; // how can this thread tell the application, that an error has occurred? this->SetState(Ready); return; // returning from this function (and ThreadStartTracking()) this will end the thread } mitk::TrackingTool* mitk::NDITrackingDevice::GetTool(unsigned int toolNumber) const { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex if (toolNumber < m_6DTools.size()) return m_6DTools.at(toolNumber); return nullptr; } mitk::TrackingTool* mitk::NDITrackingDevice::GetToolByName(std::string name) const { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) if (name.compare((*iterator)->GetToolName()) == 0) return *iterator; return nullptr; } mitk::NDIPassiveTool* mitk::NDITrackingDevice::GetInternalTool(std::string portHandle) { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) if (portHandle.compare((*iterator)->GetPortHandle()) == 0) return *iterator; return nullptr; } unsigned int mitk::NDITrackingDevice::GetToolCount() const { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex return m_6DTools.size(); } bool mitk::NDITrackingDevice::Beep(unsigned char count) { if (this->GetState() != Setup) { return (m_DeviceProtocol->BEEP(count) == NDIOKAY); } else { return false; } } mitk::TrackingTool* mitk::NDITrackingDevice::AddTool( const char* toolName, const char* fileName, TrackingPriority p /*= NDIPassiveTool::Dynamic*/ ) { mitk::NDIPassiveTool::Pointer t = mitk::NDIPassiveTool::New(); if (t->LoadSROMFile(fileName) == false) return nullptr; t->SetToolName(toolName); t->SetTrackingPriority(p); if (this->InternalAddTool(t) == false) return nullptr; return t.GetPointer(); } bool mitk::NDITrackingDevice::InternalAddTool(mitk::NDIPassiveTool* tool) { if (tool == nullptr) return false; NDIPassiveTool::Pointer p = tool; /* if the connection to the tracking device is already established, add the new tool to the device now */ if (this->GetState() == Ready) { /* get a port handle for the tool */ std::string newPortHandle; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->PHRQ(&newPortHandle); if (returnvalue == NDIOKAY) { p->SetPortHandle(newPortHandle.c_str()); /* now write the SROM file of the tool to the tracking system using PVWR */ returnvalue = m_DeviceProtocol->PVWR(&newPortHandle, p->GetSROMData(), p->GetSROMDataLength()); if (returnvalue != NDIOKAY) {mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + p->GetToolName() + std::string("' to tracking device")).c_str();} /* initialize the port handle */ returnvalue = m_DeviceProtocol->PINIT(&newPortHandle); if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize port '") + newPortHandle + std::string("' for tool '")+ p->GetToolName() + std::string("'")).c_str(); } /* enable the port handle */ if (p->IsEnabled() == true) { returnvalue = m_DeviceProtocol->PENA(&newPortHandle, p->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + newPortHandle + std::string("' for tool '")+ p->GetToolName() + std::string("'")).c_str(); } } } /* now that the tool is added to the device, add it to list too */ m_ToolsMutex->Lock(); this->m_6DTools.push_back(p); m_ToolsMutex->Unlock(); this->Modified(); return true; } else if (this->GetState() == Setup) { /* In Setup mode, we only add it to the list, so that OpenConnection() can add it later */ m_ToolsMutex->Lock(); this->m_6DTools.push_back(p); m_ToolsMutex->Unlock(); this->Modified(); return true; } else // in Tracking mode, no tools can be added return false; } bool mitk::NDITrackingDevice::RemoveTool(mitk::TrackingTool* tool) { mitk::NDIPassiveTool* ndiTool = dynamic_cast(tool); if (ndiTool == nullptr) return false; std::string portHandle = ndiTool->GetPortHandle(); /* a valid portHandle has length 2. If a valid handle exists, the tool is already added to the tracking device, so we have to remove it there if the connection to the tracking device has already been established. */ if ((portHandle.length() == 2) && (this->GetState() == Ready)) // do not remove a tool in tracking mode { NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->PHF(&portHandle); if (returnvalue != NDIOKAY) return false; /* Now that the tool is removed from the tracking device, remove it from our tool list too */ MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex (scope is inside the if-block auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) { if (iterator->GetPointer() == ndiTool) { m_6DTools.erase(iterator); this->Modified(); return true; } } return false; } else if (this->GetState() == Setup) // in Setup Mode, we are not connected to the tracking device, so we can just remove the tool from the tool list { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) { if ((*iterator).GetPointer() == ndiTool) { m_6DTools.erase(iterator); this->Modified(); return true; } } return false; } return false; } void mitk::NDITrackingDevice::InvalidateAll() { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) (*iterator)->SetDataValid(false); } bool mitk::NDITrackingDevice::SetOperationMode(OperationMode mode) { if (GetState() == Tracking) return false; m_OperationMode = mode; return true; } mitk::OperationMode mitk::NDITrackingDevice::GetOperationMode() { return m_OperationMode; } bool mitk::NDITrackingDevice::GetMarkerPositions(MarkerPointContainerType* markerpositions) { m_MarkerPointsMutex->Lock(); *markerpositions = m_MarkerPoints; // copy the internal vector to the one provided m_MarkerPointsMutex->Unlock(); return (markerpositions->size() != 0) ; } bool mitk::NDITrackingDevice::DiscoverWiredTools() { /* First, check for disconnected tools and remove them */ this->FreePortHandles(); /* check for new tools, add and initialize them */ NDIErrorCode returnvalue; std::string portHandle; returnvalue = m_DeviceProtocol->PHSR(OCCUPIED, &portHandle); if (returnvalue != NDIOKAY) {mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that are connected";} /* if there are port handles that need to be initialized, initialize them. Furthermore instantiate tools for each handle that has no tool yet. */ std::string ph; /* we need to remember the ports which are occupied to be able to readout the serial numbers of the connected tools later */ std::vector occupiedPorts = std::vector(); int numberOfToolsAtStart = this->GetToolCount(); //also remember the number of tools at start to identify the automatically detected tools later for (unsigned int i = 0; i < portHandle.size(); i += 2) { ph = portHandle.substr(i, 2); if (this->GetInternalTool(ph) != nullptr) // if we already have a tool with this handle continue; // then skip the initialization //instantiate an object for each tool that is connected mitk::NDIPassiveTool::Pointer newTool = mitk::NDIPassiveTool::New(); newTool->SetPortHandle(ph.c_str()); newTool->SetTrackingPriority(mitk::NDIPassiveTool::Dynamic); //set a name for identification newTool->SetToolName((std::string("Port ") + ph).c_str()); returnvalue = m_DeviceProtocol->PINIT(&ph); if (returnvalue != NDIINITIALIZATIONFAILED) //if the initialization failed (AURORA) it can not be enabled. A srom file will have to be specified manually first. Still return true to be able to continue { if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize port '") + ph + std::string("' for tool '")+ newTool->GetToolName() + std::string("'")).c_str(); } /* enable the port handle */ returnvalue = m_DeviceProtocol->PENA(&ph, newTool->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + ph + std::string("' for tool '")+ newTool->GetToolName() + std::string("'")).c_str(); } } //we have to temporarily unlock m_ModeMutex here to avoid a deadlock with another lock inside InternalAddTool() if (this->InternalAddTool(newTool) == false) {mitkThrowException(mitk::IGTException) << "Error while adding new tool";} else occupiedPorts.push_back(i); } // after initialization readout serial numbers of automatically detected tools for (unsigned int i = 0; i < occupiedPorts.size(); i++) { ph = portHandle.substr(occupiedPorts.at(i), 2); std::string portInfo; NDIErrorCode returnvaluePort = m_DeviceProtocol->PHINF(ph, &portInfo); if ((returnvaluePort==NDIOKAY) && (portInfo.size()>31)) dynamic_cast(this->GetTool(i+numberOfToolsAtStart))->SetSerialNumber(portInfo.substr(23,8)); itksys::SystemTools::Delay(10); } return true; } mitk::NDIErrorCode mitk::NDITrackingDevice::FreePortHandles() { /* first search for port handles that need to be freed: e.g. because of a reset of the tracking system */ NDIErrorCode returnvalue = NDIOKAY; std::string portHandle; returnvalue = m_DeviceProtocol->PHSR(FREED, &portHandle); if (returnvalue != NDIOKAY) {mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that need to be freed";} /* if there are port handles that need to be freed, free them */ if (portHandle.empty() == true) return returnvalue; std::string ph; for (unsigned int i = 0; i < portHandle.size(); i += 2) { ph = portHandle.substr(i, 2); mitk::NDIPassiveTool* t = this->GetInternalTool(ph); if (t != nullptr) // if we have a tool for the port handle that needs to be freed { if (this->RemoveTool(t) == false) // remove it (this will free the port too) returnvalue = NDIERROR; } else // we don't have a tool, the port handle exists only in the tracking device { returnvalue = m_DeviceProtocol->PHF(&ph); // free it there // What to do if port handle could not be freed? This seems to be a non critical error if (returnvalue != NDIOKAY) {mitkThrowException(mitk::IGTHardwareException) << "Could not free all port handles";} } } return returnvalue; } int mitk::NDITrackingDevice::GetMajorFirmwareRevisionNumber() { std::string revision; if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9) ) { MITK_ERROR << "Could not receive firmware revision number!"; return 0; } const std::string majrevno = revision.substr(2,3); //cut out "004" from "D.004.001" return std::atoi(majrevno.c_str()); } const char* mitk::NDITrackingDevice::GetFirmwareRevisionNumber() { static std::string revision; if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9) ) { MITK_ERROR << "Could not receive firmware revision number!"; revision = ""; return revision.c_str(); } return revision.c_str(); } +bool mitk::NDITrackingDevice::AutoDetectToolsAvailable() +{ + if (this->GetType() == mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) { return true; } + else { return false; } +} + +mitk::NavigationToolStorage::Pointer mitk::NDITrackingDevice::AutoDetectTools() +{ + mitk::NavigationToolStorage::Pointer autoDetectedStorage = mitk::NavigationToolStorage::New(); + if (this->GetType() == mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) + { + try + { + this->OpenConnection(); + this->StartTracking(); + } + catch (mitk::Exception& e) + { + MITK_WARN << "Warning, can not auto-detect tools! (" << e.GetDescription() << ")"; + return autoDetectedStorage; + } + + for (unsigned int i = 0; i < this->GetToolCount(); i++) + { + //create a navigation tool with sphere as surface + std::stringstream toolname; + toolname << "AutoDetectedTool" << i; + mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New(); + newTool->SetSerialNumber(dynamic_cast(this->GetTool(i))->GetSerialNumber()); + newTool->SetIdentifier(toolname.str()); + newTool->SetTrackingDeviceType(mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()); + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + mitk::Surface::Pointer mySphere = mitk::Surface::New(); + vtkSphereSource *vtkData = vtkSphereSource::New(); + vtkData->SetRadius(3.0f); + vtkData->SetCenter(0.0, 0.0, 0.0); + vtkData->Update(); + mySphere->SetVtkPolyData(vtkData->GetOutput()); + vtkData->Delete(); + newNode->SetData(mySphere); + newNode->SetName(toolname.str()); + newTool->SetDataNode(newNode); + autoDetectedStorage->AddTool(newTool); + } + this->StopTracking(); + this->CloseConnection(); + } + return autoDetectedStorage; +} + bool mitk::NDITrackingDevice::GetSupportedVolumes(unsigned int* numberOfVolumes, mitk::NDITrackingDevice::NDITrackingVolumeContainerType* volumes, mitk::NDITrackingDevice::TrackingVolumeDimensionType* volumesDimensions) { if (numberOfVolumes == nullptr || volumes == nullptr || volumesDimensions == nullptr) return false; static std::string info; if (m_DeviceProtocol->SFLIST(&info) != mitk::NDIOKAY || info.empty()) { MITK_ERROR << "Could not receive tracking volume information of tracking system!"; return false; } /*info contains the following: (+n times:) */ (*numberOfVolumes) = (unsigned int) std::atoi(info.substr(0,1).c_str()); for (unsigned int i=0; i<(*numberOfVolumes); i++) { //e.g. for cube: "9-025000+025000-025000+025000-055000-005000+000000+000000+000000+00000011" //for dome: "A+005000+048000+005000+066000+000000+000000+000000+000000+000000+00000011" std::string::size_type offset, end; offset = (i*73)+1; end = 73+(i*73); std::string currentVolume = info.substr(offset, end);//i=0: from 1 to 73 characters; i=1: from 75 to 148 char; // if i>0 then we have a return statement infront if (i>0) currentVolume = currentVolume.substr(1, currentVolume.size()); if (currentVolume.compare(0, 1, NDIPolarisTypeInformation::GetDeviceDataPolarisOldModel().HardwareCode) == 0) volumes->push_back(NDIPolarisTypeInformation::GetDeviceDataPolarisOldModel().Model); if (currentVolume.compare(0, 3, NDIPolarisTypeInformation::GetDeviceDataPolarisSpectra().HardwareCode) == 0) volumes->push_back(NDIPolarisTypeInformation::GetDeviceDataPolarisSpectra().Model); if (currentVolume.compare(1, 3, NDIPolarisTypeInformation::GetDeviceDataSpectraExtendedPyramid().HardwareCode) == 0) { currentVolume = currentVolume.substr(1,currentVolume.size()); volumes->push_back(NDIPolarisTypeInformation::GetDeviceDataSpectraExtendedPyramid().Model); } if (currentVolume.compare(0, 1, NDIPolarisTypeInformation::GetDeviceDataPolarisVicra().HardwareCode) == 0) volumes->push_back(NDIPolarisTypeInformation::GetDeviceDataPolarisVicra().Model); else if (currentVolume.compare(0, 1, mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarCube().HardwareCode) == 0) volumes->push_back(mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarCube().Model);//alias cube else if (currentVolume.compare(0, 1, mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarDome().HardwareCode) == 0) volumes->push_back(mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarDome().Model); //fill volumesDimensions for (unsigned int index = 0; index < 10; index++) { std::string::size_type offD, endD; offD = 1+(index*7); //7 digits per dimension and the first is the type of volume endD = offD+7; int dimension = std::atoi(currentVolume.substr(offD, endD).c_str()); dimension /= 100; //given in mm. 7 digits are xxxx.xx according to NDI //strange, the last two digits (11) also for the metal flag get read also... volumesDimensions->push_back(dimension); } } return true; } bool mitk::NDITrackingDevice::SetVolume(mitk::TrackingDeviceData volume) { if (m_DeviceProtocol->VSEL(volume) != mitk::NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << "Could not set volume!"; } return true; } diff --git a/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.h b/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.h index ce05dd0425..5c2a47cc90 100644 --- a/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.h +++ b/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.h @@ -1,324 +1,331 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKNDITRACKINGDEVICE_H_HEADER_INCLUDED_C1C2FCD2 #define MITKNDITRACKINGDEVICE_H_HEADER_INCLUDED_C1C2FCD2 #include "mitkTrackingDevice.h" #include #include #include "itkFastMutexLock.h" #include #include "mitkNDIProtocol.h" #include "mitkNDIPassiveTool.h" #include "mitkSerialCommunication.h" namespace mitk { class NDIProtocol; /** Documentation * \brief superclass for specific NDI tracking Devices that use serial communication. * * implements the TrackingDevice interface for NDI tracking devices (POLARIS, AURORA) * * \ingroup IGT */ class MITKIGT_EXPORT NDITrackingDevice : public TrackingDevice { friend class NDIProtocol; public: typedef std::vector Tool6DContainerType; ///< List of 6D tools of the correct type for this tracking device typedef mitk::TrackingDeviceType NDITrackingDeviceType; ///< This enumeration includes the two types of NDI tracking devices (Polaris, Aurora). typedef mitk::SerialCommunication::PortNumber PortNumber; ///< Port number of the serial connection typedef mitk::SerialCommunication::BaudRate BaudRate; ///< Baud rate of the serial connection typedef mitk::SerialCommunication::DataBits DataBits; ///< Number of data bits used in the serial connection typedef mitk::SerialCommunication::Parity Parity; ///< Parity mode used in the serial connection typedef mitk::SerialCommunication::StopBits StopBits; ///< Number of stop bits used in the serial connection typedef mitk::SerialCommunication::HardwareHandshake HardwareHandshake; ///< Hardware handshake mode of the serial connection typedef mitk::NDIPassiveTool::TrackingPriority TrackingPriority; ///< Tracking priority used for tracking a tool mitkClassMacro(NDITrackingDevice, TrackingDevice); itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** * \brief Set the type of the NDI Tracking Device because it can not jet handle this itself */ //itkSetMacro(Type, TrackingDeviceType); /** * \brief initialize the connection to the tracking device * * OpenConnection() establishes the connection to the tracking device by: * - initializing the serial port with the given parameters (port number, baud rate, ...) * - connection to the tracking device * - initializing the device * - initializing all manually added passive tools (user supplied srom file) * - initializing active tools that are connected to the tracking device * @throw mitk::IGTHardwareException Throws an exception if there are errors while connecting to the device. * @throw mitk::IGTException Throws a normal IGT exception if an error occures which is not related to the hardware. */ virtual bool OpenConnection() override; /** * \brief Closes the connection * * CloseConnection() resets the tracking device, invalidates all tools and then closes the serial port. */ virtual bool CloseConnection() override; /** @throw mitk::IGTHardwareException Throws an exception if there are errors while connecting to the device. */ bool InitializeWiredTools(); /** Sets the rotation mode of this class. See documentation of enum RotationMode for details * on the different modes. */ virtual void SetRotationMode(RotationMode r) override; /** * \brief TestConnection() tries to connect to a NDI tracking device on the current port/device and returns which device it has found * * TestConnection() tries to connect to a NDI tracking device on the current port/device. * \return It returns the type of the device that answers at the port/device. Throws an exception if no device is available on that port. * @throw mitk::IGTHardwareException Throws an exception if there are errors while connecting to the device. */ virtual mitk::TrackingDeviceType TestConnection(); /** * \brief retrieves all wired tools from the tracking device * * This method queries the tracking device for all wired tools, initializes them and creates TrackingTool representation objects * for them * \return True if the method was executed successful. * @throw mitk::IGTHardwareException Throws an exception if there are errors while connecting to the device. * @throw mitk::IGTException Throws a normal IGT exception if an error occures which is not related to the hardware. */ bool DiscoverWiredTools(); /** * \brief Start the tracking. * * A new thread is created, which continuously reads the position and orientation information of each tool and stores them inside the tools. * Depending on the current operation mode (see SetOperationMode()), either the 6D tools (ToolTracking6D), 5D tools (ToolTracking5D), * 3D marker positions (MarkerTracking3D) or both 6D tools and 3D markers (HybridTracking) are updated. * Call StopTracking() to stop the tracking thread. */ virtual bool StartTracking() override; /** * \brief return the tool with index toolNumber */ virtual TrackingTool* GetTool(unsigned int toolNumber) const override; virtual mitk::TrackingTool* GetToolByName(std::string name) const override; /** * \brief return current number of tools */ virtual unsigned int GetToolCount() const override; /** * \brief Create a passive 6D tool with toolName and fileName and add it to the list of tools * * This method will create a new NDIPassiveTool object, load the SROM file fileName, * set the tool name toolName and the tracking priority p and then add * it to the list of tools. It returns a pointer of type mitk::TrackingTool to the tool * that can be used to read tracking data from it. * This is the only way to add tools to NDITrackingDevice. * @throw mitk::IGTHardwareException Throws an exception if there are errors while adding the tool. * * \warning adding tools is not possible in tracking mode, only in setup and ready. */ mitk::TrackingTool* AddTool(const char* toolName, const char* fileName, TrackingPriority p = NDIPassiveTool::Dynamic); /** * \brief Remove a passive 6D tool from the list of tracked tools. * * \warning removing tools is not possible in tracking mode, only in setup and ready modes. */ virtual bool RemoveTool(TrackingTool* tool); /** * \brief reloads the srom file and reinitializes the tool */ virtual bool UpdateTool(mitk::TrackingTool* tool); virtual void SetPortNumber(const PortNumber _arg); ///< set port number for serial communication itkGetConstMacro(PortNumber, PortNumber); ///< returns the port number for serial communication virtual void SetDeviceName(std::string _arg); ///< set device name (e.g. COM1, /dev/ttyUSB0). If this is set, PortNumber will be ignored itkGetStringMacro(DeviceName); ///< returns the device name for serial communication virtual void SetBaudRate(const BaudRate _arg); ///< set baud rate for serial communication itkGetConstMacro(BaudRate, BaudRate); ///< returns the baud rate for serial communication virtual void SetDataBits(const DataBits _arg); ///< set number of data bits itkGetConstMacro(DataBits, DataBits); ///< returns the data bits for serial communication virtual void SetParity(const Parity _arg); ///< set parity mode itkGetConstMacro(Parity, Parity); ///< returns the parity mode virtual void SetStopBits(const StopBits _arg); ///< set number of stop bits itkGetConstMacro(StopBits, StopBits); ///< returns the number of stop bits virtual void SetHardwareHandshake(const HardwareHandshake _arg); ///< set use hardware handshake for serial communication itkGetConstMacro(HardwareHandshake, HardwareHandshake); ///< returns the hardware handshake setting virtual void SetIlluminationActivationRate(const IlluminationActivationRate _arg); ///< set activation rate of IR illumator for polaris itkGetConstMacro(IlluminationActivationRate, IlluminationActivationRate); ///< returns the activation rate of IR illumator for polaris virtual void SetDataTransferMode(const DataTransferMode _arg); ///< set data transfer mode to text (TX) or binary (BX). \warning: only TX is supportet at the moment itkGetConstMacro(DataTransferMode, DataTransferMode); ///< returns the data transfer mode virtual bool Beep(unsigned char count); ///< Beep the tracking device 1 to 9 times NDIErrorCode GetErrorCode(const std::string* input); ///< returns the error code for a string that contains an error code in hexadecimal format virtual bool SetOperationMode(OperationMode mode); ///< set operation mode to 6D tool tracking, 3D marker tracking or 6D&3D hybrid tracking (see OperationMode) virtual OperationMode GetOperationMode(); ///< get current operation mode /** * \brief Get 3D marker positions (operation mode must be set to MarkerTracking3D or HybridTracking) */ virtual bool GetMarkerPositions(MarkerPointContainerType* markerpositions); /** * \brief Get major revision number from tracking device * should not be called directly after starting to track **/ virtual int GetMajorFirmwareRevisionNumber(); /** * \brief Get revision number from tracking device as string * should not be called directly after starting to track **/ virtual const char* GetFirmwareRevisionNumber(); + /** @return Returns true if this device can autodetects its tools. */ + virtual bool AutoDetectToolsAvailable(); + /** Autodetects tools from this device and returns them as a navigation tool storage. + * @return Returns the detected tools. Returns an empty storage if no tools are present + * or if detection is not possible + */ + virtual mitk::NavigationToolStorage::Pointer AutoDetectTools(); protected: typedef std::vector NDITrackingVolumeContainerType; ///< vector of tracking volumes typedef std::vector TrackingVolumeDimensionType; ///< List of the supported tracking volume dimensions. /** * \brief Get number of supported tracking volumes, a vector containing the supported volumes and * a vector containing the signed dimensions in mm. For each volume 10 boundaries are stored in the order of * the supported volumes (see AURORA API GUIDE: SFLIST p.54). **/ virtual bool GetSupportedVolumes(unsigned int* numberOfVolumes, NDITrackingVolumeContainerType* volumes, TrackingVolumeDimensionType* volumesDimensions); /** * \brief Sets the desired tracking volume. Returns true if the volume type could be set. It is set in the OpenConnection() Method and sets the tracking volume out of m_Data. * @throw mitk::IGTHardwareException Throws an IGT hardware exception if the volume could not be set. **/ virtual bool SetVolume(mitk::TrackingDeviceData volume); /** * \brief Add a passive 6D tool to the list of tracked tools. This method is used by AddTool * @throw mitk::IGTHardwareException Throws an exception if there are errors while adding the tool. * \warning adding tools is not possible in tracking mode, only in setup and ready. */ virtual bool InternalAddTool(NDIPassiveTool* tool); /* Methods for NDIProtocol friend class */ virtual void InvalidateAll(); ///< invalidate all tools NDIPassiveTool* GetInternalTool(std::string portHandle); ///< returns the tool object that has been assigned the port handle or NULL if no tool can be found /** * \brief free all port handles that need to be freed * * This method retrieves a list of all port handles that need to be freed (e.g. tool got disconnected) * and frees the handles at the tracking device and it removes the tools from the internal tool list * \warning This method can remove TrackingTools from the tool list! After calling this method, GetTool(i) could return * a different tool, because tool indices could have changed. * @throw mitk::IGTHardwareException Throws an exception if there are errors while communicating with the device. * \return returns NDIOKAY if everything was sucessfull, returns an error code otherwise */ NDIErrorCode FreePortHandles(); NDIErrorCode Send(const std::string* message, bool addCRC = true); ///< Send message to tracking device NDIErrorCode Receive(std::string* answer, unsigned int numberOfBytes); ///< receive numberOfBytes bytes from tracking device NDIErrorCode ReceiveByte(char* answer); ///< lightweight receive function, that reads just one byte NDIErrorCode ReceiveLine(std::string* answer); ///< receive characters until the first LF (The LF is included in the answer string) void ClearSendBuffer(); ///< empty send buffer of serial communication interface void ClearReceiveBuffer(); ///< empty receive buffer of serial communication interface const std::string CalcCRC(const std::string* input); ///< returns the CRC16 for input as a std::string public: /** * \brief TrackTools() continuously polls serial interface for new 6d tool positions until StopTracking is called. * * Continuously tracks the 6D position of all tools until StopTracking() is called. * This function is executed by the tracking thread (through StartTracking() and ThreadStartTracking()). * It should not be called directly. * @throw mitk::IGTHardwareException Throws an exception if there are errors while tracking the tools. */ virtual void TrackTools(); /** * \brief continuously polls serial interface for new 3D marker positions until StopTracking is called. * * Continuously tracks the 3D position of all markers until StopTracking() is called. * This function is executed by the tracking thread (through StartTracking() and ThreadStartTracking()). * It should not be called directly. */ virtual void TrackMarkerPositions(); /** * \brief continuously polls serial interface for new 3D marker positions and 6D tool positions until StopTracking is called. * * Continuously tracks the 3D position of all markers and the 6D position of all tools until StopTracking() is called. * This function is executed by the tracking thread (through StartTracking() and ThreadStartTracking()). * It should not be called directly. */ virtual void TrackToolsAndMarkers(); /** * \brief static start method for the tracking thread. */ static ITK_THREAD_RETURN_TYPE ThreadStartTracking(void* data); protected: NDITrackingDevice(); ///< Constructor virtual ~NDITrackingDevice(); ///< Destructor std::string m_DeviceName;///< Device Name PortNumber m_PortNumber; ///< COM Port Number BaudRate m_BaudRate; ///< COM Port Baud Rate DataBits m_DataBits; ///< Number of Data Bits per token Parity m_Parity; ///< Parity mode for communication StopBits m_StopBits; ///< number of stop bits per token HardwareHandshake m_HardwareHandshake; ///< use hardware handshake for serial port connection ///< which tracking volume is currently used (if device supports multiple volumes) (\warning This parameter is not used yet) IlluminationActivationRate m_IlluminationActivationRate; ///< update rate of IR illuminator for Polaris DataTransferMode m_DataTransferMode; ///< use TX (text) or BX (binary) (\warning currently, only TX mode is supported) Tool6DContainerType m_6DTools; ///< list of 6D tools itk::FastMutexLock::Pointer m_ToolsMutex; ///< mutex for coordinated access of tool container mitk::SerialCommunication::Pointer m_SerialCommunication; ///< serial communication interface itk::FastMutexLock::Pointer m_SerialCommunicationMutex; ///< mutex for coordinated access of serial communication interface NDIProtocol::Pointer m_DeviceProtocol; ///< create and parse NDI protocol strings itk::MultiThreader::Pointer m_MultiThreader; ///< creates tracking thread that continuously polls serial interface for new tracking data int m_ThreadID; ///< ID of tracking thread OperationMode m_OperationMode; ///< tracking mode (6D tool tracking, 3D marker tracking,...) itk::FastMutexLock::Pointer m_MarkerPointsMutex; ///< mutex for marker point data container MarkerPointContainerType m_MarkerPoints; ///< container for markers (3D point tracking mode) }; } // namespace mitk #endif /* MITKNDITRACKINGDEVICE_H_HEADER_INCLUDED_C1C2FCD2 */ diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusInterface.cpp b/Modules/IGT/TrackingDevices/mitkPolhemusInterface.cpp new file mode 100644 index 0000000000..26f1b570b8 --- /dev/null +++ b/Modules/IGT/TrackingDevices/mitkPolhemusInterface.cpp @@ -0,0 +1,200 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#define _USE_MATH_DEFINES +#include + +#include + +BYTE MotionBuf[0x1FA400]; + +mitk::PolhemusInterface::PolhemusInterface() +{ + m_pdiDev = new CPDIdev(); + +} + +mitk::PolhemusInterface::~PolhemusInterface() +{ + delete m_pdiDev; +} + +bool mitk::PolhemusInterface::InitializeDevice() +{ + m_pdiDev->ResetTracker(); + m_pdiDev->ResetSAlignment(-1); + m_pdiDev->Trace(TRUE, 7); + return true; +} + +bool mitk::PolhemusInterface::SetupDevice() +{ + m_pdiDev->SetPnoBuffer(MotionBuf, 0x1FA400); + m_pdiDev->SetMetric(true); //use cm instead of inches + + m_pdiDev->StartPipeExport(); + + CPDImdat pdiMDat; + pdiMDat.Empty(); + pdiMDat.Append(PDI_MODATA_FRAMECOUNT); + pdiMDat.Append(PDI_MODATA_POS); + pdiMDat.Append(PDI_MODATA_ORI); + m_pdiDev->SetSDataList(-1, pdiMDat); + + CPDIbiterr cBE; + m_pdiDev->GetBITErrs(cBE); + + if (!(cBE.IsClear())) {m_pdiDev->ClearBITErrs();} + + if (this->m_HemisphereTrackingEnabled) { m_pdiDev->SetSHemiTrack(-1); } + else { m_pdiDev->SetSHemisphere(-1, { (float)2.54,0,0 }); } + + return true; +} + +bool mitk::PolhemusInterface::StartTracking() +{ + LPCTSTR szWindowClass = _T("PDIconsoleWinClass"); + HINSTANCE hInst = GetModuleHandle(0); + HWND hwnd = CreateWindowEx( + WS_EX_NOACTIVATE,//WS_EX_STATICEDGE, // + szWindowClass, + _T("MyWindowName"), + WS_POPUP, + 0, 0, 1, 1, + HWND_MESSAGE, + 0, + hInst, + 0); + + m_continousTracking = true; + return m_pdiDev->StartContPno(hwnd); +} + +bool mitk::PolhemusInterface::StopTracking() +{ + m_continousTracking = false; + return true; +} + +bool mitk::PolhemusInterface::Connect() +{ + if (!InitializeDevice()) { return false; } + + if (m_pdiDev->CnxReady()) { return true; } + CPDIser pdiSer; + m_pdiDev->SetSerialIF(&pdiSer); + + ePiCommType eType = m_pdiDev->DiscoverCnx(); + switch (eType) + { + case PI_CNX_USB: + MITK_INFO << "USB Connection: " << m_pdiDev->GetLastResultStr(); + break; + case PI_CNX_SERIAL: + MITK_INFO << "Serial Connection: " << m_pdiDev->GetLastResultStr(); + break; + default: + MITK_INFO << "DiscoverCnx result: " << m_pdiDev->GetLastResultStr(); + break; + } + + if (!SetupDevice()) { return false; } + + return m_pdiDev->CnxReady(); +} + +bool mitk::PolhemusInterface::Disconnect() +{ + if (m_continousTracking) + { + m_continousTracking = false; + if (!m_pdiDev->Disconnect()) return false; + } + return true; +} + +std::vector mitk::PolhemusInterface::GetLastFrame() +{ + PBYTE pBuf; + DWORD dwSize; + + //read one frame + if (!m_pdiDev->LastPnoPtr(pBuf, dwSize)) {MITK_WARN << m_pdiDev->GetLastResultStr();} + + std::vector returnValue = ParsePolhemusRawData(pBuf, dwSize); + + if (returnValue.empty()) { MITK_WARN << "Cannot parse data / no tools present"; } + + return returnValue; +} + +unsigned int mitk::PolhemusInterface::GetNumberOfTools() +{ + if (m_continousTracking) return GetLastFrame().size(); + else return GetSingleFrame().size(); +} + +std::vector mitk::PolhemusInterface::GetSingleFrame() +{ + if (m_continousTracking) return std::vector(); + + PBYTE pBuf; + DWORD dwSize; + + //read one frame + if (!m_pdiDev->ReadSinglePnoBuf(pBuf, dwSize)) { MITK_WARN << m_pdiDev->GetLastResultStr(); } + + return ParsePolhemusRawData(pBuf, dwSize); +} + +std::vector mitk::PolhemusInterface::ParsePolhemusRawData(PBYTE pBuf, DWORD dwSize) +{ + std::vector returnValue; + + DWORD i = 0; + + while (i eulerQuat(rollAngle, elevationAngle, azimuthAngle); + currentTrackingData.rot = eulerQuat; + + returnValue.push_back(currentTrackingData); + i += shSize; + } + return returnValue; +} diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusInterface.h b/Modules/IGT/TrackingDevices/mitkPolhemusInterface.h new file mode 100644 index 0000000000..28eea88760 --- /dev/null +++ b/Modules/IGT/TrackingDevices/mitkPolhemusInterface.h @@ -0,0 +1,117 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKPolhemusINTERFACE_H_HEADER_INCLUDED_ +#define MITKPolhemusINTERFACE_H_HEADER_INCLUDED_ + + +#include +#include + +#include +#include "mitkCommon.h" + +#include +#include + +#include +#include +#include + +#include + +class CPDIdev; + +namespace mitk +{ + + /** Documentation: + * \brief An object of this class represents the interface to Polhemus trackers. + * \ingroup IGT + */ + class MITKIGT_EXPORT PolhemusInterface : public itk::Object + { + public: + + mitkClassMacroItkParent(PolhemusInterface,itk::Object); + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + struct trackingData + { + mitk::Point3D pos; + mitk::Quaternion rot; + BYTE id; + }; + + /** + * \brief Opens the connection to the device and makes it ready to track tools. + * \return Returns true if there is a connection to the device and the device is ready to track tools, false if not. + */ + bool StartTracking(); + + /** + * \brief Clears all resources. After this method have been called the system isn't ready to track any longer. + * \return Returns true if the operation was succesful, false if not. + */ + bool StopTracking(); + + bool Connect(); + + bool Disconnect(); + + /** @return Returns a single frame. Only works if the tracking device is not in continous tracking mode. Returns an empty vector in case of an error.*/ + std::vector GetSingleFrame(); + + /** @return Returns the last frame when the tracking device is in continous tracking mode. Returns an empty vector in case of an error.*/ + std::vector GetLastFrame(); + + /** @return Returns the number of tools. Returns 0 if no information is avialable.*/ + unsigned int GetNumberOfTools(); + + /** Enables/disables hemisphere tracking for all sensors. */ + itkSetMacro(HemisphereTrackingEnabled, bool); + + protected: + /** + * \brief standard constructor + */ + PolhemusInterface(); + /** + * \brief standard destructor + */ + ~PolhemusInterface(); + + /** Polhemus liberty/patriot tracker object*/ + CPDIdev* m_pdiDev; + + /** Parses polhemus raw data to a collection of tracking data of single tools. */ + std::vector ParsePolhemusRawData(PBYTE pBuf, DWORD dwSize); + + unsigned int m_numberOfTools; + + bool m_continousTracking; + + bool InitializeDevice(); + + bool SetupDevice(); + + bool m_HemisphereTrackingEnabled; + + + }; +}//mitk +#endif diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusTool.cpp b/Modules/IGT/TrackingDevices/mitkPolhemusTool.cpp new file mode 100644 index 0000000000..dfa34e5769 --- /dev/null +++ b/Modules/IGT/TrackingDevices/mitkPolhemusTool.cpp @@ -0,0 +1,25 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkPolhemusTool.h" + +mitk::PolhemusTool::PolhemusTool() :InternalTrackingTool() +{ +} + +mitk::PolhemusTool::~PolhemusTool(void) +{ +} diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusTool.h b/Modules/IGT/TrackingDevices/mitkPolhemusTool.h new file mode 100644 index 0000000000..0d16bebb10 --- /dev/null +++ b/Modules/IGT/TrackingDevices/mitkPolhemusTool.h @@ -0,0 +1,46 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKPolhemusTOOL_H_HEADER_INCLUDED_ +#define MITKPolhemusTOOL_H_HEADER_INCLUDED_ + +#include +#include +#include + +namespace mitk +{ + class PolhemusTrackingDevice; + /** Documentation: + * \brief An object of this class represents a tool of a Polhemus tracking device. + * A tool has to be added to a tracking device which will then + * continuously update the tool coordinates. + * \ingroup IGT + */ + class MITKIGT_EXPORT PolhemusTool : public InternalTrackingTool + { + public: + friend class PolhemusTrackingDevice; + mitkClassMacro(PolhemusTool, InternalTrackingTool); + + protected: + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + PolhemusTool(); + virtual ~PolhemusTool(); + }; +}//mitk +#endif // MITKPolhemusTOOL_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusTrackerTypeInformation.cpp b/Modules/IGT/TrackingDevices/mitkPolhemusTrackerTypeInformation.cpp new file mode 100644 index 0000000000..a4e7bed526 --- /dev/null +++ b/Modules/IGT/TrackingDevices/mitkPolhemusTrackerTypeInformation.cpp @@ -0,0 +1,70 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkPolhemusTrackerTypeInformation.h" + +#include "mitkPolhemusTrackingDevice.h" + +namespace mitk +{ + std::string PolhemusTrackerTypeInformation::GetTrackingDeviceName() + { + return "Polhemus tracker"; + } + + TrackingDeviceData PolhemusTrackerTypeInformation::GetDeviceDataPolhemusTrackerLiberty() + { + TrackingDeviceData data = { PolhemusTrackerTypeInformation::GetTrackingDeviceName(), "Polhemus Liberty Tracker", "cube", "X" }; + return data; + } + + PolhemusTrackerTypeInformation::PolhemusTrackerTypeInformation() + { + m_DeviceName = PolhemusTrackerTypeInformation::GetTrackingDeviceName(); + m_TrackingDeviceData.push_back(GetDeviceDataPolhemusTrackerLiberty()); + } + + PolhemusTrackerTypeInformation::~PolhemusTrackerTypeInformation() + { + } + + mitk::TrackingDeviceSource::Pointer PolhemusTrackerTypeInformation::CreateTrackingDeviceSource( + mitk::TrackingDevice::Pointer trackingDevice, + mitk::NavigationToolStorage::Pointer navigationTools, + std::string* errorMessage, + std::vector* toolCorrespondencesInToolStorage) + { + mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); + mitk::PolhemusTrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); + *toolCorrespondencesInToolStorage = std::vector(); + //add the tools to the tracking device + for (int i = 0; i < navigationTools->GetToolCount(); i++) + { + mitk::NavigationTool::Pointer thisNavigationTool = navigationTools->GetTool(i); + toolCorrespondencesInToolStorage->push_back(i); + bool toolAddSuccess = thisDevice->AddTool(thisNavigationTool->GetToolName().c_str()); + if (!toolAddSuccess) + { + //todo error handling + errorMessage->append("Can't add tool, is the toolfile valid?"); + return NULL; + } + thisDevice->GetTool(i)->SetToolTip(thisNavigationTool->GetToolTipPosition(), thisNavigationTool->GetToolTipOrientation()); + } + returnValue->SetTrackingDevice(thisDevice); + return returnValue; + } +} diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusTrackerTypeInformation.h b/Modules/IGT/TrackingDevices/mitkPolhemusTrackerTypeInformation.h new file mode 100644 index 0000000000..52b8647821 --- /dev/null +++ b/Modules/IGT/TrackingDevices/mitkPolhemusTrackerTypeInformation.h @@ -0,0 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef mitkPolhemusTrackerTypeInformation_h +#define mitkPolhemusTrackerTypeInformation_h + +#include "mitkTrackingDeviceTypeInformation.h" + +namespace mitk +{ + /** Documentation: + * \brief Type information for Polhemus Tracking Devices. + * + * \ingroup IGTUI + */ + class MITKIGT_EXPORT PolhemusTrackerTypeInformation : public TrackingDeviceTypeInformation + { + public: + PolhemusTrackerTypeInformation(); + virtual ~PolhemusTrackerTypeInformation(); + + virtual TrackingDeviceSource::Pointer CreateTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, + mitk::NavigationToolStorage::Pointer navigationTools, + std::string* errorMessage, + std::vector* toolCorrespondencesInToolStorage) override; + + static std::string GetTrackingDeviceName(); + static TrackingDeviceData GetDeviceDataPolhemusTrackerLiberty(); + }; +} // namespace mitk + +#endif //mitkPolhemusTrackerTypeInformation_h diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.cpp b/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.cpp new file mode 100644 index 0000000000..98bd67f4f7 --- /dev/null +++ b/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.cpp @@ -0,0 +1,250 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkPolhemusTrackingDevice.h" +#include "mitkPolhemusTool.h" +#include "mitkIGTConfig.h" +#include "mitkIGTTimeStamp.h" +#include "mitkIGTHardwareException.h" +#include +#include +#include +#include "mitkPolhemusTrackerTypeInformation.h" +#include + +typedef itk::MutexLockHolder MutexLockHolder; + + +mitk::PolhemusTrackingDevice::PolhemusTrackingDevice(): mitk::TrackingDevice() +{ + //set the type of this tracking device + this->m_Data = mitk::PolhemusTrackerTypeInformation::GetDeviceDataPolhemusTrackerLiberty(); + + this->m_MultiThreader = itk::MultiThreader::New(); + m_ThreadID = 0; + + m_Device = mitk::PolhemusInterface::New(); +} + +mitk::PolhemusTrackingDevice::~PolhemusTrackingDevice() +{ +} + +bool mitk::PolhemusTrackingDevice::IsDeviceInstalled() +{ + return true; +} + +mitk::TrackingTool* mitk::PolhemusTrackingDevice::AddTool( const char* toolName) +{ + mitk::PolhemusTool::Pointer t = mitk::PolhemusTool::New(); + t->SetToolName(toolName); + if (this->InternalAddTool(t) == false) + return nullptr; + return t.GetPointer(); +} + +bool mitk::PolhemusTrackingDevice::InternalAddTool(PolhemusTool::Pointer tool) +{ + m_AllTools.push_back(tool); + return true; +} + +bool mitk::PolhemusTrackingDevice::StartTracking() +{ + bool success = m_Device->StartTracking(); + if (success) + { + mitk::IGTTimeStamp::GetInstance()->Start(this); + this->SetState(Tracking); + m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this); // start a new thread that executes the TrackTools() method + return true; + } + else + { + this->SetState(Ready); + mitkThrowException(mitk::IGTHardwareException) << "Error while trying to start the device!"; + } + return success; +} + +bool mitk::PolhemusTrackingDevice::StopTracking() +{ + return Superclass::StopTracking(); +} + + +unsigned int mitk::PolhemusTrackingDevice::GetToolCount() const +{ + return (unsigned int)this->m_AllTools.size(); +} + + +mitk::TrackingTool* mitk::PolhemusTrackingDevice::GetTool(unsigned int toolNumber) const +{ + if ( toolNumber >= this->GetToolCount()) + return nullptr; + else + return this->m_AllTools[toolNumber]; +} + + +bool mitk::PolhemusTrackingDevice::OpenConnection() +{ + //reset everything + if (m_Device.IsNull()) {m_Device = mitk::PolhemusInterface::New();} + m_Device->SetHemisphereTrackingEnabled(m_HemisphereTrackingEnabled); + m_Device->Connect(); + this->SetState(Ready); + return true; +} + +bool mitk::PolhemusTrackingDevice::CloseConnection() +{ + bool returnValue = true; + if (this->GetState() == Setup) + return true; + + returnValue = m_Device->Disconnect(); + + this->SetState(Setup); + return returnValue; +} + + +mitk::PolhemusInterface* mitk::PolhemusTrackingDevice::GetDevice() +{ + return m_Device; +} + + +std::vector mitk::PolhemusTrackingDevice::GetAllTools() +{ + return this->m_AllTools; +} + + +void mitk::PolhemusTrackingDevice::TrackTools() +{ + try + { + /* lock the TrackingFinishedMutex to signal that the execution rights are now transfered to the tracking thread */ + MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope + + bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here + this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking + localStopTracking = this->m_StopTracking; + this->m_StopTrackingMutex->Unlock(); + Sleep(100);//Wait a bit until the tracker is ready... + + while ((this->GetState() == Tracking) && (localStopTracking == false)) + { + std::vector lastData = this->GetDevice()->GetLastFrame(); + + if (lastData.size() != m_AllTools.size()) + { + MITK_WARN << "Tool count is corrupt. Aborting!"; + } + else + { + std::vector allTools = this->GetAllTools(); + for (int i = 0; i < allTools.size(); i++) + { + mitk::PolhemusTool::Pointer currentTool = allTools.at(i); + currentTool->SetDataValid(true); + currentTool->SetPosition(lastData.at(i).pos); + currentTool->SetOrientation(lastData.at(i).rot); + currentTool->SetIGTTimeStamp(mitk::IGTTimeStamp::GetInstance()->GetElapsed()); + } + } + /* Update the local copy of m_StopTracking */ + this->m_StopTrackingMutex->Lock(); + localStopTracking = m_StopTracking; + this->m_StopTrackingMutex->Unlock(); + } + } + catch(...) + { + this->StopTracking(); + mitkThrowException(mitk::IGTHardwareException) << "Error while trying to track tools. Thread stopped."; + } +} + +ITK_THREAD_RETURN_TYPE mitk::PolhemusTrackingDevice::ThreadStartTracking(void* pInfoStruct) +{ + /* extract this pointer from Thread Info structure */ + struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; + if (pInfo == nullptr) + { + return ITK_THREAD_RETURN_VALUE; + } + if (pInfo->UserData == nullptr) + { + return ITK_THREAD_RETURN_VALUE; + } + PolhemusTrackingDevice *trackingDevice = (PolhemusTrackingDevice*)pInfo->UserData; + + if (trackingDevice != nullptr) + trackingDevice->TrackTools(); + + return ITK_THREAD_RETURN_VALUE; +} + +bool mitk::PolhemusTrackingDevice::AutoDetectToolsAvailable() +{ + return true; +} + +mitk::NavigationToolStorage::Pointer mitk::PolhemusTrackingDevice::AutoDetectTools() +{ + this->OpenConnection(); + std::vector singeFrameData = this->m_Device->GetSingleFrame(); + MITK_INFO << "Found " << singeFrameData.size() << " tools."; + this->CloseConnection(); + mitk::NavigationToolStorage::Pointer returnValue = mitk::NavigationToolStorage::New(); + for each (mitk::PolhemusInterface::trackingData t in singeFrameData) + { + + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + std::stringstream name; + name << "Sensor-" << ((int)t.id); + newNode->SetName(name.str()); + + mitk::Surface::Pointer myCone = mitk::Surface::New(); + vtkConeSource *vtkData = vtkConeSource::New(); + vtkData->SetAngle(5.0); + vtkData->SetResolution(50); + vtkData->SetHeight(6.0f); + vtkData->SetRadius(2.0f); + vtkData->SetCenter(0.0, 0.0, 0.0); + vtkData->Update(); + myCone->SetVtkPolyData(vtkData->GetOutput()); + vtkData->Delete(); + newNode->SetData(myCone); + + mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New(); + newTool->SetDataNode(newNode); + + std::stringstream identifier; + identifier << "AutoDetectedTool-" << ((int)t.id); + newTool->SetIdentifier(identifier.str()); + + newTool->SetTrackingDeviceType(mitk::PolhemusTrackerTypeInformation::GetDeviceDataPolhemusTrackerLiberty().Line); + returnValue->AddTool(newTool); + } + return returnValue; + +} diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.h b/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.h new file mode 100644 index 0000000000..0d02827f2f --- /dev/null +++ b/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.h @@ -0,0 +1,145 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKPolhemusTRACKINGDEVICE_H_HEADER_INCLUDED_ +#define MITKPolhemusTRACKINGDEVICE_H_HEADER_INCLUDED_ + + +#include +#include +#include +#include +#include + +namespace mitk +{ + /** Documentation: + * \brief An object of this class represents Polhemus tracking device. You can add tools to this + * device, then open the connection and start tracking. The tracking device will then + * continuously update the tool coordinates. + * \ingroup IGT + */ + class MITKIGT_EXPORT PolhemusTrackingDevice : public TrackingDevice + { + public: + + mitkClassMacro(PolhemusTrackingDevice, TrackingDevice); + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /** + * \brief Starts the tracking. + * \return Returns true if the tracking is started. Throws an exception if an error occures. + * @throw mitk::IGTHardwareException Throws an exception if there is an error during start tracking. + */ + virtual bool StartTracking() override; + + /** + * \brief Stops the tracking. + * \return Returns true if the tracking is stopped. + */ + virtual bool StopTracking() override; + + /** + * \brief Opens the connection to the device. This have to be done before the tracking is started. + * @throw mitk::IGTHardwareException Throws an exception if there is an error during open connection. + */ + virtual bool OpenConnection() override; + + /** + * \brief Closes the connection and clears all resources. + */ + virtual bool CloseConnection() override; + + /** + * \return Returns the number of tools which have been added to the device. + */ + virtual unsigned int GetToolCount() const override; + + /** + * \param toolNumber The number of the tool which should be given back. + * \return Returns the tool which the number "toolNumber". Returns NULL, if there is + * no tool with this number. + */ + TrackingTool* GetTool(unsigned int toolNumber) const override; + + + /** + * \brief Create a new Polhemus tool with toolName and add it to the list of tools + * + * This method will create a new PolhemusTool object, + * set the tool name toolName and then add it to the list of tools. + * It returns a pointer of type mitk::TrackingTool to the tool + * that can be used to read tracking data from it. + * This is the only way to add tools to PolhemusTrackingDevice. + * + * \warning adding tools is not possible in tracking mode, only in setup and ready. + */ + mitk::TrackingTool* AddTool(const char* toolName); + + bool IsDeviceInstalled(); + + /** @return Returns true if this device can autodetects its tools. */ + virtual bool AutoDetectToolsAvailable(); + + /** Autodetects tools from this device and returns them as a navigation tool storage. + * @return Returns the detected tools. Returns an empty storage if no tools are present + * or if detection is not possible + */ + virtual mitk::NavigationToolStorage::Pointer AutoDetectTools(); + + /** Enables/disables hemisphere tracking for all sensors. */ + itkSetMacro(HemisphereTrackingEnabled, bool); + + protected: + PolhemusTrackingDevice(); + ~PolhemusTrackingDevice(); + + /** + * \brief Adds a tool to the tracking device. + * + * \param tool The tool which will be added. + * \return Returns true if the tool has been added, false otherwise. + */ + bool InternalAddTool(PolhemusTool::Pointer tool); + + /** + * \brief This method tracks tools as long as the variable m_Mode is set to "Tracking". + * Tracking tools means grabbing frames from the camera an updating the tools. + * @throw mitk::IGTHardwareException Throws an exception if there is an error during tracking of tools. + */ + void TrackTools(); + + /** + * \return Returns all tools of the tracking device. + */ + std::vector GetAllTools(); + + /** + * \return Gives back the device which is represented by an object of the class PolhemusInterface. + */ + PolhemusInterface* GetDevice(); + + static ITK_THREAD_RETURN_TYPE ThreadStartTracking(void* data); + + std::vector m_AllTools; ///< vector holding all tools + PolhemusInterface::Pointer m_Device; ///< represents the interface to the tracking hardware + itk::MultiThreader::Pointer m_MultiThreader; + int m_ThreadID; + bool m_HemisphereTrackingEnabled; + }; +}//mitk +#endif /* MITKPolhemusTRACKINGDEVICE_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/TrackingDevices/mitkTrackingDevice.cpp b/Modules/IGT/TrackingDevices/mitkTrackingDevice.cpp index ba47a9f700..dbb8bafa2d 100644 --- a/Modules/IGT/TrackingDevices/mitkTrackingDevice.cpp +++ b/Modules/IGT/TrackingDevices/mitkTrackingDevice.cpp @@ -1,138 +1,148 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTrackingDevice.h" #include "mitkIGTTimeStamp.h" #include "mitkTrackingTool.h" #include #include #include #include "mitkUnspecifiedTrackingTypeInformation.h" #include "mitkTrackingDeviceTypeCollection.h" typedef itk::MutexLockHolder MutexLockHolder; mitk::TrackingDevice::TrackingDevice() : m_Data(mitk::UnspecifiedTrackingTypeInformation::GetDeviceDataUnspecified()), m_State(mitk::TrackingDevice::Setup), m_StopTracking(false), m_RotationMode(mitk::TrackingDevice::RotationStandard) { m_StopTrackingMutex = itk::FastMutexLock::New(); m_StateMutex = itk::FastMutexLock::New(); m_TrackingFinishedMutex = itk::FastMutexLock::New(); } mitk::TrackingDevice::~TrackingDevice() { } bool mitk::TrackingDevice::IsDeviceInstalled() { return true; //this is the default for all tracking device //If a device needs installation please reimplement //this method in the subclass. } +bool mitk::TrackingDevice::AutoDetectToolsAvailable() +{ + return false; +} + +mitk::NavigationToolStorage::Pointer mitk::TrackingDevice::AutoDetectTools() +{ + return mitk::NavigationToolStorage::New(); +} + mitk::TrackingDevice::TrackingDeviceState mitk::TrackingDevice::GetState() const { MutexLockHolder lock(*m_StateMutex); return m_State; } void mitk::TrackingDevice::SetState( TrackingDeviceState state ) { itkDebugMacro("setting m_State to " << state); MutexLockHolder lock(*m_StateMutex); // lock and unlock the mutex if (m_State == state) { return; } m_State = state; this->Modified(); } void mitk::TrackingDevice::SetRotationMode(RotationMode r) { MITK_WARN << "Rotation mode switching is not implemented for this device. Leaving it at mitk::TrackingDevice::RotationStandard"; } mitk::TrackingDeviceType mitk::TrackingDevice::GetType() const{ return m_Data.Line; } void mitk::TrackingDevice::SetType(mitk::TrackingDeviceType deviceType){ us::ModuleContext* context = us::GetModuleContext(); std::vector > refs = context->GetServiceReferences(); if (refs.empty()) { MITK_ERROR << "No tracking device service found!"; } mitk::TrackingDeviceTypeCollection* deviceTypeCollection = context->GetService(refs.front()); m_Data = deviceTypeCollection->GetFirstCompatibleDeviceDataForLine(deviceType); } mitk::TrackingDeviceData mitk::TrackingDevice::GetData() const{ return m_Data; } void mitk::TrackingDevice::SetData(mitk::TrackingDeviceData data){ m_Data = data; } bool mitk::TrackingDevice::StopTracking() { if (this->GetState() == Tracking) // Only if the object is in the correct state { m_StopTrackingMutex->Lock(); // m_StopTracking is used by two threads, so we have to ensure correct thread handling m_StopTracking = true; m_StopTrackingMutex->Unlock(); //we have to wait here that the other thread recognizes the STOP-command and executes it m_TrackingFinishedMutex->Lock(); mitk::IGTTimeStamp::GetInstance()->Stop(this); // notify realtime clock // StopTracking was called, thus the mode should be changed back // to Ready now that the tracking loop has ended. this->SetState(Ready); m_TrackingFinishedMutex->Unlock(); } return true; } mitk::TrackingTool* mitk::TrackingDevice::GetToolByName( std::string name ) const { unsigned int toolCount = this->GetToolCount(); for (unsigned int i = 0; i < toolCount; ++i) if (name == this->GetTool(i)->GetToolName()) return this->GetTool(i); return nullptr; } diff --git a/Modules/IGT/TrackingDevices/mitkTrackingDevice.h b/Modules/IGT/TrackingDevices/mitkTrackingDevice.h index 4b47e4a53b..e58e014bc0 100644 --- a/Modules/IGT/TrackingDevices/mitkTrackingDevice.h +++ b/Modules/IGT/TrackingDevices/mitkTrackingDevice.h @@ -1,189 +1,199 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKTRACKINGDEVICE_H_HEADER_INCLUDED_C1C2FCD2 #define MITKTRACKINGDEVICE_H_HEADER_INCLUDED_C1C2FCD2 #include #include "itkObject.h" #include "mitkCommon.h" #include "mitkTrackingTypes.h" #include "itkFastMutexLock.h" +#include "mitkNavigationToolStorage.h" namespace mitk { class TrackingTool; // interface for a tool that can be tracked by the TrackingDevice /**Documentation * \brief Interface for all Tracking Devices * * Defines the methods that are common for all tracking devices. * * \ingroup IGT */ class MITKIGT_EXPORT TrackingDevice : public itk::Object { public: mitkClassMacroItkParent(TrackingDevice, itk::Object); /** Defines the rotation modes of this tracking device which results in different representations * of quaternions. * * - Standard: normal representation, rawdata from the device is not changed (DEFAULT) * * - Transposed: the rotation is stored transposed, which is (by mistake!) expected by some older MITK classes due * to an ambigious method naming in VNL. * * CAUTION: The rotation mode can only be changed for backward compatibility of old WRONG code. * PLEASE DO NOT CHANGE THE ROTATION MODE UNLESS YOU ARE KNOWING EXACTLY WHAT YOU ARE DOING! * * use SetRotationMode to change the mode. */ enum RotationMode {RotationStandard, RotationTransposed}; enum TrackingDeviceState {Setup, Ready, Tracking}; ///< Type for state variable. The trackingdevice is always in one of these states /** * \brief Opens a connection to the device * * This may only be called if there is currently no connection to the device. * If OpenConnection() is successful, the object will change from Setup state to Ready state */ virtual bool OpenConnection() = 0; /** * \brief Closes the connection to the device * * This may only be called if there is currently a connection to the device, but tracking is * not running (e.g. object is in Ready state) */ virtual bool CloseConnection() = 0; ///< Closes the connection with the device /** * \brief start retrieving tracking data from the device. * * This may only be called after the connection to the device has been established * with a call to OpenConnection() (E.g. object is in Ready mode). This will change the * object state from Ready to Tracking */ virtual bool StartTracking() = 0; /** * \brief stop retrieving tracking data from the device. * stop retrieving tracking data from the device. * This may only be called after StartTracking was called * (e.g. the object is in Tracking mode). * This will change the object state from Tracking to Ready. */ virtual bool StopTracking(); /** * \brief Return tool with index toolNumber * * tools are numbered from 0 to GetToolCount() - 1. */ virtual TrackingTool* GetTool(unsigned int toolNumber) const = 0; /** * \brief Returns the tool with the given tool name * * Note: subclasses can and should implement optimized versions of this method * \return the given tool or NULL if no tool with that name exists */ virtual mitk::TrackingTool* GetToolByName(std::string name) const; /** * \brief Returns number of tracking tools */ virtual unsigned int GetToolCount() const = 0; /** Sets the rotation mode of this class. See documentation of enum RotationMode for details * on the different modes. This method has to be implemented in a deriving class to become * functional / if different rotation modes should be supported. * CAUTION: The rotation mode can only be changed for backward compatibility of old WRONG code. * PLEASE DO NOT CHANGE THE ROTATION MODE UNLESS YOU ARE KNOWING EXACTLY WHAT YOU ARE DOING! */ virtual void SetRotationMode(RotationMode r); /** @return Returns the rotation mode of this class. See documentation of enum * RotationMode for details on the different modes. */ itkGetConstMacro(RotationMode,RotationMode); /** * \brief return current object state (Setup, Ready or Tracking) */ TrackingDeviceState GetState() const; /** * \brief Deprecated! Use the more specific getDeviceData instead. return device type identifier */ TrackingDeviceType GetType() const; /** * \brief Deprecated! Use the more specific setDeviceData instead. set device type */ void SetType(TrackingDeviceType type); /** * \brief return device data */ TrackingDeviceData GetData() const; /** * \brief set device type */ void SetData(TrackingDeviceData data); /** * @return Returns true if the device is installed on this system an can be used. * Installed means activated in MITK, in some cases this means the MITK * installation / build has to know the installation path of the device * libraries on this system. This path is usually given as cmake variable * during the build configuration in devellopers mode. If the device should * be available for end users with an installer the libraries can be included * into the installer or the installer has to be adapted such that it asks * for the path. * Returns fals if the device is not installed. It cannot be used on this build * in this case. * * Note that some tracking systems communicate via a standard interface (e.g., serial * port) and don't need any library or installation. These devices are always "installed". */ virtual bool IsDeviceInstalled(); + /** @return Returns true if this device can autodetects its tools. */ + virtual bool AutoDetectToolsAvailable(); + + /** Autodetects tools from this device and returns them as a navigation tool storage. + * @return Returns the detected tools. Returns an empty storage if no tools are present + * or if detection is not possible + */ + virtual mitk::NavigationToolStorage::Pointer AutoDetectTools(); + private: TrackingDeviceState m_State; ///< current object state (Setup, Ready or Tracking) protected: /** * \brief change object state */ void SetState(TrackingDeviceState state); TrackingDevice(); virtual ~TrackingDevice(); TrackingDeviceData m_Data; ///< current device Data bool m_StopTracking; ///< signal stop to tracking thread itk::FastMutexLock::Pointer m_StopTrackingMutex; ///< mutex to control access to m_StopTracking itk::FastMutexLock::Pointer m_TrackingFinishedMutex; ///< mutex to manage control flow of StopTracking() itk::FastMutexLock::Pointer m_StateMutex; ///< mutex to control access to m_State RotationMode m_RotationMode; ///< defines the rotation mode Standard or Transposed, Standard is default }; } // namespace mitk #endif /* MITKTRACKINGDEVICE_H_HEADER_INCLUDED_C1C2FCD2 */ diff --git a/Modules/IGT/autoload/DeviceRegistry/src/mitkIGTActivator.cpp b/Modules/IGT/autoload/DeviceRegistry/src/mitkIGTActivator.cpp index b5608a31ab..8e34c40cd4 100644 --- a/Modules/IGT/autoload/DeviceRegistry/src/mitkIGTActivator.cpp +++ b/Modules/IGT/autoload/DeviceRegistry/src/mitkIGTActivator.cpp @@ -1,63 +1,70 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ +#include "mitkIGTConfig.h" #include "mitkIGTActivator.h" //All Tracking devices, which should be available by default #include "mitkNDIAuroraTypeInformation.h" #include "mitkNDIPolarisTypeInformation.h" #include "mitkVirtualTrackerTypeInformation.h" #include "mitkMicronTrackerTypeInformation.h" #include "mitkNPOptitrackTrackingTypeInformation.h" #include "mitkOpenIGTLinkTypeInformation.h" +#ifdef MITK_USE_POLHEMUS_TRACKER +#include "mitkPolhemusTrackerTypeInformation.h" +#endif namespace mitk { IGTActivator::IGTActivator() { } IGTActivator::~IGTActivator() { } void IGTActivator::Load(us::ModuleContext*) { m_DeviceTypeCollection.RegisterTrackingDeviceType(new mitk::NDIAuroraTypeInformation()); m_DeviceTypeCollection.RegisterTrackingDeviceType(new mitk::NDIPolarisTypeInformation()); m_DeviceTypeCollection.RegisterTrackingDeviceType(new mitk::MicronTrackerTypeInformation()); m_DeviceTypeCollection.RegisterTrackingDeviceType(new mitk::NPOptitrackTrackingTypeInformation()); m_DeviceTypeCollection.RegisterTrackingDeviceType(new mitk::VirtualTrackerTypeInformation()); m_DeviceTypeCollection.RegisterTrackingDeviceType(new mitk::OpenIGTLinkTypeInformation()); - m_DeviceTypeCollection.RegisterAsMicroservice(); +#ifdef MITK_USE_POLHEMUS_TRACKER + m_DeviceTypeCollection.RegisterTrackingDeviceType(new mitk::PolhemusTrackerTypeInformation()); +#endif + m_DeviceTypeCollection.RegisterAsMicroservice(); } void IGTActivator::Unload(us::ModuleContext*) { try { m_DeviceTypeCollection.UnRegisterMicroservice(); } catch (std::exception& e) { MITK_WARN << "Unable to unregister IGT DeviceTypeCollection Microservice: "< +#include + +#include + +#include +#include +#include + +const std::string QmitkPolhemusTrackerWidget::VIEW_ID = "org.mitk.views.PolhemusTrackerWidget"; + +QmitkPolhemusTrackerWidget::QmitkPolhemusTrackerWidget(QWidget* parent, Qt::WindowFlags f) + : QmitkAbstractTrackingDeviceWidget(parent, f) + , m_Controls(nullptr) +{ +} +void QmitkPolhemusTrackerWidget::Initialize() +{ + InitializeSuperclassWidget(); + CreateQtPartControl(this); +} + +QmitkPolhemusTrackerWidget::~QmitkPolhemusTrackerWidget() +{ + delete m_Controls; +} + +void QmitkPolhemusTrackerWidget::CreateQtPartControl(QWidget *parent) +{ + if (!m_Controls) + { + // create GUI widgets + m_Controls = new Ui::QmitkPolhemusTrackerWidget; + m_Controls->setupUi(parent); + } +} + +void QmitkPolhemusTrackerWidget::CreateConnections() +{ + if (m_Controls) + { + + } +} + +mitk::TrackingDevice::Pointer QmitkPolhemusTrackerWidget::GetTrackingDevice() +{ + if (m_TrackingDevice.IsNull()) m_TrackingDevice = ConstructTrackingDevice(); + return m_TrackingDevice; +} + + +mitk::TrackingDevice::Pointer QmitkPolhemusTrackerWidget::ConstructTrackingDevice() +{ + mitk::PolhemusTrackingDevice::Pointer newDevice = mitk::PolhemusTrackingDevice::New(); + newDevice->SetHemisphereTrackingEnabled(m_Controls->m_hemisphereTracking->isChecked()); + return static_cast(newDevice); +} + + + +QmitkPolhemusTrackerWidget* QmitkPolhemusTrackerWidget::Clone(QWidget* parent) const +{ + QmitkPolhemusTrackerWidget* clonedWidget = new QmitkPolhemusTrackerWidget(parent); + clonedWidget->Initialize(); + return clonedWidget; +} diff --git a/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.h b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.h new file mode 100644 index 0000000000..dfd41ec261 --- /dev/null +++ b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.h @@ -0,0 +1,65 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkPolhemusTrackerWidget_H +#define QmitkPolhemusTrackerWidget_H + +#include "ui_QmitkPolhemusTrackerWidget.h" + +#include "QmitkAbstractTrackingDeviceWidget.h" + + +/** Documentation: + * \brief Implementation of a configuration widget for Polhemus Tracking Devices. + * + * \ingroup IGTUI + */ +class MITKIGTUI_EXPORT QmitkPolhemusTrackerWidget : public QmitkAbstractTrackingDeviceWidget +{ + Q_OBJECT // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) + +public: + static const std::string VIEW_ID; + + QmitkPolhemusTrackerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); + ~QmitkPolhemusTrackerWidget(); + + mitk::TrackingDevice::Pointer GetTrackingDevice(); + + virtual void Initialize(); + +signals: + +protected slots : + +private: + + /// \brief Creation of the connections + void CreateConnections(); + + void CreateQtPartControl(QWidget *parent); + +protected: + virtual QmitkPolhemusTrackerWidget* Clone(QWidget* parent) const; + + Ui::QmitkPolhemusTrackerWidget* m_Controls; + + mitk::TrackingDevice::Pointer m_TrackingDevice; + +public: + virtual mitk::TrackingDevice::Pointer ConstructTrackingDevice(); +}; +#endif diff --git a/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.ui b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.ui new file mode 100644 index 0000000000..9dee4ebd75 --- /dev/null +++ b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.ui @@ -0,0 +1,52 @@ + + + QmitkPolhemusTrackerWidget + + + + 0 + 0 + 475 + 181 + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Polhemus Tracker</span></p></body></html> + + + + + + + Enable hemisphere tracking + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/Modules/IGTUI/autoload/ConfigurationWidgetRegistry/src/mitkIGTUIActivator.cpp b/Modules/IGTUI/autoload/ConfigurationWidgetRegistry/src/mitkIGTUIActivator.cpp index c77300921b..4820db746c 100644 --- a/Modules/IGTUI/autoload/ConfigurationWidgetRegistry/src/mitkIGTUIActivator.cpp +++ b/Modules/IGTUI/autoload/ConfigurationWidgetRegistry/src/mitkIGTUIActivator.cpp @@ -1,70 +1,80 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ +#include "mitkIGTConfig.h" #include "mitkIGTUIActivator.h" //All Tracking devices, which should be available by default #include "mitkNDIAuroraTypeInformation.h" #include "mitkNDIPolarisTypeInformation.h" #include "mitkVirtualTrackerTypeInformation.h" #include "mitkMicronTrackerTypeInformation.h" #include "mitkNPOptitrackTrackingTypeInformation.h" #include "mitkOpenIGTLinkTypeInformation.h" //standard tracking devices, which always should be avaiable #include "QmitkNDIAuroraWidget.h" #include "QmitkNDIPolarisWidget.h" #include "QmitkMicronTrackerWidget.h" #include "QmitkNPOptitrackWidget.h" #include "QmitkVirtualTrackerWidget.h" #include "QmitkOpenIGTLinkWidget.h" +// Polhemus tracking device +#ifdef MITK_USE_POLHEMUS_TRACKER +#include "mitkPolhemusTrackerTypeInformation.h" +#include "QmitkPolhemusTrackerWidget.h" +#endif + namespace mitk { IGTUIActivator::IGTUIActivator() { } IGTUIActivator::~IGTUIActivator() { } void IGTUIActivator::Load(us::ModuleContext*) { m_DeviceWidgetCollection.RegisterAsMicroservice(); //Add widgets of standard tracking devices m_DeviceWidgetCollection.RegisterTrackingDeviceWidget(mitk::NDIAuroraTypeInformation::GetTrackingDeviceName(), new QmitkNDIAuroraWidget); m_DeviceWidgetCollection.RegisterTrackingDeviceWidget(mitk::NDIPolarisTypeInformation::GetTrackingDeviceName(), new QmitkNDIPolarisWidget); m_DeviceWidgetCollection.RegisterTrackingDeviceWidget(mitk::MicronTrackerTypeInformation::GetTrackingDeviceName(), new QmitkMicronTrackerWidget); m_DeviceWidgetCollection.RegisterTrackingDeviceWidget(mitk::NPOptitrackTrackingTypeInformation::GetTrackingDeviceName(), new QmitkNPOptitrackWidget); m_DeviceWidgetCollection.RegisterTrackingDeviceWidget(mitk::VirtualTrackerTypeInformation::GetTrackingDeviceName(), new QmitkVirtualTrackerWidget); m_DeviceWidgetCollection.RegisterTrackingDeviceWidget(mitk::OpenIGTLinkTypeInformation::GetTrackingDeviceName(), new QmitkOpenIGTLinkWidget); +#ifdef MITK_USE_POLHEMUS_TRACKER + m_DeviceWidgetCollection.RegisterTrackingDeviceWidget(mitk::PolhemusTrackerTypeInformation::GetTrackingDeviceName(), new QmitkPolhemusTrackerWidget); +#endif } void IGTUIActivator::Unload(us::ModuleContext*) { try { m_DeviceWidgetCollection.UnRegisterMicroservice(); } catch (std::exception& e) { MITK_WARN << "Unable to unregister IGTUI DeviceWidgetCollection Microservice: " << e.what(); } } } US_EXPORT_MODULE_ACTIVATOR(mitk::IGTUIActivator) \ No newline at end of file diff --git a/Modules/IGTUI/files.cmake b/Modules/IGTUI/files.cmake index a555fb4dea..9678e39cb4 100644 --- a/Modules/IGTUI/files.cmake +++ b/Modules/IGTUI/files.cmake @@ -1,108 +1,114 @@ set(CPP_FILES Qmitk/QmitkTrackingDeviceWidget.cpp Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp Qmitk/QmitkNDIConfigurationWidget.cpp Qmitk/QmitkFiducialRegistrationWidget.cpp Qmitk/QmitkNDIToolDelegate.cpp Qmitk/QmitkNavigationToolManagementWidget.cpp Qmitk/QmitkIGTLoggerWidget.cpp Qmitk/QmitkUpdateTimerWidget.cpp Qmitk/QmitkToolDistanceWidget.cpp Qmitk/QmitkToolTrackingStatusWidget.cpp Qmitk/QmitkTrackingSourcesCheckBoxPanelWidget.cpp Qmitk/QmitkIGTPlayerWidget.cpp Qmitk/QmitkIGTConnectionWidget.cpp Qmitk/QmitkToolSelectionWidget.cpp Qmitk/QmitkNavigationToolCreationWidget.cpp Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp Qmitk/QmitkInteractiveTransformationWidget.cpp Qmitk/QmitkNavigationToolStorageSelectionWidget.cpp Qmitk/QmitkNavigationDataPlayerControlWidget.cpp Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.cpp Qmitk/QmitkNDIAuroraWidget.cpp Qmitk/QmitkNDIPolarisWidget.cpp Qmitk/QmitkMicronTrackerWidget.cpp Qmitk/QmitkNPOptitrackWidget.cpp Qmitk/QmitkVirtualTrackerWidget.cpp Qmitk/QmitkOpenIGTLinkWidget.cpp Qmitk/mitkTrackingDeviceWidgetCollection.cpp Qmitk/QmitkTrackingDeviceConfigurationWidgetScanPortsWorker.cpp Qmitk/QmitkTrackingDeviceConfigurationWidgetConnectionWorker.cpp Qmitk/QmitkNDIAbstractDeviceWidget.cpp Qmitk/QmitkAbstractTrackingDeviceWidget.cpp ) set(UI_FILES Qmitk/QmitkNavigationToolManagementWidgetControls.ui Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui Qmitk/QmitkNDIConfigurationWidget.ui Qmitk/QmitkFiducialRegistrationWidget.ui Qmitk/QmitkIGTLoggerWidgetControls.ui Qmitk/QmitkUpdateTimerWidgetControls.ui Qmitk/QmitkToolDistanceWidgetControls.ui Qmitk/QmitkToolTrackingStatusWidgetControls.ui Qmitk/QmitkTrackingSourcesCheckBoxPanelWidgetControls.ui Qmitk/QmitkIGTPlayerWidgetControls.ui Qmitk/QmitkIGTConnectionWidgetControls.ui Qmitk/QmitkToolSelectionWidgetControls.ui Qmitk/QmitkNavigationToolCreationWidget.ui Qmitk/QmitkNavigationToolCreationAdvancedWidgetControls.ui Qmitk/QmitkNavigationDataSourceSelectionWidgetControls.ui Qmitk/QmitkInteractiveTransformationWidgetControls.ui Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui Qmitk/QmitkNavigationDataPlayerControlWidget.ui Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.ui Qmitk/QmitkNDIAuroraWidget.ui Qmitk/QmitkNDIPolarisWidget.ui Qmitk/QmitkMicronTrackerWidget.ui Qmitk/QmitkNPOptitrackWidget.ui Qmitk/QmitkVirtualTrackerWidget.ui Qmitk/QmitkOpenIGTLinkWidget.ui ) set(MOC_H_FILES Qmitk/QmitkNavigationToolManagementWidget.h Qmitk/QmitkTrackingDeviceWidget.h Qmitk/QmitkTrackingDeviceConfigurationWidget.h Qmitk/QmitkNDIConfigurationWidget.h Qmitk/QmitkFiducialRegistrationWidget.h Qmitk/QmitkNDIToolDelegate.h Qmitk/QmitkIGTLoggerWidget.h Qmitk/QmitkUpdateTimerWidget.h Qmitk/QmitkToolDistanceWidget.h Qmitk/QmitkToolTrackingStatusWidget.h Qmitk/QmitkTrackingSourcesCheckBoxPanelWidget.h Qmitk/QmitkIGTPlayerWidget.h Qmitk/QmitkIGTConnectionWidget.h Qmitk/QmitkToolSelectionWidget.h Qmitk/QmitkNavigationToolCreationWidget.h Qmitk/QmitkNavigationToolCreationAdvancedWidget.h Qmitk/QmitkNavigationDataSourceSelectionWidget.h Qmitk/QmitkInteractiveTransformationWidget.h Qmitk/QmitkNavigationToolStorageSelectionWidget.h Qmitk/QmitkNavigationDataPlayerControlWidget.h Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.h Qmitk/QmitkNDIAuroraWidget.h Qmitk/QmitkNDIPolarisWidget.h Qmitk/QmitkMicronTrackerWidget.h Qmitk/QmitkNPOptitrackWidget.h Qmitk/QmitkVirtualTrackerWidget.h Qmitk/QmitkOpenIGTLinkWidget.h Qmitk/QmitkTrackingDeviceConfigurationWidgetScanPortsWorker.h Qmitk/QmitkTrackingDeviceConfigurationWidgetConnectionWorker.h Qmitk/QmitkNDIAbstractDeviceWidget.h Qmitk/QmitkAbstractTrackingDeviceWidget.h ) +if(MITK_USE_POLHEMUS_TRACKER) + set(CPP_FILES ${CPP_FILES} Qmitk/QmitkPolhemusTrackerWidget.cpp) + set(UI_FILES ${UI_FILES} Qmitk/QmitkPolhemusTrackerWidget.ui) + set(MOC_H_FILES ${MOC_H_FILES} Qmitk/QmitkPolhemusTrackerWidget.h) +endif(MITK_USE_POLHEMUS_TRACKER) + set(QRC_FILES resources/IGTUI.qrc ) diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp index b7b6bf2b04..749aabdb59 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp @@ -1,1531 +1,1451 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkMITKIGTTrackingToolboxView.h" #include "QmitkTrackingDeviceConfigurationWidget.h" #include "QmitkStdMultiWidget.h" // Qt #include #include #include // MITK #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkNDIAuroraTypeInformation.h" // vtk #include //for exceptions #include #include //for Microservice #include "mitkPluginActivator.h" #include #include #include "usServiceReference.h" const std::string QmitkMITKIGTTrackingToolboxView::VIEW_ID = "org.mitk.views.mitkigttrackingtoolbox"; QmitkMITKIGTTrackingToolboxView::QmitkMITKIGTTrackingToolboxView() : QmitkFunctionality() , m_Controls(nullptr) , m_MultiWidget(nullptr) , m_DeviceTypeCollection(nullptr) { m_TrackingLoggingTimer = new QTimer(this); m_TrackingRenderTimer = new QTimer(this); m_TimeoutTimer = new QTimer(this); m_tracking = false; m_connected = false; m_logging = false; m_loggedFrames = 0; //create filename for autosaving of tool storage QString loggingPathWithoutFilename = QString(mitk::LoggingBackend::GetLogFile().c_str()); if (!loggingPathWithoutFilename.isEmpty()) //if there already is a path for the MITK logging file use this one { //extract path from path+filename (if someone knows a better way to do this feel free to change it) int lengthOfFilename = QFileInfo(QString::fromStdString(mitk::LoggingBackend::GetLogFile())).fileName().size(); loggingPathWithoutFilename.resize(loggingPathWithoutFilename.size() - lengthOfFilename); m_AutoSaveFilename = loggingPathWithoutFilename + "TrackingToolboxAutoSave.IGTToolStorage"; } else //if not: use a temporary path from IOUtil { m_AutoSaveFilename = QString(mitk::IOUtil::GetTempPath().c_str()) + "TrackingToolboxAutoSave.IGTToolStorage"; } MITK_INFO("IGT Tracking Toolbox") << "Filename for auto saving of IGT ToolStorages: " << m_AutoSaveFilename.toStdString(); //! [Thread 1] //initialize worker thread m_WorkerThread = new QThread(); m_Worker = new QmitkMITKIGTTrackingToolboxViewWorker(); //! [Thread 1] ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext(); if (pluginContext) { QString interfaceName = QString::fromStdString(us_service_interface_iid()); QList serviceReference = pluginContext->getServiceReferences(interfaceName); if (serviceReference.size() > 0) { m_DeviceTypeServiceReference = serviceReference.at(0); const ctkServiceReference& r = serviceReference.at(0); m_DeviceTypeCollection = pluginContext->getService(r); } else { MITK_INFO << "No Tracking Device Collection!"; } } } QmitkMITKIGTTrackingToolboxView::~QmitkMITKIGTTrackingToolboxView() { this->StoreUISettings(); m_TrackingLoggingTimer->stop(); m_TrackingRenderTimer->stop(); m_TimeoutTimer->stop(); delete m_TrackingLoggingTimer; delete m_TrackingRenderTimer; delete m_TimeoutTimer; try { //! [Thread 2] // wait for thread to finish m_WorkerThread->terminate(); m_WorkerThread->wait(); //clean up worker thread if (m_WorkerThread) { delete m_WorkerThread; } if (m_Worker) { delete m_Worker; } //! [Thread 2] //remove the tracking volume this->GetDataStorage()->Remove(m_TrackingVolumeNode); //unregister microservices if (m_toolStorage) { m_toolStorage->UnRegisterMicroservice(); } if (m_TrackingDeviceSource) { m_TrackingDeviceSource->UnRegisterMicroservice(); } if (m_IGTLMessageProvider.IsNotNull()){ m_IGTLMessageProvider->UnRegisterMicroservice(); } } catch (std::exception& e) { MITK_WARN << "Unexpected exception during clean up of tracking toolbox view: " << e.what(); } catch (...) { MITK_WARN << "Unexpected unknown error during clean up of tracking toolbox view!"; } //store tool storage and UI settings for persistence this->AutoSaveToolStorage(); this->StoreUISettings(); m_DeviceTypeCollection = nullptr; mitk::PluginActivator::GetContext()->ungetService(m_DeviceTypeServiceReference); } void QmitkMITKIGTTrackingToolboxView::CreateQtPartControl(QWidget *parent) { // build up qt view, unless already done if (!m_Controls) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkMITKIGTTrackingToolboxViewControls; m_Controls->setupUi(parent); //create connections connect(m_Controls->m_LoadTools, SIGNAL(clicked()), this, SLOT(OnLoadTools())); connect(m_Controls->m_ConnectDisconnectButton, SIGNAL(clicked()), this, SLOT(OnConnectDisconnect())); connect(m_Controls->m_StartStopTrackingButton, SIGNAL(clicked()), this, SLOT(OnStartStopTracking())); connect(m_Controls->m_FreezeUnfreezeTrackingButton, SIGNAL(clicked()), this, SLOT(OnFreezeUnfreezeTracking())); connect(m_TrackingLoggingTimer, SIGNAL(timeout()), this, SLOT(UpdateLoggingTrackingTimer())); connect(m_TrackingRenderTimer, SIGNAL(timeout()), this, SLOT(UpdateRenderTrackingTimer())); connect(m_TimeoutTimer, SIGNAL(timeout()), this, SLOT(OnTimeOut())); connect(m_Controls->m_ChooseFile, SIGNAL(clicked()), this, SLOT(OnChooseFileClicked())); connect(m_Controls->m_StartLogging, SIGNAL(clicked()), this, SLOT(StartLogging())); connect(m_Controls->m_StopLogging, SIGNAL(clicked()), this, SLOT(StopLogging())); connect(m_Controls->m_VolumeSelectionBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(OnTrackingVolumeChanged(QString))); connect(m_Controls->m_ShowTrackingVolume, SIGNAL(clicked()), this, SLOT(OnShowTrackingVolumeChanged())); connect(m_Controls->m_AutoDetectTools, SIGNAL(clicked()), this, SLOT(OnAutoDetectTools())); connect(m_Controls->m_ResetTools, SIGNAL(clicked()), this, SLOT(OnResetTools())); connect(m_Controls->m_AddSingleTool, SIGNAL(clicked()), this, SLOT(OnAddSingleTool())); connect(m_Controls->m_NavigationToolCreationWidget, SIGNAL(NavigationToolFinished()), this, SLOT(OnAddSingleToolFinished())); connect(m_Controls->m_NavigationToolCreationWidget, SIGNAL(Canceled()), this, SLOT(OnAddSingleToolCanceled())); connect(m_Controls->m_csvFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension())); connect(m_Controls->m_xmlFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension())); connect(m_Controls->m_UseDifferentUpdateRates, SIGNAL(clicked()), this, SLOT(OnToggleDifferentUpdateRates())); connect(m_Controls->m_RenderUpdateRate, SIGNAL(valueChanged(int)), this, SLOT(OnChangeRenderUpdateRate())); connect(m_Controls->m_DisableAllTimers, SIGNAL(stateChanged(int)), this, SLOT(EnableDisableTimerButtons(int))); //connections for the tracking device configuration widget connect(m_Controls->m_configurationWidget, SIGNAL(TrackingDeviceSelectionChanged()), this, SLOT(OnTrackingDeviceChanged())); //! [Thread 3] //connect worker thread connect(m_Worker, SIGNAL(AutoDetectToolsFinished(bool, QString)), this, SLOT(OnAutoDetectToolsFinished(bool, QString))); connect(m_Worker, SIGNAL(ConnectDeviceFinished(bool, QString)), this, SLOT(OnConnectFinished(bool, QString))); connect(m_Worker, SIGNAL(StartTrackingFinished(bool, QString)), this, SLOT(OnStartTrackingFinished(bool, QString))); connect(m_Worker, SIGNAL(StopTrackingFinished(bool, QString)), this, SLOT(OnStopTrackingFinished(bool, QString))); connect(m_Worker, SIGNAL(DisconnectDeviceFinished(bool, QString)), this, SLOT(OnDisconnectFinished(bool, QString))); connect(m_WorkerThread, SIGNAL(started()), m_Worker, SLOT(ThreadFunc())); //move the worker to the thread m_Worker->moveToThread(m_WorkerThread); //! [Thread 3] //initialize widgets m_Controls->m_TrackingToolsStatusWidget->SetShowPositions(true); m_Controls->m_TrackingToolsStatusWidget->SetTextAlignment(Qt::AlignLeft); //initialize tracking volume node m_TrackingVolumeNode = mitk::DataNode::New(); m_TrackingVolumeNode->SetName("TrackingVolume"); m_TrackingVolumeNode->SetBoolProperty("Backface Culling", true); mitk::Color red; red.SetRed(1); m_TrackingVolumeNode->SetColor(red); //initialize buttons m_Controls->m_AutoDetectTools->setVisible(false); //only visible if tracking device is Aurora m_Controls->m_StartStopTrackingButton->setEnabled(false); m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(false); //initialize warning labels m_Controls->m_renderWarningLabel->setVisible(false); m_Controls->m_TrackingFrozenLabel->setVisible(false); //Update List of available models for selected tool. std::vector Compatibles; if ((m_Controls == NULL) || //check all these stuff for NULL, latterly this causes crashes from time to time (m_Controls->m_configurationWidget == NULL) || (m_Controls->m_configurationWidget->GetTrackingDevice().IsNull())) { MITK_ERROR << "Couldn't get current tracking device or an object is NULL, something went wrong!"; return; } else { Compatibles = m_DeviceTypeCollection->GetDeviceDataForLine(m_Controls->m_configurationWidget->GetTrackingDevice()->GetType()); } m_Controls->m_VolumeSelectionBox->clear(); for (std::size_t i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } //initialize tool storage m_toolStorage = mitk::NavigationToolStorage::New(GetDataStorage()); m_toolStorage->SetName("TrackingToolbox Default Storage"); m_toolStorage->RegisterAsMicroservice("no tracking device"); //set home directory as default path for logfile m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(QDir::homePath()) + QDir::separator() + "logfile.csv"); //tracking device may be changed already by the persistence of the //QmitkTrackingDeciveConfigurationWidget this->OnTrackingDeviceChanged(); this->LoadUISettings(); //add tracking volume node only to data storage this->GetDataStorage()->Add(m_TrackingVolumeNode); if (!m_Controls->m_ShowTrackingVolume->isChecked()) m_TrackingVolumeNode->SetOpacity(0.0); else m_TrackingVolumeNode->SetOpacity(0.25); //Update List of available models for selected tool. m_Controls->m_VolumeSelectionBox->clear(); for (std::size_t i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } } } void QmitkMITKIGTTrackingToolboxView::StdMultiWidgetAvailable(QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkMITKIGTTrackingToolboxView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkMITKIGTTrackingToolboxView::OnLoadTools() { //read in filename QString filename = QFileDialog::getOpenFileName(NULL, tr("Open Tool Storage"), "/", tr("Tool Storage Files (*.IGTToolStorage)")); if (filename.isNull()) return; //read tool storage from disk std::string errorMessage = ""; mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(GetDataStorage()); // try-catch block for exceptions try { this->ReplaceCurrentToolStorage(myDeserializer->Deserialize(filename.toStdString()), filename.toStdString()); } catch (mitk::IGTException) { std::string errormessage = "Error during loading the tool storage file. Please only load tool storage files created with the NavigationToolManager view."; QMessageBox::warning(NULL, "Tool Storage Loading Error", errormessage.c_str()); return; } if (m_toolStorage->isEmpty()) { errorMessage = myDeserializer->GetErrorMessage(); MessageBox(errorMessage); return; } //update label UpdateToolStorageLabel(filename); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); //save filename for persistent storage m_ToolStorageFilename = filename; } void QmitkMITKIGTTrackingToolboxView::OnResetTools() { this->ReplaceCurrentToolStorage(mitk::NavigationToolStorage::New(GetDataStorage()), "TrackingToolbox Default Storage"); m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); QString toolLabel = QString(""); m_Controls->m_toolLabel->setText(toolLabel); m_ToolStorageFilename = ""; } void QmitkMITKIGTTrackingToolboxView::OnStartStopTracking() { if (!m_connected) { MITK_WARN << "Can't start tracking if no device is connected. Aborting"; return; } if (m_tracking) { OnStopTracking(); } else { OnStartTracking(); } } void QmitkMITKIGTTrackingToolboxView::OnFreezeUnfreezeTracking() { if (m_Controls->m_FreezeUnfreezeTrackingButton->text() == "Freeze Tracking") { m_TrackingDeviceSource->Freeze(); m_Controls->m_FreezeUnfreezeTrackingButton->setText("Unfreeze Tracking"); m_Controls->m_TrackingFrozenLabel->setVisible(true); } else if (m_Controls->m_FreezeUnfreezeTrackingButton->text() == "Unfreeze Tracking") { m_TrackingDeviceSource->UnFreeze(); m_Controls->m_FreezeUnfreezeTrackingButton->setText("Freeze Tracking"); m_Controls->m_TrackingFrozenLabel->setVisible(false); } } void QmitkMITKIGTTrackingToolboxView::OnConnectDisconnect() { if (m_connected) { OnDisconnect(); } else { OnConnect(); } } void QmitkMITKIGTTrackingToolboxView::OnConnect() { MITK_INFO << "Connect Clicked"; //check if everything is ready to start tracking if (this->m_toolStorage.IsNull()) { MessageBox("Error: No Tools Loaded Yet!"); return; } else if (this->m_toolStorage->GetToolCount() == 0) { MessageBox("Error: No Way To Track Without Tools!"); return; } //parse tracking device data mitk::TrackingDeviceData data = mitk::UnspecifiedTrackingTypeInformation::GetDeviceDataUnspecified(); QString qstr = m_Controls->m_VolumeSelectionBox->currentText(); if ((!qstr.isNull()) || (!qstr.isEmpty())) { std::string str = qstr.toStdString(); data = m_DeviceTypeCollection->GetDeviceDataByName(str); //Data will be set later, after device generation } //! [Thread 4] //initialize worker thread m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eConnectDevice); m_Worker->SetTrackingDevice(this->m_Controls->m_configurationWidget->GetTrackingDevice()); m_Worker->SetInverseMode(m_Controls->m_InverseMode->isChecked()); m_Worker->SetNavigationToolStorage(this->m_toolStorage); m_Worker->SetTrackingDeviceData(data); //start worker thread m_WorkerThread->start(); //! [Thread 4] //disable buttons this->m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::EnableDisableTimerButtons(int enable) { bool enableBool = enable; m_Controls->m_UpdateRateOptionsGroupBox->setEnabled(!enableBool); m_Controls->m_renderWarningLabel->setVisible(enableBool); } void QmitkMITKIGTTrackingToolboxView::OnConnectFinished(bool success, QString errorMessage) { m_WorkerThread->quit(); m_WorkerThread->wait(); //enable buttons this->m_Controls->m_MainWidget->setEnabled(true); if (!success) { MITK_WARN << errorMessage.toStdString(); MessageBox(errorMessage.toStdString()); return; } //! [Thread 6] //get data from worker thread m_TrackingDeviceSource = m_Worker->GetTrackingDeviceSource(); m_TrackingDeviceData = m_Worker->GetTrackingDeviceData(); m_ToolVisualizationFilter = m_Worker->GetToolVisualizationFilter(); //! [Thread 6] //enable/disable Buttons DisableOptionsButtons(); DisableTrackingConfigurationButtons(); m_Controls->m_TrackingControlLabel->setText("Status: connected"); m_Controls->m_ConnectDisconnectButton->setText("Disconnect"); m_Controls->m_StartStopTrackingButton->setEnabled(true); m_connected = true; } void QmitkMITKIGTTrackingToolboxView::OnDisconnect() { m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eDisconnectDevice); m_WorkerThread->start(); m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::OnDisconnectFinished(bool success, QString errorMessage) { m_WorkerThread->quit(); m_WorkerThread->wait(); m_Controls->m_MainWidget->setEnabled(true); if (!success) { MITK_WARN << errorMessage.toStdString(); MessageBox(errorMessage.toStdString()); return; } //enable/disable Buttons m_Controls->m_StartStopTrackingButton->setEnabled(false); EnableOptionsButtons(); EnableTrackingConfigurationButtons(); m_Controls->m_TrackingControlLabel->setText("Status: disconnected"); m_Controls->m_ConnectDisconnectButton->setText("Connect"); m_Controls->m_FreezeUnfreezeTrackingButton->setText("Freeze Tracking"); m_Controls->m_TrackingFrozenLabel->setVisible(false); m_connected = false; } void QmitkMITKIGTTrackingToolboxView::OnStartTracking() { //show tracking volume this->OnTrackingVolumeChanged(m_Controls->m_VolumeSelectionBox->currentText()); //Reset the view to a defined start. Do it here and not in OnStartTrackingFinished, to give other tracking devices the chance to reset the view to a different direction. this->GlobalReinit(); m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eStartTracking); m_WorkerThread->start(); this->m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::OnStartTrackingFinished(bool success, QString errorMessage) { //! [Thread 5] m_WorkerThread->quit(); m_WorkerThread->wait(); //! [Thread 5] this->m_Controls->m_MainWidget->setEnabled(true); if (!success) { MessageBox(errorMessage.toStdString()); MITK_WARN << errorMessage.toStdString(); return; } if (!(m_Controls->m_DisableAllTimers->isChecked())) { if (m_Controls->m_UseDifferentUpdateRates->isChecked()) { if (m_Controls->m_RenderUpdateRate->value() != 0) m_TrackingRenderTimer->start(1000 / (m_Controls->m_RenderUpdateRate->value())); m_TrackingLoggingTimer->start(1000 / (m_Controls->m_LogUpdateRate->value())); } else { m_TrackingRenderTimer->start(1000 / (m_Controls->m_UpdateRate->value())); m_TrackingLoggingTimer->start(1000 / (m_Controls->m_UpdateRate->value())); } } m_Controls->m_TrackingControlLabel->setText("Status: tracking"); //connect the tool visualization widget for (std::size_t i = 0; i < m_TrackingDeviceSource->GetNumberOfOutputs(); i++) { m_Controls->m_TrackingToolsStatusWidget->AddNavigationData(m_TrackingDeviceSource->GetOutput(i)); } m_Controls->m_TrackingToolsStatusWidget->ShowStatusLabels(); if (m_Controls->m_ShowToolQuaternions->isChecked()) { m_Controls->m_TrackingToolsStatusWidget->SetShowQuaternions(true); } else { m_Controls->m_TrackingToolsStatusWidget->SetShowQuaternions(false); } //if activated enable open IGT link microservice if (m_Controls->m_EnableOpenIGTLinkMicroService->isChecked()) { //create convertion filter m_IGTLConversionFilter = mitk::NavigationDataToIGTLMessageFilter::New(); m_IGTLConversionFilter->SetName("IGT Tracking Toolbox"); m_IGTLConversionFilter->ConnectTo(m_ToolVisualizationFilter); m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendTDataMsg); m_IGTLConversionFilter->RegisterAsMicroservice(); //create server and message provider m_IGTLServer = mitk::IGTLServer::New(false); m_IGTLServer->SetName("Tracking Toolbox IGTL Server"); m_IGTLMessageProvider = mitk::IGTLMessageProvider::New(); m_IGTLMessageProvider->SetIGTLDevice(m_IGTLServer); m_IGTLMessageProvider->RegisterAsMicroservice(); } m_tracking = true; m_Controls->m_ConnectDisconnectButton->setEnabled(false); m_Controls->m_StartStopTrackingButton->setText("Stop Tracking"); m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::OnStopTracking() { if (!m_tracking) return; m_TrackingRenderTimer->stop(); m_TrackingLoggingTimer->stop(); m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eStopTracking); m_WorkerThread->start(); m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::OnStopTrackingFinished(bool success, QString errorMessage) { m_WorkerThread->quit(); m_WorkerThread->wait(); m_Controls->m_MainWidget->setEnabled(true); if (!success) { MessageBox(errorMessage.toStdString()); MITK_WARN << errorMessage.toStdString(); return; } m_Controls->m_TrackingControlLabel->setText("Status: connected"); if (m_logging) StopLogging(); m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); m_tracking = false; m_Controls->m_StartStopTrackingButton->setText("Start Tracking"); m_Controls->m_ConnectDisconnectButton->setEnabled(true); m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(false); //unregister open IGT link micro service if (m_Controls->m_EnableOpenIGTLinkMicroService->isChecked()) { m_IGTLConversionFilter->UnRegisterMicroservice(); m_IGTLMessageProvider->UnRegisterMicroservice(); } } void QmitkMITKIGTTrackingToolboxView::OnTrackingDeviceChanged() { mitk::TrackingDeviceType Type; if (m_Controls->m_configurationWidget->GetTrackingDevice().IsNotNull()) { Type = m_Controls->m_configurationWidget->GetTrackingDevice()->GetType(); //enable controls because device is valid m_Controls->m_TrackingToolsGoupBox->setEnabled(true); m_Controls->m_TrackingControlsGroupBox->setEnabled(true); } else { Type = mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName(); MessageBox("Error: This tracking device is not included in this project. Please make sure that the device is installed and activated in your MITK build."); m_Controls->m_TrackingToolsGoupBox->setEnabled(false); m_Controls->m_TrackingControlsGroupBox->setEnabled(false); return; } // Code to enable/disable device specific buttons + if (m_Controls->m_configurationWidget->GetTrackingDevice()->AutoDetectToolsAvailable()) + { m_Controls->m_AutoDetectTools->setVisible(true); } + else + { m_Controls->m_AutoDetectTools->setVisible(false); } + if (Type == mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) //Aurora - { - m_Controls->m_AutoDetectTools->setVisible(true); - m_Controls->m_AddSingleTool->setEnabled(false); - } - else //Polaris or Microntracker - { - m_Controls->m_AutoDetectTools->setVisible(false); - m_Controls->m_AddSingleTool->setEnabled(true); - } + { m_Controls->m_AddSingleTool->setEnabled(false);} + else //other trackers + { m_Controls->m_AddSingleTool->setEnabled(true); } // Code to select appropriate tracking volume for current type std::vector Compatibles = m_DeviceTypeCollection->GetDeviceDataForLine(Type); m_Controls->m_VolumeSelectionBox->clear(); for (std::size_t i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } } void QmitkMITKIGTTrackingToolboxView::OnTrackingVolumeChanged(QString qstr) { if (qstr.isNull()) return; if (qstr.isEmpty()) return; mitk::TrackingVolumeGenerator::Pointer volumeGenerator = mitk::TrackingVolumeGenerator::New(); std::string str = qstr.toStdString(); mitk::TrackingDeviceData data = m_DeviceTypeCollection->GetDeviceDataByName(str); m_TrackingDeviceData = data; volumeGenerator->SetTrackingDeviceData(data); volumeGenerator->Update(); mitk::Surface::Pointer volumeSurface = volumeGenerator->GetOutput(); m_TrackingVolumeNode->SetData(volumeSurface); if (!m_Controls->m_ShowTrackingVolume->isChecked()) m_TrackingVolumeNode->SetOpacity(0.0); else m_TrackingVolumeNode->SetOpacity(0.25); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnShowTrackingVolumeChanged() { if (m_Controls->m_ShowTrackingVolume->isChecked()) { OnTrackingVolumeChanged(m_Controls->m_VolumeSelectionBox->currentText()); m_TrackingVolumeNode->SetOpacity(0.25); } else { m_TrackingVolumeNode->SetOpacity(0.0); } } void QmitkMITKIGTTrackingToolboxView::OnAutoDetectTools() { - if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() == mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) + if (m_Controls->m_configurationWidget->GetTrackingDevice()->AutoDetectToolsAvailable()) { DisableTrackingConfigurationButtons(); m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eAutoDetectTools); m_Worker->SetTrackingDevice(m_Controls->m_configurationWidget->GetTrackingDevice().GetPointer()); m_Worker->SetDataStorage(this->GetDataStorage()); m_WorkerThread->start(); m_TimeoutTimer->start(5000); - MITK_INFO << "Timeout Timer started"; //disable controls until worker thread is finished this->m_Controls->m_MainWidget->setEnabled(false); } } void QmitkMITKIGTTrackingToolboxView::OnAutoDetectToolsFinished(bool success, QString errorMessage) { m_TimeoutTimer->stop(); m_WorkerThread->quit(); m_WorkerThread->wait(); //enable controls again this->m_Controls->m_MainWidget->setEnabled(true); EnableTrackingConfigurationButtons(); if (!success) { MITK_WARN << errorMessage.toStdString(); MessageBox(errorMessage.toStdString()); EnableTrackingConfigurationButtons(); return; } mitk::NavigationToolStorage::Pointer autoDetectedStorage = m_Worker->GetNavigationToolStorage(); //save detected tools this->ReplaceCurrentToolStorage(autoDetectedStorage, "Autodetected NDI Aurora Storage"); //auto save the new storage to hard disc (for persistence) AutoSaveToolStorage(); //update label QString toolLabel = QString("Loaded Tools: ") + QString::number(m_toolStorage->GetToolCount()) + " Tools (Auto Detected)"; m_Controls->m_toolLabel->setText(toolLabel); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); EnableTrackingConfigurationButtons(); - if (m_toolStorage->GetToolCount() > 0) - { - //ask the user if he wants to save the detected tools - QMessageBox msgBox; - switch (m_toolStorage->GetToolCount()) - { - case 1: - msgBox.setText("Found one tool!"); - break; - default: - msgBox.setText("Found " + QString::number(m_toolStorage->GetToolCount()) + " tools!"); - } - msgBox.setInformativeText("Do you want to save this tools as tool storage, so you can load them again?"); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - int ret = msgBox.exec(); - - if (ret == 16384) //yes - { - //ask the user for a filename - QString fileName = QFileDialog::getSaveFileName(NULL, tr("Save File"), "/", tr("*.IGTToolStorage")); - //check for empty filename - if (fileName == "") { return; } - mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); - - //when Serialize method is used exceptions are thrown, need to be adapted - //try-catch block for exception handling in Serializer - try - { - mySerializer->Serialize(fileName.toStdString(), m_toolStorage); - } - catch (mitk::IGTException) - { - std::string errormessage = "Error during serialization. Please check the Zip file."; - QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); - } - - return; - } - else if (ret == 65536) //no - { - return; - } - } //print a logging message about the detected tools switch (m_toolStorage->GetToolCount()) { case 0: MITK_INFO("IGT Tracking Toolbox") << "Found no tools. Empty ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString(); break; case 1: MITK_INFO("IGT Tracking Toolbox") << "Found one tool. ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString(); break; default: MITK_INFO("IGT Tracking Toolbox") << "Found " << m_toolStorage->GetToolCount() << " tools. ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString(); } } void QmitkMITKIGTTrackingToolboxView::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkMITKIGTTrackingToolboxView::UpdateRenderTrackingTimer() { //update filter m_ToolVisualizationFilter->Update(); MITK_DEBUG << "Number of outputs ToolVisualizationFilter: " << m_ToolVisualizationFilter->GetNumberOfIndexedOutputs(); MITK_DEBUG << "Number of inputs ToolVisualizationFilter: " << m_ToolVisualizationFilter->GetNumberOfIndexedInputs(); //update tool colors to show tool status for (unsigned int i = 0; i < m_ToolVisualizationFilter->GetNumberOfIndexedOutputs(); i++) { mitk::NavigationData::Pointer currentTool = m_ToolVisualizationFilter->GetOutput(i); if (currentTool->IsDataValid()) { this->m_toolStorage->GetTool(i)->GetDataNode()->SetColor(mitk::IGTColor_VALID); } else { this->m_toolStorage->GetTool(i)->GetDataNode()->SetColor(mitk::IGTColor_WARNING); } } //refresh view and status widget mitk::RenderingManager::GetInstance()->RequestUpdateAll(); m_Controls->m_TrackingToolsStatusWidget->Refresh(); //code to better isolate bug 17713, could be removed when bug 17713 is fixed static int i = 0; static mitk::Point3D lastPositionTool1 = m_ToolVisualizationFilter->GetOutput(0)->GetPosition(); static itk::TimeStamp lastTimeStamp = m_ToolVisualizationFilter->GetOutput(0)->GetTimeStamp(); i++; //every 20 frames: check if tracking is frozen if (i > 20) { i = 0; if (m_ToolVisualizationFilter->GetOutput(0)->IsDataValid()) { if (mitk::Equal(lastPositionTool1, m_ToolVisualizationFilter->GetOutput(0)->GetPosition(), 0.000000001, false) && m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() != "Da Vinci") { MITK_WARN << "Seems as tracking (of at least tool 1) is frozen which means that bug 17713 occurred. Restart tracking might help."; //display further information to find the bug MITK_WARN << "Timestamp of current navigation data: " << m_ToolVisualizationFilter->GetOutput(0)->GetTimeStamp(); MITK_WARN << "Timestamp of last navigation data (which holds the same values): " << lastTimeStamp; } lastPositionTool1 = m_ToolVisualizationFilter->GetOutput(0)->GetPosition(); lastTimeStamp = m_ToolVisualizationFilter->GetOutput(0)->GetTimeStamp(); } } } void QmitkMITKIGTTrackingToolboxView::UpdateLoggingTrackingTimer() { //update logging if (m_logging) { this->m_loggingFilter->Update(); m_loggedFrames = this->m_loggingFilter->GetNumberOfRecordedSteps(); this->m_Controls->m_LoggedFramesLabel->setText("Logged Frames: " + QString::number(m_loggedFrames)); //check if logging stopped automatically if ((m_loggedFrames > 1) && (!m_loggingFilter->GetRecording())){ StopLogging(); } } //refresh status widget m_Controls->m_TrackingToolsStatusWidget->Refresh(); } void QmitkMITKIGTTrackingToolboxView::OnChooseFileClicked() { QDir currentPath = QFileInfo(m_Controls->m_LoggingFileName->text()).dir(); // if no path was selected (QDir would select current working dir then) or the // selected path does not exist -> use home directory if (currentPath == QDir() || !currentPath.exists()) { currentPath = QDir(QDir::homePath()); } QString filename = QFileDialog::getSaveFileName(NULL, tr("Choose Logging File"), currentPath.absolutePath(), "*.*"); if (filename == "") return; this->m_Controls->m_LoggingFileName->setText(filename); this->OnToggleFileExtension(); } // bug-16470: toggle file extension after clicking on radio button void QmitkMITKIGTTrackingToolboxView::OnToggleFileExtension() { QString currentInputText = this->m_Controls->m_LoggingFileName->text(); QString currentFile = QFileInfo(currentInputText).baseName(); QDir currentPath = QFileInfo(currentInputText).dir(); if (currentFile.isEmpty()) { currentFile = "logfile"; } // Setting currentPath to default home path when currentPath is empty or it does not exist if (currentPath == QDir() || !currentPath.exists()) { currentPath = QDir::homePath(); } // check if csv radio button is clicked if (this->m_Controls->m_csvFormat->isChecked()) { // you needn't add a seperator to the input text when currentpath is the rootpath if (currentPath.isRoot()) { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + currentFile + ".csv"); } else { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + QDir::separator() + currentFile + ".csv"); } } // check if xml radio button is clicked else if (this->m_Controls->m_xmlFormat->isChecked()) { // you needn't add a seperator to the input text when currentpath is the rootpath if (currentPath.isRoot()) { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + currentFile + ".xml"); } else { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + QDir::separator() + currentFile + ".xml"); } } } void QmitkMITKIGTTrackingToolboxView::OnToggleDifferentUpdateRates() { if (m_Controls->m_UseDifferentUpdateRates->isChecked()) { if (m_Controls->m_RenderUpdateRate->value() == 0) m_Controls->m_renderWarningLabel->setVisible(true); else m_Controls->m_renderWarningLabel->setVisible(false); m_Controls->m_UpdateRate->setEnabled(false); m_Controls->m_OptionsUpdateRateLabel->setEnabled(false); m_Controls->m_RenderUpdateRate->setEnabled(true); m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(true); m_Controls->m_LogUpdateRate->setEnabled(true); m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(true); } else { m_Controls->m_renderWarningLabel->setVisible(false); m_Controls->m_UpdateRate->setEnabled(true); m_Controls->m_OptionsUpdateRateLabel->setEnabled(true); m_Controls->m_RenderUpdateRate->setEnabled(false); m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(false); m_Controls->m_LogUpdateRate->setEnabled(false); m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(false); } } void QmitkMITKIGTTrackingToolboxView::OnChangeRenderUpdateRate() { if (m_Controls->m_RenderUpdateRate->value() == 0) m_Controls->m_renderWarningLabel->setVisible(true); else m_Controls->m_renderWarningLabel->setVisible(false); } void QmitkMITKIGTTrackingToolboxView::StartLogging() { if (m_ToolVisualizationFilter.IsNull()) { MessageBox("Cannot activate logging without a connected device. Configure and connect a tracking device first."); return; } if (!m_logging) { //initialize logging filter m_loggingFilter = mitk::NavigationDataRecorder::New(); m_loggingFilter->ConnectTo(m_ToolVisualizationFilter); if (m_Controls->m_LoggingLimit->isChecked()){ m_loggingFilter->SetRecordCountLimit(m_Controls->m_LoggedFramesLimit->value()); } //start filter with try-catch block for exceptions try { m_loggingFilter->StartRecording(); } catch (mitk::IGTException) { std::string errormessage = "Error during start recording. Recorder already started recording?"; QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); m_loggingFilter->StopRecording(); return; } //update labels / logging variables this->m_Controls->m_LoggingLabel->setText("Logging ON"); this->m_Controls->m_LoggedFramesLabel->setText("Logged Frames: 0"); m_loggedFrames = 0; m_logging = true; DisableLoggingButtons(); } } void QmitkMITKIGTTrackingToolboxView::StopLogging() { if (m_logging) { //stop logging m_loggingFilter->StopRecording(); m_logging = false; //update GUI this->m_Controls->m_LoggingLabel->setText("Logging OFF"); EnableLoggingButtons(); //write the results to a file if (m_Controls->m_csvFormat->isChecked()) { mitk::IOUtil::SaveBaseData(m_loggingFilter->GetNavigationDataSet(), this->m_Controls->m_LoggingFileName->text().toStdString()); } else if (m_Controls->m_xmlFormat->isChecked()) { mitk::IOUtil::SaveBaseData(m_loggingFilter->GetNavigationDataSet(), this->m_Controls->m_LoggingFileName->text().toStdString()); } } } void QmitkMITKIGTTrackingToolboxView::OnAddSingleTool() { QString Identifier = "Tool#"; QString Name = "NewTool"; if (m_toolStorage.IsNotNull()) { Identifier += QString::number(m_toolStorage->GetToolCount()); Name += QString::number(m_toolStorage->GetToolCount()); } else { Identifier += "0"; Name += "0"; } m_Controls->m_NavigationToolCreationWidget->Initialize(GetDataStorage(), Identifier.toStdString(), Name.toStdString()); m_Controls->m_NavigationToolCreationWidget->SetTrackingDeviceType(m_Controls->m_configurationWidget->GetTrackingDevice()->GetType(), false); m_Controls->m_TrackingToolsWidget->setCurrentIndex(1); //disable tracking volume during tool editing lastTrackingVolumeState = m_Controls->m_ShowTrackingVolume->isChecked(); if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnAddSingleToolFinished() { m_Controls->m_TrackingToolsWidget->setCurrentIndex(0); if (this->m_toolStorage.IsNull()) { //this shouldn't happen! MITK_WARN << "No ToolStorage available, cannot add tool, aborting!"; return; } m_toolStorage->AddTool(m_Controls->m_NavigationToolCreationWidget->GetCreatedTool()); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); m_Controls->m_toolLabel->setText(""); //auto save current storage for persistence MITK_INFO << "Auto saving manually added tools for persistence."; AutoSaveToolStorage(); //enable tracking volume again if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnAddSingleToolCanceled() { m_Controls->m_TrackingToolsWidget->setCurrentIndex(0); //enable tracking volume again if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::GlobalReinit() { // get all nodes that have not set "includeInBoundingBox" to false mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox", mitk::BoolProperty::New(false))); mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeGeometry::Pointer bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } void QmitkMITKIGTTrackingToolboxView::DisableLoggingButtons() { m_Controls->m_StartLogging->setEnabled(false); m_Controls->m_LoggingFileName->setEnabled(false); m_Controls->m_ChooseFile->setEnabled(false); m_Controls->m_LoggingLimit->setEnabled(false); m_Controls->m_LoggedFramesLimit->setEnabled(false); m_Controls->m_csvFormat->setEnabled(false); m_Controls->m_xmlFormat->setEnabled(false); m_Controls->m_StopLogging->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::EnableLoggingButtons() { m_Controls->m_StartLogging->setEnabled(true); m_Controls->m_LoggingFileName->setEnabled(true); m_Controls->m_ChooseFile->setEnabled(true); m_Controls->m_LoggingLimit->setEnabled(true); m_Controls->m_LoggedFramesLimit->setEnabled(true); m_Controls->m_csvFormat->setEnabled(true); m_Controls->m_xmlFormat->setEnabled(true); m_Controls->m_StopLogging->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::DisableOptionsButtons() { m_Controls->m_ShowTrackingVolume->setEnabled(false); m_Controls->m_UseDifferentUpdateRates->setEnabled(false); m_Controls->m_UpdateRate->setEnabled(false); m_Controls->m_OptionsUpdateRateLabel->setEnabled(false); m_Controls->m_RenderUpdateRate->setEnabled(false); m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(false); m_Controls->m_LogUpdateRate->setEnabled(false); m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(false); m_Controls->m_DisableAllTimers->setEnabled(false); m_Controls->m_OtherOptionsGroupBox->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::EnableOptionsButtons() { m_Controls->m_ShowTrackingVolume->setEnabled(true); m_Controls->m_UseDifferentUpdateRates->setEnabled(true); m_Controls->m_DisableAllTimers->setEnabled(true); m_Controls->m_OtherOptionsGroupBox->setEnabled(true); OnToggleDifferentUpdateRates(); } void QmitkMITKIGTTrackingToolboxView::EnableTrackingControls() { m_Controls->m_TrackingControlsGroupBox->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::DisableTrackingControls() { m_Controls->m_TrackingControlsGroupBox->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::EnableTrackingConfigurationButtons() { m_Controls->m_AutoDetectTools->setEnabled(true); if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() != mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) m_Controls->m_AddSingleTool->setEnabled(true); m_Controls->m_LoadTools->setEnabled(true); m_Controls->m_ResetTools->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::DisableTrackingConfigurationButtons() { m_Controls->m_AutoDetectTools->setEnabled(false); if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() != mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) m_Controls->m_AddSingleTool->setEnabled(false); m_Controls->m_LoadTools->setEnabled(false); m_Controls->m_ResetTools->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::ReplaceCurrentToolStorage(mitk::NavigationToolStorage::Pointer newStorage, std::string newStorageName) { //first: get rid of the old one //don't reset if there is no tool storage. BugFix #17793 if (m_toolStorage.IsNotNull()){ m_toolStorage->UnLockStorage(); //only to be sure... m_toolStorage->UnRegisterMicroservice(); m_toolStorage = nullptr; } //now: replace by the new one m_toolStorage = newStorage; m_toolStorage->SetName(newStorageName); m_toolStorage->RegisterAsMicroservice("no tracking device"); } void QmitkMITKIGTTrackingToolboxView::OnTimeOut() { - MITK_INFO << "Time Out"; m_WorkerThread->terminate(); m_WorkerThread->wait(); - m_TimeoutTimer->stop(); } //! [StoreUISettings] void QmitkMITKIGTTrackingToolboxView::StoreUISettings() { // persistence service does not directly work in plugins for now // -> using QSettings QSettings settings; settings.beginGroup(QString::fromStdString(VIEW_ID)); // set the values of some widgets and attrbutes to the QSettings settings.setValue("ShowTrackingVolume", QVariant(m_Controls->m_ShowTrackingVolume->isChecked())); settings.setValue("toolStorageFilename", QVariant(m_ToolStorageFilename)); settings.setValue("VolumeSelectionBox", QVariant(m_Controls->m_VolumeSelectionBox->currentIndex())); settings.endGroup(); } //! [StoreUISettings] //! [LoadUISettings] void QmitkMITKIGTTrackingToolboxView::LoadUISettings() { // persistence service does not directly work in plugins for now // -> using QSettings QSettings settings; settings.beginGroup(QString::fromStdString(VIEW_ID)); // set some widgets and attributes by the values from the QSettings m_Controls->m_ShowTrackingVolume->setChecked(settings.value("ShowTrackingVolume", true).toBool()); m_Controls->m_VolumeSelectionBox->setCurrentIndex(settings.value("VolumeSelectionBox", 0).toInt()); m_ToolStorageFilename = settings.value("toolStorageFilename", QVariant("")).toString(); settings.endGroup(); //! [LoadUISettings] //! [LoadToolStorage] // try to deserialize the tool storage from the given tool storage file name if (!m_ToolStorageFilename.isEmpty()) { // try-catch block for exceptions try { mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(GetDataStorage()); m_toolStorage->UnRegisterMicroservice(); m_toolStorage = myDeserializer->Deserialize(m_ToolStorageFilename.toStdString()); m_toolStorage->RegisterAsMicroservice("no tracking device"); //update label UpdateToolStorageLabel(m_ToolStorageFilename); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); } catch (mitk::IGTException) { MITK_WARN("QmitkMITKIGTTrackingToolBoxView") << "Error during restoring tools. Problems with file (" << m_ToolStorageFilename.toStdString() << "), please check the file?"; this->OnResetTools(); //if there where errors reset the tool storage to avoid problems later on } } //! [LoadToolStorage] } void QmitkMITKIGTTrackingToolboxView::UpdateToolStorageLabel(QString pathOfLoadedStorage) { QFileInfo myPath(pathOfLoadedStorage); //use this to seperate filename from path QString toolLabel = myPath.fileName(); if (toolLabel.size() > 45) //if the tool storage name is to long trimm the string { toolLabel.resize(40); toolLabel += "[...]"; } m_Controls->m_toolLabel->setText(toolLabel); } void QmitkMITKIGTTrackingToolboxView::AutoSaveToolStorage() { m_ToolStorageFilename = m_AutoSaveFilename; mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); mySerializer->Serialize(m_ToolStorageFilename.toStdString(), m_toolStorage); } void QmitkMITKIGTTrackingToolboxViewWorker::SetWorkerMethod(WorkerMethod w) { m_WorkerMethod = w; } void QmitkMITKIGTTrackingToolboxViewWorker::SetTrackingDevice(mitk::TrackingDevice::Pointer t) { m_TrackingDevice = t; } void QmitkMITKIGTTrackingToolboxViewWorker::SetDataStorage(mitk::DataStorage::Pointer d) { m_DataStorage = d; } void QmitkMITKIGTTrackingToolboxViewWorker::SetInverseMode(bool mode) { m_InverseMode = mode; } void QmitkMITKIGTTrackingToolboxViewWorker::SetTrackingDeviceData(mitk::TrackingDeviceData d) { m_TrackingDeviceData = d; } void QmitkMITKIGTTrackingToolboxViewWorker::SetNavigationToolStorage(mitk::NavigationToolStorage::Pointer n) { m_NavigationToolStorage = n; } //! [Thread 7] void QmitkMITKIGTTrackingToolboxViewWorker::ThreadFunc() { switch (m_WorkerMethod) { case eAutoDetectTools: this->AutoDetectTools(); break; case eConnectDevice: this->ConnectDevice(); break; case eStartTracking: this->StartTracking(); break; case eStopTracking: this->StopTracking(); break; case eDisconnectDevice: this->DisconnectDevice(); break; default: MITK_WARN << "Undefined worker method was set ... something went wrong!"; break; } } //! [Thread 7] void QmitkMITKIGTTrackingToolboxViewWorker::AutoDetectTools() { - mitk::ProgressBar::GetInstance()->AddStepsToDo(4); + mitk::ProgressBar::GetInstance()->AddStepsToDo(2); mitk::NavigationToolStorage::Pointer autoDetectedStorage = mitk::NavigationToolStorage::New(m_DataStorage); - mitk::NDITrackingDevice::Pointer currentDevice = dynamic_cast(m_TrackingDevice.GetPointer()); try { - currentDevice->OpenConnection(); + mitk::NavigationToolStorage::Pointer tempStorage = m_TrackingDevice->AutoDetectTools(); mitk::ProgressBar::GetInstance()->Progress(); - currentDevice->StartTracking(); + for (int i = 0; i < tempStorage->GetToolCount(); i++) { autoDetectedStorage->AddTool(tempStorage->GetTool(i)); } } catch (mitk::Exception& e) { - QString message = QString("Warning, can not auto-detect tools! (") + QString(e.GetDescription()) + QString(")"); - //MessageBox(message.toStdString()); //TODO: give message to the user here! - - MITK_WARN << message.toStdString(); - mitk::ProgressBar::GetInstance()->Progress(4); - emit AutoDetectToolsFinished(false, message.toStdString().c_str()); + MITK_WARN << e.GetDescription(); + mitk::ProgressBar::GetInstance()->Progress(2); + emit AutoDetectToolsFinished(false, e.GetDescription()); return; } - - for (unsigned int i = 0; i < currentDevice->GetToolCount(); i++) - { - //create a navigation tool with sphere as surface - std::stringstream toolname; - toolname << "AutoDetectedTool" << i; - mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New(); - newTool->SetSerialNumber(dynamic_cast(currentDevice->GetTool(i))->GetSerialNumber()); - newTool->SetIdentifier(toolname.str()); - newTool->SetTrackingDeviceType(mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()); - mitk::DataNode::Pointer newNode = mitk::DataNode::New(); - mitk::Surface::Pointer mySphere = mitk::Surface::New(); - vtkSphereSource *vtkData = vtkSphereSource::New(); - vtkData->SetRadius(3.0f); - vtkData->SetCenter(0.0, 0.0, 0.0); - vtkData->Update(); - mySphere->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); - newNode->SetData(mySphere); - newNode->SetName(toolname.str()); - newTool->SetDataNode(newNode); - autoDetectedStorage->AddTool(newTool); - } - m_NavigationToolStorage = autoDetectedStorage; - - currentDevice->StopTracking(); mitk::ProgressBar::GetInstance()->Progress(); - currentDevice->CloseConnection(); - emit AutoDetectToolsFinished(true, ""); - mitk::ProgressBar::GetInstance()->Progress(4); + mitk::ProgressBar::GetInstance()->Progress(2); } void QmitkMITKIGTTrackingToolboxViewWorker::ConnectDevice() { std::string message = ""; mitk::ProgressBar::GetInstance()->AddStepsToDo(10); //build the IGT pipeline mitk::TrackingDevice::Pointer trackingDevice = m_TrackingDevice; trackingDevice->SetData(m_TrackingDeviceData); //set device to rotation mode transposed becaus we are working with VNL style quaternions if (m_InverseMode) { trackingDevice->SetRotationMode(mitk::TrackingDevice::RotationTransposed); } //Get Tracking Volume Data mitk::TrackingDeviceData data = m_TrackingDeviceData; mitk::ProgressBar::GetInstance()->Progress(); //Create Navigation Data Source with the factory class mitk::TrackingDeviceSourceConfigurator::Pointer myTrackingDeviceSourceFactory = mitk::TrackingDeviceSourceConfigurator::New(m_NavigationToolStorage, trackingDevice); m_TrackingDeviceSource = myTrackingDeviceSourceFactory->CreateTrackingDeviceSource(m_ToolVisualizationFilter); mitk::ProgressBar::GetInstance()->Progress(); if (m_TrackingDeviceSource.IsNull()) { message = std::string("Cannot connect to device: ") + myTrackingDeviceSourceFactory->GetErrorMessage(); emit ConnectDeviceFinished(false, QString(message.c_str())); return; } //set filter to rotation mode transposed becaus we are working with VNL style quaternions if (m_InverseMode) m_ToolVisualizationFilter->SetRotationMode(mitk::NavigationDataObjectVisualizationFilter::RotationTransposed); //First check if the created object is valid if (m_TrackingDeviceSource.IsNull()) { message = myTrackingDeviceSourceFactory->GetErrorMessage(); emit ConnectDeviceFinished(false, QString(message.c_str())); return; } MITK_INFO << "Number of tools: " << m_TrackingDeviceSource->GetNumberOfOutputs(); mitk::ProgressBar::GetInstance()->Progress(); //The tools are maybe reordered after initialization, e.g. in case of auto-detected tools of NDI Aurora mitk::NavigationToolStorage::Pointer toolsInNewOrder = myTrackingDeviceSourceFactory->GetUpdatedNavigationToolStorage(); if ((toolsInNewOrder.IsNotNull()) && (toolsInNewOrder->GetToolCount() > 0)) { //so delete the old tools in wrong order and add them in the right order //we cannot simply replace the tool storage because the new storage is //not correctly initialized with the right data storage /* m_NavigationToolStorage->DeleteAllTools(); for (int i=0; i < toolsInNewOrder->GetToolCount(); i++) {m_NavigationToolStorage->AddTool(toolsInNewOrder->GetTool(i));} This was replaced and thereby fixed Bug 18318 DeleteAllTools() is not Threadsafe! */ for (int i = 0; i < toolsInNewOrder->GetToolCount(); i++) { m_NavigationToolStorage->AssignToolNumber(toolsInNewOrder->GetTool(i)->GetIdentifier(), i); } } mitk::ProgressBar::GetInstance()->Progress(); //connect to device try { m_TrackingDeviceSource->Connect(); mitk::ProgressBar::GetInstance()->Progress(); //Microservice registration: m_TrackingDeviceSource->RegisterAsMicroservice(); m_NavigationToolStorage->UnRegisterMicroservice(); m_NavigationToolStorage->RegisterAsMicroservice(m_TrackingDeviceSource->GetMicroserviceID()); m_NavigationToolStorage->LockStorage(); } catch (...) //todo: change to mitk::IGTException { message = "Error on connecting the tracking device."; emit ConnectDeviceFinished(false, QString(message.c_str())); return; } emit ConnectDeviceFinished(true, QString(message.c_str())); mitk::ProgressBar::GetInstance()->Progress(10); } void QmitkMITKIGTTrackingToolboxViewWorker::StartTracking() { QString errorMessage = ""; try { m_TrackingDeviceSource->StartTracking(); } catch (...) //todo: change to mitk::IGTException { errorMessage += "Error while starting the tracking device!"; emit StartTrackingFinished(false, errorMessage); return; } //remember the original colors of the tools m_OriginalColors = std::map(); for (int i = 0; i < this->m_NavigationToolStorage->GetToolCount(); i++) { mitk::DataNode::Pointer currentToolNode = m_NavigationToolStorage->GetTool(i)->GetDataNode(); float c[3]; currentToolNode->GetColor(c); mitk::Color color; color.SetRed(c[0]); color.SetGreen(c[1]); color.SetBlue(c[2]); m_OriginalColors[currentToolNode] = color; } emit StartTrackingFinished(true, errorMessage); } void QmitkMITKIGTTrackingToolboxViewWorker::StopTracking() { //stop tracking try { m_TrackingDeviceSource->StopTracking(); } catch (mitk::Exception& e) { emit StopTrackingFinished(false, e.GetDescription()); } //restore the original colors of the tools for (int i = 0; i < this->m_NavigationToolStorage->GetToolCount(); i++) { mitk::DataNode::Pointer currentToolNode = m_NavigationToolStorage->GetTool(i)->GetDataNode(); if (m_OriginalColors.find(currentToolNode) == m_OriginalColors.end()) { MITK_WARN << "Cannot restore original color of tool " << m_NavigationToolStorage->GetTool(i)->GetToolName(); } else { currentToolNode->SetColor(m_OriginalColors[currentToolNode]); } } //emit signal emit StopTrackingFinished(true, ""); } void QmitkMITKIGTTrackingToolboxViewWorker::DisconnectDevice() { try { if (m_TrackingDeviceSource->IsTracking()) { m_TrackingDeviceSource->StopTracking(); } m_TrackingDeviceSource->Disconnect(); m_TrackingDeviceSource->UnRegisterMicroservice(); m_NavigationToolStorage->UnLockStorage(); } catch (mitk::Exception& e) { emit DisconnectDeviceFinished(false, e.GetDescription()); } emit DisconnectDeviceFinished(true, ""); } \ No newline at end of file