diff --git a/Modules/IGT/IGTFilters/mitkTimeStamp.cpp b/Modules/IGT/IGTFilters/mitkIGTTimeStamp.cpp similarity index 74% rename from Modules/IGT/IGTFilters/mitkTimeStamp.cpp rename to Modules/IGT/IGTFilters/mitkIGTTimeStamp.cpp index c4f96e9fc2..1c086a271b 100644 --- a/Modules/IGT/IGTFilters/mitkTimeStamp.cpp +++ b/Modules/IGT/IGTFilters/mitkIGTTimeStamp.cpp @@ -1,157 +1,156 @@ /*=================================================================== 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 "mitkTimeStamp.h" +#include "mitkIGTTimeStamp.h" #include #include "mitkRealTimeClock.h" -mitk::TimeStamp::Pointer mitk::TimeStamp::s_Instance = NULL; +mitk::IGTTimeStamp::Pointer mitk::IGTTimeStamp::s_Instance = NULL; -mitk::TimeStamp::TimeStamp() : itk::Object() +mitk::IGTTimeStamp::IGTTimeStamp() : itk::Object() , m_Time(-1.0), m_ReferenceTime(0.0) { } -mitk::TimeStamp::~TimeStamp() +mitk::IGTTimeStamp::~IGTTimeStamp() { } -mitk::TimeStamp* mitk::TimeStamp::CreateInstance() +mitk::IGTTimeStamp* mitk::IGTTimeStamp::CreateInstance() { -return mitk::TimeStamp::GetInstance(); +return mitk::IGTTimeStamp::GetInstance(); } -mitk::TimeStamp* mitk::TimeStamp::GetInstance() +mitk::IGTTimeStamp* mitk::IGTTimeStamp::GetInstance() { - if (TimeStamp::s_Instance.IsNull()) + if (IGTTimeStamp::s_Instance.IsNull()) { - mitk::TimeStamp::Pointer ts = new mitk::TimeStamp; + mitk::IGTTimeStamp::Pointer ts = new mitk::IGTTimeStamp; s_Instance = ts; return s_Instance; } else return s_Instance; } -void mitk::TimeStamp::Start(itk::Object::Pointer device) +void mitk::IGTTimeStamp::Start(itk::Object::Pointer device) { if (m_RealTimeClock.IsNull()) { Initialize(); } if ( s_Instance.IsNotNull() ) { if (m_DeviceMap.empty()) { m_ReferenceTime = GetCurrentStamp(); m_Time = 0.0; } m_DeviceMap.insert( std::pair(device, this->GetElapsed()) ); } else { itkGenericOutputMacro("Trying to use mitk::TimeStamp::Start() " << "without an available singleton instance. Either no instance has " << "been created (use TimeStamp::CreateInstance) or it has already " << "been destroyed."); } } -void mitk::TimeStamp::Stop(itk::Object::Pointer device) +void mitk::IGTTimeStamp::Stop(itk::Object::Pointer device) { if ( s_Instance.IsNotNull() ) { m_MapIterator = m_DeviceMap.find(device); if ( m_MapIterator != m_DeviceMap.end() ) { m_DeviceMap.erase( m_MapIterator ); } if (m_DeviceMap.empty()) { m_ReferenceTime = NULL; m_Time = -1; } } else { itkGenericOutputMacro("Trying to use mitk::TimeStamp::Stop() " << "without an available singleton instance. Either no instance has " << "been created (use TimeStamp::CreateInstance) or it has already " << "been destroyed."); } } -double mitk::TimeStamp::GetElapsed() +double mitk::IGTTimeStamp::GetElapsed() { if (m_Time > -1) { m_Time = GetCurrentStamp(); m_Time = m_Time - m_ReferenceTime; } return (double) m_Time; } -double mitk::TimeStamp::GetElapsed(itk::Object::Pointer device) +double mitk::IGTTimeStamp::GetElapsed(itk::Object::Pointer device) { double offset = this->GetOffset( device ); if ( offset > -1 ) { double time = this->GetElapsed(); return (double) time - this->GetOffset(device); } else { return (double) -1; } } -double mitk::TimeStamp::GetCurrentStamp() +double mitk::IGTTimeStamp::GetCurrentStamp() { if (m_RealTimeClock.IsNotNull()) { return m_RealTimeClock->GetCurrentStamp(); } else return 0.0; } -void mitk::TimeStamp::SetRealTimeClock(mitk::RealTimeClock::Pointer Clock) +void mitk::IGTTimeStamp::SetRealTimeClock(mitk::RealTimeClock::Pointer Clock) { m_RealTimeClock = Clock; } -double mitk::TimeStamp::GetOffset(itk::Object::Pointer Device) +double mitk::IGTTimeStamp::GetOffset(itk::Object::Pointer Device) { m_MapIterator = m_DeviceMap.find(Device); if ( m_MapIterator != m_DeviceMap.end() ) { return m_MapIterator->second; } else { return -1.0; } } -void mitk::TimeStamp::Initialize() +void mitk::IGTTimeStamp::Initialize() { if ( m_RealTimeClock.IsNull() ) m_RealTimeClock = mitk::RealTimeClock::New(); } - diff --git a/Modules/IGT/IGTFilters/mitkTimeStamp.h b/Modules/IGT/IGTFilters/mitkIGTTimeStamp.h similarity index 95% rename from Modules/IGT/IGTFilters/mitkTimeStamp.h rename to Modules/IGT/IGTFilters/mitkIGTTimeStamp.h index 5056ece9da..029b56b33b 100644 --- a/Modules/IGT/IGTFilters/mitkTimeStamp.h +++ b/Modules/IGT/IGTFilters/mitkIGTTimeStamp.h @@ -1,190 +1,190 @@ /*=================================================================== 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 MITKTIMESTAMP_H_HEADER_INCLUDED_ #define MITKTIMESTAMP_H_HEADER_INCLUDED_ #include #include #include #include "mitkRealTimeClock.h" namespace mitk { /** * \brief Time stamp in milliseconds * * This class provides a timestamp in milliseconds. * It is a Singleton class, that internally uses a mitkRealTimeClock() for * time-acquisition. * * First you have to call Start() in order to set the reference-time to the current time. * If the user has not created and set his own "RealTimeClock", initialize() will be called and a * default mitkRealTimeClock() is created. * In addition the TimeStamp() saves a pointer to the device calling and the respective offset-time. * The first device will have an offset of 0, the following's offset will be the time elapsed since the * starting of the first device. This offset can be prompted by calling GetOffset(); * * You can always get the time elapsed since calling Start() with GetElapsed(). It returns the * time spent in milliseconds as a double. * * When the TimeStamp is no longer used, you can call Stop(). This erases the pointer to the device * and the offset. When all devices have "stopped tracking" the reference-time and the current-time are reset to 0. * * \ingroup IGT */ - class MitkIGT_EXPORT TimeStamp : public itk::Object + class MitkIGT_EXPORT IGTTimeStamp : public itk::Object { public: - mitkClassMacro(TimeStamp, itk::Object); + mitkClassMacro(IGTTimeStamp, itk::Object); /** * \brief creates a new instance of mitkTimeStamp * * This method returns a pointer to the currently existing TimeStamp. * If there is no exisiting instance, a new one is created and returned automatically * * DECREPATED: Use GetInstance instead */ - static TimeStamp* CreateInstance(); + static IGTTimeStamp* CreateInstance(); /** * \brief returns a pointer to the current instance of mitkTimeStamp * * This method returns a pointer to the currently existing TimeStamp. * If there is no exisiting instance, a new one is created and returned automatically */ - static TimeStamp* GetInstance(); + static IGTTimeStamp* GetInstance(); /** * \brief starts the time-acquisition * * Each device is to call this method when it starts tracking. * The current time is saved as a reference-value (m_Time = 0). * Internally the device (pointer) and its offset are saved in a map, so that * no device can call this method twice. * If the user has not set its own RealTimeClock, a default one is created dependant on the OS * in use. * */ void Start( itk::Object::Pointer device ); /** * \brief stops the time-acqusition * * Each device has to call Stop() when it has finished and its * pointer will be erased from the map. When the last device has "stopped" * the reference-time and the current-time will be reset to 0. * */ void Stop( itk::Object::Pointer device ); /** * \brief returns the time elapsed since calling Start() for the first time in milliseconds * * GetElapsed() returns the time elapsed since Start() has been called first, no matter * which itk::Object did the call. * This method-call can be used if you want to need to have several processes you want to * monitor and need timestamps in the same space of time, e.g. when using two tracking-devices * on the same experiment. */ double GetElapsed(); /** * \brief returns the time elapsed since 'device' called Start() in milliseconds * * GetElapsed(itk::Object device) returns the time elapsed since the given itk::Object called * Start(). * This overloaded method should be used when you only have one independent process to keep * track of, e.g. when you want to measure how long it takes to execute a piece of code. */ double GetElapsed(itk::Object::Pointer device); /** * \brief returns the offset of this device's starting-time to the * reference-time in ms * * Device 'A' is the first device to call Start(). Device 'B' calls Start() * some time later. This time-difference is the offset, that each device has realtive to the * device that started the time-acquisition. * Each device's offset is stored in a map with a pointer to the device. * * If this device has not been or is no longer saved in the map of devices, * -1 will be returned. * * * only used internally */ double GetOffset(itk::Object::Pointer Device); /** * \brief setter for the internally used RealTimeClock() * * If you want to use a "third-party" RealTimeClock, e.g PocoRealTimeClock, BoostRealTimeClock * or ITKRealTimeClock, you can set it using this method: * mitk::RealTimeClock::Pointer RealTimeClock = mitk::RealTimeClock::New(); * mitk::TimeStamp::GetInstance()->SetRealTimeClock(RealTimeClock); * * Right now, none of these RealTimeClocks have been implemented!! * * Notice: The mitk-implementation of an os-dependant RealTimeClock is used * by default. */ void SetRealTimeClock(mitk::RealTimeClock::Pointer Clock); /** * \brief creates a new RealTimeClock * * Instanciates a new RealTimeClock, that will be specific for the Operating System. * This will only be called internally when no other RealTimeClock has been set * by the user. * */ void Initialize(); protected: - TimeStamp(); + IGTTimeStamp(); - virtual ~TimeStamp(); + virtual ~IGTTimeStamp(); double GetCurrentStamp(); /* the current timestamp when GetCurrentStamp() is called. */ double m_Time; /* the timestamp in ms acquired when Start() was called. */ double m_ReferenceTime; /* pointer to the RealTimeClock used internally */ mitk::RealTimeClock::Pointer m_RealTimeClock; /* pointer to the current instance */ - static mitk::TimeStamp::Pointer s_Instance; + static mitk::IGTTimeStamp::Pointer s_Instance; /* map, in which pointer to all devices calling Start(), are saved */ std::map m_DeviceMap; std::map::iterator m_MapIterator; }; } // namespace mitk #endif /* MITKTIMESTAMP_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.cpp index c3008185fb..53c4823896 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.cpp @@ -1,550 +1,550 @@ /*=================================================================== 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 "mitkNavigationDataPlayer.h" #include -#include +#include #include //includes for exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" mitk::NavigationDataPlayer::NavigationDataPlayer() : mitk::NavigationDataPlayerBase() { m_NumberOfOutputs = 0; m_Pause = false; m_Playing = false; m_Stream = NULL; m_PlayerMode = NormalFile; m_FileName = ""; m_FileVersion = 1; m_Playing = false; m_Pause = false; m_NumberOfOutputs = 0; m_StartPlayingTimeStamp = 0.0; m_PauseTimeStamp = 0.0; m_parentElement = NULL; m_currentNode = NULL; m_StreamEnd = false; m_StreamSetOutsideFromClass = false; //To get a start time - mitk::TimeStamp::GetInstance()->Start(this); + mitk::IGTTimeStamp::GetInstance()->Start(this); } mitk::NavigationDataPlayer::~NavigationDataPlayer() { StopPlaying(); delete m_parentElement; } void mitk::NavigationDataPlayer::GenerateData() { //Only produce new output if the player is started if (!m_Playing) //m_Playing==true means player has started { //The output is not valid anymore for (unsigned int index = 0; index < m_NumberOfOutputs; index++) { mitk::NavigationData* output = this->GetOutput(index); assert(output); mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); position.Fill(0.0); nd->SetPosition(position); nd->SetOrientation(orientation); nd->SetDataValid(false); output->Graft(nd); } return; } //first of all get current time - TimeStampType now = mitk::TimeStamp::GetInstance()->GetElapsed(); + TimeStampType now = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); //now we make a little time arithmetic //to get the elapsed time since the start of the player TimeStampType timeSinceStart = now - m_StartPlayingTimeStamp; //init the vectors std::vector< NavigationData::Pointer > nextCandidates; std::vector< NavigationData::Pointer > lastCandidates; std::vector< NavigationData::TimeStampType > currentTimeOfData; for (unsigned int index=0; index < m_NumberOfOutputs; index++) { nextCandidates.push_back(m_NextToPlayNavigationData.at(index)); lastCandidates.push_back(m_NextToPlayNavigationData.at(index)); currentTimeOfData.push_back(timeSinceStart + m_StartTimeOfData.at(index)); } if (m_NextToPlayNavigationData.size() != m_NumberOfOutputs) { MITK_ERROR << "Mismatch in data"; return; } // Now we try to find next NavigationData in the stream: // This means we step through the stream of NavigationDatas until we find // a NavigationData which has a current timestamp (currentTimeOfData) greater // than the current playing time. Then we store the data in // m_NextToPlayNavigationData and take the last data (lastCandidates) for the // output of this filter. // // The loop will stop when a suitable NavigationData is found or we reach EOF. // The timestamps of each recorded NavigationData should be equal // therefore we take always the time from the first. while( nextCandidates[0]->GetTimeStamp() < currentTimeOfData[0]) { for (unsigned int index=0; index < m_NumberOfOutputs; index++) { lastCandidates[index] = nextCandidates.at(index); switch(m_FileVersion) // m_FileVersion indicates which XML encoding is used { case 1: nextCandidates[index] = ReadVersion1(); break; default: //this case should not happen! therefore return at this point MITK_ERROR << "File encoding format was not stored, aborting!"; return; break; } //check if the input stream delivered a correct NavigationData object for (unsigned int i = 0; i < m_NumberOfOutputs; i++) { if (nextCandidates.at(index).IsNull()) //Stops playing because there is now more nextCandidate, the file ended for all outputs { m_StreamEnd = true; StopPlaying(); return; //the case if no NavigationData is found, e.g. EOF, bad stream } } } } //Now lastCandidates stores the new output and nextCandidates is stored to the m_NextToPlay vector for (unsigned int index = 0; index < m_NumberOfOutputs; index++) { mitk::NavigationData* output = this->GetOutput(index); assert(output); output->Graft(lastCandidates.at(index)); m_NextToPlayNavigationData[index] = nextCandidates.at(index); } } void mitk::NavigationDataPlayer::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } void mitk::NavigationDataPlayer::InitPlayer() { if (m_Stream == NULL) { StreamInvalid("Playing not possible. Wrong file name or path?"); return; } if (!m_Stream->good()) { StreamInvalid("Playing not possible. Stream is not good!"); return; } //first get the file version m_FileVersion = GetFileVersion(m_Stream); //check if we have a valid version: m_FileVersion has to be always bigger than 1 for playing if (m_FileVersion < 1) { StreamInvalid("Playing not possible. Invalid file version!"); return; } if(m_NumberOfOutputs == 0) {m_NumberOfOutputs = GetNumberOfNavigationDatas(m_Stream);} //with the information about the tracked tool number we can generate the output if (m_NumberOfOutputs > 0) { //Generate the output only if there are changes to the amount of outputs //This happens when the player is stopped and start again with different file if (this->GetNumberOfOutputs() != m_NumberOfOutputs) {SetNumberOfOutputs(m_NumberOfOutputs);} //initialize the player with first data GetFirstData(); //set stream valid m_ErrorMessage = ""; m_StreamValid = true; } else { StreamInvalid("The input stream seems to have NavigationData incompatible format"); return; } } unsigned int mitk::NavigationDataPlayer::GetFileVersion(std::istream* stream) { if (stream==NULL) { MITK_ERROR << "No input stream set!"; mitkThrowException(mitk::IGTException)<<"No input stream set!"; } if (!stream->good()) { MITK_ERROR << "Stream is not good!"; mitkThrowException(mitk::IGTException)<<"Stream is not good!"; } int version = 1; TiXmlDeclaration* dec = new TiXmlDeclaration(); *stream >> *dec; if(strcmp(dec->Version(),"") == 0) { MITK_ERROR << "The input stream seems to have XML incompatible format"; mitkThrowException(mitk::IGTIOException) << "The input stream seems to have XML incompatible format"; } m_parentElement = new TiXmlElement(""); *stream >> *m_parentElement; //2nd line this is the file version std::string tempValue = m_parentElement->Value(); if(tempValue != "Version") { if(tempValue == "Data"){ m_parentElement->QueryIntAttribute("version",&version); } } else { m_parentElement->QueryIntAttribute("Ver",&version); } if (version > 0) return version; else return 0; } unsigned int mitk::NavigationDataPlayer::GetNumberOfNavigationDatas(std::istream* stream) { if (stream == NULL) { MITK_ERROR << "No input stream set!"; mitkThrowException(mitk::IGTException)<<"No input stream set!"; } if (!stream->good()) { MITK_ERROR << "Stream not good!"; mitkThrowException(mitk::IGTException)<<"Stream not good!"; } //If something has changed in a future version of the XML definition e.g. navigationcount or addional parameters //catch this here with a select case block (see GenerateData() method) int numberOfTools = 0; std::string tempValue = m_parentElement->Value(); if(tempValue == "Version"){ *stream >> *m_parentElement; } m_parentElement->QueryIntAttribute("ToolCount",&numberOfTools); if (numberOfTools > 0) return numberOfTools; return 0; } mitk::NavigationData::Pointer mitk::NavigationDataPlayer::ReadVersion1() { if (m_Stream == NULL) { m_Playing = false; MITK_ERROR << "Playing not possible. Wrong file name or path? "; mitkThrowException(mitk::IGTException) << "Playing not possible. Wrong file name or path? "; } if (!m_Stream->good()) { m_Playing = false; MITK_ERROR << "Playing not possible. Stream is not good!"; mitkThrowException(mitk::IGTException) << "Playing not possible. Stream is not good!"; } /*TiXmlElement* elem = new TiXmlElement(""); m_currentNode = m_parentElement->IterateChildren(m_currentNode); if(m_currentNode) { elem = m_currentNode->ToElement(); }*/ TiXmlElement* elem; m_currentNode = m_parentElement->IterateChildren(m_currentNode); bool delElem; if(m_currentNode) { elem = m_currentNode->ToElement(); if(elem==NULL) { mitkThrowException(mitk::IGTException) << "Cannot find element: Is this file damaged?"; } delElem = false; } else { elem = new TiXmlElement(""); delElem = true; } mitk::NavigationData::Pointer nd = this->ReadNavigationData(elem); if(delElem) delete elem; return nd; } void mitk::NavigationDataPlayer::StartPlaying() { if (m_Stream == NULL) { m_Playing = false; //Perhaps the SetStream method was not called so we do this when a FileName is set with SetStream(PlayerMode) if (m_FileName != "") { //The PlayerMode is initialized with LastSetStream //CreateStreamFromFilename also calls InitPlayer() try { CreateStreamFromFilename(); } catch(mitk::IGTIOException e) { MITK_ERROR << "Cannot create stream from filename, please check the stream"; throw e; //TODO replace by macro } catch(mitk::IGTException e2) { MITK_ERROR << "Cannot open the file, please check the file"; throw e2; //TODO replace by macro } } //now check again if (m_Stream == NULL) { StopPlaying(); MITK_ERROR << "Playing not possible. Wrong file name or path?"; mitkThrowException(mitk::IGTException) << "Playing not possible. Wrong file name or path?"; } } if (!m_Playing && m_Stream->good()) { m_Playing = true; - m_StartPlayingTimeStamp = mitk::TimeStamp::GetInstance()->GetElapsed(); + m_StartPlayingTimeStamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); } else { MITK_ERROR << "Player already started or stream is not good!"; StopPlaying(); } } void mitk::NavigationDataPlayer::StopPlaying() { //re init all data!! for playing again with different data //only PlayerMode and FileName are not changed m_Pause = false; m_Playing = false; if (!m_StreamSetOutsideFromClass) {delete m_Stream;} m_Stream = NULL; m_FileVersion = 1; m_Playing = false; m_Pause = false; m_StartPlayingTimeStamp = 0.0; m_PauseTimeStamp = 0.0; m_NextToPlayNavigationData.clear(); m_StartTimeOfData.clear(); } void mitk::NavigationDataPlayer::GetFirstData() { //Here we read the first lines of input (dependend on the number of inputs) for (unsigned int index=0; index < m_NumberOfOutputs; index++) { //Here we init the vector for later use m_NextToPlayNavigationData.push_back(NULL); m_StartTimeOfData.push_back(0.0); mitk::NavigationData::Pointer nd = this->GetOutput(index); switch(m_FileVersion) { case 1: m_NextToPlayNavigationData[index] = ReadVersion1(); //check if there is valid data in it if (m_NextToPlayNavigationData[index].IsNull()) { m_StreamEnd = true; StopPlaying(); mitkThrowException(mitk::IGTIOException) << "XML File is corrupt or has no NavigationData."; } //Have a look it the output was set already without this check the pipline will disconnect after a start/stop cycle if (nd.IsNull()) {this->SetNthOutput(index, m_NextToPlayNavigationData[index]);} m_StartTimeOfData[index] = m_NextToPlayNavigationData[index]->GetTimeStamp(); break; default: //this case should not happen! therefore the return at this point return; break; } } } void mitk::NavigationDataPlayer::Pause() { //player runs and pause was called -> pause the player if(m_Playing && !m_Pause) { m_Playing = false; m_Pause = true; - m_PauseTimeStamp = mitk::TimeStamp::GetInstance()->GetElapsed(); + m_PauseTimeStamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); } else { MITK_ERROR << "Player is either not started or already is paused" << std::endl; } } void mitk::NavigationDataPlayer::Resume() { //player is in pause mode -> play at the last position if(!m_Playing && m_Pause) { m_Playing = true; m_Pause = false; - mitk::NavigationData::TimeStampType now = mitk::TimeStamp::GetInstance()->GetElapsed(); + mitk::NavigationData::TimeStampType now = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); // in this case m_StartPlayingTimeStamp is set to the total elapsed time with NO playback m_StartPlayingTimeStamp = now - (m_PauseTimeStamp - m_StartPlayingTimeStamp); } else { MITK_ERROR << "Player is not paused!" << std::endl; } } void mitk::NavigationDataPlayer::CreateStreamFromFilename() { m_Stream = NULL; if (!itksys::SystemTools::FileExists(m_FileName.c_str())) { mitkThrowException(mitk::IGTIOException) << "File does not exist!"; } switch(m_PlayerMode) { case NormalFile: m_Stream = new std::ifstream(m_FileName.c_str()); m_StreamSetOutsideFromClass = false; break; case ZipFile: m_Stream = NULL; MITK_ERROR << "Sorry no ZipFile support yet"; break; default: m_Stream = NULL; mitkThrowException(mitk::IGTException) << "The stream is NULL"; break; } this->Modified(); InitPlayer(); } void mitk::NavigationDataPlayer::SetStream( std::istream* stream ) { if ( (stream == NULL) || (!stream->good())) { // throw an exception for stream=NULL or it is not good mitkThrowException(mitk::IGTException) << "The stream is NULL or it is not good"; m_StreamEnd = true; return; } m_Stream = stream; m_StreamSetOutsideFromClass = true; this->Modified(); InitPlayer(); } bool mitk::NavigationDataPlayer::IsAtEnd() { return this->m_StreamEnd; } void mitk::NavigationDataPlayer::StreamInvalid(std::string message) { m_StreamEnd = true; StopPlaying(); m_ErrorMessage = message; m_StreamValid = false; mitkThrowException(mitk::IGTIOException) << "Invalid stream!"; } \ No newline at end of file diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp index e0b027c076..fa07be141a 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp @@ -1,366 +1,366 @@ /*=================================================================== 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 "mitkNavigationDataRecorder.h" #include -#include +#include #include #include //headers for exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" mitk::NavigationDataRecorder::NavigationDataRecorder() { //set default values m_NumberOfInputs = 0; m_RecordingMode = NormalFile; m_Recording = false; m_NumberOfRecordedFiles = 0; m_Stream = NULL; m_FileName = ""; m_SystemTimeClock = RealTimeClock::New(); m_OutputFormat = mitk::NavigationDataRecorder::xml; m_RecordCounter = 0; m_RecordCountLimit = -1; m_DoNotOverwriteFiles = false; m_StreamMustBeDeleted = false; //To get a start time - mitk::TimeStamp::GetInstance()->Start(this); + mitk::IGTTimeStamp::GetInstance()->Start(this); } mitk::NavigationDataRecorder::~NavigationDataRecorder() { } void mitk::NavigationDataRecorder::GenerateData() { } void mitk::NavigationDataRecorder::AddNavigationData( const NavigationData* nd ) { // Process object is not const-correct so the const_cast is required here this->SetNthInput(m_NumberOfInputs, const_cast< mitk::NavigationData * >( nd ) ); m_NumberOfInputs++; this->Modified(); } void mitk::NavigationDataRecorder::SetRecordingMode( RecordingMode mode ) { m_RecordingMode = mode; this->Modified(); } void mitk::NavigationDataRecorder::Update() { if (m_Recording) { DataObjectPointerArray inputs = this->GetInputs(); //get all inputs mitk::NavigationData::TimeStampType timestamp=0.0; // timestamp for mitk time - timestamp = mitk::TimeStamp::GetInstance()->GetElapsed(); + timestamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); mitk::NavigationData::TimeStampType sysTimestamp = 0.0; // timestamp for system time sysTimestamp = m_SystemTimeClock->GetCurrentStamp(); // cast system time double value to stringstream to avoid low precision rounding std::ostringstream strs; strs.precision(15); // rounding precision for system time double value strs << sysTimestamp; std::string sysTimeStr = strs.str(); //if csv-mode: write csv header and timestamp at beginning if (m_OutputFormat == mitk::NavigationDataRecorder::csv) { //write header only when it's the first line if (m_firstLine) { m_firstLine = false; *m_Stream << "TimeStamp"; for (unsigned int index = 0; index < inputs.size(); index++){ *m_Stream << ";Valid_Tool" << index << ";X_Tool" << index << ";Y_Tool" << index << ";Z_Tool" << index << ";QX_Tool" << index << ";QY_Tool" << index << ";QZ_Tool" << index << ";QR_Tool" << index;} *m_Stream << "\n"; } //write timestamp (always) *m_Stream << timestamp; } //write tool data for every tool for (unsigned int index = 0; index < inputs.size(); index++) { mitk::NavigationData* nd = dynamic_cast(inputs[index].GetPointer()); nd->Update(); // call update to propagate update to previous filters mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); mitk::NavigationData::CovarianceMatrixType matrix; bool hasPosition = true; bool hasOrientation = true; bool dataValid = false; position.Fill(0.0); matrix.SetIdentity(); position = nd->GetPosition(); orientation = nd->GetOrientation(); matrix = nd->GetCovErrorMatrix(); hasPosition = nd->GetHasPosition(); hasOrientation = nd->GetHasOrientation(); dataValid = nd->IsDataValid(); //use this one if you want the timestamps of the source //timestamp = nd->GetTimeStamp(); //a timestamp is never < 0! this case happens only if you are using the timestamp of the nd object instead of getting a new one if (timestamp >= 0) { if (this->m_OutputFormat == mitk::NavigationDataRecorder::xml) { TiXmlElement* elem = new TiXmlElement("NavigationData"); elem->SetDoubleAttribute("Time", timestamp); elem->SetAttribute("SystemTime", sysTimeStr); // tag for system time elem->SetDoubleAttribute("Tool", index); elem->SetDoubleAttribute("X", position[0]); elem->SetDoubleAttribute("Y", position[1]); elem->SetDoubleAttribute("Z", position[2]); elem->SetDoubleAttribute("QX", orientation[0]); elem->SetDoubleAttribute("QY", orientation[1]); elem->SetDoubleAttribute("QZ", orientation[2]); elem->SetDoubleAttribute("QR", orientation[3]); elem->SetDoubleAttribute("C00", matrix[0][0]); elem->SetDoubleAttribute("C01", matrix[0][1]); elem->SetDoubleAttribute("C02", matrix[0][2]); elem->SetDoubleAttribute("C03", matrix[0][3]); elem->SetDoubleAttribute("C04", matrix[0][4]); elem->SetDoubleAttribute("C05", matrix[0][5]); elem->SetDoubleAttribute("C10", matrix[1][0]); elem->SetDoubleAttribute("C11", matrix[1][1]); elem->SetDoubleAttribute("C12", matrix[1][2]); elem->SetDoubleAttribute("C13", matrix[1][3]); elem->SetDoubleAttribute("C14", matrix[1][4]); elem->SetDoubleAttribute("C15", matrix[1][5]); if (dataValid) elem->SetAttribute("Valid",1); else elem->SetAttribute("Valid",0); if (hasOrientation) elem->SetAttribute("hO",1); else elem->SetAttribute("hO",0); if (hasPosition) elem->SetAttribute("hP",1); else elem->SetAttribute("hP",0); // set additional attribute? std::map >::iterator it = m_AdditionalAttributes.find( nd ); if( it != m_AdditionalAttributes.end() ) { elem->SetAttribute(it->second.first, it->second.second); } *m_Stream << " " << *elem << std::endl; delete elem; } else if (this->m_OutputFormat == mitk::NavigationDataRecorder::csv) { *m_Stream << ";" << dataValid << ";" << position[0] << ";" << position[1] << ";" << position[2] << ";" << orientation[0] << ";" << orientation[1] << ";" << orientation[2] << ";" << orientation[3]; } } } if (this->m_OutputFormat == mitk::NavigationDataRecorder::csv) { *m_Stream << "\n"; } } m_RecordCounter++; if ((m_RecordCountLimit<=m_RecordCounter)&&(m_RecordCountLimit != -1)) {StopRecording();} } void mitk::NavigationDataRecorder::SetAdditionalAttribute(const NavigationData* nd, const std::string& attributeName , const std::string& attributeValue ) { std::map >::iterator it = m_AdditionalAttributes.find( nd ); if( it == m_AdditionalAttributes.end() ) m_AdditionalAttributes[nd] = std::pair(attributeName, attributeValue); else { it->second.first = attributeName; it->second.second = attributeValue; } } void mitk::NavigationDataRecorder::RemoveAdditionalAttribute( const NavigationData* nd ) { std::map >::iterator it = m_AdditionalAttributes.find( nd ); if( it != m_AdditionalAttributes.end() ) m_AdditionalAttributes.erase(it); } void mitk::NavigationDataRecorder::StartRecording() { if(!m_Recording) { if (m_Stream == NULL) { std::stringstream ss; std::ostream* stream; //An existing extension will be cut and replaced with .xml std::string tmpPath = itksys::SystemTools::GetFilenamePath(m_FileName); m_FileName = itksys::SystemTools::GetFilenameWithoutExtension(m_FileName); std::string extension = ".xml"; if (m_OutputFormat == mitk::NavigationDataRecorder::csv) extension = ".csv"; ss << tmpPath << "/" << m_FileName << "-" << m_NumberOfRecordedFiles << extension; if( m_DoNotOverwriteFiles ) { unsigned int index = m_NumberOfRecordedFiles+1; while( itksys::SystemTools::FileExists( ss.str().c_str() ) ) { ss.str(""); ss << tmpPath << "/" << m_FileName << "-" << index << extension; index++; } } switch(m_RecordingMode) { case Console: stream = &std::cout; break; case NormalFile: if (m_FileName == "") //Check if there is a file name and path { std::string message = "No file name or file path set."; MITK_ERROR << message; mitkThrowException(mitk::IGTException) << message; } else { stream = new std::ofstream(ss.str().c_str()); } break; case ZipFile: stream = &std::cout; MITK_WARN << "Sorry no ZipFile support yet"; break; default: stream = &std::cout; break; } m_Stream = stream; m_StreamMustBeDeleted = true; m_firstLine = true; m_RecordCounter = 0; StartRecording(stream); } } else if (m_Recording) { MITK_WARN << "Already recording please stop before start new recording session"; return; } } void mitk::NavigationDataRecorder::StartRecording(std::ostream* stream) { if (m_Recording) { MITK_WARN << "Already recording please stop before start new recording session"; return; } m_Stream = stream; m_Stream->precision(10); //TODO store date and GMT time //cheking if the stream is good if (m_Stream->good()) { if (m_OutputFormat == mitk::NavigationDataRecorder::xml) { *m_Stream << "" << std::endl; /**m_Stream << "" << std::endl;*/ // should be a generic version, meaning a member variable, which has the actual version *m_Stream << " " << "" << std::endl; } m_Recording = true; } else { m_Recording = false; mitkThrowException(mitk::IGTException)<<"The stream is not good"; } } void mitk::NavigationDataRecorder::StopRecording() { if (!m_Recording) { std::cout << "You have to start a recording first" << std::endl; return; } if ((m_Stream) && (m_OutputFormat == mitk::NavigationDataRecorder::xml)) { *m_Stream << "" << std::endl; } m_NumberOfRecordedFiles++; m_Recording = false; m_Stream->flush(); if (m_StreamMustBeDeleted) //stream must only be deleted if it was created inside this class { m_StreamMustBeDeleted = false; delete m_Stream; } m_Stream = NULL; } diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp index 64d7436c3c..2dcdc583dd 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp @@ -1,227 +1,225 @@ /*=================================================================== 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 "mitkNavigationDataSequentialPlayer.h" #include //for the pause - -#include #include #include //Exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" mitk::NavigationDataSequentialPlayer::NavigationDataSequentialPlayer() : mitk::NavigationDataPlayerBase() , m_Doc(new TiXmlDocument) , m_DataElem(0) , m_CurrentElem(0) , m_Repeat(false) , m_NumberOfSnapshots(0) , m_LastGoTo(0) { } mitk::NavigationDataSequentialPlayer::~NavigationDataSequentialPlayer() { delete m_Doc; } void mitk::NavigationDataSequentialPlayer::ReinitXML() { m_DataElem = m_Doc->FirstChildElement("Data"); int toolcount; if(!m_DataElem) { MITK_WARN << "Data element not found"; mitkThrowException(mitk::IGTException) << "Data element not found"; } else { m_DataElem->QueryIntAttribute("ToolCount", &toolcount); this->SetNumberOfOutputs(toolcount); mitk::NavigationData::Pointer emptyNd = mitk::NavigationData::New(); mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); position.Fill(0.0); emptyNd->SetPosition(position); emptyNd->SetOrientation(orientation); emptyNd->SetDataValid(false); mitk::NavigationData::Pointer tmp; for (unsigned int index = 0; index < this->GetNumberOfOutputs(); index++) { tmp = mitk::NavigationData::New(); tmp->Graft(emptyNd); this->SetNthOutput(index, tmp); } // find out _NumberOfSnapshots m_NumberOfSnapshots = 0; TiXmlElement* nextND = m_DataElem->FirstChildElement("NavigationData"); while(nextND) { ++m_NumberOfSnapshots; nextND = nextND->NextSiblingElement("NavigationData"); } // e.g. 12 nd found and 2 tools used => number of snapshots is 12:2=6 m_NumberOfSnapshots = m_NumberOfSnapshots/toolcount; } } void mitk::NavigationDataSequentialPlayer::GoToSnapshot(int i) { if(!m_Repeat && (this->GetNumberOfSnapshots() numOfUpdateCalls = 4 if(m_LastGoTo <= i) numOfUpdateCalls = i - m_LastGoTo; // goto(4), m_LastGoTo=7 => numOfUpdateCalls = 7 else { if(!m_Repeat) { std::stringstream message; message <<"Cannot go back to snapshot " << i << " because the " << this->GetNameOfClass() << " is configured to not repeat the" << " navigation data."; MITK_WARN << message.str(); mitkThrowException(mitk::IGTException) << message.str(); } else { numOfUpdateCalls = (m_NumberOfSnapshots - m_LastGoTo) + i; } } for(int j=0; jUpdate(); m_LastGoTo = i; } void mitk::NavigationDataSequentialPlayer:: SetFileName(const std::string& _FileName) { m_FileName = _FileName; if(!m_Doc->LoadFile(m_FileName)) { this->SetNumberOfOutputs(0); std::ostringstream s; s << "File " << _FileName << " could not be loaded"; mitkThrowException(mitk::IGTIOException)<ReinitXML(); } this->Modified(); } void mitk::NavigationDataSequentialPlayer:: SetXMLString(const std::string& _XMLString) { m_XMLString = _XMLString; if((m_Doc->Parse( m_XMLString.c_str()))== NULL) { this->ReinitXML(); } else { //if the string is not an XML string std::ostringstream s; s << "String" << _XMLString << " is not an XML string"; mitkThrowException(mitk::IGTIOException)<Modified(); } void mitk::NavigationDataSequentialPlayer::GenerateData() { assert(m_DataElem); // very important: go through the tools (there could be more than one) mitk::NavigationData::Pointer tmp; for (unsigned int index = 0; index < this->GetNumberOfOutputs(); index++) { // go to the first element if(!m_CurrentElem) m_CurrentElem = m_DataElem->FirstChildElement("NavigationData"); // go to the next element else { m_CurrentElem = m_CurrentElem->NextSiblingElement(); } // if repeat is on: go back to the first element (prior calls delivered NULL // elem) if(!m_CurrentElem && m_Repeat) m_CurrentElem = m_DataElem->FirstChildElement("NavigationData"); mitk::NavigationData* output = this->GetOutput(index); tmp = this->ReadVersion1(); if(tmp.IsNotNull()) { output->Graft(tmp); m_StreamValid = true; } else // no valid output { output->SetDataValid(false); m_StreamValid = false; m_ErrorMessage = "Error: Cannot parse input file."; mitkThrowException(mitk::IGTException)<ReadNavigationData(elem); } void mitk::NavigationDataSequentialPlayer::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataToPointSetFilter.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataToPointSetFilter.cpp index 4c0ce09a64..60445f9fc8 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataToPointSetFilter.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataToPointSetFilter.cpp @@ -1,246 +1,245 @@ /*=================================================================== 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 "mitkNavigationDataToPointSetFilter.h" #include #include -#include #include mitk::NavigationDataToPointSetFilter::NavigationDataToPointSetFilter() { this->SetNumberOfRequiredInputs(1); m_OperationMode = Mode3D; m_CurrentTimeStep = 0; m_RingBufferSize = 50; //the default ring buffer size m_NumberForMean = 100; } mitk::NavigationDataToPointSetFilter::~NavigationDataToPointSetFilter() { } void mitk::NavigationDataToPointSetFilter::GenerateData() { switch (m_OperationMode) { case Mode3D: GenerateDataMode3D(); break; case Mode3DMean: GenerateDataMode3DMean(); break; case Mode4D: GenerateDataMode4D(); break; default: break; } } void mitk::NavigationDataToPointSetFilter::SetInput(const NavigationData* nd) { // Process object is not const-correct so the const_cast is required here this->ProcessObject::SetNthInput(0, const_cast(nd)); this->CreateOutputsForAllInputs(); } void mitk::NavigationDataToPointSetFilter::SetInput(unsigned int idx, const NavigationData* nd) { // Process object is not const-correct so the const_cast is required here this->ProcessObject::SetNthInput(idx, const_cast(nd)); this->CreateOutputsForAllInputs(); } const mitk::NavigationData* mitk::NavigationDataToPointSetFilter::GetInput( void ) { if (this->GetNumberOfInputs() < 1) return NULL; return static_cast(this->ProcessObject::GetInput(0)); } const mitk::NavigationData* mitk::NavigationDataToPointSetFilter::GetInput( unsigned int idx ) { if (this->GetNumberOfInputs() < 1) return NULL; return static_cast(this->ProcessObject::GetInput(idx)); } void mitk::NavigationDataToPointSetFilter::CreateOutputsForAllInputs() { switch (m_OperationMode) { case Mode3D: this->SetNumberOfOutputs(this->GetNumberOfInputs()); // create one pointset output for each navigation data input break; case Mode3DMean: this->SetNumberOfOutputs(this->GetNumberOfInputs()); // create one pointset output for each navigation data input break; case Mode4D: this->SetNumberOfOutputs(1); // create just one output pointset that will contain all input navigation data objects break; default: break; } for (unsigned int idx = 0; idx < this->GetNumberOfOutputs(); ++idx) if (this->GetOutput(idx) == NULL) { DataObjectPointer newOutput = this->MakeOutput(idx); this->SetNthOutput(idx, newOutput); } this->Modified(); } void mitk::NavigationDataToPointSetFilter::GenerateDataMode3D() { for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i) // for each output PointSet { mitk::PointSet* output = this->GetOutput(i); assert(output); const mitk::NavigationData* input = this->GetInput(i); assert(input); if (input->IsDataValid() == false) // don't add point if input is invalid continue; mitk::PointSet::PointType pos = input->GetPosition(); // NavigationData::PositionType must be compatible with PointSet::PointType! output->InsertPoint(output->GetSize(), pos); // add point with current position of input NavigationData to the output PointSet // \TODO: regard ringbuffersize } } /** * @brief read n times all connected inputs and sum them into outputs. Finish with dividing each output by n. **/ void mitk::NavigationDataToPointSetFilter::GenerateDataMode3DMean() { //make it editable through a Set method if needed //check for outputs and inputs for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i) // for each output PointSet; change through pointsets to collect all navigation data in order { assert(this->GetOutput(i)); assert(this->GetInput(i)); } //vector of counters for each output std::vector counterVec(this->GetNumberOfOutputs(),0); //vector of old timesteps for each output std::vector vectorOldTime(this->GetNumberOfOutputs()); //use first Output to get the size of the pointsets. All output pointssets have to have the same size! mitk::PointSet::PointIdentifier newPointId = this->GetOutput(0)->GetSize(); bool numberForMean_is_reached = false; while (!numberForMean_is_reached) { for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i) // for each output PointSet; change through pointsets to collect all navigation data in order { mitk::PointSet* output = this->GetOutput(i); const mitk::NavigationData* input = this->GetInput(i); if (input->IsDataValid() == false) // don't add point if input is invalid continue;//do not store mitk::PointSet::PointType pos; if (counterVec[i] == 0) //first Element must be inserted { vectorOldTime[i] = input->GetTimeStamp(); //no need to call an update pos = input->GetPosition(); // NavigationData::PositionType must be compatible with PointSet::PointType! output->InsertPoint(newPointId, pos); // add point with current position of input NavigationData to the output PointSet counterVec[i]++; } else { //manually call an update to track new positions this->ProcessObject::GetInput(i)->Update(); input = this->GetInput(i); mitk::NavigationData::TimeStampType newTime = input->GetTimeStamp(); if (vectorOldTime[i]GetPosition(); // NavigationData::PositionType must be compatible with PointSet::PointType! //calculate the summ of the old position and the current coordinate mitk::Vector3D vec; vec.SetVnlVector(pos.GetVnlVector()); mitk::PointSet::PointType oPoint = output->GetPoint(newPointId); oPoint += vec;//summ up output->SetPoint(newPointId, oPoint); //store in counterVec to know how many have been added (and not skipped because of invalid data) counterVec[i]++; vectorOldTime[i] = newTime; } } // \TODO: regard ringbuffersize } numberForMean_is_reached = true; for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i) { if (counterVec[i]GetNumberOfOutputs() ; ++i) // for each output PointSet; change through pointsets to collect all navigation data in order { mitk::PointSet* output = this->GetOutput(i); mitk::PointSet::PointType oPoint = output->GetPoint(newPointId); for (unsigned int index = 0; index < oPoint.Size(); index++) oPoint[index] = oPoint[index] / counterVec[i]; output->SetPoint(newPointId, oPoint); MBI_INFO << "For output # " << i << ", " << counterVec[i] << " tracked positions used for averaging"; } } void mitk::NavigationDataToPointSetFilter::GenerateDataMode4D() { mitk::PointSet* output = GetOutput(); assert(output); for (unsigned int index = 0; index < this->GetNumberOfInputs(); index++) { const mitk::NavigationData* nd = GetInput(index); assert(nd); mitk::NavigationData::PositionType point = nd->GetPosition(); //get the position output->SetPoint( index, point, m_CurrentTimeStep); //store it in the pointset always at the current time step } if (m_CurrentTimeStep == m_RingBufferSize - 1) // update ring buffer index m_CurrentTimeStep = 0; else m_CurrentTimeStep++; } void mitk::NavigationDataToPointSetFilter::SetOperationMode( OperationMode mode ) { m_OperationMode = mode; //Initialize 4D Mode if (m_OperationMode == Mode4D) m_CurrentTimeStep = 0; this->Modified(); this->CreateOutputsForAllInputs(); } diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataToPointSetPlayer.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataToPointSetPlayer.cpp deleted file mode 100644 index 0bfc5a28eb..0000000000 --- a/Modules/IGT/IGTFilters/mitkNavigationDataToPointSetPlayer.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/*=================================================================== - -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 "mitkNavigationDataToPointSetPlayer.h" - -//for the pause -#include - -#include -#include -#include - -#include - -mitk::NavigationDataToPointSetPlayer::NavigationDataToPointSetPlayer() - : m_Doc(new TiXmlDocument) - , m_DataElem(0) - , m_CurrentElem(0) - , m_Repeat(false) - , m_NumberOfSnapshots(0) - , m_LastGoTo(0) -{ -} - - -mitk::NavigationDataToPointSetPlayer::~NavigationDataToPointSetPlayer() -{ - delete m_Doc; -} - -void mitk::NavigationDataToPointSetPlayer::ReinitXML() -{ - m_NDPointSet.clear(); - m_PointSetFilter = mitk::NavigationDataToPointSetFilter::New(); - - m_DataElem = m_Doc->FirstChildElement("Data"); - int toolcount; - if(!m_DataElem) - MITK_WARN << "Data element not found"; - else - { - m_DataElem->QueryIntAttribute("ToolCount", &toolcount); - this->SetNumberOfOutputs(toolcount); - - mitk::NavigationData::Pointer emptyNd = mitk::NavigationData::New(); - mitk::NavigationData::PositionType position; - mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); - position.Fill(0.0); - - emptyNd->SetPosition(position); - emptyNd->SetOrientation(orientation); - emptyNd->SetDataValid(false); - - mitk::NavigationData::Pointer tmp; - for (unsigned int index = 0; index < this->GetNumberOfOutputs(); index++) - { - tmp = mitk::NavigationData::New(); - tmp->Graft(emptyNd); - this->SetNthOutput(index, tmp); - } - - // find out _NumberOfSnapshots - - NavigationData::Pointer nd; - - m_NumberOfSnapshots = 0; - TiXmlElement* nextND = m_DataElem->FirstChildElement("NavigationData"); - - while(nextND) - { - ++m_NumberOfSnapshots; - nextND = nextND->NextSiblingElement("NavigationData"); - } - - // e.g. 12 nd found and 2 tools used => number of snapshots is 12:2=6 - m_NumberOfSnapshots = m_NumberOfSnapshots/toolcount; - - /*NavigationData::TimeStampType recordedTime = (lastTimestamp-firstTimestamp) / 1000; - int frameRate = static_cast(floor(1000 / (float) (m_NumberOfSnapshots/recordedTime) + 0.5));*/ - - } -} - - - -void mitk::NavigationDataToPointSetPlayer:: - SetFileName(const std::string& _FileName) -{ - m_FileName = _FileName; - - if(!m_Doc->LoadFile(m_FileName)) - { - this->SetNumberOfOutputs(0); - std::ostringstream s; - s << "File " << _FileName << " could not be loaded"; - throw std::invalid_argument(s.str()); - } - else - { - this->ReinitXML(); - } - - this->Modified(); -} - - -void mitk::NavigationDataToPointSetPlayer::GenerateData() -{ - assert(m_DataElem); - - // very important: go through the tools (there could be more then one) - mitk::NavigationData::Pointer tmp; - for (unsigned int index = 0; index < this->GetNumberOfOutputs(); index++) - { - // go to the first element - if(!m_CurrentElem) - m_CurrentElem = m_DataElem->FirstChildElement("NavigationData"); - // go to the next element - else - m_CurrentElem = m_CurrentElem->NextSiblingElement(); - - // if repeat is on: go back to the first element (prior calls delivered NULL - // elem) - if(!m_CurrentElem && m_Repeat) - m_CurrentElem = m_DataElem->FirstChildElement("NavigationData"); - - mitk::NavigationData* output = this->GetOutput(index); - tmp = this->ReadVersion1(); - if(tmp.IsNotNull()) - output->Graft(tmp); - else // no valid output - output->SetDataValid(false); - } -} - - -void mitk::NavigationDataToPointSetPlayer::StartPlaying() -{ - //TODO -} - -void mitk::NavigationDataToPointSetPlayer::StopPlaying() -{ - //TODO -} - -void mitk::NavigationDataToPointSetPlayer::Pause() -{ - //TODO -} - -void mitk::NavigationDataToPointSetPlayer::Resume() -{ - //TODO -} - - -//TODO -const bool mitk::NavigationDataToPointSetPlayer::IsAtEnd() -{ - bool result = false; - return result; -} - -mitk::NavigationData::Pointer mitk::NavigationDataToPointSetPlayer::ReadVersion1() -{ - TiXmlElement* elem = m_CurrentElem; - - if(!elem) - return NULL; - - return this->ReadNavigationData(elem); -} - -void mitk::NavigationDataToPointSetPlayer::UpdateOutputInformation() -{ - this->Modified(); // make sure that we need to be updated - Superclass::UpdateOutputInformation(); -} diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataToPointSetPlayer.h b/Modules/IGT/IGTFilters/mitkNavigationDataToPointSetPlayer.h deleted file mode 100644 index 2966634d47..0000000000 --- a/Modules/IGT/IGTFilters/mitkNavigationDataToPointSetPlayer.h +++ /dev/null @@ -1,158 +0,0 @@ -/*=================================================================== - -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 MITKNavigationDataToPointSetPlayer_H_HEADER_INCLUDED_ -#define MITKNavigationDataToPointSetPlayer_H_HEADER_INCLUDED_ - -#include -#include -#include -#include "tinyxml.h" - - -namespace mitk -{ - - /**Documentation - * \brief This class is a slightly changed reimplementation of the - * NavigationDataPlayer which does not care about timestamps and just - * outputs the navigationdatas in their sequential order - * - * \ingroup IGT - */ - class MitkIGT_EXPORT NavigationDataToPointSetPlayer - : public NavigationDataPlayerBase - { - public: - mitkClassMacro(NavigationDataToPointSetPlayer, NavigationDataPlayerBase); - itkNewMacro(Self); - - /** - * \brief sets the file name and path (if XMLString is set, this is neglected) - */ - void SetFileName(const std::string& _FileName); - - /** - * \brief returns the file name and path - */ - itkGetStringMacro(FileName); - - /** - * \brief sets a xml string (by this, the xml string is not read from file) - */ - void SetXMLString(const std::string& _XMLString); - - /** - * \brief returns the current xml string - */ - itkGetStringMacro(XMLString); - - /// - /// set to true if the data player should repeat the outputs - /// - itkSetMacro(Repeat, bool); - /// - /// set if the data player should repeat the outputs - /// - itkGetMacro(Repeat, bool); - /// - /// \return the number of navigation data snapshots available in the file - /// - itkGetMacro(NumberOfSnapshots, unsigned int); - - /// - /// advance the output to the i-th snapshot - /// e.g. if you want to have the NavData of snapshot - /// 17 then you can call GoToSnapshot(17). index begins at 1! - /// you can then also go back to snapshot 1 with GoToSnapshot(1) - /// - void GoToSnapshot(int i); - - /** - * \brief Used for pipeline update just to tell the pipeline - * that we always have to update - */ - virtual void UpdateOutputInformation(); - - - - /** - * \brief This method starts the player. - * - * Before the stream has to be set. Either with a PlayingMode (SetStream(PlayerMode)) and FileName. Or - * with an own inputstream (SetStream(istream*)). - */ - void StartPlaying(); - - /** - * \brief Stops the player and closes the stream. After a call of StopPlaying() - * StartPlaying() must be called to get new output data - * - * \warning the output is generated in this method because we know first about the number of output after - * reading the first lines of the XML file. Therefore you should assign your output after the call of this method - */ - void StopPlaying(); - - /** - * \brief This method pauses the player. If you want to play again call Resume() - * - *\warning This method is not tested yet. It is not save to use! - */ - void Pause(); - - /** - * \brief This method resumes the player when it was paused. - * - *\warning This method is not tested yet. It is not save to use! - */ - void Resume(); - - - - - - - - const bool IsAtEnd(); - - protected: - NavigationDataToPointSetPlayer(); - virtual ~NavigationDataToPointSetPlayer(); - void ReinitXML(); - mitk::NavigationData::Pointer ReadVersion1(); - /// - /// do the work here - /// - virtual void GenerateData(); - - - NavigationDataToPointSetFilter::Pointer m_PointSetFilter; - - std::string m_FileName; - std::string m_XMLString; - TiXmlDocument* m_Doc; - TiXmlElement* m_DataElem; - TiXmlElement* m_CurrentElem; - bool m_Repeat; - unsigned int m_NumberOfSnapshots; - int m_LastGoTo; - - std::vector m_NDPointSet; - }; -} // namespace mitk - -#endif /* MITKNavigationDataToPointSetPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IGTFilters/mitkTrackingDeviceSource.cpp b/Modules/IGT/IGTFilters/mitkTrackingDeviceSource.cpp index 674ef77ef2..3a068bb2f7 100644 --- a/Modules/IGT/IGTFilters/mitkTrackingDeviceSource.cpp +++ b/Modules/IGT/IGTFilters/mitkTrackingDeviceSource.cpp @@ -1,215 +1,215 @@ /*=================================================================== 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 "mitkTrackingDeviceSource.h" #include "mitkTrackingDevice.h" #include "mitkTrackingTool.h" -#include "mitkTimeStamp.h" +#include "mitkIGTTimeStamp.h" mitk::TrackingDeviceSource::TrackingDeviceSource() : mitk::NavigationDataSource(), m_TrackingDevice(NULL) { } mitk::TrackingDeviceSource::~TrackingDeviceSource() { if (m_TrackingDevice.IsNotNull()) { if (m_TrackingDevice->GetState() == mitk::TrackingDevice::Tracking) { this->StopTracking(); } if (m_TrackingDevice->GetState() == mitk::TrackingDevice::Ready) { this->Disconnect(); } m_TrackingDevice = NULL; } } void mitk::TrackingDeviceSource::GenerateData() { if (m_TrackingDevice.IsNull()) return; if (m_TrackingDevice->GetToolCount() < 1) return; if (this->GetNumberOfOutputs() != m_TrackingDevice->GetToolCount()) // mismatch between tools and outputs. What should we do? Were tools added to the tracking device after SetTrackingDevice() was called? { //check this: TODO: ////this might happen if a tool is plugged into an aurora during tracking. //this->CreateOutputs(); std::stringstream ss; ss << "mitk::TrackingDeviceSource: not enough outputs available for all tools. " << this->GetNumberOfOutputs() << " outputs available, but " << m_TrackingDevice->GetToolCount() << " tools available in the tracking device."; throw std::out_of_range(ss.str()); } /* update outputs with tracking data from tools */ unsigned int toolCount = m_TrackingDevice->GetToolCount(); for (unsigned int i = 0; i < toolCount; ++i) { mitk::NavigationData* nd = this->GetOutput(i); assert(nd); mitk::TrackingTool* t = m_TrackingDevice->GetTool(i); assert(t); if ((t->IsEnabled() == false) || (t->IsDataValid() == false)) { nd->SetDataValid(false); continue; } nd->SetDataValid(true); mitk::NavigationData::PositionType p; t->GetPosition(p); nd->SetPosition(p); mitk::NavigationData::OrientationType o; t->GetOrientation(o); nd->SetOrientation(o); nd->SetOrientationAccuracy(t->GetTrackingError()); nd->SetPositionAccuracy(t->GetTrackingError()); - nd->SetTimeStamp( mitk::TimeStamp::GetInstance()->GetElapsed() ); + nd->SetTimeStamp( mitk::IGTTimeStamp::GetInstance()->GetElapsed() ); } } void mitk::TrackingDeviceSource::SetTrackingDevice( mitk::TrackingDevice* td ) { MITK_DEBUG << "Setting TrackingDevice to " << td; if (this->m_TrackingDevice.GetPointer() != td) { this->m_TrackingDevice = td; this->CreateOutputs(); std::stringstream name; // create a human readable name for the source name << td->GetData().Model << " Tracking Source"; this->SetName(name.str()); } } void mitk::TrackingDeviceSource::CreateOutputs(){ //if outputs are set then delete them if (this->GetNumberOfOutputs() > 0) { for (unsigned int numOP = this->GetNumberOfOutputs(); numOP>0; numOP--) this->RemoveOutput(this->GetOutput(numOP)); this->Modified(); } //fill the outputs if a valid tracking device is set if (m_TrackingDevice.IsNull()) return; this->SetNumberOfOutputs(m_TrackingDevice->GetToolCount()); // create outputs for all tools unsigned int numberOfOutputs = this->GetNumberOfOutputs(); for (unsigned int idx = 0; idx < numberOfOutputs; ++idx) { if (this->GetOutput(idx) == NULL) { DataObjectPointer newOutput = this->MakeOutput(idx); static_cast(newOutput.GetPointer())->SetName(m_TrackingDevice->GetTool(idx)->GetToolName()); // set NavigationData name to ToolName this->SetNthOutput(idx, newOutput); this->Modified(); } } } void mitk::TrackingDeviceSource::Connect() { if (m_TrackingDevice.IsNull()) throw std::invalid_argument("mitk::TrackingDeviceSource: No tracking device set"); if (this->IsConnected()) return; if (m_TrackingDevice->OpenConnection() == false) throw std::runtime_error(std::string("mitk::TrackingDeviceSource: Could not open connection to tracking device. Error: ") + m_TrackingDevice->GetErrorMessage()); /* NDI Aurora needs a connection to discover tools that are connected to it. Therefore we need to create outputs for these tools now */ //if (m_TrackingDevice->GetType() == mitk::NDIAurora) //this->CreateOutputs(); } void mitk::TrackingDeviceSource::StartTracking() { if (m_TrackingDevice.IsNull()) throw std::invalid_argument("mitk::TrackingDeviceSource: No tracking device set"); if (m_TrackingDevice->GetState() == mitk::TrackingDevice::Tracking) return; if (m_TrackingDevice->StartTracking() == false) throw std::runtime_error("mitk::TrackingDeviceSource: Could not start tracking"); } void mitk::TrackingDeviceSource::Disconnect() { if (m_TrackingDevice.IsNull()) throw std::invalid_argument("mitk::TrackingDeviceSource: No tracking device set"); if (m_TrackingDevice->CloseConnection() == false) throw std::runtime_error("mitk::TrackingDeviceSource: Could not close connection to tracking device"); } void mitk::TrackingDeviceSource::StopTracking() { if (m_TrackingDevice.IsNull()) throw std::invalid_argument("mitk::TrackingDeviceSource: No tracking device set"); if (m_TrackingDevice->StopTracking() == false) throw std::runtime_error("mitk::TrackingDeviceSource: Could not stop tracking"); } void mitk::TrackingDeviceSource::UpdateOutputInformation() { if(this->GetTrackingDevice()->GetToolCount() != this->GetNumberOfOutputs()) this->CreateOutputs(); this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } //unsigned int mitk::TrackingDeviceSource::GetToolCount() //{ // if (m_TrackingDevice) // return m_TrackingDevice->GetToolCount(); // return 0; //} bool mitk::TrackingDeviceSource::IsConnected() { if (m_TrackingDevice.IsNull()) return false; return (m_TrackingDevice->GetState() == mitk::TrackingDevice::Ready) || (m_TrackingDevice->GetState() == mitk::TrackingDevice::Tracking); } bool mitk::TrackingDeviceSource::IsTracking() { if (m_TrackingDevice.IsNull()) return false; return m_TrackingDevice->GetState() == mitk::TrackingDevice::Tracking; } diff --git a/Modules/IGT/IGTTrackingDevices/mitkClaronTrackingDevice.cpp b/Modules/IGT/IGTTrackingDevices/mitkClaronTrackingDevice.cpp index 1f3b47dc4c..cfdda85099 100644 --- a/Modules/IGT/IGTTrackingDevices/mitkClaronTrackingDevice.cpp +++ b/Modules/IGT/IGTTrackingDevices/mitkClaronTrackingDevice.cpp @@ -1,327 +1,327 @@ /*=================================================================== 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 "mitkClaronTrackingDevice.h" #include "mitkClaronTool.h" #include "mitkIGTConfig.h" -#include "mitkTimeStamp.h" +#include "mitkIGTTimeStamp.h" #include #include #include typedef itk::MutexLockHolder MutexLockHolder; mitk::ClaronTrackingDevice::ClaronTrackingDevice(): mitk::TrackingDevice() { //set the type of this tracking device this->m_Data = mitk::DeviceDataMicronTrackerH40; this->m_MultiThreader = itk::MultiThreader::New(); m_ThreadID = 0; m_Device = mitk::ClaronInterface::New(); //############################# standard directories (from cmake) ################################## if (m_Device->IsMicronTrackerInstalled()) { #ifdef MITK_MICRON_TRACKER_TEMP_DIR m_ToolfilesDir = std::string(MITK_MICRON_TRACKER_TEMP_DIR); m_ToolfilesDir.append("/MT-tools"); #endif #ifdef MITK_MICRON_TRACKER_CALIBRATION_DIR m_CalibrationDir = std::string(MITK_MICRON_TRACKER_CALIBRATION_DIR); #endif } else { m_ToolfilesDir = "Error - No Microntracker installed"; m_CalibrationDir = "Error - No Microntracker installed"; } //################################################################################################## m_Device->Initialize(m_CalibrationDir, m_ToolfilesDir); } mitk::ClaronTrackingDevice::~ClaronTrackingDevice() { } mitk::TrackingTool* mitk::ClaronTrackingDevice::AddTool( const char* toolName, const char* fileName ) { mitk::ClaronTool::Pointer t = mitk::ClaronTool::New(); if (t->LoadFile(fileName) == false) { return NULL; } t->SetToolName(toolName); if (this->InternalAddTool(t) == false) return NULL; return t.GetPointer(); } bool mitk::ClaronTrackingDevice::InternalAddTool(ClaronTool::Pointer tool) { m_AllTools.push_back(tool); return true; } std::vector mitk::ClaronTrackingDevice::DetectTools() { std::vector returnValue; std::vector allHandles = m_Device->GetAllActiveTools(); for (std::vector::iterator iter = allHandles.begin(); iter != allHandles.end(); ++iter) { ClaronTool::Pointer newTool = ClaronTool::New(); newTool->SetToolName(m_Device->GetName(*iter)); newTool->SetCalibrationName(m_Device->GetName(*iter)); newTool->SetToolHandle(*iter); returnValue.push_back(newTool); } return returnValue; } bool mitk::ClaronTrackingDevice::StartTracking() { //By Alfred: next line because no temp directory is set if MicronTracker is not installed if (!m_Device->IsMicronTrackerInstalled()) return false; //################################################################################## //be sure that the temp-directory is empty at start: delete all files in the tool files directory itksys::SystemTools::RemoveADirectory(m_ToolfilesDir.c_str()); itksys::SystemTools::MakeDirectory(m_ToolfilesDir.c_str()); //copy all toolfiles into the temp directory for (unsigned int i=0; iGetFile().c_str(), m_ToolfilesDir.c_str()); } 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(); //restart the Microntracker, so it will load the new tool files m_Device->StopTracking(); m_Device->Initialize(m_CalibrationDir,m_ToolfilesDir); m_TrackingFinishedMutex->Unlock(); // transfer the execution rights to tracking thread if (m_Device->StartTracking()) { - mitk::TimeStamp::GetInstance()->Start(this); + mitk::IGTTimeStamp::GetInstance()->Start(this); m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this); // start a new thread that executes the TrackTools() method return true; } else { m_ErrorMessage = "Error while trying to start the device!"; return false; } } bool mitk::ClaronTrackingDevice::StopTracking() { Superclass::StopTracking(); //delete all files in the tool files directory itksys::SystemTools::RemoveADirectory(m_ToolfilesDir.c_str()); return true; } unsigned int mitk::ClaronTrackingDevice::GetToolCount() const { return (unsigned int)this->m_AllTools.size(); } mitk::TrackingTool* mitk::ClaronTrackingDevice::GetTool(unsigned int toolNumber) const { if ( toolNumber >= this->GetToolCount()) return NULL; else return this->m_AllTools[toolNumber]; } bool mitk::ClaronTrackingDevice::OpenConnection() { bool returnValue; //Create the temp directory itksys::SystemTools::MakeDirectory(m_ToolfilesDir.c_str()); m_Device->Initialize(m_CalibrationDir,m_ToolfilesDir); returnValue = m_Device->StartTracking(); if (returnValue) { this->SetState(Ready); } else { //reset everything if (m_Device.IsNull()) { m_Device = mitk::ClaronInterface::New(); m_Device->Initialize(m_CalibrationDir, m_ToolfilesDir); } m_Device->StopTracking(); this->SetState(Setup); m_ErrorMessage = "Error while trying to open connection to the MicronTracker."; } return returnValue; } bool mitk::ClaronTrackingDevice::CloseConnection() { bool returnValue = true; if (this->GetState() == Setup) return true; returnValue = m_Device->StopTracking(); //delete the temporary directory itksys::SystemTools::RemoveADirectory(m_ToolfilesDir.c_str()); this->SetState(Setup); return returnValue; } mitk::ClaronInterface* mitk::ClaronTrackingDevice::GetDevice() { return m_Device; } std::vector mitk::ClaronTrackingDevice::GetAllTools() { return this->m_AllTools; } void mitk::ClaronTrackingDevice::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(); while ((this->GetState() == Tracking) && (localStopTracking == false)) { this->GetDevice()->GrabFrame(); std::vector detectedTools = this->DetectTools(); std::vector allTools = this->GetAllTools(); std::vector::iterator itAllTools; for(itAllTools = allTools.begin(); itAllTools != allTools.end(); itAllTools++) { mitk::ClaronTool::Pointer currentTool = *itAllTools; //test if current tool was detected std::vector::iterator itDetectedTools; bool foundTool = false; for(itDetectedTools = detectedTools.begin(); itDetectedTools != detectedTools.end(); itDetectedTools++) { mitk::ClaronTool::Pointer aktuDet = *itDetectedTools; std::string tempString(currentTool->GetCalibrationName()); if (tempString.compare(aktuDet->GetCalibrationName())==0) { currentTool->SetToolHandle(aktuDet->GetToolHandle()); foundTool = true; } } if (!foundTool) { currentTool->SetToolHandle(0); } if (currentTool->GetToolHandle() != 0) { currentTool->SetDataValid(true); //get tip position of tool: std::vector pos_vector = this->GetDevice()->GetTipPosition(currentTool->GetToolHandle()); //write tip position into tool: mitk::Point3D pos; pos[0] = pos_vector[0]; pos[1] = pos_vector[1]; pos[2] = pos_vector[2]; currentTool->SetPosition(pos); //get tip quaternion of tool std::vector quat = this->GetDevice()->GetTipQuaternions(currentTool->GetToolHandle()); //write tip quaternion into tool mitk::Quaternion orientation(quat[1], quat[2], quat[3], quat[0]); currentTool->SetOrientation(orientation); } else { mitk::Point3D origin; origin.Fill(0); currentTool->SetPosition(origin); currentTool->SetOrientation(mitk::Quaternion(0,0,0,0)); currentTool->SetDataValid(false); } } /* Update the local copy of m_StopTracking */ this->m_StopTrackingMutex->Lock(); localStopTracking = m_StopTracking; this->m_StopTrackingMutex->Unlock(); } } catch(...) { this->StopTracking(); this->SetErrorMessage("Error while trying to track tools. Thread stopped."); } } bool mitk::ClaronTrackingDevice::IsMicronTrackerInstalled() { return this->m_Device->IsMicronTrackerInstalled(); } ITK_THREAD_RETURN_TYPE mitk::ClaronTrackingDevice::ThreadStartTracking(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } ClaronTrackingDevice *trackingDevice = (ClaronTrackingDevice*)pInfo->UserData; if (trackingDevice != NULL) trackingDevice->TrackTools(); return ITK_THREAD_RETURN_VALUE; } diff --git a/Modules/IGT/IGTTrackingDevices/mitkNDITrackingDevice.cpp b/Modules/IGT/IGTTrackingDevices/mitkNDITrackingDevice.cpp index 42ff051758..92221dc306 100644 --- a/Modules/IGT/IGTTrackingDevices/mitkNDITrackingDevice.cpp +++ b/Modules/IGT/IGTTrackingDevices/mitkNDITrackingDevice.cpp @@ -1,1321 +1,1321 @@ /*=================================================================== 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 "mitkTimeStamp.h" +#include "mitkIGTTimeStamp.h" #include #include #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_NDITrackingVolume(Standard), m_IlluminationActivationRate(Hz20), m_DataTransferMode(TX), m_6DTools(), m_ToolsMutex(NULL), m_SerialCommunication(NULL), m_SerialCommunicationMutex(NULL), m_DeviceProtocol(NULL), m_MultiThreader(NULL), m_ThreadID(0), m_OperationMode(ToolTracking6D), m_MarkerPointsMutex(NULL), m_MarkerPoints() { m_Data = mitk::DeviceDataUnspecified; 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 == NULL) return false; std::string portHandle = ndiTool->GetPortHandle(); //return false if the SROM Data has not been set if (ndiTool->GetSROMData() == NULL) 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; } } 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 = NULL; /* free serial communication interface */ if (m_SerialCommunication.IsNotNull()) { m_SerialCommunication->ClearReceiveBuffer(); m_SerialCommunication->ClearSendBuffer(); m_SerialCommunication->CloseConnection(); m_SerialCommunication = NULL; } } 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 == NULL) 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 == NULL) 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 == NULL) 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 == NULL) 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 == NULL) 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) { this->SetErrorMessage("Can only try to open the connection if in setup mode"); return false; } // 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 { this->SetErrorMessage("Can not open serial port"); m_SerialCommunication->CloseConnection(); m_SerialCommunication = NULL; return false; } /* 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 { this->SetErrorMessage("Hardware Reset of tracking device did not work"); if (m_SerialCommunication.IsNotNull()) { m_SerialCommunication->CloseConnection(); m_SerialCommunication = NULL; } return false; } /* Now the tracking device is 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) { this->SetErrorMessage("Could not set comm settings in trackingdevice"); return false; } //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) { this->SetErrorMessage("Could not initialize the tracking device"); return false; } if (this->GetType() == mitk::TrackingSystemNotSpecified) // 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::TrackingSystemNotSpecified)) { this->SetErrorMessage("Could not determine tracking device type. Please set manually and try again."); return false; } 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; Tool6DContainerType::iterator endIt = m_6DTools.end(); for(Tool6DContainerType::iterator 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 == NDIPolaris) { returnvalue = m_DeviceProtocol->PVWR(&portHandle, (*it)->GetSROMData(), (*it)->GetSROMDataLength()); if (returnvalue != NDIOKAY) { this->SetErrorMessage((std::string("Could not write SROM file for tool '") + (*it)->GetToolName() + std::string("' to tracking device")).c_str()); return false; } returnvalue = m_DeviceProtocol->PINIT(&portHandle); if (returnvalue != NDIOKAY) { this->SetErrorMessage((std::string("Could not initialize tool '") + (*it)->GetToolName()).c_str()); return false; } if ((*it)->IsEnabled() == true) { returnvalue = m_DeviceProtocol->PENA(&portHandle, (*it)->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { this->SetErrorMessage((std::string("Could not enable port '") + portHandle + std::string("' for tool '")+ (*it)->GetToolName() + std::string("'")).c_str()); return false; } } } } } } // 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 == NDIPolaris) { returnvalue = m_DeviceProtocol->IRATE(this->m_IlluminationActivationRate); if (returnvalue != NDIOKAY) { this->SetErrorMessage("Could not set the illuminator activation rate"); return false; } } /* finish - now all tools should be added, initialized and enabled, so that tracking can be started */ this->SetState(Ready); this->SetErrorMessage(""); return true; } bool mitk::NDITrackingDevice::InitializeWiredTools() { NDIErrorCode returnvalue; std::string portHandle; returnvalue = m_DeviceProtocol->PHSR(OCCUPIED, &portHandle); if (returnvalue != NDIOKAY) { this->SetErrorMessage("Could not obtain a list of port handles that are connected"); return false; // ToDo: Is this a fatal error? } /* 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 == NULL) // if we don't have a tool, something is wrong. Tools should be discovered first by calling DiscoverWiredTools() continue; if (pt->GetSROMData() == NULL) continue; returnvalue = m_DeviceProtocol->PVWR(&ph, pt->GetSROMData(), pt->GetSROMDataLength()); if (returnvalue != NDIOKAY) { this->SetErrorMessage((std::string("Could not write SROM file for tool '") + pt->GetToolName() + std::string("' to tracking device")).c_str()); return false; } returnvalue = m_DeviceProtocol->PINIT(&ph); if (returnvalue != NDIOKAY) { this->SetErrorMessage((std::string("Could not initialize tool '") + pt->GetToolName()).c_str()); return false; } if (pt->IsEnabled() == true) { returnvalue = m_DeviceProtocol->PENA(&ph, pt->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { this->SetErrorMessage((std::string("Could not enable port '") + portHandle + std::string("' for tool '")+ pt->GetToolName() + std::string("'")).c_str()); return false; } } } return true; } mitk::TrackingDeviceType mitk::NDITrackingDevice::TestConnection() { if (this->GetState() != Setup) { return mitk::TrackingSystemNotSpecified; } 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 = NULL; return mitk::TrackingSystemNotSpecified; } /* 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 { this->SetErrorMessage("Hardware Reset of tracking device did not work"); m_SerialCommunication->CloseConnection(); m_SerialCommunication = NULL; return mitk::TrackingSystemNotSpecified; } /* 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::TrackingSystemNotSpecified)) { m_SerialCommunication = NULL; return mitk::TrackingSystemNotSpecified; } m_SerialCommunication = NULL; 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); this->SetErrorMessage(""); m_SerialCommunication = NULL; } 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 == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } NDITrackingDevice *trackingDevice = (NDITrackingDevice*)pInfo->UserData; if (trackingDevice != NULL) { 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_TrackingFinishedMutex->Unlock(); // transfer the execution rights to tracking thread m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this); // start a new thread that executes the TrackTools() method - mitk::TimeStamp::GetInstance()->Start(this); + mitk::IGTTimeStamp::GetInstance()->Start(this); return true; } void mitk::NDITrackingDevice::TrackTools() { if (this->GetState() != Tracking) return; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->TSTART(); if (returnvalue != NDIOKAY) return; /* 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(); 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) { /* insert error handling/notification here */ ; // how can this thread tell the application, that an error has occurred? } 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() { if (m_OperationMode == ToolTracking6D) return; if (this->GetState() != Tracking) return; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->DSTART(); // Start Diagnostic Mode if (returnvalue != NDIOKAY) return; 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(); 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() { if (m_OperationMode != HybridTracking) return; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->TSTART(); // Start Diagnostic Mode if (returnvalue != NDIOKAY) return; 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(); 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 NULL; } mitk::TrackingTool* mitk::NDITrackingDevice::GetToolByName(std::string name) const { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex Tool6DContainerType::const_iterator end = m_6DTools.end(); for (Tool6DContainerType::const_iterator iterator = m_6DTools.begin(); iterator != end; ++iterator) if (name.compare((*iterator)->GetToolName()) == 0) return *iterator; return NULL; } mitk::NDIPassiveTool* mitk::NDITrackingDevice::GetInternalTool(std::string portHandle) { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex Tool6DContainerType::iterator end = m_6DTools.end(); for (Tool6DContainerType::iterator iterator = m_6DTools.begin(); iterator != end; ++iterator) if (portHandle.compare((*iterator)->GetPortHandle()) == 0) return *iterator; return NULL; } 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 NULL; t->SetToolName(toolName); t->SetTrackingPriority(p); if (this->InternalAddTool(t) == false) return NULL; return t.GetPointer(); } bool mitk::NDITrackingDevice::InternalAddTool(mitk::NDIPassiveTool* tool) { if (tool == NULL) 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) { this->SetErrorMessage((std::string("Could not write SROM file for tool '") + p->GetToolName() + std::string("' to tracking device")).c_str()); return false; } /* initialize the port handle */ returnvalue = m_DeviceProtocol->PINIT(&newPortHandle); if (returnvalue != NDIOKAY) { this->SetErrorMessage((std::string("Could not initialize port '") + newPortHandle + std::string("' for tool '")+ p->GetToolName() + std::string("'")).c_str()); return false; } /* enable the port handle */ if (p->IsEnabled() == true) { returnvalue = m_DeviceProtocol->PENA(&newPortHandle, p->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { this->SetErrorMessage((std::string("Could not enable port '") + newPortHandle + std::string("' for tool '")+ p->GetToolName() + std::string("'")).c_str()); return false; } } } /* 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 == NULL) 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 Tool6DContainerType::iterator end = m_6DTools.end(); for (Tool6DContainerType::iterator 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 Tool6DContainerType::iterator end = m_6DTools.end(); for (Tool6DContainerType::iterator 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 Tool6DContainerType::iterator end = m_6DTools.end(); for (Tool6DContainerType::iterator 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) { this->SetErrorMessage("Could not obtain a list of port handles that are connected"); return false; // ToDo: Is this a fatal error? } /* 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) != NULL) // 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) { this->SetErrorMessage((std::string("Could not initialize port '") + ph + std::string("' for tool '")+ newTool->GetToolName() + std::string("'")).c_str()); return false; } /* enable the port handle */ returnvalue = m_DeviceProtocol->PENA(&ph, newTool->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { this->SetErrorMessage((std::string("Could not enable port '") + ph + std::string("' for tool '")+ newTool->GetToolName() + std::string("'")).c_str()); return false; } } //we have to temporarily unlock m_ModeMutex here to avoid a deadlock with another lock inside InternalAddTool() if (this->InternalAddTool(newTool) == false) this->SetErrorMessage("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) { this->SetErrorMessage("Could not obtain a list of port handles that need to be freed"); return returnvalue; // ToDo: Is this a fatal error? } /* 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 != NULL) // 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) { this->SetErrorMessage("Could not free all port handles"); // return false; // could not free all Handles } } } return returnvalue; } int mitk::NDITrackingDevice::GetMajorFirmwareRevisionNumber() { std::string revision; if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9) ) { this->SetErrorMessage("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) ) { this->SetErrorMessage("Could not receive firmware revision number!"); revision = ""; return revision.c_str(); } return revision.c_str(); } bool mitk::NDITrackingDevice::GetSupportedVolumes(unsigned int* numberOfVolumes, mitk::NDITrackingDevice::NDITrackingVolumeContainerType* volumes, mitk::NDITrackingDevice::TrackingVolumeDimensionType* volumesDimensions) { if (numberOfVolumes == NULL || volumes == NULL || volumesDimensions == NULL) return false; static std::string info; if (m_DeviceProtocol->SFLIST(&info) != mitk::NDIOKAY || info.empty()) { this->SetErrorMessage("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()); std::string standard = "0"; std::string pyramid = "4"; std::string spectraPyramid = "5"; std::string vicraVolume = "7"; std::string cube = "9"; std::string dome = "A"; if (currentVolume.compare(0,1,standard)==0) volumes->push_back(mitk::Standard); if (currentVolume.compare(0,1,pyramid)==0) volumes->push_back(mitk::Pyramid); if (currentVolume.compare(0,1,spectraPyramid)==0) volumes->push_back(mitk::SpectraPyramid); if (currentVolume.compare(0,1,vicraVolume)==0) volumes->push_back(mitk::VicraVolume); else if (currentVolume.compare(0,1,cube)==0) volumes->push_back(mitk::Cube);//alias cube else if (currentVolume.compare(0,1,dome)==0) volumes->push_back(mitk::Dome); //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(NDITrackingVolume volume) { if (m_DeviceProtocol->VSEL(volume) != mitk::NDIOKAY) { this->SetErrorMessage("Could not set volume!"); return false; } return true; } diff --git a/Modules/IGT/IGTTrackingDevices/mitkTrackingDevice.cpp b/Modules/IGT/IGTTrackingDevices/mitkTrackingDevice.cpp index 148e9b31b2..1a67441b11 100644 --- a/Modules/IGT/IGTTrackingDevices/mitkTrackingDevice.cpp +++ b/Modules/IGT/IGTTrackingDevices/mitkTrackingDevice.cpp @@ -1,108 +1,108 @@ /*=================================================================== 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 "mitkTimeStamp.h" +#include "mitkIGTTimeStamp.h" #include "mitkTrackingTool.h" #include typedef itk::MutexLockHolder MutexLockHolder; mitk::TrackingDevice::TrackingDevice() : m_Data(mitk::DeviceDataUnspecified), m_State(mitk::TrackingDevice::Setup), m_StopTracking(false), m_ErrorMessage("") { m_StopTrackingMutex = itk::FastMutexLock::New(); m_StateMutex = itk::FastMutexLock::New(); m_TrackingFinishedMutex = itk::FastMutexLock::New(); m_TrackingFinishedMutex->Lock(); // execution rights are owned by the application thread at the beginning } mitk::TrackingDevice::~TrackingDevice() { } 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(); } mitk::TrackingDeviceType mitk::TrackingDevice::GetType() const{ return m_Data.Line; } void mitk::TrackingDevice::SetType(mitk::TrackingDeviceType deviceType){ m_Data = mitk::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::TimeStamp::GetInstance()->Stop(this); // notify realtime clock + 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); } 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 NULL; } diff --git a/Modules/IGT/IGTTrackingDevices/mitkVirtualTrackingDevice.cpp b/Modules/IGT/IGTTrackingDevices/mitkVirtualTrackingDevice.cpp index 4b2abf2990..04899e16cb 100644 --- a/Modules/IGT/IGTTrackingDevices/mitkVirtualTrackingDevice.cpp +++ b/Modules/IGT/IGTTrackingDevices/mitkVirtualTrackingDevice.cpp @@ -1,318 +1,318 @@ /*=================================================================== 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 "mitkVirtualTrackingDevice.h" +#include "mitkIGTTimeStamp.h" #include #include #include -#include #include #include typedef itk::MutexLockHolder MutexLockHolder; mitk::VirtualTrackingDevice::VirtualTrackingDevice() : mitk::TrackingDevice(), m_AllTools(), m_ToolsMutex(NULL), m_MultiThreader(NULL), m_ThreadID(-1), m_RefreshRate(100), m_NumberOfControlPoints(20) { m_Data = mitk::DeviceDataVirtualTracker; m_Bounds[0] = m_Bounds[2] = m_Bounds[4] = -400.0; // initialize bounds to -400 ... +400 (mm) cube m_Bounds[1] = m_Bounds[3] = m_Bounds[5] = 400.0; m_ToolsMutex = itk::FastMutexLock::New(); } mitk::VirtualTrackingDevice::~VirtualTrackingDevice() { if (this->GetState() == Tracking) { this->StopTracking(); } if (this->GetState() == Ready) { this->CloseConnection(); } /* cleanup tracking thread */ if (m_MultiThreader.IsNotNull() && (m_ThreadID != -1)) { m_MultiThreader->TerminateThread(m_ThreadID); m_MultiThreader = NULL; } m_AllTools.clear(); } mitk::TrackingTool* mitk::VirtualTrackingDevice::AddTool(const char* toolName) { //if (this->GetState() == Tracking) //{ // return NULL; //} mitk::VirtualTrackingTool::Pointer t = mitk::VirtualTrackingTool::New(); t->SetToolName(toolName); t->SetVelocity(0.1); this->InitializeSpline(t); MutexLockHolder lock(*m_ToolsMutex); // lock and unlock the mutex m_AllTools.push_back(t); return t; } bool mitk::VirtualTrackingDevice::StartTracking() { if (this->GetState() != Ready) return false; this->SetState(Tracking); // go to mode Tracking this->m_StopTrackingMutex->Lock(); this->m_StopTracking = false; this->m_StopTrackingMutex->Unlock(); m_TrackingFinishedMutex->Unlock(); // transfer the execution rights to tracking thread - mitk::TimeStamp::GetInstance()->Start(this); + mitk::IGTTimeStamp::GetInstance()->Start(this); if (m_MultiThreader.IsNotNull() && (m_ThreadID != -1)) m_MultiThreader->TerminateThread(m_ThreadID); if (m_MultiThreader.IsNull()) m_MultiThreader = itk::MultiThreader::New(); m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this); // start a new thread that executes the TrackTools() method return true; } bool mitk::VirtualTrackingDevice::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(); this->SetState(Ready); } - mitk::TimeStamp::GetInstance()->Stop(this); + mitk::IGTTimeStamp::GetInstance()->Stop(this); m_TrackingFinishedMutex->Lock(); return true; } unsigned int mitk::VirtualTrackingDevice::GetToolCount() const { MutexLockHolder lock(*m_ToolsMutex); // lock and unlock the mutex return static_cast(this->m_AllTools.size()); } mitk::TrackingTool* mitk::VirtualTrackingDevice::GetTool(unsigned int toolNumber) const { MutexLockHolder lock(*m_ToolsMutex); // lock and unlock the mutex if ( toolNumber < m_AllTools.size()) return this->m_AllTools.at(toolNumber); return NULL; } bool mitk::VirtualTrackingDevice::OpenConnection() { if (m_NumberOfControlPoints < 1) { this->SetErrorMessage("to few control points for spline interpolation"); return false; } srand(time(NULL)); //Init random number generator this->SetState(Ready); return true; } void mitk::VirtualTrackingDevice::InitializeSpline( mitk::VirtualTrackingTool* t ) { if (t == NULL) return; typedef mitk::VirtualTrackingTool::SplineType SplineType; /* create random control points */ SplineType::ControlPointListType controlPoints; controlPoints.reserve(m_NumberOfControlPoints + 1); controlPoints.push_back(this->GetRandomPoint()); // insert point 0 double length = 0.0; // estimate spline length by calculating line segments lengths for (unsigned int i = 1; i < m_NumberOfControlPoints - 1; ++i) // set points 1..n-2 { SplineType::ControlPointType pos; pos = this->GetRandomPoint(); length += controlPoints.at(i - 1).EuclideanDistanceTo(pos); controlPoints.push_back(pos); } controlPoints.push_back(controlPoints.at(0)); // close spline --> insert point last control point with same value as first control point length += controlPoints.at(controlPoints.size() - 2).EuclideanDistanceTo(controlPoints.at(controlPoints.size() - 1)); /* Create knot list. TODO: rethink knot list values and list size. Is there a better solution? */ SplineType::KnotListType knotList; knotList.push_back(0.0); for (unsigned int i = 1; i < controlPoints.size() + t->GetSpline()->GetSplineOrder() + 1; ++i) knotList.push_back(i); knotList.push_back(controlPoints.size() + t->GetSpline()->GetSplineOrder() + 1); t->GetSpline()->SetControlPoints(controlPoints); t->GetSpline()->SetKnots(knotList); t->SetSplineLength(length); } bool mitk::VirtualTrackingDevice::CloseConnection() { bool returnValue = true; if(this->GetState() == Setup) return true; this->SetState(Setup); return returnValue; } mitk::ScalarType mitk::VirtualTrackingDevice::GetSplineChordLength(unsigned int idx) { mitk::VirtualTrackingTool* t = this->GetInternalTool(idx); if (t != NULL) return t->GetSplineLength(); else throw std::invalid_argument("invalid index"); } void mitk::VirtualTrackingDevice::SetToolSpeed(unsigned int idx, mitk::ScalarType roundsPerSecond) { if (roundsPerSecond < 0.0001) throw std::invalid_argument("Minimum tool speed is 0.0001 rounds per second"); mitk::VirtualTrackingTool* t = this->GetInternalTool(idx); if (t != NULL) t->SetVelocity(roundsPerSecond); else throw std::invalid_argument("invalid index"); } mitk::VirtualTrackingTool* mitk::VirtualTrackingDevice::GetInternalTool(unsigned int idx) { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex if (idx < m_AllTools.size()) return m_AllTools.at(idx); else return NULL; } void mitk::VirtualTrackingDevice::TrackTools() { try { 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; /* lock the TrackingFinishedMutex to signal that the execution rights are now transfered to the tracking thread */ if (!localStopTracking) { m_TrackingFinishedMutex->Lock(); } this->m_StopTrackingMutex->Unlock(); mitk::ScalarType t = 0.0; while ((this->GetState() == Tracking) && (localStopTracking == false)) { //for (ToolContainer::iterator itAllTools = m_AllTools.begin(); itAllTools != m_AllTools.end(); itAllTools++) for (unsigned int i = 0; i < this->GetToolCount(); ++i) // use mutexed methods to access tool container { mitk::VirtualTrackingTool::Pointer currentTool = this->GetInternalTool(i); mitk::VirtualTrackingTool::SplineType::PointType pos; /* calculate tool position with spline interpolation */ pos = currentTool->GetSpline()->EvaluateSpline(t); mitk::Point3D mp; mitk::itk2vtk(pos, mp); // convert from SplineType::PointType to mitk::Point3D currentTool->SetPosition(mp); // Currently, a constant speed is used. TODO: use tool velocity setting t += 0.001; if (t >= 1.0) t = 0.0; mitk::Quaternion quat; /* fix quaternion rotation */ quat.x() = 1.0; quat.y() = 1.0; quat.z() = 1.0; quat.r() = 1.0; currentTool->SetOrientation(quat); // TODO: rotate once per cycle around a fixed rotation vector currentTool->SetTrackingError( 2 * (rand() / (RAND_MAX + 1.0))); // tracking error in 0 .. 2 Range currentTool->SetDataValid(true); currentTool->Modified(); } itksys::SystemTools::Delay(m_RefreshRate); /* Update the local copy of m_StopTracking */ this->m_StopTrackingMutex->Lock(); localStopTracking = m_StopTracking; this->m_StopTrackingMutex->Unlock(); } // tracking ends if we pass this line m_TrackingFinishedMutex->Unlock(); // transfer control back to main thread } catch(...) { m_TrackingFinishedMutex->Unlock(); this->StopTracking(); this->SetErrorMessage("Error while trying to track tools. Thread stopped."); } } ITK_THREAD_RETURN_TYPE mitk::VirtualTrackingDevice::ThreadStartTracking(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } VirtualTrackingDevice *trackingDevice = static_cast(pInfo->UserData); if (trackingDevice != NULL) trackingDevice->TrackTools(); trackingDevice->m_ThreadID = -1; // reset thread ID because we end the thread here return ITK_THREAD_RETURN_VALUE; } mitk::VirtualTrackingDevice::ControlPointType mitk::VirtualTrackingDevice::GetRandomPoint() { ControlPointType pos; pos[0] = m_Bounds[0] + (m_Bounds[1] - m_Bounds[0]) * (rand() / (RAND_MAX + 1.0)); // X = xMin + xRange * (random number between 0 and 1) pos[1] = m_Bounds[2] + (m_Bounds[3] - m_Bounds[2]) * (rand() / (RAND_MAX + 1.0)); // Y pos[2] = m_Bounds[4] + (m_Bounds[5] - m_Bounds[4]) * (rand() / (RAND_MAX + 1.0)); // Z return pos; } diff --git a/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp b/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp index 1cc2f90671..85872525cc 100644 --- a/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp @@ -1,550 +1,550 @@ /*=================================================================== 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 "mitkNavigationDataPlayer.h" #include "mitkNavigationData.h" #include "mitkTestingMacros.h" #include "mitkStandardFileLocations.h" -#include "mitkTimeStamp.h" +#include "mitkIGTTimeStamp.h" #include #include #include #include "mitkIGTException.h" #include "mitkIGTIOException.h" #include class mitkNavigationDataPlayerTestClass { public: static void TestInstantiation() { // let's create an object of our class mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); // first test: did this work? // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since // it makes no sense to continue without an object. MITK_TEST_CONDITION_REQUIRED(player.IsNotNull(), "Testing instantiation"); } static void TestSimpleDataPlay() { std::string tmp = ""; // let's create an object of our class mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); player->SetFileName( file ); MITK_TEST_CONDITION_REQUIRED( strcmp(player->GetFileName(), file.c_str()) == 0, "Testing SetFileName and GetFileName"); //exception is thrown in StartPlaying method player->StartPlaying(); player->Update(); player->StopPlaying();; mitk::NavigationData::Pointer nd = player->GetOutput(); mitk::Point3D pnt; pnt[0] = 1; pnt[1] = 0; pnt[2] = 3; MITK_TEST_CONDITION_REQUIRED( nd->GetPosition() == pnt, "Testing position of replayed NavigaionData" ); player = mitk::NavigationDataPlayer::New(); player->SetFileName( file ); std::vector times, refTimes; refTimes.resize(5); refTimes[0] = 3.9; refTimes[1] = 83.6; refTimes[2] = 174.4; refTimes[3] = 275.0; refTimes[4] = 385.39; std::vector points, refPoints; refPoints.resize(5); refPoints[0][0] = 1; refPoints[0][1] = 0; refPoints[0][2] = 3; refPoints[1][0] = 2; refPoints[1][1] = 1; refPoints[1][2] = 4; refPoints[2][0] = 3; refPoints[2][1] = 2; refPoints[2][2] = 5; refPoints[3][0] = 4; refPoints[3][1] = 3; refPoints[3][2] = 6; refPoints[4][0] = 5; refPoints[4][1] = 4; refPoints[4][2] = 7; - mitk::TimeStamp::Pointer timer = mitk::TimeStamp::GetInstance(); + mitk::IGTTimeStamp::Pointer timer = mitk::IGTTimeStamp::GetInstance(); timer->Initialize(); itk::Object::Pointer obj = itk::Object::New(); mitk::Point3D oldPos; oldPos[0] = 1; oldPos[1] = 0; oldPos[2] = 3; timer->Start( obj ); player->StartPlaying(); while( times.size()<5 ) { player->Update(); pnt = player->GetOutput()->GetPosition(); if ( pnt != oldPos ) { times.push_back( timer->GetElapsed(obj) ); points.push_back(oldPos); oldPos = pnt; } } player->StopPlaying(); // if this test fails, it may be because the dartclient runs on a virtual machine. // Under these circumstances, it may be impossible to achieve a time-accuracy of 10ms for ( int i=0;i<5;i++ ) { if ((times[i]>refTimes[i]-150 && times[i]refTimes[i]-150 && times[i]FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); player->SetFileName( file ); MITK_TEST_CONDITION_REQUIRED( strcmp(player->GetFileName(), file.c_str()) == 0, "Testing SetFileName and GetFileName"); player->StartPlaying(); player->Update(); mitk::NavigationData::Pointer nd = player->GetOutput(); mitk::Point3D pnt; pnt[0] = 1; pnt[1] = 0; pnt[2] = 3; MITK_TEST_CONDITION_REQUIRED( nd->GetPosition() == pnt, "Testing position of replayed NavigaionData" ); MITK_TEST_OUTPUT(<<"Test double call of Pause() method!"); player->Pause(); //test pause method player->Pause(); //call again to see if this causes an error MITK_TEST_OUTPUT(<<"Test double call of Resume() method!"); player->Resume(); //test resume method player->Resume(); //call again to see if this causes an error player->Update(); player->StopPlaying(); player = mitk::NavigationDataPlayer::New(); player->SetFileName( file ); std::vector times, refTimes; refTimes.resize(5); refTimes[0] = 3.9; refTimes[1] = 83.6; refTimes[2] = 174.4; refTimes[3] = 275.0; refTimes[4] = 385.39; std::vector points, refPoints; refPoints.resize(5); refPoints[0][0] = 1; refPoints[0][1] = 0; refPoints[0][2] = 3; refPoints[1][0] = 2; refPoints[1][1] = 1; refPoints[1][2] = 4; refPoints[2][0] = 3; refPoints[2][1] = 2; refPoints[2][2] = 5; refPoints[3][0] = 4; refPoints[3][1] = 3; refPoints[3][2] = 6; refPoints[4][0] = 5; refPoints[4][1] = 4; refPoints[4][2] = 7; - mitk::TimeStamp::Pointer timer = mitk::TimeStamp::GetInstance(); + mitk::IGTTimeStamp::Pointer timer = mitk::IGTTimeStamp::GetInstance(); timer->Initialize(); itk::Object::Pointer obj = itk::Object::New(); mitk::Point3D oldPos; oldPos[0] = 1; oldPos[1] = 0; oldPos[2] = 3; timer->Start( obj ); player->StartPlaying(); MITK_TEST_CONDITION_REQUIRED(!player->IsAtEnd(), "Testing method IsAtEnd() #0"); while( times.size()<3 ) { player->Update(); pnt = player->GetOutput()->GetPosition(); if ( pnt != oldPos ) { times.push_back( timer->GetElapsed(obj) ); points.push_back(oldPos); oldPos = pnt; } } MITK_TEST_OUTPUT(<<"Test pause method!"); player->Pause(); MITK_TEST_CONDITION_REQUIRED(!player->IsAtEnd(), "Testing method IsAtEnd() #1"); MITK_TEST_OUTPUT(<<"Test resume method!"); player->Resume(); while( times.size()<5 ) { player->Update(); pnt = player->GetOutput()->GetPosition(); if ( pnt != oldPos ) { times.push_back( timer->GetElapsed(obj) ); points.push_back(oldPos); oldPos = pnt; } } player->StopPlaying(); // if this test fails, it may be because the dartclient runs on a virtual machine. // Under these circumstances, it may be impossible to achieve a time-accuracy of 10ms for ( int i=0;i<5;i++ ) { if ((times[i]>refTimes[i]-150 && times[i]refTimes[i]-150 && times[i]IsAtEnd(), "Testing method IsAtEnd() #2"); } static void TestInvalidStream() { MITK_TEST_OUTPUT(<<"#### Testing invalid input data: errors are expected. ####"); //declarate test variables mitk::NavigationDataPlayer::Pointer player; std::string file; //case 0: stream not set player = mitk::NavigationDataPlayer::New(); bool InvalidStreamException0 = false; try { player->StartPlaying(); } catch(mitk::IGTException) { InvalidStreamException0=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#0: Tested stream not set. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException0, "Testing Invalid Stream method if exception (stream not set) was thrown."); //case 1: non-existing file player = mitk::NavigationDataPlayer::New(); bool InvalidStreamException1 = false; player->SetFileName( "ffdsd" ); try { player->StartPlaying(); } catch(mitk::IGTException) { InvalidStreamException1=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#1: Tested non-existing file. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException1, "Testing Invalid Stream method if exception (non-existing file) was thrown."); //case 2: wrong file format player = mitk::NavigationDataPlayer::New(); bool InvalidStreamException2 = false; file = mitk::StandardFileLocations::GetInstance()->FindFile("SROMFile.rom", "Modules/IGT/Testing/Data"); player->SetFileName( file ); try { player->StartPlaying(); } catch(mitk::IGTException) { InvalidStreamException2=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#2: Tested wrong file format. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException2, "Testing Invalid Stream method if exception (wrong file format) was thrown."); //case 3: wrong file version player = mitk::NavigationDataPlayer::New(); file = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidVersionNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); player->SetFileName( file ); bool InvalidStreamException3 = false; try { player->StartPlaying(); } catch(mitk::IGTException) { InvalidStreamException3 = true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#3: Tested wrong file version. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException3, "Testing Invalid Stream method if exception (wrong file version) was thrown."); //case 4: wrong file player = mitk::NavigationDataPlayer::New(); player->SetFileName( "cs:\fsd/$%§²³ffdsd" ); bool InvalidStreamException4=false; try { player->StartPlaying(); } catch(mitk::IGTException) { InvalidStreamException4=true; MITK_TEST_OUTPUT(<<"#4: Tested wrong file. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException4, "Testing Invalid Stream method if exception (wrong file) was thrown."); //case 5: null stream player = mitk::NavigationDataPlayer::New(); bool InvalidStreamException5=false; try { player->StartPlaying(); } catch(mitk::IGTException) { InvalidStreamException5=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#5: Tested null stream. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException5, "Testing Invalid Stream method if exception (null stream) was thrown."); //case 6: empty stream, exception is thrown in setstream player = mitk::NavigationDataPlayer::New(); bool InvalidStreamException6=false; std::ifstream* myEmptyStream; try { myEmptyStream = new std::ifstream(""); player->SetStream( myEmptyStream ); } catch(mitk::IGTException) { InvalidStreamException6=true; MITK_TEST_OUTPUT(<<"#6: Tested empty stream. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException6, "Testing Invalid Stream method if exception (empty stream) was thrown."); //case 7: wrong stream player = mitk::NavigationDataPlayer::New(); file = mitk::StandardFileLocations::GetInstance()->FindFile("SROMFile.rom", "Modules/IGT/Testing/Data"); bool InvalidStreamException7=false; std::ifstream* myWrongStream; myWrongStream = new std::ifstream(file.c_str()); try { player->SetStream( myWrongStream ); } catch(mitk::IGTIOException) { InvalidStreamException7=true; MITK_TEST_OUTPUT(<<"#7: Tested wrong stream. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException7, "Testing Invalid Stream method if exception (wrong stream) was thrown."); //case 8: invalid player = mitk::NavigationDataPlayer::New(); file = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidDataNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); player->SetFileName( file ); bool InvalidStreamException8=false; try { player->StartPlaying(); } catch(mitk::IGTIOException) { InvalidStreamException8=true; MITK_TEST_OUTPUT(<<"#8: Tested invalid file version. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException8, "Testing Invalid Stream method if exception (Invalid) was thrown."); //clean up delete myEmptyStream; delete myWrongStream; } static void TestSetStreamExceptions() { mitk::NavigationDataPlayer::Pointer myTestPlayer = mitk::NavigationDataPlayer::New(); std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); myTestPlayer->SetFileName( file ); bool exceptionThrown=false; try { std::istream* stream=NULL; myTestPlayer->SetStream(stream); } catch(mitk::IGTException) { exceptionThrown = true; MITK_TEST_OUTPUT(<<"#9: Tested exceptions in SetStream. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(exceptionThrown, "Testing SetStream method in exception was thrown."); } static void TestStartPlayingExceptions() { MITK_INFO <<"In the following, exceptions are tested. Errors will occur and are expected."; //Case1 Testing if stream=NULL mitk::NavigationDataPlayer::Pointer myTestPlayer1 = mitk::NavigationDataPlayer::New(); bool exceptionThrown1 = false; try { myTestPlayer1->StartPlaying(); } catch(mitk::IGTException) { exceptionThrown1 = true; myTestPlayer1->StopPlaying(); MITK_TEST_OUTPUT(<<"#10: Tested exception for the case when stream=NULL in StartPlaying. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(exceptionThrown1, "Testing StartPlaying method if exception (stream=NULL) was thrown."); //Case2 Testing if file does not exist mitk::NavigationDataPlayer::Pointer myTestPlayer2 = mitk::NavigationDataPlayer::New(); myTestPlayer2->SetFileName("ffdsd"); bool exceptionThrown2 = false; try{ myTestPlayer2->StartPlaying(); } catch(mitk::IGTIOException) { exceptionThrown2 = true; myTestPlayer2->StopPlaying(); MITK_TEST_OUTPUT(<<"#11: Tested exception for the case when file does not exist in StartPlaying. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(exceptionThrown2, "Testing StartPlaying method if exception is thrown when file does not exist."); //Case3 Testing if wrong file format mitk::NavigationDataPlayer::Pointer myTestPlayer3 = mitk::NavigationDataPlayer::New(); std::string file3 = mitk::StandardFileLocations::GetInstance()->FindFile("SROMFile.rom", "Modules/IGT/Testing/Data"); myTestPlayer3->SetFileName( file3 ); bool exceptionThrown3 = false; try{ myTestPlayer3->StartPlaying(); } catch(mitk::IGTIOException) { exceptionThrown3 = true; myTestPlayer3->StopPlaying(); MITK_TEST_OUTPUT(<<"#12: Tested exception for the case when file format is wrong in StartPlaying. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(exceptionThrown3, "Testing StartPlaying method if exception (file format is wrong) was thrown."); //Case4 Testing if wrong file version mitk::NavigationDataPlayer::Pointer myTestPlayer4 = mitk::NavigationDataPlayer::New(); std::string file4 = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidVersionNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); myTestPlayer4->SetFileName( file3 ); bool exceptionThrown4 = false; try{ myTestPlayer4->StartPlaying(); } catch(mitk::IGTIOException) { exceptionThrown4 = true; myTestPlayer4->StopPlaying(); MITK_TEST_OUTPUT(<<"#13: Tested exception for the case when file version is wrong in StartPlaying. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(exceptionThrown4, "Testing StartPlaying method if exception (file version is wrong) was thrown."); //Case5 Testing if not existing file name mitk::NavigationDataPlayer::Pointer myTestPlayer5 = mitk::NavigationDataPlayer::New(); myTestPlayer5->SetFileName("ffdsd"); bool exceptionThrown5 = false; try{ myTestPlayer5->StartPlaying(); } catch(mitk::IGTIOException) { exceptionThrown5 = true; myTestPlayer5->StopPlaying(); MITK_TEST_OUTPUT(<<"#14: Tested exception for the case when non-existing file name in StartPlaying. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(exceptionThrown5, "Testing StartPlaying method if exception (non-existing file name) was thrown."); } }; /**Documentation * test for the class "NavigationDataPlayer". */ int mitkNavigationDataPlayerTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationDataPlayer"); std::string tmp = ""; mitkNavigationDataPlayerTestClass::TestInstantiation(); mitkNavigationDataPlayerTestClass::TestSimpleDataPlay(); mitkNavigationDataPlayerTestClass::TestSetStreamExceptions(); mitkNavigationDataPlayerTestClass::TestStartPlayingExceptions(); mitkNavigationDataPlayerTestClass::TestPauseAndResume(); mitkNavigationDataPlayerTestClass::TestInvalidStream(); // always end with this! MITK_TEST_END(); } diff --git a/Modules/IGT/Testing/mitkNavigationDataToPointSetFilterTest.cpp b/Modules/IGT/Testing/mitkNavigationDataToPointSetFilterTest.cpp index c3e08adb31..330ac17c58 100644 --- a/Modules/IGT/Testing/mitkNavigationDataToPointSetFilterTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataToPointSetFilterTest.cpp @@ -1,251 +1,249 @@ /*=================================================================== 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 "mitkNavigationDataToPointSetFilter.h" #include "mitkNavigationDataPlayer.h" -#include "mitkTimeStamp.h" -#include "mitkStandardFileLocations.h" - -#include "mitkTestingMacros.h" +#include +#include #include #include /** * Simple example for a test for the (non-existent) class "NavigationDataToPointSetFilter". * * argc and argv are the command line parameters which were passed to * the ADD_TEST command in the CMakeLists.txt file. For the automatic * tests, argv is either empty for the simple tests or contains the filename * of a test image for the image tests (see CMakeLists.txt). */ class mitkNavigationDataToPointSetFilterTestClass { public: static void TestMode3D(mitk::NavigationDataToPointSetFilter::Pointer myNavigationDataToPointSetFilter) { myNavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode3D); //Build up test data mitk::NavigationData::Pointer nd0 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd1 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New(); mitk::NavigationData::PositionType point0; point0[0] = 1.0; point0[1] = 2.0; point0[2] = 3.0; nd0->SetPosition(point0); nd0->SetDataValid(true); mitk::NavigationData::PositionType point1; point1[0] = 4.0; point1[1] = 5.0; point1[2] = 6.0; nd1->SetPosition(point1); nd1->SetDataValid(true); mitk::NavigationData::PositionType point2; point2[0] = 7.0; point2[1] = 8.0; point2[2] = 9.0; nd2->SetPosition(point2); nd2->SetDataValid(true); mitk::NavigationData::PositionType point3; point3[0] = 10.0; point3[1] = 11.0; point3[2] = 12.0; nd3->SetPosition(point3); nd3->SetDataValid(true); myNavigationDataToPointSetFilter->SetInput(0, nd0); myNavigationDataToPointSetFilter->SetInput(1, nd1); myNavigationDataToPointSetFilter->SetInput(2, nd2); myNavigationDataToPointSetFilter->SetInput(3, nd3); //Process mitk::PointSet::Pointer pointSet0 = myNavigationDataToPointSetFilter->GetOutput(0); mitk::PointSet::Pointer pointSet1 = myNavigationDataToPointSetFilter->GetOutput(1); mitk::PointSet::Pointer pointSet2 = myNavigationDataToPointSetFilter->GetOutput(2); mitk::PointSet::Pointer pointSet3 = myNavigationDataToPointSetFilter->GetOutput(3); pointSet0->Update(); MITK_TEST_OUTPUT(<< "Testing the conversion of navigation data object to PointSets in Mode 3D:"); MITK_TEST_CONDITION(mitk::Equal(pointSet0->GetPoint(0), point0), "Pointset 0 correct?"); MITK_TEST_CONDITION(mitk::Equal(pointSet1->GetPoint(0), point1), "Pointset 1 correct?"); MITK_TEST_CONDITION(mitk::Equal(pointSet2->GetPoint(0), point2), "Pointset 2 correct?"); MITK_TEST_CONDITION(mitk::Equal(pointSet3->GetPoint(0), point3), "Pointset 3 correct?"); //pointSet0->GetPoint(0)[0] == 1.0 && pointSet0->GetPoint(0)[1] == 2.0 && pointSet0->GetPoint(0)[2] == 3.0 && // pointSet1->GetPoint(0)[0] == 4.0 && pointSet1->GetPoint(0)[1] == 5.0 && pointSet1->GetPoint(0)[2] == 6.0 && // pointSet2->GetPoint(0)[0] == 7.0 && pointSet2->GetPoint(0)[1] == 8.0 && pointSet2->GetPoint(0)[2] == 9.0 && // pointSet3->GetPoint(0)[0] == 10.0 && pointSet3->GetPoint(0)[1] == 11.0 && pointSet3->GetPoint(0)[2] == 12.0 //, "Testing the conversion of navigation data object to PointSets in Mode 3D" ); } static void TestMode4D(mitk::NavigationDataToPointSetFilter::Pointer myNavigationDataToPointSetFilter) { myNavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode4D); myNavigationDataToPointSetFilter->SetRingBufferSize(2); //Build up test data mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd4 = mitk::NavigationData::New(); mitk::NavigationData::PositionType point; point[0] = 1.0; point[1] = 2.0; point[2] = 3.0; nd->SetPosition(point); point[0] = 4.0; point[1] = 5.0; point[2] = 6.0; nd2->SetPosition(point); point[0] = 7.0; point[1] = 8.0; point[2] = 9.0; nd3->SetPosition(point); point[0] = 10.0; point[1] = 11.0; point[2] = 12.0; nd4->SetPosition(point); myNavigationDataToPointSetFilter->SetInput(0, nd); myNavigationDataToPointSetFilter->SetInput(1, nd2); mitk::PointSet::Pointer pointSet = myNavigationDataToPointSetFilter->GetOutput(); pointSet->Update(); MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 1.0 && pointSet->GetPoint(0,0)[1] == 2.0 && pointSet->GetPoint(0,0)[2] == 3.0 && pointSet->GetPoint(1,0)[0] == 4.0 && pointSet->GetPoint(1,0)[1] == 5.0 && pointSet->GetPoint(1,0)[2] == 6.0 , "Testing the conversion of navigation data object to one point set in Mode 4D in first timestep" ); myNavigationDataToPointSetFilter->SetInput(0, nd3); myNavigationDataToPointSetFilter->SetInput(1, nd4); myNavigationDataToPointSetFilter->Update(); pointSet = myNavigationDataToPointSetFilter->GetOutput(); MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 1.0 && pointSet->GetPoint(0,0)[1] == 2.0 && pointSet->GetPoint(0,0)[2] == 3.0 && pointSet->GetPoint(1,0)[0] == 4.0 && pointSet->GetPoint(1,0)[1] == 5.0 && pointSet->GetPoint(1,0)[2] == 6.0 && pointSet->GetPoint(0,1)[0] == 7.0 && pointSet->GetPoint(0,1)[1] == 8.0 && pointSet->GetPoint(0,1)[2] == 9.0 && pointSet->GetPoint(1,1)[0] == 10.0 && pointSet->GetPoint(1,1)[1] == 11.0 && pointSet->GetPoint(1,1)[2] == 12.0 , "Testing the conversion of navigation data object to one point set in Mode 4D in second timestep" ); myNavigationDataToPointSetFilter->SetInput(0, nd3); //nd3->Modified(); //necessary because the generate data is only called when input has changed... myNavigationDataToPointSetFilter->SetInput(1, nd4); //nd4->Modified(); //myNavigationDataToPointSetFilter->Update(); pointSet = myNavigationDataToPointSetFilter->GetOutput(); pointSet->Update(); MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 7.0 && pointSet->GetPoint(0,0)[1] == 8.0 && pointSet->GetPoint(0,0)[2] == 9.0 && pointSet->GetPoint(1,0)[0] == 10.0 && pointSet->GetPoint(1,0)[1] == 11.0 && pointSet->GetPoint(1,0)[2] == 12.0 && pointSet->GetPoint(0,1)[0] == 7.0 && pointSet->GetPoint(0,1)[1] == 8.0 && pointSet->GetPoint(0,1)[2] == 9.0 && pointSet->GetPoint(1,1)[0] == 10.0 && pointSet->GetPoint(1,1)[1] == 11.0 && pointSet->GetPoint(1,1)[2] == 12.0 , "Testing the correct ring buffer behavior" ); } static void TestMode3DMean(mitk::NavigationDataToPointSetFilter::Pointer myNavigationDataToPointSetFilter) { myNavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode3DMean); int numberForMean = 5; myNavigationDataToPointSetFilter->SetNumberForMean(numberForMean); MITK_TEST_CONDITION(mitk::Equal(myNavigationDataToPointSetFilter->GetNumberForMean(), numberForMean), "Testing get/set for numberForMean"); mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData_2Tools.xml", "Modules/IGT/Testing/Data"); player->SetFileName( file ); player->StartPlaying(); for (int i = 0; i< player->GetNumberOfOutputs(); i++) { myNavigationDataToPointSetFilter->SetInput(i, player->GetOutput(i)); } mitk::PointSet::Pointer pointSet0 = myNavigationDataToPointSetFilter->GetOutput(0); mitk::PointSet::Pointer pointSet1 = myNavigationDataToPointSetFilter->GetOutput(1); myNavigationDataToPointSetFilter->Update(); player->StopPlaying(); MITK_TEST_CONDITION(pointSet0->GetPoint(0)[0]==3.0 && pointSet0->GetPoint(0)[1]==2.0 && pointSet0->GetPoint(0)[2]==5.0, "Testing the average of first input"); MITK_TEST_CONDITION(pointSet1->GetPoint(0)[0]==30.0 && pointSet1->GetPoint(0)[1]==20.0 && pointSet1->GetPoint(0)[2]==50.0, "Testing the average of second input"); } }; int mitkNavigationDataToPointSetFilterTest(int /* argc */, char* /*argv*/[]) { // always start with this! MITK_TEST_BEGIN("NavigationDataToPointSetFilter"); // let's create an object of our class mitk::NavigationDataToPointSetFilter::Pointer myNavigationDataToPointSetFilter = mitk::NavigationDataToPointSetFilter::New(); // first test: did this work? // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since // it makes no sense to continue without an object. MITK_TEST_CONDITION_REQUIRED(myNavigationDataToPointSetFilter.IsNotNull(),"Testing instantiation"); // write your own tests here and use the macros from mitkTestingMacros.h !!! // do not write to std::cout and do not return from this function yourself! mitk::NavigationData::Pointer nd_in = mitk::NavigationData::New(); const mitk::NavigationData* nd_out = mitk::NavigationData::New(); mitk::NavigationData::PositionType point; point[0] = 1.0; point[1] = 2.0; point[2] = 3.0; nd_in->SetPosition(point); myNavigationDataToPointSetFilter->SetInput(nd_in); nd_out = myNavigationDataToPointSetFilter->GetInput(); MITK_TEST_CONDITION( nd_out->GetPosition() == nd_in->GetPosition(), "Testing get/set input" ); myNavigationDataToPointSetFilter = mitk::NavigationDataToPointSetFilter::New(); mitkNavigationDataToPointSetFilterTestClass::TestMode3D(myNavigationDataToPointSetFilter); myNavigationDataToPointSetFilter = mitk::NavigationDataToPointSetFilter::New(); mitkNavigationDataToPointSetFilterTestClass::TestMode4D(myNavigationDataToPointSetFilter); myNavigationDataToPointSetFilter = mitk::NavigationDataToPointSetFilter::New(); mitkNavigationDataToPointSetFilterTestClass::TestMode3DMean(myNavigationDataToPointSetFilter); // always end with this! MITK_TEST_END(); } diff --git a/Modules/IGT/Testing/mitkTimeStampTest.cpp b/Modules/IGT/Testing/mitkTimeStampTest.cpp index 8680866ff3..cb7224d234 100644 --- a/Modules/IGT/Testing/mitkTimeStampTest.cpp +++ b/Modules/IGT/Testing/mitkTimeStampTest.cpp @@ -1,117 +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. ===================================================================*/ -#include "mitkTimeStamp.h" +#include "mitkIGTTimeStamp.h" #include "mitkRealTimeClock.h" #include "mitkTestingMacros.h" #include "itkObject.h" //#include #ifndef WIN32 #include #endif /** - * test for the class "mitkTimeStamp" + * test for the class "mitkIGTTimeStamp" */ int mitkTimeStampTest(int /* argc */, char* /*argv*/[]) { - MITK_TEST_BEGIN("TimeStamp") + MITK_TEST_BEGIN("IGTTimeStamp") //create testing objects itk::Object::Pointer tester = itk::Object::New(); itk::Object::Pointer tester2 = itk::Object::New(); //try methods without calling CreateInstance() before (error test cases) MITK_TEST_OUTPUT(<<"Testing behavior of methodes if they are called at the wrong moment (error should occure)."); - mitk::TimeStamp::GetInstance()->Start(tester2); - mitk::TimeStamp::GetInstance()->Stop(tester2); + mitk::IGTTimeStamp::GetInstance()->Start(tester2); + mitk::IGTTimeStamp::GetInstance()->Stop(tester2); //create instance of singleton time stamp class - MITK_TEST_CONDITION_REQUIRED(mitk::TimeStamp::CreateInstance() != (0), "Testing GetInstance() of Singleton" ); + MITK_TEST_CONDITION_REQUIRED(mitk::IGTTimeStamp::CreateInstance() != (0), "Testing GetInstance() of Singleton" ); - double timestampX = mitk::TimeStamp::GetInstance()->GetElapsed(); + double timestampX = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); MITK_TEST_CONDITION_REQUIRED(timestampX==-1,"..Testing method GetCurrentTimeStamp()."); - double offsetX = mitk::TimeStamp::GetInstance()->GetOffset(tester2); + double offsetX = mitk::IGTTimeStamp::GetInstance()->GetOffset(tester2); MITK_TEST_CONDITION_REQUIRED(offsetX==-1.0,"..Testing method GetOffset()."); //start-tracking sets the reference-time, timestamps are relative to this time - mitk::TimeStamp::GetInstance()->Start(tester); + mitk::IGTTimeStamp::GetInstance()->Start(tester); MITK_INFO << "first device has started tracking\n"; //sleeps for 20 ms #if defined (WIN32) || defined (_WIN32) Sleep(20); #else usleep(20000); #endif MITK_INFO << "supposed to have waited 20ms \n"; double time_elapsed, relative_time_elapsed; //gets time elapsed since start - time_elapsed = mitk::TimeStamp::GetInstance()->GetElapsed(); + time_elapsed = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); MITK_INFO << "have actually waited : " << time_elapsed << "ms \n"; //elapsed time is not allowed to be too far from 20 ms (+-10ms)-> debugging "destroys" the correct value of course MITK_TEST_CONDITION_REQUIRED((time_elapsed-20) > -10 , "Testing if elapsed time is correct (-10)"); //MITK_TEST_CONDITION_REQUIRED((time_elapsed-20) < 10 , "Testing if elapsed time is correct (+10)"); //second "device" starts tracking - mitk::TimeStamp::GetInstance()->Start(tester2); + mitk::IGTTimeStamp::GetInstance()->Start(tester2); MITK_INFO << "second device has started\n"; //first device stops - mitk::TimeStamp::GetInstance()->Stop(tester); + mitk::IGTTimeStamp::GetInstance()->Stop(tester); MITK_INFO << "first device has stopped tracking\n"; - time_elapsed = mitk::TimeStamp::GetInstance()->GetElapsed(); - relative_time_elapsed = mitk::TimeStamp::GetInstance()->GetElapsed(tester2); + time_elapsed = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); + relative_time_elapsed = mitk::IGTTimeStamp::GetInstance()->GetElapsed(tester2); MITK_INFO << "time elapsed supposed to be greater than 20 ms\n"; MITK_INFO << time_elapsed << " actually elapsed\n"; MITK_INFO << "relative time elapsed supposed to be smaller than absolute time elapsed : \n"; MITK_INFO << relative_time_elapsed << " actually elapsed\n"; //relative timespan must be smaller than absolute timespan MITK_TEST_CONDITION_REQUIRED( time_elapsed > relative_time_elapsed , " testing if relative timespan is shorter than absolute timespan"); //timestamp still has to be valid (tester2 still tracking), and has to be larger than 20ms //MITK_TEST_CONDITION_REQUIRED( time_elapsed > 15 , "testing if second device is still keeping the TimeStamp \"alive\""); - mitk::TimeStamp::GetInstance()->Stop(tester2); + mitk::IGTTimeStamp::GetInstance()->Stop(tester2); MITK_INFO << " second device has stopped tracking\n"; - time_elapsed = mitk::TimeStamp::GetInstance()->GetElapsed(); + time_elapsed = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); //when all devices have stopped, -1 has to be returned MITK_TEST_CONDITION_REQUIRED( time_elapsed == -1 , "testing if -1 is returned after all devices have stopped"); //test set realtime clock mitk::RealTimeClock::Pointer myRealTimeClock = mitk::RealTimeClock::New(); - mitk::TimeStamp::GetInstance()->SetRealTimeClock(myRealTimeClock); + mitk::IGTTimeStamp::GetInstance()->SetRealTimeClock(myRealTimeClock); // always end with this! MITK_TEST_END(); } diff --git a/Modules/IGT/files.cmake b/Modules/IGT/files.cmake index 18c52a2f02..0f3aa00769 100644 --- a/Modules/IGT/files.cmake +++ b/Modules/IGT/files.cmake @@ -1,63 +1,63 @@ set(CPP_FILES IGTFilters/mitkNavigationDataLandmarkTransformFilter.cpp IGTFilters/mitkNavigationDataReferenceTransformFilter.cpp IGTFilters/mitkNavigationDataTransformFilter.cpp IGTFilters/mitkNavigationDataRecorder.cpp IGTFilters/mitkNavigationDataPlayer.cpp IGTFilters/mitkNavigationDataPlayerBase.cpp IGTFilters/mitkNavigationDataObjectVisualizationFilter.cpp IGTFilters/mitkCameraVisualization.cpp IGTFilters/mitkNavigationData.cpp IGTFilters/mitkNavigationDataDisplacementFilter.cpp IGTFilters/mitkNavigationDataSequentialPlayer.cpp IGTFilters/mitkNavigationDataSource.cpp IGTFilters/mitkNavigationDataToMessageFilter.cpp IGTFilters/mitkNavigationDataToNavigationDataFilter.cpp IGTFilters/mitkNavigationDataToPointSetFilter.cpp IGTFilters/mitkNavigationDataEvaluationFilter.cpp IGTFilters/mitkTrackingDeviceSource.cpp IGTFilters/mitkTrackingVolumeGenerator.cpp - IGTFilters/mitkTimeStamp.cpp + IGTFilters/mitkIGTTimeStamp.cpp IGTFilters/mitkRealTimeClock.cpp IGTFilters/mitkTrackingDeviceSourceConfigurator.cpp IGTTrackingDevices/mitkClaronTool.cpp IGTTrackingDevices/mitkClaronTrackingDevice.cpp IGTTrackingDevices/mitkInternalTrackingTool.cpp IGTTrackingDevices/mitkNDIPassiveTool.cpp IGTTrackingDevices/mitkNDIProtocol.cpp IGTTrackingDevices/mitkNDITrackingDevice.cpp IGTTrackingDevices/mitkSerialCommunication.cpp IGTTrackingDevices/mitkTrackingDevice.cpp IGTTrackingDevices/mitkTrackingTool.cpp IGTTrackingDevices/mitkVirtualTrackingDevice.cpp IGTTrackingDevices/mitkVirtualTrackingTool.cpp IGTToolManagement/mitkNavigationToolStorage.cpp IGTToolManagement/mitkNavigationToolStorageSerializer.cpp IGTToolManagement/mitkNavigationToolStorageDeserializer.cpp IGTToolManagement/mitkNavigationTool.cpp IGTToolManagement/mitkNavigationToolReader.cpp IGTToolManagement/mitkNavigationToolWriter.cpp IGTExceptionHandling/mitkIGTException.cpp IGTExceptionHandling/mitkIGTHardwareException.cpp IGTExceptionHandling/mitkIGTIOException.cpp ) if(MITK_USE_MICRON_TRACKER) set(CPP_FILES ${CPP_FILES} IGTTrackingDevices/mitkClaronInterface.cpp) else() set(CPP_FILES ${CPP_FILES} IGTTrackingDevices/mitkClaronInterfaceStub.cpp) endif(MITK_USE_MICRON_TRACKER) if(MITK_USE_MICROBIRD_TRACKER) set(CPP_FILES ${CPP_FILES} IGTTrackingDevices/mitkMicroBirdTrackingDevice.cpp) endif(MITK_USE_MICROBIRD_TRACKER) if(WIN32) set(CPP_FILES ${CPP_FILES} IGTFilters/mitkWindowsRealTimeClock.cpp) else() set(CPP_FILES ${CPP_FILES} IGTFilters/mitkLinuxRealTimeClock.cpp) endif(WIN32) diff --git a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.h b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.h index 2c409648dc..dbef727ab9 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.h @@ -1,261 +1,259 @@ /*=================================================================== 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 QmitkIGTPlayerWidget_H #define QmitkIGTPlayerWidget_H //QT headers #include //mitk headers #include "MitkIGTUIExports.h" -#include "mitkNavigationTool.h" -#include "mitkNavigationDataPlayer.h" -#include "mitkNavigationDataSequentialPlayer.h" -#include - +#include +#include +#include #include //ui header #include "ui_QmitkIGTPlayerWidgetControls.h" /** Documentation: * \brief GUI to access the IGT Player. * User must specify the file name where the input xml-file is located. The NavigationDatas from the xml-file can be * played in normal mode or in PointSet mode. * * In normal mode the player updates the NavigationDatas every 100ms (can be changed in SetUpdateRate()) and returns * them when GetNavigationDatas() is called. * In PointSet mode the player generates a PointSet with all NavigationDatas from the xml-file. So the playback is * performed on this ND PointSet. * * \ingroup IGTUI */ class MitkIGTUI_EXPORT QmitkIGTPlayerWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; /*! \brief default constructor */ QmitkIGTPlayerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); /*! \brief default deconstructor */ ~QmitkIGTPlayerWidget(); /*! \brief Sets the real time player for this player widget */ void SetRealTimePlayer(mitk::NavigationDataPlayer::Pointer player); /*! \brief Sets the sequential player for this player widget */ void SetSequentialPlayer(mitk::NavigationDataSequentialPlayer::Pointer player); /*! \brief Returns the playing timer of this widget */ QTimer* GetPlayingTimer(); /*! \brief Returns the current playback NavigationDatas from the xml-file */ const std::vector GetNavigationDatas(); /*! \brief Returns a PointSet of the current NavigationDatas for all recorded tools. */ const mitk::PointSet::Pointer GetNavigationDatasPointSet(); /*! \brief Returns a PointType of the current NavigationData for a specific tool with the given index. */ const mitk::PointSet::PointType GetNavigationDataPoint(unsigned int index); /*! \brief Sets the update rate of this widget's playing timer */ void SetUpdateRate(unsigned int msecs); /*! \brief Returns the number of different tools from the current playing stream. * * Retuns 0 if playback file is invalid. */ unsigned int GetNumberOfTools(); /*! \brief Stops the playback */ void StopPlaying(); /*! \brief Sets the given tool names list to the trajectory select combobox. */ void SetTrajectoryNames(const QStringList toolNames); /*! \brief Returns the current resolution value from the resolution spinbox. */ int GetResolution(); /*! \brief Clears all items in the trajectory selection combobox. */ void ClearTrajectorySelectCombobox(); /*! \brief Returns whether spline mode checkbox is selected. */ bool IsTrajectoryInSplineMode(); enum PlaybackMode { ///< playback mode enum RealTimeMode = 1, SequentialMode = 2 }; PlaybackMode GetCurrentPlaybackMode(); signals: /*! \brief This signal is emitted when the player starts the playback. */ void SignalPlayingStarted(); /*! \brief This signal is emitted when the player resumes after a pause. */ void SignalPlayingResumed(); /*! \brief This signal is emitted when the player stops. */ void SignalPlayingStopped(); /*! \brief This signal is emitted when the player is paused. */ void SignalPlayingPaused(); /*! \brief This signal is emitted when the player reaches the end of the playback. */ void SignalPlayingEnded(); /*! \brief This signal is emitted every time the player updated the NavigationDatas. */ void SignalPlayerUpdated(); /*! \brief This signal is emitted if the input file for the replay was changed. */ void SignalInputFileChanged(); /*! \brief This signal is emitted if the index of the current selected trajectory select combobox item changes. */ void SignalCurrentTrajectoryChanged(int index); /*! \brief This signal is emitted if the spline mode checkbox is toggled or untoggled. */ void SignalSplineModeToggled(bool toggled); protected slots: /*! \brief Starts or pauses the playback */ void OnPlayButtonClicked(bool toggled); /*! \brief Updates the playback data */ void OnPlaying(); /*! \brief Stops the playback */ void OnStopPlaying(); /*! \brief Updates the input filename */ void SetInputFileName(const QString& inputFileName); /*! \brief Opens file open dialog for searching the input file */ void OnSelectPressed(); /*! \brief Stops the playback */ void OnGoToEnd(); /*! \brief Stops the playback and resets the player to the beginning */ void OnGoToBegin(); /*! \brief Switches widget between realtime and sequential mode */ void OnSequencialModeToggled(bool toggled); /*! \brief Pauses playback when slider is pressed by user */ void OnSliderPressed(); /*! \brief Moves player position to the position selected with the slider */ void OnSliderReleased(); protected: /// \brief Creation of the connections virtual void CreateConnections(); /// \brief Creation of the Qt control virtual void CreateQtPartControl(QWidget *parent); /*! \brief Checks if an imput file with the set filename exists */ bool CheckInputFileValid(); /*! \brief Sets all LCD numbers to 0 */ void ResetLCDNumbers(); Ui::QmitkIGTPlayerWidgetControls* m_Controls; mitk::NavigationDataPlayer::Pointer m_RealTimePlayer; ///< plays NDs from a XML file mitk::NavigationDataSequentialPlayer::Pointer m_SequentialPlayer; QString m_CmpFilename; ///< filename of the input file QTimer* m_PlayingTimer; ///< update timer mitk::NavigationData::TimeStampType m_StartTime; ///< start time of playback needed for time display unsigned int m_CurrentSequentialPointNumber; ///< current point number }; #endif