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
mitkIGTLMessageToNavigationDataFilter.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 
18 #include "igtlTrackingDataMessage.h"
19 #include "igtlQuaternionTrackingDataMessage.h"
20 #include "igtlTransformMessage.h"
21 #include "mitkQuaternion.h"
22 #include <vnl/vnl_det.h>
23 
26 {
28  this->SetNumberOfRequiredOutputs(1);
29  this->SetNthOutput(0, output.GetPointer());
30 }
31 
33 {
34 }
35 
37 {
38  this->SetInput(0, msg);
39 }
40 
42 {
43  if (msg == NULL) // if an input is set to NULL, remove it
44  {
45  this->RemoveInput(idx);
46  }
47  else
48  {
49  // ProcessObject is not const-correct so a const_cast is required here
50  this->ProcessObject::SetNthInput(idx, const_cast<IGTLMessage*>(msg));
51  }
52  this->CreateOutputsForAllInputs();
53 }
54 
55 const mitk::IGTLMessage*
57 {
58  if (this->GetNumberOfInputs() < 1)
59  return NULL;
60 
61  return static_cast<const IGTLMessage*>(this->ProcessObject::GetInput(0));
62 }
63 
64 const mitk::IGTLMessage*
66 {
67  if (this->GetNumberOfInputs() < 1)
68  return NULL;
69 
70  return static_cast<const IGTLMessage*>(this->ProcessObject::GetInput(idx));
71 }
72 
73 const mitk::IGTLMessage*
75 {
76  const DataObjectPointerArray& inputs = const_cast<Self*>(this)->GetInputs();
77  for (DataObjectPointerArray::const_iterator it = inputs.begin();
78  it != inputs.end(); ++it)
79  {
80  if (std::string(messageName) ==
81  (static_cast<IGTLMessage*>(it->GetPointer()))->GetName())
82  {
83  return static_cast<IGTLMessage*>(it->GetPointer());
84  }
85  }
86  return NULL;
87 }
88 
89 itk::ProcessObject::DataObjectPointerArraySizeType
91 {
92  DataObjectPointerArray outputs = this->GetInputs();
93  for (DataObjectPointerArray::size_type i = 0; i < outputs.size(); ++i)
94  {
95  if (messageName ==
96  (static_cast<IGTLMessage*>(outputs.at(i).GetPointer()))->GetName())
97  {
98  return i;
99  }
100  }
101  throw std::invalid_argument("output name does not exist");
102 }
103 
105  mitk::IGTLMessageSource* UpstreamFilter)
106 {
107  for (DataObjectPointerArraySizeType i = 0;
108  i < UpstreamFilter->GetNumberOfOutputs(); i++)
109  {
110  this->SetInput(i, UpstreamFilter->GetOutput(i));
111  }
112 }
113 
115  unsigned int numOutputs)
116 {
117  this->SetNumberOfIndexedOutputs(numOutputs);
118  this->CreateOutputsForAllInputs();
119 }
120 
122 {
123  // create outputs for all inputs
124  // this->SetNumberOfIndexedOutputs(this->GetNumberOfIndexedInputs());
125  bool isModified = false;
126  for (unsigned int idx = 0; idx < this->GetNumberOfIndexedOutputs(); ++idx)
127  {
128  if (this->GetOutput(idx) == NULL)
129  {
131  this->SetNthOutput(idx, newOutput);
132  isModified = true;
133  }
134  }
135 
136  if (isModified)
137  this->Modified();
138 }
139 
141 {
142  const mitk::IGTLMessage* input = this->GetInput(0);
143  assert(input);
144 
145  //cast the input message into the proper type
146  igtl::TransformMessage* tMsg =
147  (igtl::TransformMessage*)(input->GetMessage().GetPointer());
148 
149  //check if cast was successful
150  if (!tMsg)
151  {
152  mitkThrow() << "Cast from igtl::MessageBase to igtl::TransformMessage "
153  << "failed! Please check the message.";
154  }
155 
156  /* update outputs with tracking data from tools */
157  for (unsigned int i = 0; i < this->GetNumberOfOutputs(); ++i)
158  {
159  mitk::NavigationData* output = this->GetOutput(i);
160  assert(output);
161 
162  if (input->IsDataValid() == false)
163  {
164  output->SetDataValid(false);
165  continue;
166  }
167 
168  //get the transformation matrix and convert it into an affinetransformation
169  igtl::Matrix4x4 transformation_;
170  tMsg->GetMatrix(transformation_);
171  mitk::AffineTransform3D::Pointer affineTransformation =
173  mitk::Matrix3D transformation;
175  for (unsigned int r = 0; r < 3; r++)
176  {
177  for (unsigned int c = 0; c < 3; c++)
178  {
179  transformation.GetVnlMatrix().set(r, c, transformation_[r][c]);
180  }
181  offset.SetElement(r, transformation_[r][3]);
182  }
183  //convert the igtl matrix here and set it in the affine transformation
184  affineTransformation->SetMatrix(transformation);
185  affineTransformation->SetOffset(offset);
186 
187  //create a new navigation data here, there is a neat constructor for
188  //affine transformations that sets the orientation, position according to
189  //the affine transformation. The other values are initialized with standard
190  //values
192  mitk::NavigationData::New(affineTransformation, true);
193  //set the time stamp
194  nd->SetIGTTimeStamp(input->GetTimeStamp());
195  //set the name
196  nd->SetName(input->GetName());
197 
198  output->Graft(nd);
199  }
200 }
201 
203 {
204  const mitk::IGTLMessage* input = this->GetInput(0);
205  assert(input);
206 
207  //cast the input message into the proper type
208  igtl::TrackingDataMessage* tdMsg =
209  (igtl::TrackingDataMessage*)(input->GetMessage().GetPointer());
210 
211  //check if cast was successful
212  if (!tdMsg)
213  {
214  mitkThrow() << "Cast from igtl::MessageBase to igtl::TrackingDataMessage "
215  << "failed! Please check the message.";
216  }
217 
218  //get the number of tracking data elements
219  unsigned int numTrackingDataElements =
220  tdMsg->GetNumberOfTrackingDataElements();
221 
222  if (!numTrackingDataElements)
223  {
224  MITK_ERROR("IGTLMsgToNavDataFilter") << "There are no tracking data "
225  "elements in this message";
226  }
227 
228  /* update outputs with tracking data from tools */
229  for (unsigned int i = 0; i < this->GetNumberOfOutputs(); ++i)
230  {
231  mitk::NavigationData* output = this->GetOutput(i);
232  assert(output);
233 
234  //invalidate the output
235  output->SetDataValid(false);
236 
237  //check if the current index, all outputs that have no corresponding input
238  //tracking element stay invalidated, the others are validated according to
239  //the tracking element
240  if (input->IsDataValid() == false || i >= numTrackingDataElements)
241  {
242  continue;
243  }
244  output->SetDataValid(true);
245 
246  //get the tracking data element which holds all the data
248  tdMsg->GetTrackingDataElement(i, td);
249 
250  //get the transformation matrix and convert it into an affinetransformation
251  igtl::Matrix4x4 transformation_;
252  td->GetMatrix(transformation_);
253  mitk::AffineTransform3D::Pointer affineTransformation =
255  mitk::Matrix3D transformation;
257  for (unsigned int r = 0; r < 3; r++)
258  {
259  for (unsigned int c = 0; c < 3; c++)
260  {
261  transformation.GetVnlMatrix().set(r, c, transformation_[r][c]);
262  }
263  offset.SetElement(r, transformation_[r][3]);
264  }
265  //convert the igtl matrix here and set it in the affine transformation
266  affineTransformation->SetMatrix(transformation);
267  affineTransformation->SetOffset(offset);
268 
270 
271  //check the rotation matrix
272  vnl_matrix_fixed<ScalarType, 3, 3> rotationMatrix =
273  affineTransformation->GetMatrix().GetVnlMatrix();
274  vnl_matrix_fixed<ScalarType, 3, 3> rotationMatrixTransposed =
275  rotationMatrix.transpose();
276  // a quadratic matrix is a rotation matrix exactly when determinant is 1
277  // and transposed is inverse
278  if (!Equal(1.0, vnl_det(rotationMatrix), 0.1)
279  || !((rotationMatrix*rotationMatrixTransposed).is_identity(0.1)))
280  {
281  MITK_ERROR("IGTLMsgToNavDataFilter") << "tried to initialize NavData "
282  << "with non-rotation matrix :" << rotationMatrix << " (Does your "
283  "AffineTransform3D object include spacing? This is not "
284  "supported by NavigationData objects!)";
286  }
287  else
288  {
289  //create a new navigation data here, there is a neat constructor for
290  //affine transformations that sets the orientation, position according to
291  //the affine transformation. The other values are initialized with standard
292  //values
293  nd = mitk::NavigationData::New(affineTransformation, true);
294  }
295  //set the time stamp
296  nd->SetIGTTimeStamp(input->GetIGTTimeStamp());
297  //set the name
298  nd->SetName(td->GetName());
299  output->Graft(nd);
300  }
301 }
302 
303 void
305 {
306  const mitk::IGTLMessage* input = this->GetInput(0);
307  assert(input);
308 
309  //cast the input message into the proper type
310  igtl::QuaternionTrackingDataMessage* tdMsg =
311  (igtl::QuaternionTrackingDataMessage*)(input->GetMessage().GetPointer());
312 
313  //check if cast was successful
314  if (!tdMsg)
315  {
316  mitkThrow() << "Cast from igtl::MessageBase to igtl::TrackingDataMessage "
317  << "failed! Please check the message.";
318  }
319 
320  //get the number of tracking data elements
321  unsigned int numTrackingDataElements =
322  tdMsg->GetNumberOfQuaternionTrackingDataElements();
323 
324  if (!numTrackingDataElements)
325  {
326  MITK_ERROR("IGTLMsgToNavDataFilter") << "There are no tracking data "
327  "elements in this message";
328  }
329 
330  /* update outputs with tracking data from tools */
331  for (unsigned int i = 0; i < this->GetNumberOfOutputs(); ++i)
332  {
333  mitk::NavigationData* output = this->GetOutput(i);
334  assert(output);
335 
336  //invalidate the output
337  output->SetDataValid(false);
338 
339  //check if the current index, all outputs that have no corresponding input
340  //tracking element stay invalidated, the others are validated according to
341  //the tracking element
342  if (input->IsDataValid() == false || i >= numTrackingDataElements)
343  {
344  continue;
345  }
346  output->SetDataValid(true);
347 
348  //get the tracking data element which holds all the data
350  tdMsg->GetQuaternionTrackingDataElement(i, td);
351 
352  //get the quaternion and set it
353  float quaternion_[4]; //igtl quat type
354  td->GetQuaternion(quaternion_);
355  mitk::Quaternion quaternion;
356  quaternion.put(0, quaternion_[0]);
357  quaternion.put(1, quaternion_[1]);
358  quaternion.put(2, quaternion_[2]);
359  quaternion.put(3, quaternion_[3]);
360  output->SetOrientation(quaternion);
361  output->SetHasOrientation(true);
362 
363  //get the position and set it
364  float position_[3]; //igtl position type
365  td->GetPosition(position_);
366  mitk::NavigationData::PositionType position; //mitk position type
367  position.SetElement(0, position_[0]);
368  position.SetElement(1, position_[1]);
369  position.SetElement(2, position_[2]);
370  output->SetPosition(position);
371  output->SetHasPosition(true);
372  //set the time stamp
373  output->SetIGTTimeStamp(input->GetTimeStamp());
374  //set the name
375  output->SetName(td->GetName());
376 
377  //there is no explicit covarience matrix
379  }
380 }
381 
383 {
384  //get the IGTLMessage from the previous filter
385  const mitk::IGTLMessage* input = this->GetInput(0);
386  assert(input);
387 
388  //check if the message is valid, if it is not valid we do not generate new
389  //outputs
390  if (!input->IsDataValid())
391  {
392  MITK_DEBUG("IGTLMessageToNavigationDataFilter") << "Input data is invalid.";
393  return;
394  }
395 
396  //get the message type
397  const char* msgType = input->GetIGTLMessageType();
398 
399  //check if the IGTL message has the proper type
400  if (strcmp(msgType, "TRANSFORM") == 0)
401  {
402  this->GenerateTransformData();
403  }
404  else if (strcmp(msgType, "TDATA") == 0)
405  {
406  this->GenerateTrackingDataData();
407  }
408  else if (strcmp(msgType, "QTDATA") == 0)
409  {
410  this->GenerateQuaternionTrackingDataData();
411  }
412  else
413  {
414  //the message has another type
415  //ignore
416  MITK_INFO("IGTLMessageToNavigationDataFilter") << "The input has a unknown "
417  << "message type: "
418  << msgType;
419  }
420 }
421 
423 {
424  // Superclass::GenerateOutputInformation();
425 
426  // mitk::NavigationData* output = this->GetOutput(0);
427  // assert(output);
428  // const mitk::IGTLMessage* input = this->GetInput(0);
429  // assert(input);
430 
431  itkDebugMacro(<< "GenerateOutputInformation()");
432 
433  // output->Initialize(input->GetPixelType(), input->GetDimension(), input->GetDimensions());
434 
435  // // initialize geometry
436  // output->SetPropertyList(input->GetPropertyList()->Clone());
437  // mitk::TimeGeometry::Pointer clonGeometry = input->GetTimeGeometry()->Clone();
438  // output->SetTimeGeometry(clonGeometry.GetPointer());
439 }
virtual bool IsDataValid() const
returns true if the object contains valid data
virtual igtl::MessageBase::Pointer GetMessage() const
returns the OpenIGTLink message
DataObjectPointerArraySizeType GetInputIndex(std::string messageName)
return the index of the input with name messageName, throw std::invalid_argument exception if that na...
static Pointer New()
virtual void ConnectTo(mitk::IGTLMessageSource *UpstreamFilter)
Connects the input of this filter to the outputs of the given IGTLMessageSource.
itk::SmartPointer< Self > Pointer
#define MITK_INFO
Definition: mitkLogMacros.h:22
itk::Matrix< mitk::ScalarType, 6, 6 > CovarianceMatrixType
type that holds the error characterization of the position and orientation measurements ...
virtual void SetCovErrorMatrix(CovarianceMatrixType _arg)
sets the 6x6 Error Covariance Matrix of the NavigationData object
#define MITK_ERROR
Definition: mitkLogMacros.h:24
Navigation Data.
virtual void SetName(const char *_arg)
set the name of the NavigationData object
#define MITK_DEBUG
Definition: mitkLogMacros.h:26
DataCollection - Class to facilitate loading/accessing structured data.
virtual void SetInput(const IGTLMessage *msg)
Set the input of this filter.
virtual void SetDataValid(bool _arg)
sets the dataValid flag of the NavigationData object indicating if the object contains valid data ...
const char * GetIGTLMessageType() const
virtual void SetIGTTimeStamp(TimeStampType _arg)
sets the IGT timestamp of the NavigationData object
virtual void GenerateOutputInformation() override
Defines how the input will be copied into the output.
virtual void SetHasPosition(bool _arg)
sets the HasPosition flag of the NavigationData object
void CreateOutputsForAllInputs()
Create an output for each input.
const IGTLMessage * GetInput(void) const
Get the input of this filter.
static Vector3D offset
IGTLMessage * GetOutput(void)
return the output (output with id 0) of the filter
virtual void SetHasOrientation(bool _arg)
sets the HasOrientation flag of the NavigationData object
A wrapper for the OpenIGTLink message type.
virtual void SetOrientation(OrientationType _arg)
sets the orientation of the NavigationData object
void SetNumberOfExpectedOutputs(unsigned int numOutputs)
Sets the number of expected outputs.
#define mitkThrow()
virtual const char * GetName() const
returns the name of the IGTLMessage object
OpenIGTLink message source.
vnl_quaternion< ScalarType > Quaternion
virtual void SetPosition(PositionType _arg)
sets the position of the NavigationData object
virtual void Graft(const DataObject *data) override
Graft the data and information from one NavigationData to another.
MITKNEWMODULE_EXPORT bool Equal(mitk::ExampleDataStructure *leftHandSide, mitk::ExampleDataStructure *rightHandSide, mitk::ScalarType eps, bool verbose)
Returns true if the example data structures are considered equal.
virtual TimeStampType GetIGTTimeStamp() const
gets the IGT timestamp of the IGTLMessage object
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.