8 #include "PlusConfigure.h" 18 #include <vtkStreamingVolumeCodecFactory.h> 21 #include <igsioTrackedFrame.h> 22 #include <vtkIGSIOTrackedFrameList.h> 23 #if defined PLUS_USE_VP9 24 #include <vtkVP9VolumeCodec.h> 31 #include <vtkObjectFactory.h> 32 #include <vtkXMLDataElement.h> 33 #include <vtksys/SystemTools.hxx> 42 , StartupDelaySec(0.0)
47 vtkStreamingVolumeCodecFactory* factory = vtkStreamingVolumeCodecFactory::GetInstance();
48 #if defined PLUS_USE_VP9 49 vtkSmartPointer<vtkVP9VolumeCodec> vp9Codec = vtkSmartPointer<vtkVP9VolumeCodec>::New();
50 factory->RegisterStreamingCodec(vp9Codec);
57 LOG_TRACE(
"vtkPlusDataCollector::~vtkPlusDataCollector()");
77 LOG_TRACE(
"vtkPlusDataCollector::ReadConfiguration()");
81 LOG_ERROR(
"Unable to read configuration");
88 LOG_ERROR(
"Repeated calls of vtkPlusDataCollector::ReadConfiguration are not permitted. Delete the data collector and re-create to connect to a different config file.");
92 vtkXMLDataElement* dataCollectionElement = aConfig->FindNestedElementWithName(
"DataCollection");
94 if (dataCollectionElement == NULL)
96 LOG_ERROR(
"Unable to find data collection element in XML tree!");
101 double startupDelaySec(0.0);
102 if (dataCollectionElement->GetScalarAttribute(
"StartupDelaySec", startupDelaySec))
105 LOG_DEBUG(
"StartupDelaySec: " << std::fixed << startupDelaySec);
108 std::set<std::string> existingDeviceIds;
110 for (
int i = 0;
i < dataCollectionElement->GetNumberOfNestedElements(); ++
i)
112 vtkXMLDataElement* deviceElement = dataCollectionElement->GetNestedElement(
i);
113 if (deviceElement == NULL || STRCASECMP(deviceElement->GetName(),
"Device") != 0)
120 const char* deviceId = deviceElement->GetAttribute(
"Id");
121 if (deviceId == NULL)
123 LOG_ERROR(
"Device of type " << (deviceElement->GetAttribute(
"Type") == NULL ?
"UNDEFINED" : deviceElement->GetAttribute(
"Type")) <<
" has no Id attribute");
127 if (existingDeviceIds.count(deviceId) > 0)
129 LOG_ERROR(
"Multiple devices exist with the same Id: \'" << deviceId <<
"\'");
132 existingDeviceIds.insert(deviceId);
134 if (
DeviceFactory->CreateInstance(deviceElement->GetAttribute(
"Type"), device, deviceElement->GetAttribute(
"Id")) ==
PLUS_FAIL)
136 LOG_ERROR(
"Unable to create device: " << deviceElement->GetAttribute(
"Type"));
142 LOG_ERROR(
"Failed to read parameters of device: " << deviceElement->GetAttribute(
"Id") <<
" (type: " << deviceElement->GetAttribute(
"Type") <<
")");
150 LOG_ERROR(
"No devices created. Please verify configuration file and any error produced.");
155 std::set<std::string> existingOutputChannelNames;
156 bool outputChannelFound =
false;
159 for (
ChannelContainerConstIterator outputChannelIt = (*deviceIt)->GetOutputChannelsStart(); outputChannelIt != (*deviceIt)->GetOutputChannelsEnd(); ++outputChannelIt)
161 outputChannelFound =
true;
162 const char* outputChannelId = (*outputChannelIt)->GetChannelId();
165 if (existingOutputChannelNames.count(outputChannelId) > 0)
167 LOG_ERROR(
"Same output channel Id is defined at multiple locations: " << outputChannelId);
170 existingOutputChannelNames.insert(outputChannelId);
175 if (!outputChannelFound)
177 LOG_WARNING(
"No output channels defined. Unable to locate any for data collection.");
181 for (
int i = 0;
i < dataCollectionElement->GetNumberOfNestedElements(); ++
i)
183 vtkXMLDataElement* deviceElement = dataCollectionElement->GetNestedElement(
i);
184 if (deviceElement == NULL || STRCASECMP(deviceElement->GetName(),
"Device") != 0)
192 LOG_ERROR(
"Device " << deviceElement->GetAttribute(
"Id") <<
" does not exist.");
195 vtkXMLDataElement* inputChannelsElement = deviceElement->FindNestedElementWithName(
"InputChannels");
196 if (inputChannelsElement == NULL)
201 for (
int i = 0;
i < inputChannelsElement->GetNumberOfNestedElements(); ++
i)
203 vtkXMLDataElement* inputChannelElement = inputChannelsElement->GetNestedElement(
i);
204 if (STRCASECMP(inputChannelElement->GetName(),
"InputChannel") == 0)
207 const char* inputChannelId = inputChannelElement->GetAttribute(
"Id");
208 if (inputChannelId == NULL)
210 LOG_ERROR(
"Device " << deviceElement->GetAttribute(
"Id") <<
" has an input channel without Id attribute.");
223 if (aChannel == NULL)
225 LOG_ERROR(
"Device " << deviceElement->GetAttribute(
"Id") <<
" is specified to use channel " << inputChannelId <<
" as input, but an output channel by this Id does not exist");
230 LOG_ERROR(
"Failed to add input channel " << inputChannelId <<
" to device " << deviceElement->GetAttribute(
"Id"));
241 LOG_ERROR(
"Device: " << (*it)->GetDeviceId() <<
" reports incorrect configuration. Please verify configuration.");
254 if (element ==
nullptr)
264 LOG_ERROR(
"Datacollector failed to read configuration");
274 LOG_TRACE(
"vtkPlusDataCollector::WriteConfiguration()");
276 vtkXMLDataElement* dataCollectionConfig = igsioXmlUtils::GetNestedElementWithName(aConfig,
"DataCollection");
277 if (dataCollectionConfig == NULL)
279 LOG_ERROR(
"Cannot find DataCollection element in XML tree!");
293 LOG_ERROR(
"Failed to save device configuration " << device->
GetDeviceId());
304 if (factory !=
nullptr)
319 LOG_TRACE(
"vtkPlusDataCollector::Start()");
323 const double startTime = vtkIGSIOAccurateTimer::GetSystemTime();
331 LOG_ERROR(
"Failed to start data acquisition for device " << device->
GetDeviceId() <<
".");
337 LOG_DEBUG(
"vtkPlusDataCollector::Start -- wait " << std::fixed << this->
StartupDelaySec <<
" sec for buffer init...");
339 vtkIGSIOAccurateTimer::DelayWithEventProcessing(this->
StartupDelaySec);
349 LOG_TRACE(
"vtkPlusDataCollector::Stop()");
359 LOG_TRACE(
"vtkPlusDataCollector::Connect()");
369 LOG_ERROR(
"Unable to connect device: " << device->
GetDeviceId() <<
".");
382 LOG_WARNING(
"Failed to set loop times!");
393 LOG_TRACE(
"vtkPlusDataCollector::Disconnect()");
403 LOG_ERROR(
"Unable to disconnect device: " << device->
GetDeviceId() <<
".");
409 LOG_DEBUG(
"vtkPlusDataCollector::Disconnect: All devices have been disconnected");
417 LOG_TRACE(
"vtkPlusDataCollector::PrintSelf()");
419 this->Superclass::PrintSelf(os, indent);
423 os << indent <<
"Device: " << std::endl;
424 (*it)->PrintSelf(os, indent);
431 LOG_TRACE(
"vtkPlusDataCollector::GetDevice( aDevice, " << aDeviceId <<
")");
450 LOG_TRACE(
"vtkPlusDataCollector::GetDevices()");
456 OutVector.push_back(*it);
477 LOG_TRACE(
"vtkPlusDataCollector::DumpBuffersToDirectory(" << aDirectory <<
")");
480 std::string dateAndTime = vtksys::SystemTools::GetCurrentDateTime(
"%Y%m%d_%H%M%S");
488 LOG_INFO(
"Write device buffer to " << outputDeviceBufferSequenceFileName);
494 LOG_ERROR(
"Unable to retrieve the video source in the device.");
519 LOG_TRACE(
"vtkPlusDataCollector::GetTrackingData(" << aRequestedChannel->
GetChannelId() <<
", " << aTimestampFrom <<
")");
521 if (aTrackedFrameList == NULL)
523 LOG_ERROR(
"Unable to get tracked frame list - output tracked frame list is NULL");
530 LOG_ERROR(
"Unable to get tracked frame list - Tracking is not enabled");
538 LOG_ERROR(
"Unable to get tracked frame list - there is no active tool!");
544 LOG_DEBUG(
"vtkPlusDataCollector::GetTrackingData: the tracking buffer is empty, no items will be returned");
551 for (
BufferItemUidType itemUid = oldestItemUid; itemUid <= latestItemUid; ++itemUid)
553 double itemTimestamp = 0;
559 if (itemTimestamp <= aTimestampFrom)
564 aTimestampFrom = itemTimestamp;
566 igsioTrackedFrame* trackedFrame =
new igsioTrackedFrame;
569 LOG_ERROR(
"Unable to get tracking data by time: " << std::fixed << itemTimestamp);
573 if (aTrackedFrameList->TakeTrackedFrame(trackedFrame, vtkIGSIOTrackedFrameList::SKIP_INVALID_FRAME) !=
PLUS_SUCCESS)
575 LOG_ERROR(
"Unable to add tracking data to the list!");
586 LOG_TRACE(
"vtkPlusDataCollector::GetVideoData(" << aRequestedChannel->
GetChannelId() <<
", " << aTimestampFrom <<
")");
588 if (aTrackedFrameList == NULL)
590 LOG_ERROR(
"Unable to get tracked frame list - output tracked frmae list is NULL");
598 LOG_DEBUG(
"vtkPlusDataCollector::GetVideoData: the video buffer is empty, no items will be returned");
605 for (
BufferItemUidType itemUid = oldestItemUid; itemUid <= latestItemUid; ++itemUid)
607 double itemTimestamp = 0;
613 if (itemTimestamp <= aTimestampFrom)
618 aTimestampFrom = itemTimestamp;
620 igsioTrackedFrame* trackedFrame =
new igsioTrackedFrame;
624 LOG_ERROR(
"Couldn't get video buffer item by frame UID: " << itemUid);
630 trackedFrame->SetImageData(currentStreamBufferItem.
GetFrame());
631 trackedFrame->SetTimestamp(itemTimestamp);
635 for (igsioFieldMapType::const_iterator fieldIterator = fieldMap.begin(); fieldIterator != fieldMap.end(); fieldIterator++)
637 trackedFrame->SetFrameField(fieldIterator->first, fieldIterator->second.second, fieldIterator->second.first);
641 if (aTrackedFrameList->TakeTrackedFrame(trackedFrame, vtkIGSIOTrackedFrameList::SKIP_INVALID_FRAME) !=
PLUS_SUCCESS)
643 LOG_ERROR(
"Unable to add video data to the list!");
654 LOG_TRACE(
"vtkPlusDataCollector::SetLoopTimes");
656 double latestLoopStartTime(0);
657 double earliestLoopStopTime(0);
658 bool isLoopStartStopTimeInitialized =
false;
663 if (savedDataSource == NULL)
670 LOG_DEBUG(
"The device " << savedDataSource->
GetDeviceId() <<
" does not use original timestamps, therefore synchronization of loop time is not applicable");
673 double loopStartTime = 0;
674 double loopStopTime = 0;
676 if (loopStartTime > latestLoopStartTime || !isLoopStartStopTimeInitialized)
678 latestLoopStartTime = loopStartTime;
680 if (loopStopTime < earliestLoopStopTime || !isLoopStartStopTimeInitialized)
682 earliestLoopStopTime = loopStopTime;
684 isLoopStartStopTimeInitialized =
true;
687 if (!isLoopStartStopTimeInitialized)
689 LOG_DEBUG(
"No saved data source devices were found that use original timestamps, so synchronization of loop times is not performed");
693 if (latestLoopStartTime >= earliestLoopStopTime)
695 LOG_ERROR(
"Data sets in saved data source devices do not have a common time range. Synchronization of loop times is not possible.");
703 if (savedDataSource == NULL)
708 savedDataSource->
SetLoopTimeRange(latestLoopStartTime, earliestLoopStopTime);
717 if (aDevice ==
nullptr)
719 LOG_ERROR(
"Null device sent to vtkPlusDataCollector::AddDevice");
726 LOG_ERROR(
"Device with ID: " << aDevice->
GetDeviceId() <<
" already exists.");
740 if ((*it)->GetOutputChannelByName(aChannel, aChannelId.c_str()) ==
PLUS_SUCCESS)
757 LOG_ERROR(
"Cannot return first device: No devices to return.");
763 if ((*it)->OutputChannelCount() == 0)
768 aChannel = *(*it)->GetOutputChannelsStart();
virtual BufferItemUidType GetLatestItemUidInBuffer()
PlusStatus GetDevices(DeviceCollection &OutVector) const
PlusStatus AddInputChannel(vtkPlusChannel *aChannel)
vtkXMLDataElement * CreateDeviceSetConfigurationFromFile(const std::string &aConfigFile)
std::string GetOutputPath(const std::string &subPath)
virtual PlusStatus WriteToSequenceFile(const char *filename, bool useCompression=false)
Abstract interface for tracker and video devices.
std::vector< vtkPlusDevice * >::const_iterator DeviceCollectionConstIterator
vtkSmartPointer< vtkPlusDeviceFactory > DeviceFactory
virtual ItemStatus GetStreamBufferItem(BufferItemUidType uid, StreamBufferItem *bufferItem)
PlusStatus GetDevice(vtkPlusDevice *&aDevice, const std::string &aDeviceId) const
virtual PlusStatus GetTrackedFrame(double timestamp, igsioTrackedFrame &trackedFrame, bool enableImageData=true)
virtual PlusStatus StartRecording()
virtual PlusStatus GetVideoData(vtkPlusChannel *aRequestedChannel, double &aTimestamp, vtkIGSIOTrackedFrameList *aTrackedFrameList)
virtual std::string GetDeviceId() const
void SetLoopTimeRange(double loopStartTime, double loopStopTime)
std::vector< vtkPlusDevice * > DeviceCollection
vtkPlusDeviceFactory & GetDeviceFactory()
static vtkPlusConfig * GetInstance()
DeviceCollectionConstIterator GetDeviceConstIteratorBegin() const
PlusStatus GetFirstChannel(vtkPlusChannel *&aChannel) const
igsioFieldMapType GetFrameFieldMap()
PlusStatus GetOutputChannelByName(vtkPlusChannel *&aChannel, const char *aChannelId)
virtual ItemStatus GetTimeStamp(BufferItemUidType uid, double ×tamp)
virtual PlusStatus Disconnect()
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *)
virtual bool GetUseOriginalTimestamps()
virtual PlusStatus SetLoopTimes()
PlusStatus GetFirstActiveTool(vtkPlusDataSource *&aTool) const
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *)
ChannelContainerConstIterator GetOutputChannelsEnd() const
DeviceCollectionConstIterator GetDeviceConstIteratorEnd() const
virtual BufferItemUidType GetOldestItemUidInBuffer()
Manages devices that record image or positional data.
ChannelContainerConstIterator GetOutputChannelsStart() const
virtual PlusStatus Connect()
ChannelContainer::const_iterator ChannelContainerConstIterator
PlusStatus ReadConfiguration(vtkXMLDataElement *aConfig)
void GetLoopTimeRange(double &loopStartTime, double &loopStopTime)
virtual double GetStartupDelaySec()
void SetDeviceFactory(vtkSmartPointer< vtkPlusDeviceFactory > factory)
virtual char * GetChannelId()
vtkStandardNewMacro(vtkPlusDataCollector)
PlusStatus GetTrackingData(vtkPlusChannel *aRequestedChannel, double &aTimestampFrom, vtkIGSIOTrackedFrameList *aTrackedFrameList)
igsioVideoFrame & GetFrame()
PlusStatus WriteConfiguration(vtkXMLDataElement *aConfig)
virtual void SetStartupDelaySec(double)
bool GetTrackingEnabled() const
Factory class of supported devices.
Class for providing VTK video input interface from sequence fileAttributes:
virtual void SetDataCollector(vtkPlusDataCollector *_arg)
std::vector< vtkPlusDevice * >::iterator DeviceCollectionIterator
PlusStatus AddDevice(vtkPlusDevice *aDevice)
Contains an optional timestamped circular buffer containing the video images and a number of timestam...
virtual void SetStartTime(double startTime)
void SetDeviceSetConfigurationFileName(const std::string &aFilePath)
bool GetConnected() const
PlusStatus GetChannel(vtkPlusChannel *&aChannel, const std::string &aChannelId) const
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
virtual ~vtkPlusDataCollector()
PlusStatus GetVideoSource(vtkPlusDataSource *&aVideoSource) const
ChannelContainer::iterator ChannelContainerIterator
unsigned long long BufferItemUidType
vtkPlusDevice * GetOwnerDevice() const
PlusStatus DumpBuffersToDirectory(const char *aDirectory)
void SetDeviceSetConfigurationData(vtkXMLDataElement *deviceSetConfigurationData)
virtual int GetNumberOfItems()
Interface to a 3D positioning tool, video source, or generalized data stream.