diff --git a/Modules/OpenIGTLink/files.cmake b/Modules/OpenIGTLink/files.cmake index 2ea75a3a97..c8a685de24 100644 --- a/Modules/OpenIGTLink/files.cmake +++ b/Modules/OpenIGTLink/files.cmake @@ -1,10 +1,12 @@ set(CPP_FILES mitkIGTLClient.cpp mitkIGTLDevice.cpp mitkIGTLMessageSource.cpp mitkIGTLDeviceSource.cpp mitkIGTLMessage.cpp mitkIGTLMessageCommon.cpp mitkIGTLMessageFactory.cpp mitkIGTLMessageCloneHandler.h + mitkIGTLDummyMessage.cpp + mitkIGTLMessageQueue.cpp ) diff --git a/Modules/OpenIGTLink/mitkIGTLDevice.cpp b/Modules/OpenIGTLink/mitkIGTLDevice.cpp index a0623ec139..8aa59d2849 100644 --- a/Modules/OpenIGTLink/mitkIGTLDevice.cpp +++ b/Modules/OpenIGTLink/mitkIGTLDevice.cpp @@ -1,475 +1,449 @@ /*=================================================================== 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 "mitkIGTLDevice.h" //#include "mitkIGTTimeStamp.h" #include #include #include #include #include typedef itk::MutexLockHolder MutexLockHolder; mitk::IGTLDevice::IGTLDevice() : // m_Data(mitk::DeviceDataUnspecified), m_State(mitk::IGTLDevice::Setup), m_StopCommunication(false), m_PortNumber(-1), m_MultiThreader(NULL), m_ThreadID(0) { m_StopCommunicationMutex = itk::FastMutexLock::New(); m_StateMutex = itk::FastMutexLock::New(); - m_LatestMessageMutex = itk::FastMutexLock::New(); +// m_LatestMessageMutex = itk::FastMutexLock::New(); m_CommunicationFinishedMutex = itk::FastMutexLock::New(); // execution rights are owned by the application thread at the beginning m_CommunicationFinishedMutex->Lock(); m_MultiThreader = itk::MultiThreader::New(); // m_Data = mitk::DeviceDataUnspecified; - m_LatestMessage = igtl::MessageBase::New(); +// m_LatestMessage = igtl::MessageBase::New(); m_MessageFactory = mitk::IGTLMessageFactory::New(); + m_Queue = mitk::IGTLMessageQueue::New(); } mitk::IGTLDevice::~IGTLDevice() { /* stop communication and disconnect from igtl device */ if (GetState() == Running) { this->StopCommunication(); } if (GetState() == Ready) { this->CloseConnection(); } /* cleanup tracking thread */ if ((m_ThreadID != 0) && (m_MultiThreader.IsNotNull())) { m_MultiThreader->TerminateThread(m_ThreadID); } m_MultiThreader = NULL; } mitk::IGTLDevice::IGTLDeviceState mitk::IGTLDevice::GetState() const { MutexLockHolder lock(*m_StateMutex); return m_State; } void mitk::IGTLDevice::SetState( IGTLDeviceState 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::IGTLDeviceData mitk::IGTLDevice::GetData() const{ // return m_Data; //} //void mitk::IGTLDevice::SetData(mitk::IGTLDeviceData data){ // m_Data = data; //} bool mitk::IGTLDevice::SendMessage(igtl::MessageBase::Pointer msg) { // 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; return true; } //mitk::NDIErrorCode mitk::IGTLDevice::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; //} bool mitk::IGTLDevice::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 // { // m_SerialCommunication->CloseConnection(); // m_SerialCommunication = NULL; // mitkThrowException(mitk::IGTHardwareException) << "Hardware Reset of tracking device did not work"; // } // /* Now the tracking device is reset, start initialization */ // NDIErrorCode returnvalue; // /* initialize the tracking device */ // //returnvalue = m_DeviceProtocol->INIT(); // //if (returnvalue != NDIOKAY) // //{ // // this->SetErrorMessage("Could not initialize the tracking device"); // // return mitk::TrackingSystemNotSpecified; // //} // mitk::TrackingDeviceType deviceType; // returnvalue = m_DeviceProtocol->VER(deviceType); // if ((returnvalue != NDIOKAY) || (deviceType == mitk::TrackingSystemNotSpecified)) // { // m_SerialCommunication = NULL; // return mitk::TrackingSystemNotSpecified; // } // m_SerialCommunication = NULL; // return deviceType; return true; } ITK_THREAD_RETURN_TYPE mitk::IGTLDevice::ThreadStartCommunication(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; } IGTLDevice *igtlDevice = (IGTLDevice*)pInfo->UserData; if (igtlDevice != NULL) { igtlDevice->RunCommunication(); } igtlDevice->m_ThreadID = 0; // erase thread id because thread will end. return ITK_THREAD_RETURN_VALUE; } void mitk::IGTLDevice::RunCommunication() { if (this->GetState() != Running) return; // keep lock until end of scope MutexLockHolder communicationFinishedLockHolder(*m_CommunicationFinishedMutex); // Because m_StopCommunication is used by two threads, access has to be guarded // by a mutex. To minimize thread locking, a local copy is used here bool localStopCommunication; // update the local copy of m_StopCommunication this->m_StopCommunicationMutex->Lock(); localStopCommunication = this->m_StopCommunication; this->m_StopCommunicationMutex->Unlock(); while ((this->GetState() == Running) && (localStopCommunication == false)) { //POLLLING // Create a message buffer to receive header igtl::MessageHeader::Pointer headerMsg; headerMsg = igtl::MessageHeader::New(); // Initialize receive buffer headerMsg->InitPack(); // Receive generic header from the socket // this->m_SocketMutex->Lock(); int r = m_Socket->Receive(headerMsg->GetPackPointer(), headerMsg->GetPackSize(),1); // this->m_SocketMutex->Unlock(); if(r == 0) { //this->StopCommunication(); // an error was received, therefor the communication must be stopped m_StopCommunicationMutex->Lock(); m_StopCommunication = true; m_StopCommunicationMutex->Unlock(); } else if (r == headerMsg->GetPackSize()) { // Deserialize the header and check the CRC int crcCheck = headerMsg->Unpack(1); if (crcCheck & igtl::MessageHeader::UNPACK_HEADER) { // Allocate a time stamp igtl::TimeStamp::Pointer ts; ts = igtl::TimeStamp::New(); // Get time stamp igtlUint32 sec; igtlUint32 nanosec; headerMsg->GetTimeStamp(ts); ts->GetTimeStamp(&sec, &nanosec); //check for invalid timestamps // if(sec != 0) { std::cerr << "Time stamp: " << sec << "." << nanosec << std::endl; std::cerr << "Dev type and name: " << headerMsg->GetDeviceType() << " " << headerMsg->GetDeviceName() << std::endl; headerMsg->Print(std::cout); //Create a message buffer to receive transform data /*igtl::MessageBase::Pointer curMessage; curMessage = igtl::MessageBase::New(); curMessage->SetMessageHeader(headerMsg); curMessage->AllocatePack();*/ //Create a message buffer to receive transform data igtl::MessageBase::Pointer curMessage; curMessage = m_MessageFactory->CreateInstance(headerMsg); curMessage->SetMessageHeader(headerMsg); curMessage->AllocatePack(); // Receive transform data from the socket int receiveCheck = 0; receiveCheck = m_Socket->Receive(curMessage->GetPackBodyPointer(), curMessage->GetPackBodySize()); if ( receiveCheck > 0 ) { int c = curMessage->Unpack(1); if ( !(c & igtl::MessageHeader::UNPACK_BODY) ) { mitkThrow() << "crc error"; } //copy the current message into the latest message member - m_LatestMessageMutex->Lock(); - m_LatestMessage = m_MessageFactory->Clone(curMessage); - m_LatestMessageMutex->Unlock(); +// m_LatestMessageMutex->Lock(); + m_Queue->PushMessage(curMessage); +// m_LatestMessage = m_MessageFactory->Clone(curMessage); +// m_LatestMessageMutex->Unlock(); } else { MITK_ERROR("IGTLDevice") << "Received a valid header but could not " << "read the whole message."; } - - -// if (strcmp(headerMsg->GetDeviceType(), "TRANSFORM") == 0) -// { -// //ReceiveImage(socket, headerMsg); - -// // Create a message buffer to receive transform data -// igtl::TransformMessage::Pointer transMsg; -// transMsg = igtl::TransformMessage::New(); -// transMsg->SetMessageHeader(headerMsg); -// transMsg->AllocatePack(); - -// // Receive transform data from the socket -// m_Socket->Receive(transMsg->GetPackBodyPointer(), -// transMsg->GetPackBodySize()); - -// // Deserialize the transform data -// // If you want to skip CRC check, call Unpack() without argument. -// int c = transMsg->Unpack(1); - -// if (c & igtl::MessageHeader::UNPACK_BODY) // if CRC check is OK -// { -// // Retrive the transform data -// igtl::Matrix4x4 matrix; -// transMsg->GetMatrix(matrix); -// igtl::PrintMatrix(matrix); -// std::cerr << std::endl; -// } -// } } } } else { //Message size information and actual data size don't match. } // 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_StopCommunication */ this->m_StopCommunicationMutex->Lock(); localStopCommunication = m_StopCommunication; this->m_StopCommunicationMutex->Unlock(); itksys::SystemTools::Delay(1); } // StopCommunication was called, thus the mode should be changed back to Ready now // that the tracking loop has ended. this->SetState(Ready); MITK_DEBUG("IGTLDevice::RunCommunication") << "Reached end of communication."; // returning from this function (and ThreadStartCommunication()) // this will end the thread return; } bool mitk::IGTLDevice::StartCommunication() { if (this->GetState() != Ready) return false; this->SetState(Running); // go to mode Running // update the local copy of m_StopCommunication this->m_StopCommunicationMutex->Lock(); this->m_StopCommunication = false; this->m_StopCommunicationMutex->Unlock(); // transfer the execution rights to tracking thread m_CommunicationFinishedMutex->Unlock(); // start a new thread that executes the communication m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartCommunication, this); // mitk::IGTTimeStamp::GetInstance()->Start(this); return true; } bool mitk::IGTLDevice::StopCommunication() { if (this->GetState() == Running) // Only if the object is in the correct state { // m_StopCommunication is used by two threads, so we have to ensure correct // thread handling m_StopCommunicationMutex->Lock(); m_StopCommunication = true; m_StopCommunicationMutex->Unlock(); // we have to wait here that the other thread recognizes the STOP-command // and executes it m_CommunicationFinishedMutex->Lock(); // mitk::IGTTimeStamp::GetInstance()->Stop(this); // notify realtime clock // StopCommunication was called, thus the mode should be changed back // to Ready now that the tracking loop has ended. this->SetState(Ready); } return true; } bool mitk::IGTLDevice::CloseConnection() { if (this->GetState() == Setup) { return true; } else if (this->GetState() == Running) { this->StopCommunication(); } m_Socket->CloseSocket(); // //init before closing to force the field generator from aurora to switch itself off // m_DeviceProtocol->INIT(); // /* close the serial connection */ // m_SerialCommunication->CloseConnection(); // /* invalidate all tools */ // this->InvalidateAll(); /* return to setup mode */ this->SetState(Setup); // m_SerialCommunication = NULL; return true; } igtl::MessageBase::Pointer mitk::IGTLDevice::GetLatestMessage() { //copy the latest message into the given msg - m_LatestMessageMutex->Lock(); - igtl::MessageBase::Pointer msg = - this->m_MessageFactory->Clone(m_LatestMessage); - m_LatestMessageMutex->Unlock(); - return msg; +// m_LatestMessageMutex->Lock(); +// igtl::MessageBase::Pointer msg = +// this->m_MessageFactory->Clone(m_LatestMessage); +// m_LatestMessageMutex->Unlock(); +// return msg; + return this->m_Queue->PullMessage(); } diff --git a/Modules/OpenIGTLink/mitkIGTLDevice.h b/Modules/OpenIGTLink/mitkIGTLDevice.h index 6067d9e2e6..254fa5701f 100644 --- a/Modules/OpenIGTLink/mitkIGTLDevice.h +++ b/Modules/OpenIGTLink/mitkIGTLDevice.h @@ -1,195 +1,198 @@ /*=================================================================== 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 MITKIGTLDEVICE_H #define MITKIGTLDEVICE_H #include #include "itkObject.h" #include "mitkCommon.h" #include "itkFastMutexLock.h" #include //#include #include "igtlSocket.h" #include "igtlMessageBase.h" #include "igtlTransformMessage.h" #include "mitkIGTLMessageFactory.h" +#include "mitkIGTLMessageQueue.h" namespace mitk { /**Documentation * \brief Interface for all Open IGT Link Devices * * Defines the methods that are common for all devices using Open IGT Link. * */ class MITK_OPENIGTLINK_EXPORT IGTLDevice : public itk::Object { public: mitkClassMacro(IGTLDevice, itk::Object) /** * Type for state variable. The IGTLDevice is always in one of these states */ enum IGTLDeviceState {Setup, Ready, Running}; /** * \brief Opens a connection to the device * * This may only be called if there is currently no connection to the * device. If OpenConnection() is successful, the object will change from * Setup state to Ready state */ virtual bool OpenConnection() = 0; /** * \brief Closes the connection to the device * * This may only be called if there is currently a connection to the * device, but device is not running (e.g. object is in Ready state) */ virtual bool CloseConnection(); /** * \brief Stops the communication between the two devices * * This may only be called if there the device is in Running state */ virtual bool StopCommunication(); bool StartCommunication(); void RunCommunication(); /** * \brief Sends a message via the open IGT Link. * * This may only be called after the connection to the device has been * established with a call to OpenConnection() (E.g. object is in Ready * mode). This will change the object state from Ready to Running */ bool SendMessage(igtl::MessageBase::Pointer msg); /** * \brief return current object state (Setup, Ready or Running) */ IGTLDeviceState GetState() const; /** * \brief Returns the latest received message * \param msg A smartpointer to the message base where the latest message * shall be copied into * \retval true The latest message is stored in msg * \retval false The latest message could not been copied, do not use this * data */ igtl::MessageBase::Pointer GetLatestMessage(); /** * \brief return device data */ // igtl::MessageBase::Pointer GetData() const; /** * \brief set device data */ // void SetData(IGTLDeviceData data); /** * \brief Sets the port number of the device */ itkSetMacro(PortNumber,int); /** * \brief Returns the port number of the device */ itkGetMacro(PortNumber,int); /** * \brief Sets the ip/hostname of the device */ itkSetMacro(Hostname,std::string); /** * \brief Returns the ip/hostname of the device */ itkGetMacro(Hostname,std::string); /** * \brief static start method for the tracking thread. */ static ITK_THREAD_RETURN_TYPE ThreadStartCommunication(void* data); /** * \brief TestConnection() tries to connect to a IGTL server on the current * ip and port * * \todo check this description * * TestConnection() tries to connect to a IGTL server on the current * ip and port and returns which device it has found. * \return It returns the type of the device that answers. Throws an exception * if no device is available on that ip/port. * @throw mitk::IGTHardwareException Throws an exception if there are errors * while connecting to the device. */ virtual bool TestConnection(); protected: /** * \brief change object state */ void SetState(IGTLDeviceState state); IGTLDevice(); virtual ~IGTLDevice(); // IGTLDeviceData m_Data; ///< current device Data IGTLDeviceState m_State; ///< current object state (Setup, Ready or Running) bool m_StopCommunication; ///< signal stop to thread /** mutex to control access to m_StopThread */ itk::FastMutexLock::Pointer m_StopCommunicationMutex; /** mutex to manage control flow of StopTracking() */ itk::FastMutexLock::Pointer m_CommunicationFinishedMutex; /** mutex to control access to m_State */ itk::FastMutexLock::Pointer m_StateMutex; /** mutex to control access to m_Socket */ // itk::FastMutexLock::Pointer m_SocketMutex; /** mutex to control access to m_LatestMessage */ - itk::FastMutexLock::Pointer m_LatestMessageMutex; +// itk::FastMutexLock::Pointer m_LatestMessageMutex; /** the hostname or ip of the device */ std::string m_Hostname; /** the port number of the device */ int m_PortNumber; /** the socket used to communicate with other IGTL devices */ igtl::Socket::Pointer m_Socket; /** the latest received message */ - igtl::MessageBase::Pointer m_LatestMessage; +// igtl::MessageBase::Pointer m_LatestMessage; + /** The message queue */ + mitk::IGTLMessageQueue::Pointer m_Queue; /** the latest received message */ mitk::IGTLMessageFactory::Pointer m_MessageFactory; private: /** creates worker thread that continuously polls interface for new messages */ itk::MultiThreader::Pointer m_MultiThreader; int m_ThreadID; ///< ID of polling thread }; } // namespace mitk #endif /* MITKIGTLDEVICE_H */ diff --git a/Modules/OpenIGTLink/mitkIGTLDeviceSource.cpp b/Modules/OpenIGTLink/mitkIGTLDeviceSource.cpp index c60167f398..cbec5d5e7f 100644 --- a/Modules/OpenIGTLink/mitkIGTLDeviceSource.cpp +++ b/Modules/OpenIGTLink/mitkIGTLDeviceSource.cpp @@ -1,179 +1,179 @@ /*=================================================================== 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 "mitkIGTLDeviceSource.h" #include "mitkIGTLDevice.h" #include "mitkIGTLMessage.h" //#include "mitkIGTTimeStamp.h" //#include "mitkIGTException.h" mitk::IGTLDeviceSource::IGTLDeviceSource() : mitk::IGTLMessageSource(), m_IGTLDevice(NULL) { } mitk::IGTLDeviceSource::~IGTLDeviceSource() { if (m_IGTLDevice.IsNotNull()) { if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Running) { this->StopCommunication(); } if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Ready) { this->Disconnect(); } m_IGTLDevice = NULL; } } void mitk::IGTLDeviceSource::GenerateData() { if (m_IGTLDevice.IsNull()) return; /* update output with message from the device */ IGTLMessage* msgOut = this->GetOutput(); assert(msgOut); igtl::MessageBase::Pointer msgIn = m_IGTLDevice->GetLatestMessage(); if ( msgIn.IsNotNull() ) { assert(msgIn); msgOut->SetMessage(msgIn); msgOut->SetName(msgIn->GetDeviceName()); } - else - { - MITK_ERROR("IGTLDeviceSource") << "Could not get the latest message."; - } +// else +// { +// MITK_ERROR("IGTLDeviceSource") << "Could not get the latest message."; +// } } void mitk::IGTLDeviceSource::SetIGTLDevice( mitk::IGTLDevice* igtlDevice ) { MITK_DEBUG << "Setting IGTLDevice to " << igtlDevice; if (this->m_IGTLDevice.GetPointer() != igtlDevice) { this->m_IGTLDevice = igtlDevice; this->CreateOutputs(); std::stringstream name; // create a human readable name for the source name << "OpenIGTLink Message Source"; this->SetName(name.str()); } } void mitk::IGTLDeviceSource::CreateOutputs() { //if outputs are set then delete them if (this->GetNumberOfOutputs() > 0) { for (int numOP = this->GetNumberOfOutputs() - 1; numOP >= 0; numOP--) this->RemoveOutput(numOP); this->Modified(); } //fill the outputs if a valid OpenIGTLink device is set if (m_IGTLDevice.IsNull()) return; this->SetNumberOfIndexedOutputs(1); if (this->GetOutput(0) == NULL) { DataObjectPointer newOutput = this->MakeOutput(0); this->SetNthOutput(0, newOutput); this->Modified(); } } void mitk::IGTLDeviceSource::Connect() { if (m_IGTLDevice.IsNull()) { throw std::invalid_argument("mitk::IGTLDeviceSource: " "No OpenIGTLink device set"); } if (this->IsConnected()) { return; } try { m_IGTLDevice->OpenConnection(); } catch (mitk::Exception &e) { throw std::runtime_error(std::string("mitk::IGTLDeviceSource: Could not open" "connection to OpenIGTLink device. Error: ") + e.GetDescription()); } } void mitk::IGTLDeviceSource::StartCommunication() { if (m_IGTLDevice.IsNull()) throw std::invalid_argument("mitk::IGTLDeviceSource: " "No OpenIGTLink device set"); if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Running) return; if (m_IGTLDevice->StartCommunication() == false) throw std::runtime_error("mitk::IGTLDeviceSource: " "Could not start communication"); } void mitk::IGTLDeviceSource::Disconnect() { if (m_IGTLDevice.IsNull()) throw std::invalid_argument("mitk::IGTLDeviceSource: " "No OpenIGTLink device set"); if (m_IGTLDevice->CloseConnection() == false) throw std::runtime_error("mitk::IGTLDeviceSource: Could not close connection" " to OpenIGTLink device"); } void mitk::IGTLDeviceSource::StopCommunication() { if (m_IGTLDevice.IsNull()) throw std::invalid_argument("mitk::IGTLDeviceSource: " "No OpenIGTLink device set"); if (m_IGTLDevice->StopCommunication() == false) throw std::runtime_error("mitk::IGTLDeviceSource: " "Could not stop communicating"); } void mitk::IGTLDeviceSource::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } bool mitk::IGTLDeviceSource::IsConnected() { if (m_IGTLDevice.IsNull()) return false; return (m_IGTLDevice->GetState() == mitk::IGTLDevice::Ready) || (m_IGTLDevice->GetState() == mitk::IGTLDevice::Running); } bool mitk::IGTLDeviceSource::IsCommunicating() { if (m_IGTLDevice.IsNull()) return false; return m_IGTLDevice->GetState() == mitk::IGTLDevice::Running; } diff --git a/Modules/OpenIGTLink/mitkIGTLDummyMessage.cpp b/Modules/OpenIGTLink/mitkIGTLDummyMessage.cpp new file mode 100644 index 0000000000..753f5336b8 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLDummyMessage.cpp @@ -0,0 +1,66 @@ +/*=================================================================== + +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 "mitkIGTLDummyMessage.h" + +#include "igtlutil/igtl_header.h" +#include "igtlutil/igtl_util.h" + + +mitk::IGTLDummyMessage::IGTLDummyMessage() : StringMessage() +{ + this->m_DefaultBodyType = "DUMMY"; +} + +mitk::IGTLDummyMessage::~IGTLDummyMessage() +{ +} + +void mitk::IGTLDummyMessage::SetDummyString( const std::string& dummyString ) +{ + this->m_dummyString = dummyString; + this->m_String = "This is a dummy string"; +} + +std::string mitk::IGTLDummyMessage::GetDummyString() +{ + return this->m_dummyString; +} + +igtl::MessageBase::Pointer mitk::IGTLDummyMessage::Clone() +{ + //initialize the clone + mitk::IGTLDummyMessage::Pointer clone = mitk::IGTLDummyMessage::New(); + + //copy the data + clone->SetString(this->GetString()); + clone->SetDummyString(this->GetDummyString()); + + return igtl::MessageBase::Pointer(clone.GetPointer()); +} + +/** + * \brief Clones the original message interpreted as transform message + * \param original_ The original message that will be interpreted as transform + * message + * \return The clone of the input message + */ +igtl::MessageBase::Pointer mitk::DummyMsgCloneHandler::Clone(igtl::MessageBase* original_) +{ + mitk::IGTLDummyMessage* original = (mitk::IGTLDummyMessage*)original_; + return original->Clone(); +} diff --git a/Modules/OpenIGTLink/mitkIGTLDummyMessage.h b/Modules/OpenIGTLink/mitkIGTLDummyMessage.h new file mode 100644 index 0000000000..d559bdca68 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLDummyMessage.h @@ -0,0 +1,74 @@ +/*=================================================================== + +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 MITKIGTLDUMMYMESSAGE_H +#define MITKIGTLDUMMYMESSAGE_H + +#include "MitkOpenIGTLinkExports.h" + +#include "igtlObject.h" +#include "igtlStringMessage.h" +#include "mitkIGTLMessageCloneHandler.h" + +namespace mitk +{ + +/** Documentation +* \class IGTLDummyMessage +* \brief This class is a dummy message to show the how to implement a new message +* type +*/ +class MITK_OPENIGTLINK_EXPORT IGTLDummyMessage: public igtl::StringMessage +{ +public: + typedef IGTLDummyMessage Self; + typedef StringMessage Superclass; + typedef igtl::SmartPointer Pointer; + typedef igtl::SmartPointer ConstPointer; + + igtlTypeMacro( mitk::IGTLDummyMessage, igtl::StringMessage ); + igtlNewMacro( mitk::IGTLDummyMessage ); + +public: + /** + * Set dummy string + */ + void SetDummyString( const std::string& dummyString ); + + /** + * Get dummy string + */ + std::string GetDummyString(); + + /** + * Returns a clone of itself + */ + igtl::MessageBase::Pointer Clone(); + +protected: + IGTLDummyMessage(); + ~IGTLDummyMessage(); + + std::string m_dummyString; +}; + + +mitkIGTMessageCloneClassMacro(IGTLDummyMessage, DummyMsgCloneHandler); + + +} // namespace mitk + +#endif diff --git a/Modules/OpenIGTLink/mitkIGTLMessageFactory.cpp b/Modules/OpenIGTLink/mitkIGTLMessageFactory.cpp index 8624669dfd..7b6219d6f3 100644 --- a/Modules/OpenIGTLink/mitkIGTLMessageFactory.cpp +++ b/Modules/OpenIGTLink/mitkIGTLMessageFactory.cpp @@ -1,211 +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 "mitkIGTLMessageFactory.h" // IGT message types #include "igtlImageMessage.h" #include "igtlTransformMessage.h" #include "igtlPositionMessage.h" #include "igtlStatusMessage.h" +//own types +#include "mitkIGTLDummyMessage.h" + #include "mitkIGTLMessageCommon.h" #include "itksys/SystemTools.hxx" //------------------------------------------------------------ // Define message clone classes // igtlMessageHandlerClassMacro() defines a child class of // igtl::MessageHandler to handle OpenIGTLink messages for // the message type specified as the first argument. The // second argument will be used for the name of this // message handler class, while the third argument specifies // a type of data that will be shared with the message functions // of this handler class. mitkIGTMessageCloneClassMacro(igtl::TransformMessage, TransformMsgCloneHandler); /** * \brief Clones the original message interpreted as transform message * \param original_ The original message that will be interpreted as transform * message * \return The clone of the input message */ igtl::MessageBase::Pointer TransformMsgCloneHandler::Clone(igtl::MessageBase* original_) { bool copySuccess = false; igtl::TransformMessage::Pointer clone_ = igtl::TransformMessage::New(); //initialize the clone // clone = igtl::MessageBase::New(); igtl::TransformMessage* original = (igtl::TransformMessage*)original_; //copy all meta data copySuccess = clone_->Copy(original); if ( !copySuccess ) return NULL; //copy all data that is important for this class //copy the matrix igtl::Matrix4x4 mat; original->GetMatrix(mat); clone_->SetMatrix(mat); //copy the normals float normals[3][3]; original->GetNormals(normals); clone_->SetNormals(normals); //copy the position float position[3]; original->GetPosition(position); clone_->SetPosition(position); return igtl::MessageBase::Pointer(clone_.GetPointer()); } + mitk::IGTLMessageFactory::IGTLMessageFactory() { //create clone handlers // mitk::IGTLMessageCloneHandler::Pointer tmch = ; this->AddMessageType("NONE", NULL, NULL); //OpenIGTLink Types V1 // this->AddMessageType("IMAGE", (PointerToCloneMessageFunction)&igtl::ImageMessage::New); this->AddMessageType("TRANSFORM", (PointerToMessageBaseNew)&igtl::TransformMessage::New, TransformMsgCloneHandler::New().GetPointer()); // this->AddMessageType("POSITION", (PointerToCloneMessageFunction)&igtl::PositionMessage::New); // this->AddMessageType("STATUS", (PointerToCloneMessageFunction)&igtl::StatusMessage::New); // this->AddMessageType("CAPABILITY", (PointerToCloneMessageFunction)&igtl::StatusMessage::New); // //OpenIGTLink Types V2 -// this->AddMessageType("IMGMETA", (PointerToCloneMessageFunction)&igtl::PlusClientInfoMessage::New); +// this->AddMessageType("IMGMETA", (PointerToCloneMessageFunction)&igtl::IGTLDummyMessage::New); // this->AddMessageType("LBMETA", (PointerToCloneMessageFunction)&igtl::PlusTrackedFrameMessage::New); // this->AddMessageType("COLORT", (PointerToCloneMessageFunction)&igtl::PlusUsMessage::New); // this->AddMessageType("POINT", (PointerToCloneMessageFunction)&igtl::PlusUsMessage::New); // this->AddMessageType("TRAJ", (PointerToCloneMessageFunction)&igtl::PlusUsMessage::New); // this->AddMessageType("TDATA", (PointerToCloneMessageFunction)&igtl::PlusUsMessage::New); // this->AddMessageType("QTDATA", (PointerToCloneMessageFunction)&igtl::PlusUsMessage::New); // this->AddMessageType("SENSOR", (PointerToCloneMessageFunction)&igtl::PlusUsMessage::New); // this->AddMessageType("STRING", (PointerToCloneMessageFunction)&igtl::PlusUsMessage::New); // this->AddMessageType("NDARRAY", (PointerToCloneMessageFunction)&igtl::PlusUsMessage::New); // this->AddMessageType("BIND", (PointerToCloneMessageFunction)&igtl::PlusUsMessage::New); // this->AddMessageType("POLYDATA", (PointerToCloneMessageFunction)&igtl::PlusUsMessage::New); -// //Own Types -// this->AddMessageType("MITKXXX", (PointerToCloneMessageFunction)&igtl::PlusUsMessage::New); + //Own Types + this->AddMessageType("DUMMY", (PointerToMessageBaseNew)&mitk::IGTLDummyMessage::New, DummyMsgCloneHandler::New().GetPointer()); } mitk::IGTLMessageFactory::~IGTLMessageFactory() { } void mitk::IGTLMessageFactory::AddMessageType(std::string messageTypeName, IGTLMessageFactory::PointerToMessageBaseNew messageTypeNewPointer, mitk::IGTLMessageCloneHandler::Pointer cloneHandler) { this->AddMessageNewMethod(messageTypeName, messageTypeNewPointer); this->AddMessageCloneHandler(messageTypeName, cloneHandler); } void mitk::IGTLMessageFactory::AddMessageNewMethod(std::string messageTypeName, IGTLMessageFactory::PointerToMessageBaseNew messageTypeNewPointer ) { this->m_NewMethods[messageTypeName] = messageTypeNewPointer; } void mitk::IGTLMessageFactory::AddMessageCloneHandler(std::string msgTypeName, mitk::IGTLMessageCloneHandler::Pointer cloneHandler ) { this->m_CloneHandlers[msgTypeName] = cloneHandler; } mitk::IGTLMessageCloneHandler::Pointer mitk::IGTLMessageFactory::GetCloneHandler(std::string messageTypeName) { if ( this->m_CloneHandlers.find(messageTypeName) != this->m_CloneHandlers.end() ) { return m_CloneHandlers[messageTypeName]; } MITK_ERROR("IGTLMessageFactory") << messageTypeName << " message type is not registered to factory!"; mitkThrow() << messageTypeName << " message type is not registered to factory!"; return NULL; } igtl::MessageBase::Pointer mitk::IGTLMessageFactory::Clone(igtl::MessageBase::Pointer msg) { return this->GetCloneHandler(msg->GetDeviceType())->Clone(msg); } mitk::IGTLMessageFactory::PointerToMessageBaseNew mitk::IGTLMessageFactory::GetMessageTypeNewPointer(std::string messageTypeName) { if ( this->m_NewMethods.find(messageTypeName) != this->m_NewMethods.end() ) { return m_NewMethods[messageTypeName]; } MITK_ERROR("IGTLMessageFactory") << messageTypeName << " message type is not registered to factory!"; return NULL; } igtl::MessageBase::Pointer mitk::IGTLMessageFactory::CreateInstance(igtl::MessageHeader::Pointer msgHeader) { std::string messageType; //check the header if ( msgHeader.IsNull() ) { messageType = "NONE"; } else { messageType = msgHeader->GetDeviceType(); } //make message type uppercase messageType = itksys::SystemTools::UpperCase(messageType); //find the according new method if ( this->m_NewMethods.find( messageType ) != this->m_NewMethods.end() ) { if ( this->m_NewMethods[messageType] != NULL) { // Call tracker New() function if tracker not NULL return (*this->m_NewMethods[messageType])(); } else return NULL; } else { MITK_ERROR("IGTLMessageFactory") << "Unknown IGT message type: " << messageType; return NULL; } } diff --git a/Modules/OpenIGTLink/mitkIGTLMessageQueue.cpp b/Modules/OpenIGTLink/mitkIGTLMessageQueue.cpp new file mode 100644 index 0000000000..c2d6e22e43 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessageQueue.cpp @@ -0,0 +1,57 @@ +/*=================================================================== + +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 "mitkIGTLMessageQueue.h" +#include +#include "igtlMessageBase.h" + + + +void mitk::IGTLMessageQueue::PushMessage( igtl::MessageBase::Pointer message ) +{ + this->m_Mutex->Lock(); + this->m_Queue.push_back( message ); + this->m_Mutex->Unlock(); +} + +igtl::MessageBase::Pointer mitk::IGTLMessageQueue::PullMessage() +{ + this->m_Mutex->Lock(); + igtl::MessageBase::Pointer ret = NULL; + if ( this->m_Queue.size() > 0 ) + { + ret = this->m_Queue.front(); + this->m_Queue.pop_front(); + } + this->m_Mutex->Unlock(); + + return ret; +} + +int mitk::IGTLMessageQueue::GetSize() +{ + return this->m_Queue.size(); +} + +mitk::IGTLMessageQueue::IGTLMessageQueue() +{ + this->m_Mutex = itk::FastMutexLock::New(); +} + +mitk::IGTLMessageQueue::~IGTLMessageQueue() +{ + this->m_Mutex->Delete(); +} diff --git a/Modules/OpenIGTLink/mitkIGTLMessageQueue.h b/Modules/OpenIGTLink/mitkIGTLMessageQueue.h new file mode 100644 index 0000000000..7a44fbe163 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessageQueue.h @@ -0,0 +1,67 @@ +/*=================================================================== + +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 IGTLMessageQueue_H +#define IGTLMessageQueue_H + +#include "MitkOpenIGTLinkExports.h" + +#include "itkObject.h" +#include "itkFastMutexLock.h" +#include "mitkCommon.h" + +#include + +#include "igtlMessageBase.h" + + +namespace mitk { + /** + * \class IGTLMessageQueue + * \brief Thread safe message queue to store OpenIGTLink messages. + */ + class MITK_OPENIGTLINK_EXPORT IGTLMessageQueue : public itk::Object + { + public: + mitkClassMacro(mitk::IGTLMessageQueue, itk::Object) + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + void PushMessage( igtl::MessageBase::Pointer message ); + igtl::MessageBase::Pointer PullMessage(); + + int GetSize(); + + protected: + IGTLMessageQueue(); + virtual ~IGTLMessageQueue(); + + + protected: + /** + * \brief Mutex to take car of the queue + */ + itk::FastMutexLock::Pointer m_Mutex; + + /** + * \brief the queue that stores pointer to the inserted messages + */ + std::deque< igtl::MessageBase::Pointer > m_Queue; + }; +} + + +#endif