Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
mitkOpenIGTLinkTrackingDevice.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 
19 #include "mitkIGTConfig.h"
20 #include "mitkIGTTimeStamp.h"
21 #include "mitkIGTHardwareException.h"
22 #include "mitkTrackingTypes.h"
23 #include <itksys/SystemTools.hxx>
24 #include <iostream>
25 #include <itkMutexLockHolder.h>
26 #include <itkCommand.h>
28 
29 //sleep headers
30 #include <chrono>
31 #include <thread>
32 
34 
36 {
37  //set the type of this tracking device
39 
41  m_OpenIGTLinkClient->SetName("OpenIGTLink Tracking Device");
42 
45 }
46 
48 {
49 }
50 
52 {
53  return m_OpenIGTLinkClient->GetPortNumber();
54 }
55 
57 {
58  return m_OpenIGTLinkClient->GetHostname();
59 }
60 
62 {
63  m_OpenIGTLinkClient->SetPortNumber(portNumber);
64 }
65 
67 {
68  m_OpenIGTLinkClient->SetHostname(hostname);
69 }
70 
72 {
73  return true;
74 }
75 
76 mitk::TrackingTool* mitk::OpenIGTLinkTrackingDevice::AddTool(const char* toolName, const char* fileName)
77 {
78  mitk::OpenIGTLinkTrackingTool::Pointer t;// = mitk::OpenIGTLinkTrackingTool::New();
79  //TODO: Implement
80  if (this->InternalAddTool(t) == false)
81  return NULL;
82  return t.GetPointer();
83 }
84 
86 {
87  m_AllTools.push_back(tool);
88  return true;
89 }
90 
92 {
93  if (m_OpenIGTLinkClient->GetPortNumber() == -1)
94  {
95  MITK_WARN << "Connection not initialized, aborting (invalid port number).";
96  return false;
97  }
98 
99  try
100  {
101  m_IGTLDeviceSource->Connect();
102  m_IGTLDeviceSource->StartCommunication();
103  }
104  catch (std::runtime_error &e)
105  {
106  MITK_WARN << "Open IGT Link device retruned an error while trying to connect: " << e.what();
107  return false;
108  }
109 
110  //send a message to the server: start tracking stream
111  mitk::IGTLMessageFactory::Pointer msgFactory = m_OpenIGTLinkClient->GetMessageFactory();
112  std::string message = "STT_TDATA";
113  igtl::MessageBase::Pointer sttMsg = msgFactory->CreateInstance(message);
114  //TODO: Fix this to dynamically get this from GUI
115  ((igtl::StartTrackingDataMessage*)sttMsg.GetPointer())->SetResolution(m_UpdateRate);
116  m_OpenIGTLinkClient->SendMessage(sttMsg);
117 
118  mitk::IGTLMessage::Pointer receivedMessage;
119 
120  std::chrono::high_resolution_clock::time_point time = std::chrono::high_resolution_clock::now();
121  std::chrono::milliseconds d = std::chrono::milliseconds(waitingTime);
122 
123  while (!(receivedMessage.IsNotNull() && receivedMessage->IsDataValid()))
124  {
125  m_IGTLDeviceSource->Update();
126  receivedMessage = m_IGTLDeviceSource->GetOutput();
127 
128  if ((time + d) < std::chrono::high_resolution_clock::now())
129  break;
130 
131  std::this_thread::sleep_for(std::chrono::milliseconds(100));
132  }
133 
134  //check the tracking stream for the number and type of tools
135  //igtl::MessageBase::Pointer receivedMessage = m_OpenIGTLinkClient->GetNextMessage();
136  if (receivedMessage.IsNull())
137  {
138  MITK_WARN << "No message was received. Is there really a server?";
139  return false;
140  }
141  else if (!receivedMessage->IsDataValid())
142  {
143  MITK_WARN << "Received invalid message.";
144  return false;
145  }
146 
147  const char* msgType = receivedMessage->GetIGTLMessageType();
148 
149  mitk::OpenIGTLinkTrackingDevice::TrackingMessageType type = GetMessageTypeFromString(msgType);
150 
151  switch (type)
152  {
153  case TDATA:
154  return DiscoverToolsFromTData(dynamic_cast<igtl::TrackingDataMessage*>(receivedMessage->GetMessage().GetPointer()));
155  case QTDATA:
156  return DiscoverToolsFromQTData(dynamic_cast<igtl::QuaternionTrackingDataMessage*>(receivedMessage->GetMessage().GetPointer()));
157  case TRANSFORM:
158  return DiscoverToolsFromTransform();
159  default:
160  MITK_INFO << "Server does not send tracking data. Received data is not of a compatible type. Received type: " << msgType;
161  return false;
162  }
163 }
164 
165 bool mitk::OpenIGTLinkTrackingDevice::DiscoverToolsFromTData(igtl::TrackingDataMessage::Pointer tdMsg)
166 {
167  MITK_INFO << "Start discovering tools by TDATA messages";
168  if (tdMsg == nullptr)
169  {
170  MITK_WARN << "Message was not a TrackingDataMessage, aborting!";
171  return false;
172  }
173 
174  int numberOfTools = tdMsg->GetNumberOfTrackingDataElements();
175  MITK_INFO << "Found " << numberOfTools << " tools";
176  for (int i = 0; i < numberOfTools; i++)
177  {
178  igtl::TrackingDataElement::Pointer currentTrackingData;
179  tdMsg->GetTrackingDataElement(i, currentTrackingData);
180  std::string name = currentTrackingData->GetName();
181  AddNewToolForName(name, i);
182  }
183 
184  m_IGTLDeviceSource->StopCommunication();
185  SetState(Ready);
186  return true;
187 }
188 
189 bool mitk::OpenIGTLinkTrackingDevice::DiscoverToolsFromQTData(igtl::QuaternionTrackingDataMessage::Pointer msg)
190 {
191  MITK_INFO << "Start discovering tools by QTDATA messages";
192  if (msg == nullptr)
193  {
194  MITK_WARN << "Message was not a QuaternionTrackingDataMessage, aborting!";
195  return false;
196  }
197  int numberOfTools = msg->GetNumberOfQuaternionTrackingDataElements();
198  MITK_INFO << "Found " << numberOfTools << " tools";
199  for (int i = 0; i < numberOfTools; i++)
200  {
202  msg->GetQuaternionTrackingDataElement(i, currentTrackingData);
203  std::string name = currentTrackingData->GetName();
204  AddNewToolForName(name, i);
205  }
206  m_IGTLDeviceSource->StopCommunication();
207  SetState(Ready);
208  return true;
209 }
210 
211 void mitk::OpenIGTLinkTrackingDevice::AddNewToolForName(std::string name, int i)
212 {
214  if (name == "") //if no name was given create a default name
215  {
216  std::stringstream defaultName;
217  defaultName << "OpenIGTLinkTool#" << i;
218  name = defaultName.str();
219  }
220  MITK_INFO << "Added tool " << name << " to tracking device.";
221  newTool->SetToolName(name);
222  InternalAddTool(newTool);
223 }
224 
225 bool mitk::OpenIGTLinkTrackingDevice::DiscoverToolsFromTransform()
226 {
227  MITK_INFO << "Start discovering tools by TRANSFORM messages";
228  std::map<std::string, int> toolNameMap;
229  bool condition = false;
230  while (!condition)
231  {
232  //TODO: Fix this.. :/
233  std::this_thread::sleep_for(std::chrono::milliseconds(20));
234  m_IGTLDeviceSource->Update();
235  igtl::TransformMessage::Pointer msg = dynamic_cast<igtl::TransformMessage*>(m_IGTLDeviceSource->GetOutput()->GetMessage().GetPointer());
236  if (msg == nullptr || msg.IsNull())
237  {
238  MITK_INFO << "Received message could not be casted to TransformMessage. Skipping..";
239  continue;
240  }
241 
242  condition = true;
243  int count = toolNameMap[msg->GetDeviceName()];
244  if (count == 0)
245  {
246  MITK_WARN << "ADDED NEW TOOL TO TOOLCHAIN: " << msg->GetDeviceName() << " - 1";
247  toolNameMap[msg->GetDeviceName()] = 1;
248  }
249  else
250  {
251  toolNameMap[msg->GetDeviceName()]++;
252  MITK_WARN << "INCREMENTED TOOL COUNT IN TOOLCHAIN: " << msg->GetDeviceName() << " - " << toolNameMap[msg->GetDeviceName()];
253  }
254 
255  for (std::map<std::string, int>::iterator it = toolNameMap.begin(); it != toolNameMap.end(); ++it)
256  {
257  if (it->second < 5)
258  {
259  condition = false;
260  break;
261  }
262  }
263  }
264 
265  int i = 0;
266  for (std::map<std::string, int>::iterator it = toolNameMap.begin(); it != toolNameMap.end(); ++it)
267  {
268  AddNewToolForName(it->first, i++);
269  }
270  //TODO InternalAddTool for all tools
271 
272  return true;
273 }
274 
276 {
277  if (this->GetState() != Tracking)
278  {
279  MITK_ERROR << "Method was called in the wrong state, something went wrong!";
280  return;
281  }
282 
283  m_IGTLMsgToNavDataFilter->Update();
284 
285  mitk::NavigationData::Pointer currentNavData = m_IGTLMsgToNavDataFilter->GetOutput();
286  const char* name = currentNavData->GetName();
287  MITK_WARN << name;
288 
289  for (int i = 0; i < m_AllTools.size(); i++)
290  {
291  if (strcmp(m_AllTools.at(i)->GetToolName(), name) == 0)
292  {
293  m_AllTools.at(i)->SetDataValid(currentNavData->IsDataValid());
294  m_AllTools.at(i)->SetPosition(currentNavData->GetPosition());
295  m_AllTools.at(i)->SetOrientation(currentNavData->GetOrientation());
296  m_AllTools.at(i)->SetIGTTimeStamp(currentNavData->GetIGTTimeStamp());
297  }
298  }
299 }
300 
302 {
303  //check tracking state
304  if (this->GetState() != Ready)
305  {
306  MITK_WARN << "Cannot start tracking, device is not ready!";
307  return false;
308  }
309 
310  try
311  {
312  m_IGTLDeviceSource->StartCommunication();
313 
314  //send a message to the server: start tracking stream
315  mitk::IGTLMessageFactory::Pointer msgFactory = m_OpenIGTLinkClient->GetMessageFactory();
316  std::string message = "STT_TDATA";
317  //m_OpenIGTLinkClient->SendMessage(msgFactory->CreateInstance(message));
318  }
319  catch (std::runtime_error &e)
320  {
321  MITK_WARN << "Open IGT Link device retruned an error while starting communication: " << e.what();
322  return false;
323  }
324 
325  //create internal igtl pipeline
326  m_IGTLMsgToNavDataFilter = mitk::IGTLMessageToNavigationDataFilter::New();
327  m_IGTLMsgToNavDataFilter->SetNumberOfExpectedOutputs(this->GetToolCount());
328  m_IGTLMsgToNavDataFilter->ConnectTo(m_IGTLDeviceSource);
329 
330  //connect itk events
331  typedef itk::SimpleMemberCommand< mitk::OpenIGTLinkTrackingDevice > CurCommandType;
332  CurCommandType::Pointer messageReceivedCommand = CurCommandType::New();
333  messageReceivedCommand->SetCallbackFunction(this, &mitk::OpenIGTLinkTrackingDevice::UpdateTools);
334  m_MessageReceivedObserverTag = m_OpenIGTLinkClient->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand);
335 
336  this->SetState(Tracking);
337  return true;
338 }
339 
341 {
342  //check tracking state
343  if (this->GetState() != Tracking)
344  {
345  MITK_WARN << "Cannot open connection, device is already connected!";
346  return false;
347  }
348 
349  m_OpenIGTLinkClient->RemoveObserver(m_MessageReceivedObserverTag); //disconnect itk events
350 
351  try
352  {
353  m_IGTLDeviceSource->StopCommunication();
354  }
355  catch (std::runtime_error &e)
356  {
357  MITK_WARN << "Open IGT Link device retruned an error while stopping communication: " << e.what();
358  return false;
359  }
360  this->SetState(Ready);
361  return true;
362 }
363 
365 {
366  return (unsigned int)this->m_AllTools.size();
367 }
368 
370 {
371  if (toolNumber >= this->GetToolCount())
372  return NULL;
373  else
374  return this->m_AllTools[toolNumber];
375 }
376 
378 {
379  //check tracking state
380  if (this->GetState() != Setup)
381  {
382  MITK_WARN << "Cannot open connection, device is already connected!";
383  return false;
384  }
385 
386  try
387  {
388  m_IGTLDeviceSource->Connect();
389  }
390  catch (std::runtime_error &e)
391  {
392  MITK_WARN << "Open IGT Link device retruned an error while trying to connect: " << e.what();
393  return false;
394  }
395  this->SetState(Ready);
396  return true;
397 }
398 
400 {
401  //check tracking state
402  if (this->GetState() != Ready)
403  {
404  MITK_WARN << "Cannot close connection, device is in the wrong state!";
405  return false;
406  }
407 
408  try
409  {
410  m_IGTLDeviceSource->Disconnect();
411  }
412  catch (std::runtime_error &e)
413  {
414  MITK_WARN << "Open IGT Link device retruned an error while trying to disconnect: " << e.what();
415  return false;
416  }
417 
418  this->SetState(Setup);
419 
420  return true;
421 }
422 
423 std::vector<mitk::OpenIGTLinkTrackingTool::Pointer> mitk::OpenIGTLinkTrackingDevice::GetAllTools()
424 {
425  return this->m_AllTools;
426 }
427 
428 mitk::OpenIGTLinkTrackingDevice::TrackingMessageType mitk::OpenIGTLinkTrackingDevice::GetMessageTypeFromString(const char* messageTypeString)
429 {
430  if (strcmp(messageTypeString, "TDATA") == 0)
431  {
432  return mitk::OpenIGTLinkTrackingDevice::TrackingMessageType::TDATA;
433  }
434  else if (strcmp(messageTypeString, "QTDATA") == 0)
435  {
436  return mitk::OpenIGTLinkTrackingDevice::TrackingMessageType::QTDATA;
437  }
438  else if (strcmp(messageTypeString, "TRANSFORM") == 0)
439  {
440  return mitk::OpenIGTLinkTrackingDevice::TrackingMessageType::TRANSFORM;
441  }
442  else
443  {
444  return mitk::OpenIGTLinkTrackingDevice::TrackingMessageType::UNKNOWN;
445  }
446 }
Interface for all Tracking Tools.
itk::SmartPointer< Self > Pointer
TrackingTool * GetTool(unsigned int toolNumber) const
#define MITK_INFO
Definition: mitkLogMacros.h:22
#define MITK_ERROR
Definition: mitkLogMacros.h:24
bool DiscoverTools(int WaitingTime=10000)
Discover the tools available from the connected OpenIGTLink device and adds these tools to this track...
DataCollection - Class to facilitate loading/accessing structured data.
OpenIGTLinkTrackingDevice()
Returns the update rate of the device in fps.
itk::MutexLockHolder< itk::FastMutexLock > MutexLockHolder
mitk::TrackingTool * AddTool(const char *toolName, const char *fileName)
Create a new OpenIGTLink tool with toolName and fileName and add it to the list of tools...
#define MITK_WARN
Definition: mitkLogMacros.h:23
virtual bool StopTracking()
Stops the tracking.
virtual bool CloseConnection()
Closes the connection and clears all resources.
Interface for all Tracking Devices.
static TrackingDeviceData GetDeviceDataOpenIGTLinkTrackingDeviceConnection()
TrackingDeviceData m_Data
current device Data
mitk::IGTLTransformDeviceSource::Pointer m_IGTLDeviceSource
std::vector< OpenIGTLinkTrackingTool::Pointer > GetAllTools()
static void Setup()
virtual bool OpenConnection()
Opens the connection to the device. This have to be done before the tracking is started.
bool InternalAddTool(OpenIGTLinkTrackingTool::Pointer tool)
Adds a tool to the tracking device.
virtual bool StartTracking()
Starts the tracking.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.