Medical Imaging Interaction Toolkit  2018.4.99-4c24e3cb
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 (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkIGTLDeviceSource.h"
14 
15 #include "mitkIGTLDevice.h"
16 #include "mitkIGTLMessage.h"
17 
18 //#include "mitkIGTTimeStamp.h"
19 //#include "mitkIGTException.h"
20 
21 //Microservices
22 #include <usGetModuleContext.h>
23 #include <usModule.h>
24 #include <usServiceProperties.h>
25 #include <usModuleContext.h>
26 
27 //itk
28 #include <itkCommand.h>
29 
32 
34  : mitk::IGTLMessageSource(), m_IGTLDevice(nullptr)
35 {
36  this->SetName("IGTLDeviceSource (no defined type)");
37 }
38 
40 {
41  if (m_IGTLDevice.IsNotNull())
42  {
43  if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Running)
44  {
45  this->StopCommunication();
46  }
47  if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Ready)
48  {
49  this->Disconnect();
50  }
51  this->RemoveObservers();
52  m_IGTLDevice = nullptr;
53  }
54 }
55 
57 {
58  if (m_IGTLDevice.IsNull())
59  return;
60 
61  /* update output with message from the device */
62  IGTLMessage* msgOut = this->GetOutput();
63  assert(msgOut);
64  igtl::MessageBase::Pointer msgIn = dynamic_cast<igtl::MessageBase*>(m_IGTLDevice->GetNextImage2dMessage().GetPointer());
65  if (msgIn.IsNotNull())
66  {
67  assert(msgIn);
68 
69  msgOut->SetMessage(msgIn);
70  msgOut->SetName(msgIn->GetDeviceName());
71  }
72  // else
73  // {
74  // MITK_ERROR("IGTLDeviceSource") << "Could not get the latest message.";
75  // }
76 }
77 
79 {
80  if (this->m_IGTLDevice.IsNotNull())
81  {
82  this->m_IGTLDevice->RemoveObserver(m_IncomingMessageObserverTag);
83  this->m_IGTLDevice->RemoveObserver(m_IncomingCommandObserverTag);
84  this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag);
85  }
86 }
87 
89 {
90  MITK_DEBUG << "Setting IGTLDevice to " << igtlDevice;
91  if (this->m_IGTLDevice.GetPointer() != igtlDevice)
92  {
93  //check if we want to override the device
94  if (this->m_IGTLDevice.IsNotNull())
95  {
96  //the device was set previously => we need to reset the observers
97  this->RemoveObservers();
98  }
99  //set the device
100  this->m_IGTLDevice = igtlDevice;
101  this->CreateOutputs();
102  std::stringstream name; // create a human readable name for the source
103  name << "OIGTL Device Source ( " << igtlDevice->GetName() << " )";
104  this->SetName(name.str());
105 
106  //setup a observer that listens to new messages and new commands
107  typedef itk::SimpleMemberCommand<IGTLDeviceSource> DeviceSrcCommand;
108 
109  DeviceSrcCommand::Pointer msgReceivedCommand = DeviceSrcCommand::New();
110  msgReceivedCommand->SetCallbackFunction(this, &IGTLDeviceSource::OnIncomingMessage);
112  this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), msgReceivedCommand);
113 
114  DeviceSrcCommand::Pointer cmdReceivedCommand = DeviceSrcCommand::New();
115  cmdReceivedCommand->SetCallbackFunction(this, &IGTLDeviceSource::OnIncomingCommand);
117  this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), cmdReceivedCommand);
118 
119  DeviceSrcCommand::Pointer connectionLostCommand = DeviceSrcCommand::New();
120  connectionLostCommand->SetCallbackFunction(this, &IGTLDeviceSource::OnLostConnection);
122  this->m_IGTLDevice->AddObserver(mitk::LostConnectionEvent(), connectionLostCommand);
123  }
124 }
125 
127 {
128  //if outputs are set then delete them
129  if (this->GetNumberOfOutputs() > 0)
130  {
131  for (int numOP = this->GetNumberOfOutputs() - 1; numOP >= 0; numOP--)
132  this->RemoveOutput(numOP);
133  this->Modified();
134  }
135 
136  //fill the outputs if a valid OpenIGTLink device is set
137  if (m_IGTLDevice.IsNull())
138  return;
139 
140  this->SetNumberOfIndexedOutputs(1);
141  if (this->GetOutput(0) == nullptr)
142  {
143  DataObjectPointer newOutput = this->MakeOutput(0);
144  this->SetNthOutput(0, newOutput);
145  this->Modified();
146  }
147 }
148 
150 {
151  if (m_IGTLDevice.IsNull())
152  {
153  throw std::invalid_argument("mitk::IGTLDeviceSource: "
154  "No OpenIGTLink device set");
155  }
156  if (this->IsConnected())
157  {
158  return;
159  }
160  try
161  {
162  m_IGTLDevice->OpenConnection();
163  }
164  catch (mitk::Exception &e)
165  {
166  throw std::runtime_error(std::string("mitk::IGTLDeviceSource: Could not open"
167  "connection to OpenIGTLink device. Error: ") + e.GetDescription());
168  }
169 }
170 
172 {
173  if (m_IGTLDevice.IsNull())
174  throw std::invalid_argument("mitk::IGTLDeviceSource: "
175  "No OpenIGTLink device set");
176  if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Running)
177  return;
178  if (m_IGTLDevice->StartCommunication() == false)
179  throw std::runtime_error("mitk::IGTLDeviceSource: "
180  "Could not start communication");
181 }
182 
184 {
185  if (m_IGTLDevice.IsNull())
186  throw std::invalid_argument("mitk::IGTLDeviceSource: "
187  "No OpenIGTLink device set");
188  if (m_IGTLDevice->CloseConnection() == false)
189  throw std::runtime_error("mitk::IGTLDeviceSource: Could not close connection"
190  " to OpenIGTLink device");
191 }
192 
194 {
195  if (m_IGTLDevice.IsNull())
196  throw std::invalid_argument("mitk::IGTLDeviceSource: "
197  "No OpenIGTLink device set");
198  if (m_IGTLDevice->StopCommunication() == false)
199  throw std::runtime_error("mitk::IGTLDeviceSource: "
200  "Could not stop communicating");
201 }
202 
204 {
205  this->Modified(); // make sure that we need to be updated
206  Superclass::UpdateOutputInformation();
207 }
208 
209 void mitk::IGTLDeviceSource::SetInput(unsigned int idx, const IGTLMessage* msg)
210 {
211  if (msg == nullptr) // if an input is set to nullptr, remove it
212  {
213  this->RemoveInput(idx);
214  }
215  else
216  {
217  // ProcessObject is not const-correct so a const_cast is required here
218  this->ProcessObject::SetNthInput(idx, const_cast<IGTLMessage*>(msg));
219  }
220  // this->CreateOutputsForAllInputs();
221 }
222 
224 {
225  if (m_IGTLDevice.IsNull())
226  return false;
227 
228  return (m_IGTLDevice->GetState() == mitk::IGTLDevice::Ready) ||
229  (m_IGTLDevice->GetState() == mitk::IGTLDevice::Running);
230 }
231 
233 {
234  if (m_IGTLDevice.IsNull())
235  return false;
236 
237  return m_IGTLDevice->GetState() == mitk::IGTLDevice::Running;
238 }
239 
241 {
242  // Get Context
243  us::ModuleContext* context = us::GetModuleContext();
244 
245  // Define ServiceProps
246  us::ServiceProperties props;
247  mitk::UIDGenerator uidGen =
248  mitk::UIDGenerator("org.mitk.services.IGTLDeviceSource.id_", 16);
249  props[US_PROPKEY_ID] = uidGen.GetUID();
250  props[US_PROPKEY_DEVICENAME] = this->GetName();
252  props[US_PROPKEY_DEVICETYPE] = m_Type;
253  m_ServiceRegistration = context->RegisterService(this, props);
254 
255  MITK_INFO << "Registered new DeviceSource as microservice: " << uidGen.GetUID();
256 }
257 
259 {
260 }
261 
263 {
264 }
265 
267 {
268 }
269 
271 {
272  if (this->GetNumberOfInputs() < 1)
273  return nullptr;
274 
275  return static_cast<const IGTLMessage*>(this->ProcessObject::GetInput(0));
276 }
277 
278 const mitk::IGTLMessage*
279 mitk::IGTLDeviceSource::GetInput(unsigned int idx) const
280 {
281  if (this->GetNumberOfInputs() < 1)
282  return nullptr;
283 
284  return static_cast<const IGTLMessage*>(this->ProcessObject::GetInput(idx));
285 }
286 
287 const mitk::IGTLMessage*
288 mitk::IGTLDeviceSource::GetInput(std::string msgName) const
289 {
290  const DataObjectPointerArray& inputs = const_cast<Self*>(this)->GetInputs();
291  for (DataObjectPointerArray::const_iterator it = inputs.begin();
292  it != inputs.end(); ++it)
293  if (std::string(msgName) ==
294  (static_cast<IGTLMessage*>(it->GetPointer()))->GetName())
295  return static_cast<IGTLMessage*>(it->GetPointer());
296  return nullptr;
297 }
298 
299 itk::ProcessObject::DataObjectPointerArraySizeType
301 {
302  DataObjectPointerArray outputs = this->GetInputs();
303  for (DataObjectPointerArray::size_type i = 0; i < outputs.size(); ++i)
304  if (msgName ==
305  (static_cast<IGTLMessage*>(outputs.at(i).GetPointer()))->GetName())
306  return i;
307  throw std::invalid_argument("output name does not exist");
308 }
virtual bool IsCommunicating()
returns true if communication is in progress
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.
unsigned int m_IncomingCommandObserverTag
#define MITK_INFO
Definition: mitkLogMacros.h:18
void SetMessage(igtl::MessageBase::Pointer msg)
Sets the OpenIGTLink message.
void StopCommunication()
stops the communication of the device.
us::ServiceRegistration< Self > m_ServiceRegistration
virtual void OnLostConnection()
This method is called when the IGTL device lost the connection to the other side. ...
itk::DataObject::Pointer MakeOutput(DataObjectPointerArraySizeType idx) override
void Disconnect()
Closes the connection to the OpenIGTLink device.
const IGTLMessage * GetInput(void) const
Get the input of this filter.
#define MITK_DEBUG
Definition: mitkLogMacros.h:22
DataCollection - Class to facilitate loading/accessing structured data.
void UpdateOutputInformation() override
Used for pipeline update.
mitk::IGTLDevice::Pointer m_IGTLDevice
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.
virtual std::string GetName()
IGTLMessage * GetOutput(void)
return the output (output with id 0) of the filter
A wrapper for the OpenIGTLink message type.
An object of this class represents an exception of MITK. Please don&#39;t instantiate exceptions manually...
Definition: mitkException.h:45
void RegisterAsMicroservice() override
Registers this object as a Microservice, making it available to every module and/or plugin...
static const std::string US_PROPKEY_DEVICETYPE
unsigned int m_LostConnectionObserverTag
OpenIGTLink message source.
void StartCommunication()
starts the communication of the device. This needs to be called before Update() or GetOutput()->Updat...
static const std::string US_PROPKEY_ID
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.
static const std::string US_PROPKEY_DEVICENAME
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 const std::string US_INTERFACE_NAME
These Constants are used in conjunction with Microservices.
unsigned int m_IncomingMessageObserverTag
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.