PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusMicronTracker.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 // TODO: need to evaluate if USE_MicronTracker_TIMESTAMPS without filtering
8 // is better then simply using accurate timestamp with filtering.
9 // E.g., it could be checked by performing temporal calibration.
10 // #define USE_MicronTracker_TIMESTAMPS
11 
12 // Local includes
13 #include "PlusConfigure.h"
14 #include "vtkPlusDataSource.h"
15 #include "vtkPlusMicronTracker.h"
16 
17 // Micron interface includes
18 #include <MicronTrackerInterface.h>
19 #include <MicronTrackerLogger.h>
20 
21 // VTK includes
22 #include <vtkImageData.h>
23 #include <vtkImageImport.h>
24 #include <vtkMatrix4x4.h>
25 #include <vtkNew.h>
26 #include <vtkObjectFactory.h>
27 
28 // STL includes
29 #include <fstream>
30 #include <iostream>
31 #include <set>
32 
33 // Note that "MTC.h" is not included directly, as it causes compilation warnings
34 // and unnecessary coupling to lower-level MTC functions.
35 // All MTC internal functions shall be accessed through MicronTrackerInterface.
36 
37 /****************************************************************************/
38 
40 
41 //----------------------------------------------------------------------------
43  : IsMicronTrackingInitialized(false)
44  , MicronTracker(new MicronTrackerInterface())
45 #ifdef USE_MicronTracker_TIMESTAMPS
46  , TrackerTimeToSystemTimeSec(0)
47  , TrackerTimeToSystemTimeComputed(false)
48 #endif
49  , IniFile("MicronTracker.ini")
50  , FrameLeft(vtkSmartPointer<vtkImageData>::New())
51  , FrameRight(vtkSmartPointer<vtkImageData>::New())
52 {
53  MicronTrackerLogger::Instance()->SetLogMessageCallback(LogMessageCallback, this);
54 
55  this->FrameNumber = 0;
57 
58  // No callback function provided by the device, so the data capture thread will be used to poll the hardware and add new items to the buffer
59  this->StartThreadForInternalUpdates = true;
60  this->AcquisitionRate = 20;
61 
62  this->FrameLeft = vtkSmartPointer<vtkImageData>::New();
63  this->FrameRight = vtkSmartPointer<vtkImageData>::New();
64  this->FrameSize[0] = 0;
65  this->FrameSize[1] = 0;
66  this->FrameSize[2] = 1;
67 }
68 
69 //----------------------------------------------------------------------------
71 {
73  {
74  this->MicronTracker->mtEnd();
75  this->IsMicronTrackingInitialized = false;
76  }
77 
78  delete this->MicronTracker;
79  this->MicronTracker = NULL;
80 }
81 
82 //----------------------------------------------------------------------------
84 {
85  return this->MicronTracker->GetSdkVersion();
86 }
87 
88 //----------------------------------------------------------------------------
90 {
92  {
93  LOG_ERROR("vtkPlusMicronTracker::Probe should not be called while the device is already initialized");
94  return PLUS_FAIL;
95  }
96 
97  std::string iniFilePath = vtkPlusConfig::GetInstance()->GetDeviceSetConfigurationPath(this->IniFile);
98  LOG_DEBUG("Use MicronTracker ini file: " << iniFilePath);
99  if (!vtksys::SystemTools::FileExists(iniFilePath.c_str(), true))
100  {
101  LOG_WARNING("Unable to find MicronTracker IniFile file at: " << iniFilePath);
102  }
103  std::string templateFullPath = vtkPlusConfig::GetInstance()->GetDeviceSetConfigurationPath(this->TemplateDirectory.c_str());
104  LOG_DEBUG("Loading the marker templates from " << templateFullPath);
105  if (!vtksys::SystemTools::FileExists(templateFullPath.c_str(), false))
106  {
107  LOG_WARNING("Unable to find MicronTracker TemplateDirectory at: " << templateFullPath);
108  }
109 
110  if (this->MicronTracker->mtInit(iniFilePath) != 1)
111  {
112  LOG_ERROR("Error in initializing Micron Tracker");
113  return PLUS_FAIL;
114  }
115 
116  // Try to attach the cameras till find the cameras
117  if (this->MicronTracker->mtSetupCameras() != 1)
118  {
119  LOG_ERROR("Error in initializing Micron Tracker: setup cameras failed. Check the camera connections.");
120  return PLUS_FAIL;
121  }
122 
123  int numOfCameras = this->MicronTracker->mtGetNumOfCameras();
124  if (numOfCameras == 0)
125  {
126  LOG_ERROR("Error in initializing Micron Tracker: no cameras attached. Check the camera connections.");
127  return PLUS_FAIL;
128  }
129 
130  LOG_DEBUG("Number of attached cameras: " << numOfCameras);
131 
132  this->MicronTracker->mtEnd();
133  this->IsMicronTrackingInitialized = false;
134 
135  return PLUS_SUCCESS;
136 }
137 
138 //----------------------------------------------------------------------------
140 {
141  if (!this->IsMicronTrackingInitialized)
142  {
143  LOG_ERROR("InternalStartRecording failed: MicronTracker has not been initialized");
144  return PLUS_FAIL;
145  }
146  return PLUS_SUCCESS;
147 }
148 
149 //----------------------------------------------------------------------------
151 {
152  if (!this->IsMicronTrackingInitialized)
153  {
154  LOG_ERROR("InternalUpdate failed: MicronTracker has not been initialized");
155  return PLUS_FAIL;
156  }
157 
158  // Setting the timestamp
159  const double unfilteredTimestamp = vtkIGSIOAccurateTimer::GetSystemTime();
160 
161  if (this->MicronTracker->mtGrabFrame() != 0) // mtOK
162  {
163  // If grabbing a frame was not successful then just skip this attempt and retry on the next callback
164  LOG_WARNING("Failed to grab a new frame (" << this->MicronTracker->GetLastErrorString() << "). Maybe the requested frame rate is too high.");
165  return PLUS_FAIL;
166  }
167 
168 #ifdef USE_MicronTracker_TIMESTAMPS
169  if (!this->TrackerTimeToSystemTimeComputed)
170  {
171  const double timeSystemSec = unfilteredTimestamp;
172  const double timeTrackerSec = this->MicronTracker->mtGetLatestFrameTime();
173  this->TrackerTimeToSystemTimeSec = timeSystemSec - timeTrackerSec;
174  this->TrackerTimeToSystemTimeComputed = true;
175  }
176  const double timeTrackerSec = this->MicronTracker->mtGetLatestFrameTime();
177  const double timeSystemSec = timeTrackerSec + this->TrackerTimeToSystemTimeSec;
178 #endif
179 
180  if (this->MicronTracker->mtProcessFrame() != 0) // mtOK
181  {
182  LOG_ERROR("Error in processing a frame! (" << this->MicronTracker->GetLastErrorString() << ")");
183  return PLUS_FAIL;
184  }
185 
186  this->MicronTracker->mtFindIdentifiedMarkers();
187 
188  // Generate a frame number, as the tool does not provide a frame number.
189  // FrameNumber will be used in ToolTimeStampedUpdate for timestamp filtering
190  ++this->FrameNumber;
191 
192  int numOfIdentifiedMarkers = this->MicronTracker->mtGetIdentifiedMarkersCount();
193  LOG_TRACE("Number of identified markers: " << numOfIdentifiedMarkers);
194 
195  // Set status and transform for tools with detected markers
196  std::set<std::string> identifiedToolSourceIds;
197  vtkNew<vtkMatrix4x4> toolToTracker;
198  for (int identifedMarkerIndex = 0; identifedMarkerIndex < numOfIdentifiedMarkers; identifedMarkerIndex++)
199  {
200  char* identifiedTemplateName = this->MicronTracker->mtGetIdentifiedTemplateName(identifedMarkerIndex);
201  vtkPlusDataSource* tool = NULL;
202  if (this->GetToolByPortName(identifiedTemplateName, tool) != PLUS_SUCCESS)
203  {
204  LOG_DEBUG("Marker " << identifiedTemplateName << " has no associated tool");
205  continue;
206  }
207 
208  this->GetTransformMatrix(identifedMarkerIndex, toolToTracker.GetPointer());
209 #ifdef USE_MicronTracker_TIMESTAMPS
210  this->ToolTimeStampedUpdateWithoutFiltering(tool->GetSourceId(), toolToTracker, TOOL_OK, timeSystemSec, timeSystemSec);
211 #else
212  this->ToolTimeStampedUpdate(tool->GetSourceId(), toolToTracker.GetPointer(), TOOL_OK, this->FrameNumber, unfilteredTimestamp);
213 #endif
214 
215  identifiedToolSourceIds.insert(tool->GetSourceId());
216  }
217 
218  // Set status for tools with non-detected markers
219  vtkNew<vtkMatrix4x4> transformMatrix;
220  for (DataSourceContainerConstIterator it = this->GetToolIteratorBegin(); it != this->GetToolIteratorEnd(); ++it)
221  {
222  if (identifiedToolSourceIds.find(it->second->GetSourceId()) != identifiedToolSourceIds.end())
223  {
224  // this tool has been found and update has been already called with the correct transform
225  LOG_TRACE("Tool " << it->second->GetSourceId() << ": found");
226  continue;
227  }
228  LOG_TRACE("Tool " << it->second->GetSourceId() << ": not found");
229 #ifdef USE_MicronTracker_TIMESTAMPS
230  ToolTimeStampedUpdateWithoutFiltering(it->second->GetSourceId(), transformMatrix, TOOL_OUT_OF_VIEW, timeSystemSec, timeSystemSec);
231 #else
232  ToolTimeStampedUpdate(it->second->GetSourceId(), transformMatrix.GetPointer(), TOOL_OUT_OF_VIEW, this->FrameNumber, unfilteredTimestamp);
233 #endif
234  }
235 
236  if (this->GetNumberOfVideoSources() > 0)
237  {
238  this->GetImage(this->FrameLeft, this->FrameRight);
239  vtkPlusDataSource* aSource(NULL);
240  for (int i = 0; i < this->GetNumberOfVideoSources(); ++i)
241  {
242  if (this->GetVideoSourceByIndex(i, aSource) != PLUS_SUCCESS)
243  {
244  LOG_ERROR("Failed to retrieve MicronTracker video source");
245  return PLUS_FAIL;
246  }
247  aSource->SetInputImageOrientation(US_IMG_ORIENT_MN);
248  aSource->SetInputFrameSize(this->FrameSize);
249  if (aSource->AddItem((i == 0) ? this->FrameLeft : this->FrameRight, US_IMG_ORIENT_MN, US_IMG_BRIGHTNESS, this->FrameNumber, unfilteredTimestamp) != PLUS_SUCCESS)
250  {
251  LOG_ERROR("Failed to add item " << i << " to MicronTracker video source");
252  return PLUS_FAIL;
253  }
254  this->Modified();
255  }
256  }
257 
258  return PLUS_SUCCESS;
259 }
260 
261 //----------------------------------------------------------------------------
263 {
264  std::vector<std::string> vTemplatesName;
265  std::vector<std::string> vTemplatesError;
266 
267  std::string templateFullPath = vtkPlusConfig::GetInstance()->GetDeviceSetConfigurationPath(this->TemplateDirectory.c_str());
268  LOG_DEBUG("Loading the marker templates from " << templateFullPath);
269  if (!vtksys::SystemTools::FileExists(templateFullPath.c_str(), false))
270  {
271  LOG_WARNING("Unable to find MicronTracker TemplateDirectory at: " << templateFullPath);
272  }
273  int callResult = this->MicronTracker->mtRefreshTemplates(vTemplatesName, vTemplatesError, templateFullPath);
274  for (unsigned int i = 0; i < vTemplatesName.size(); i++)
275  {
276  LOG_DEBUG("Loaded " << vTemplatesName[i]);
277  }
278  if (callResult != 0)
279  {
280  LOG_ERROR("Failed to load marker templates from " << templateFullPath);
281  for (unsigned int i = 0; i < vTemplatesError.size(); i++)
282  {
283  LOG_ERROR("Error loading template: " << vTemplatesError[i]);
284  }
285  return PLUS_FAIL;
286  }
287  return PLUS_SUCCESS;
288 }
289 
290 //----------------------------------------------------------------------------
291 void vtkPlusMicronTracker::GetTransformMatrix(int markerIndex, vtkMatrix4x4* transformMatrix)
292 {
293  std::vector<double> vRotMat;
294  this->MicronTracker->mtGetRotations(vRotMat, markerIndex);
295  std::vector<double> vPos;
296  this->MicronTracker->mtGetTranslations(vPos, markerIndex);
297 
298  transformMatrix->Identity();
299  int rotIndex = 0;
300  for (int col = 0; col < 3; col++)
301  {
302  for (int row = 0; row < 3; row++)
303  {
304  transformMatrix->SetElement(row, col, vRotMat[rotIndex++]);
305  }
306  }
307  // Add the offset to the last column of the transformation matrix
308  transformMatrix->SetElement(0, 3, vPos[0]);
309  transformMatrix->SetElement(1, 3, vPos[1]);
310  transformMatrix->SetElement(2, 3, vPos[2]);
311 }
312 
313 //----------------------------------------------------------------------------
314 PlusStatus vtkPlusMicronTracker::GetImage(vtkImageData* leftImage, vtkImageData* rightImage)
315 {
316  igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->UpdateMutex);
317 
318  unsigned char** leftImageArray = 0;
319  unsigned char** rightImageArray = 0;
320  if (this->MicronTracker->mtGetLeftRightImageArray(leftImageArray, rightImageArray) != 0) // mtOK
321  {
322  LOG_ERROR("Error getting images from MicronTracker");
323  return PLUS_FAIL;
324  }
325 
326  if (leftImage != NULL)
327  {
328  vtkSmartPointer<vtkImageImport> imageImport = vtkSmartPointer<vtkImageImport>::New();
329  imageImport->SetDataScalarTypeToUnsignedChar();
330  imageImport->SetImportVoidPointer((unsigned char*)leftImageArray);
331  imageImport->SetDataScalarTypeToUnsignedChar();
332  imageImport->SetDataExtent(0, this->FrameSize[0] - 1, 0, this->FrameSize[1] - 1, 0, 0);
333  imageImport->SetWholeExtent(0, this->FrameSize[0] - 1, 0, this->FrameSize[1] - 1, 0, 0);
334  imageImport->Update();
335  leftImage->DeepCopy(imageImport->GetOutput());
336  }
337 
338  if (rightImage != NULL)
339  {
340  vtkSmartPointer<vtkImageImport> imageImport = vtkSmartPointer<vtkImageImport>::New();
341  imageImport->SetDataScalarTypeToUnsignedChar();
342  imageImport->SetImportVoidPointer((unsigned char*)rightImageArray);
343  imageImport->SetDataScalarTypeToUnsignedChar();
344  imageImport->SetDataExtent(0, this->FrameSize[0] - 1, 0, this->FrameSize[1] - 1, 0, 0);
345  imageImport->SetWholeExtent(0, this->FrameSize[0] - 1, 0, this->FrameSize[1] - 1, 0, 0);
346  imageImport->Update();
347  rightImage->DeepCopy(imageImport->GetOutput());
348  }
349 
350  return PLUS_SUCCESS;
351 }
352 
353 //----------------------------------------------------------------------------
354 PlusStatus vtkPlusMicronTracker::ReadConfiguration(vtkXMLDataElement* rootConfigElement)
355 {
356  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement);
357 
358  XML_READ_STRING_ATTRIBUTE_OPTIONAL(TemplateDirectory, deviceConfig);
359  XML_READ_STRING_ATTRIBUTE_OPTIONAL(IniFile, deviceConfig);
360 
361  return PLUS_SUCCESS;
362 }
363 
364 //----------------------------------------------------------------------------
365 PlusStatus vtkPlusMicronTracker::WriteConfiguration(vtkXMLDataElement* rootConfigElement)
366 {
367  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(trackerConfig, rootConfigElement);
368 
369  XML_WRITE_STRING_ATTRIBUTE_IF_NOT_EMPTY(TemplateDirectory, trackerConfig);
370  XML_WRITE_STRING_ATTRIBUTE_IF_NOT_EMPTY(IniFile, trackerConfig);
371 
372  return PLUS_SUCCESS;
373 }
374 
375 //----------------------------------------------------------------------------
377 {
378  if (this->IsMicronTrackingInitialized)
379  {
380  LOG_DEBUG("Already connected to MicronTracker");
381  return PLUS_SUCCESS;
382  }
383 
384  std::string iniFilePath = vtkPlusConfig::GetInstance()->GetDeviceSetConfigurationPath(this->IniFile);
385  LOG_DEBUG("Use MicronTracker ini file: " << iniFilePath);
386  if (!vtksys::SystemTools::FileExists(iniFilePath.c_str(), true))
387  {
388  LOG_WARNING("Unable to find MicronTracker IniFile file at: " << iniFilePath);
389  }
390  std::string templateFullPath = vtkPlusConfig::GetInstance()->GetDeviceSetConfigurationPath(this->TemplateDirectory.c_str());
391  LOG_DEBUG("Loading the marker templates from " << templateFullPath);
392  if (!vtksys::SystemTools::FileExists(templateFullPath.c_str(), false))
393  {
394  LOG_ERROR("Unable to find MicronTracker TemplateDirectory at: " << templateFullPath);
395  }
396 
397  if (this->MicronTracker->mtInit(iniFilePath) != 1)
398  {
399  LOG_ERROR("Error in initializing Micron Tracker");
400  return PLUS_FAIL;
401  }
402 
403  // Try to attach the cameras till find the cameras
404  if (this->MicronTracker->mtSetupCameras() != 1)
405  {
406  LOG_ERROR("Error in initializing Micron Tracker: setup cameras failed. Check the camera connections and INI and Markers file locations.");
407  this->MicronTracker->mtEnd();
408  return PLUS_FAIL;
409  }
410 
411  int numOfCameras = this->MicronTracker->mtGetNumOfCameras();
412  if (numOfCameras == 0)
413  {
414  LOG_ERROR("Error in initializing Micron Tracker: no cameras attached. Check the camera connections and INI and Markers file locations.");
415  this->MicronTracker->mtEnd();
416  return PLUS_FAIL;
417  }
418  LOG_DEBUG("Number of attached cameras: " << numOfCameras);
419  for (int i = 0; i < numOfCameras; i++)
420  {
421  LOG_DEBUG("Camera " << i << ": "
422  << this->MicronTracker->mtGetXResolution(i) << "x" << this->MicronTracker->mtGetYResolution(i) << ", "
423  << this->MicronTracker->mtGetNumOfSensors(i) << " sensors "
424  << "(serial number: " << this->MicronTracker->mtGetSerialNum(i) << ")");
425  }
426 
428  {
429  LOG_ERROR("Error in initializing Micron Tracker: Failed to load marker templates. Check if the marker directory is set correctly.");
430  this->MicronTracker->mtEnd();
431  return PLUS_FAIL;
432  }
433 
434 #ifdef USE_MicronTracker_TIMESTAMPS
435  this->TrackerTimeToSystemTimeSec = 0;
436  this->TrackerTimeToSystemTimeComputed = false;
437 #endif
438 
439  int imageWidth = this->MicronTracker->mtGetXResolution(-1);
440  int imageHeight = this->MicronTracker->mtGetYResolution(-1);
441  if (imageWidth < 0 || imageHeight < 0)
442  {
443  LOG_ERROR("Invalid resolution returned from Micron device.");
444  return PLUS_FAIL;
445  }
446  this->FrameSize[0] = static_cast<unsigned int>(imageWidth);
447  this->FrameSize[1] = static_cast<unsigned int>(imageHeight);
448 
449  this->IsMicronTrackingInitialized = true;
450 
451  return PLUS_SUCCESS;
452 }
453 
454 //----------------------------------------------------------------------------
456 {
457  if (this->IsMicronTrackingInitialized)
458  {
459  this->MicronTracker->mtEnd();
460  this->IsMicronTrackingInitialized = false;
461  }
462  return PLUS_SUCCESS;
463 }
464 
465 //----------------------------------------------------------------------------
467 {
468  if (this->GetNumberOfVideoSources() > 0 && this->GetNumberOfVideoSources() != 2)
469  {
470  LOG_ERROR("Micron stereo camera capture requires exactly 2 video sources. Check configuration.");
471  return PLUS_FAIL;
472  }
473 
474  return PLUS_SUCCESS;
475 }
476 
477 //----------------------------------------------------------------------------
478 void vtkPlusMicronTracker::LogMessageCallback(int level, const char* message, void* /*userdata*/)
479 {
480  switch (level)
481  {
482  case MicronTrackerLogger::WARNING_LEVEL:
483  LOG_WARNING("MicronTracker: " << (message ? message : ""));
484  break;
485  case MicronTrackerLogger::DEBUG_LEVEL:
486  if (message)
487  {
488  LOG_DEBUG("MicronTracker: " << message);
489  }
490  break;
491  case MicronTrackerLogger::ERROR_LEVEL:
492  default:
493  LOG_ERROR("MicronTracker: " << (message ? message : ""));
494  break;
495  }
496 }
DataSourceContainer::const_iterator DataSourceContainerConstIterator
void GetTransformMatrix(int markerIndex, vtkMatrix4x4 *transformMatrix)
const char int const char const char Phidget_LogLevel level
Definition: phidget22.h:2458
vtkSmartPointer< vtkImageData > FrameRight
virtual int GetNumberOfVideoSources() const
vtkStandardNewMacro(vtkPlusMicronTracker)
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
virtual PlusStatus ToolTimeStampedUpdateWithoutFiltering(const std::string &aToolSourceId, vtkMatrix4x4 *matrix, ToolStatus status, double unfilteredtimestamp, double filteredtimestamp, const igsioFieldMapType *customFields=NULL)
std::string GetSourceId() const
igsioStatus PlusStatus
Definition: PlusCommon.h:40
PlusStatus GetVideoSourceByIndex(const unsigned int index, vtkPlusDataSource *&aVideoSource)
PlusStatus SetInputFrameSize(unsigned int x, unsigned int y, unsigned int z)
virtual PlusStatus ToolTimeStampedUpdate(const std::string &aToolSourceId, vtkMatrix4x4 *matrix, ToolStatus status, unsigned long frameNumber, double unfilteredtimestamp, const igsioFieldMapType *customFields=NULL)
virtual PlusStatus AddItem(vtkImageData *frame, US_IMAGE_ORIENTATION usImageOrientation, US_IMAGE_TYPE imageType, long frameNumber, double unfilteredTimestamp=UNDEFINED_TIMESTAMP, double filteredTimestamp=UNDEFINED_TIMESTAMP, const igsioFieldMapType *customFields=NULL)
bool RequirePortNameInDeviceSetConfiguration
for i
virtual PlusStatus InternalDisconnect()
double AcquisitionRate
PlusStatus GetImage(vtkImageData *leftImage, vtkImageData *rightImage)
#define PLUS_FAIL
Definition: PlusCommon.h:43
virtual PlusStatus SetInputImageOrientation(US_IMAGE_ORIENTATION imageOrientation)
static vtkPlusConfig * GetInstance()
Interface class to Claron MicronTracker optical trackers.
MicronTrackerInterface * MicronTracker
unsigned long FrameNumber
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
PlusStatus GetToolByPortName(const char *aPortName, vtkPlusDataSource *&aSource)
virtual PlusStatus NotifyConfigured()
vtkIGSIORecursiveCriticalSection * UpdateMutex
static void LogMessageCallback(int level, const char *message, void *userdata)
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement)
bool StartThreadForInternalUpdates
DataSourceContainerConstIterator GetToolIteratorBegin() const
virtual PlusStatus InternalConnect()
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *config)
std::string GetDeviceSetConfigurationPath(const std::string &subPath)
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *rootConfigElement)
const char * message
Definition: phidget22.h:2457
DataSourceContainerConstIterator GetToolIteratorEnd() const
virtual std::string GetSdkVersion()
vtkSmartPointer< vtkImageData > FrameLeft
Interface to a 3D positioning tool, video source, or generalized data stream.