27#include <pcl/io/openni2/openni2_device_manager.h>
28#include <pcl/io/pcd_io.h>
36#include <Calibration/Calibration.h>
37#include <Image/ImageProcessor.h>
44#if PCL_VERSION > PCL_VERSION_CALC(1, 12, 0)
46using FctT = std::function<T>;
49using FctT = boost::function<T>;
99 grabberInterface.reset();
103 OpenNIPointCloudProvider::loadCalibrationFile(std::string fileName,
104 visionx::CameraParameters& calibration)
108 FileStorage fs(fileName, FileStorage::READ);
116 std::string cameraName = fs[
"camera_name"];
117 ARMARX_LOG <<
"loading calibration file for " << cameraName;
121 int imageWidth = fs[
"image_width"];
122 int imageHeight = fs[
"image_height"];
124 if (imageWidth != dimensions(0) || imageHeight != dimensions(1))
130 Mat cameraMatrix, distCoeffs;
132 fs[
"camera_matrix"] >> cameraMatrix;
133 fs[
"distortion_coefficients"] >> distCoeffs;
135 for (
int i = 0; i < 5; i++)
137 calibration.distortion[i] = distCoeffs.at<
float>(0, i);
140 calibration.focalLength[0] = cameraMatrix.at<
float>(0, 0);
141 calibration.focalLength[1] = cameraMatrix.at<
float>(1, 1);
143 calibration.principalPoint[0] = cameraMatrix.at<
float>(0, 2);
144 calibration.principalPoint[1] = cameraMatrix.at<
float>(1, 2);
158 width = dimensions(0);
159 height = dimensions(1);
161 newPointCloudCapturingRequested =
true;
162 newImageCapturingRequested =
true;
167 using namespace pcl::io::openni2;
168 auto connectedDeviceURIs = *OpenNI2DeviceManager::getInstance()->getConnectedDeviceURIs();
169 ARMARX_INFO <<
"connected devices: " << connectedDeviceURIs;
170 if (!configuredDeviceId.empty() && configuredDeviceId.size() > 2)
174 std::string deviceIndexNumber;
175 ARMARX_INFO <<
"Trying to find device with configured URI: '" << configuredDeviceId
177 for (
auto& uri : connectedDeviceURIs)
179 if (uri == configuredDeviceId)
181 ARMARX_INFO <<
"Found device with URI " << configuredDeviceId <<
" at index "
183 deviceIndexNumber =
"#" + std::to_string(i);
188 if (deviceIndexNumber.empty())
190 ARMARX_WARNING <<
"Could not find device with URI: " << configuredDeviceId
191 <<
" - Connecting now to any device";
192 grabberInterface.reset(
new pcl::io::OpenNI2Grabber());
196 grabberInterface.reset(
new pcl::io::OpenNI2Grabber(deviceIndexNumber));
199 else if (!configuredDeviceId.empty())
202 ARMARX_INFO <<
"Connecting to device id " << configuredDeviceId;
203 grabberInterface.reset(
new pcl::io::OpenNI2Grabber(
"#" + configuredDeviceId));
208 grabberInterface.reset(
new pcl::io::OpenNI2Grabber());
212 visionx::CameraParameters RGBCameraIntrinsics;
213 RGBCameraIntrinsics.focalLength.resize(2, 0.0f);
214 RGBCameraIntrinsics.principalPoint.resize(2, 0.0f);
215 RGBCameraIntrinsics.distortion.resize(4, 0.0f);
218 RGBCameraIntrinsics.rotation =
220 RGBCameraIntrinsics.translation =
224 std::string rgbCameraCalibrationFile =
226 if (!rgbCameraCalibrationFile.empty() &&
227 loadCalibrationFile(rgbCameraCalibrationFile, RGBCameraIntrinsics))
230 grabberInterface->setRGBCameraIntrinsics(RGBCameraIntrinsics.focalLength[0],
231 RGBCameraIntrinsics.focalLength[1],
232 RGBCameraIntrinsics.principalPoint[0],
233 RGBCameraIntrinsics.principalPoint[1]);
238 ARMARX_INFO <<
"unable to load calibration file. using default values.";
239 double fx, fy, cx, cy;
240 grabberInterface->getRGBCameraIntrinsics(fx, fy, cx, cy);
244 if (grabberInterface->getDevice()->hasColorSensor())
246 fx = fy = grabberInterface->getDevice()->getColorFocalLength();
249 cx = (width - 1) / 2.0;
250 cy = (height - 1) / 2.0;
252 ARMARX_INFO <<
"rgb camera fx: " << fx <<
" fy: " << fy <<
" cx: " << cx
255 RGBCameraIntrinsics.principalPoint[0] = cx;
256 RGBCameraIntrinsics.principalPoint[1] = cy;
257 RGBCameraIntrinsics.focalLength[0] = fx;
258 RGBCameraIntrinsics.focalLength[1] = fy;
259 RGBCameraIntrinsics.width = width;
260 RGBCameraIntrinsics.height = height;
263 visionx::CameraParameters depthCameraIntrinsics;
264 depthCameraIntrinsics.focalLength.resize(2, 0.0f);
265 depthCameraIntrinsics.principalPoint.resize(2, 0.0f);
266 depthCameraIntrinsics.distortion.resize(4, 0.0f);
267 depthCameraIntrinsics.rotation =
269 depthCameraIntrinsics.translation =
272 std::string depthCameraCalibrationFile =
274 if (!depthCameraCalibrationFile.empty() &&
275 loadCalibrationFile(depthCameraCalibrationFile, depthCameraIntrinsics))
278 grabberInterface->setDepthCameraIntrinsics(depthCameraIntrinsics.focalLength[0],
279 depthCameraIntrinsics.focalLength[1],
280 depthCameraIntrinsics.principalPoint[0],
281 depthCameraIntrinsics.principalPoint[1]);
286 ARMARX_INFO <<
"unable to load calibration file. using default values.";
287 double fx, fy, cx, cy;
288 grabberInterface->getDepthCameraIntrinsics(fx, fy, cx, cy);
292 if (grabberInterface->getDevice()->hasDepthSensor())
294 fx = fy = grabberInterface->getDevice()->getDepthFocalLength();
296 cx = (width - 1) / 2.0;
297 cy = (height - 1) / 2.0;
299 ARMARX_INFO <<
"depth camera fx: " << fx <<
" fy: " << fy <<
" cx: " << cx
302 depthCameraIntrinsics.principalPoint[0] = cx;
303 depthCameraIntrinsics.principalPoint[1] = cy;
304 depthCameraIntrinsics.focalLength[0] = fx;
305 depthCameraIntrinsics.focalLength[1] = fy;
306 depthCameraIntrinsics.width = width;
307 depthCameraIntrinsics.height = height;
314 calibration.calibrationLeft.cameraParam = RGBCameraIntrinsics;
315 calibration.calibrationRight.cameraParam = depthCameraIntrinsics;
316 calibration.rectificationHomographyLeft =
318 calibration.rectificationHomographyRight =
321 ARMARX_INFO <<
"Baseline:" << grabberInterface->getDevice()->getBaseline();
323 pointcloudBuffer = pcl::PointCloud<pcl::PointXYZRGBA>::Ptr(
324 new pcl::PointCloud<pcl::PointXYZRGBA>(width, height));
326 rgbImages =
new CByteImage*[2];
328 rgbImages[0] =
new CByteImage(width, height, CByteImage::eRGB24);
329 rgbImages[1] =
new CByteImage(width, height, CByteImage::eRGB24);
330 ::ImageProcessor::Zero(rgbImages[0]);
331 ::ImageProcessor::Zero(rgbImages[1]);
333 if (grabberInterface->getDevice()->hasColorSensor())
335 FctT<void(
const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> pointCloudCallback =
338 callbackFunctionForOpenNIGrabberPointCloudWithRGB(std::forward<
decltype(PH1)>(PH1));
340 grabberInterface->registerCallback(pointCloudCallback);
342 FctT<void(
const pcl::io::Image::Ptr&,
const pcl::io::DepthImage::Ptr&,
float)>
343 imageCallback = [
this](
auto&& PH1,
auto&& PH2,
auto&& PH3)
345 grabImages(std::forward<
decltype(PH1)>(PH1),
346 std::forward<
decltype(PH2)>(PH2),
347 std::forward<
decltype(PH3)>(PH3));
349 grabberInterface->registerCallback(imageCallback);
353 ARMARX_INFO <<
"depth sensor. no color image available.";
355 FctT<void(
const pcl::PointCloud<pcl::PointXYZ>::ConstPtr&)> pointCloudCallback =
357 { callbackFunctionForOpenNIGrabberPointCloud(std::forward<
decltype(PH1)>(PH1)); };
358 grabberInterface->registerCallback(pointCloudCallback);
360 FctT<void(
const pcl::io::IRImage::Ptr&,
const pcl::io::DepthImage::Ptr&,
float)>
361 imageCallback = [
this](
auto&& PH1,
auto&& PH2,
auto&& PH3)
363 grabDepthImage(std::forward<
decltype(PH1)>(PH1),
364 std::forward<
decltype(PH2)>(PH2),
365 std::forward<
decltype(PH3)>(PH3));
367 grabberInterface->registerCallback(imageCallback);
377 {
"Vision",
"Camera"},
378 "OpenNIPointCloudProvider");
384 ARMARX_INFO <<
"Openni grabber interface name: " << grabberInterface->getName();
385 ARMARX_INFO <<
"Openni device interface name: " << grabberInterface->getDevice()->getName()
386 <<
" id: " << grabberInterface->getDevice()->getStringID();
389 grabberInterface->getDevice()->setAutoExposure(
391 grabberInterface->getDevice()->setAutoWhiteBalance(
394 grabberInterface->start();
403 ARMARX_INFO <<
"Stopping OpenNI Grabber Interface";
404 if (grabberInterface)
406 grabberInterface->stop();
410 std::scoped_lock lock(syncMutex);
412 condition.notify_one();
432 setImageFormat(visionx::ImageDimension(dimensions(0), dimensions(1)), visionx::eRgb);
443 OpenNIPointCloudProvider::callbackFunctionForOpenNIGrabberPointCloudWithRGB(
444 const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr& newCloud)
448 if (newPointCloudCapturingRequested)
451 timeOfLastPointCloudCapture = IceUtil::Time::now().toMicroSeconds() - offset;
452 pcl::copyPointCloud(*newCloud, *pointcloudBuffer);
453 std::scoped_lock lock(syncMutex);
454 auto size = newCloud->size();
455 pointcloudBuffer->resize(size);
456 float scaling = 1000.f;
457 for (
size_t i = 0; i < size; i++)
459 pointcloudBuffer->at(i).x = newCloud->at(i).x * scaling;
460 pointcloudBuffer->at(i).y = newCloud->at(i).y * scaling;
461 pointcloudBuffer->at(i).z = newCloud->at(i).z * scaling;
464 newPointCloudCapturingRequested =
false;
466 condition.notify_one();
471 OpenNIPointCloudProvider::callbackFunctionForOpenNIGrabberPointCloud(
472 const pcl::PointCloud<pcl::PointXYZ>::ConstPtr& newCloud)
477 if (newPointCloudCapturingRequested)
481 timeOfLastPointCloudCapture = IceUtil::Time::now().toMicroSeconds() - offset;
482 Eigen::Affine3f
transform(Eigen::Scaling(1000.0f));
484 std::scoped_lock lock(syncMutex);
485 pcl::copyPointCloud(*newCloud, *pointcloudBuffer);
486 pcl::transformPointCloud(*pointcloudBuffer, *pointcloudBuffer,
transform);
489 newPointCloudCapturingRequested =
false;
491 condition.notify_one();
496 OpenNIPointCloudProvider::grabDepthImage(
const pcl::io::IRImage::Ptr& IRImage,
497 const pcl::io::DepthImage::Ptr& depthImage,
503 if (newImageCapturingRequested)
506 timeOfLastImageCapture = IceUtil::Time::now().toMicroSeconds() - offset;
507 cv::Mat depthBuffer(height, width, CV_16UC1);
508 depthImage->fillDepthImageRaw(width, height, (
unsigned short*)depthBuffer.data);
510 std::scoped_lock lock(syncMutex);
514 for (
int j = 0; j < depthBuffer.rows; j++)
516 int index = 3 * (j * width);
517 for (
int i = 0; i < depthBuffer.cols; i++)
519 unsigned short value = depthBuffer.at<
unsigned short>(j, i);
521 rgbImages[1]->pixels[
index + 0],
522 rgbImages[1]->pixels[
index + 1],
523 rgbImages[1]->pixels[
index + 2],
532 newImageCapturingRequested =
false;
534 condition.notify_one();
539 OpenNIPointCloudProvider::grabImages(
const pcl::io::Image::Ptr& RGBImage,
540 const pcl::io::DepthImage::Ptr& depthImage,
541 float reciprocalFocalLength)
546 if (newImageCapturingRequested)
549 timeOfLastImageCapture = IceUtil::Time::now().toMicroSeconds() - offset;
551 cv::Mat depthBuffer(height, width, CV_16UC1);
552 depthImage->fillDepthImageRaw(width, height, (
unsigned short*)depthBuffer.data);
554 std::scoped_lock lock(syncMutex);
559 for (
int j = 0; j < depthBuffer.rows; j++)
561 int index = 3 * (j * width);
562 for (
int i = 0; i < depthBuffer.cols; i++)
564 unsigned short value = depthBuffer.at<
unsigned short>(j, i);
566 rgbImages[1]->pixels[
index + 0],
567 rgbImages[1]->pixels[
index + 1],
568 rgbImages[1]->pixels[
index + 2],
607 RGBImage->fillRGB(width, height, rgbImages[0]->pixels);
609 newImageCapturingRequested =
false;
611 condition.notify_one();
619 std::unique_lock lock(syncMutex);
621 newPointCloudCapturingRequested =
true;
622 newImageCapturingRequested =
true;
624 while (
captureEnabled && (newPointCloudCapturingRequested || newImageCapturingRequested))
627 condition.wait_for(lock, std::chrono::milliseconds(100));
636 provideImages(rgbImages, IceUtil::Time::microSeconds(timeOfLastImageCapture));
638 pcl::PointCloud<pcl::PointXYZRGBA>::Ptr pointcloud(
639 new pcl::PointCloud<PointXYZRGBA>(*pointcloudBuffer));
641 pointcloud->header.stamp = timeOfLastPointCloudCapture;
644 heartbeatPlugin->heartbeat();
647 IceUtil::Time reportTime = now - lastReportTimestamp;
650 durations[
"report_time_ms"] =
new armarx::Variant(reportTime.toMilliSecondsDouble());
651 debugObserver->setDebugChannel(
getName(), durations);
654 lastReportTimestamp = now;
659 std::vector<imrec::ChannelPreferences>
664 imrec::ChannelPreferences rgb;
665 rgb.requiresLossless =
false;
668 imrec::ChannelPreferences depth;
669 depth.requiresLossless =
true;
670 depth.name =
"depth";
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
std::vector< imrec::ChannelPreferences > getImageRecordingChannelPreferences(const Ice::Current &) override
void onInitImageProvider() override
void onExitComponent() override
Hook for subclass.
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()