Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkIGTLDeviceSource.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkIGTLDeviceSource.h"
18 
19 #include "mitkIGTLDevice.h"
20 #include "mitkIGTLMessage.h"
21 
22 //#include "mitkIGTTimeStamp.h"
23 //#include "mitkIGTException.h"
24 
25 //Microservices
26 #include <usGetModuleContext.h>
27 #include <usModule.h>
28 #include <usServiceProperties.h>
29 #include <usModuleContext.h>
30 
31 //itk
32 #include <itkCommand.h>
33 
36 
38  : mitk::IGTLMessageSource(), m_IGTLDevice(NULL)
39 {
40  this->SetName("IGTLDeviceSource (no defined type)");
41 }
42 
44 {
45  if (m_IGTLDevice.IsNotNull())
46  {
47  if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Running)
48  {
49  this->StopCommunication();
50  }
51  if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Ready)
52  {
53  this->Disconnect();
54  }
55  this->RemoveObservers();
56  m_IGTLDevice = NULL;
57  }
58 }
59 
61 {
62  if (m_IGTLDevice.IsNull())
63  return;
64 
65  /* update output with message from the device */
66  IGTLMessage* msgOut = this->GetOutput();
67  assert(msgOut);
68  igtl::MessageBase::Pointer msgIn = dynamic_cast<igtl::MessageBase*>(m_IGTLDevice->GetNextImage2dMessage().GetPointer());
69  if (msgIn.IsNotNull())
70  {
71  assert(msgIn);
72 
73  msgOut->SetMessage(msgIn);
74  msgOut->SetName(msgIn->GetDeviceName());
75  }
76  // else
77  // {
78  // MITK_ERROR("IGTLDeviceSource") << "Could not get the latest message.";
79  // }
80 }
81 
83 {
84  if (this->m_IGTLDevice.IsNotNull())
85  {
86  this->m_IGTLDevice->RemoveObserver(m_IncomingMessageObserverTag);
87  this->m_IGTLDevice->RemoveObserver(m_IncomingCommandObserverTag);
88  this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag);
89  }
90 }
91 
93 {
94  MITK_DEBUG << "Setting IGTLDevice to " << igtlDevice;
95  if (this->m_IGTLDevice.GetPointer() != igtlDevice)
96  {
97  //check if we want to override the device
98  if (this->m_IGTLDevice.IsNotNull())
99  {
100  //the device was set previously => we need to reset the observers
101  this->RemoveObservers();
102  }
103  //set the device
104  this->m_IGTLDevice = igtlDevice;
105  this->CreateOutputs();
106  std::stringstream name; // create a human readable name for the source
107  name << "OIGTL Device Source ( " << igtlDevice->GetName() << " )";
108  this->SetName(name.str());
109 
110  //setup a observer that listens to new messages and new commands
111  typedef itk::SimpleMemberCommand<IGTLDeviceSource> DeviceSrcCommand;
112 
113  DeviceSrcCommand::Pointer msgReceivedCommand = DeviceSrcCommand::New();
114  msgReceivedCommand->SetCallbackFunction(this, &IGTLDeviceSource::OnIncomingMessage);
115  this->m_IncomingMessageObserverTag =
116  this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), msgReceivedCommand);
117 
118  DeviceSrcCommand::Pointer cmdReceivedCommand = DeviceSrcCommand::New();
119  cmdReceivedCommand->SetCallbackFunction(this, &IGTLDeviceSource::OnIncomingCommand);
120  this->m_IncomingCommandObserverTag =
121  this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), cmdReceivedCommand);
122 
123  DeviceSrcCommand::Pointer connectionLostCommand = DeviceSrcCommand::New();
124  connectionLostCommand->SetCallbackFunction(this, &IGTLDeviceSource::OnLostConnection);
125  this->m_LostConnectionObserverTag =
126  this->m_IGTLDevice->AddObserver(mitk::LostConnectionEvent(), connectionLostCommand);
127  }
128 }
129 
131 {
132  //if outputs are set then delete them
133  if (this->GetNumberOfOutputs() > 0)
134  {
135  for (int numOP = this->GetNumberOfOutputs() - 1; numOP >= 0; numOP--)
136  this->RemoveOutput(numOP);
137  this->Modified();
138  }
139 
140  //fill the outputs if a valid OpenIGTLink device is set
141  if (m_IGTLDevice.IsNull())
142  return;
143 
144  this->SetNumberOfIndexedOutputs(1);
145  if (this->GetOutput(0) == NULL)
146  {
147  DataObjectPointer newOutput = this->MakeOutput(0);
148  this->SetNthOutput(0, newOutput);
149  this->Modified();
150  }
151 }
152 
154 {
155  if (m_IGTLDevice.IsNull())
156  {
157  throw std::invalid_argument("mitk::IGTLDeviceSource: "
158  "No OpenIGTLink device set");
159  }
160  if (this->IsConnected())
161  {
162  return;
163  }
164  try
165  {
166  m_IGTLDevice->OpenConnection();
167  }
168  catch (mitk::Exception &e)
169  {
170  throw std::runtime_error(std::string("mitk::IGTLDeviceSource: Could not open"
171  "connection to OpenIGTLink device. Error: ") + e.GetDescription());
172  }
173 }
174 
176 {
177  if (m_IGTLDevice.IsNull())
178  throw std::invalid_argument("mitk::IGTLDeviceSource: "
179  "No OpenIGTLink device set");
180  if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Running)
181  return;
182  if (m_IGTLDevice->StartCommunication() == false)
183  throw std::runtime_error("mitk::IGTLDeviceSource: "
184  "Could not start communication");
185 }
186 
188 {
189  if (m_IGTLDevice.IsNull())
190  throw std::invalid_argument("mitk::IGTLDeviceSource: "
191  "No OpenIGTLink device set");
192  if (m_IGTLDevice->CloseConnection() == false)
193  throw std::runtime_error("mitk::IGTLDeviceSource: Could not close connection"
194  " to OpenIGTLink device");
195 }
196 
198 {
199  if (m_IGTLDevice.IsNull())
200  throw std::invalid_argument("mitk::IGTLDeviceSource: "
201  "No OpenIGTLink device set");
202  if (m_IGTLDevice->StopCommunication() == false)
203  throw std::runtime_error("mitk::IGTLDeviceSource: "
204  "Could not stop communicating");
205 }
206 
208 {
209  this->Modified(); // make sure that we need to be updated
210  Superclass::UpdateOutputInformation();
211 }
212 
213 void mitk::IGTLDeviceSource::SetInput(unsigned int idx, const IGTLMessage* msg)
214 {
215  if (msg == NULL) // if an input is set to NULL, remove it
216  {
217  this->RemoveInput(idx);
218  }
219  else
220  {
221  // ProcessObject is not const-correct so a const_cast is required here
222  this->ProcessObject::SetNthInput(idx, const_cast<IGTLMessage*>(msg));
223  }
224  // this->CreateOutputsForAllInputs();
225 }
226 
228 {
229  if (m_IGTLDevice.IsNull())
230  return false;
231 
232  return (m_IGTLDevice->GetState() == mitk::IGTLDevice::Ready) ||
233  (m_IGTLDevice->GetState() == mitk::IGTLDevice::Running);
234 }
235 
237 {
238  if (m_IGTLDevice.IsNull())
239  return false;
240 
241  return m_IGTLDevice->GetState() == mitk::IGTLDevice::Running;
242 }
243 
245 {
246  // Get Context
247  us::ModuleContext* context = us::GetModuleContext();
248 
249  // Define ServiceProps
250  us::ServiceProperties props;
251  mitk::UIDGenerator uidGen =
252  mitk::UIDGenerator("org.mitk.services.IGTLDeviceSource.id_", 16);
253  props[US_PROPKEY_ID] = uidGen.GetUID();
254  props[US_PROPKEY_DEVICENAME] = this->GetName();
255  props[US_PROPKEY_IGTLDEVICENAME] = m_Name;
256  props[US_PROPKEY_DEVICETYPE] = m_Type;
257  m_ServiceRegistration = context->RegisterService(this, props);
258 
259  MITK_INFO << "Registered new DeviceSource as microservice: " << uidGen.GetUID();
260 }
261 
263 {
264 }
265 
267 {
268 }
269 
271 {
272 }
273 
275 {
276  if (this->GetNumberOfInputs() < 1)
277  return NULL;
278 
279  return static_cast<const IGTLMessage*>(this->ProcessObject::GetInput(0));
280 }
281 
282 const mitk::IGTLMessage*
283 mitk::IGTLDeviceSource::GetInput(unsigned int idx) const
284 {
285  if (this->GetNumberOfInputs() < 1)
286  return NULL;
287 
288  return static_cast<const IGTLMessage*>(this->ProcessObject::GetInput(idx));
289 }
290 
291 const mitk::IGTLMessage*
292 mitk::IGTLDeviceSource::GetInput(std::string msgName) const
293 {
294  const DataObjectPointerArray& inputs = const_cast<Self*>(this)->GetInputs();
295  for (DataObjectPointerArray::const_iterator it = inputs.begin();
296  it != inputs.end(); ++it)
297  if (std::string(msgName) ==
298  (static_cast<IGTLMessage*>(it->GetPointer()))->GetName())
299  return static_cast<IGTLMessage*>(it->GetPointer());
300  return NULL;
301 }
302 
303 itk::ProcessObject::DataObjectPointerArraySizeType
305 {
306  DataObjectPointerArray outputs = this->GetInputs();
307  for (DataObjectPointerArray::size_type i = 0; i < outputs.size(); ++i)
308  if (msgName ==
309  (static_cast<IGTLMessage*>(outputs.at(i).GetPointer()))->GetName())
310  return i;
311  throw std::invalid_argument("output name does not exist");
312 }
virtual bool IsCommunicating()
returns true if communication is in progress
itk::SmartPointer< Self > Pointer
virtual void OnIncomingCommand()
This method is called when the IGTL device hold by this class receives a new command.
Generated unique IDs.
static const std::string US_PROPKEY_IGTLDEVICENAME
These Constants are used in conjunction with Microservices.
#define MITK_INFO
Definition: mitkLogMacros.h:22
void SetMessage(igtl::MessageBase::Pointer msg)
Sets the OpenIGTLink message.
void StopCommunication()
stops the communication of the device.
virtual void OnLostConnection()
This method is called when the IGTL device lost the connection to the other side. ...
void Disconnect()
Closes the connection to the OpenIGTLink device.
#define MITK_DEBUG
Definition: mitkLogMacros.h:26
DataCollection - Class to facilitate loading/accessing structured data.
virtual void UpdateOutputInformation() override
Used for pipeline update.
virtual void GenerateData() override
filter execute method
virtual void SetIGTLDevice(mitk::IGTLDevice *td)
sets the OpenIGTLink device that will be used as a data source
virtual void SetName(const char *_arg)
set the name of the IGTLMessage object
void CreateOutputs()
Create the necessary outputs for the m_IGTLDevice.
A wrapper for the OpenIGTLink message type.
An object of this class represents an exception of MITK. Please don't instantiate exceptions manually...
Definition: mitkException.h:49
virtual void RegisterAsMicroservice() override
Registers this object as a Microservice, making it available to every module and/or plugin...
OpenIGTLink message source.
void StartCommunication()
starts the communication of the device. This needs to be called before Update() or GetOutput()->Updat...
virtual void OnIncomingMessage()
This method is called when the IGTL device hold by this class receives a new message.
virtual void RemoveObservers()
Removes all observers that listen to the igtl device.
US_UNORDERED_MAP_TYPE< std::string, Any > ServiceProperties
virtual void SetInput(unsigned int idx, const IGTLMessage *msg)
Set input with id idx of this filter.
Interface for all OpenIGTLink Devices.
void Connect()
Establishes a connection to the OpenIGTLink device. If there is already a connection the method does ...
virtual void SetName(std::string _arg)
Sets the human readable name of this source. There is also a default name, but you can use this metho...
virtual bool IsConnected()
returns true if a connection to the OpenIGTLink device is established
static std::string GetName(std::string fileName, std::string suffix)
static const std::string US_INTERFACE_NAME
These Constants are used in conjunction with Microservices.
const IGTLMessage * GetInput(void) const
Get the input of this filter.
DataObjectPointerArraySizeType GetInputIndex(std::string msgName)
return the index of the input with name msgName, throw std::invalid_argument exception if that name w...
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.