PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusIgtlMessageCommon.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2 Program: Plus
3 Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4 See License.txt for details.
5 =========================================================Plus=header=end*/
6 
7 // Local includes
8 #include "PlusConfigure.h"
9 #include "igsioTrackedFrame.h"
10 #include "igsioVideoFrame.h"
12 #include "vtkIGSIOTrackedFrameList.h"
13 #include "vtkIGSIOTransformRepository.h"
14 #include <vtkIGSIOFrameConverter.h>
15 
16 // VTK includes
17 #include <vtkImageData.h>
18 #include <vtkMatrix4x4.h>
19 #include <vtkObjectFactory.h>
20 #include <vtkTransform.h>
21 #include <vtkNew.h>
22 
23 // OpenIGTLink includes
24 #include <igtl_tdata.h>
25 
26 // OpenIGTLinkIO includes
27 #include <igtlioImageConverter.h>
28 #include <igtlioPolyDataConverter.h>
29 #include <igtlioTransformConverter.h>
30 #include <igtlioConverterUtilities.h>
31 #if defined(OpenIGTLink_ENABLE_VIDEOSTREAMING)
32  #include <igtlioVideoConverter.h>
33 #endif
34 
35 //----------------------------------------------------------------------------
36 
38 
39 //----------------------------------------------------------------------------
41 {
42 }
43 
44 //----------------------------------------------------------------------------
46 {
47 }
48 
49 //----------------------------------------------------------------------------
50 void vtkPlusIgtlMessageCommon::PrintSelf(ostream& os, vtkIndent indent)
51 {
52  this->Superclass::PrintSelf(os, indent);
53 }
54 
55 //----------------------------------------------------------------------------
57  vtkIGSIOTransformRepository* transformRepository,
58  igsioTransformName& transformName)
59 {
60  igtl::IdentityMatrix(igtlMatrix);
61 
62  if (transformRepository == NULL || !transformName.IsValid())
63  {
64  LOG_ERROR("GetIgtlMatrix failed: Transform repository or transform name is invalid");
65  return PLUS_FAIL;
66  }
67 
68  ToolStatus status(TOOL_INVALID);
69  vtkSmartPointer<vtkMatrix4x4> vtkMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
70  if (transformRepository->GetTransform(transformName, vtkMatrix, &status) != PLUS_SUCCESS)
71  {
72  LOG_ERROR("Failed to get transform from transform repository (" << transformName.From() << " to " << transformName.To() << ")");
73  return PLUS_FAIL;
74  }
75 
76  if (status != TOOL_OK)
77  {
78  LOG_DEBUG("Skipped transformation matrix - Invalid transform in the transform repository (" << transformName.From() << " to " << transformName.To() << ")");
79  return PLUS_FAIL;
80  }
81 
82  // Copy VTK matrix to IGTL matrix
83  igtlioTransformConverter::VTKToIGTLTransform(*vtkMatrix, igtlMatrix);
84 
85  return PLUS_SUCCESS;
86 }
87 
88 //----------------------------------------------------------------------------
89 PlusStatus vtkPlusIgtlMessageCommon::PackTrackedFrameMessage(igtl::PlusTrackedFrameMessage::Pointer trackedFrameMessage,
90  igsioTrackedFrame& trackedFrame,
91  vtkSmartPointer<vtkMatrix4x4> embeddedImageTransform,
92  const std::vector<igsioTransformName>& requestedTransforms)
93 {
94  if (trackedFrameMessage.IsNull())
95  {
96  LOG_ERROR("Failed to pack tracked frame message - input tracked frame message is NULL");
97  return PLUS_FAIL;
98  }
99 
100  PlusStatus status = trackedFrameMessage->SetTrackedFrame(trackedFrame, requestedTransforms);
101  if (status == PLUS_FAIL)
102  {
103  return status;
104  }
105  status = trackedFrameMessage->SetEmbeddedImageTransform(embeddedImageTransform);
106  if (status == PLUS_FAIL)
107  {
108  return status;
109  }
110 
111  trackedFrameMessage->Pack();
112 
113  return status;
114 }
115 
116 //----------------------------------------------------------------------------
118  igtl::Socket* socket,
119  igsioTrackedFrame& trackedFrame,
120  const igsioTransformName& embeddedTransformName,
121  int crccheck)
122 {
123  if (headerMsg.IsNull())
124  {
125  LOG_ERROR("Unable to unpack tracked frame message - header message is NULL!");
126  return PLUS_FAIL;
127  }
128 
129  if (socket == NULL)
130  {
131  LOG_ERROR("Unable to unpack tracked frame message - socket is NULL!");
132  return PLUS_FAIL;
133  }
134 
135  igtl::PlusTrackedFrameMessage::Pointer trackedFrameMsg = dynamic_cast<igtl::PlusTrackedFrameMessage*>(headerMsg.GetPointer());
136  if (trackedFrameMsg.IsNull())
137  {
138  trackedFrameMsg = igtl::PlusTrackedFrameMessage::New();
139  }
140  trackedFrameMsg->SetMessageHeader(headerMsg);
141  trackedFrameMsg->AllocateBuffer();
142 
143  bool timeout(false);
144  socket->Receive(trackedFrameMsg->GetBufferBodyPointer(), trackedFrameMsg->GetBufferBodySize(), timeout);
145 
146  int c = trackedFrameMsg->Unpack(crccheck);
147  if (!(c & igtl::MessageHeader::UNPACK_BODY))
148  {
149  LOG_ERROR("Couldn't receive tracked frame message from server!");
150  return PLUS_FAIL;
151  }
152 
153  // if CRC check is OK. get tracked frame data.
154  trackedFrame = trackedFrameMsg->GetTrackedFrame();
155 
156  if (embeddedTransformName.IsValid())
157  {
158  // Save the transform that is embedded in the TRACKEDFRAME message into the tracked frame
159  trackedFrame.SetFrameTransform(embeddedTransformName, trackedFrameMsg->GetEmbeddedImageTransform());
160  }
161 
162  return PLUS_SUCCESS;
163 }
164 
165 //----------------------------------------------------------------------------
166 PlusStatus vtkPlusIgtlMessageCommon::PackUsMessage(igtl::PlusUsMessage::Pointer usMessage, igsioTrackedFrame& trackedFrame)
167 {
168  if (usMessage.IsNull())
169  {
170  LOG_ERROR("Failed to pack US message - input US message is NULL");
171  return PLUS_FAIL;
172  }
173 
174  PlusStatus status = usMessage->SetTrackedFrame(trackedFrame);
175  usMessage->Pack();
176 
177  return status;
178 }
179 
180 //----------------------------------------------------------------------------
181 PlusStatus vtkPlusIgtlMessageCommon::UnpackUsMessage(igtl::MessageHeader::Pointer headerMsg,
182  igtl::Socket* socket,
183  igsioTrackedFrame& trackedFrame,
184  int crccheck)
185 {
186  if (headerMsg.IsNull())
187  {
188  LOG_ERROR("Unable to unpack US message - header message is NULL!");
189  return PLUS_FAIL;
190  }
191 
192  if (socket == NULL)
193  {
194  LOG_ERROR("Unable to unpack US message - socket is NULL!");
195  return PLUS_FAIL;
196  }
197 
198  auto usMsg = igtl::PlusUsMessage::New();
199  usMsg->SetMessageHeader(headerMsg);
200  usMsg->AllocateBuffer();
201 
202  bool timeout(false);
203  socket->Receive(usMsg->GetBufferBodyPointer(), usMsg->GetBufferBodySize(), timeout);
204 
205  int c = usMsg->Unpack(crccheck);
206  if (!(c & igtl::MessageHeader::UNPACK_BODY))
207  {
208  LOG_ERROR("Couldn't receive US message from server!");
209  return PLUS_FAIL;
210  }
211 
212  // if CRC check is OK. get tracked frame data.
213  trackedFrame = usMsg->GetTrackedFrame();
214 
215  return PLUS_SUCCESS;
216 }
217 
218 //----------------------------------------------------------------------------
219 PlusStatus vtkPlusIgtlMessageCommon::PackImageMessage(igtl::ImageMessage::Pointer imageMessage,
220  igsioTrackedFrame& trackedFrame,
221  const vtkMatrix4x4& matrix,
222  vtkIGSIOFrameConverter* frameConverter/*=NULL*/)
223 {
224  if (imageMessage.IsNull())
225  {
226  LOG_ERROR("Failed to pack image message - input image message is NULL");
227  return PLUS_FAIL;
228  }
229 
230  if (!trackedFrame.GetImageData()->IsImageValid())
231  {
232  LOG_WARNING("Unable to send image message - image data is NOT valid!");
233  return PLUS_FAIL;
234  }
235 
236  vtkSmartPointer<vtkIGSIOFrameConverter> converter = frameConverter;
237  if (!converter)
238  {
239  converter = vtkSmartPointer<vtkIGSIOFrameConverter>::New();
240  }
241 
242  double timestamp = trackedFrame.GetTimestamp();
243  vtkSmartPointer<vtkImageData> frameImage = converter->GetImageData(trackedFrame.GetImageData());
244 
245  auto igtlFrameTime = igtl::TimeStamp::New();
246  igtlFrameTime->SetTime(timestamp);
247 
248  int imageSizePixels[3] = { 0 };
249  int subSizePixels[3] = { 0 };
250  int subOffset[3] = { 0 };
251  double imageSpacingMm[3] = { 0 };
252  double imageOriginMm[3] = { 0 };
253  int scalarType = PlusCommon::GetIGTLScalarPixelTypeFromVTK(trackedFrame.GetImageData()->GetVTKScalarPixelType());
254  unsigned int numScalarComponents(1);
255  if (trackedFrame.GetImageData()->GetNumberOfScalarComponents(numScalarComponents) == PLUS_FAIL)
256  {
257  LOG_ERROR("Unable to retrieve number of scalar components.");
258  return PLUS_FAIL;
259  }
260 
261  frameImage->GetDimensions(imageSizePixels);
262  frameImage->GetSpacing(imageSpacingMm);
263  frameImage->GetOrigin(imageOriginMm);
264  frameImage->GetDimensions(subSizePixels);
265 
266  float spacingFloat[3] = { 0 };
267  for (int i = 0; i < 3; ++ i)
268  {
269  spacingFloat[ i ] = (float)imageSpacingMm[ i ];
270  }
271 
272  imageMessage->SetDimensions(imageSizePixels);
273  imageMessage->SetSpacing(spacingFloat);
274  imageMessage->SetNumComponents(numScalarComponents);
275  imageMessage->SetScalarType(scalarType);
276  imageMessage->SetEndian(igtl_is_little_endian() ? igtl::ImageMessage::ENDIAN_LITTLE : igtl::ImageMessage::ENDIAN_BIG);
277  imageMessage->SetSubVolume(subSizePixels, subOffset);
278  imageMessage->AllocateScalars();
279 
280  unsigned char* igtlImagePointer = (unsigned char*)(imageMessage->GetScalarPointer());
281  unsigned char* vtkImagePointer = (unsigned char*)(frameImage->GetScalarPointer());
282 
283  memcpy(igtlImagePointer, vtkImagePointer, imageMessage->GetImageSize());
284 
285  // Convert VTK transform to IGTL transform.
286  if (igtlioImageConverter::VTKTransformToIGTLImage(matrix, imageSizePixels, imageSpacingMm, imageOriginMm, imageMessage) != 1)
287  {
288  LOG_ERROR("Failed to pack image message - unable to compute IJKToRAS transform");
289  return PLUS_FAIL;
290  }
291 
292  imageMessage->SetTimeStamp(igtlFrameTime);
293  imageMessage->Pack();
294 
295  return PLUS_SUCCESS;
296 }
297 
298 //----------------------------------------------------------------------------
299 PlusStatus vtkPlusIgtlMessageCommon::PackImageMessage(igtl::ImageMessage::Pointer imageMessage,
300  vtkImageData* image,
301  const vtkMatrix4x4& imageToReferenceTransform,
302  double timestamp)
303 {
304  if (imageMessage.IsNull())
305  {
306  LOG_ERROR("Failed to pack image message - input image message is NULL");
307  return PLUS_FAIL;
308  }
309 
310  int imageSizePixels[3] = { 0 };
311  image->GetDimensions(imageSizePixels);
312  imageMessage->SetDimensions(imageSizePixels);
313 
314  int subSizePixels[3] = { 0 };
315  image->GetDimensions(subSizePixels);
316  int subOffset[3] = { 0 };
317  imageMessage->SetSubVolume(subSizePixels, subOffset);
318 
319  double imageSpacingMm[3] = { 0 };
320  image->GetSpacing(imageSpacingMm);
321  float spacingFloat[3] = { 0 };
322  for (int i = 0; i < 3; ++i)
323  {
324  spacingFloat[i] = (float)imageSpacingMm[i];
325  }
326  imageMessage->SetSpacing(spacingFloat);
327 
328  double imageOriginMm[3] = { 0 };
329  image->GetOrigin(imageOriginMm);
330  // imageMessage->SetOrigin() is not used, because origin and normal is set later by igtlioImageConverter::VTKTransformToIGTLImage()
331 
332  int scalarType = PlusCommon::GetIGTLScalarPixelTypeFromVTK(image->GetScalarType());
333  imageMessage->SetScalarType(scalarType);
334  imageMessage->SetEndian(igtl_is_little_endian() ? igtl::ImageMessage::ENDIAN_LITTLE : igtl::ImageMessage::ENDIAN_BIG);
335  imageMessage->AllocateScalars();
336 
337  unsigned char* igtlImagePointer = (unsigned char*)(imageMessage->GetScalarPointer());
338  unsigned char* vtkImagePointer = (unsigned char*)(image->GetScalarPointer());
339 
340  memcpy(igtlImagePointer, vtkImagePointer, imageMessage->GetImageSize());
341 
342  if (igtlioImageConverter::VTKTransformToIGTLImage(imageToReferenceTransform, imageSizePixels, imageSpacingMm, imageOriginMm, imageMessage) != 1)
343  {
344  LOG_ERROR("Failed to pack image message - unable to compute IJKToRAS transform");
345  return PLUS_FAIL;
346  }
347 
348  auto igtlTime = igtl::TimeStamp::New();
349  igtlTime->SetTime(timestamp);
350  imageMessage->SetTimeStamp(igtlTime);
351 
352  imageMessage->Pack();
353 
354  return PLUS_SUCCESS;
355 
356 }
357 
358 //----------------------------------------------------------------------------
359 PlusStatus vtkPlusIgtlMessageCommon::UnpackImageMessage(igtl::MessageHeader::Pointer headerMsg,
360  igtl::Socket* socket,
361  igsioTrackedFrame& trackedFrame,
362  const igsioTransformName& embeddedTransformName,
363  int crccheck)
364 {
365  if (headerMsg.IsNull())
366  {
367  LOG_ERROR("Unable to unpack image message - header message is NULL!");
368  return PLUS_FAIL;
369  }
370 
371  if (socket == NULL)
372  {
373  LOG_ERROR("Unable to unpack image message - socket is NULL!");
374  return PLUS_FAIL;
375  }
376 
377  // Message body handler for IMAGE
378  igtl::ImageMessage::Pointer imgMsg = dynamic_cast<igtl::ImageMessage*>(headerMsg.GetPointer());
379  if (imgMsg.IsNull())
380  {
381  imgMsg = igtl::ImageMessage::New();
382  }
383  imgMsg->SetMessageHeader(headerMsg);
384  imgMsg->AllocateBuffer();
385 
386  bool timeout(false);
387  socket->Receive(imgMsg->GetBufferBodyPointer(), imgMsg->GetBufferBodySize(), timeout);
388 
389  int c = imgMsg->Unpack(crccheck);
390  if (!(c & igtl::MessageHeader::UNPACK_BODY))
391  {
392  LOG_ERROR("Couldn't receive image message from server!");
393  return PLUS_FAIL;
394  }
395 
396  // if CRC check is OK. Read data.
397  auto igtlTimestamp = igtl::TimeStamp::New();
398  imgMsg->GetTimeStamp(igtlTimestamp);
399 
400  int imgSize[3] = {0}; // image dimension in pixels
401  imgMsg->GetDimensions(imgSize);
402 
403  if (imgSize[0] < 0 || imgSize[1] < 0 || imgSize[2] < 0)
404  {
405  LOG_ERROR("Image with negative dimension. Aborting.");
406  return PLUS_FAIL;
407  }
408  FrameSizeType imageSize = {static_cast<unsigned int>(imgSize[0]), static_cast<unsigned int>(imgSize[1]), static_cast<unsigned int>(imgSize[2]) };
409 
410  // Set scalar pixel type
411  igsioCommon::VTKScalarPixelType pixelType = PlusCommon::GetVTKScalarPixelTypeFromIGTL(imgMsg->GetScalarType());
412  igsioVideoFrame frame;
413  if (frame.AllocateFrame(imageSize, pixelType, imgMsg->GetNumComponents()) != PLUS_SUCCESS)
414  {
415  LOG_ERROR("Failed to allocate image data for tracked frame!");
416  return PLUS_FAIL;
417  }
418 
419  // Set the image type to support color images
420  if (imgMsg->GetScalarType() == igtl::ImageMessage::TYPE_INT8)
421  {
422  frame.SetImageType((imgMsg->GetNumComponents() == igtl::ImageMessage::DTYPE_VECTOR) ? US_IMG_RGB_COLOR : US_IMG_BRIGHTNESS);
423  }
424 
425  // Copy image to buffer
426  memcpy(frame.GetScalarPointer(), imgMsg->GetScalarPointer(), frame.GetFrameSizeInBytes());
427 
428  trackedFrame.SetImageData(frame);
429  trackedFrame.SetTimestamp(igtlTimestamp->GetTimeStamp());
430 
431  if (embeddedTransformName.IsValid())
432  {
433  vtkSmartPointer<vtkMatrix4x4> vtkMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
434  if (igtlioImageConverter::IGTLImageToVTKTransform(imgMsg, vtkMatrix) != 1)
435  {
436  LOG_ERROR("Failed to unpack image message - unable to extract IJKToRAS transform");
437  return PLUS_FAIL;
438  }
439  trackedFrame.SetFrameTransform(embeddedTransformName, vtkMatrix);
440  }
441 
442  return PLUS_SUCCESS;
443 }
444 
445 //----------------------------------------------------------------------------
446 PlusStatus vtkPlusIgtlMessageCommon::PackImageMetaMessage(igtl::ImageMetaMessage::Pointer imageMetaMessage,
447  igsioCommon::ImageMetaDataList& imageMetaDataList)
448 {
449  if (imageMetaMessage.IsNull())
450  {
451  LOG_ERROR("Failed to pack image message - input image message is NULL");
452  return PLUS_FAIL;
453  }
454  for (igsioCommon::ImageMetaDataList::iterator it = imageMetaDataList.begin(); it != imageMetaDataList.end(); it++)
455  {
456  auto imageMetaElement = igtl::ImageMetaElement::New();
457  auto timeStamp = igtl::TimeStamp::New();
458  if (!imageMetaElement->SetName(it->Description.c_str()))
459  {
460  LOG_ERROR("vtkPlusIgtlMessageCommon::PackImageMetaMessage failed: image name is too long " << it->Id);
461  return PLUS_FAIL;
462  }
463  if (!imageMetaElement->SetDeviceName(it->Id.c_str()))
464  {
465  LOG_ERROR("vtkPlusIgtlMessageCommon::PackImageMetaMessage failed: device name is too long " << it->Id);
466  return PLUS_FAIL;
467  }
468  imageMetaElement->SetModality(it->Modality.c_str());
469  if (!imageMetaElement->SetPatientName(it->PatientName.c_str()))
470  {
471  LOG_ERROR("vtkPlusIgtlMessageCommon::PackImageMetaMessage failed: patient name is too long " << it->Id);
472  return PLUS_FAIL;
473  }
474  if (!imageMetaElement->SetPatientID(it->PatientId.c_str()))
475  {
476  LOG_ERROR("vtkPlusIgtlMessageCommon::PackImageMetaMessage failed: patient id is too long " << it->Id);
477  return PLUS_FAIL;
478  }
479  timeStamp->SetTime(it->TimeStampUtc);
480  imageMetaElement->SetTimeStamp(timeStamp);
481  imageMetaElement->SetSize(it->Size[0], it->Size[1], it->Size[2]);
482  imageMetaElement->SetScalarType(it->ScalarType);
483  imageMetaMessage->AddImageMetaElement(imageMetaElement);
484  }
485  imageMetaMessage->Pack();
486  return PLUS_SUCCESS;
487 }
488 
489 //----------------------------------------------------------------------------
490 #if defined(OpenIGTLink_ENABLE_VIDEOSTREAMING)
491 PlusStatus vtkPlusIgtlMessageCommon::PackVideoMessage(igtl::VideoMessage::Pointer videoMessage,
492  igsioTrackedFrame& trackedFrame,
493  vtkMatrix4x4& matrix,
494  vtkIGSIOFrameConverter* frameConverter/*=NULL*/,
495  std::string fourCC/*=""*/,
496  std::map<std::string, std::string> parameters)
497 {
498  if (videoMessage.IsNull())
499  {
500  LOG_ERROR("Failed to pack image message - input image message is NULL");
501  return PLUS_FAIL;
502  }
503 
504  if (!trackedFrame.GetImageData()->IsImageValid())
505  {
506  LOG_WARNING("Unable to send image message - image data is NOT valid!");
507  return PLUS_FAIL;
508  }
509 
510  vtkSmartPointer<vtkStreamingVolumeFrame> frame = trackedFrame.GetImageData()->GetEncodedFrame();
511  std::string codecFourCC = fourCC;
512  if (codecFourCC.empty() && frame)
513  {
514  codecFourCC = frame->GetCodecFourCC();
515  }
516  if (codecFourCC.empty())
517  {
518  LOG_ERROR("Unknown frame encoding!");
519  return PLUS_FAIL;
520  }
521 
522  frame = frameConverter->GetEncodedFrame(trackedFrame.GetImageData(), codecFourCC, parameters);
523  if (!frame)
524  {
525  LOG_ERROR("Could not encode frame!");
526  return PLUS_FAIL;
527  }
528 
529  vtkSmartPointer<vtkUnsignedCharArray> frameData = frame->GetFrameData();
530  int frameType = frame->GetFrameType();
531  unsigned int frameSize = frameData->GetSize() * frameData->GetElementComponentSize();
532  codecFourCC = frame->GetCodecFourCC();
533  int endian = (igtl_is_little_endian() == 1 ? IGTL_VIDEO_ENDIAN_LITTLE : IGTL_VIDEO_ENDIAN_BIG);
534  int dimensions[3] = { 0, 0, 0 };
535  frame->GetDimensions(dimensions);
536  double spacing[3] = { 1.0, 1.0, 1.0 };
537  int encodedFrameType = FrameTypeUnKnown;
538  if (frameType == vtkStreamingVolumeFrame::IFrame)
539  {
540  encodedFrameType = FrameTypeKey;
541  }
542  if (frame->GetNumberOfComponents() == 1)
543  {
544  encodedFrameType = encodedFrameType << 8;
545  }
546 
547  igtl::Matrix4x4 videoMatrix;
548  igtl::IdentityMatrix(videoMatrix);
549  igtlioConverterUtilities::VTKTransformToIGTLTransform(&matrix, frame->GetDimensions(), spacing, videoMatrix);
550 
551  double timestamp = trackedFrame.GetTimestamp();
552  auto igtlFrameTime = igtl::TimeStamp::New();
553  igtlFrameTime->SetTime(timestamp);
554 
555  videoMessage->SetCodecType(codecFourCC.c_str());
556  videoMessage->SetEndian(endian); //little endian is 2 big endian is 1
557  videoMessage->SetSpacing(spacing[0], spacing[1], spacing[2]);
558  videoMessage->SetWidth(dimensions[0]);
559  videoMessage->SetHeight(dimensions[1]);
560  videoMessage->SetAdditionalZDimension(dimensions[2]);
561  videoMessage->SetMatrix(videoMatrix);
562  videoMessage->SetFrameType(encodedFrameType);
563  videoMessage->SetTimeStamp(igtlFrameTime);
564  videoMessage->SetBitStreamSize(frameSize);
565  videoMessage->AllocateScalars();
566  memcpy(videoMessage->GetPackFragmentPointer(2), frameData->GetPointer(0), frameSize);
567  videoMessage->Pack();
568 
569  return PLUS_SUCCESS;
570 }
571 #endif
572 
573 //-------------------------------------------------------------------------------
574 PlusStatus vtkPlusIgtlMessageCommon::PackTransformMessage(igtl::TransformMessage::Pointer transformMessage,
575  igsioTransformName& transformName,
576  igtl::Matrix4x4& igtlMatrix,
577  ToolStatus status,
578  double timestamp)
579 {
580  if (transformMessage.IsNull())
581  {
582  LOG_ERROR("Failed to pack transform message - input transform message is NULL");
583  return PLUS_FAIL;
584  }
585 
586  auto igtlTime = igtl::TimeStamp::New();
587  igtlTime->SetTime(timestamp);
588 
589  std::string strTransformName;
590  transformName.GetTransformName(strTransformName);
591 
592  transformMessage->SetMetaDataElement("TransformValid", status == TOOL_OK);
593  transformMessage->SetMetaDataElement("TransformStatus", IANA_TYPE_US_ASCII, igsioCommon::ConvertToolStatusToString(status));
594  transformMessage->SetMatrix(igtlMatrix);
595  transformMessage->SetTimeStamp(igtlTime);
596  if (strTransformName.length() > IGTL_TDATA_LEN_NAME)
597  {
598  std::string shortenedName = strTransformName.substr(0, IGTL_TDATA_LEN_NAME);
599  transformMessage->SetDeviceName(shortenedName.c_str());
600  transformMessage->SetMetaDataElement("IGTL_DEVICE_NAME", IANA_TYPE_US_ASCII, strTransformName);
601  }
602  else
603  {
604  transformMessage->SetDeviceName(strTransformName.c_str());
605  }
606  transformMessage->Pack();
607 
608  return PLUS_SUCCESS;
609 }
610 
611 //----------------------------------------------------------------------------
612 PlusStatus vtkPlusIgtlMessageCommon::PackPolyDataMessage(igtl::PolyDataMessage::Pointer polydataMessage,
613  vtkSmartPointer<vtkPolyData> polyData,
614  double timestamp)
615 {
616  if (polydataMessage.IsNull())
617  {
618  LOG_ERROR("Failed to pack poly data message - input polydata message is NULL");
619  return PLUS_FAIL;
620  }
621 
622  auto igtlTime = igtl::TimeStamp::New();
623  igtlTime->SetTime(timestamp);
624 
625  igtlioPolyDataConverter::VTKPolyDataToIGTL(polyData, polydataMessage);
626  polydataMessage->SetTimeStamp(igtlTime);
627  polydataMessage->Pack();
628 
629  return PLUS_SUCCESS;
630 }
631 
632 //-------------------------------------------------------------------------------
633 PlusStatus vtkPlusIgtlMessageCommon::PackTrackingDataMessage(igtl::TrackingDataMessage::Pointer trackingDataMessage,
634  const std::vector<igsioTransformName>& names,
635  const vtkIGSIOTransformRepository& repository,
636  double timestamp)
637 {
638  if (trackingDataMessage.IsNull())
639  {
640  LOG_ERROR("Failed to pack tracking data message - input tracking data message is NULL");
641  return PLUS_FAIL;
642  }
643 
644  auto igtlTime = igtl::TimeStamp::New();
645  igtlTime->SetTime(timestamp);
646 
647  uint32_t i = 0;
648  for (auto it = names.begin(); it != names.end(); ++it)
649  {
650  if (it->GetTransformName().empty())
651  {
652  LOG_ERROR("Unable to pack transform element in TDATA message. Skipping.");
653  continue;
654  }
655 
656  vtkNew<vtkMatrix4x4> vtkMat;
657  ToolStatus status(TOOL_INVALID);
658  if (repository.GetTransform(*it, vtkMat.GetPointer(), &status) != PLUS_SUCCESS)
659  {
660  LOG_ERROR("Transform " << it->From() << "To" << it->To() << " not found in repository.");
661  continue;
662  }
663  igtl::Matrix4x4 matrix;
664  if (igtlioTransformConverter::VTKToIGTLTransform(*vtkMat.GetPointer(), matrix) != 1)
665  {
666  LOG_ERROR("Unable to convert from VTK to IGTL transform.");
667  continue;
668  }
669 
670  auto trackElement = igtl::TrackingDataElement::New();
671  std::string shortenedName = it->GetTransformName().substr(0, IGTL_TDATA_LEN_NAME);
672  trackElement->SetName(shortenedName.c_str());
673  trackElement->SetType(igtl::TrackingDataElement::TYPE_6D);
674  trackElement->SetMatrix(matrix);
675  trackingDataMessage->AddTrackingDataElement(trackElement);
676  trackingDataMessage->SetMetaDataElement(it->GetTransformName() + "Status", IANA_TYPE_US_ASCII, igsioCommon::ConvertToolStatusToString(status));
677  trackingDataMessage->SetMetaDataElement(it->GetTransformName() + "Index", IANA_TYPE_US_ASCII, igsioCommon::ToString(i));
678  ++i;
679  }
680 
681  trackingDataMessage->SetDeviceName("TDATA_" + igsioCommon::ToString(trackingDataMessage->GetNumberOfTrackingDataElements()) + "Elem");
682  trackingDataMessage->SetTimeStamp(igtlTime);
683  trackingDataMessage->Pack();
684 
685  return PLUS_SUCCESS;
686 }
687 
688 //----------------------------------------------------------------------------
690  igtl::Socket* socket,
691  std::vector<igsioTransformName>& names,
692  vtkIGSIOTransformRepository& repository,
693  double& timestamp,
694  int crccheck)
695 {
696  if (headerMsg.IsNull())
697  {
698  LOG_ERROR("Unable to unpack transform message - header message is NULL!");
699  return PLUS_FAIL;
700  }
701 
702  if (socket == NULL)
703  {
704  LOG_ERROR("Unable to unpack transform message - socket is NULL!");
705  return PLUS_FAIL;
706  }
707 
708  auto tdMsg = igtl::TrackingDataMessage::New();
709  tdMsg->SetMessageHeader(headerMsg);
710  tdMsg->InitBuffer();
711 
712  bool timeout(false);
713  socket->Receive(tdMsg->GetBufferBodyPointer(), tdMsg->GetBufferBodySize(), timeout);
714 
715  int c = tdMsg->Unpack(crccheck);
716  if (!(c & igtl::MessageHeader::UNPACK_BODY))
717  {
718  LOG_ERROR("Couldn't receive tracking data message from server!");
719  return PLUS_FAIL;
720  }
721 
722  // if CRC check is OK. Read transform data.
723  int numberOfTools = tdMsg->GetNumberOfTrackingDataElements();
724 
725  if (numberOfTools > 1)
726  {
727  LOG_INFO("Found " << numberOfTools << " tools");
728  }
729 
730  for (int i = 0; i < numberOfTools; ++i)
731  {
732  igtl::TrackingDataElement::Pointer currentTrackingData;
733  tdMsg->GetTrackingDataElement(i, currentTrackingData);
734  std::string name = currentTrackingData->GetName();
735 
736  igtl::Matrix4x4 igtlMatrix;
737  currentTrackingData->GetMatrix(igtlMatrix);
738 
739  ToolStatus status(TOOL_UNKNOWN);
740  std::string statusStr;
741  if (tdMsg->GetMetaDataElement(std::string(currentTrackingData->GetName()) + "Status", statusStr))
742  {
743  status = igsioCommon::ConvertStringToToolStatus(statusStr);
744  }
745  else
746  {
747  LOG_WARNING("Incoming TDATA message element " << currentTrackingData->GetName() << " is without a tool status. Defaulting to TOOL_OK.");
748  status = TOOL_OK;
749  }
750  vtkSmartPointer<vtkMatrix4x4> mat = vtkSmartPointer<vtkMatrix4x4>::New();
751  if (igtlioTransformConverter::IGTLToVTKTransform(igtlMatrix, mat) != 1)
752  {
753  LOG_ERROR("Unable to unpack transform message - cannot convert from IGTL to VTK");
754  continue;
755  }
756  igsioTransformName transName(name);
757  if (!transName.IsValid())
758  {
759  LOG_ERROR("Invalid transform name sent via TDATA message. Skipping.");
760  continue;
761  }
762  names.push_back(name);
763  repository.SetTransform(transName, mat, status);
764  }
765 
766  // Get timestamp
767  auto igtlTimestamp = igtl::TimeStamp::New();
768  tdMsg->GetTimeStamp(igtlTimestamp);
769  timestamp = igtlTimestamp->GetTimeStamp();
770 
771  return PLUS_SUCCESS;
772 }
773 
774 //----------------------------------------------------------------------------
775 PlusStatus vtkPlusIgtlMessageCommon::UnpackTransformMessage(igtl::MessageHeader::Pointer headerMsg,
776  igtl::Socket* socket,
777  vtkMatrix4x4* transformMatrix,
778  ToolStatus& toolStatus,
779  std::string& transformName,
780  double& timestamp,
781  int crccheck)
782 {
783  if (headerMsg.IsNull())
784  {
785  LOG_ERROR("Unable to unpack transform message - header message is NULL!");
786  return PLUS_FAIL;
787  }
788 
789  if (socket == NULL)
790  {
791  LOG_ERROR("Unable to unpack transform message - socket is NULL!");
792  return PLUS_FAIL;
793  }
794 
795  if (transformMatrix == NULL)
796  {
797  LOG_ERROR("Unable to unpack transform message - matrix is NULL!");
798  return PLUS_FAIL;
799  }
800 
801  igtl::TransformMessage::Pointer transMsg = dynamic_cast<igtl::TransformMessage*>(headerMsg.GetPointer());
802  if (transMsg.IsNull())
803  {
804  transMsg = igtl::TransformMessage::New();
805  }
806  transMsg->SetMessageHeader(headerMsg);
807  transMsg->AllocateBuffer();
808 
809  bool timeout(false);
810  socket->Receive(transMsg->GetBufferBodyPointer(), transMsg->GetBufferBodySize(), timeout);
811 
812  int c = transMsg->Unpack(crccheck);
813  if (!(c & igtl::MessageHeader::UNPACK_BODY))
814  {
815  LOG_ERROR("Couldn't receive transform message from server!");
816  return PLUS_FAIL;
817  }
818  // if CRC check is OK. Read transform data.
819  igtl::Matrix4x4 igtlMatrix;
820  igtl::IdentityMatrix(igtlMatrix);
821  transMsg->GetMatrix(igtlMatrix);
822 
823  // convert igtl matrix to vtk matrix
824  vtkSmartPointer<vtkMatrix4x4> mat = vtkSmartPointer<vtkMatrix4x4>::New();
825  if (igtlioTransformConverter::IGTLToVTKTransform(igtlMatrix, transformMatrix) != 1)
826  {
827  LOG_ERROR("Unable to unpack transform message - cannot convert from IGTL to VTK");
828  return PLUS_FAIL;
829  }
830 
831  // Get timestamp
832  auto igtlTimestamp = igtl::TimeStamp::New();
833  transMsg->GetTimeStamp(igtlTimestamp);
834  timestamp = igtlTimestamp->GetTimeStamp();
835 
836  // Status
837  std::string statusStr;
838  toolStatus = TOOL_UNKNOWN;
839  if (transMsg->GetMetaDataElement("TransformStatus", statusStr))
840  {
841  toolStatus = igsioCommon::ConvertStringToToolStatus(statusStr);
842  }
843  else
844  {
845  LOG_WARNING("Incoming TRANSFORM message was received without a tool status. Defaulting to TOOL_OK.");
846  toolStatus = TOOL_OK;
847  }
848 
849  // Get transform name
850  transformName = transMsg->GetDeviceName();
851 
852  return PLUS_SUCCESS;
853 }
854 
855 //----------------------------------------------------------------------------
856 PlusStatus vtkPlusIgtlMessageCommon::PackPositionMessage(igtl::PositionMessage::Pointer positionMessage,
857  igsioTransformName& transformName,
858  ToolStatus status,
859  float position[3],
860  float quaternion[4],
861  double timestamp)
862 {
863  if (positionMessage.IsNull())
864  {
865  LOG_ERROR("Failed to pack position message - input position message is NULL");
866  return PLUS_FAIL;
867  }
868 
869  auto igtlTime = igtl::TimeStamp::New();
870  igtlTime->SetTime(timestamp);
871 
872  std::string strTransformName;
873  transformName.GetTransformName(strTransformName);
874 
875  positionMessage->SetPosition(position);
876  positionMessage->SetQuaternion(quaternion);
877  positionMessage->SetMetaDataElement("TransformStatus", IANA_TYPE_US_ASCII, igsioCommon::ConvertToolStatusToString(status));
878  positionMessage->SetTimeStamp(igtlTime);
879  positionMessage->SetDeviceName(strTransformName.c_str());
880  positionMessage->Pack();
881 
882  return PLUS_SUCCESS;
883 }
884 
885 //----------------------------------------------------------------------------
886 PlusStatus vtkPlusIgtlMessageCommon::UnpackPositionMessage(igtl::MessageHeader::Pointer headerMsg,
887  igtl::Socket* socket,
888  vtkMatrix4x4* transformMatrix,
889  std::string& transformName,
890  ToolStatus& toolStatus,
891  double& timestamp,
892  int crccheck)
893 {
894  if (headerMsg.IsNull())
895  {
896  LOG_ERROR("Unable to unpack position message - header message is NULL!");
897  return PLUS_FAIL;
898  }
899 
900  if (socket == NULL)
901  {
902  LOG_ERROR("Unable to unpack position message - socket is NULL!");
903  return PLUS_FAIL;
904  }
905 
906  if (transformMatrix == NULL)
907  {
908  LOG_ERROR("Unable to unpack position message - transformMatrix is NULL!");
909  return PLUS_FAIL;
910  }
911 
912  igtl::PositionMessage::Pointer posMsg = dynamic_cast<igtl::PositionMessage*>(headerMsg.GetPointer());
913  if (posMsg.IsNull())
914  {
915  posMsg = igtl::PositionMessage::New();
916  }
917  posMsg->SetMessageHeader(headerMsg);
918  posMsg->AllocateBuffer();
919 
920  bool timeout(false);
921  socket->Receive(posMsg->GetBufferBodyPointer(), posMsg->GetBufferBodySize(), timeout);
922 
923  // If crccheck is specified it performs CRC check and unpack the data only if CRC passes
924  int c = posMsg->Unpack(crccheck);
925  if (!(c & igtl::MessageHeader::UNPACK_BODY))
926  {
927  LOG_ERROR("Couldn't receive position message from server!");
928  return PLUS_FAIL;
929  }
930 
931  // if CRC check is OK. Read position data.
932  float position[3] = {0};
933  posMsg->GetPosition(position);
934 
935  float quaternion[4] = {0, 0, 0, 1};
936  posMsg->GetQuaternion(quaternion);
937 
938  // Orientation
939  igtl::Matrix4x4 igtlMatrix;
940  igtl::IdentityMatrix(igtlMatrix);
941  igtl::QuaternionToMatrix(quaternion, igtlMatrix);
942 
943  // Position
944  transformMatrix->SetElement(0, 3, igtlMatrix[0][3]);
945  transformMatrix->SetElement(1, 3, igtlMatrix[1][3]);
946  transformMatrix->SetElement(2, 3, igtlMatrix[2][3]);
947 
948  // Status
949  std::string statusStr;
950  toolStatus = TOOL_UNKNOWN;
951  if (posMsg->GetMetaDataElement("Status", statusStr))
952  {
953  toolStatus = igsioCommon::ConvertStringToToolStatus(statusStr);
954  }
955  else
956  {
957  LOG_WARNING("Incoming POSITION message was received without a tool status. Defaulting to TOOL_OK.");
958  toolStatus = TOOL_OK;
959  }
960 
961  // Get timestamp
962  auto igtlTimestamp = igtl::TimeStamp::New();
963  posMsg->GetTimeStamp(igtlTimestamp);
964  timestamp = igtlTimestamp->GetTimeStamp();
965 
966  // Get transform name
967  transformName = posMsg->GetDeviceName();
968 
969  return PLUS_SUCCESS;
970 }
971 
972 //-------------------------------------------------------------------------------
973 PlusStatus vtkPlusIgtlMessageCommon::PackStringMessage(igtl::StringMessage::Pointer stringMessage,
974  const char* stringName,
975  const char* stringValue,
976  double timestamp)
977 {
978  if (stringMessage.IsNull())
979  {
980  LOG_ERROR("Failed to pack string message - input string message is NULL");
981  return PLUS_FAIL;
982  }
983 
984  auto igtlTime = igtl::TimeStamp::New();
985  igtlTime->SetTime(timestamp);
986 
987  stringMessage->SetString(stringValue); // assume default encoding
988  stringMessage->SetTimeStamp(igtlTime);
989  stringMessage->SetDeviceName(stringName);
990  stringMessage->Pack();
991 
992  return PLUS_SUCCESS;
993 }
994 
995 //----------------------------------------------------------------------------
996 PlusStatus vtkPlusIgtlMessageCommon::PackStringMessage(igtl::StringMessage::Pointer stringMessage, const std::string& stringName, const std::string& stringValue, double timestamp)
997 {
998  return PackStringMessage(stringMessage, stringName.c_str(), stringValue.c_str(), timestamp);
999 }
static PlusStatus PackImageMessage(igtl::ImageMessage::Pointer imageMessage, igsioTrackedFrame &trackedFrame, const vtkMatrix4x4 &imageToReferenceTransform, vtkIGSIOFrameConverter *frameConverter=NULL)
double * timestamp
Definition: phidget22.h:3432
Helper class for OpenIGTLink message generation.
static PlusStatus GetIgtlMatrix(igtl::Matrix4x4 &igtlMatrix, vtkIGSIOTransformRepository *transformRepository, igsioTransformName &transformName)
static PlusStatus UnpackTransformMessage(igtl::MessageHeader::Pointer headerMsg, igtl::Socket *socket, vtkMatrix4x4 *transformMatrix, ToolStatus &toolStatus, std::string &transformName, double &timestamp, int crccheck)
igsioStatus PlusStatus
Definition: PlusCommon.h:40
for i
static PlusStatus UnpackPositionMessage(igtl::MessageHeader::Pointer headerMsg, igtl::Socket *socket, vtkMatrix4x4 *transformMatrix, std::string &transformName, ToolStatus &toolStatus, double &timestamp, int crccheck)
#define PLUS_FAIL
Definition: PlusCommon.h:43
static PlusStatus PackTransformMessage(igtl::TransformMessage::Pointer transformMessage, igsioTransformName &transformName, igtl::Matrix4x4 &igtlMatrix, ToolStatus status, double timestamp)
static PlusStatus UnpackTrackedFrameMessage(igtl::MessageHeader::Pointer headerMsg, igtl::Socket *socket, igsioTrackedFrame &trackedFrame, const igsioTransformName &embeddedTransformName, int crccheck)
static PlusStatus PackPositionMessage(igtl::PositionMessage::Pointer positionMessage, igsioTransformName &transformName, ToolStatus status, float position[3], float quaternion[4], double timestamp)
static PlusStatus PackImageMetaMessage(igtl::ImageMetaMessage::Pointer imageMetaMessage, igsioCommon::ImageMetaDataList &imageMetaDataList)
static PlusStatus PackUsMessage(igtl::PlusUsMessage::Pointer usMessage, igsioTrackedFrame &trackedFrame)
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
vtkStandardNewMacro(vtkPlusIgtlMessageCommon)
static PlusStatus PackStringMessage(igtl::StringMessage::Pointer stringMessage, const char *stringName, const char *stringValue, double timestamp)
static PlusStatus PackTrackedFrameMessage(igtl::PlusTrackedFrameMessage::Pointer trackedFrameMessage, igsioTrackedFrame &trackedFrame, vtkSmartPointer< vtkMatrix4x4 > embeddedImageTransform, const std::vector< igsioTransformName > &requestedTransforms)
static PlusStatus UnpackImageMessage(igtl::MessageHeader::Pointer headerMsg, igtl::Socket *socket, igsioTrackedFrame &trackedFrame, const igsioTransformName &embeddedTransformName, int crccheck)
int VTKScalarPixelType
Definition: PlusCommon.h:55
double * position
Definition: phidget22.h:3303
static PlusStatus UnpackUsMessage(igtl::MessageHeader::Pointer headerMsg, igtl::Socket *socket, igsioTrackedFrame &trackedFrame, int crccheck)
static PlusStatus UnpackTrackingDataMessage(igtl::MessageHeader::Pointer headerMsg, igtl::Socket *socket, std::vector< igsioTransformName > &names, vtkIGSIOTransformRepository &repository, double &timestamp, int crccheck)
static PlusStatus PackTrackingDataMessage(igtl::TrackingDataMessage::Pointer tdataMessage, const std::vector< igsioTransformName > &names, const vtkIGSIOTransformRepository &repository, double timestamp)
static PlusStatus PackPolyDataMessage(igtl::PolyDataMessage::Pointer polydataMessage, vtkSmartPointer< vtkPolyData > polyData, double timestamp)