29#include <pcl/io/openni2/openni2_device_manager.h>
30#include <pcl/io/pcd_io.h>
38#include <Calibration/Calibration.h>
39#include <Image/ImageProcessor.h>
46#if PCL_VERSION > PCL_VERSION_CALC(1, 12, 0)
48using FctT = std::function<T>;
51using FctT = boost::function<T>;
101 grabberInterface.reset();
105 OpenNIPointCloudProvider::loadCalibrationFile(std::string fileName,
106 visionx::CameraParameters& calibration)
110 FileStorage fs(fileName, FileStorage::READ);
118 std::string cameraName = fs[
"camera_name"];
119 ARMARX_LOG <<
"loading calibration file for " << cameraName;
123 int imageWidth = fs[
"image_width"];
124 int imageHeight = fs[
"image_height"];
126 if (imageWidth != dimensions(0) || imageHeight != dimensions(1))
132 Mat cameraMatrix, distCoeffs;
134 fs[
"camera_matrix"] >> cameraMatrix;
135 fs[
"distortion_coefficients"] >> distCoeffs;
137 for (
int i = 0; i < 5; i++)
139 calibration.distortion[i] = distCoeffs.at<
float>(0, i);
142 calibration.focalLength[0] = cameraMatrix.at<
float>(0, 0);
143 calibration.focalLength[1] = cameraMatrix.at<
float>(1, 1);
145 calibration.principalPoint[0] = cameraMatrix.at<
float>(0, 2);
146 calibration.principalPoint[1] = cameraMatrix.at<
float>(1, 2);
160 width = dimensions(0);
161 height = dimensions(1);
163 newPointCloudCapturingRequested =
true;
164 newImageCapturingRequested =
true;
169 using namespace pcl::io::openni2;
170 auto connectedDeviceURIs = *OpenNI2DeviceManager::getInstance()->getConnectedDeviceURIs();
171 ARMARX_INFO <<
"connected devices: " << connectedDeviceURIs;
172 if (!configuredDeviceId.empty() && configuredDeviceId.size() > 2)
176 std::string deviceIndexNumber;
177 ARMARX_INFO <<
"Trying to find device with configured URI: '" << configuredDeviceId
179 for (
auto& uri : connectedDeviceURIs)
181 if (uri == configuredDeviceId)
183 ARMARX_INFO <<
"Found device with URI " << configuredDeviceId <<
" at index "
185 deviceIndexNumber =
"#" + std::to_string(i);
190 if (deviceIndexNumber.empty())
192 ARMARX_WARNING <<
"Could not find device with URI: " << configuredDeviceId
193 <<
" - Connecting now to any device";
194 grabberInterface.reset(
new pcl::io::OpenNI2Grabber());
198 grabberInterface.reset(
new pcl::io::OpenNI2Grabber(deviceIndexNumber));
201 else if (!configuredDeviceId.empty())
204 ARMARX_INFO <<
"Connecting to device id " << configuredDeviceId;
205 grabberInterface.reset(
new pcl::io::OpenNI2Grabber(
"#" + configuredDeviceId));
210 grabberInterface.reset(
new pcl::io::OpenNI2Grabber());
214 visionx::CameraParameters RGBCameraIntrinsics;
215 RGBCameraIntrinsics.focalLength.resize(2, 0.0f);
216 RGBCameraIntrinsics.principalPoint.resize(2, 0.0f);
217 RGBCameraIntrinsics.distortion.resize(4, 0.0f);
220 RGBCameraIntrinsics.rotation =
222 RGBCameraIntrinsics.translation =
226 std::string rgbCameraCalibrationFile =
228 if (!rgbCameraCalibrationFile.empty() &&
229 loadCalibrationFile(rgbCameraCalibrationFile, RGBCameraIntrinsics))
232 grabberInterface->setRGBCameraIntrinsics(RGBCameraIntrinsics.focalLength[0],
233 RGBCameraIntrinsics.focalLength[1],
234 RGBCameraIntrinsics.principalPoint[0],
235 RGBCameraIntrinsics.principalPoint[1]);
240 ARMARX_INFO <<
"unable to load calibration file. using default values.";
241 double fx, fy, cx, cy;
242 grabberInterface->getRGBCameraIntrinsics(fx, fy, cx, cy);
246 if (grabberInterface->getDevice()->hasColorSensor())
248 fx = fy = grabberInterface->getDevice()->getColorFocalLength();
251 cx = (width - 1) / 2.0;
252 cy = (height - 1) / 2.0;
254 ARMARX_INFO <<
"rgb camera fx: " << fx <<
" fy: " << fy <<
" cx: " << cx
257 RGBCameraIntrinsics.principalPoint[0] = cx;
258 RGBCameraIntrinsics.principalPoint[1] = cy;
259 RGBCameraIntrinsics.focalLength[0] = fx;
260 RGBCameraIntrinsics.focalLength[1] = fy;
261 RGBCameraIntrinsics.width = width;
262 RGBCameraIntrinsics.height = height;
265 visionx::CameraParameters depthCameraIntrinsics;
266 depthCameraIntrinsics.focalLength.resize(2, 0.0f);
267 depthCameraIntrinsics.principalPoint.resize(2, 0.0f);
268 depthCameraIntrinsics.distortion.resize(4, 0.0f);
269 depthCameraIntrinsics.rotation =
271 depthCameraIntrinsics.translation =
274 std::string depthCameraCalibrationFile =
276 if (!depthCameraCalibrationFile.empty() &&
277 loadCalibrationFile(depthCameraCalibrationFile, depthCameraIntrinsics))
280 grabberInterface->setDepthCameraIntrinsics(depthCameraIntrinsics.focalLength[0],
281 depthCameraIntrinsics.focalLength[1],
282 depthCameraIntrinsics.principalPoint[0],
283 depthCameraIntrinsics.principalPoint[1]);
288 ARMARX_INFO <<
"unable to load calibration file. using default values.";
289 double fx, fy, cx, cy;
290 grabberInterface->getDepthCameraIntrinsics(fx, fy, cx, cy);
294 if (grabberInterface->getDevice()->hasDepthSensor())
296 fx = fy = grabberInterface->getDevice()->getDepthFocalLength();
298 cx = (width - 1) / 2.0;
299 cy = (height - 1) / 2.0;
301 ARMARX_INFO <<
"depth camera fx: " << fx <<
" fy: " << fy <<
" cx: " << cx
304 depthCameraIntrinsics.principalPoint[0] = cx;
305 depthCameraIntrinsics.principalPoint[1] = cy;
306 depthCameraIntrinsics.focalLength[0] = fx;
307 depthCameraIntrinsics.focalLength[1] = fy;
308 depthCameraIntrinsics.width = width;
309 depthCameraIntrinsics.height = height;
316 calibration.calibrationLeft.cameraParam = RGBCameraIntrinsics;
317 calibration.calibrationRight.cameraParam = depthCameraIntrinsics;
318 calibration.rectificationHomographyLeft =
320 calibration.rectificationHomographyRight =
323 ARMARX_INFO <<
"Baseline:" << grabberInterface->getDevice()->getBaseline();
325 pointcloudBuffer = pcl::PointCloud<pcl::PointXYZRGBA>::Ptr(
326 new pcl::PointCloud<pcl::PointXYZRGBA>(width, height));
328 rgbImages =
new CByteImage*[2];
330 rgbImages[0] =
new CByteImage(width, height, CByteImage::eRGB24);
331 rgbImages[1] =
new CByteImage(width, height, CByteImage::eRGB24);
332 ::ImageProcessor::Zero(rgbImages[0]);
333 ::ImageProcessor::Zero(rgbImages[1]);
335 if (grabberInterface->getDevice()->hasColorSensor())
337 FctT<void(
const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> pointCloudCallback =
340 callbackFunctionForOpenNIGrabberPointCloudWithRGB(std::forward<
decltype(PH1)>(PH1));
342 grabberInterface->registerCallback(pointCloudCallback);
344 FctT<void(
const pcl::io::Image::Ptr&,
const pcl::io::DepthImage::Ptr&,
float)>
345 imageCallback = [
this](
auto&& PH1,
auto&& PH2,
auto&& PH3)
347 grabImages(std::forward<
decltype(PH1)>(PH1),
348 std::forward<
decltype(PH2)>(PH2),
349 std::forward<
decltype(PH3)>(PH3));
351 grabberInterface->registerCallback(imageCallback);
355 ARMARX_INFO <<
"depth sensor. no color image available.";
357 FctT<void(
const pcl::PointCloud<pcl::PointXYZ>::ConstPtr&)> pointCloudCallback =
359 { callbackFunctionForOpenNIGrabberPointCloud(std::forward<
decltype(PH1)>(PH1)); };
360 grabberInterface->registerCallback(pointCloudCallback);
362 FctT<void(
const pcl::io::IRImage::Ptr&,
const pcl::io::DepthImage::Ptr&,
float)>
363 imageCallback = [
this](
auto&& PH1,
auto&& PH2,
auto&& PH3)
365 grabDepthImage(std::forward<
decltype(PH1)>(PH1),
366 std::forward<
decltype(PH2)>(PH2),
367 std::forward<
decltype(PH3)>(PH3));
369 grabberInterface->registerCallback(imageCallback);
379 {
"Vision",
"Camera"},
380 "OpenNIPointCloudProvider");
386 ARMARX_INFO <<
"Openni grabber interface name: " << grabberInterface->getName();
387 ARMARX_INFO <<
"Openni device interface name: " << grabberInterface->getDevice()->getName()
388 <<
" id: " << grabberInterface->getDevice()->getStringID();
391 grabberInterface->getDevice()->setAutoExposure(
393 grabberInterface->getDevice()->setAutoWhiteBalance(
396 grabberInterface->start();
405 ARMARX_INFO <<
"Stopping OpenNI Grabber Interface";
406 if (grabberInterface)
408 grabberInterface->stop();
412 std::scoped_lock lock(syncMutex);
414 condition.notify_one();
434 setImageFormat(visionx::ImageDimension(dimensions(0), dimensions(1)), visionx::eRgb);
445 OpenNIPointCloudProvider::callbackFunctionForOpenNIGrabberPointCloudWithRGB(
446 const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr& newCloud)
450 if (newPointCloudCapturingRequested)
453 timeOfLastPointCloudCapture = IceUtil::Time::now().toMicroSeconds() - offset;
454 pcl::copyPointCloud(*newCloud, *pointcloudBuffer);
455 std::scoped_lock lock(syncMutex);
456 auto size = newCloud->size();
457 pointcloudBuffer->resize(size);
458 float scaling = 1000.f;
459 for (
size_t i = 0; i < size; i++)
461 pointcloudBuffer->at(i).x = newCloud->at(i).x * scaling;
462 pointcloudBuffer->at(i).y = newCloud->at(i).y * scaling;
463 pointcloudBuffer->at(i).z = newCloud->at(i).z * scaling;
466 newPointCloudCapturingRequested =
false;
468 condition.notify_one();
473 OpenNIPointCloudProvider::callbackFunctionForOpenNIGrabberPointCloud(
474 const pcl::PointCloud<pcl::PointXYZ>::ConstPtr& newCloud)
479 if (newPointCloudCapturingRequested)
483 timeOfLastPointCloudCapture = IceUtil::Time::now().toMicroSeconds() - offset;
484 Eigen::Affine3f
transform(Eigen::Scaling(1000.0f));
486 std::scoped_lock lock(syncMutex);
487 pcl::copyPointCloud(*newCloud, *pointcloudBuffer);
488 pcl::transformPointCloud(*pointcloudBuffer, *pointcloudBuffer,
transform);
491 newPointCloudCapturingRequested =
false;
493 condition.notify_one();
498 OpenNIPointCloudProvider::grabDepthImage(
const pcl::io::IRImage::Ptr& IRImage,
499 const pcl::io::DepthImage::Ptr& depthImage,
505 if (newImageCapturingRequested)
508 timeOfLastImageCapture = IceUtil::Time::now().toMicroSeconds() - offset;
509 cv::Mat depthBuffer(height, width, CV_16UC1);
510 depthImage->fillDepthImageRaw(width, height, (
unsigned short*)depthBuffer.data);
512 std::scoped_lock lock(syncMutex);
516 for (
int j = 0; j < depthBuffer.rows; j++)
518 int index = 3 * (j * width);
519 for (
int i = 0; i < depthBuffer.cols; i++)
521 unsigned short value = depthBuffer.at<
unsigned short>(j, i);
523 rgbImages[1]->pixels[
index + 0],
524 rgbImages[1]->pixels[
index + 1],
525 rgbImages[1]->pixels[
index + 2],
534 newImageCapturingRequested =
false;
536 condition.notify_one();
541 OpenNIPointCloudProvider::grabImages(
const pcl::io::Image::Ptr& RGBImage,
542 const pcl::io::DepthImage::Ptr& depthImage,
543 float reciprocalFocalLength)
548 if (newImageCapturingRequested)
551 timeOfLastImageCapture = IceUtil::Time::now().toMicroSeconds() - offset;
553 cv::Mat depthBuffer(height, width, CV_16UC1);
554 depthImage->fillDepthImageRaw(width, height, (
unsigned short*)depthBuffer.data);
556 std::scoped_lock lock(syncMutex);
561 for (
int j = 0; j < depthBuffer.rows; j++)
563 int index = 3 * (j * width);
564 for (
int i = 0; i < depthBuffer.cols; i++)
566 unsigned short value = depthBuffer.at<
unsigned short>(j, i);
568 rgbImages[1]->pixels[
index + 0],
569 rgbImages[1]->pixels[
index + 1],
570 rgbImages[1]->pixels[
index + 2],
609 RGBImage->fillRGB(width, height, rgbImages[0]->pixels);
611 newImageCapturingRequested =
false;
613 condition.notify_one();
621 std::unique_lock lock(syncMutex);
623 newPointCloudCapturingRequested =
true;
624 newImageCapturingRequested =
true;
626 while (
captureEnabled && (newPointCloudCapturingRequested || newImageCapturingRequested))
629 condition.wait_for(lock, std::chrono::milliseconds(100));
638 provideImages(rgbImages, IceUtil::Time::microSeconds(timeOfLastImageCapture));
640 pcl::PointCloud<pcl::PointXYZRGBA>::Ptr pointcloud(
641 new pcl::PointCloud<PointXYZRGBA>(*pointcloudBuffer));
643 pointcloud->header.stamp = timeOfLastPointCloudCapture;
646 heartbeatPlugin->heartbeat();
649 IceUtil::Time reportTime = now - lastReportTimestamp;
652 durations[
"report_time_ms"] =
new armarx::Variant(reportTime.toMilliSecondsDouble());
653 debugObserver->setDebugChannel(
getName(), durations);
656 lastReportTimestamp = now;
661 std::vector<imrec::ChannelPreferences>
666 imrec::ChannelPreferences rgb;
667 rgb.requiresLossless =
false;
670 imrec::ChannelPreferences depth;
671 depth.requiresLossless =
true;
672 depth.name =
"depth";
692 return "OpenNIPointCloudProvider";
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
boost::function< T > FctT
static bool getAbsolutePath(const std::string &relativeFilename, std::string &storeAbsoluteFilename, const std::vector< std::string > &additionalSearchPaths={}, bool verbose=true)
TopicProxyType getTopicFromProperty(const std::string &propertyName)
Get a topic proxy whose name is specified by the given property.
void offeringTopicFromProperty(const std::string &propertyName)
Offer a topic whose name is specified by the given property.
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Property< PropertyType > getProperty(const std::string &name)
static Duration MilliSeconds(std::int64_t milliSeconds)
Constructs a duration in milliseconds.
virtual void onExitComponent()
Hook for subclass.
virtual void onDisconnectComponent()
Hook for subclass.
PluginT * addPlugin(const std::string prefix="", ParamsT &&... params)
virtual void onConnectComponent()=0
Pure virtual hook for the subclass.
std::string getName() const
Retrieve name of object.
virtual void onInitComponent()=0
Pure virtual hook for the subclass.
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
The Variant class is described here: Variants.
float frameRate
Required frame rate.
std::atomic_bool captureEnabled
Indicates that capturing is enabled and running.
void onInitComponent() override
void onDisconnectComponent() override
Hook for subclass.
void setImageFormat(ImageDimension imageDimension, ImageType imageType, BayerPatternType bayerPatternType=visionx::eBayerPatternRg)
Sets the image basic format data.
void provideImages(void **inputBuffers, const IceUtil::Time &imageTimestamp=IceUtil::Time())
send images raw.
void onConnectComponent() override
void setNumberImages(int numberImages)
Sets the number of images on each capture.
void onExitComponent() override
void onInitComponent() override
Pure virtual hook for the subclass.
bool doCapture() override
void onExitCapturingPointCloudProvider() override
void onDisconnectComponent() override
Hook for subclass.
OpenNIPointCloudProvider()
void onConnectPointCloudProvider() override
void onStartCapture(float frameRate) override
void onInitCapturingPointCloudProvider() override
void onConnectComponent() override
Pure virtual hook for the subclass.
StereoCalibration getStereoCalibration(const Ice::Current &c=Ice::emptyCurrent) override
void onStopCapture() override
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
static std::string GetDefaultName()
std::vector< imrec::ChannelPreferences > getImageRecordingChannelPreferences(const Ice::Current &) override
void onInitImageProvider() override
void onExitComponent() override
Hook for subclass.
std::string getDefaultName() const override
Retrieve default name of component.
void providePointCloud(PointCloudPtrT pointCloudPtr)
offer the new point cloud.
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::map< std::string, VariantBasePtr > StringVariantBaseMap
auto transform(const Container< InputT, Alloc > &in, OutputT(*func)(InputT const &)) -> Container< OutputT, typename std::allocator_traits< Alloc >::template rebind_alloc< OutputT > >
Convenience function (with less typing) to transform a container of type InputT into the same contain...
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
std::shared_ptr< Value > value()