PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusDevice.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 "vtkPlusBuffer.h"
10 #include "vtkPlusChannel.h"
11 #include "vtkPlusDataSource.h"
12 #include "vtkPlusDevice.h"
13 #include "vtkIGSIORecursiveCriticalSection.h"
14 #include "vtkPlusSequenceIO.h"
15 #include "vtkIGSIOTrackedFrameList.h"
16 
17 // VTK includes
18 #include <vtkImageData.h>
19 #include <vtkInformation.h>
20 #include <vtkInformationVector.h>
21 #include <vtkMatrix4x4.h>
22 #include <vtkMultiThreader.h>
23 #include <vtkObjectFactory.h>
24 #include <vtkStreamingDemandDrivenPipeline.h>
25 #include <vtkWindows.h>
26 #include <vtksys/SystemTools.hxx>
27 
28 // STD includes
29 #include <set>
30 
31 // System includes
32 #include <ctype.h>
33 #include <time.h>
34 
35 #if ( _MSC_VER >= 1300 ) // Visual studio .NET
36 #pragma warning ( disable : 4311 )
37 #pragma warning ( disable : 4312 )
38 #endif
39 
40 #define LOCAL_LOG_ERROR(msg) \
41 { \
42  std::ostringstream msgStream; \
43  if( this->DeviceId.empty() ) \
44  { \
45  msgStream << " " << msg << std::ends; \
46  } \
47  else \
48  { \
49  msgStream << this->DeviceId << ": " << msg << std::ends; \
50  } \
51  std::string finalStr(msgStream.str()); \
52  LOG_ERROR(finalStr); \
53 }
54 #define LOCAL_LOG_WARNING(msg) \
55 { \
56  std::ostringstream msgStream; \
57  if( this->DeviceId.empty() ) \
58 { \
59  msgStream << " " << msg << std::ends; \
60 } \
61  else \
62 { \
63  msgStream << this->DeviceId << ": " << msg << std::ends; \
64 } \
65  std::string finalStr(msgStream.str()); \
66  LOG_WARNING(finalStr); \
67 }
68 #define LOCAL_LOG_INFO(msg) \
69 { \
70  std::ostringstream msgStream; \
71  if( this->DeviceId.empty() ) \
72 { \
73  msgStream << " " << msg << std::ends; \
74 } \
75  else \
76 { \
77  msgStream << this->DeviceId << ": " << msg << std::ends; \
78 } \
79  std::string finalStr(msgStream.str()); \
80  LOG_INFO(finalStr); \
81 }
82 #define LOCAL_LOG_DEBUG(msg) \
83 { \
84  std::ostringstream msgStream; \
85  if( this->DeviceId.empty() ) \
86 { \
87  msgStream << " " << msg << std::ends; \
88 } \
89  else \
90 { \
91  msgStream << this->DeviceId << ": " << msg << std::ends; \
92 } \
93  std::string finalStr(msgStream.str()); \
94  LOG_DEBUG(finalStr); \
95 }
96 #define LOCAL_LOG_TRACE(msg) \
97 { \
98  std::ostringstream msgStream; \
99  if( this->DeviceId.empty() ) \
100 { \
101  msgStream << " " << msg << std::ends; \
102 } \
103  else \
104 { \
105  msgStream << this->DeviceId << ": " << msg << std::ends; \
106 } \
107  std::string finalStr(msgStream.str()); \
108  LOG_TRACE(finalStr); \
109 }
110 
111 //----------------------------------------------------------------------------
112 
114 
116 static const int FRAME_RATE_AVERAGING = 10;
117 const std::string vtkPlusDevice::BMODE_PORT_NAME = "B";
118 const std::string vtkPlusDevice::RFMODE_PORT_NAME = "Rf";
119 const std::string vtkPlusDevice::PARAMETERS_XML_ELEMENT_TAG = "Parameters";
120 const std::string vtkPlusDevice::PARAMETER_XML_ELEMENT_TAG = "Parameter";
121 
122 //----------------------------------------------------------------------------
124  : ThreadAlive(false)
125  , Connected(0)
126  , Threader(vtkMultiThreader::New())
127  , ThreadId(-1)
128  , CurrentStreamBufferItem(new StreamBufferItem())
129  , ToolReferenceFrameName("")
130  , DeviceId("")
131  , DataCollector(NULL)
132  , AcquisitionRate(30)
133  , Recording(0)
134  , DesiredTimestamp(-1)
135  , UpdateWithDesiredTimestamp(0)
136  , TimestampClosestToDesired(-1)
137  , FrameNumber(0)
138  , FrameTimeStamp(0)
139  , OutputNeedsInitialization(1)
140  , CorrectlyConfigured(true)
141  , StartThreadForInternalUpdates(false)
142  , LocalTimeOffsetSec(0.0)
143  , MissingInputGracePeriodSec(0.0)
144  , RequireImageOrientationInConfiguration(false)
145  , RequirePortNameInDeviceSetConfiguration(false)
146 {
147  this->SetNumberOfInputPorts(0);
148 
149  // For threaded capture of transformations
150  this->UpdateMutex = vtkIGSIORecursiveCriticalSection::New();
151 }
152 
153 //----------------------------------------------------------------------------
155 {
156  LOCAL_LOG_TRACE("vtkPlusDevice::~vtkPlusDevice()");
157  if (this->Connected)
158  {
159  Disconnect();
160  }
161 
162  for (ChannelContainerIterator it = this->OutputChannels.begin(); it != this->OutputChannels.end(); ++it)
163  {
164  (*it)->UnRegister(this);
165  }
166  this->InputChannels.clear();
167  this->OutputChannels.clear();
168  for (DataSourceContainerIterator it = this->Tools.begin(); it != this->Tools.end(); ++it)
169  {
170  it->second->UnRegister(this);
171  }
172  this->Tools.clear();
173  for (DataSourceContainerIterator it = this->Fields.begin(); it != this->Fields.end(); ++it)
174  {
175  it->second->UnRegister(this);
176  }
177  this->Fields.clear();
178  for (DataSourceContainerIterator it = this->VideoSources.begin(); it != this->VideoSources.end(); ++it)
179  {
180  it->second->UnRegister(this);
181  }
182  this->VideoSources.clear();
183 
184  delete this->CurrentStreamBufferItem;
185  this->CurrentStreamBufferItem = NULL;
186 
187  DELETE_IF_NOT_NULL(this->Threader);
188 
189  DELETE_IF_NOT_NULL(this->UpdateMutex);
190 
191  LOCAL_LOG_TRACE("vtkPlusDevice::~vtkPlusDevice() completed");
192 }
193 
194 //----------------------------------------------------------------------------
195 void vtkPlusDevice::PrintSelf(ostream& os, vtkIndent indent)
196 {
197  this->Superclass::PrintSelf(os, indent);
198 
199  os << indent << "Connected: " << (this->Connected ? "Yes\n" : "No\n");
200  os << indent << "SDK version: " << this->GetSdkVersion() << std::endl;
201  os << indent << "AcquisitionRate: " << this->AcquisitionRate << std::endl;
202  os << indent << "Recording: " << (this->Recording ? "On\n" : "Off\n");
203 
204  for (ChannelContainerConstIterator it = this->OutputChannels.begin(); it != this->OutputChannels.end(); ++it)
205  {
206  vtkPlusChannel* str = *it;
207  str->PrintSelf(os, indent);
208  }
209 
210  if (!this->ToolReferenceFrameName.empty())
211  {
212  os << indent << "ToolReferenceFrameName: " << this->ToolReferenceFrameName << "\n";
213  }
214 
215  for (DataSourceContainerConstIterator it = this->VideoSources.begin(); it != this->VideoSources.end(); ++it)
216  {
217  vtkPlusDataSource* dataSource = it->second;
218  dataSource->PrintSelf(os, indent);
219  }
220 
221  for (DataSourceContainerConstIterator it = this->Tools.begin(); it != this->Tools.end(); ++it)
222  {
223  vtkPlusDataSource* dataSource = it->second;
224  dataSource->PrintSelf(os, indent);
225  }
226 
227  for (DataSourceContainerConstIterator it = this->Fields.begin(); it != this->Fields.end(); ++it)
228  {
229  vtkPlusDataSource* dataSource = it->second;
230  dataSource->PrintSelf(os, indent);
231  }
232 
233  os << indent << PARAMETERS_XML_ELEMENT_TAG << std::endl;
234  for (std::map<std::string, std::string>::iterator it = this->Parameters.begin(); it != this->Parameters.end(); ++it)
235  {
236  os << indent << indent << it->first << ": " << it->second << std::endl;
237  }
238 }
239 
240 //----------------------------------------------------------------------------
242 {
243  // Base class version is the same as the Plus library version
244  std::string ver = std::string("Plus-") + std::string(PLUSLIB_VERSION);
245  return ver;
246 }
247 
248 //----------------------------------------------------------------------------
250 {
251  // By default, devices cannot be reset.
252  return false;
253 }
254 
255 //----------------------------------------------------------------------------
257 {
258  // By default, Reset has no effect.
259  return PLUS_SUCCESS;
260  this->Parameters.clear();
261 }
262 
263 //----------------------------------------------------------------------------
265 {
266  return this->Tools.begin();
267 }
268 
269 //----------------------------------------------------------------------------
271 {
272  return this->Tools.end();
273 }
274 
275 //----------------------------------------------------------------------------
277 {
278  return this->Tools.size();
279 }
280 
281 //----------------------------------------------------------------------------
282 PlusStatus vtkPlusDevice::AddTool(vtkPlusDataSource* tool, bool requireUniquePortName)
283 {
284  if (tool == NULL)
285  {
286  LOCAL_LOG_ERROR("Failed to add tool to tracker, tool is NULL!");
287  return PLUS_FAIL;
288  }
289 
290  if (tool->GetId().empty())
291  {
292  LOCAL_LOG_ERROR("Failed to add tool to tracker, tool source ID must be defined!");
293  return PLUS_FAIL;
294  }
295 
296  if (this->Tools.find(tool->GetId()) != this->GetToolIteratorEnd())
297  {
298  LOCAL_LOG_ERROR("Tool with ID '" << tool->GetId() << "' is already in the tool container!");
299  return PLUS_FAIL;
300  }
301 
302  if (requireUniquePortName && !tool->GetPortName().empty())
303  {
304  // Check tool port names, it should be unique too
305  for (DataSourceContainerConstIterator it = this->GetToolIteratorBegin(); it != this->GetToolIteratorEnd(); ++it)
306  {
307  if (it->second->GetPortName().empty())
308  {
309  continue;
310  }
311  if (tool->GetPortName() == it->second->GetPortName())
312  {
313  LOCAL_LOG_ERROR("Failed to add '" << tool->GetId() << "' tool to container: tool with name '" << it->second->GetId()
314  << "' is already defined on port '" << tool->GetPortName() << "'!");
315  return PLUS_FAIL;
316  }
317  }
318  }
319 
320  tool->Register(this);
321  tool->SetDevice(this);
322  this->Tools[tool->GetId()] = tool;
323 
324  return PLUS_SUCCESS;
325 }
326 
327 //----------------------------------------------------------------------------
328 PlusStatus vtkPlusDevice::GetFieldDataSource(const char* aSourceId, vtkPlusDataSource*& aSource) const
329 {
330  if (aSourceId == NULL)
331  {
332  LOCAL_LOG_ERROR("vtkPlusDevice::GetTool failed: aToolSourceId is invalid");
333  return PLUS_FAIL;
334  }
335 
336  return this->GetFieldDataSource(std::string(aSourceId), aSource);
337 }
338 
339 //----------------------------------------------------------------------------
340 PlusStatus vtkPlusDevice::GetFieldDataSource(const std::string& aSourceId, vtkPlusDataSource*& aSource) const
341 {
342  if (this->Fields.find(aSourceId) != this->Fields.end())
343  {
344  aSource = this->Fields.find(aSourceId)->second;
345  return PLUS_SUCCESS;
346  }
347 
348  return PLUS_FAIL;
349 }
350 
351 //----------------------------------------------------------------------------
353 {
354  return this->Fields.begin();
355 }
356 
357 //----------------------------------------------------------------------------
359 {
360  return this->Fields.end();
361 }
362 
363 //----------------------------------------------------------------------------
365 {
366  if (aSource == NULL)
367  {
368  LOCAL_LOG_ERROR("Failed to add field data source to device, source is NULL!");
369  return PLUS_FAIL;
370  }
371 
372  if (aSource->GetId().empty())
373  {
374  LOCAL_LOG_ERROR("Failed to add field data to device, field data source ID must be defined!");
375  return PLUS_FAIL;
376  }
377 
378  if (this->Fields.find(aSource->GetId()) != this->GetFieldDataSourcessIteratorEnd())
379  {
380  LOCAL_LOG_ERROR("Field data with ID '" << aSource->GetId() << "' is already in the field data container!");
381  return PLUS_FAIL;
382  }
383 
384  aSource->Register(this);
385  aSource->SetDevice(this);
386  this->Fields[aSource->GetId()] = aSource;
387 
388  return PLUS_SUCCESS;
389 }
390 
391 //----------------------------------------------------------------------------
393 {
394  return this->Fields.size();
395 }
396 
397 //----------------------------------------------------------------------------
399 {
400  if (this->Tools.size() == 0)
401  {
402  LOCAL_LOG_ERROR("Failed to get first active tool - there are no tools!");
403  return PLUS_FAIL;
404  }
405 
406  // Get the first tool
407  aTool = this->Tools.begin()->second;
408 
409  return PLUS_SUCCESS;
410 }
411 
412 //----------------------------------------------------------------------------
413 PlusStatus vtkPlusDevice::GetTool(const char* aToolSourceId, vtkPlusDataSource*& aTool) const
414 {
415  if (aToolSourceId == NULL)
416  {
417  LOCAL_LOG_ERROR("vtkPlusDevice::GetTool failed: aToolSourceId is invalid");
418  return PLUS_FAIL;
419  }
420 
421  if (this->Tools.find(aToolSourceId) != this->Tools.end())
422  {
423  aTool = this->Tools.find(aToolSourceId)->second;
424  return PLUS_SUCCESS;
425  }
426 
427  return PLUS_FAIL;
428 }
429 
430 //----------------------------------------------------------------------------
431 PlusStatus vtkPlusDevice::GetTool(const std::string& aToolSourceId, vtkPlusDataSource*& aTool) const
432 {
433  return this->GetTool(aToolSourceId.c_str(), aTool);
434 }
435 
436 //-----------------------------------------------------------------------------
438 {
439  if (portName == NULL)
440  {
441  LOCAL_LOG_ERROR("Failed to get tool - port name is NULL!");
442  return PLUS_FAIL;
443  }
444 
445  return this->GetToolByPortName(std::string(portName), aTool);
446 }
447 
448 //----------------------------------------------------------------------------
449 PlusStatus vtkPlusDevice::GetToolByPortName(const std::string& portName, vtkPlusDataSource*& aSource)
450 {
451  for (DataSourceContainerIterator it = this->Tools.begin(); it != this->Tools.end(); ++it)
452  {
453  if (portName == it->second->GetPortName())
454  {
455  aSource = it->second;
456  return PLUS_SUCCESS;
457  }
458  }
459 
460  return PLUS_FAIL;
461 }
462 
463 //-----------------------------------------------------------------------------
464 PlusStatus vtkPlusDevice::GetVideoSourcesByPortName(const char* aPortName, std::vector<vtkPlusDataSource*>& sources)
465 {
466  if (aPortName == NULL)
467  {
468  LOCAL_LOG_ERROR("Failed to get video source - port name is NULL!");
469  return PLUS_FAIL;
470  }
471 
472  return this->GetVideoSourcesByPortName(std::string(aPortName), sources);
473 }
474 
475 //----------------------------------------------------------------------------
476 PlusStatus vtkPlusDevice::GetVideoSourcesByPortName(const std::string& aPortName, std::vector<vtkPlusDataSource*>& sources)
477 {
478  sources.clear();
479 
480  for (DataSourceContainerIterator it = this->VideoSources.begin(); it != this->VideoSources.end(); ++it)
481  {
482  if (it->second->GetPortName().empty())
483  {
484  LOCAL_LOG_DEBUG("Port name is not defined for video source " << (!it->second->GetId().empty() ? it->second->GetId() : "unknown"));
485  continue;
486  }
487  if (aPortName == it->second->GetPortName())
488  {
489  sources.push_back(it->second);
490  }
491  }
492 
493  return PLUS_SUCCESS;
494 }
495 
496 //-----------------------------------------------------------------------------
498 {
499  LOCAL_LOG_TRACE("vtkPlusDevice::SetToolsBufferSize(" << aBufferSize << ")");
500  for (DataSourceContainerConstIterator it = this->GetToolIteratorBegin(); it != this->GetToolIteratorEnd(); ++it)
501  {
502  it->second->SetBufferSize(aBufferSize);
503  }
504 }
505 
506 //----------------------------------------------------------------------------
508 {
509  LOCAL_LOG_TRACE("vtkPlusDevice::SetFieldDataSourcesBufferSize(" << aBufferSize << ")");
511  {
512  it->second->SetBufferSize(aBufferSize);
513  }
514 }
515 
516 //----------------------------------------------------------------------------
517 void vtkPlusDevice::SetLocalTimeOffsetSec(double aTimeOffsetSec)
518 {
519  for (DataSourceContainerIterator it = this->VideoSources.begin(); it != this->VideoSources.end(); ++it)
520  {
521  vtkPlusDataSource* image = it->second;
522  image->SetLocalTimeOffsetSec(aTimeOffsetSec);
523  }
524  // local tools
525  for (DataSourceContainerIterator it = this->Tools.begin(); it != this->Tools.end(); ++it)
526  {
527  vtkPlusDataSource* tool = it->second;
528  tool->SetLocalTimeOffsetSec(aTimeOffsetSec);
529  }
530  this->LocalTimeOffsetSec = aTimeOffsetSec;
531 }
532 
533 //----------------------------------------------------------------------------
535 {
536  return this->LocalTimeOffsetSec;
537 }
538 
539 //----------------------------------------------------------------------------
541 {
542  return PLUS_SUCCESS;
543 }
544 
545 //----------------------------------------------------------------------------
546 PlusStatus vtkPlusDevice::GetInputDevices(std::vector<vtkPlusDevice*>& outDeviceList) const
547 {
548  for (ChannelContainerConstIterator iter = this->InputChannels.cbegin(); iter != this->InputChannels.cend(); ++iter)
549  {
550  const vtkPlusChannel* channel = *iter;
551  outDeviceList.push_back(channel->GetOwnerDevice());
552  }
553 
554  return PLUS_SUCCESS;
555 }
556 
557 //----------------------------------------------------------------------------
558 PlusStatus vtkPlusDevice::GetInputDevicesRecursive(std::vector<vtkPlusDevice*>& outDeviceList) const
559 {
560  for (auto it = this->InputChannels.begin(); it != this->InputChannels.end(); ++it)
561  {
562  (*it)->GetOwnerDevice()->GetInputDevicesRecursive(outDeviceList);
563  outDeviceList.push_back((*it)->GetOwnerDevice());
564  }
565 
566  return PLUS_SUCCESS;
567 }
568 
569 //----------------------------------------------------------------------------
570 PlusStatus vtkPlusDevice::SetParameter(const std::string& key, const std::string& value)
571 {
572  this->Parameters[key] = value;
573 
574  return PLUS_SUCCESS;
575 }
576 
577 //----------------------------------------------------------------------------
578 std::string vtkPlusDevice::GetParameter(const std::string& key) const
579 {
580  if (this->Parameters.find(key) != this->Parameters.end())
581  {
582  return this->Parameters.find(key)->second;
583  }
584 
585  return "";
586 }
587 
588 //----------------------------------------------------------------------------
589 PlusStatus vtkPlusDevice::GetParameter(const std::string& key, std::string& outValue) const
590 {
591  if (this->Parameters.find(key) != this->Parameters.end())
592  {
593  outValue = this->Parameters.find(key)->second;
594  return PLUS_SUCCESS;
595  }
596 
597  return PLUS_FAIL;
598 }
599 
600 //-----------------------------------------------------------------------------
602 {
603  this->ThreadAlive = false;
604  this->Connected = device.GetConnected();
606  this->DeviceId = device.GetDeviceId() + "_Copy";
608  this->LocalTimeOffsetSec = device.GetLocalTimeOffsetSec();
612  this->Parameters = device.Parameters;
613  // Don't set data collector, because that will be done if the copied device is added to a data collector
614 
615  // VTK functions aren't const clean, this is necessary =/
616  vtkPlusDevice* ewwwwDevice = const_cast<vtkPlusDevice*>(&device);
617  this->SetNumberOfInputPorts(ewwwwDevice->GetNumberOfInputPorts());
618 
619  LOCAL_LOG_TRACE("vtkPlusDevice::DeepCopy");
620  for (DataSourceContainerConstIterator it = device.Tools.begin(); it != device.Tools.end(); ++it)
621  {
622  LOCAL_LOG_DEBUG("Copy the buffer of tracker tool: " << it->first);
623  if (this->AddTool(it->second, false) != PLUS_SUCCESS)
624  {
625  LOCAL_LOG_ERROR("Copy of tool '" << it->first << "' failed - unable to add tool to the container!");
626  continue;
627  }
628 
629  vtkPlusDataSource* tool = NULL;
630  if (this->GetTool(it->first.c_str(), tool) != PLUS_SUCCESS)
631  {
632  LOCAL_LOG_ERROR("Copy of tool '" << it->first << "' failed - unable to get tool from container!");
633  continue;
634  }
635 
636  tool->DeepCopy(*it->second);
637  }
638 
639  for (DataSourceContainerConstIterator it = device.Fields.begin(); it != device.Fields.end(); ++it)
640  {
641  LOCAL_LOG_DEBUG("Copy the buffer of field data source: " << it->first);
642  if (this->AddFieldDataSource(it->second) != PLUS_SUCCESS)
643  {
644  LOCAL_LOG_ERROR("Copy of field data source '" << it->first << "' failed - unable to add field data source to the container!");
645  continue;
646  }
647 
648  vtkPlusDataSource* aSource = NULL;
649  if (this->GetFieldDataSource(it->first.c_str(), aSource) != PLUS_SUCCESS)
650  {
651  LOCAL_LOG_ERROR("Copy of field data source '" << it->first << "' failed - unable to get field data source from container!");
652  continue;
653  }
654 
655  aSource->DeepCopy(*it->second);
656  }
657 
658  this->InternalUpdateRate = device.GetInternalUpdateRate();
659  this->SetAcquisitionRate(device.GetAcquisitionRate());
660 }
661 
662 //-----------------------------------------------------------------------------
664 {
665  return this->InternalUpdateRate;
666 }
667 
668 //-----------------------------------------------------------------------------
670 {
671  LOCAL_LOG_TRACE("vtkPlusDevice::SetAcquisitionRate(" << aRate << ")");
672 
673  if (this->AcquisitionRate == aRate)
674  {
675  return PLUS_SUCCESS;
676  }
677 
678  this->AcquisitionRate = aRate;
679  this->Modified();
680 
681  return PLUS_SUCCESS;
682 }
683 
684 //----------------------------------------------------------------------------
686 {
687  return (this->Recording != 0);
688 }
689 
690 //----------------------------------------------------------------------------
691 std::string vtkPlusDevice::GetDeviceId() const
692 {
693  return this->DeviceId;
694 }
695 
696 //----------------------------------------------------------------------------
697 void vtkPlusDevice::SetDeviceId(const std::string& id)
698 {
699  this->DeviceId = id;
700 }
701 
702 //----------------------------------------------------------------------------
703 unsigned long vtkPlusDevice::GetFrameNumber() const
704 {
705  return this->FrameNumber;
706 }
707 
708 //----------------------------------------------------------------------------
710 {
711  return this->FrameTimeStamp;
712 }
713 
714 //----------------------------------------------------------------------------
715 PlusStatus vtkPlusDevice::WriteToolsToSequenceFile(const std::string& filename, bool useCompression /*= false*/)
716 {
717  LOCAL_LOG_TRACE("vtkPlusDevice::WriteToolsToSequenceFile: " << filename);
718 
719  if (this->GetNumberOfTools() == 0)
720  {
721  LOCAL_LOG_ERROR("Failed to write tracker to metafile - there are no active tools!");
722  return PLUS_FAIL;
723  }
724 
725  // Get the number of items from buffers and use the lowest
726  int numberOfItems(-1);
727  for (DataSourceContainerConstIterator it = this->Tools.begin(); it != this->Tools.end(); ++it)
728  {
729  if (numberOfItems < 0 || numberOfItems > it->second->GetNumberOfItems())
730  {
731  numberOfItems = it->second->GetNumberOfItems();
732  }
733  }
734 
735  vtkSmartPointer<vtkIGSIOTrackedFrameList> trackedFrameList = vtkSmartPointer<vtkIGSIOTrackedFrameList>::New();
736 
737  PlusStatus status = PLUS_SUCCESS;
738 
739  // Get the first source
740  vtkPlusDataSource* firstActiveTool = this->Tools.begin()->second;
741 
742  for (int i = 0 ; i < numberOfItems; i++)
743  {
744  // Create fake image
745  igsioTrackedFrame trackedFrame;
746  igsioVideoFrame videoFrame;
747  FrameSizeType frameSize = {1, 1, 1};
748  // Don't waste space, create a greyscale image
749  videoFrame.AllocateFrame(frameSize, VTK_UNSIGNED_CHAR, 1);
750  trackedFrame.SetImageData(videoFrame);
751 
752  StreamBufferItem bufferItem;
753  BufferItemUidType uid = firstActiveTool->GetOldestItemUidInBuffer() + i;
754 
755  if (firstActiveTool->GetStreamBufferItem(uid, &bufferItem) != ITEM_OK)
756  {
757  LOCAL_LOG_ERROR("Failed to get tracker buffer item with UID: " << uid);
758  continue;
759  }
760 
761  const double frameTimestamp = bufferItem.GetFilteredTimestamp(firstActiveTool->GetLocalTimeOffsetSec());
762 
763  // Add main source timestamp
764  std::ostringstream timestampFieldValue;
765  timestampFieldValue << std::fixed << frameTimestamp;
766  trackedFrame.SetFrameField("Timestamp", timestampFieldValue.str());
767 
768  // Add main source unfiltered timestamp
769  std::ostringstream unfilteredtimestampFieldValue;
770  unfilteredtimestampFieldValue << std::fixed << bufferItem.GetUnfilteredTimestamp(firstActiveTool->GetLocalTimeOffsetSec());
771  trackedFrame.SetFrameField("UnfilteredTimestamp", unfilteredtimestampFieldValue.str());
772 
773  // Add main source frameNumber
774  std::ostringstream frameNumberFieldValue;
775  frameNumberFieldValue << std::fixed << bufferItem.GetIndex();
776  trackedFrame.SetFrameField("FrameNumber", frameNumberFieldValue.str());
777 
778  // Add transforms
779  for (DataSourceContainerConstIterator it = this->Tools.begin(); it != this->Tools.end(); ++it)
780  {
781  StreamBufferItem toolBufferItem;
782  if (it->second->GetStreamBufferItemFromTime(frameTimestamp, &toolBufferItem, vtkPlusBuffer::EXACT_TIME) != ITEM_OK)
783  {
784  LOCAL_LOG_ERROR("Failed to get tracker buffer item from time: " << std::fixed << frameTimestamp);
785  continue;
786  }
787 
788  vtkSmartPointer<vtkMatrix4x4> toolMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
789  if (toolBufferItem.GetMatrix(toolMatrix) != PLUS_SUCCESS)
790  {
791  LOCAL_LOG_ERROR("Failed to get toolMatrix");
792  return PLUS_FAIL;
793  }
794 
795  igsioTransformName toolToTrackerTransform(it->second->GetId(), this->ToolReferenceFrameName);
796  trackedFrame.SetFrameTransform(toolToTrackerTransform, toolMatrix);
797 
798  // Add source status
799  trackedFrame.SetFrameTransformStatus(toolToTrackerTransform, toolBufferItem.GetStatus());
800  }
801 
802  // Add tracked frame to the list
803  // This is a debugging/test function, so the additional copying in AddTrackedFrame compared to TakeTrackedFrame is not relevant.
804  trackedFrameList->AddTrackedFrame(&trackedFrame);
805  }
806 
807  // Save tracked frames to metafile
808  if (vtkPlusSequenceIO::Write(filename, trackedFrameList, trackedFrameList->GetImageOrientation(), useCompression) != PLUS_SUCCESS)
809  {
810  LOCAL_LOG_ERROR("Failed to save tracked frames to sequence metafile!");
811  return PLUS_FAIL;
812  }
813 
814  return status;
815 }
816 
817 //----------------------------------------------------------------------------
818 void vtkPlusDevice::SetToolReferenceFrameName(const std::string& frameName)
819 {
820  this->ToolReferenceFrameName = frameName;
821 }
822 
823 //----------------------------------------------------------------------------
825 {
826  return this->ToolReferenceFrameName;
827 }
828 
829 //----------------------------------------------------------------------------
831 {
832  return this->CorrectlyConfigured;
833 }
834 
835 //----------------------------------------------------------------------------
836 vtkXMLDataElement* vtkPlusDevice::FindThisDeviceElement(vtkXMLDataElement* rootXMLElement)
837 {
838  if (rootXMLElement == NULL)
839  {
840  LOCAL_LOG_ERROR("Unable to find device XML element for this device.");
841  return NULL;
842  }
843 
844  vtkXMLDataElement* dataCollectionElement = rootXMLElement->FindNestedElementWithName("DataCollection");
845  if (dataCollectionElement == NULL)
846  {
847  LOCAL_LOG_ERROR("Unable to find data collection element in XML tree!");
848  return NULL;
849  }
850 
851  vtkXMLDataElement* deviceXMLElement = NULL;
852  for (int i = 0; i < dataCollectionElement->GetNumberOfNestedElements(); ++i)
853  {
854  deviceXMLElement = dataCollectionElement->GetNestedElement(i);
855 
856  if (deviceXMLElement->GetName() != NULL &&
857  deviceXMLElement->GetAttribute("Id") != NULL &&
858  std::string(deviceXMLElement->GetName()) == "Device" &&
859  std::string(deviceXMLElement->GetAttribute("Id")) == this->GetDeviceId())
860  {
861  return deviceXMLElement;
862  }
863  }
864 
865  return NULL;
866 }
867 
868 //----------------------------------------------------------------------------
869 vtkXMLDataElement* vtkPlusDevice::FindOutputChannelElement(vtkXMLDataElement* rootXMLElement, const char* aChannelId)
870 {
871  if (rootXMLElement == NULL || aChannelId == NULL)
872  {
873  LOCAL_LOG_ERROR("Unable to find XML element for this channel. Bad inputs.");
874  return NULL;
875  }
876 
877  vtkXMLDataElement* deviceXMLElement = this->FindThisDeviceElement(rootXMLElement);
878 
879  vtkXMLDataElement* outputChannelsElement = deviceXMLElement->FindNestedElementWithName("OutputChannels");
880  if (outputChannelsElement != NULL)
881  {
882  for (int i = 0; i < outputChannelsElement->GetNumberOfNestedElements(); ++i)
883  {
884  vtkXMLDataElement* anXMLElement = outputChannelsElement->GetNestedElement(i);
885 
886  if (anXMLElement->GetName() != NULL &&
887  anXMLElement->GetAttribute("Id") != NULL &&
888  STRCASECMP(anXMLElement->GetName(), "OutputChannel") == 0 &&
889  STRCASECMP(anXMLElement->GetAttribute("Id"), aChannelId) == 0)
890  {
891  return anXMLElement;
892  }
893  }
894  }
895 
896  return NULL;
897 }
898 
899 //----------------------------------------------------------------------------
900 vtkXMLDataElement* vtkPlusDevice::FindInputChannelElement(vtkXMLDataElement* rootXMLElement, const char* aChannelId)
901 {
902  if (rootXMLElement == NULL || aChannelId == NULL)
903  {
904  LOCAL_LOG_ERROR("Unable to find XML element for this channel. Bad inputs.");
905  return NULL;
906  }
907 
908  vtkXMLDataElement* deviceXMLElement = this->FindThisDeviceElement(rootXMLElement);
909 
910  vtkXMLDataElement* inputChannelsElement = deviceXMLElement->FindNestedElementWithName("InputChannels");
911  if (inputChannelsElement != NULL)
912  {
913  for (int i = 0; i < inputChannelsElement->GetNumberOfNestedElements(); ++i)
914  {
915  vtkXMLDataElement* anXMLElement = inputChannelsElement->GetNestedElement(i);
916 
917  if (anXMLElement->GetName() != NULL && anXMLElement->GetAttribute("Id") != NULL &&
918  STRCASECMP(anXMLElement->GetName(), "InputChannel") == 0 && STRCASECMP(anXMLElement->GetAttribute("Id"), aChannelId) == 0)
919  {
920  return anXMLElement;
921  }
922  }
923  }
924 
925  return NULL;
926 }
927 
928 //-----------------------------------------------------------------------------
929 PlusStatus vtkPlusDevice::ReadConfiguration(vtkXMLDataElement* rootXMLElement)
930 {
931  LOCAL_LOG_TRACE("vtkPlusDevice::ReadConfiguration");
932 
933  if (rootXMLElement == NULL)
934  {
935  LOCAL_LOG_ERROR("Unable to find device XML element for this device.");
936  return PLUS_FAIL;
937  }
938 
939  vtkXMLDataElement* deviceXMLElement = this->FindThisDeviceElement(rootXMLElement);
940 
941  if (deviceXMLElement == NULL)
942  {
943  LOCAL_LOG_ERROR("Unable to find device XML element for device");
944  return PLUS_FAIL;
945  }
946 
947  // Continue with device configuration
948  const char* referenceName = deviceXMLElement->GetAttribute("ToolReferenceFrame");
949  if (referenceName != NULL)
950  {
951  this->SetToolReferenceFrameName(referenceName);
952  }
953  else
954  {
955  this->SetToolReferenceFrameName(this->GetDeviceId());
956  if (this->IsTracker())
957  {
958  LOCAL_LOG_WARNING("ToolReferenceFrame is undefined. Default \"" << (this->GetToolReferenceFrameName().empty() ? this->GetToolReferenceFrameName() : "(undefined)") << "\" will be used.");
959  }
960  }
961 
962  if (deviceXMLElement->GetAttribute("MissingInputGracePeriodSec") != NULL)
963  {
964  deviceXMLElement->GetScalarAttribute("MissingInputGracePeriodSec", this->MissingInputGracePeriodSec);
965  }
966 
967  vtkXMLDataElement* dataSourcesElement = deviceXMLElement->FindNestedElementWithName("DataSources");
968  if (dataSourcesElement != NULL)
969  {
970  // Read source configurations
971  for (int source = 0; source < dataSourcesElement->GetNumberOfNestedElements(); source++)
972  {
973  vtkXMLDataElement* dataSourceElement = dataSourcesElement->GetNestedElement(source);
974 
975  if (STRCASECMP(dataSourceElement->GetName(), "DataSource") != 0)
976  {
977  // if this is not a Tool element, skip it
978  continue;
979  }
980 
981  std::string sourceId = dataSourceElement->GetAttribute("Id") != NULL ? dataSourceElement->GetAttribute("Id") : "";
982  if (sourceId.empty())
983  {
984  LOG_ERROR("Unable to find attribute \"Id\"! \"Id\" attribute is mandatory in source definition. Skipping.");
985  continue;
986  }
987 
988  if (this->IsTracker() && sourceId == this->ToolReferenceFrameName)
989  {
990  LOG_ERROR("Data source \"" << this->ToolReferenceFrameName << "\" cannot have same name as the ToolReferenceFrameName. Skipping.");
991  continue;
992  }
993 
994  if (this->EnsureUniqueDataSourceId(sourceId) == PLUS_FAIL)
995  {
996  LOG_ERROR("Data source name \"" << sourceId << "\" is not unique. Skipping.");
997  continue;
998  }
999 
1000  vtkSmartPointer<vtkPlusDataSource> aDataSource = vtkSmartPointer<vtkPlusDataSource>::New();
1001  bool isEqual(false);
1002  if (igsioCommon::XML::SafeCheckAttributeValueInsensitive(*dataSourceElement, "Type", vtkPlusDataSource::DATA_SOURCE_TYPE_TOOL_TAG, isEqual) == PLUS_SUCCESS && isEqual)
1003  {
1004  aDataSource->SetReferenceCoordinateFrameName(this->ToolReferenceFrameName);
1005 
1006  if (aDataSource->ReadConfiguration(dataSourceElement, this->RequirePortNameInDeviceSetConfiguration, this->RequireImageOrientationInConfiguration, this->GetDeviceId()) != PLUS_SUCCESS)
1007  {
1008  LOCAL_LOG_ERROR("Unable to add tool to tracker - failed to read tool configuration");
1009  continue;
1010  }
1011 
1012  if (this->AddTool(aDataSource) != PLUS_SUCCESS)
1013  {
1014  LOCAL_LOG_ERROR("Failed to add tool '" << (!aDataSource->GetId().empty() ? aDataSource->GetId() : "(unspecified)") << "' to device on port " << (!aDataSource->GetPortName().empty() ? aDataSource->GetPortName() : "(unspecified)"));
1015  }
1016  }
1017  else if (igsioCommon::XML::SafeCheckAttributeValueInsensitive(*dataSourceElement, "Type", vtkPlusDataSource::DATA_SOURCE_TYPE_FIELDDATA_TAG, isEqual) == PLUS_SUCCESS && isEqual)
1018  {
1019  if (aDataSource->ReadConfiguration(dataSourceElement, this->RequirePortNameInDeviceSetConfiguration, this->RequireImageOrientationInConfiguration, this->GetDeviceId()) != PLUS_SUCCESS)
1020  {
1021  LOCAL_LOG_ERROR("Unable to add field data source to device - failed to read field data source configuration");
1022  continue;
1023  }
1024 
1025  if (this->AddFieldDataSource(aDataSource) != PLUS_SUCCESS)
1026  {
1027  LOCAL_LOG_ERROR("Failed to add field data source '" << (!aDataSource->GetId().empty() ? aDataSource->GetId() : "(unspecified)") << "' to device.");
1028  }
1029  }
1030  else if (igsioCommon::XML::SafeCheckAttributeValueInsensitive(*dataSourceElement, "Type", vtkPlusDataSource::DATA_SOURCE_TYPE_VIDEO_TAG, isEqual) == PLUS_SUCCESS && isEqual)
1031  {
1032  aDataSource->ReadConfiguration(dataSourceElement, this->RequirePortNameInDeviceSetConfiguration, this->RequireImageOrientationInConfiguration, this->GetDeviceId());
1033 
1034  if (this->AddVideoSource(aDataSource) != PLUS_SUCCESS)
1035  {
1036  LOCAL_LOG_ERROR("Failed to add video source '" << (!aDataSource->GetId().empty() ? aDataSource->GetId() : "(unspecified)") << "' to device.");
1037  }
1038  }
1039  }
1040  }
1041 
1042  // Continue with device configuration
1043  double acquisitionRate = 0;
1044  if (deviceXMLElement->GetScalarAttribute("AcquisitionRate", acquisitionRate))
1045  {
1046  this->SetAcquisitionRate(acquisitionRate);
1047  }
1048  else
1049  {
1050  LOCAL_LOG_DEBUG("Unable to find acquisition rate in device element when it is required, using default " << this->GetAcquisitionRate());
1051  }
1052 
1053  vtkXMLDataElement* outputChannelsElement = deviceXMLElement->FindNestedElementWithName("OutputChannels");
1054  if (outputChannelsElement != NULL)
1055  {
1056  // Now that we have the tools and images, we can create the output streams and connect things as necessary
1057  for (int channel = 0; channel < outputChannelsElement->GetNumberOfNestedElements(); channel++)
1058  {
1059  vtkXMLDataElement* channelElement = outputChannelsElement->GetNestedElement(channel);
1060  if (STRCASECMP(channelElement->GetName(), "OutputChannel") != 0)
1061  {
1062  // if this is not a channel element, skip it
1063  continue;
1064  }
1065 
1066  if (channelElement->GetAttribute("Id") == NULL)
1067  {
1068  LOCAL_LOG_ERROR("No channel Id present. Skipping channel configuration.");
1069  continue;
1070  }
1071 
1072  bool skip(false);
1073  for (ChannelContainerIterator it = this->OutputChannels.begin(); it != this->OutputChannels.end(); ++it)
1074  {
1075  if (STRCASECMP((*it)->GetChannelId(), channelElement->GetAttribute("Id")) == 0)
1076  {
1077  LOCAL_LOG_ERROR("Channel with duplicate channel Id \'" << (*it)->GetChannelId() << "\'. Skipping channel configuration.");
1078  skip = true;
1079  break;
1080  }
1081  }
1082  if (skip)
1083  {
1084  continue;
1085  }
1086 
1087  vtkSmartPointer<vtkPlusChannel> aChannel = vtkSmartPointer<vtkPlusChannel>::New();
1088  aChannel->SetOwnerDevice(this);
1089  aChannel->ReadConfiguration(channelElement, this->RequireImageOrientationInConfiguration);
1090  AddOutputChannel(aChannel);
1091  }
1092  }
1093 
1094  double localTimeOffsetSec = 0;
1095  if (deviceXMLElement->GetScalarAttribute("LocalTimeOffsetSec", localTimeOffsetSec))
1096  {
1097  // DeviceId is never null, if it is, there is memory stomping occurring elsewhere
1098  LOCAL_LOG_INFO("Local time offset: " << 1000 * localTimeOffsetSec << "ms");
1099  this->SetLocalTimeOffsetSec(localTimeOffsetSec);
1100  }
1101  else
1102  {
1103  LOCAL_LOG_DEBUG("Local time offset was not defined in device configuration");
1104  }
1105 
1106  // Parameter reading
1107  XML_FIND_NESTED_ELEMENT_OPTIONAL(parametersElem, deviceXMLElement, vtkPlusDevice::PARAMETERS_XML_ELEMENT_TAG.c_str());
1108  if (parametersElem)
1109  {
1110  for (int i = 0; i < parametersElem->GetNumberOfNestedElements(); ++i)
1111  {
1112  vtkXMLDataElement* element = parametersElem->GetNestedElement(i);
1113  if (!igsioCommon::IsEqualInsensitive(element->GetName(), PARAMETER_XML_ELEMENT_TAG))
1114  {
1115  // Not a Parameter tag, skip
1116  continue;
1117  }
1118 
1119  std::string name = element->GetAttribute("name") ? element->GetAttribute("name") : "";
1120  std::string value = element->GetAttribute("value") ? element->GetAttribute("value") : "";
1121  if (name.empty())
1122  {
1123  continue;
1124  }
1125 
1126  this->Parameters[name] = value;
1127  }
1128 
1129  return PLUS_SUCCESS;
1130  }
1131 
1132  return PLUS_SUCCESS;
1133 }
1134 
1135 //----------------------------------------------------------------------------
1137 {
1138  if (config == NULL)
1139  {
1140  LOCAL_LOG_ERROR("Unable to write configuration: xml data element is NULL!");
1141  return PLUS_FAIL;
1142  }
1143 
1144  vtkXMLDataElement* deviceDataElement = this->FindThisDeviceElement(config);
1145 
1146  if (deviceDataElement == NULL)
1147  {
1148  LOCAL_LOG_ERROR("Unable to write configuration: xml data element is NULL!");
1149  return PLUS_FAIL;
1150  }
1151 
1152  vtkXMLDataElement* dataSourcesElement = deviceDataElement->FindNestedElementWithName("DataSources");
1153  if (dataSourcesElement != NULL)
1154  {
1155  for (int i = 0; i < dataSourcesElement->GetNumberOfNestedElements(); i++)
1156  {
1157  vtkXMLDataElement* dataSourceElement = dataSourcesElement->GetNestedElement(i);
1158  if (STRCASECMP(dataSourceElement->GetName(), "DataSource") != 0)
1159  {
1160  // if this is not a data source element, skip it
1161  continue;
1162  }
1163  vtkPlusDataSource* aDataSource = NULL;
1164  bool isEqual(false);
1165  if (igsioCommon::XML::SafeCheckAttributeValueInsensitive(*dataSourceElement, "Type", vtkPlusDataSource::DATA_SOURCE_TYPE_TOOL_TAG, isEqual) == PLUS_SUCCESS && isEqual)
1166  {
1167  igsioTransformName toolId(dataSourceElement->GetAttribute("Id"), this->GetToolReferenceFrameName());
1168  if (dataSourceElement->GetAttribute("Id") == NULL || this->GetTool(toolId.GetTransformName(), aDataSource) != PLUS_SUCCESS)
1169  {
1170  LOCAL_LOG_ERROR("Unable to retrieve tool when saving config.");
1171  return PLUS_FAIL;
1172  }
1173  aDataSource->WriteConfiguration(dataSourceElement);
1174  }
1175  else if (igsioCommon::XML::SafeCheckAttributeValueInsensitive(*dataSourceElement, "Type", vtkPlusDataSource::DATA_SOURCE_TYPE_FIELDDATA_TAG, isEqual) == PLUS_SUCCESS && isEqual)
1176  {
1177  if (dataSourceElement->GetAttribute("Id") == NULL || this->GetFieldDataSource(dataSourceElement->GetAttribute("Id"), aDataSource) != PLUS_SUCCESS)
1178  {
1179  LOCAL_LOG_ERROR("Unable to retrieve field data source when saving config.");
1180  return PLUS_FAIL;
1181  }
1182  aDataSource->WriteConfiguration(dataSourceElement);
1183  }
1184  else if (igsioCommon::XML::SafeCheckAttributeValueInsensitive(*dataSourceElement, "Type", vtkPlusDataSource::DATA_SOURCE_TYPE_VIDEO_TAG, isEqual) == PLUS_SUCCESS && isEqual)
1185  {
1186  if (dataSourceElement->GetAttribute("Id") == NULL || this->GetVideoSource(dataSourceElement->GetAttribute("Id"), aDataSource) != PLUS_SUCCESS)
1187  {
1188  LOCAL_LOG_ERROR("Unable to retrieve video source when saving config.");
1189  return PLUS_FAIL;
1190  }
1191  aDataSource->WriteConfiguration(dataSourceElement);
1192  }
1193  }
1194  }
1195 
1196  this->InternalWriteOutputChannels(config);
1197  this->InternalWriteInputChannels(config);
1198 
1199  if (this->GetLocalTimeOffsetSec() != 0.0)
1200  {
1201  deviceDataElement->SetDoubleAttribute("LocalTimeOffsetSec", this->GetLocalTimeOffsetSec());
1202  }
1203 
1204  // Parameters writing
1205  XML_FIND_NESTED_ELEMENT_CREATE_IF_MISSING(parameterList, deviceDataElement, PARAMETERS_XML_ELEMENT_TAG.c_str());
1206 
1207  // Clear the list before writing new elements
1208  parameterList->RemoveAllNestedElements();
1209 
1210  for (std::map<std::string, std::string>::iterator it = this->Parameters.begin(); it != this->Parameters.end(); ++it)
1211  {
1212  vtkSmartPointer<vtkXMLDataElement> parameter = vtkSmartPointer<vtkXMLDataElement>::New();
1213  parameter->SetName(PARAMETER_XML_ELEMENT_TAG.c_str());
1214  parameter->SetAttribute("name", it->first.c_str());
1215  parameter->SetAttribute("value", it->second.c_str());
1216 
1217  parameterList->AddNestedElement(parameter);
1218  }
1219 
1220  return PLUS_SUCCESS;
1221 }
1222 
1223 //----------------------------------------------------------------------------
1225 {
1226  LOCAL_LOG_DEBUG("vtkPlusDevice::Connect: " << (!this->DeviceId.empty() ? this->DeviceId : "undefined"));
1227 
1228  if (this->Connected)
1229  {
1230  LOCAL_LOG_DEBUG("Already connected to the data source");
1231  return PLUS_SUCCESS;
1232  }
1233 
1234  // We will report unknown tools after each Connect
1235  this->ReportedUnknownTools.clear();
1236 
1237  if (this->InternalConnect() != PLUS_SUCCESS)
1238  {
1239  LOCAL_LOG_ERROR("Cannot connect to device, ConnectInternal failed");
1240  return PLUS_FAIL;
1241  }
1242 
1243  this->Connected = 1;
1244 
1245  return PLUS_SUCCESS;
1246 }
1247 
1248 //----------------------------------------------------------------------------
1250 {
1251  LOCAL_LOG_DEBUG("vtkPlusDevice::Disconnect");
1252 
1253  if (!this->Connected)
1254  {
1255  LOCAL_LOG_DEBUG("Data source is already disconnected");
1256  return PLUS_SUCCESS;
1257  }
1258  if (this->Recording)
1259  {
1260  this->StopRecording();
1261  }
1262 
1263  this->Connected = 0;
1264 
1266 
1267  return PLUS_SUCCESS;
1268 }
1269 
1270 //----------------------------------------------------------------------------
1271 // Set the source to acquire data continuously.
1272 // You should override this as appropriate for your device.
1274 {
1275  LOCAL_LOG_DEBUG("vtkPlusDevice::StartRecording");
1276 
1277  if (this->Recording)
1278  {
1279  LOCAL_LOG_DEBUG("Recording is already active");
1280  return PLUS_SUCCESS;
1281  }
1282 
1283  if (!this->Connected)
1284  {
1285  if (this->Connect() != PLUS_SUCCESS)
1286  {
1287  LOCAL_LOG_ERROR("Cannot start recording, connection failed");
1288  return PLUS_FAIL;
1289  }
1290  }
1291 
1292  if (this->InternalStartRecording() != PLUS_SUCCESS)
1293  {
1294  LOCAL_LOG_ERROR("Cannot start recording, internal StartRecording failed");
1295  return PLUS_FAIL;
1296  }
1297 
1298  this->RecordingStartTime = vtkIGSIOAccurateTimer::GetSystemTime();
1299  this->Recording = 1;
1300 
1302  {
1303  this->ThreadId =
1304  this->Threader->SpawnThread((vtkThreadFunctionType)\
1305  &vtkDataCaptureThread, this);
1306  }
1307 
1308  this->Modified();
1309 
1310  return PLUS_SUCCESS;
1311 }
1312 
1313 //----------------------------------------------------------------------------
1314 // Stop continuous acquisition. You will have to override this
1315 // if your class overrides Record()
1317 {
1318  LOCAL_LOG_DEBUG("vtkPlusDevice::StopRecording");
1319 
1320  if (!this->Recording)
1321  {
1322  LOCAL_LOG_DEBUG("Recording is already inactive");
1323  return PLUS_SUCCESS;
1324  }
1325 
1326  this->Recording = 0;
1327 
1329  {
1330  LOCAL_LOG_DEBUG("Wait for internal update thread to terminate");
1331  // Let's give a chance to the thread to stop before we kill the connection
1332  while (this->ThreadAlive)
1333  {
1334  vtkIGSIOAccurateTimer::Delay(0.1);
1335  }
1336  int tempID = this->ThreadId;
1337  this->ThreadId = -1;
1338  this->Threader->TerminateThread(tempID);
1339  LOCAL_LOG_DEBUG("Internal update thread terminated");
1340  }
1341 
1342  if (this->InternalStopRecording() != PLUS_SUCCESS)
1343  {
1344  LOCAL_LOG_ERROR("Failed to stop tracking thread!");
1345  return PLUS_FAIL;
1346  }
1347 
1348  this->Modified();
1349 
1350  return PLUS_SUCCESS;
1351 }
1352 
1353 //----------------------------------------------------------------------------
1354 // this function runs in an alternate thread to asynchronously acquire data
1355 void* vtkPlusDevice::vtkDataCaptureThread(vtkMultiThreader::ThreadInfo* data)
1356 {
1357  vtkPlusDevice* self = (vtkPlusDevice*)(data->UserData);
1358 
1359  double rate = self->GetAcquisitionRate();
1360  double currtime[FRAME_RATE_AVERAGING] = {0};
1361  unsigned long updatecount = 0;
1362  self->ThreadAlive = true;
1363 
1364  while (self->IsRecording() && self->GetCorrectlyConfigured())
1365  {
1366  double newtime = vtkIGSIOAccurateTimer::GetSystemTime();
1367  // get current tracking rate over last few updates
1368  double difftime = newtime - currtime[updatecount % FRAME_RATE_AVERAGING];
1369  currtime[updatecount % FRAME_RATE_AVERAGING] = newtime;
1370  if (updatecount > FRAME_RATE_AVERAGING && difftime != 0)
1371  {
1372  self->InternalUpdateRate = (FRAME_RATE_AVERAGING / difftime);
1373  }
1374 
1375  {
1376  // Lock before update
1377  igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(self->UpdateMutex);
1378  if (!self->Recording)
1379  {
1380  // recording has been stopped
1381  break;
1382  }
1383  self->InternalUpdate();
1384  self->UpdateTime.Modified();
1385  }
1386 
1387  double delay = (newtime + 1.0 / rate - vtkIGSIOAccurateTimer::GetSystemTime());
1388  if (delay > 0)
1389  {
1390  vtkIGSIOAccurateTimer::Delay(delay);
1391  }
1392 
1393  updatecount++;
1394  }
1395 
1396  self->ThreadAlive = false;
1397  return NULL;
1398 }
1399 
1400 //----------------------------------------------------------------------------
1402 {
1403  return PLUS_SUCCESS;
1404 }
1405 
1406 //----------------------------------------------------------------------------
1408 {
1409  return PLUS_SUCCESS;
1410 }
1411 
1412 //----------------------------------------------------------------------------
1414 {
1415  return PLUS_SUCCESS;
1416 }
1417 
1418 //----------------------------------------------------------------------------
1420 {
1421  return PLUS_SUCCESS;
1422 }
1423 
1424 //----------------------------------------------------------------------------
1425 PlusStatus vtkPlusDevice::GetBufferSize(vtkPlusChannel& aChannel, int& outVal, const std::string& aSourceId)
1426 {
1427  LOCAL_LOG_TRACE("vtkPlusDeviceg::GetBufferSize");
1428 
1429  if (aSourceId.empty())
1430  {
1431  vtkPlusDataSource* aSource(NULL);
1432  if (aChannel.GetVideoSource(aSource) != PLUS_SUCCESS)
1433  {
1434  LOCAL_LOG_ERROR("Unable to retrieve the buffer size of the video source in channel: " << aChannel.GetChannelId() << ".");
1435  return PLUS_FAIL;
1436  }
1437 
1438  outVal = aSource->GetBufferSize();
1439  return PLUS_SUCCESS;
1440  }
1441 
1442  for (DataSourceContainerConstIterator it = this->GetToolIteratorBegin(); it != this->GetToolIteratorEnd(); ++it)
1443  {
1444  if (it->second->GetId() == aSourceId)
1445  {
1446  outVal = it->second->GetBufferSize();
1447  return PLUS_SUCCESS;
1448  }
1449  }
1450 
1452  {
1453  if (it->second->GetId() == aSourceId)
1454  {
1455  outVal = it->second->GetBufferSize();
1456  return PLUS_SUCCESS;
1457  }
1458  }
1459 
1460  LOCAL_LOG_ERROR("Unable to find tool " << aSourceId << " when requesting its buffer size.");
1461  return PLUS_FAIL;
1462 }
1463 
1464 //----------------------------------------------------------------------------
1465 // set or change the circular buffer size
1466 // you will have to override this if you want the buffers
1467 // to be device-specific (i.e. something other than vtkDataArray)
1468 PlusStatus vtkPlusDevice::SetBufferSize(vtkPlusChannel& aChannel, int FrameBufferSize, const std::string& aSourceId)
1469 {
1470  LOCAL_LOG_TRACE("vtkPlusDevice::SetBufferSize(" << FrameBufferSize << ")");
1471 
1472  if (FrameBufferSize < 0)
1473  {
1474  LOCAL_LOG_ERROR("vtkPlusDevice::SetBufferSize: There must be at least one framebuffer");
1475  return PLUS_FAIL;
1476  }
1477 
1478  if (aSourceId.empty())
1479  {
1480  vtkPlusDataSource* aSource(NULL);
1481  if (aChannel.GetVideoSource(aSource) != PLUS_SUCCESS)
1482  {
1483  LOCAL_LOG_ERROR("Unable to retrieve the video source.");
1484  return PLUS_FAIL;
1485  }
1486 
1487  // update the buffer size
1488  if (aSource->SetBufferSize(FrameBufferSize) != PLUS_SUCCESS)
1489  {
1490  LOCAL_LOG_ERROR("Failed to set buffer size!");
1491  return PLUS_FAIL;
1492  }
1493  return PLUS_SUCCESS;
1494  }
1495 
1496  for (DataSourceContainerConstIterator it = this->GetToolIteratorBegin(); it != this->GetToolIteratorEnd(); ++it)
1497  {
1498  if (it->second->GetId() == aSourceId)
1499  {
1500  it->second->SetBufferSize(FrameBufferSize);
1501  }
1502  }
1503 
1505  {
1506  if (it->second->GetId() == aSourceId)
1507  {
1508  it->second->SetBufferSize(FrameBufferSize);
1509  }
1510  }
1511 
1512  return PLUS_SUCCESS;
1513 }
1514 
1515 //----------------------------------------------------------------------------
1516 void vtkPlusDevice::SetStartTime(double startTime)
1517 {
1519  {
1520  it->second->SetStartTime(startTime);
1521  }
1522 
1523  for (DataSourceContainerConstIterator it = this->GetToolIteratorBegin(); it != this->GetToolIteratorEnd(); ++it)
1524  {
1525  it->second->SetStartTime(startTime);
1526  }
1527 
1529  {
1530  it->second->SetStartTime(startTime);
1531  }
1532 }
1533 
1534 //----------------------------------------------------------------------------
1536 {
1537  // TODO : should this return the buffer start time or should the buffer start time
1538  // simply be included in the average
1539  double sumStartTime = 0.0;
1540  double numberOfBuffers(0);
1542  {
1543  sumStartTime += it->second->GetStartTime();
1544  numberOfBuffers++;
1545  }
1546 
1547  for (DataSourceContainerConstIterator it = this->GetToolIteratorBegin(); it != this->GetToolIteratorEnd(); ++it)
1548  {
1549  sumStartTime += it->second->GetStartTime();
1550  numberOfBuffers++;
1551  }
1552 
1554  {
1555  sumStartTime += it->second->GetStartTime();
1556  numberOfBuffers++;
1557  }
1558 
1559  return sumStartTime / numberOfBuffers;
1560 }
1561 
1562 //----------------------------------------------------------------------------
1564 {
1565  igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->UpdateMutex);
1566 
1567  if (this->InternalStartRecording() != PLUS_SUCCESS)
1568  {
1569  return PLUS_FAIL;
1570  }
1571 
1572  if (this->InternalStopRecording() != PLUS_SUCCESS)
1573  {
1574  return PLUS_FAIL;
1575  }
1576 
1577  return PLUS_SUCCESS;
1578 }
1579 
1580 //-----------------------------------------------------------------------------
1582 {
1584  {
1585  it->second->Clear();
1586  }
1587  for (DataSourceContainerConstIterator it = this->GetToolIteratorBegin(); it != this->GetToolIteratorEnd(); ++it)
1588  {
1589  it->second->Clear();
1590  }
1592  {
1593  it->second->Clear();
1594  }
1595 }
1596 
1597 //----------------------------------------------------------------------------
1599 {
1600  LOCAL_LOG_TRACE("vtkPlusDevice::ForceUpdate");
1601 
1602  if (!this->Connected)
1603  {
1604  if (this->Connect() != PLUS_SUCCESS)
1605  {
1606  LOCAL_LOG_ERROR("Cannot acquire a single frame, connection failed");
1607  return PLUS_FAIL;
1608  }
1609  }
1610 
1611  {
1612  igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->UpdateMutex);
1613  this->InternalUpdate();
1614  }
1615  return PLUS_SUCCESS;
1616 }
1617 
1618 //----------------------------------------------------------------------------
1619 PlusStatus vtkPlusDevice::ToolTimeStampedUpdateWithoutFiltering(const std::string& aToolSourceId, vtkMatrix4x4* matrix, ToolStatus status, double unfilteredtimestamp, double filteredtimestamp, const igsioFieldMapType* customFields /* = NULL */)
1620 {
1621  if (aToolSourceId.empty())
1622  {
1623  LOCAL_LOG_ERROR("Failed to update tool - tool source ID is empty!");
1624  return PLUS_FAIL;
1625  }
1626 
1627  vtkPlusDataSource* tool = NULL;
1628  if (this->GetTool(aToolSourceId, tool) != PLUS_SUCCESS)
1629  {
1630  if (this->ReportedUnknownTools.find(aToolSourceId) == this->ReportedUnknownTools.end())
1631  {
1632  // We have not reported yet that this tool is unknown
1633  LOCAL_LOG_ERROR("Failed to update tool - unable to find tool: " << aToolSourceId);
1634  this->ReportedUnknownTools.insert(std::string(aToolSourceId));
1635  }
1636  return PLUS_FAIL;
1637  }
1638 
1639  // This function is for devices has no frame numbering, just auto increment tool frame number if new frame received
1640  unsigned long frameNumber = tool->GetFrameNumber() + 1 ;
1641  PlusStatus bufferStatus = tool->AddTimeStampedItem(matrix, status, frameNumber, unfilteredtimestamp, filteredtimestamp, customFields);
1642  tool->SetFrameNumber(frameNumber);
1643 
1644  return bufferStatus;
1645 }
1646 
1647 //----------------------------------------------------------------------------
1648 PlusStatus vtkPlusDevice::AddVideoItemToVideoSources(const std::vector<vtkPlusDataSource*>& videoSources, const igsioVideoFrame& frame, long frameNumber, double unfilteredTimestamp/*=UNDEFINED_TIMESTAMP*/, double filteredTimestamp/*=UNDEFINED_TIMESTAMP*/, const igsioFieldMapType* customFields /*= NULL*/)
1649 {
1650  PlusStatus result(PLUS_SUCCESS);
1651  for (std::vector<vtkPlusDataSource*>::const_iterator it = videoSources.begin(); it != videoSources.end(); ++it)
1652  {
1653  vtkPlusDataSource* source = *it;
1654  if (source->AddItem(&frame, frameNumber, unfilteredTimestamp, filteredTimestamp, customFields) != PLUS_SUCCESS)
1655  {
1656  result = PLUS_FAIL;
1657  }
1658  }
1659  return result;
1660 }
1661 
1662 //----------------------------------------------------------------------------
1663 PlusStatus vtkPlusDevice::AddVideoItemToVideoSources(const std::vector<vtkPlusDataSource*>& videoSources, void* imageDataPtr, US_IMAGE_ORIENTATION usImageOrientation, const FrameSizeType& frameSizeInPx, igsioCommon::VTKScalarPixelType pixelType, unsigned int numberOfScalarComponents, US_IMAGE_TYPE imageType, int numberOfBytesToSkip, long frameNumber, double unfilteredTimestamp /*= UNDEFINED_TIMESTAMP*/, double filteredTimestamp /*= UNDEFINED_TIMESTAMP*/, const igsioFieldMapType* customFields /*= NULL*/)
1664 {
1665  PlusStatus result(PLUS_SUCCESS);
1666  for (std::vector<vtkPlusDataSource*>::const_iterator it = videoSources.begin(); it != videoSources.end(); ++it)
1667  {
1668  vtkPlusDataSource* source = *it;
1669  if (source->AddItem(imageDataPtr, usImageOrientation, frameSizeInPx, pixelType, numberOfScalarComponents, imageType, numberOfBytesToSkip, frameNumber, unfilteredTimestamp, filteredTimestamp, customFields) != PLUS_SUCCESS)
1670  {
1671  result = PLUS_FAIL;
1672  }
1673  }
1674  return result;
1675 }
1676 
1677 //----------------------------------------------------------------------------
1678 PlusStatus vtkPlusDevice::ToolTimeStampedUpdate(const std::string& aToolSourceId, vtkMatrix4x4* matrix, ToolStatus status, unsigned long frameNumber, double unfilteredtimestamp, const igsioFieldMapType* customFields/*= NULL*/)
1679 {
1680  if (aToolSourceId.empty())
1681  {
1682  LOCAL_LOG_ERROR("Failed to update tool - tool source ID is empty!");
1683  return PLUS_FAIL;
1684  }
1685 
1686  vtkPlusDataSource* tool = NULL;
1687  if (this->GetTool(aToolSourceId, tool) != PLUS_SUCCESS)
1688  {
1689  if (this->ReportedUnknownTools.find(aToolSourceId) == this->ReportedUnknownTools.end())
1690  {
1691  // We have not reported yet that this tool is unknown
1692  LOCAL_LOG_ERROR("Failed to update tool - unable to find tool: " << aToolSourceId);
1693  this->ReportedUnknownTools.insert(std::string(aToolSourceId));
1694  }
1695  return PLUS_FAIL;
1696  }
1697 
1698  PlusStatus bufferStatus = tool->AddTimeStampedItem(matrix, status, frameNumber, unfilteredtimestamp, UNDEFINED_TIMESTAMP, customFields);
1699  tool->SetFrameNumber(frameNumber);
1700 
1701  return bufferStatus;
1702 }
1703 
1704 //----------------------------------------------------------------------------
1705 // This method returns the largest data that can be generated.
1706 int vtkPlusDevice::RequestInformation(vtkInformation* vtkNotUsed(request), vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector)
1707 {
1708  LOCAL_LOG_TRACE("vtkPlusDevice::RequestInformation");
1709 
1710  if (!this->Connected)
1711  {
1712  this->Connect();
1713  }
1714 
1715  // get the info objects
1716  vtkInformation* outInfo = outputVector->GetInformationObject(0);
1717 
1718  // Find a video source and set extent
1719  vtkPlusDataSource* aSource(NULL);
1720  for (ChannelContainerIterator it = this->OutputChannels.begin(); it != this->OutputChannels.end(); ++it)
1721  {
1722  if ((*it)->GetVideoSource(aSource) == PLUS_SUCCESS)
1723  {
1724  break;
1725  }
1726  }
1727  if (aSource == NULL)
1728  {
1729  return 0;
1730  }
1731 
1732  FrameSizeType frameSize = aSource->GetOutputFrameSize();
1733  // TODO : determine another mechanism to see if device has data yet or not
1734 
1735  int extent[6] = { 0, static_cast<int>(frameSize[0]) - 1, 0, static_cast<int>(frameSize[1]) - 1, 0, static_cast<int>(frameSize[2]) - 1 };
1736  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent, 6);
1737 
1738  // Set the origin and spacing. The video source provides raw pixel output,
1739  // therefore the spacing is (1,1,1) and the origin is (0,0,0)
1740  double spacing[3] = { 1, 1, 1 };
1741  outInfo->Set(vtkDataObject::SPACING(), spacing, 3);
1742  double origin[3] = { 0, 0, 0 };
1743  outInfo->Set(vtkDataObject::ORIGIN(), origin, 3);
1744 
1745  // set default data type - unsigned char and number of components 1
1746  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, aSource->GetPixelType(), 1);
1747 
1748  return 1;
1749 }
1750 
1751 //----------------------------------------------------------------------------
1752 // The Execute method is fairly complex, so I would not recommend overriding
1753 // it unless you have to. Override the UnpackRasterLine() method instead.
1754 int vtkPlusDevice::RequestData(vtkInformation* vtkNotUsed(request), vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* vtkNotUsed(outputVector))
1755 {
1756  LOCAL_LOG_TRACE("vtkPlusDevice::RequestData");
1757 
1758  // Find a video source and set extent
1759  vtkPlusDataSource* aSource(NULL);
1760  for (ChannelContainerIterator it = this->OutputChannels.begin(); it != this->OutputChannels.end(); ++it)
1761  {
1762  if ((*it)->GetVideoSource(aSource) == PLUS_SUCCESS)
1763  {
1764  break;
1765  }
1766  }
1767  if (aSource == NULL)
1768  {
1769  return 1;
1770  }
1771 
1772  if (aSource->GetNumberOfItems() < 1)
1773  {
1774  LOCAL_LOG_DEBUG("Cannot request data from video source, the video buffer is empty or does not exist!");
1775  vtkImageData* data = vtkImageData::SafeDownCast(this->GetOutputDataObject(0));
1776  FrameSizeType frameSize = aSource->GetOutputFrameSize();
1777  data->SetExtent(0, frameSize[0] - 1, 0, frameSize[1] - 1, 0, frameSize[2] - 1);
1778  data->AllocateScalars(aSource->GetPixelType(), aSource->GetNumberOfScalarComponents());
1779 
1780  return 1;
1781  }
1782 
1783  if (this->UpdateWithDesiredTimestamp && this->DesiredTimestamp != -1)
1784  {
1786  if (itemStatus != ITEM_OK)
1787  {
1788  LOCAL_LOG_ERROR("Unable to copy video data to the requested output!");
1789  return 1;
1790  }
1791  }
1792  else
1793  {
1794  // get the most recent frame if we are not updating with the desired timestamp
1795  ItemStatus itemStatus = aSource->GetLatestStreamBufferItem(this->CurrentStreamBufferItem);
1796  if (itemStatus != ITEM_OK)
1797  {
1798  LOCAL_LOG_ERROR("Unable to copy video data to the requested output!");
1799  return 1;
1800  }
1801  }
1802 
1805 
1806  void* sourcePtr = this->CurrentStreamBufferItem->GetFrame().GetScalarPointer();
1807  int bytesToCopy = this->CurrentStreamBufferItem->GetFrame().GetFrameSizeInBytes();
1808 
1809  // The whole image buffer is copied, regardless of the UPDATE_EXTENT value to make the copying implementation simpler
1810  // For a more efficient implementation, we should only update the requested part of the image.
1811  vtkImageData* data = vtkImageData::SafeDownCast(this->GetOutputDataObject(0));
1812  FrameSizeType frameSize = { 0, 0, 0 };
1813  this->CurrentStreamBufferItem->GetFrame().GetFrameSize(frameSize);
1814  data->SetExtent(0, frameSize[0] - 1, 0, frameSize[1] - 1, 0, frameSize[2] - 1);
1815  data->AllocateScalars(aSource->GetPixelType(), aSource->GetNumberOfScalarComponents());
1816 
1817  unsigned char* outPtr = (unsigned char*)data->GetScalarPointer();
1818  memcpy(outPtr, sourcePtr, bytesToCopy);
1819 
1820  return 1;
1821 }
1822 
1823 //----------------------------------------------------------------------------
1825 {
1826  return this->Connected;
1827 }
1828 
1829 //----------------------------------------------------------------------------
1831 {
1832  return this->Connected == 1;
1833 }
1834 
1835 //----------------------------------------------------------------------------
1836 PlusStatus vtkPlusDevice::SetInputFrameSize(vtkPlusDataSource& aSource, unsigned int x, unsigned int y, unsigned int z)
1837 {
1838  FrameSizeType frameSize = aSource.GetInputFrameSize();
1839  if (x == frameSize[0] && y == frameSize[1] && z == frameSize[2])
1840  {
1841  return PLUS_SUCCESS;
1842  }
1843 
1844  if (x != 0 && y != 0 && z == 0)
1845  {
1846  LOCAL_LOG_WARNING("Single slice images should have a dimension of z=1");
1847  z = 1;
1848  }
1849 
1850  if (x < 1 || y < 1 || z < 1)
1851  {
1852  LOCAL_LOG_ERROR("SetInputFrameSize: Illegal frame size " << x << "x" << y << "x" << z);
1853  return PLUS_FAIL;
1854  }
1855 
1856  aSource.SetInputFrameSize(x, y, z);
1857  aSource.Modified();
1858 
1859  return PLUS_SUCCESS;
1860 }
1861 
1862 //----------------------------------------------------------------------------
1863 PlusStatus vtkPlusDevice::GetOutputFrameSize(vtkPlusChannel& aChannel, unsigned int& x, unsigned int& y, unsigned int& z) const
1864 {
1865  LOCAL_LOG_TRACE("vtkPlusDevice::GetOutputFrameSize");
1866 
1867  FrameSizeType dim = {0, 0, 0};
1868  if (this->GetOutputFrameSize(aChannel, dim) != PLUS_SUCCESS)
1869  {
1870  LOCAL_LOG_ERROR("Unable to get frame size from the device.");
1871  return PLUS_FAIL;
1872  }
1873  x = dim[0];
1874  y = dim[1];
1875  z = dim[2];
1876 
1877  return PLUS_SUCCESS;
1878 }
1879 
1880 //----------------------------------------------------------------------------
1882 {
1883  LOCAL_LOG_TRACE("vtkPlusDevice::GetOutputFrameSize");
1884 
1885  vtkPlusDataSource* aSource(NULL);
1886  if (aChannel.GetVideoSource(aSource) != PLUS_SUCCESS)
1887  {
1888  LOCAL_LOG_ERROR("Unable to retrieve the video source.");
1889  return PLUS_FAIL;
1890  }
1891 
1892  dim = aSource->GetOutputFrameSize();
1893  return PLUS_SUCCESS;
1894 }
1895 
1896 //----------------------------------------------------------------------------
1897 PlusStatus vtkPlusDevice::GetInputFrameSize(vtkPlusChannel& aChannel, unsigned int& x, unsigned int& y, unsigned int& z) const
1898 {
1899  LOCAL_LOG_TRACE("vtkPlusDevice::GetInputFrameSize");
1900 
1901  FrameSizeType dim = {0, 0, 0};
1902  if (this->GetInputFrameSize(aChannel, dim) != PLUS_SUCCESS)
1903  {
1904  LOCAL_LOG_ERROR("Unable to get frame size from the device.");
1905  return PLUS_FAIL;
1906  }
1907  x = dim[0];
1908  y = dim[1];
1909  z = dim[2];
1910 
1911  return PLUS_SUCCESS;
1912 }
1913 
1914 //----------------------------------------------------------------------------
1915 PlusStatus vtkPlusDevice::GetInputFrameSize(vtkPlusChannel& aChannel, FrameSizeType& dim) const
1916 {
1917  LOCAL_LOG_TRACE("vtkPlusDevice::GetInputFrameSize");
1918 
1919  vtkPlusDataSource* aSource(NULL);
1920  if (aChannel.GetVideoSource(aSource) != PLUS_SUCCESS)
1921  {
1922  LOCAL_LOG_ERROR("Unable to retrieve the video source.");
1923  return PLUS_FAIL;
1924  }
1925 
1926  dim = aSource->GetInputFrameSize();
1927  return PLUS_SUCCESS;
1928 }
1929 
1930 //----------------------------------------------------------------------------
1932 {
1933  LOCAL_LOG_TRACE("vtkPlusDevice::SetPixelType");
1934 
1935  vtkPlusDataSource* aSource(NULL);
1936  if (aChannel.GetVideoSource(aSource) != PLUS_SUCCESS)
1937  {
1938  LOCAL_LOG_ERROR("Unable to retrieve the video source.");
1939  return PLUS_FAIL;
1940  }
1941 
1942  return aSource->SetPixelType(pixelType);
1943 }
1944 
1945 //----------------------------------------------------------------------------
1947 {
1948  LOCAL_LOG_TRACE("vtkPlusDevice::GetPixelType");
1949 
1950  vtkPlusDataSource* aSource(NULL);
1951  if (aChannel.GetVideoSource(aSource) != PLUS_SUCCESS)
1952  {
1953  LOCAL_LOG_ERROR("Unable to retrieve the video source.");
1954  return VTK_VOID;
1955  }
1956 
1957  return aSource->GetPixelType();
1958 }
1959 
1960 //----------------------------------------------------------------------------
1962 {
1963  vtkPlusDataSource* aSource(NULL);
1964  if (aChannel.GetVideoSource(aSource) != PLUS_SUCCESS)
1965  {
1966  LOCAL_LOG_ERROR("Unable to retrieve the video source.");
1967  return US_IMG_TYPE_XX;
1968  }
1969 
1970  return aSource->GetImageType();
1971 }
1972 
1973 //----------------------------------------------------------------------------
1974 PlusStatus vtkPlusDevice::SetImageType(vtkPlusChannel& aChannel, US_IMAGE_TYPE imageType)
1975 {
1976  vtkPlusDataSource* aSource(NULL);
1977  if (aChannel.GetVideoSource(aSource) != PLUS_SUCCESS)
1978  {
1979  LOCAL_LOG_ERROR("Unable to retrieve the video source.");
1980  return PLUS_FAIL;
1981  }
1982  return aSource->SetImageType(imageType);
1983 }
1984 
1985 //----------------------------------------------------------------------------
1987 {
1988  if (this->OutputChannels.size() == 0)
1989  {
1990  LOCAL_LOG_ERROR("Failed to get first output channel - there are no output channels!");
1991  return PLUS_FAIL;
1992  }
1993 
1994  aChannel = (* this->OutputChannels.begin());
1995 
1996  return PLUS_SUCCESS;
1997 }
1998 
1999 //----------------------------------------------------------------------------
2001 {
2002  if (aChannelId == NULL)
2003  {
2004  LOCAL_LOG_ERROR("Null channel name sent to GetOutputChannelByName.");
2005  return PLUS_FAIL;
2006  }
2007 
2008  for (ChannelContainerIterator it = this->OutputChannels.begin(); it != this->OutputChannels.end(); ++it)
2009  {
2010  vtkPlusChannel* channel = (*it);
2011  if (STRCASECMP(channel->GetChannelId(), aChannelId) == 0)
2012  {
2013  aChannel = channel;
2014  return PLUS_SUCCESS;
2015  }
2016  }
2017 
2018  return PLUS_FAIL;
2019 }
2020 
2021 //----------------------------------------------------------------------------
2022 PlusStatus vtkPlusDevice::GetOutputChannelByName(vtkPlusChannel*& aChannel, const std::string& aChannelId)
2023 {
2024  return GetOutputChannelByName(aChannel, aChannelId.c_str());
2025 }
2026 
2027 //----------------------------------------------------------------------------
2029 {
2030  return OutputChannels.size();
2031 }
2032 
2033 //----------------------------------------------------------------------------
2035 {
2036  if (aChannel == NULL)
2037  {
2038  LOCAL_LOG_ERROR("vtkPlusDevice::AddInputChannel failed: input channel is invalid");
2039  return PLUS_FAIL;
2040  }
2041  for (ChannelContainerIterator it = InputChannels.begin(); it != InputChannels.end(); ++it)
2042  {
2043  if (STRCASECMP((*it)->GetChannelId(), aChannel->GetChannelId()) == 0)
2044  {
2045  LOCAL_LOG_WARNING("Duplicate addition of an input aChannel.");
2046  return PLUS_SUCCESS;
2047  }
2048  }
2049 
2050  // aChannel remains valid, as it is owned by another device (which provides it as an output)
2051  // TODO: it could be safer to increase the reference counter of aChannel here (and decrease the ref counter when aChannel is removed from InputChannels)
2052  this->InputChannels.push_back(aChannel);
2053  return PLUS_SUCCESS;
2054 }
2055 
2056 //----------------------------------------------------------------------------
2058 {
2059  return PLUS_SUCCESS;
2060 }
2061 
2062 //----------------------------------------------------------------------------
2064 {
2065  return this->AcquisitionRate;
2066 }
2067 
2068 //----------------------------------------------------------------------------
2069 void vtkPlusDevice::InternalWriteOutputChannels(vtkXMLDataElement* rootXMLElement)
2070 {
2071  LOCAL_LOG_TRACE("vtkPlusDevice::InternalWriteOutputChannels( " << rootXMLElement->GetName() << ")");
2072 
2073  for (ChannelContainerConstIterator it = this->OutputChannels.begin(); it != this->OutputChannels.end(); ++it)
2074  {
2075  vtkPlusChannel* aStream = *it;
2076  vtkXMLDataElement* streamElement = this->FindOutputChannelElement(rootXMLElement, aStream->GetChannelId());
2077  aStream->WriteConfiguration(streamElement);
2078  }
2079 }
2080 
2081 //----------------------------------------------------------------------------
2082 void vtkPlusDevice::InternalWriteInputChannels(vtkXMLDataElement* rootXMLElement)
2083 {
2084  LOCAL_LOG_TRACE("vtkPlusDevice::InternalWriteInputChannels( " << rootXMLElement->GetName() << ")");
2085 
2086  for (ChannelContainerConstIterator it = this->InputChannels.begin(); it != this->InputChannels.end(); ++it)
2087  {
2088  vtkPlusChannel* aStream = *it;
2089  vtkXMLDataElement* streamElement = this->FindInputChannelElement(rootXMLElement, aStream->GetChannelId());
2090  aStream->WriteConfiguration(streamElement);
2091  }
2092 }
2093 
2094 //----------------------------------------------------------------------------
2096 {
2097  for (DataSourceContainer::iterator it = begin(this->Tools); it != end(this->Tools); ++it)
2098  {
2099  if (it->second->GetId() == aSourceId)
2100  {
2101  return PLUS_FAIL;
2102  }
2103  }
2104  for (DataSourceContainer::iterator it = begin(this->VideoSources); it != end(this->VideoSources); ++it)
2105  {
2106  if (it->second->GetId() == aSourceId)
2107  {
2108  return PLUS_FAIL;
2109  }
2110  }
2111  for (DataSourceContainer::iterator it = begin(this->Fields); it != end(this->Fields); ++it)
2112  {
2113  if (it->second->GetId() == aSourceId)
2114  {
2115  return PLUS_FAIL;
2116  }
2117  }
2118 
2119  return PLUS_SUCCESS;
2120 }
2121 
2122 //----------------------------------------------------------------------------
2124 {
2125  return this->StartThreadForInternalUpdates;
2126 }
2127 
2128 //----------------------------------------------------------------------------
2130 {
2131  return this->RecordingStartTime;
2132 }
2133 
2134 //----------------------------------------------------------------------------
2136 {
2137  return this->DataCollector;
2138 }
2139 
2140 //----------------------------------------------------------------------------
2142 {
2143  return this->VideoSources.begin();
2144 }
2145 
2146 //----------------------------------------------------------------------------
2148 {
2149  return this->VideoSources.end();
2150 }
2151 
2152 //----------------------------------------------------------------------------
2154 {
2155  return this->VideoSources.size();
2156 }
2157 
2158 //----------------------------------------------------------------------------
2160 {
2161  if (aVideo == NULL)
2162  {
2163  LOCAL_LOG_ERROR("Failed to add video to device, video is NULL!");
2164  return PLUS_FAIL;
2165  }
2166 
2167  if (aVideo->GetId().empty())
2168  {
2169  LOCAL_LOG_ERROR("Failed to add video to device, image Id must be defined!");
2170  return PLUS_FAIL;
2171  }
2172 
2173  if (this->VideoSources.find(aVideo->GetId()) == this->GetVideoSourceIteratorEnd())
2174  {
2175  // Check image port names, it should be unique too
2177  {
2178  if (aVideo->GetId() == it->second->GetId())
2179  {
2180  LOCAL_LOG_ERROR("Failed to add '" << aVideo->GetId() << "' video to container: video with Id '" << it->second->GetId()
2181  << "' is already defined'!");
2182  return PLUS_FAIL;
2183  }
2184  }
2185 
2186  aVideo->Register(this);
2187  aVideo->SetDevice(this);
2188  this->VideoSources[aVideo->GetId()] = aVideo;
2189  }
2190  else
2191  {
2192  LOCAL_LOG_ERROR("Image with Id '" << aVideo->GetId() << "' is already in the image container!");
2193  return PLUS_FAIL;
2194  }
2195 
2196  return PLUS_SUCCESS;
2197 }
2198 
2199 //----------------------------------------------------------------------------
2201 {
2202  if (this->VideoSources.size() == 0)
2203  {
2204  LOCAL_LOG_ERROR("Failed to get first active video source - there are no video sources!");
2205  return PLUS_FAIL;
2206  }
2207 
2208  aVideoSource = this->VideoSources.begin()->second;
2209 
2210  return PLUS_SUCCESS;
2211 }
2212 
2213 //----------------------------------------------------------------------------
2214 PlusStatus vtkPlusDevice::GetVideoSource(const char* aSourceId, vtkPlusDataSource*& aVideoSource)
2215 {
2216  if (aSourceId == NULL)
2217  {
2218  LOCAL_LOG_ERROR("Failed to get image, image name is NULL");
2219  return PLUS_FAIL;
2220  }
2221 
2222  if (this->VideoSources.find(aSourceId) != this->VideoSources.end())
2223  {
2224  aVideoSource = this->VideoSources.find(aSourceId)->second;
2225  return PLUS_SUCCESS;
2226  }
2227 
2228  return PLUS_FAIL;
2229 }
2230 
2231 //----------------------------------------------------------------------------
2232 std::vector<vtkPlusDataSource*> vtkPlusDevice::GetVideoSources() const
2233 {
2234  std::vector<vtkPlusDataSource*> results;
2235  for (DataSourceContainerConstIterator it = this->VideoSources.begin(); it != this->VideoSources.end(); ++it)
2236  {
2237  results.push_back(it->second);
2238  }
2239  return results;
2240 }
2241 
2242 //----------------------------------------------------------------------------
2243 PlusStatus vtkPlusDevice::GetVideoSourceByIndex(const unsigned int index, vtkPlusDataSource*& aVideoSource)
2244 {
2245  if (index > this->VideoSources.size())
2246  {
2247  LOCAL_LOG_ERROR("Failed to get video source, index is outside of range.");
2248  aVideoSource = NULL;
2249  return PLUS_FAIL;
2250  }
2251 
2252  DataSourceContainerIterator it = this->VideoSources.begin();
2253  for (unsigned int i = 0 ; i < index; ++i)
2254  {
2255  ++it;
2256  }
2257  aVideoSource = it->second;
2258  return PLUS_SUCCESS;
2259 }
2260 
2261 //----------------------------------------------------------------------------
2263 {
2264  if (this->GetVideoSource(aSourceId, aSource) == PLUS_SUCCESS)
2265  {
2266  return PLUS_SUCCESS;
2267  }
2268  if (this->GetTool(aSourceId, aSource) == PLUS_SUCCESS)
2269  {
2270  return PLUS_SUCCESS;
2271  }
2272  if (this->GetFieldDataSource(aSourceId, aSource) == PLUS_SUCCESS)
2273  {
2274  return PLUS_SUCCESS;
2275  }
2276  else
2277  {
2278  return PLUS_FAIL;
2279  }
2280 }
2281 
2282 //----------------------------------------------------------------------------
2283 PlusStatus vtkPlusDevice::GetDataSource(const std::string& aSourceId, vtkPlusDataSource*& aSource)
2284 {
2285  return GetDataSource(aSourceId.c_str(), aSource);
2286 }
2287 
2288 //----------------------------------------------------------------------------
2290 {
2291  return this->OutputChannels.begin();
2292 }
2293 
2294 //----------------------------------------------------------------------------
2296 {
2297  return this->OutputChannels.begin();
2298 }
2299 
2300 //----------------------------------------------------------------------------
2302 {
2303  return this->OutputChannels.end();
2304 }
2305 
2306 //----------------------------------------------------------------------------
2308 {
2309  return this->OutputChannels.end();
2310 }
2311 
2312 //------------------------------------------------------------------------------
2313 PlusStatus vtkPlusDevice::GetToolReferenceFrameFromTrackedFrame(igsioTrackedFrame& aFrame, std::string& aToolReferenceFrameName)
2314 {
2315  LOG_TRACE("vtkPlusDataCollectorFile::GetTrackerToolReferenceFrame");
2316 
2317  // Try to find it out from the custom transforms that are stored in the tracked frame
2318  std::vector<igsioTransformName> transformNames;
2319  aFrame.GetFrameTransformNameList(transformNames);
2320 
2321  if (transformNames.size() == 0)
2322  {
2323  LOG_ERROR("No transforms found in tracked frame!");
2324  return PLUS_FAIL;
2325  }
2326 
2327  std::string frameName = "";
2328  for (std::vector<igsioTransformName>::iterator it = transformNames.begin(); it != transformNames.end(); ++it)
2329  {
2330  if (frameName == "")
2331  {
2332  frameName = it->To();
2333  }
2334  else if (frameName != it->To())
2335  {
2336  LOG_ERROR("Destination coordinate frame names are not the same!");
2337  return PLUS_FAIL;
2338  }
2339  }
2340 
2341  aToolReferenceFrameName = frameName;
2342 
2343  return PLUS_SUCCESS;
2344 }
2345 
2346 //------------------------------------------------------------------------------
2348 {
2349  LOCAL_LOG_ERROR("Calling base IsTracker. Override in the derived classes.");
2350  return false;
2351 }
2352 
2353 //----------------------------------------------------------------------------
2355 {
2356  return false;
2357 }
2358 
2359 //------------------------------------------------------------------------------
2361 {
2362  if (aChannel == NULL)
2363  {
2364  LOCAL_LOG_ERROR("Cannot add device, aChannel is invalid");
2365  return PLUS_FAIL;
2366  }
2367  if (aChannel->GetOwnerDevice() == NULL)
2368  {
2369  aChannel->SetOwnerDevice(this);
2370  }
2371  this->OutputChannels.push_back(aChannel);
2372  aChannel->Register(this);
2373  return PLUS_SUCCESS;
2374 }
2375 
2376 //------------------------------------------------------------------------------
2378 {
2379  this->DataCollector = _arg;
2380 }
2381 
2382 //------------------------------------------------------------------------------
2384 {
2385  return (vtkIGSIOAccurateTimer::GetSystemTime() - this->RecordingStartTime) > this->MissingInputGracePeriodSec;
2386 }
2387 
2388 //----------------------------------------------------------------------------
2390 {
2391  return this->MissingInputGracePeriodSec;
2392 }
2393 
2394 //------------------------------------------------------------------------------
2395 PlusStatus vtkPlusDevice::CreateDefaultOutputChannel(const char* channelId /*=NULL*/, bool addSource/*=true*/)
2396 {
2397  // Create output channel
2398  vtkSmartPointer<vtkPlusChannel> aChannel = vtkSmartPointer<vtkPlusChannel>::New();
2399  aChannel->SetOwnerDevice(this);
2400  aChannel->SetChannelId(channelId != NULL ? channelId : "OutputChannel");
2401  if (this->AddOutputChannel(aChannel) != PLUS_SUCCESS)
2402  {
2403  return PLUS_FAIL;
2404  }
2405  if (!addSource)
2406  {
2407  // no need to add sources, so we are done
2408  return PLUS_SUCCESS;
2409  }
2410 
2411  if (this->IsTracker())
2412  {
2413  // TODO: add default tools
2414  }
2415  else
2416  {
2417  // Create an output video stream for this channel
2418  vtkPlusDataSource* aDataSource = vtkPlusDataSource::New();
2419  if (aDataSource->SetBufferSize(30) != PLUS_SUCCESS)
2420  {
2421  LOG_ERROR("Failed to set video buffer size!");
2422  return PLUS_FAIL;
2423  }
2424  aDataSource->SetInputImageOrientation(US_IMG_ORIENT_MF);
2425  if (aDataSource->SetId("Video") != PLUS_SUCCESS)
2426  {
2427  return PLUS_FAIL;
2428  }
2429  if (this->AddVideoSource(aDataSource) != PLUS_SUCCESS)
2430  {
2431  return PLUS_FAIL;
2432  }
2433  aChannel->SetVideoSource(aDataSource);
2434  }
2435  return PLUS_SUCCESS;
2436 }
2437 
2438 //----------------------------------------------------------------------------
2440 {
2441  aVideoSource = NULL;
2442  if (this->OutputChannels.empty())
2443  {
2444  LOCAL_LOG_ERROR("Failed to get first active output video source - there are no output channels");
2445  return PLUS_FAIL;
2446  }
2447  for (ChannelContainerIterator it = this->OutputChannels.begin(); it != this->OutputChannels.end(); ++it)
2448  {
2449  if ((*it)->GetVideoSource(aVideoSource) == PLUS_SUCCESS && aVideoSource != NULL)
2450  {
2451  // found a video source in the output channel
2452  return PLUS_SUCCESS;
2453  }
2454  }
2455 
2456  LOG_ERROR("There is no active video sources in the output channel(s)");
2457  return PLUS_FAIL;
2458 }
2459 
2460 //----------------------------------------------------------------------------
2461 PlusStatus vtkPlusDevice::GetImageMetaData(igsioCommon::ImageMetaDataList& imageMetaDataItems)
2462 {
2463  LOCAL_LOG_DEBUG("No ImageMetaData is available");
2464  return PLUS_SUCCESS;
2465 }
2466 
2467 //----------------------------------------------------------------------------
2468 PlusStatus vtkPlusDevice::GetImage(const std::string& requestedImageId, std::string& assignedImageId, const std::string& imageReferencFrameName, vtkImageData* imageData, vtkMatrix4x4* ijkToReferenceTransform)
2469 {
2470  LOCAL_LOG_ERROR("vtkPlusDevice::GetImage is not implemented");
2471  return PLUS_FAIL;
2472 }
2473 
2474 //----------------------------------------------------------------------------
2475 PlusStatus vtkPlusDevice::SendText(const std::string& textToSend, std::string* textReceived/*=NULL*/)
2476 {
2477  LOCAL_LOG_ERROR("vtkPlusDevice::SendText is not implemented");
2478  return PLUS_FAIL;
2479 }
DataSourceContainer::const_iterator DataSourceContainerConstIterator
PlusStatus GetDataSource(const char *aSourceId, vtkPlusDataSource *&aSource)
DataSourceContainerConstIterator GetVideoSourceIteratorBegin() const
static const int VIRTUAL_DEVICE_FRAME_RATE
const uint32_t * data
Definition: phidget22.h:3971
#define LOCAL_LOG_INFO(msg)
std::string ToolReferenceFrameName
virtual PlusStatus SetInputFrameSize(vtkPlusDataSource &aSource, unsigned int x, unsigned int y, unsigned int z)
virtual PlusStatus SetBufferSize(int n)
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
PlusStatus AddInputChannel(vtkPlusChannel *aChannel)
int * channel
Definition: phidget22.h:1303
virtual void SetLocalTimeOffsetSec(double aTimeOffsetSec)
static const std::string RFMODE_PORT_NAME
Definition: vtkPlusDevice.h:68
vtkPlusDataCollector * DataCollector
ToolStatus GetStatus() const
void DeepCopy(const vtkPlusDevice &device)
virtual unsigned long GetFrameNumber() const
const char * key
Definition: phidget22.h:5111
virtual PlusStatus InternalStopRecording()
PlusStatus AddVideoSource(vtkPlusDataSource *anImage)
virtual void SetLocalTimeOffsetSec(double offsetSec)
virtual void InternalWriteOutputChannels(vtkXMLDataElement *rootXMLElement)
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *aChannelElement)
Abstract interface for tracker and video devices.
Definition: vtkPlusDevice.h:60
US_IMAGE_TYPE GetImageType()
virtual void InternalWriteInputChannels(vtkXMLDataElement *rootXMLElement)
PlusStatus GetInputDevices(std::vector< vtkPlusDevice * > &outDeviceList) const
virtual double GetLocalTimeOffsetSec()
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *toolElement)
static const std::string PARAMETER_XML_ELEMENT_TAG
Definition: vtkPlusDevice.h:70
virtual int GetNumberOfVideoSources() const
const char * source
Definition: phidget22.h:2461
virtual PlusStatus GetInputFrameSize(vtkPlusChannel &aChannel, unsigned int &x, unsigned int &y, unsigned int &z) const
vtkXMLDataElement * FindOutputChannelElement(vtkXMLDataElement *rootXMLElement, const char *aChannelId)
PlusStatus SetId(const char *aSourceId)
double GetMissingInputGracePeriodSec() const
PlusStatus EnsureUniqueDataSourceId(const std::string &aSourceId)
virtual ItemStatus GetStreamBufferItem(BufferItemUidType uid, StreamBufferItem *bufferItem)
vtkStandardNewMacro(vtkPlusDevice)
virtual PlusStatus ToolTimeStampedUpdateWithoutFiltering(const std::string &aToolSourceId, vtkMatrix4x4 *matrix, ToolStatus status, double unfilteredtimestamp, double filteredtimestamp, const igsioFieldMapType *customFields=NULL)
PlusStatus GetFirstOutputChannel(vtkPlusChannel *&aChannel)
double FrameTimeStamp
virtual PlusStatus InternalConnect()
virtual PlusStatus StartRecording()
#define LOCAL_LOG_TRACE(msg)
virtual PlusStatus SetParameter(const std::string &key, const std::string &value)
void SetFieldDataSourcesBufferSize(int aBufferSize)
igsioStatus PlusStatus
Definition: PlusCommon.h:40
ChannelContainer InputChannels
static const std::string BMODE_PORT_NAME
Definition: vtkPlusDevice.h:67
PlusStatus GetVideoSourceByIndex(const unsigned int index, vtkPlusDataSource *&aVideoSource)
virtual std::string GetDeviceId() const
virtual bool IsTracker() const
PlusStatus AddTool(vtkPlusDataSource *tool, bool requireUniquePortName=true)
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)
double GetRecordingStartTime() const
std::vector< vtkPlusDataSource * > GetVideoSources() const
bool RequirePortNameInDeviceSetConfiguration
virtual std::string GetParameter(const std::string &key) const
DataSourceContainer VideoSources
std::map< std::string, std::string > Parameters
PlusStatus AddTimeStampedItem(vtkMatrix4x4 *matrix, ToolStatus status, unsigned long frameNumber, double unfilteredTimestamp, double filteredTimestamp=UNDEFINED_TIMESTAMP, const igsioFieldMapType *customFields=NULL)
PlusStatus GetInputDevicesRecursive(std::vector< vtkPlusDevice * > &outDeviceList) const
bool RequireImageOrientationInConfiguration
virtual unsigned int GetNumberOfScalarComponents()
PlusStatus SetImageType(US_IMAGE_TYPE imageType)
for i
double AcquisitionRate
PlusStatus SetAcquisitionRate(double aRate)
virtual double GetStartTime()
#define PLUS_FAIL
Definition: PlusCommon.h:43
virtual PlusStatus SetInputImageOrientation(US_IMAGE_ORIENTATION imageOrientation)
DataSourceContainer Tools
PlusStatus GetVideoSourcesByPortName(const char *aPortName, std::vector< vtkPlusDataSource * > &sources)
virtual int GetNumberOfTools() const
virtual std::string GetSdkVersion()
static std::string DATA_SOURCE_TYPE_FIELDDATA_TAG
PlusStatus SetPixelType(igsioCommon::VTKScalarPixelType pixelType)
virtual vtkPlusDataCollector * GetDataCollector()
virtual PlusStatus Probe()
double LocalTimeOffsetSec
vtkMultiThreader * Threader
static std::string DATA_SOURCE_TYPE_VIDEO_TAG
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
DataSourceContainer Fields
virtual PlusStatus SetPixelType(vtkPlusChannel &aChannel, igsioCommon::VTKScalarPixelType pixelType)
virtual double GetAcquisitionRate() const
virtual PlusStatus GetImageMetaData(igsioCommon::ImageMetaDataList &imageMetaDataItems)
PlusStatus GetOutputChannelByName(vtkPlusChannel *&aChannel, const char *aChannelId)
PlusStatus GetFirstVideoSource(vtkPlusDataSource *&anImage)
double GetFilteredTimestamp(double localTimeOffsetSec)
PlusStatus AddOutputChannel(vtkPlusChannel *aChannel)
virtual igsioCommon::VTKScalarPixelType GetPixelType()
virtual PlusStatus Disconnect()
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *)
virtual PlusStatus ForceUpdate()
PlusStatus GetFirstActiveOutputVideoSource(vtkPlusDataSource *&aVideoSource)
static igsioStatus Write(const std::string &filename, igsioTrackedFrame *frame, US_IMAGE_ORIENTATION orientationInFile=US_IMG_ORIENT_MF, bool useCompression=true, bool EnableImageDataWrite=true)
double MissingInputGracePeriodSec
virtual PlusStatus GetOutputFrameSize(vtkPlusChannel &aChannel, unsigned int &x, unsigned int &y, unsigned int &z) const
virtual bool GetCorrectlyConfigured() const
virtual PlusStatus Reset()
PlusStatus GetFirstActiveTool(vtkPlusDataSource *&aTool) const
iter
Definition: algo3.m:29
unsigned long FrameNumber
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *)
ChannelContainerConstIterator GetOutputChannelsEnd() const
virtual BufferItemUidType GetOldestItemUidInBuffer()
Manages devices that record image or positional data.
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
PlusStatus GetToolByPortName(const char *aPortName, vtkPlusDataSource *&aSource)
PlusStatus AddFieldDataSource(vtkPlusDataSource *aSource)
virtual PlusStatus InternalStartRecording()
static PlusStatus GetToolReferenceFrameFromTrackedFrame(igsioTrackedFrame &aFrame, std::string &aToolReferenceFrameName)
DataSourceContainerConstIterator GetVideoSourceIteratorEnd() const
double RecordingStartTime
virtual PlusStatus SetBufferSize(vtkPlusChannel &aChannel, int FrameBufferSize, const std::string &aSourceId=std::string(""))
ChannelContainerConstIterator GetOutputChannelsStart() const
virtual PlusStatus Connect()
vtkIGSIORecursiveCriticalSection * UpdateMutex
vtkXMLDataElement * FindThisDeviceElement(vtkXMLDataElement *rootXMLElement)
virtual PlusStatus WriteToolsToSequenceFile(const std::string &filename, bool useCompression=false)
ChannelContainer::const_iterator ChannelContainerConstIterator
Definition: vtkPlusDevice.h:35
StreamBufferItem * CurrentStreamBufferItem
virtual void SetFrameNumber(unsigned long)
virtual PlusStatus GetImage(const std::string &requestedImageId, std::string &assignedImageId, const std::string &imageReferencFrameName, vtkImageData *imageData, vtkMatrix4x4 *ijkToReferenceTransform)
double DesiredTimestamp
double InternalUpdateRate
void DeepCopy(const vtkPlusDataSource &source)
#define LOCAL_LOG_DEBUG(msg)
virtual int GetNumberOfFieldDataSources() const
virtual PlusStatus StopRecording()
PlusStatus GetMatrix(vtkMatrix4x4 *outputMatrix)
static const int FRAME_RATE_AVERAGING
void SetDevice(vtkPlusDevice *_arg)
static void * vtkDataCaptureThread(vtkMultiThreader::ThreadInfo *data)
unsigned long GetIndex()
double GetInternalUpdateRate() const
virtual char * GetChannelId()
virtual US_IMAGE_TYPE GetImageType(vtkPlusChannel &aChannel)
double GetUnfilteredTimestamp(double localTimeOffsetSec)
#define LOCAL_LOG_WARNING(msg)
DataSourceContainer::iterator DataSourceContainerIterator
virtual int GetBufferSize()
int x
Definition: phidget22.h:4265
igsioVideoFrame & GetFrame()
int UpdateWithDesiredTimestamp
std::string DeviceId
const char const char * value
Definition: phidget22.h:5111
virtual PlusStatus SetImageType(vtkPlusChannel &aChannel, US_IMAGE_TYPE imageType)
static std::string DATA_SOURCE_TYPE_TOOL_TAG
virtual bool IsRecording() const
virtual bool IsConnected() const
virtual ItemStatus GetLatestStreamBufferItem(StreamBufferItem *bufferItem)
int VTKScalarPixelType
Definition: PlusCommon.h:55
virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *)
bool StartThreadForInternalUpdates
virtual FrameSizeType GetOutputFrameSize() const
virtual void SetDataCollector(vtkPlusDataCollector *_arg)
DataSourceContainerConstIterator GetToolIteratorBegin() const
static const std::string PARAMETERS_XML_ELEMENT_TAG
Definition: vtkPlusDevice.h:69
virtual ItemStatus GetStreamBufferItemFromTime(double time, StreamBufferItem *bufferItem, vtkPlusBuffer::DataItemTemporalInterpolationType interpolation)
bool HasGracePeriodExpired()
virtual int GetConnected() const
virtual PlusStatus CreateDefaultOutputChannel(const char *channelId=NULL, bool addSource=true)
bool GetStartThreadForInternalUpdates() const
Contains an optional timestamped circular buffer containing the video images and a number of timestam...
virtual ~vtkPlusDevice()
virtual PlusStatus GetBufferSize(vtkPlusChannel &aChannel, int &outVal, const std::string &aSourceId=std::string(""))
ChannelContainer OutputChannels
virtual PlusStatus AddVideoItemToVideoSources(const std::vector< vtkPlusDataSource * > &videoSources, const igsioVideoFrame &frame, long frameNumber, double unfilteredTimestamp=UNDEFINED_TIMESTAMP, double filteredTimestamp=UNDEFINED_TIMESTAMP, const igsioFieldMapType *customFields=NULL)
virtual double GetLocalTimeOffsetSec() const
Direction vectors of rods y
Definition: algo3.m:15
virtual PlusStatus NotifyConfigured()
double TimestampClosestToDesired
virtual void SetStartTime(double startTime)
std::set< std::string > ReportedUnknownTools
static vtkPlusDataSource * New()
virtual igsioCommon::VTKScalarPixelType GetPixelType(vtkPlusChannel &aChannel)
virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *)
std::string GetToolReferenceFrameName() const
void SetToolReferenceFrameName(const std::string &frameName)
virtual PlusStatus InternalDisconnect()
DataSourceContainerConstIterator GetFieldDataSourcessIteratorEnd() const
PlusStatus GetVideoSource(vtkPlusDataSource *&aVideoSource) const
PlusStatus GetVideoSource(const char *aSourceId, vtkPlusDataSource *&aVideoSource)
virtual bool IsVirtual() const
virtual int OutputChannelCount() const
PlusStatus GetTool(const char *aToolSourceId, vtkPlusDataSource *&aTool) const
ChannelContainer::iterator ChannelContainerIterator
Definition: vtkPlusDevice.h:36
vtkXMLDataElement * FindInputChannelElement(vtkXMLDataElement *rootXMLElement, const char *aChannelId)
unsigned long long BufferItemUidType
void SetOwnerDevice(vtkPlusDevice *_arg)
virtual PlusStatus SendText(const std::string &textToSend, std::string *textReceived=NULL)
FrameSizeType GetInputFrameSize() const
DataSourceContainerConstIterator GetToolIteratorEnd() const
DataSourceContainerConstIterator GetFieldDataSourcessIteratorBegin() const
vtkPlusDevice * GetOwnerDevice() const
virtual PlusStatus InternalUpdate()
void SetToolsBufferSize(int aBufferSize)
virtual bool IsResettable()
#define LOCAL_LOG_ERROR(msg)
virtual int GetNumberOfItems()
double GetTimestamp(double localTimeOffsetSec)
PlusStatus GetFieldDataSource(const char *aSourceId, vtkPlusDataSource *&aSource) const
void SetDeviceId(const std::string &id)
virtual double GetFrameTimeStamp() const
bool CorrectlyConfigured
Interface to a 3D positioning tool, video source, or generalized data stream.