diff --git a/Modules/OpenIGTLink/files.cmake b/Modules/OpenIGTLink/files.cmake index 216e1731ad..0e87986c24 100644 --- a/Modules/OpenIGTLink/files.cmake +++ b/Modules/OpenIGTLink/files.cmake @@ -1,13 +1,14 @@ set(CPP_FILES mitkIGTLClient.cpp + mitkIGTLServer.cpp mitkIGTLDevice.cpp mitkIGTLMessageSource.cpp mitkIGTLDeviceSource.cpp mitkIGTLMessage.cpp mitkIGTLMessageCommon.cpp mitkIGTLMessageFactory.cpp mitkIGTLMessageCloneHandler.h mitkIGTLDummyMessage.cpp mitkIGTLMessageQueue.cpp mitkIGTLMessageProvider.cpp ) diff --git a/Modules/OpenIGTLink/mitkIGTLClient.cpp b/Modules/OpenIGTLink/mitkIGTLClient.cpp index 3eaaf33c48..dfe387e05c 100644 --- a/Modules/OpenIGTLink/mitkIGTLClient.cpp +++ b/Modules/OpenIGTLink/mitkIGTLClient.cpp @@ -1,77 +1,115 @@ /*=================================================================== 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 "mitkIGTLClient.h" //#include "mitkIGTTimeStamp.h" //#include "mitkIGTHardwareException.h" #include #include #include #include typedef itk::MutexLockHolder MutexLockHolder; mitk::IGTLClient::IGTLClient() : IGTLDevice() { } mitk::IGTLClient::~IGTLClient() { } bool mitk::IGTLClient::OpenConnection() { if (this->GetState() != Setup) { mitkThrowException(mitk::Exception) << "Can only try to open the connection if in setup mode"; return false; } std::string hostname = this->GetHostname(); int portNumber = this->GetPortNumber(); if (portNumber == -1 || hostname.size() <= 0) { //port number or hostname was not correct return false; } //create a new client socket m_Socket = igtl::ClientSocket::New(); //try to connect to the igtl server int response = dynamic_cast(m_Socket.GetPointer())-> ConnectToServer(hostname.c_str(), portNumber); //check the response if ( response != 0 ) { mitkThrowException(mitk::Exception) << "The client could not connect to " << hostname << " port: " << portNumber; return false; } // everything is initialized and connected so the communication can be started this->SetState(Ready); return true; } + +void mitk::IGTLClient::Connect() +{ + +} + +void mitk::IGTLClient::Receive() +{ + this->ReceivePrivate(this->m_Socket); +} + +void mitk::IGTLClient::Send() +{ + igtl::MessageBase::Pointer curMessage; + + //get the latest message from the queue + curMessage = this->m_SendQueue->PullMessage(); + + // there is no message => return + if ( curMessage.IsNull() ) + return; + + if ( this->SendMessagePrivate(curMessage.GetPointer(), this->m_Socket) ) + { + MITK_INFO("IGTLDevice") << "Successfully sent the message."; + } + else + { + MITK_ERROR("IGTLDevice") << "Could not send the message."; + } +} + +void mitk::IGTLClient::StopCommunicationWithSocket(igtl::Socket* /*socket*/) +{ + m_StopCommunicationMutex->Lock(); + m_StopCommunication = true; + m_StopCommunicationMutex->Unlock(); +} diff --git a/Modules/OpenIGTLink/mitkIGTLClient.h b/Modules/OpenIGTLink/mitkIGTLClient.h index 2fa19c8651..dcd7074c4f 100644 --- a/Modules/OpenIGTLink/mitkIGTLClient.h +++ b/Modules/OpenIGTLink/mitkIGTLClient.h @@ -1,62 +1,94 @@ /*=================================================================== 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 MITKIGTLCLIENT_H #define MITKIGTLCLIENT_H #include "mitkIGTLDevice.h" #include namespace mitk { /** Documentation * \brief superclass for open IGT link client * * implements the IGTLDevice interface for IGTL clients * * \ingroup IGT */ class MITK_OPENIGTLINK_EXPORT IGTLClient : public IGTLDevice { public: mitkClassMacro(IGTLClient, IGTLDevice) itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** * \brief initialize the connection to the IGTL device * * \todo check this description * * OpenConnection() establishes the connection to the IGTL server by: * - connection to the IGTL device * - initializing the device * @throw mitk::IGTHardwareException Throws an exception if there are errors while connecting to the device. * @throw mitk::IGTException Throws a normal IGT exception if an error occures which is not related to the hardware. */ virtual bool OpenConnection(); protected: IGTLClient(); ///< Constructor virtual ~IGTLClient(); ///< Destructor + + /** + * \brief Call this method to receive a message. + * + * The message will be saved in the receive queue. + */ + virtual void Receive(); + + /** + * \brief Call this method to send a message. The message will be read from + * the queue + */ + virtual void Send(); + + /** + * \brief Call this method to check for other devices that want to connect + * to this one. + * + * In case of a client this method is doing nothing. In case of a server it + * is checking for other devices and if there is one it establishes a + * connection. + */ + virtual void Connect(); + + /** + * \brief Stops the communication with the given socket. + * + * The client uses just one socket. Therefore, calling this function causes + * the stop of the communication. + * + */ + virtual void StopCommunicationWithSocket(igtl::Socket*); }; } // namespace mitk #endif /* MITKIGTLCLIENT_H */ diff --git a/Modules/OpenIGTLink/mitkIGTLDevice.cpp b/Modules/OpenIGTLink/mitkIGTLDevice.cpp index a21d3166ac..57e2c91566 100644 --- a/Modules/OpenIGTLink/mitkIGTLDevice.cpp +++ b/Modules/OpenIGTLink/mitkIGTLDevice.cpp @@ -1,379 +1,396 @@ /*=================================================================== 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 static const int SOCKET_SEND_RECEIVE_TIMEOUT_MSEC = 100; typedef itk::MutexLockHolder MutexLockHolder; mitk::IGTLDevice::IGTLDevice() : // m_Data(mitk::DeviceDataUnspecified), m_State(mitk::IGTLDevice::Setup), m_StopCommunication(false), m_PortNumber(-1), m_Name("Unspecified Device"), m_MultiThreader(NULL), m_ThreadID(0) { m_StopCommunicationMutex = itk::FastMutexLock::New(); m_StateMutex = 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_MessageFactory = mitk::IGTLMessageFactory::New(); - m_SendQueue = mitk::IGTLMessageQueue::New(); - m_ReceiveQueue = mitk::IGTLMessageQueue::New(); + m_SendQueue = mitk::IGTLMessageQueue::New(); + m_ReceiveQueue = mitk::IGTLMessageQueue::New(); + m_CommandQueue = 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(); } -void mitk::IGTLDevice::SendMessage(igtl::MessageBase::Pointer msg) -{ - //add the message to the queue - m_SendQueue->PushMessage(msg); -} - -bool mitk::IGTLDevice::SendMessagePrivate(igtl::MessageBase::Pointer msg) -{ - //check the input message - if ( msg.IsNull() ) - { - MITK_ERROR("IGTLDevice") << "Could not send message because message is not " - "valid. Please check."; - return false; - } - - // add the name of this device to the message - msg->SetDeviceName(this->GetName().c_str()); - - // Pack (serialize) and send - msg->Pack(); - int sendSuccess = - this->m_Socket->Send(msg->GetPackPointer(), msg->GetPackSize()); - - if (sendSuccess) - return true; - else - return false; -} - bool mitk::IGTLDevice::TestConnection() { return true; } -void mitk::IGTLDevice::Receive() +void mitk::IGTLDevice::ReceivePrivate(igtl::Socket* socket) { // 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 int r = - m_Socket->Receive(headerMsg->GetPackPointer(), headerMsg->GetPackSize(),1); + socket->Receive(headerMsg->GetPackPointer(), headerMsg->GetPackSize(), 1); if(r == 0) { - //this->StopCommunication(); - // an error was received, therefor the communication must be stopped - m_StopCommunicationMutex->Lock(); - m_StopCommunication = true; - m_StopCommunicationMutex->Unlock(); + // an error was received, therefor the communication with this socket + // must be stopped + + this->StopCommunicationWithSocket(socket); } 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); 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 = 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 ) + //check the type of the received message + //if it is a command push it into the command queue + //otherwise into the normal receive queue + const char* curDevType = headerMsg->GetDeviceType(); + if ( std::strstr( curDevType, "GET_" ) != NULL || + std::strstr( curDevType, "STT_" ) != NULL || + std::strstr( curDevType, "STP_" ) != NULL) { - int c = curMessage->Unpack(1); - if ( !(c & igtl::MessageHeader::UNPACK_BODY) ) - { - mitkThrow() << "crc error"; - } - - //push the current message into the queue - m_ReceiveQueue->PushMessage(curMessage); - this->InvokeEvent(MessageReceivedEvent()); + this->m_CommandQueue->PushMessage(headerMsg); + this->InvokeEvent(CommandReceivedEvent()); } else { - MITK_ERROR("IGTLDevice") << "Received a valid header but could not " - << "read the whole message."; + //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 = socket->Receive(curMessage->GetPackBodyPointer(), + curMessage->GetPackBodySize()); + + if ( receiveCheck > 0 ) + { + int c = curMessage->Unpack(1); + if ( !(c & igtl::MessageHeader::UNPACK_BODY) ) + { + mitkThrow() << "crc error"; + } + + this->m_ReceiveQueue->PushMessage(curMessage); + this->InvokeEvent(MessageReceivedEvent()); + } + else + { + MITK_ERROR("IGTLDevice") << "Received a valid header but could not " + << "read the whole message."; + } } } } else { //Message size information and actual data size don't match. } } -void mitk::IGTLDevice::Send() +void mitk::IGTLDevice::SendMessage(igtl::MessageBase::Pointer msg) { - igtl::MessageBase::Pointer curMessage; - - //get the latest message from the queue - curMessage = m_SendQueue->PullMessage(); - - // there is no message => return - if ( curMessage.IsNull() ) - return; + //add the message to the queue + m_SendQueue->PushMessage(msg); +} - if ( this->SendMessagePrivate(curMessage.GetPointer()) ) +bool mitk::IGTLDevice::SendMessagePrivate(igtl::MessageBase::Pointer msg, + igtl::Socket::Pointer socket) +{ + //check the input message + if ( msg.IsNull() ) { - MITK_INFO("IGTLDevice") << "Successfully sent the message."; + MITK_ERROR("IGTLDevice") << "Could not send message because message is not " + "valid. Please check."; + return false; } + + // add the name of this device to the message + msg->SetDeviceName(this->GetName().c_str()); + + // Pack (serialize) and send + msg->Pack(); + int sendSuccess = socket->Send(msg->GetPackPointer(), msg->GetPackSize()); + + if (sendSuccess) + return true; else - { - MITK_ERROR("IGTLDevice") << "Could not send the message."; - } + return false; } 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)) { + // Check if other igtl devices want to connect with this one. This method + // is overwritten for igtl servers but is doing nothing in case of a igtl + // client + this->Connect(); + // Check if there is something to receive and store it in the message queue this->Receive(); // Check if there is something to send this->Send(); /* Update the local copy of m_StopCommunication */ this->m_StopCommunicationMutex->Lock(); localStopCommunication = m_StopCommunication; this->m_StopCommunicationMutex->Unlock(); // time to relax 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; // go to mode Running this->SetState(Running); // set a timeout for the sending and receiving this->m_Socket->SetTimeout(SOCKET_SEND_RECEIVE_TIMEOUT_MSEC); // 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(); /* return to setup mode */ this->SetState(Setup); // m_SerialCommunication = NULL; return true; } -igtl::MessageBase::Pointer mitk::IGTLDevice::GetLatestMessage() +igtl::MessageBase::Pointer mitk::IGTLDevice::GetNextMessage() { - //copy the latest message into the given msg -// m_ReceiveQueueMutex->Lock(); + //copy the next message into the given msg igtl::MessageBase::Pointer msg = this->m_ReceiveQueue->PullMessage(); -// m_ReceiveQueueMutex->Unlock(); return msg; } -std::string mitk::IGTLDevice::GetOldestMessageInformation() +igtl::MessageBase::Pointer mitk::IGTLDevice::GetNextCommand() { - return this->m_ReceiveQueue->GetOldestMsgInformation(); + //copy the next command into the given msg + igtl::MessageBase::Pointer msg = this->m_CommandQueue->PullMessage(); + return msg; } +//std::string mitk::IGTLDevice::GetNextMessageInformation() +//{ +// return this->m_ReceiveQueue->GetNextMsgInformationString(); +//} + +//std::string mitk::IGTLDevice::GetNextMessageDeviceType() +//{ +// return this->m_ReceiveQueue->GetNextMsgDeviceType(); +//} + +//std::string mitk::IGTLDevice::GetNextCommandInformation() +//{ +// return this->m_CommandQueue->GetNextMsgInformationString(); +//} + +//std::string mitk::IGTLDevice::GetNextCommandDeviceType() +//{ +// return this->m_CommandQueue->GetNextMsgDeviceType(); +//} + 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; } diff --git a/Modules/OpenIGTLink/mitkIGTLDevice.h b/Modules/OpenIGTLink/mitkIGTLDevice.h index 2f309859aa..a541125f70 100644 --- a/Modules/OpenIGTLink/mitkIGTLDevice.h +++ b/Modules/OpenIGTLink/mitkIGTLDevice.h @@ -1,250 +1,329 @@ /*=================================================================== 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(). Note that the message * is not send directly. This method just adds it to the send queue. */ void 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 + * \brief Returns the oldest command message + * \param msg A smartpointer to the message base where the oldest command * 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(); + igtl::MessageBase::Pointer GetNextCommand(); /** - * \brief Returns information about the oldest message in the receive queue + * \brief Returns the oldest 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 */ - std::string GetOldestMessageInformation(); + igtl::MessageBase::Pointer GetNextMessage(); + +// /** +// * \brief Returns information about the oldest message in the receive queue +// */ +// std::string GetNextMessageInformation(); + +// /** +// * \brief Returns device type about the oldest message in the receive queue +// */ +// std::string GetNextMessageDeviceType(); + +// /** +// * \brief Returns information about the oldest message in the command queue +// */ +// std::string GetNextCommandInformation(); + +// /** +// * \brief Returns device type about the oldest message in the command queue +// */ +// std::string GetNextCommandDeviceType(); /** * \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 Returns the name of this device */ itkGetConstMacro(Name, std::string); /** * \brief Sets the name of this device */ itkSetMacro(Name, std::string); + /** + * \brief Returns a const reference to the receive queue + */ + itkGetConstMacro(ReceiveQueue, mitk::IGTLMessageQueue::Pointer); + + /** + * \brief Returns a const reference to the command queue + */ + itkGetConstMacro(CommandQueue, mitk::IGTLMessageQueue::Pointer); + + /** + * \brief Returns a const reference to the send queue + */ + itkGetConstMacro(SendQueue, mitk::IGTLMessageQueue::Pointer); + + /** * \brief Returns the message factory */ itkGetMacro(MessageFactory, mitk::IGTLMessageFactory::Pointer); /** * \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 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() */ - bool SendMessagePrivate(igtl::MessageBase::Pointer msg); + bool SendMessagePrivate(igtl::MessageBase::Pointer msg, + igtl::Socket::Pointer socket); /** - * \brief Call this method to receive a message. The message will be saved - * in the queue + * \brief Call this method to receive a message. + * + * The message will be saved in the receive queue. + */ + virtual void Receive() = 0; + + /** + * \brief Call this method to receive a message from the given client. + * + * The message will be saved in the receive queue. */ - void Receive(); + void ReceivePrivate(igtl::Socket* client); /** * \brief Call this method to send a message. The message will be read from * the queue */ - void Send(); + virtual void Send() = 0; + + /** + * \brief Call this method to check for other devices that want to connect + * to this one. + * + * In case of a client this method is doing nothing. In case of a server it + * is checking for other devices and if there is one it establishes a + * connection. + */ + virtual void Connect() = 0; + + /** + * \brief Stops the communication with the given socket + * + */ + virtual void StopCommunicationWithSocket(igtl::Socket* socket) = 0; /** * \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_ReceiveQueue */ // itk::FastMutexLock::Pointer m_ReceiveQueueMutex; /** mutex to control access to m_SendQueue */ // itk::FastMutexLock::Pointer m_SendQueueMutex; /** 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; /** The message receive queue */ mitk::IGTLMessageQueue::Pointer m_ReceiveQueue; /** The message send queue */ mitk::IGTLMessageQueue::Pointer m_SendQueue; - /** the latest received message */ + /** A queue that stores just command messages received by this device */ + mitk::IGTLMessageQueue::Pointer m_CommandQueue; + /** A message factory that provides the New() method for all msg types */ mitk::IGTLMessageFactory::Pointer m_MessageFactory; /** the name of this device */ std::string m_Name; private: /** creates worker thread that continuously polls interface for new messages */ itk::MultiThreader::Pointer m_MultiThreader; int m_ThreadID; ///< ID of polling thread }; /**Documentation * @brief connect to this Event to get noticed when a message was received * */ itkEventMacro( MessageReceivedEvent , itk::AnyEvent ); + /**Documentation + * @brief connect to this Event to get noticed when a command was received + * */ + itkEventMacro( CommandReceivedEvent , itk::AnyEvent ); + + /**Documentation + * @brief connect to this Event to get noticed when another igtl device + * connects with this device. + * */ + itkEventMacro( NewClientConnectionEvent , itk::AnyEvent ); + } // namespace mitk #endif /* MITKIGTLDEVICE_H */ diff --git a/Modules/OpenIGTLink/mitkIGTLDeviceSource.cpp b/Modules/OpenIGTLink/mitkIGTLDeviceSource.cpp index 41954cfb12..c6989a0682 100644 --- a/Modules/OpenIGTLink/mitkIGTLDeviceSource.cpp +++ b/Modules/OpenIGTLink/mitkIGTLDeviceSource.cpp @@ -1,223 +1,234 @@ /*=================================================================== 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" //Microservices #include #include #include #include //itk #include const std::string mitk::IGTLDeviceSource::US_PROPKEY_IGTLDEVICENAME = mitk::IGTLMessageSource::US_INTERFACE_NAME + ".igtldevicename"; mitk::IGTLDeviceSource::IGTLDeviceSource() : mitk::IGTLMessageSource(), m_IGTLDevice(NULL) { this->SetName("IGTLDeviceSource (no defined type)"); } 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(); + igtl::MessageBase::Pointer msgIn = m_IGTLDevice->GetNextMessage(); if ( msgIn.IsNotNull() ) { assert(msgIn); msgOut->SetMessage(msgIn); msgOut->SetName(msgIn->GetDeviceName()); } // 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 << "OIGTL Device Source ( " << igtlDevice->GetName() << " )"; this->SetName(name.str()); - //setup a observer that listens to new messages + //setup a observer that listens to new messages and new commands typedef itk::SimpleMemberCommand CurCommandType; - CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); - messageReceivedCommand->SetCallbackFunction( + CurCommandType::Pointer msgReceivedCommand = CurCommandType::New(); + msgReceivedCommand->SetCallbackFunction( this, &IGTLDeviceSource::OnIncomingMessage ); this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), - messageReceivedCommand); + msgReceivedCommand); + CurCommandType::Pointer cmdReceivedCommand = CurCommandType::New(); + cmdReceivedCommand->SetCallbackFunction( + this, &IGTLDeviceSource::OnIncomingCommand ); + this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), + cmdReceivedCommand); } } 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; } void mitk::IGTLDeviceSource::RegisterAsMicroservice() { // Get Context us::ModuleContext* context = us::GetModuleContext(); // Define ServiceProps us::ServiceProperties props; mitk::UIDGenerator uidGen = mitk::UIDGenerator ("org.mitk.services.IGTLDeviceSource.id_", 16); props[ US_PROPKEY_ID ] = uidGen.GetUID(); props[ US_PROPKEY_DEVICENAME ] = this->GetName(); props[ US_PROPKEY_IGTLDEVICENAME ] = m_Name; + props[ US_PROPKEY_DEVICETYPE ] = m_Type; m_ServiceRegistration = context->RegisterService(this, props); } void mitk::IGTLDeviceSource::OnIncomingMessage() { } + +void mitk::IGTLDeviceSource::OnIncomingCommand() +{ + +} diff --git a/Modules/OpenIGTLink/mitkIGTLDeviceSource.h b/Modules/OpenIGTLink/mitkIGTLDeviceSource.h index e1f838ba28..e71d4bad3f 100644 --- a/Modules/OpenIGTLink/mitkIGTLDeviceSource.h +++ b/Modules/OpenIGTLink/mitkIGTLDeviceSource.h @@ -1,146 +1,152 @@ /*=================================================================== 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 IGTLDEVICESOURCE_H_HEADER_INCLUDED_ #define IGTLDEVICESOURCE_H_HEADER_INCLUDED_ #include "mitkIGTLDevice.h" #include "mitkIGTLMessageSource.h" namespace mitk { /**Documentation * \brief Connects a mitk::IGTLDevice to a * MITK-OpenIGTLink Message-Filterpipeline * * This class is the source of most OpenIGTLink pipelines. It encapsulates a * mitk::IGTLDevice and provides the information/messages of the connected * OpenIGTLink devices as igtl::MessageBase objects. Note, that there is just * one single output. * */ class MITK_OPENIGTLINK_EXPORT IGTLDeviceSource : public IGTLMessageSource { public: mitkClassMacro(IGTLDeviceSource, IGTLMessageSource); itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** *\brief These Constants are used in conjunction with Microservices */ static const std::string US_PROPKEY_IGTLDEVICENAME; /** * \brief sets the OpenIGTLink device that will be used as a data source */ virtual void SetIGTLDevice(mitk::IGTLDevice* td); /** * \brief returns the OpenIGTLink device that is used by this filter */ itkGetObjectMacro(IGTLDevice, mitk::IGTLDevice); /** *\brief Registers this object as a Microservice, making it available to every * module and/or plugin. To unregister, call UnregisterMicroservice(). */ virtual void RegisterAsMicroservice(); /** * \brief Establishes a connection to the OpenIGTLink device. If there is * already a connection the method does nothing. * \warning. Will throw a std::invalid_argument exception if no OpenIGTLink * device was set with SetIGTLDevice(). Will throw a std::runtime_error if * the OpenIGTLink device returns an error. */ void Connect(); /** * \brief Closes the connection to the OpenIGTLink device * \warning. Will throw a std::invalid_argument exception if no OpenIGTLink * device was set with SetIGTLDevice(). Will throw a std::runtime_error if * the OpenIGTLink device returns an error. */ void Disconnect(); /** * \brief starts the communication of the device. * This needs to be called before Update() or GetOutput()->Update(). If the * device is already communicating the method does nothing. * \warning. Will throw a std::invalid_argument exception if no OpenIGTLink * device was set with SetIGTLDevice(). Will throw a std::runtime_error if * the OpenIGTLink device returns an error. */ void StartCommunication(); /** * \brief stops the communication of the device. * \warning. Will throw a std::invalid_argument exception if no OpenIGTLink * device was set with SetIGTLDevice(). Will throw a std::runtime_error if * the OpenIGTLink device returns an error. */ void StopCommunication(); /** * \brief returns true if a connection to the OpenIGTLink device is established * */ virtual bool IsConnected(); /** * \brief returns true if communication is in progress * */ virtual bool IsCommunicating(); /** * \brief Used for pipeline update */ virtual void UpdateOutputInformation(); protected: IGTLDeviceSource(); virtual ~IGTLDeviceSource(); /** * \brief filter execute method * * queries the OpenIGTLink device for new messages and updates its output * igtl::MessageBase objects with it. * \warning Will raise a std::out_of_range exception, if tools were added to * the OpenIGTLink device after it was set as input for this filter */ virtual void GenerateData(); /** * \brief Create the necessary outputs for the m_IGTLDevice * * This Method is called internally whenever outputs need to be reset. Old * Outputs are deleted when called. **/ void CreateOutputs(); /** * \brief This method is called when the IGTL device hold by this class * receives a new message **/ virtual void OnIncomingMessage(); + /** + * \brief This method is called when the IGTL device hold by this class + * receives a new command + **/ + virtual void OnIncomingCommand(); + /** the OpenIGTLink device that is used as a source for this filter object*/ mitk::IGTLDevice::Pointer m_IGTLDevice; }; } // namespace mitk #endif /* MITKIGTLDeviceSource_H_HEADER_INCLUDED_ */ diff --git a/Modules/OpenIGTLink/mitkIGTLMessageFactory.cpp b/Modules/OpenIGTLink/mitkIGTLMessageFactory.cpp index 53c24b653d..bc25fbcd4c 100644 --- a/Modules/OpenIGTLink/mitkIGTLMessageFactory.cpp +++ b/Modules/OpenIGTLink/mitkIGTLMessageFactory.cpp @@ -1,280 +1,281 @@ /*=================================================================== 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" #include "igtlImageMetaMessage.h" #include "igtlPointMessage.h" #include "igtlTrajectoryMessage.h" #include "igtlStringMessage.h" #include "igtlSensorMessage.h" #include "igtlBindMessage.h" #include "igtlPolyDataMessage.h" #include "igtlQuaternionTrackingDataMessage.h" #include "igtlCapabilityMessage.h" #include "igtlNDArrayMessage.h" #include "igtlTrackingDataMessage.h" #include "igtlColorTableMessage.h" #include "igtlLabelMetaMessage.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->AddMessageNewMethod("NONE", NULL); //OpenIGTLink Types V1 this->AddMessageNewMethod("IMAGE", (PointerToMessageBaseNew)&igtl::ImageMessage::New); this->AddMessageNewMethod("TRANSFORM", (PointerToMessageBaseNew)&igtl::TransformMessage::New); this->AddMessageNewMethod("POSITION", (PointerToMessageBaseNew)&igtl::PositionMessage::New); this->AddMessageNewMethod("STATUS", (PointerToMessageBaseNew)&igtl::StatusMessage::New); this->AddMessageNewMethod("CAPABILITY", (PointerToMessageBaseNew)&igtl::StatusMessage::New); this->AddMessageNewMethod("GET_IMAGE", (PointerToMessageBaseNew)&igtl::GetImageMessage::New); this->AddMessageNewMethod("GET_TRANS", (PointerToMessageBaseNew)&igtl::GetTransformMessage::New); // this->AddMessageNewMethod("GET_POS", (PointerToMessageBaseNew)&igtl::GetPositionMessage::New); //not available??? this->AddMessageNewMethod("GET_STATUS", (PointerToMessageBaseNew)&igtl::GetStatusMessage::New); this->AddMessageNewMethod("GET_CAPABIL", (PointerToMessageBaseNew)&igtl::GetCapabilityMessage::New); // //OpenIGTLink Types V2 this->AddMessageNewMethod("IMGMETA", (PointerToMessageBaseNew)&igtl::ImageMetaMessage::New); this->AddMessageNewMethod("LBMETA", (PointerToMessageBaseNew)&igtl::LabelMetaMessage::New); this->AddMessageNewMethod("COLORT", (PointerToMessageBaseNew)&igtl::ColorTableMessage::New); this->AddMessageNewMethod("POINT", (PointerToMessageBaseNew)&igtl::PointMessage::New); this->AddMessageNewMethod("TRAJ", (PointerToMessageBaseNew)&igtl::TrajectoryMessage::New); this->AddMessageNewMethod("TDATA", (PointerToMessageBaseNew)&igtl::TrackingDataMessage::New); this->AddMessageNewMethod("QTDATA", (PointerToMessageBaseNew)&igtl::QuaternionTrackingDataMessage::New); this->AddMessageNewMethod("SENSOR", (PointerToMessageBaseNew)&igtl::SensorMessage::New); this->AddMessageNewMethod("STRING", (PointerToMessageBaseNew)&igtl::StringMessage::New); this->AddMessageNewMethod("NDARRAY", (PointerToMessageBaseNew)&igtl::NDArrayMessage::New); this->AddMessageNewMethod("BIND", (PointerToMessageBaseNew)&igtl::BindMessage::New); this->AddMessageNewMethod("POLYDATA", (PointerToMessageBaseNew)&igtl::PolyDataMessage::New); this->AddMessageNewMethod("GET_IMGMETA", (PointerToMessageBaseNew)&igtl::GetImageMetaMessage::New); this->AddMessageNewMethod("GET_LBMETA", (PointerToMessageBaseNew)&igtl::GetLabelMetaMessage::New); this->AddMessageNewMethod("GET_COLORT", (PointerToMessageBaseNew)&igtl::GetColorTableMessage::New); this->AddMessageNewMethod("GET_POINT", (PointerToMessageBaseNew)&igtl::GetPointMessage::New); this->AddMessageNewMethod("GET_TRAJ", (PointerToMessageBaseNew)&igtl::GetTrajectoryMessage::New); // this->AddMessageNewMethod("GET_TDATA", (PointerToMessageBaseNew)&igtl::GetTrackingDataMessage::New); //not available??? // this->AddMessageNewMethod("GET_QTDATA", (PointerToMessageBaseNew)&igtl::GetQuaternionTrackingDataMessage::New); // this->AddMessageNewMethod("GET_SENSOR", (PointerToMessageBaseNew)&igtl::GetSensorMessage::New); // this->AddMessageNewMethod("GET_STRING", (PointerToMessageBaseNew)&igtl::GetStringMessage::New); // this->AddMessageNewMethod("GET_NDARRAY", (PointerToMessageBaseNew)&igtl::GetNDArrayMessage::New); this->AddMessageNewMethod("GET_BIND", (PointerToMessageBaseNew)&igtl::GetBindMessage::New); this->AddMessageNewMethod("GET_POLYDATA", (PointerToMessageBaseNew)&igtl::GetPolyDataMessage::New); this->AddMessageNewMethod("RTS_BIND", (PointerToMessageBaseNew)&igtl::RTSBindMessage::New); this->AddMessageNewMethod("RTS_QTDATA", (PointerToMessageBaseNew)&igtl::RTSQuaternionTrackingDataMessage::New); this->AddMessageNewMethod("RTS_TDATA", (PointerToMessageBaseNew)&igtl::RTSTrackingDataMessage::New); //todo: check if there are more RTS messages this->AddMessageNewMethod("STT_BIND", (PointerToMessageBaseNew)&igtl::StartBindMessage::New); this->AddMessageNewMethod("STT_TDATA", (PointerToMessageBaseNew)&igtl::StartTrackingDataMessage::New); this->AddMessageNewMethod("STT_QTDATA", (PointerToMessageBaseNew)&igtl::StartQuaternionTrackingDataMessage::New); //todo: check if there are more STT messages this->AddMessageNewMethod("STP_BIND", (PointerToMessageBaseNew)&igtl::StopBindMessage::New); this->AddMessageNewMethod("STP_TDATA", (PointerToMessageBaseNew)&igtl::StopTrackingDataMessage::New); this->AddMessageNewMethod("STP_QTDATA", (PointerToMessageBaseNew)&igtl::StopQuaternionTrackingDataMessage::New); //todo: check if there are more STP messages //Own Types this->AddMessageNewMethod("DUMMY", (PointerToMessageBaseNew)&mitk::IGTLDummyMessage::New); } 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; } std::list mitk::IGTLMessageFactory::GetAvailableMessageRequestTypes() { std::list allGetMessages; for ( std::map::const_iterator it = this->m_NewMethods.begin(); it != this->m_NewMethods.end(); ++it) { if ( it->first.find("GET_") != std::string::npos || - it->first.find("STT_") != std::string::npos) + it->first.find("STT_") != std::string::npos || + it->first.find("STP_") != std::string::npos) { allGetMessages.push_back(it->first); } } return allGetMessages; } 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/mitkIGTLMessageProvider.cpp b/Modules/OpenIGTLink/mitkIGTLMessageProvider.cpp index a8174aab2a..05a6f6514d 100644 --- a/Modules/OpenIGTLink/mitkIGTLMessageProvider.cpp +++ b/Modules/OpenIGTLink/mitkIGTLMessageProvider.cpp @@ -1,91 +1,157 @@ /*=================================================================== 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 "mitkIGTLMessageProvider.h" #include "mitkIGTLDevice.h" #include "mitkIGTLMessage.h" +#include "mitkIGTLMessageFactory.h" //#include "mitkIGTTimeStamp.h" //#include "mitkIGTException.h" +//Microservices +#include "usServiceReference.h" +#include "usModuleContext.h" +#include "usServiceEvent.h" +#include "mitkServiceInterface.h" +#include "usGetModuleContext.h" + mitk::IGTLMessageProvider::IGTLMessageProvider() : mitk::IGTLDeviceSource() { this->SetName("IGTLMessageProvider"); } mitk::IGTLMessageProvider::~IGTLMessageProvider() { } void mitk::IGTLMessageProvider::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(); + igtl::MessageBase::Pointer msgIn = m_IGTLDevice->GetNextMessage(); if ( msgIn.IsNotNull() ) { assert(msgIn); msgOut->SetMessage(msgIn); msgOut->SetName(msgIn->GetDeviceName()); } } void mitk::IGTLMessageProvider::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::IGTLMessageProvider::UpdateOutputInformation() //{ // this->Modified(); // make sure that we need to be updated // Superclass::UpdateOutputInformation(); //} void mitk::IGTLMessageProvider::OnIncomingMessage() { - //check type of incoming message, it must be a request type (GET_ or STT_) - //otherwise ignore it + +} + +std::string RemoveRequestPrefixes(std::string requestType) +{ + return requestType.substr(4); +} + +void mitk::IGTLMessageProvider::OnIncomingCommand() +{ + //get the next command + igtl::MessageBase::Pointer curCommand = this->m_IGTLDevice->GetNextCommand(); + //extract the type + const char * requestType = curCommand->GetDeviceType(); + //get the type from the request type (remove STT_, STP_ or GET_) + std::string type = RemoveRequestPrefixes(requestType); //check all microservices if there is a fitting source for the requested type - //if it is a single value return the value - //if it is a stream start streaming + mitk::IGTLMessageSource::Pointer source = this->GetFittingSource(type.c_str()); + //if there is no fitting source return an RTS message + if ( source.IsNull() ) + { + std::string returnType("RTS_"); + returnType.append(type); + mitk::IGTLMessageFactory::Pointer msgFactory = + this->GetIGTLDevice()->GetMessageFactory(); + mitk::IGTLMessageFactory::PointerToMessageBaseNew retMsgNew = + msgFactory->GetMessageTypeNewPointer(returnType); + //if retMsgNew is NULL there is no return message defined and thus it is not + //necessary to send one back + if ( retMsgNew != NULL ) + { + igtl::MessageBase::Pointer rtsMsg = retMsgNew(); + this->GetIGTLDevice()->SendMessage(rtsMsg); + } + } + else + { + //if it is a single value return the value + source->GetOutput(); + //if it is a stream start streaming + } +} + +mitk::IGTLMessageSource::Pointer mitk::IGTLMessageProvider::GetFittingSource(const char* requestedType) +{ + us::ModuleContext* context = us::GetModuleContext(); + std::string interface = mitk::IGTLMessageSource::US_INTERFACE_NAME; + std::string filter = "(" + us::ServiceConstants::OBJECTCLASS() + "=" + interface + ")"; + std::vector serviceReferences = + context->GetServiceReferences(interface, ""); + std::vector::iterator it = serviceReferences.begin(); + std::vector::iterator end = serviceReferences.end(); + for ( ; it != end; it++ ) + { + mitk::IGTLMessageSource::Pointer curSource = + context->GetService(*it); + std::string type = curSource->GetType(); + if ( std::strcmp(type.c_str(), requestedType) == 0 ) + { + return curSource; + } + } + return NULL; } diff --git a/Modules/OpenIGTLink/mitkIGTLMessageProvider.h b/Modules/OpenIGTLink/mitkIGTLMessageProvider.h index 0cb4ee11c8..7c63e2f7f4 100644 --- a/Modules/OpenIGTLink/mitkIGTLMessageProvider.h +++ b/Modules/OpenIGTLink/mitkIGTLMessageProvider.h @@ -1,72 +1,84 @@ /*=================================================================== 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 IGTLMESSAGEPROVIDER_H_HEADER_INCLUDED_ #define IGTLMESSAGEPROVIDER_H_HEADER_INCLUDED_ #include "mitkIGTLDevice.h" #include "mitkIGTLDeviceSource.h" namespace mitk { /**Documentation * \brief Provides information/objects from a MITK-Pipeline to other OpenIGTLink * devices * * This class is intended as the drain of the pipeline. Other OpenIGTLink * devices connect with the device hold by this provider. The other device asks * for a special data. The provider checks if there are other IGTLMessageSources * available that provide this data type. If yes, they connect with this source * and send the message to the requesting device. * * */ class MITK_OPENIGTLINK_EXPORT IGTLMessageProvider : public IGTLDeviceSource { public: mitkClassMacro(IGTLMessageProvider, IGTLDeviceSource); itkFactorylessNewMacro(Self) itkCloneMacro(Self) protected: IGTLMessageProvider(); virtual ~IGTLMessageProvider(); /** * \brief filter execute method * * queries the OpenIGTLink device for new messages and updates its output * igtl::MessageBase objects with it. * \warning Will raise a std::out_of_range exception, if tools were added to * the OpenIGTLink device after it was set as input for this filter */ virtual void GenerateData(); /** * \brief Create the necessary outputs for the m_IGTLDevice * * This Method is called internally whenever outputs need to be reset. Old * Outputs are deleted when called. **/ void CreateOutputs(); /** * \brief This method is called when the IGTL device hold by this class * receives a new message **/ virtual void OnIncomingMessage(); + + /** + * \brief This method is called when the IGTL device hold by this class + * receives a new command + **/ + virtual void OnIncomingCommand(); + + /** + * \brief Looks for microservices that provide messages with the requested + * type. + **/ + mitk::IGTLMessageSource::Pointer GetFittingSource(const char* requestedType); }; } // namespace mitk #endif /* MITKIGTLMESSAGEPROVIDER_H_HEADER_INCLUDED_ */ diff --git a/Modules/OpenIGTLink/mitkIGTLMessageQueue.cpp b/Modules/OpenIGTLink/mitkIGTLMessageQueue.cpp index 465b160c8b..6740ac8221 100644 --- a/Modules/OpenIGTLink/mitkIGTLMessageQueue.cpp +++ b/Modules/OpenIGTLink/mitkIGTLMessageQueue.cpp @@ -1,74 +1,123 @@ /*=================================================================== 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; } -std::string mitk::IGTLMessageQueue::GetOldestMsgInformation() +std::string mitk::IGTLMessageQueue::GetNextMsgInformationString() { this->m_Mutex->Lock(); std::stringstream s; if ( this->m_Queue.size() > 0 ) { s << "Device Type: " << this->m_Queue.front()->GetDeviceType() << std::endl; s << "Device Name: " << this->m_Queue.front()->GetDeviceName() << std::endl; } else { s << "No Msg"; } this->m_Mutex->Unlock(); return s.str(); } +std::string mitk::IGTLMessageQueue::GetNextMsgDeviceType() +{ + this->m_Mutex->Lock(); + std::stringstream s; + if ( this->m_Queue.size() > 0 ) + { + s << this->m_Queue.front()->GetDeviceType(); + } + else + { + s << ""; + } + this->m_Mutex->Unlock(); + return s.str(); +} + +std::string mitk::IGTLMessageQueue::GetLatestMsgInformationString() +{ + this->m_Mutex->Lock(); + std::stringstream s; + if ( this->m_Queue.size() > 0 ) + { + s << "Device Type: " << this->m_Queue.back()->GetDeviceType() << std::endl; + s << "Device Name: " << this->m_Queue.back()->GetDeviceName() << std::endl; + } + else + { + s << "No Msg"; + } + this->m_Mutex->Unlock(); + return s.str(); +} + +std::string mitk::IGTLMessageQueue::GetLatestMsgDeviceType() +{ + this->m_Mutex->Lock(); + std::stringstream s; + if ( this->m_Queue.size() > 0 ) + { + s << this->m_Queue.back()->GetDeviceType(); + } + else + { + s << ""; + } + this->m_Mutex->Unlock(); + return s.str(); +} + int mitk::IGTLMessageQueue::GetSize() { return this->m_Queue.size(); } mitk::IGTLMessageQueue::IGTLMessageQueue() { this->m_Mutex = itk::FastMutexLock::New(); } mitk::IGTLMessageQueue::~IGTLMessageQueue() { this->m_Mutex->Unlock(); } diff --git a/Modules/OpenIGTLink/mitkIGTLMessageQueue.h b/Modules/OpenIGTLink/mitkIGTLMessageQueue.h index 65d47f9d9a..b29f735f0c 100644 --- a/Modules/OpenIGTLink/mitkIGTLMessageQueue.h +++ b/Modules/OpenIGTLink/mitkIGTLMessageQueue.h @@ -1,69 +1,72 @@ /*=================================================================== 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(); - std::string GetOldestMsgInformation(); + std::string GetNextMsgInformationString(); + std::string GetNextMsgDeviceType(); + std::string GetLatestMsgInformationString(); + std::string GetLatestMsgDeviceType(); 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 diff --git a/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp b/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp index cd2da548b7..f501c1dab8 100644 --- a/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp +++ b/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp @@ -1,174 +1,178 @@ /*=================================================================== 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 "mitkIGTLMessageSource.h" #include "mitkUIDGenerator.h" //Microservices #include #include #include #include const std::string mitk::IGTLMessageSource::US_INTERFACE_NAME = "org.mitk.services.IGTLMessageSource"; const std::string mitk::IGTLMessageSource::US_PROPKEY_DEVICENAME = US_INTERFACE_NAME + ".devicename"; +const std::string mitk::IGTLMessageSource::US_PROPKEY_DEVICETYPE = + US_INTERFACE_NAME + ".devicetype"; const std::string mitk::IGTLMessageSource::US_PROPKEY_ID = US_INTERFACE_NAME + ".id"; const std::string mitk::IGTLMessageSource::US_PROPKEY_ISACTIVE = US_INTERFACE_NAME + ".isActive"; mitk::IGTLMessageSource::IGTLMessageSource() - : itk::ProcessObject(), m_Name("IGTLMessageSource (no defined type)") + : itk::ProcessObject(), m_Name("IGTLMessageSource (no defined type)"), + m_Type("NONE") { } mitk::IGTLMessageSource::~IGTLMessageSource() { this->UnRegisterMicroservice(); } mitk::IGTLMessage* mitk::IGTLMessageSource::GetOutput() { if (this->GetNumberOfIndexedOutputs() < 1) return NULL; return static_cast(this->ProcessObject::GetPrimaryOutput()); } mitk::IGTLMessage* mitk::IGTLMessageSource::GetOutput( DataObjectPointerArraySizeType idx) { IGTLMessage* out = dynamic_cast( this->ProcessObject::GetOutput(idx) ); if ( out == NULL && this->ProcessObject::GetOutput(idx) != NULL ) { itkWarningMacro (<< "Unable to convert output number " << idx << " to type " << typeid( IGTLMessage ).name () ); } return out; } mitk::IGTLMessage* mitk::IGTLMessageSource::GetOutput( const std::string& messageName) { DataObjectPointerArray outputs = this->GetOutputs(); for (DataObjectPointerArray::iterator it = outputs.begin(); it != outputs.end(); ++it) { if (messageName == (static_cast(it->GetPointer()))->GetName()) { return static_cast(it->GetPointer()); } } return NULL; } itk::ProcessObject::DataObjectPointerArraySizeType mitk::IGTLMessageSource::GetOutputIndex( std::string messageName ) { DataObjectPointerArray outputs = this->GetOutputs(); for (DataObjectPointerArray::size_type i = 0; i < outputs.size(); ++i) { if (messageName == (static_cast(outputs.at(i).GetPointer()))->GetName()) { return i; } } throw std::invalid_argument("output name does not exist"); } void mitk::IGTLMessageSource::RegisterAsMicroservice() { // Get Context us::ModuleContext* context = us::GetModuleContext(); // Define ServiceProps us::ServiceProperties props; mitk::UIDGenerator uidGen = mitk::UIDGenerator ("org.mitk.services.IGTLMessageSource.id_", 16); props[ US_PROPKEY_ID ] = uidGen.GetUID(); props[ US_PROPKEY_DEVICENAME ] = m_Name; + props[ US_PROPKEY_DEVICETYPE ] = m_Type; m_ServiceRegistration = context->RegisterService(this, props); } void mitk::IGTLMessageSource::UnRegisterMicroservice() { if (m_ServiceRegistration != NULL) m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } std::string mitk::IGTLMessageSource::GetMicroserviceID() { us::Any referenceProperty = this->m_ServiceRegistration.GetReference().GetProperty(US_PROPKEY_ID); return referenceProperty.ToString(); } void mitk::IGTLMessageSource::GraftOutput(itk::DataObject *graft) { this->GraftNthOutput(0, graft); } void mitk::IGTLMessageSource::GraftNthOutput(unsigned int idx, itk::DataObject *graft) { if ( idx >= this->GetNumberOfIndexedOutputs() ) { itkExceptionMacro(<<"Requested to graft output " << idx << " but this filter" "only has " << this->GetNumberOfIndexedOutputs() << " Outputs."); } if ( !graft ) { itkExceptionMacro(<<"Requested to graft output with a NULL pointer object" ); } itk::DataObject* output = this->GetOutput(idx); if ( !output ) { itkExceptionMacro(<<"Requested to graft output that is a NULL pointer" ); } // Call Graft on IGTLMessage to copy member data output->Graft( graft ); } itk::DataObject::Pointer mitk::IGTLMessageSource::MakeOutput ( DataObjectPointerArraySizeType /*idx*/ ) { return IGTLMessage::New().GetPointer(); } itk::DataObject::Pointer mitk::IGTLMessageSource::MakeOutput( const DataObjectIdentifierType & name ) { itkDebugMacro("MakeOutput(" << name << ")"); if( this->IsIndexedOutputName(name) ) { return this->MakeOutput( this->MakeIndexFromOutputName(name) ); } return static_cast(IGTLMessage::New().GetPointer()); } mitk::PropertyList::ConstPointer mitk::IGTLMessageSource::GetParameters() const { mitk::PropertyList::Pointer p = mitk::PropertyList::New(); // add properties to p like this: //p->SetProperty("MyFilter_MyParameter", mitk::PropertyDataType::New(m_MyParameter)); return mitk::PropertyList::ConstPointer(p); } diff --git a/Modules/OpenIGTLink/mitkIGTLMessageSource.h b/Modules/OpenIGTLink/mitkIGTLMessageSource.h index 7798328bc1..3c14dce003 100644 --- a/Modules/OpenIGTLink/mitkIGTLMessageSource.h +++ b/Modules/OpenIGTLink/mitkIGTLMessageSource.h @@ -1,177 +1,193 @@ /*=================================================================== 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 MITKIGTLMESSAGESOURCE_H_HEADER_INCLUDED_ #define MITKIGTLMESSAGESOURCE_H_HEADER_INCLUDED_ #include #include "mitkPropertyList.h" #include "MitkOpenIGTLinkExports.h" #include "mitkIGTLMessage.h" // Microservices #include #include namespace mitk { /**Documentation * \brief OpenIGTLink message source * * Base class for all OpenIGTLink filters that produce OpenIGTLink message * objects as output. This class defines the output-interface for * OpenIGTLinkMessageFilters. * \warning: if Update() is called on any output object, all IGTLMessage filters * will generate new output data for all outputs, not just the one on which * Update() was called. * */ class MITK_OPENIGTLINK_EXPORT IGTLMessageSource : public itk::ProcessObject { public: mitkClassMacro(IGTLMessageSource, itk::ProcessObject); /** @return Returns a human readable name of this source. There will be a * default name, or you can set the name with the method SetName() if you * want to change it. */ itkGetMacro(Name,std::string); /** @brief Sets the human readable name of this source. There is also a * default name, but you can use this method if you need to define it on your * own. */ itkSetMacro(Name,std::string); + /** @return Returns a human readable type of this source. There will be a + * default type, or you can set the name with the method SetType(). You have + * to set this parameter otherwise it will not be found by the message + * provider. + */ + itkGetMacro(Type,std::string); + + /** @return Returns a human readable type of this source. There will be a + * default type, or you can set the name with the method SetType(). You have + * to set this parameter otherwise it will not be found by the message + * provider. + */ + itkSetMacro(Type,std::string); + /** *\brief return the output (output with id 0) of the filter */ IGTLMessage* GetOutput(void); /** *\brief return the output with id idx of the filter */ IGTLMessage* GetOutput(DataObjectPointerArraySizeType idx); /** *\brief return the output with name messageName of the filter */ IGTLMessage* GetOutput(const std::string& messageName); /** *\brief return the index of the output with name messageName, -1 if no output * with that name was found * * \warning if a subclass has outputs that have different data type than * igtl::MessageBase, they have to overwrite this method */ DataObjectPointerArraySizeType GetOutputIndex(std::string messageName); /** *\brief Registers this object as a Microservice, making it available to every * module and/or plugin. To unregister, call UnregisterMicroservice(). */ virtual void RegisterAsMicroservice(); /** *\brief Registers this object as a Microservice, making it available to every * module and/or plugin. */ virtual void UnRegisterMicroservice(); /** *\brief Returns the id that this device is registered with. The id will only * be valid, if the IGTLMessageSource has been registered using * RegisterAsMicroservice(). */ std::string GetMicroserviceID(); /** *\brief These Constants are used in conjunction with Microservices */ static const std::string US_INTERFACE_NAME; static const std::string US_PROPKEY_DEVICENAME; + static const std::string US_PROPKEY_DEVICETYPE; static const std::string US_PROPKEY_ID; static const std::string US_PROPKEY_ISACTIVE; //NOT IMPLEMENTED YET! /** *\brief Graft the specified DataObject onto this ProcessObject's output. * * See itk::ImageSource::GraftNthOutput for details */ virtual void GraftNthOutput(unsigned int idx, itk::DataObject *graft); /** * \brief Graft the specified DataObject onto this ProcessObject's output. * * See itk::ImageSource::Graft Output for details */ virtual void GraftOutput(itk::DataObject *graft); /** * Allocates a new output object and returns it. Currently the * index idx is not evaluated. * @param idx the index of the output for which an object should be created * @returns the new object */ virtual itk::DataObject::Pointer MakeOutput ( DataObjectPointerArraySizeType idx ); /** * This is a default implementation to make sure we have something. * Once all the subclasses of ProcessObject provide an appopriate * MakeOutput(), then ProcessObject::MakeOutput() can be made pure * virtual. */ virtual itk::DataObject::Pointer MakeOutput(const DataObjectIdentifierType &name); /** * \brief Set all filter parameters as the PropertyList p * * This method allows to set all parameters of a filter with one * method call. For the names of the parameters, take a look at * the GetParameters method of the filter * This method has to be overwritten by each MITK-IGT filter. */ virtual void SetParameters(const mitk::PropertyList*){}; /** * \brief Get all filter parameters as a PropertyList * * This method allows to get all parameters of a filter with one * method call. The returned PropertyList must be assigned to a * SmartPointer immediately, or else it will get destroyed. * Every filter must overwrite this method to create a filter-specific * PropertyList. Note that property names must be unique over all * MITK-IGT filters. Therefore each filter should use its name as a prefix * for each property name. * Secondly, each filter should list the property names and data types * in the method documentation. */ virtual mitk::PropertyList::ConstPointer GetParameters() const; protected: IGTLMessageSource(); virtual ~IGTLMessageSource(); std::string m_Name; + std::string m_Type; us::ServiceRegistration m_ServiceRegistration; }; } // namespace mitk // This is the microservice declaration. Do not meddle! MITK_DECLARE_SERVICE_INTERFACE(mitk::IGTLMessageSource, "org.mitk.services.IGTLMessageSource") #endif /* MITKIGTLMESSAGESOURCE_H_HEADER_INCLUDED_ */ diff --git a/Modules/OpenIGTLink/mitkIGTLServer.cpp b/Modules/OpenIGTLink/mitkIGTLServer.cpp new file mode 100644 index 0000000000..bc279e77e5 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLServer.cpp @@ -0,0 +1,144 @@ +/*=================================================================== + +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 "mitkIGTLServer.h" +#include + +#include +#include + +#include + + +mitk::IGTLServer::IGTLServer() : +IGTLDevice() +{ +} + +mitk::IGTLServer::~IGTLServer() +{ + +} + +bool mitk::IGTLServer::OpenConnection() +{ + if (this->GetState() != Setup) + { + mitkThrowException(mitk::Exception) << + "Can only try to create a server if in setup mode"; + return false; + } + + int portNumber = this->GetPortNumber(); + + if (portNumber == -1 ) + { + //port number was not correct + return false; + } + + //create a new server socket + m_Socket = igtl::ServerSocket::New(); + + //try to create the igtl server + int response = dynamic_cast(m_Socket.GetPointer())-> + CreateServer(portNumber); + + //check the response + if ( response != 0 ) + { + mitkThrowException(mitk::Exception) << + "The server could not be created. Port: " << portNumber; + return false; + } + + // everything is initialized and connected so the communication can be started + this->SetState(Ready); + + return true; +} + +void mitk::IGTLServer::Connect() +{ + igtl::Socket::Pointer socket; + //check if another igtl device wants to connect to this socket + socket = + ((igtl::ServerSocket*)(this->m_Socket.GetPointer()))->WaitForConnection(10); + //if there is a new connection the socket is not null + if ( socket.IsNotNull() ) + { + //add the new client socket to the list of registered clients + this->m_RegisteredClients.push_back(socket); + //inform observers about this new client + this->InvokeEvent(NewClientConnectionEvent()); + } +} + +void mitk::IGTLServer::Receive() +{ + //the server can be connected with several clients, therefore it has to check + //all registered clients + std::list::iterator it; + std::list::iterator it_end = + this->m_RegisteredClients.end(); + for ( it = this->m_RegisteredClients.begin(); it != it_end; ++it ) + { + //maybe there should be a check here if the current socket is still active + this->ReceivePrivate(*it); + } +} + +void mitk::IGTLServer::Send() +{ + igtl::MessageBase::Pointer curMessage; + + //get the latest message from the queue + curMessage = this->m_SendQueue->PullMessage(); + + // there is no message => return + if ( curMessage.IsNull() ) + return; + + //the server can be connected with several clients, therefore it has to check + //all registered clients + std::list::iterator it; + std::list::iterator it_end = + this->m_RegisteredClients.end(); + for ( it = this->m_RegisteredClients.begin(); it != it_end; ++it ) + { + //maybe there should be a check here if the current socket is still active + this->SendMessagePrivate(curMessage.GetPointer(), *it); + } +} + + + +void mitk::IGTLServer::StopCommunicationWithSocket(igtl::Socket* client) +{ + std::list::iterator it = + this->m_RegisteredClients.begin(); + std::list::iterator itEnd = + this->m_RegisteredClients.end(); + + for (; it != itEnd; ++it ) + { + if ( (*it).GetPointer() == client ) + { + this->m_RegisteredClients.remove(*it); + break; + } + } +} diff --git a/Modules/OpenIGTLink/mitkIGTLServer.h b/Modules/OpenIGTLink/mitkIGTLServer.h new file mode 100644 index 0000000000..0aea88046f --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLServer.h @@ -0,0 +1,98 @@ +/*=================================================================== + +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 MITKIGTLSERVER_H +#define MITKIGTLSERVER_H + +#include "mitkIGTLDevice.h" + +#include + + +namespace mitk +{ + + /** Documentation + * \brief superclass for open IGT link server + * + * implements the IGTLDevice interface for IGTL servers + * + * \ingroup IGT + */ + class MITK_OPENIGTLINK_EXPORT IGTLServer : public IGTLDevice + { + public: + mitkClassMacro(IGTLServer, IGTLDevice) + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /** + * \brief initialize the connection for the IGTL device + * + * \todo check this description + * + * OpenConnection() starts the IGTL server so that clients can connect to it + * @throw mitk::IGTHardwareException Throws an exception if there are errors + * while connecting to the device. + * @throw mitk::IGTException Throws a normal IGT exception if an error occures + * which is not related to the hardware. + */ + virtual bool OpenConnection(); + + + protected: + IGTLServer(); ///< Constructor + virtual ~IGTLServer(); ///< Destructor + + /** + * \brief Call this method to check for other devices that want to connect + * to this one. + * + * In case of a client this method is doing nothing. In case of a server it + * is checking for other devices and if there is one it establishes a + * connection. + */ + virtual void Connect(); + + /** + * \brief Call this method to receive a message. + * + * The message will be saved in the receive queue. + */ + virtual void Receive(); + + /** + * \brief Call this method to send a message. The message will be read from + * the queue + */ + virtual void Send(); + + /** + * \brief Stops the communication with the given socket. + * + * This method removes the given socket from the registered clients list + * + */ + virtual void StopCommunicationWithSocket(igtl::Socket* client); + + /** + * @brief A list with all registered clients + */ + std::list m_RegisteredClients; + }; +} // namespace mitk +#endif /* MITKIGTLSERVER_H */ diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.cpp index ab72e78063..2cb467af40 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.cpp +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.cpp @@ -1,549 +1,597 @@ /*=================================================================== 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 "QmitkIGTLDeviceSourceManagementWidget.h" //mitk headers #include #include #include #include //qt headers #include #include #include #include //igtl #include //poco headers #include const std::string QmitkIGTLDeviceSourceManagementWidget::VIEW_ID = "org.mitk.views.igtldevicesourcemanagementwidget"; QmitkIGTLDeviceSourceManagementWidget::QmitkIGTLDeviceSourceManagementWidget( QWidget* parent, Qt::WindowFlags f) - : QWidget(parent, f), m_OutputChanged(false) + : QWidget(parent, f), m_OutputChanged(false), m_IsClient(false) { m_Controls = NULL; m_OutputMutex = itk::FastMutexLock::New(); CreateQtPartControl(this); } QmitkIGTLDeviceSourceManagementWidget::~QmitkIGTLDeviceSourceManagementWidget() { } void QmitkIGTLDeviceSourceManagementWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTLDeviceSourceManagementWidgetControls; // setup GUI widgets m_Controls->setupUi(parent); } //every 100ms the logging window has to be updated m_UpdateLoggingWindowTimer.setInterval(100); // set the validator for the ip edit box (values must be between 0 and 255 and // there are four of them, seperated with a point QRegExpValidator *v = new QRegExpValidator(this); QRegExp rx("((1{0,1}[0-9]{0,2}|2[0-4]{1,1}[0-9]{1,1}|25[0-5]{1,1})\\.){3,3}(1{0,1}[0-9]{0,2}|2[0-4]{1,1}[0-9]{1,1}|25[0-5]{1,1})"); v->setRegExp(rx); m_Controls->editIP->setValidator(v); // set the validator for the port edit box (values must be between 1 and 65535) m_Controls->editPort->setValidator(new QIntValidator(1, 65535, this)); //connect slots with signals CreateConnections(); } void QmitkIGTLDeviceSourceManagementWidget::CreateConnections() { if (m_Controls) { // connect the widget items with the methods - connect( m_Controls->butConnectWithServer, SIGNAL(clicked()), + connect( m_Controls->butConnect, SIGNAL(clicked()), this, SLOT(OnConnect())); connect( m_Controls->editPort, SIGNAL(editingFinished()), this, SLOT(OnPortChanged()) ); connect( m_Controls->editIP, SIGNAL(editingFinished()), this, SLOT(OnHostnameChanged()) ); connect( m_Controls->butSend, SIGNAL(clicked()), this, SLOT(OnSendMessage())); connect( m_Controls->butSendCommand, SIGNAL(clicked()), this, SLOT(OnSendCommand())); connect( m_Controls->commandsComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(OnCommandChanged(const QString &))); connect( &m_UpdateLoggingWindowTimer, SIGNAL(timeout()), this, SLOT(OnUpdateLoggingWindow())); } // //main widget page: // connect( (QObject*)(m_Controls->m_AddTool), SIGNAL(clicked()), this, SLOT(OnAddTool()) ); // connect( (QObject*)(m_Controls->m_DeleteTool), SIGNAL(clicked()), this, SLOT(OnDeleteTool()) ); // connect( (QObject*)(m_Controls->m_EditTool), SIGNAL(clicked()), this, SLOT(OnEditTool()) ); // connect( (QObject*)(m_Controls->m_LoadStorage), SIGNAL(clicked()), this, SLOT(OnLoadStorage()) ); // connect( (QObject*)(m_Controls->m_SaveStorage), SIGNAL(clicked()), this, SLOT(OnSaveStorage()) ); // connect( (QObject*)(m_Controls->m_LoadTool), SIGNAL(clicked()), this, SLOT(OnLoadTool()) ); // connect( (QObject*)(m_Controls->m_SaveTool), SIGNAL(clicked()), this, SLOT(OnSaveTool()) ); // connect( (QObject*)(m_Controls->m_CreateNewStorage), SIGNAL(clicked()), this, SLOT(OnCreateStorage()) ); // //widget page "add tool": // connect( (QObject*)(m_Controls->m_ToolCreationWidget), SIGNAL(Canceled()), this, SLOT(OnAddToolCancel()) ); // connect( (QObject*)(m_Controls->m_ToolCreationWidget), SIGNAL(NavigationToolFinished()), this, SLOT(OnAddToolSave()) ); } //void QmitkIGTLDeviceSourceManagementWidget::OnLoadTool() //{ // if(m_IGTLDeviceSource->isLocked()) // { // MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); // return; // } // mitk::NavigationToolReader::Pointer myReader = mitk::NavigationToolReader::New(); // std::string filename = QFileDialog::getOpenFileName(NULL,tr("Add Navigation Tool"), "/", "*.IGTTool").toAscii().data(); // if (filename == "") return; // mitk::NavigationTool::Pointer readTool = myReader->DoRead(filename); // if (readTool.IsNull()) MessageBox("Error: " + myReader->GetErrorMessage()); // else // { // if (!m_IGTLDeviceSource->AddTool(readTool)) // { // MessageBox("Error: Can't add tool!"); // m_DataStorage->Remove(readTool->GetDataNode()); // } // UpdateToolTable(); // } //} //void QmitkIGTLDeviceSourceManagementWidget::OnSaveTool() //{ // //if no item is selected, show error message: // if (m_Controls->m_ToolList->currentItem() == NULL) {MessageBox("Error: Please select tool first!");return;} // mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); // std::string filename = QFileDialog::getSaveFileName(NULL,tr("Save Navigation Tool"), "/", "*.IGTTool").toAscii().data(); // if (filename == "") return; // if (!myWriter->DoWrite(filename,m_IGTLDeviceSource->GetTool(m_Controls->m_ToolList->currentIndex().row()))) // MessageBox("Error: "+ myWriter->GetErrorMessage()); //} void QmitkIGTLDeviceSourceManagementWidget::Initialize( mitk::DataStorage* /*dataStorage*/) { // m_DataStorage = dataStorage; // m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage,"Tool0"); } void QmitkIGTLDeviceSourceManagementWidget::LoadSource( mitk::IGTLDeviceSource::Pointer sourceToLoad) { + + DisableSourceControls(); + if(sourceToLoad.IsNotNull()) { this->m_IGTLDeviceSource = sourceToLoad; - this->m_IGTLClient = (mitk::IGTLClient*)this->m_IGTLDeviceSource->GetIGTLDevice(); + //check if the device is a server or a client + if ( dynamic_cast( + this->m_IGTLDeviceSource->GetIGTLDevice()) == NULL ) + { + m_IsClient = false; + m_Controls->butConnect->setText("Go Online"); + } + else + { + m_IsClient = true; + m_Controls->butConnect->setText("Connect"); + } + //get the device + this->m_IGTLDevice = this->m_IGTLDeviceSource->GetIGTLDevice(); m_Controls->selectedSourceLabel->setText(m_IGTLDeviceSource->GetName().c_str()); //add observer for new message receiving // typedef itk::MemberCommand< QmitkIGTLDeviceSourceManagementWidget > CurCommandType; // CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); // messageReceivedCommand->SetCallbackFunction( // this, &QmitkIGTLDeviceSourceManagementWidget::OnMessageReceived ); -// this->m_IGTLClient->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand); +// this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand); typedef itk::MemberCommand< QmitkIGTLDeviceSourceManagementWidget > CurCommandType; m_MessageReceivedCommand = CurCommandType::New(); m_MessageReceivedCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSourceManagementWidget::OnMessageReceived ); - this->m_IGTLClient->AddObserver(mitk::MessageReceivedEvent(), m_MessageReceivedCommand); + this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), m_MessageReceivedCommand); + + typedef itk::MemberCommand< QmitkIGTLDeviceSourceManagementWidget > CurCommandType; + CurCommandType::Pointer commandReceivedCommand = CurCommandType::New(); + commandReceivedCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceSourceManagementWidget::OnCommandReceived ); + this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), commandReceivedCommand); //Fill the commands combo box with all available commands FillCommandsComboBox(); //enable the controls of this widget EnableSourceControls(); //start to update the logging window this->m_UpdateLoggingWindowTimer.start(); } else { m_IGTLDeviceSource = NULL; - DisableSourceControls(); } //reset the loggin text edit ResetOutput(); } -////################################################################################## -////############################## slots: main widget ################################ -////################################################################################## - -//void QmitkIGTLDeviceSourceManagementWidget::OnAddTool() -// { -// if(m_IGTLDeviceSource->isLocked()) -// { -// MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); -// return; -// } -// QString defaultIdentifier = "NavigationTool#"+QString::number(m_IGTLDeviceSource->GetToolCount()); -// m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage,defaultIdentifier.toStdString()); -// m_edit = false; -// m_Controls->m_MainWidgets->setCurrentIndex(1); -// } - -//void QmitkIGTLDeviceSourceManagementWidget::OnDeleteTool() -// { -// //first: some checks -// if(m_IGTLDeviceSource->isLocked()) -// { -// MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); -// return; -// } -// else if (m_Controls->m_ToolList->currentItem() == NULL) //if no item is selected, show error message: -// { -// MessageBox("Error: Please select tool first!"); -// return; -// } - -// m_DataStorage->Remove(m_IGTLDeviceSource->GetTool(m_Controls->m_ToolList->currentIndex().row())->GetDataNode()); -// m_IGTLDeviceSource->DeleteTool(m_Controls->m_ToolList->currentIndex().row()); -// UpdateToolTable(); - -// } - -//void QmitkIGTLDeviceSourceManagementWidget::OnEditTool() -// { -// if(m_IGTLDeviceSource->isLocked()) -// { -// MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); -// return; -// } -// else if (m_Controls->m_ToolList->currentItem() == NULL) //if no item is selected, show error message: -// { -// MessageBox("Error: Please select tool first!"); -// return; -// } -// mitk::NavigationTool::Pointer selectedTool = m_IGTLDeviceSource->GetTool(m_Controls->m_ToolList->currentIndex().row()); -// m_Controls->m_ToolCreationWidget->SetDefaultData(selectedTool); -// m_edit = true; -// m_Controls->m_MainWidgets->setCurrentIndex(1); -// } - -//void QmitkIGTLDeviceSourceManagementWidget::OnCreateStorage() -// { -// QString storageName = QInputDialog::getText(NULL,"Storage Name","Name of the new tool storage:"); -// if (storageName.isNull()) return; -// m_IGTLDeviceSource = mitk::NavigationToolStorage::New(this->m_DataStorage); -// m_IGTLDeviceSource->SetName(storageName.toStdString()); -// m_Controls->m_StorageName->setText(m_IGTLDeviceSource->GetName().c_str()); -// EnableStorageControls(); -// emit NewStorageAdded(m_IGTLDeviceSource, storageName.toStdString()); -// } - -//void QmitkIGTLDeviceSourceManagementWidget::OnLoadStorage() -// { -// mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(m_DataStorage); -// std::string filename = QFileDialog::getOpenFileName(NULL, tr("Open Navigation Tool Storage"), "/", tr("IGT Tool Storage (*.IGTToolStorage)")).toStdString(); -// if (filename == "") return; - -// try -// { -// mitk::NavigationToolStorage::Pointer tempStorage = myDeserializer->Deserialize(filename); - -// if (tempStorage.IsNull()) MessageBox("Error" + myDeserializer->GetErrorMessage()); -// else -// { -// Poco::Path myPath = Poco::Path(filename.c_str()); -// tempStorage->SetName(myPath.getFileName()); //set the filename as name for the storage, so the user can identify it -// this->LoadStorage(tempStorage); -// emit NewStorageAdded(m_IGTLDeviceSource,myPath.getFileName()); -// } -// } -// catch (const mitk::Exception& exception) -// { -// MessageBox(exception.GetDescription()); -// } -// } - -//void QmitkIGTLDeviceSourceManagementWidget::OnSaveStorage() -// { -// //read in filename -// QString filename = QFileDialog::getSaveFileName(NULL, tr("Save Navigation Tool Storage"), "/", tr("IGT Tool Storage (*.IGTToolStorage)")); -// if (filename.isEmpty()) return; //canceled by the user - -// // add file extension if it wasn't added by the file dialog -// if ( filename.right(15) != ".IGTToolStorage" ) { filename += ".IGTToolStorage"; } - -// //serialize tool storage -// mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); -// if (!mySerializer->Serialize(filename.toStdString(),m_IGTLDeviceSource)) -// { -// MessageBox("Error: " + mySerializer->GetErrorMessage()); -// return; -// } -// Poco::Path myPath = Poco::Path(filename.toStdString()); -// m_Controls->m_StorageName->setText(QString::fromStdString(myPath.getFileName())); - -// } - - -////################################################################################## -////############################## slots: add tool widget ############################ -////################################################################################## - -//void QmitkIGTLDeviceSourceManagementWidget::OnAddToolSave() -// { -// mitk::NavigationTool::Pointer newTool = m_Controls->m_ToolCreationWidget->GetCreatedTool(); - -// if (m_edit) //here we edit a existing tool -// { -// mitk::NavigationTool::Pointer editedTool = m_IGTLDeviceSource->GetTool(m_Controls->m_ToolList->currentIndex().row()); -// editedTool->Graft(newTool); -// } -// else //here we create a new tool -// { -// m_IGTLDeviceSource->AddTool(newTool); -// } - -// UpdateToolTable(); - -// m_Controls->m_MainWidgets->setCurrentIndex(0); -// } - -//void QmitkIGTLDeviceSourceManagementWidget::OnAddToolCancel() -// { -// m_Controls->m_MainWidgets->setCurrentIndex(0); -// } - - - - void QmitkIGTLDeviceSourceManagementWidget::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkIGTLDeviceSourceManagementWidget::DisableSourceControls() { m_Controls->selectedSourceLabel->setText(""); m_Controls->editIP->setEnabled(false); m_Controls->editPort->setEnabled(false); m_Controls->editSend->setEnabled(false); m_Controls->butSendCommand->setEnabled(false); // m_Controls->m_AddTool->setEnabled(false); // m_Controls->m_LoadTool->setEnabled(false); // m_Controls->m_selectedLabel->setEnabled(false); // m_Controls->m_DeleteTool->setEnabled(false); // m_Controls->m_EditTool->setEnabled(false); // m_Controls->m_SaveTool->setEnabled(false); // m_Controls->m_ToolList->setEnabled(false); // m_Controls->m_SaveStorage->setEnabled(false); // m_Controls->m_ToolLabel->setEnabled(false); } void QmitkIGTLDeviceSourceManagementWidget::EnableSourceControls() { - m_Controls->editIP->setEnabled(true); - m_Controls->editPort->setEnabled(true); - m_Controls->butConnectWithServer->setEnabled(true); + if ( this->m_IsClient ) + { + m_Controls->editIP->setEnabled(true); + m_Controls->editPort->setEnabled(true); + m_Controls->butConnect->setEnabled(true); + } + else + { + m_Controls->editPort->setEnabled(true); + m_Controls->butConnect->setEnabled(true); + } // m_Controls->editSend->setEnabled(false); // m_Controls->m_AddTool->setEnabled(true); // m_Controls->m_LoadTool->setEnabled(true); // m_Controls->m_selectedLabel->setEnabled(true); // m_Controls->m_DeleteTool->setEnabled(true); // m_Controls->m_EditTool->setEnabled(true); // m_Controls->m_SaveTool->setEnabled(true); // m_Controls->m_ToolList->setEnabled(true); // m_Controls->m_SaveStorage->setEnabled(true); // m_Controls->m_ToolLabel->setEnabled(true); } void QmitkIGTLDeviceSourceManagementWidget::OnConnect() { - if(m_Controls->butConnectWithServer->text() == "Connect") + if(m_Controls->butConnect->text() == "Connect" || + m_Controls->butConnect->text() == "Go Online" ) { QString port = m_Controls->editPort->text(); - m_IGTLClient->SetPortNumber(port.toInt()); + m_IGTLDevice->SetPortNumber(port.toInt()); std::string hostname = m_Controls->editIP->text().toStdString(); - m_IGTLClient->SetHostname(hostname); - if ( m_IGTLClient->OpenConnection() ) + m_IGTLDevice->SetHostname(hostname); + if ( m_IGTLDevice->OpenConnection() ) { - if ( m_IGTLClient->StartCommunication() ) + if ( m_IGTLDevice->StartCommunication() ) { this->m_Controls->editIP->setEnabled(false); this->m_Controls->editPort->setEnabled(false); this->m_Controls->editSend->setEnabled(true); this->m_Controls->butSend->setEnabled(true); this->m_Controls->commandsComboBox->setEnabled(true); this->m_Controls->butSendCommand->setEnabled(true); - this->m_Controls->butConnectWithServer->setText("Disconnect"); - std::stringstream s; - s << "
Successfully connected to " << hostname - << " on port " << port.toStdString(); - this->AddOutput(s.str()); + this->m_Controls->butConnect->setText("Disconnect"); + if ( this->m_IsClient ) + { + std::stringstream s; + s << "
Successfully connected to " << hostname + << " on port " << port.toStdString(); + this->AddOutput(s.str()); + } } else { MITK_ERROR("QmitkIGTLDeviceSourceManagementWidget") << "Could not start a communication with the" "server because the client is in the wrong state"; this->AddOutput("
Connection is not working."); } } else { MITK_ERROR("QmitkIGTLDeviceSourceManagementWidget") << "Could not connect to the server. " "Please check the hostname and port."; this->AddOutput("
Connection is not working. Please Check Host and Port."); } } else { - m_Controls->editIP->setEnabled(true); + if ( this->m_IsClient ) + m_Controls->editIP->setEnabled(true); m_Controls->editPort->setEnabled(true); m_Controls->editSend->setEnabled(false); m_Controls->butSend->setEnabled(false); m_Controls->butSendCommand->setEnabled(false); m_Controls->commandsComboBox->setEnabled(false); - m_Controls->butConnectWithServer->setText("Connect"); - m_IGTLClient->CloseConnection(); + m_Controls->butConnect->setText("Connect"); + m_IGTLDevice->CloseConnection(); this->AddOutput("
Closed connection."); } } void QmitkIGTLDeviceSourceManagementWidget::OnPortChanged() { } void QmitkIGTLDeviceSourceManagementWidget::OnHostnameChanged() { } void QmitkIGTLDeviceSourceManagementWidget::OnSendCommand() { - m_IGTLClient->SendMessage(m_CurrentCommand.GetPointer()); + m_IGTLDevice->SendMessage(m_CurrentCommand.GetPointer()); std::stringstream s; s << "
Sent command with DeviceType: " << m_CurrentCommand->GetDeviceType(); this->AddOutput(s.str()); } void QmitkIGTLDeviceSourceManagementWidget::OnCommandChanged( const QString & curCommand) { mitk::IGTLMessageFactory::Pointer msgFactory = - this->m_IGTLClient->GetMessageFactory(); + this->m_IGTLDevice->GetMessageFactory(); //create a new message that fits to the selected get message type command this->m_CurrentCommand = msgFactory->GetMessageTypeNewPointer( curCommand.toStdString())(); } void QmitkIGTLDeviceSourceManagementWidget::OnSendMessage() { std::string toBeSend = m_Controls->editSend->text().toStdString(); igtl::StringMessage::Pointer msg = igtl::StringMessage::New().GetPointer(); msg->SetString(toBeSend); - m_IGTLClient->SendMessage(msg.GetPointer()); + m_IGTLDevice->SendMessage(msg.GetPointer()); std::stringstream s; s << "
Sent message with DeviceType: " << msg->GetDeviceType(); this->AddOutput(s.str()); } -void QmitkIGTLDeviceSourceManagementWidget::OnMessageReceived(itk::Object* caller, const itk::EventObject&/*event*/) +void QmitkIGTLDeviceSourceManagementWidget::OnMessageReceived( + itk::Object* caller, const itk::EventObject&/*event*/) { //get the IGTL device that invoked this event mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; std::stringstream s; s << "
Received a message:
" - << dev->GetOldestMessageInformation(); + << dev->GetReceiveQueue()->GetLatestMsgInformationString(); + + this->AddOutput(s.str()); +} + +void QmitkIGTLDeviceSourceManagementWidget::OnCommandReceived( + itk::Object* caller, const itk::EventObject&/*event*/) +{ + //get the IGTL device that invoked this event + mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; + + std::stringstream s; + s << "
Received a command:
" + << dev->GetCommandQueue()->GetLatestMsgInformationString(); this->AddOutput(s.str()); } void QmitkIGTLDeviceSourceManagementWidget::OnUpdateLoggingWindow() { m_OutputMutex->Lock(); // m_Controls->m_Logging->setHtml(QString(m_Output.str().c_str())); // m_Controls->m_Logging->update(); if ( m_OutputChanged ) { m_Controls->m_Logging->setText(QString(m_Output.str().c_str())); QScrollBar* sb = m_Controls->m_Logging->verticalScrollBar(); sb->setValue(sb->maximum()); m_OutputChanged = false; } m_OutputMutex->Unlock(); } void QmitkIGTLDeviceSourceManagementWidget::FillCommandsComboBox() { //load the msg factory from the client (maybe this will be moved later on) mitk::IGTLMessageFactory::Pointer msgFactory = - this->m_IGTLClient->GetMessageFactory(); + this->m_IGTLDevice->GetMessageFactory(); //get the available commands as std::list std::list commandsList_ = msgFactory->GetAvailableMessageRequestTypes(); //create a string list to convert the std::list QStringList commandsList; while ( commandsList_.size() ) { commandsList.append(QString::fromStdString(commandsList_.front())); commandsList_.pop_front(); } //fill the combo box with life this->m_Controls->commandsComboBox->addItems(commandsList); } void QmitkIGTLDeviceSourceManagementWidget::ResetOutput() { m_OutputMutex->Lock(); m_Output.str(""); m_Output <<"output:"; m_Controls->m_Logging->setHtml(QString(m_Output.str().c_str())); m_OutputMutex->Unlock(); } void QmitkIGTLDeviceSourceManagementWidget::AddOutput(std::string s) { //print output m_OutputMutex->Lock(); m_Output << s; m_OutputChanged = true; m_OutputMutex->Unlock(); } + + + + +////################################################################################## +////############################## slots: main widget ################################ +////################################################################################## + +//void QmitkIGTLDeviceSourceManagementWidget::OnAddTool() +// { +// if(m_IGTLDeviceSource->isLocked()) +// { +// MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); +// return; +// } +// QString defaultIdentifier = "NavigationTool#"+QString::number(m_IGTLDeviceSource->GetToolCount()); +// m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage,defaultIdentifier.toStdString()); +// m_edit = false; +// m_Controls->m_MainWidgets->setCurrentIndex(1); +// } + +//void QmitkIGTLDeviceSourceManagementWidget::OnDeleteTool() +// { +// //first: some checks +// if(m_IGTLDeviceSource->isLocked()) +// { +// MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); +// return; +// } +// else if (m_Controls->m_ToolList->currentItem() == NULL) //if no item is selected, show error message: +// { +// MessageBox("Error: Please select tool first!"); +// return; +// } + +// m_DataStorage->Remove(m_IGTLDeviceSource->GetTool(m_Controls->m_ToolList->currentIndex().row())->GetDataNode()); +// m_IGTLDeviceSource->DeleteTool(m_Controls->m_ToolList->currentIndex().row()); +// UpdateToolTable(); + +// } + +//void QmitkIGTLDeviceSourceManagementWidget::OnEditTool() +// { +// if(m_IGTLDeviceSource->isLocked()) +// { +// MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); +// return; +// } +// else if (m_Controls->m_ToolList->currentItem() == NULL) //if no item is selected, show error message: +// { +// MessageBox("Error: Please select tool first!"); +// return; +// } +// mitk::NavigationTool::Pointer selectedTool = m_IGTLDeviceSource->GetTool(m_Controls->m_ToolList->currentIndex().row()); +// m_Controls->m_ToolCreationWidget->SetDefaultData(selectedTool); +// m_edit = true; +// m_Controls->m_MainWidgets->setCurrentIndex(1); +// } + +//void QmitkIGTLDeviceSourceManagementWidget::OnCreateStorage() +// { +// QString storageName = QInputDialog::getText(NULL,"Storage Name","Name of the new tool storage:"); +// if (storageName.isNull()) return; +// m_IGTLDeviceSource = mitk::NavigationToolStorage::New(this->m_DataStorage); +// m_IGTLDeviceSource->SetName(storageName.toStdString()); +// m_Controls->m_StorageName->setText(m_IGTLDeviceSource->GetName().c_str()); +// EnableStorageControls(); +// emit NewStorageAdded(m_IGTLDeviceSource, storageName.toStdString()); +// } + +//void QmitkIGTLDeviceSourceManagementWidget::OnLoadStorage() +// { +// mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(m_DataStorage); +// std::string filename = QFileDialog::getOpenFileName(NULL, tr("Open Navigation Tool Storage"), "/", tr("IGT Tool Storage (*.IGTToolStorage)")).toStdString(); +// if (filename == "") return; + +// try +// { +// mitk::NavigationToolStorage::Pointer tempStorage = myDeserializer->Deserialize(filename); + +// if (tempStorage.IsNull()) MessageBox("Error" + myDeserializer->GetErrorMessage()); +// else +// { +// Poco::Path myPath = Poco::Path(filename.c_str()); +// tempStorage->SetName(myPath.getFileName()); //set the filename as name for the storage, so the user can identify it +// this->LoadStorage(tempStorage); +// emit NewStorageAdded(m_IGTLDeviceSource,myPath.getFileName()); +// } +// } +// catch (const mitk::Exception& exception) +// { +// MessageBox(exception.GetDescription()); +// } +// } + +//void QmitkIGTLDeviceSourceManagementWidget::OnSaveStorage() +// { +// //read in filename +// QString filename = QFileDialog::getSaveFileName(NULL, tr("Save Navigation Tool Storage"), "/", tr("IGT Tool Storage (*.IGTToolStorage)")); +// if (filename.isEmpty()) return; //canceled by the user + +// // add file extension if it wasn't added by the file dialog +// if ( filename.right(15) != ".IGTToolStorage" ) { filename += ".IGTToolStorage"; } + +// //serialize tool storage +// mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); +// if (!mySerializer->Serialize(filename.toStdString(),m_IGTLDeviceSource)) +// { +// MessageBox("Error: " + mySerializer->GetErrorMessage()); +// return; +// } +// Poco::Path myPath = Poco::Path(filename.toStdString()); +// m_Controls->m_StorageName->setText(QString::fromStdString(myPath.getFileName())); + +// } + + +////################################################################################## +////############################## slots: add tool widget ############################ +////################################################################################## + +//void QmitkIGTLDeviceSourceManagementWidget::OnAddToolSave() +// { +// mitk::NavigationTool::Pointer newTool = m_Controls->m_ToolCreationWidget->GetCreatedTool(); + +// if (m_edit) //here we edit a existing tool +// { +// mitk::NavigationTool::Pointer editedTool = m_IGTLDeviceSource->GetTool(m_Controls->m_ToolList->currentIndex().row()); +// editedTool->Graft(newTool); +// } +// else //here we create a new tool +// { +// m_IGTLDeviceSource->AddTool(newTool); +// } + +// UpdateToolTable(); + +// m_Controls->m_MainWidgets->setCurrentIndex(0); +// } + +//void QmitkIGTLDeviceSourceManagementWidget::OnAddToolCancel() +// { +// m_Controls->m_MainWidgets->setCurrentIndex(0); +// } diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.h index 6c1e3dd7a1..6b023ccc0d 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.h +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.h @@ -1,152 +1,158 @@ /*=================================================================== 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 QMITKIGTLDeviceSourceMANAGEMENTWIDGET_H #define QMITKIGTLDeviceSourceMANAGEMENTWIDGET_H //QT headers #include #include //mitk headers #include "MitkOpenIGTLinkUIExports.h" #include "mitkIGTLDeviceSource.h" #include "mitkIGTLClient.h" #include "mitkDataStorage.h" //itk #include //ui header #include "ui_QmitkIGTLDeviceSourceManagementWidgetControls.h" /** Documentation: * \brief An object of this class offers an UI to manage OpenIGTLink Device * Sources and OpenIGTLink Devices. * * Be sure to call the Initialize-methode before you start the widget * otherwise some errors might occure. * * \ingroup OpenIGTLinkUI */ class MITK_OPENIGTLINKUI_EXPORT QmitkIGTLDeviceSourceManagementWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; /** Initializes the widget. Has to be called before any action, * otherwise errors might occur. */ void Initialize(mitk::DataStorage*); /** Loads a source to the widget. The old source is dropped, so be careful, * if the source is not saved somewhere else it might be lost. You might * want to ask the user if he wants to save the changes before calling this * method. * @param sourceToLoad This source will be loaded and might be modified * by the user. */ void LoadSource(mitk::IGTLDeviceSource::Pointer sourceToLoad); QmitkIGTLDeviceSourceManagementWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkIGTLDeviceSourceManagementWidget(); /// \brief Is called when the current device received a message void OnMessageReceived(itk::Object* caller, const itk::EventObject&); + /// \brief Is called when the current device received a command + void OnCommandReceived(itk::Object* caller, const itk::EventObject&); + signals: /** This signal is emmited if a new source was added by the widget itself, * e.g. because a source was loaded. * @param newSource Holds the new source which was added. * @param sourceName Name of the new source */ void NewSourceAdded(mitk::IGTLDeviceSource::Pointer newSource, std::string sourceName); protected slots: void OnConnect(); void OnPortChanged(); void OnHostnameChanged(); void OnCommandChanged(const QString& curCommand); void OnSendMessage(); void OnSendCommand(); void ResetOutput(); void AddOutput(std::string s); void OnUpdateLoggingWindow(); // //main widget page: // void OnAddTool(); // void OnDeleteTool(); // void OnEditTool(); // void OnLoadTool(); // void OnSaveTool(); // void OnLoadSource(); // void OnSaveSource(); // void OnCreateSource(); // //widget page "add tool": // void OnAddToolCancel(); // void OnAddToolSave(); protected: /// \brief Fills the commands combo box with available commands void FillCommandsComboBox(); /// \brief Creation of the connections virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); Ui::QmitkIGTLDeviceSourceManagementWidgetControls* m_Controls; /** @brief holds the OpenIGTLink device */ - mitk::IGTLClient* m_IGTLClient; + mitk::IGTLDevice* m_IGTLDevice; /** @brief holds the IGTLDeviceSource we are working with. */ mitk::IGTLDeviceSource::Pointer m_IGTLDeviceSource; /** @brief shows if we are in edit mode, if not we create new source. */ bool m_edit; igtl::MessageBase::Pointer m_CurrentCommand; /** mutex to control access to m_State */ itk::FastMutexLock::Pointer m_OutputMutex; /** @brief a string stream used for logging */ std::stringstream m_Output; /** @brief flag to indicate if the output has to be updated */ bool m_OutputChanged; + /** @brief flag to indicate if the IGTL device is a client or a server */ + bool m_IsClient; + /** @brief a string stream used for logging */ QTimer m_UpdateLoggingWindowTimer; itk::MemberCommand< QmitkIGTLDeviceSourceManagementWidget >::Pointer m_MessageReceivedCommand; //############## private help methods ####################### void MessageBox(std::string s); // void UpdateToolTable(); void DisableSourceControls(); void EnableSourceControls(); }; #endif diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidgetControls.ui b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidgetControls.ui index 13ac12d886..b278401555 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidgetControls.ui +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidgetControls.ui @@ -1,217 +1,217 @@ QmitkIGTLDeviceSourceManagementWidgetControls 0 0 443 781 Form Selected IGTL Device Source: <none> Setup Connection Port Server-IP false 18944 5 true Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Port false 127.0.0.1 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + false Do image processing Connect false false false false false Send String Messages false false Send String Send Command Messages false Choose Command Message Type false Send Command Logging <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;" bgcolor="#000000"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> Qt::Vertical 20 40 diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.cpp b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.cpp index 3e63838d89..5d46bcba31 100644 --- a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.cpp +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.cpp @@ -1,134 +1,149 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkRenderWindow.h" // Qt #include // mitk #include #include #include // vtk #include // #include "OpenIGTLinkExample.h" //igtl #include "igtlStringMessage.h" const std::string OpenIGTLinkExample::VIEW_ID = "org.mitk.views.OpenIGTLinkExample"; void OpenIGTLinkExample::SetFocus() { } void OpenIGTLinkExample::CreateQtPartControl( QWidget *parent ) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); // connect the widget items with the methods connect( m_Controls.butStart, SIGNAL(clicked()), this, SLOT(Start()) ); connect( &m_Timer, SIGNAL(timeout()), this, SLOT(UpdatePipeline())); //Setup the pipeline this->CreatePipeline(); } void OpenIGTLinkExample::CreatePipeline() { //create a new OpenIGTLinkExample Client m_IGTLClient = mitk::IGTLClient::New(); - m_IGTLClient->SetName("OIGTL Example Device"); + m_IGTLClient->SetName("OIGTL Example Client Device"); //create a new OpenIGTLinkExample Device source m_IGTLDeviceSource = mitk::IGTLDeviceSource::New(); //set the client as the source for the device source m_IGTLDeviceSource->SetIGTLDevice(m_IGTLClient); m_IGTLDeviceSource->RegisterAsMicroservice(); //create a filter that converts OpenIGTLinkExample messages into navigation data m_IGTLMsgToNavDataFilter = mitk::IGTLMessageToNavigationDataFilter::New(); //create a visualization filter m_VisFilter = mitk::NavigationDataObjectVisualizationFilter::New(); //connect the filters with each other //the OpenIGTLinkExample messages will be passed to the first filter that converts //it to navigation data, then it is passed to the visualization filter that //will visualize the transformation m_IGTLMsgToNavDataFilter->ConnectTo(m_IGTLDeviceSource); m_VisFilter->ConnectTo(m_IGTLMsgToNavDataFilter); //create an object that will be moved respectively to the navigation data m_DemoNode = mitk::DataNode::New(); QString name = "IGTLDevice " + QString::fromStdString(m_IGTLClient->GetHostname()); m_DemoNode->SetName(name.toStdString()); //create small sphere and use it as surface mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkSphereSource *vtkData = vtkSphereSource::New(); vtkData->SetRadius(5.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); m_DemoNode->SetData(mySphere); // add node to DataStorage this->GetDataStorage()->Add(m_DemoNode); //use this sphere as representation object m_VisFilter->SetRepresentationObject(0, mySphere); + + + //REMOVE THIS CODE LATER + //create a new OpenIGTLinkExample Server + m_IGTLServer = mitk::IGTLServer::New(); + m_IGTLServer->SetName("OIGTL Example Server Device"); + + //create a new OpenIGTLinkExample Device source + m_IGTLDeviceSource2 = mitk::IGTLDeviceSource::New(); + + //set the client as the source for the device source + m_IGTLDeviceSource2->SetIGTLDevice(m_IGTLServer); + + m_IGTLDeviceSource2->RegisterAsMicroservice(); + } void OpenIGTLinkExample::DestroyPipeline() { m_VisFilter = NULL; this->GetDataStorage()->Remove(m_DemoNode); } void OpenIGTLinkExample::Start() { m_Timer.setInterval(1000); m_Timer.start(); } void OpenIGTLinkExample::UpdatePipeline() { m_VisFilter->Update(); //Update rendering QmitkRenderWindow* renWindow = this->GetRenderWindowPart()->GetQmitkRenderWindow("3d"); renWindow->GetRenderer()->GetVtkRenderer()->Render(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.h b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.h index d836c64b21..cbd69ed7f0 100644 --- a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.h +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.h @@ -1,76 +1,81 @@ /*=================================================================== 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 OpenIGTLinkExample_h #define OpenIGTLinkExample_h #include #include #include "ui_OpenIGTLinkExampleControls.h" #include "mitkIGTLClient.h" +#include "mitkIGTLServer.h" #include "mitkIGTLDeviceSource.h" #include "mitkNavigationDataObjectVisualizationFilter.h" #include "mitkIGTLMessageToNavigationDataFilter.h" #include "qtimer.h" /** \brief OpenIGTLinkExample \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \sa QmitkAbstractView \ingroup ${plugin_target}_internal */ class OpenIGTLinkExample : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; protected slots: void Start(); void UpdatePipeline(); protected: virtual void CreateQtPartControl(QWidget *parent); virtual void SetFocus(); void CreatePipeline(); void DestroyPipeline(); Ui::OpenIGTLinkExampleControls m_Controls; mitk::IGTLClient::Pointer m_IGTLClient; mitk::IGTLDeviceSource::Pointer m_IGTLDeviceSource; mitk::IGTLMessageToNavigationDataFilter::Pointer m_IGTLMsgToNavDataFilter; mitk::NavigationDataObjectVisualizationFilter::Pointer m_VisFilter; mitk::DataNode::Pointer m_DemoNode; + //REMOVE LATER + mitk::IGTLServer::Pointer m_IGTLServer; + mitk::IGTLDeviceSource::Pointer m_IGTLDeviceSource2; + QTimer m_Timer; }; #endif // OpenIGTLinkExample_h diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp index 773b4079b1..fd94b5ba29 100644 --- a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp @@ -1,171 +1,175 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkRenderWindow.h" // Qt #include #include // mitk #include #include #include #include // vtk #include // #include "OpenIGTLinkProviderExample.h" //igtl #include "igtlStringMessage.h" const std::string OpenIGTLinkProviderExample::VIEW_ID = "org.mitk.views.OpenIGTLinkProviderExample"; void OpenIGTLinkProviderExample::SetFocus() { } void OpenIGTLinkProviderExample::CreateQtPartControl( QWidget *parent ) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); // connect the widget items with the methods connect( m_Controls.butStart, SIGNAL(clicked()), this, SLOT(Start()) ); connect( m_Controls.butOpenNavData, SIGNAL(clicked()), this, SLOT(OnOpenFile()) ); } void OpenIGTLinkProviderExample::CreatePipeline() { //create a new OpenIGTLink Client - m_IGTLClient = mitk::IGTLClient::New(); - m_IGTLClient->SetName("OIGTL Provider Example Device"); + m_IGTLServer = mitk::IGTLServer::New(); + m_IGTLServer->SetName("OIGTL Provider Example Device"); //create a new OpenIGTLink Device source m_IGTLMessageProvider = mitk::IGTLMessageProvider::New(); //set the client as the source for the device source - m_IGTLMessageProvider->SetIGTLDevice(m_IGTLClient); + m_IGTLMessageProvider->SetIGTLDevice(m_IGTLServer); //register the provider so that it can be configured with the IGTL manager //plugin. This could be hardcoded but now I already have the fancy plugin. m_IGTLMessageProvider->RegisterAsMicroservice(); //create a filter that converts navigation data into IGTL messages m_NavDataToIGTLMsgFilter = mitk::NavigationDataToIGTLMessageFilter::New(); //register this filter as micro service. The message provider looks for //provided IGTLMessageSources, once it found this microservice and someone //requested this data type then the provider will connect with this filter //automatically m_NavDataToIGTLMsgFilter->RegisterAsMicroservice(); + //define the operation mode for this filter + m_NavDataToIGTLMsgFilter->SetOperationMode( + mitk::NavigationDataToIGTLMessageFilter::ModeSendQTransMsg); + //create a navigation data player object that will play nav data from a //recorded file m_NavDataPlayer = mitk::NavigationDataPlayer::New(); //connect the filters with each other //the navigation data player reads a file with recorded navigation data, //passes this data to a filter that converts it into a IGTLMessage. //The provider is not connected because it will search for fitting services. //Once it found the filter it will automatically connect to it. m_NavDataToIGTLMsgFilter->ConnectTo(m_NavDataPlayer); //create an object that will be moved respectively to the navigation data m_DemoNode = mitk::DataNode::New(); QString name = - "IGTLDevice " + QString::fromStdString(m_IGTLClient->GetHostname()); + "IGTLDevice " + QString::fromStdString(m_IGTLServer->GetHostname()); m_DemoNode->SetName(name.toStdString()); //create small sphere and use it as surface mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkSphereSource *vtkData = vtkSphereSource::New(); vtkData->SetRadius(5.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); m_DemoNode->SetData(mySphere); // add node to DataStorage this->GetDataStorage()->Add(m_DemoNode); //use this sphere as representation object m_NavDataPlayer->SetNavigationDataSet(m_NavDataSet); } void OpenIGTLinkProviderExample::DestroyPipeline() { m_NavDataPlayer->StopPlaying(); this->GetDataStorage()->Remove(m_DemoNode); } void OpenIGTLinkProviderExample::Start() { if ( this->m_Controls.butStart->text().contains("Start") ) { m_NavDataPlayer->StartPlaying(); this->m_Controls.butStart->setText("Stop Playing Recorded Navigation Data "); } else { m_NavDataPlayer->StopPlaying(); this->m_Controls.butStart->setText("Start Playing Recorded Navigation Data "); } } void OpenIGTLinkProviderExample::OnOpenFile(){ mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); // FIXME Filter for correct files and use correct Reader QString fileName = QFileDialog::getOpenFileName(NULL, "Open Navigation Data Set", "", "XML files (*.xml)"); if ( fileName.isNull() ) { return; } // user pressed cancel try { m_NavDataSet = reader->Read(fileName.toStdString()); } catch ( const mitk::Exception &e ) { MITK_WARN("NavigationDataPlayerView") << "could not open file " << fileName.toStdString(); QMessageBox::critical(0, "Error Reading File", "The file '" + fileName +"' could not be read.\n" + e.GetDescription() ); return; } this->m_Controls.butStart->setEnabled(true); //Setup the pipeline this->CreatePipeline(); // Update Labels // m_Controls->m_LblFilePath->setText(fileName); // m_Controls->m_LblTools->setText(QString::number(m_NavDataSet->GetNumberOfTools())); } diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.h b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.h index 59eab7f329..61a5fb1149 100644 --- a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.h +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.h @@ -1,75 +1,75 @@ /*=================================================================== 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 OpenIGTLinkProviderExample_h #define OpenIGTLinkProviderExample_h #include #include #include "ui_OpenIGTLinkProviderExampleControls.h" -#include "mitkIGTLClient.h" +#include "mitkIGTLServer.h" #include "mitkIGTLMessageProvider.h" #include "mitkNavigationDataToIGTLMessageFilter.h" #include "mitkNavigationDataPlayer.h" #include "qtimer.h" /** \brief OpenIGTLinkProviderExample \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \sa QmitkAbstractView \ingroup ${plugin_target}_internal */ class OpenIGTLinkProviderExample : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; protected slots: void Start(); void OnOpenFile(); protected: virtual void CreateQtPartControl(QWidget *parent); virtual void SetFocus(); void CreatePipeline(); void DestroyPipeline(); Ui::OpenIGTLinkProviderExampleControls m_Controls; - mitk::IGTLClient::Pointer m_IGTLClient; + mitk::IGTLServer::Pointer m_IGTLServer; mitk::IGTLMessageProvider::Pointer m_IGTLMessageProvider; mitk::NavigationDataToIGTLMessageFilter::Pointer m_NavDataToIGTLMsgFilter; mitk::NavigationDataPlayer::Pointer m_NavDataPlayer; mitk::DataNode::Pointer m_DemoNode; mitk::NavigationDataSet::Pointer m_NavDataSet; }; #endif // OpenIGTLinkProviderExample_h