7 #include "PlusConfigure.h" 15 #include <vtkImageData.h> 16 #include <vtkObjectFactory.h> 19 #include "3DCamera.hpp" 38 struct StreamConfigBase
41 StreamInfo StreamProps;
45 struct PCLStreamConfig : StreamConfigBase
49 struct ConcreteStreamConfig : StreamConfigBase
55 struct DepthStreamConfig : ConcreteStreamConfig
60 std::string convertErrorCode(ERROR_CODE error)
64 case ERROR_CODE::ERROR_PARAM:
66 case ERROR_CODE::ERROR_DEVICE_NOT_FOUND:
67 return "Device not found";
68 case ERROR_CODE::ERROR_DEVICE_NOT_CONNECT:
69 return "Device not connected";
70 case ERROR_CODE::ERROR_DEVICE_BUSY:
72 case ERROR_CODE::ERROR_STREAM_NOT_START:
73 return "Device not started";
74 case ERROR_CODE::ERROR_STREAM_BUSY:
76 case ERROR_CODE::ERROR_FRAME_TIMEOUT:
77 return "Frame timeout";
78 case ERROR_CODE::ERROR_NOT_SUPPORT:
79 return "Not supported";
80 case ERROR_CODE::ERROR_PROPERTY_GET_FAILED:
81 return "Getting property failed";
82 case ERROR_CODE::ERROR_PROPERTY_SET_FAILED:
83 return "Setting property failed";
92 class vtkPlusRevopoint3DCamera::vtkInternal
96 DepthStreamConfig DepthStream;
97 PCLStreamConfig PCLStream;
98 cs::ICameraPtr Camera;
99 cs::IFramePtr DepthFrame;
100 std::unique_ptr<float[]> PCLFrame;
101 int AvailableStreamsFlag{0};
106 this->Camera = cs::getCameraPtr();
111 if (!this->DepthStream.Id.empty())
113 this->AvailableStreamsFlag |= RevoSourceType::DEPTH;
116 if (!this->PCLStream.Id.empty())
118 this->AvailableStreamsFlag |= RevoSourceType::PCL;
121 if ((this->AvailableStreamsFlag & RevoSourceType::PCL) && !(this->AvailableStreamsFlag & RevoSourceType::DEPTH))
123 LOG_ERROR(
"Invalid configuration: PCL stream is required but no Depth stream set");
132 std::vector<StreamInfo> streamProps;
133 this->Camera->getStreamInfos(STREAM_TYPE::STREAM_TYPE_DEPTH, streamProps);
135 bool foundMatchingConfig{
false};
136 for (
auto streamProp : streamProps)
138 LOG_TRACE(
"New stream configuration for format: " << streamProp.format);
139 if (streamProp.format == this->DepthStream.StreamProps.format)
141 LOG_INFO(
"New depth stream compliant configuration: " << streamProp.width <<
"x" << streamProp.height <<
"@" << streamProp.fps);
142 if (this->DepthStream.StreamProps.width != streamProp.width)
147 if (this->DepthStream.StreamProps.fps > streamProp.fps)
149 this->DepthStream.StreamProps.fps = streamProp.fps;
150 LOG_WARNING(
"Expected frame rate too high for current bandwidth. Actual framerate will be @" << streamProp.fps <<
" fps.");
153 this->DepthStream.StreamProps.height = streamProp.height;
154 foundMatchingConfig =
true;
159 if (!foundMatchingConfig)
161 LOG_ERROR(
"No matching configuration found");
162 LOG_ERROR(
"Available configurations:");
163 for (
auto streamProp : streamProps)
165 if (streamProp.format == this->DepthStream.StreamProps.format)
167 LOG_ERROR(
"- " << streamProp.width <<
"x" << streamProp.height <<
"@" << streamProp.fps);
173 this->Camera->getIntrinsics(STREAM_TYPE::STREAM_TYPE_DEPTH, this->DepthStream.Intr);
174 this->Camera->getExtrinsics(this->DepthStream.Extr);
176 PropertyExtension
value;
177 value.depthRange.min = this->DepthStream.DepthRange[0];
178 value.depthRange.max = this->DepthStream.DepthRange[1];
179 value.algorithmContrast = 5;
181 auto ret = this->Camera->setPropertyExtension(PROPERTY_TYPE_EXTENSION::PROPERTY_EXT_DEPTH_RANGE,
value);
182 if (ret != ERROR_CODE::SUCCESS)
184 LOG_ERROR(
"Failed to set camera depth range: " << convertErrorCode(ret));
193 this->PCLStream.StreamProps = this->DepthStream.StreamProps;
199 if ((this->AvailableStreamsFlag & RevoSourceType::DEPTH) && this->UpdateDepthStreamConfig() !=
PLUS_SUCCESS)
204 if ((this->AvailableStreamsFlag & RevoSourceType::PCL) && this->UpdatePCLStreamConfig() !=
PLUS_SUCCESS)
217 auto ret = this->Camera->connect();
218 if (ret != ERROR_CODE::SUCCESS)
220 LOG_ERROR(
"Failed to connect camera: " << convertErrorCode(ret));
229 auto ret = this->Camera->disconnect();
230 if (ret != ERROR_CODE::SUCCESS)
232 LOG_ERROR(
"Failed to disconnect camera: " << convertErrorCode(ret));
241 auto ret = this->Camera->startStream(STREAM_TYPE::STREAM_TYPE_DEPTH, this->DepthStream.StreamProps);
242 if (ret != ERROR_CODE::SUCCESS)
244 LOG_ERROR(
"Failed to start camera: " << convertErrorCode(ret));
253 auto ret = this->Camera->stopStream(STREAM_TYPE::STREAM_TYPE_DEPTH);
254 if (ret != ERROR_CODE::SUCCESS)
256 LOG_ERROR(
"Failed to stop camera: " << convertErrorCode(ret));
265 if (this->AvailableStreamsFlag & RevoSourceType::DEPTH)
267 this->DepthFrame.reset();
268 auto ret = this->Camera->getFrame(STREAM_TYPE::STREAM_TYPE_DEPTH, DepthFrame);
269 if (ret != ERROR_CODE::SUCCESS)
271 LOG_ERROR(
"Failed to retrieve frame: " << convertErrorCode(ret));
275 if ((this->AvailableStreamsFlag & RevoSourceType::PCL) && this->IsDepthFrameValid())
278 PropertyExtension
value;
280 this->Camera->getPropertyExtension(PROPERTY_EXT_DEPTH_SCALE,
value))
282 scale =
value.depthScale;
286 pc.generatePoints(reinterpret_cast<unsigned short*>(const_cast<char*>(this->DepthFrame->getData())),
287 this->DepthFrame->getWidth(), this->DepthFrame->getHeight(),
288 scale, &this->DepthStream.Intr,
nullptr, &this->DepthStream.Extr);
289 auto vertices = pc.getVertices();
290 this->PCLFrame.reset(
new float[vertices.size() * 3]);
292 for (std::size_t idx = 0; idx < vertices.size(); ++idx)
294 this->PCLFrame[idx * 3] = vertices[idx].x;
295 this->PCLFrame[idx * 3 + 1] = vertices[idx].y;
296 this->PCLFrame[idx * 3 + 2] = vertices[idx].z;
301 bool IsDepthFrameValid()
const 303 return this->DepthFrame && !(this->DepthFrame->empty()) && (this->DepthFrame->getWidth() == this->DepthStream.StreamProps.width) &&
304 (this->DepthFrame->getHeight() == this->DepthStream.StreamProps.height);
310 : Internal(new vtkInternal(this))
319 delete this->Internal;
320 this->Internal =
nullptr;
328 os << indent <<
"Revopoint Surface Configuration" << std::endl;
330 if (this->Internal->AvailableStreamsFlag & RevoSourceType::DEPTH)
332 os << indent <<
"DEPTH Stream" << std::endl;
333 os << indent <<
"Source: " << this->Internal->DepthStream.Id << std::endl;
334 os << indent << indent <<
"Frame Rate: " << this->Internal->DepthStream.StreamProps.fps << std::endl;
335 os << indent << indent <<
"Frame Width: " << this->Internal->DepthStream.StreamProps.width << std::endl;
336 os << indent << indent <<
"Frame Height: " << this->Internal->DepthStream.StreamProps.height << std::endl;
337 os << indent << indent <<
"Depth Range: [" << this->Internal->DepthStream.DepthRange[0] <<
"," << Internal->DepthStream.DepthRange[1] <<
"]" << std::endl;
340 if (this->Internal->AvailableStreamsFlag & RevoSourceType::PCL)
342 os << indent <<
"PCL Stream" << std::endl;
343 os << indent <<
"Source: " << this->Internal->PCLStream.Id << std::endl;
351 XML_FIND_NESTED_ELEMENT_REQUIRED(dataSourcesElement, deviceConfig,
"DataSources");
353 LOG_TRACE(
"Reading custom configuration fields in " << dataSourcesElement->GetNumberOfNestedElements() <<
" nested elements");
355 for (
int nestedElementIndex = 0; nestedElementIndex < dataSourcesElement->GetNumberOfNestedElements(); ++nestedElementIndex)
357 vtkXMLDataElement* dataElement = dataSourcesElement->GetNestedElement(nestedElementIndex);
358 if (std::string(dataElement->GetName()) !=
"DataSource")
363 LOG_TRACE(
"Found a new data source");
364 if (dataElement->GetAttribute(
"Type") !=
nullptr && std::string(dataElement->GetAttribute(
"Type")) ==
"Video")
366 const char* toolId = dataElement->GetAttribute(
"Id");
367 if (toolId ==
nullptr)
369 LOG_ERROR(
"Failed to initialize Revopoint Surface DataSource: Id is missing");
373 LOG_TRACE(
"Data source name: " << toolId);
376 XML_READ_ENUM2_ATTRIBUTE_NONMEMBER_REQUIRED(FrameType, sourceType, dataElement,
"DEPTH", RevoSourceType::DEPTH,
"PCL", RevoSourceType::PCL);
378 if (sourceType == RevoSourceType::DEPTH)
380 DepthStreamConfig stream;
382 stream.DepthRange[0] = 5;
383 stream.DepthRange[1] = 500;
384 XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_REQUIRED(
int, FrameRate, stream.StreamProps.fps, dataElement);
385 XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_REQUIRED(
int, FrameWidth, stream.StreamProps.width, dataElement);
386 XML_READ_VECTOR_ATTRIBUTE_NONMEMBER_OPTIONAL(
int, 2, DepthRange, stream.DepthRange, dataElement);
387 stream.StreamProps.format = STREAM_FORMAT::STREAM_FORMAT_Z16;
388 this->Internal->DepthStream = stream;
392 this->Internal->PCLStream.Id = toolId;
397 LOG_ERROR(
"DataSource with unknown type.");
402 if (this->Internal->DepthStream.Id.empty())
404 LOG_ERROR(
"Required DEPTH type data source is missing.");
421 return this->Internal->CheckBasicConfig();
427 if (this->Internal->AvailableStreamsFlag & RevoSourceType::DEPTH)
429 GetVideoSource(this->Internal->DepthStream.Id.c_str(), this->Internal->DepthStream.Source);
430 if (Internal->DepthStream.Source ==
nullptr)
432 LOG_ERROR(
"Invalid source for tool id " << this->Internal->DepthStream.Id);
437 if (this->Internal->AvailableStreamsFlag & RevoSourceType::PCL)
439 GetVideoSource(this->Internal->PCLStream.Id.c_str(), this->Internal->PCLStream.Source);
440 if (Internal->PCLStream.Source ==
nullptr)
442 LOG_ERROR(
"Invalid source for tool id " << this->Internal->PCLStream.Id);
453 return this->Internal->UpdateConfig();
459 return this->Internal->Disconnect();
465 this->FrameNumber = 0;
467 return this->Internal->Start();
473 return this->Internal->Stop();
481 this->Internal->Update();
483 if ((this->Internal->AvailableStreamsFlag & RevoSourceType::DEPTH) && this->Internal->DepthStream.Source->GetNumberOfItems() == 0)
486 LOG_TRACE(
"Setting up depth frame");
487 this->Internal->DepthStream.Source->SetImageType(US_IMG_BRIGHTNESS);
488 this->Internal->DepthStream.Source->SetPixelType(VTK_TYPE_UINT16);
489 this->Internal->DepthStream.Source->SetNumberOfScalarComponents(1);
490 this->Internal->DepthStream.Source->SetInputFrameSize(this->Internal->DepthStream.StreamProps.width, this->Internal->DepthStream.StreamProps.height, 1);
493 if ((this->Internal->AvailableStreamsFlag & RevoSourceType::PCL) && this->Internal->PCLStream.Source->GetNumberOfItems() == 0)
495 LOG_TRACE(
"Setting up pcl frame");
496 this->Internal->PCLStream.Source->SetImageType(US_IMG_BRIGHTNESS);
497 this->Internal->PCLStream.Source->SetPixelType(VTK_TYPE_FLOAT32);
498 this->Internal->PCLStream.Source->SetNumberOfScalarComponents(3);
499 this->Internal->PCLStream.Source->SetInputFrameSize(this->Internal->PCLStream.StreamProps.width, this->Internal->PCLStream.StreamProps.height, 1);
502 if (this->Internal->AvailableStreamsFlag & RevoSourceType::DEPTH)
504 if (!this->Internal->IsDepthFrameValid())
506 if (this->Internal->DepthStream.Source->GetNumberOfItems() == 0)
508 LOG_TRACE(
"Waiting for Revopoint Surface depth images");
512 LOG_WARNING(
"Failed to get Revopoint Surface depth image");
516 FrameSizeType frameSizeDepth = {static_cast<unsigned>(this->Internal->DepthStream.StreamProps.width), static_cast<unsigned>(this->Internal->DepthStream.StreamProps.height), 1};
517 if (this->Internal->DepthStream.Source->AddItem(reinterpret_cast<void*>(const_cast<char*>(this->Internal->DepthFrame->getData(FRAME_DATA_FORMAT::FRAME_DATA_FORMAT_Z16))), this->Internal->DepthStream.Source->GetInputImageOrientation(), frameSizeDepth, VTK_TYPE_UINT16, 1, US_IMG_BRIGHTNESS, 0, this->FrameNumber) ==
PLUS_FAIL)
519 LOG_ERROR(
"Unable to send DEPTH image. Skipping frame.");
525 if (this->Internal->AvailableStreamsFlag & RevoSourceType::PCL)
527 FrameSizeType frameSizeDepth = {static_cast<unsigned>(this->Internal->PCLStream.StreamProps.width), static_cast<unsigned>(this->Internal->PCLStream.StreamProps.height), 1};
528 if (this->Internal->PCLStream.Source->AddItem(reinterpret_cast<void*>(this->Internal->PCLFrame.get()), this->Internal->PCLStream.Source->GetInputImageOrientation(), frameSizeDepth, VTK_TYPE_FLOAT32, 3, US_IMG_BRIGHTNESS, 0, this->FrameNumber) ==
PLUS_FAIL)
530 LOG_ERROR(
"Unable to send PCL image. Skipping frame.");
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
PlusStatus InternalStartRecording()
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
vtkStandardNewMacro(vtkPlusRevopoint3DCamera)
vtkPlusRevopoint3DCamera()
bool RequireImageOrientationInConfiguration
~vtkPlusRevopoint3DCamera()
virtual PlusStatus Disconnect()
PlusStatus WriteConfiguration(vtkXMLDataElement *config)
virtual PlusStatus InternalDisconnect()
virtual PlusStatus NotifyConfigured()
virtual PlusStatus Connect()
double InternalUpdateRate
PlusStatus InternalStopRecording()
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement)
virtual PlusStatus InternalConnect()
const char const char * value
bool StartThreadForInternalUpdates
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *config)
Interface class to Revopoint 3D cameras.
PlusStatus GetVideoSource(const char *aSourceId, vtkPlusDataSource *&aVideoSource)
virtual void PrintSelf(ostream &os, vtkIndent indent)
virtual PlusStatus InternalUpdate()
Interface to a 3D positioning tool, video source, or generalized data stream.