25 #include <pcl/common/transforms.h>
27 #include <rc_genicam_api/system.h>
28 #include <rc_genicam_api/interface.h>
29 #include <rc_genicam_api/buffer.h>
30 #include <rc_genicam_api/image.h>
31 #include <rc_genicam_api/config.h>
32 #include <rc_genicam_api/pixel_formats.h>
34 #include <VirtualRobot/MathTools.h>
41 #include <Calibration/Calibration.h>
42 #include <Calibration/StereoCalibration.h>
43 #include <Image/ImageProcessor.h>
53 using Point = pcl::PointXYZRGBA;
58 static void rcg_getColor(uint8_t rgb[3],
const std::shared_ptr<const rcg::Image>& img,
59 uint32_t ds, uint32_t i, uint32_t k)
64 if (img->getPixelFormat() == Mono8)
66 size_t lstep = img->getWidth() + img->getXPadding();
67 const uint8_t* p = img->getPixels() + k * lstep + i;
69 uint32_t g = 0, n = 0;
71 for (uint32_t kk = 0; kk < ds; kk++)
73 for (uint32_t ii = 0; ii < ds; ii++)
82 rgb[2] = rgb[1] = rgb[0] =
static_cast<uint8_t
>(g / n);
84 else if (img->getPixelFormat() == YCbCr411_8)
86 size_t lstep = (img->getWidth() >> 2) * 6 + img->getXPadding();
87 const uint8_t* p = img->getPixels() + k * lstep;
94 for (uint32_t kk = 0; kk < ds; kk++)
96 for (uint32_t ii = 0; ii < ds; ii++)
99 rcg::convYCbCr411toRGB(
v, p,
static_cast<int>(i + ii));
110 rgb[0] =
static_cast<uint8_t
>(r / n);
111 rgb[1] =
static_cast<uint8_t
>(g / n);
112 rgb[2] =
static_cast<uint8_t
>(b / n);
117 static void storePointCloud(
double f,
double t,
double scale,
118 std::shared_ptr<const rcg::Image> intensityCombined,
119 std::shared_ptr<const rcg::Image> disp,
125 size_t width = disp->getWidth();
126 size_t height = disp->getHeight();
127 bool bigendian = disp->isBigEndian();
128 size_t leftWidth = intensityCombined->getWidth();
129 size_t ds = (leftWidth + disp->getWidth() - 1) / disp->getWidth();
137 const uint8_t* dps = disp->getPixels();
138 size_t dstep = disp->getWidth() *
sizeof(uint16_t) + disp->getXPadding();
143 for (
size_t k = 0; k < height; k++)
146 for (
size_t i = 0; i < width; i++)
148 if ((dps[j] | dps[j + 1]) != 0)
158 dps = disp->getPixels();
161 outPoints->
reserve(height * width);
165 for (
size_t k = 0; k < height; k++)
167 for (
size_t i = 0; i < width; i++)
175 d = scale * ((dps[j] << 8) | dps[j + 1]);
180 d = scale * ((dps[j + 1] << 8) | dps[j]);
189 double x = (i + 0.5 - 0.5 * width) * t / d;
190 double y = (k + 0.5 - 0.5 * height) * t / d;
191 double z = f * t / d;
200 uint8_t rgb[3] = {0, 0, 0 };
202 ::rcg_getColor(rgb, intensityCombined,
static_cast<uint32_t
>(ds),
static_cast<uint32_t
>(i),
203 static_cast<uint32_t
>(k));
207 const double meterToMillimeter = 1000.0f;
208 point.x = x * meterToMillimeter;
209 point.y = y * meterToMillimeter;
210 point.z = z * meterToMillimeter;
225 : intensityBuffer(50)
226 , disparityBuffer(25)
236 updateFinalCloudTransform(
237 getProperty<float>(
"PointCloud_Scale_X").getValue(),
238 getProperty<float>(
"PointCloud_Scale_Y").getValue(),
239 getProperty<float>(
"PointCloud_Scale_Z").getValue(),
240 getProperty<float>(
"PointCloud_Rotate_Roll").getValue(),
241 getProperty<float>(
"PointCloud_Rotate_Pitch").getValue(),
242 getProperty<float>(
"PointCloud_Rotate_Yaw").getValue(),
243 getProperty<float>(
"PointCloud_Translate_X").getValue(),
244 getProperty<float>(
"PointCloud_Translate_Y").getValue(),
245 getProperty<float>(
"PointCloud_Translate_Z").getValue());
274 if (!
initDevice(getProperty<std::string>(
"DeviceId")))
288 if (rcg::setEnum(
nodemap,
"PixelFormat",
"YCbCr411_8",
false))
298 getProperty<float>(
"ScaleFactor"),
299 "/tmp/armar6_rc_point_cloud_calibration.txt"
302 std::string depthQuality = getProperty<std::string>(
"DepthImageResolution").getValue();
307 catch (std::invalid_argument& e)
310 ARMARX_WARNING <<
"Selected DepthImageResolution '" << depthQuality.c_str() <<
"' is currently not available for this device. "
321 scan3dCoordinateScale = rcg::getFloat(
nodemap,
"Scan3dCoordinateScale",
nullptr,
nullptr,
true);
345 const rcg::Buffer* buffer =
stream->grab(10000);
354 if (buffer->getIsIncomplete() || !buffer->getImagePresent(0))
362 uint64_t pixelformat = buffer->getPixelFormat(0);
363 if (pixelformat == Mono8 || pixelformat == YCbCr411_8)
365 intensityBuffer.add(buffer, 0);
367 else if (pixelformat == Coord3D_C16)
369 disparityBuffer.add(buffer, 0);
378 uint64_t timestamp = buffer->getTimestampNS();
380 std::shared_ptr<const rcg::Image> intensityCombined = intensityBuffer.find(timestamp);
381 std::shared_ptr<const rcg::Image> disparity = disparityBuffer.find(timestamp);
383 if (!intensityCombined || !disparity)
402 int width = imageFormat.dimension.width;
403 int height = imageFormat.dimension.height;
411 const uint8_t* p = intensityCombined->getPixels();
413 size_t px = intensityCombined->getXPadding();
414 uint64_t format = intensityCombined->getPixelFormat();
446 PointCloud::Ptr transformedPointCloud(
new PointCloud());
447 const auto& tr = getFinalCloudTransform();
449 pcl::transformPointCloud(*pointCloud, *transformedPointCloud, tr);
454 intensityBuffer.removeOld(timestamp);
455 disparityBuffer.removeOld(timestamp);
471 throw std::runtime_error(
"Not yet implemented");
484 armarx::ComponentPropertyDefinitions(prefix)
488 defineOptionalProperty<std::string>(
"DeviceId",
"00_14_2d_2c_6e_ed",
"");
489 defineOptionalProperty<float>(
"ScaleFactor", 2.0,
"Image down scale factor");
490 defineOptionalProperty<float>(
"framerate", 25.0f,
"Frames per second, actual framerate is equal to min(this framerate, framerate provided by the device)")
491 .setMatchRegex(
"\\d+(.\\d*)?")
494 defineOptionalProperty<bool>(
"isEnabled",
true,
"enable the capturing process immediately");
495 defineOptionalProperty<std::string>(
"DepthImageResolution",
"640x480@3Fps",
"Resolution of the depth image. "
496 "The higher the resolution, the lower the framerate provided by the device")
497 .setCaseInsensitive(
true)
503 defineOptionalProperty<std::string>(
"ReferenceFrameName",
"Roboception_LeftCamera",
"Optional reference frame name.");
505 defineOptionalProperty<float>(
"PointCloud_Scale_X", 1.0,
"");
506 defineOptionalProperty<float>(
"PointCloud_Scale_Y", 1.0,
"");
507 defineOptionalProperty<float>(
"PointCloud_Scale_Z", 1.0,
"");
508 defineOptionalProperty<float>(
"PointCloud_Translate_X", 0,
"");
509 defineOptionalProperty<float>(
"PointCloud_Translate_Y", 0,
"");
510 defineOptionalProperty<float>(
"PointCloud_Translate_Z", 0,
"");
511 defineOptionalProperty<float>(
"PointCloud_Rotate_Roll", 0,
"");
512 defineOptionalProperty<float>(
"PointCloud_Rotate_Pitch", 0,
"");
513 defineOptionalProperty<float>(
"PointCloud_Rotate_Yaw", 0,
"");
518 const auto& srt = finalCloudTransform.getWriteBuffer();;
524 .
addChild(
new armarx::RemoteGui::HSpacer)
530 .
addChild(
new armarx::RemoteGui::HSpacer)
536 .
addChild(
new armarx::RemoteGui::HSpacer);
541 updateFinalCloudTransform(
553 void RCPointCloudProvider::updateFinalCloudTransform(
554 float sx,
float sy,
float sz,
555 float rx,
float ry,
float rz,
556 float tx,
float ty,
float tz)
558 finalCloudTransform.getWriteBuffer()(0) = sx;
559 finalCloudTransform.getWriteBuffer()(1) = sy;
560 finalCloudTransform.getWriteBuffer()(2) = sz;
562 finalCloudTransform.getWriteBuffer()(3) = rx;
563 finalCloudTransform.getWriteBuffer()(4) = ry;
564 finalCloudTransform.getWriteBuffer()(5) = rz;
566 finalCloudTransform.getWriteBuffer()(6) = tx;
567 finalCloudTransform.getWriteBuffer()(7) = ty;
568 finalCloudTransform.getWriteBuffer()(8) = tz;
570 finalCloudTransform.commitWrite();
575 const auto& srt = finalCloudTransform.getUpToDateReadBuffer();
576 return VirtualRobot::MathTools::posrpy2eigen4f(srt(6), srt(7), srt(8), srt(4), srt(5), srt(6)) *
577 Eigen::Vector4f{srt(0), srt(1), srt(2), 1.f}.asDiagonal();