27#include <Eigen/Geometry>
29#include <pcl/common/transforms.h>
30#include <pcl/compression/organized_pointcloud_conversion.h>
32#include <SimoxUtility/math/convert/deg_to_rad.h>
33#include <VirtualRobot/Nodes/RobotNode.h>
34#include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h>
42#include <Inventor/SoInteraction.h>
43#include <Inventor/actions/SoGLRenderAction.h>
53 "FloatImageMode",
false,
"Whether to provide a CFloatImage or the standard CByteImage");
56 "Noise of the point cloud position results as standard "
57 "deviation of the normal distribution (in mm)")
61 "Distance of the near clipping plain. (If set too small "
62 "the agent's model's inside may be visible")
67 "Distance of the far clipping plain. (DistanceZFar-DistanceZNear should be "
68 "minimal, DistanceZFar > DistanceZNear)")
71 "FieldOfView", 90,
"Vertical field of view (FOV) in degrees.");
73 "BaseLine", 0.075,
"The value returned from getBaseline(). It has no other effect.");
76 "Value of points that are farther away than DistanceZFar. "
77 "Most cameras return NaN here.");
81 visionx::ImageDimension(640, 480),
82 "Target resolution of the images. Captured images will be converted to this size.")
83 .setCaseInsensitive(
true)
84 .map(
"200x200", visionx::ImageDimension(200, 200))
85 .map(
"320x240", visionx::ImageDimension(320, 240))
86 .map(
"640x480", visionx::ImageDimension(640, 480))
87 .map(
"800x600", visionx::ImageDimension(800, 600))
88 .map(
"768x576", visionx::ImageDimension(768, 576))
89 .map(
"1024x768", visionx::ImageDimension(1024, 768))
90 .map(
"1280x960", visionx::ImageDimension(1280, 960))
91 .map(
"1600x1200", visionx::ImageDimension(1600, 1200))
92 .map(
"1920x1080", visionx::ImageDimension(1920, 1080))
93 .map(
"none", visionx::ImageDimension(0, 0));
96 "RobotNodeCamera",
"DepthCameraSim",
"The coordinate system of the used camera");
102 "Whether the point cloud is drawn to the given DebugDrawerTopic");
104 "DebugDrawerUpdates",
105 "Name of the DebugDrawerTopic");
107 "DrawPointCloud_DrawDelay",
109 "The time between updates of the drawn point cloud (in ms)");
112 "DrawPointCloud_PointSkip",
114 "Only draw every n'th point in x and y direction (n=DrawPointCloud_PointSkip). "
115 "Increase this whenever the ice buffer size is to small to transmitt the cloud "
119 "DrawPointCloud_ClipPoints",
121 "Whether to clip the point cloud drawn to the given DebugDrawerTopic");
124 "DrawPointCloud_ClipXHi", 25000,
"Skip points with x higher than this limit.");
126 "DrawPointCloud_ClipYHi", 25000,
"Skip points with y higher than this limit.");
128 "DrawPointCloud_ClipZHi", 25000,
"Skip points with z higher than this limit.");
131 "DrawPointCloud_ClipXLo", -25000,
"Skip points with x lower than this limit.");
133 "DrawPointCloud_ClipYLo", -25000,
"Skip points with y lower than this limit.");
135 "DrawPointCloud_ClipZLo", -25000,
"Skip points with z lower than this limit.");
157 lastUpdate = std::chrono::high_resolution_clock::now() -
188 ImageProvider::onInitComponent();
189 CapturingPointCloudProvider::onInitComponent();
190 ARMARX_VERBOSE_S <<
"done DepthImageProviderDynamicSimulation::onInitComponent";
197 ARMARX_VERBOSE_S <<
"DepthImageProviderDynamicSimulation::onConnectComponent";
204 ImageProvider::onConnectComponent();
205 CapturingPointCloudProvider::onConnectComponent();
206 ARMARX_VERBOSE_S <<
"done DepthImageProviderDynamicSimulation::onConnectComponent";
213 CapturingPointCloudProvider::onExitComponent();
214 ImageProvider::onExitComponent();
215 ARMARX_VERBOSE_S <<
"done DepthImageProviderDynamicSimulation::onExitComponent";
222 ARMARX_INFO <<
"DepthImageProviderDynamicSimulation::onStartCapture";
229 simVisu->synchronizeVisualizationData();
239 auto l =
simVisu->getScopedLock();
244 VirtualRobot::CoinVisualizationFactory::createOffscreenRenderer(
width,
height));
245 ARMARX_INFO <<
"done DepthImageProviderDynamicSimulation::onStartCapture";
266 return "DepthImageProviderDynamicSimulation";
275 visionx::StereoCalibration
278 visionx::StereoCalibration stereoCalibration;
280 float r =
static_cast<float>(
width) /
static_cast<float>(
height);
282 visionx::CameraParameters RGBCameraIntrinsics;
283 RGBCameraIntrinsics.distortion = {0, 0, 0, 0};
284 RGBCameraIntrinsics.focalLength = {
285 static_cast<float>(
width) / (2 * std::tan((
vertFov * r) / 2)),
287 RGBCameraIntrinsics.height =
height;
288 RGBCameraIntrinsics.principalPoint = {
width / 2.0f,
height / 2.0f};
289 RGBCameraIntrinsics.rotation =
291 RGBCameraIntrinsics.translation =
293 RGBCameraIntrinsics.width =
width;
295 visionx::CameraParameters DepthCameraIntrinsics;
296 DepthCameraIntrinsics.distortion = {0, 0, 0, 0};
297 DepthCameraIntrinsics.focalLength = {
298 static_cast<float>(
width) / (2 * std::tan((
vertFov * r) / 2)),
300 DepthCameraIntrinsics.height =
height;
301 DepthCameraIntrinsics.principalPoint = {
width / 2.0f,
height / 2.0f};
302 DepthCameraIntrinsics.rotation =
304 DepthCameraIntrinsics.translation = {0.075, 0, 0};
305 DepthCameraIntrinsics.width =
width;
310 stereoCalibration.calibrationLeft.cameraParam = RGBCameraIntrinsics;
311 stereoCalibration.calibrationRight.cameraParam = DepthCameraIntrinsics;
312 stereoCalibration.rectificationHomographyLeft =
314 stereoCalibration.rectificationHomographyRight =
318 return stereoCalibration;
367 ARMARX_VERBOSE_S <<
"DepthImageProviderDynamicSimulation::onInitImageProvider";
379 static_cast<int>(
width),
static_cast<int>(
height), CByteImage::eRGB24});
380 dImage.reset(
new CByteImage{
381 static_cast<int>(
width),
static_cast<int>(
height), CByteImage::eRGB24});
387 setImageFormat(visionx::ImageDimension(imgSz), visionx::eFloat1Channel);
391 new CFloatImage{
static_cast<int>(
width),
static_cast<int>(
height), 1});
396 pointcloud.reset(
new pcl::PointCloud<PointT>{
static_cast<unsigned int>(
width),
397 static_cast<unsigned int>(
height)});
409 SoInteraction::init();
411 std::stringstream svName;
412 svName <<
getName() <<
"_PhysicsWorldVisualization";
416 ARMARX_VERBOSE_S <<
"done DepthImageProviderDynamicSimulation::onInitImageProvider";
427 ImageProvider::onDisconnectComponent();
428 CapturingPointCloudProvider::onDisconnectComponent();
446 bool succeeded =
true;
451 : IceUtil::Time::now().toMicroSeconds();
467 Eigen::Matrix4f rotate = Eigen::Matrix4f::Identity();
469 rotate.block(0, 0, 3, 3) =
470 Eigen::AngleAxis<float>(M_PI_2, Eigen::Vector3f::UnitZ()).toRotationMatrix();
471 pcl::PointCloud<PointT>::Ptr cloudTransformedPtr(
new pcl::PointCloud<PointT>());
472 pcl::transformPointCloud(*
pointcloud, *cloudTransformedPtr, rotate);
473 cloudTransformedPtr->header.stamp =
timestamp;
489 lastUpdate = std::chrono::high_resolution_clock::now();
490 DebugDrawer24BitColoredPointCloud dbgPcl;
491 dbgPcl.points.reserve(cloudTransformedPtr->size());
495 const auto pointCloudBaseNode =
498 if (!pointCloudBaseNode)
502 <<
"\nthe point cloud will be attached to (0,0,0)";
505 Eigen::Matrix4f rotate = Eigen::Matrix4f::Identity();
507 Eigen::Matrix4f transformCamToWorld =
508 (pointCloudBaseNode ? pointCloudBaseNode->getGlobalPose()
509 : Eigen::Matrix4f::Identity()) *
515 for (std::size_t
x = 0; x < static_cast<std::size_t>(
width);
x +=
pointSkip)
517 for (std::size_t y = 0; y < static_cast<std::size_t>(
height); y +=
pointSkip)
519 const auto& pclPoint = cloudTransformedPtr->at(
x, y);
522 const Eigen::Vector4f pointFromPcl{pclPoint.x, pclPoint.y, pclPoint.z, 1};
524 const Eigen::Vector4f pointInWorld = transformCamToWorld * pointFromPcl;
525 const Eigen::Vector4f pointInWorldNormalizedW =
526 pointInWorld / pointInWorld(3);
528 DebugDrawer24BitColoredPointCloudElement dbgPoint;
530 dbgPoint.x = pointInWorldNormalizedW(0);
531 dbgPoint.y = pointInWorldNormalizedW(1);
532 dbgPoint.z = pointInWorldNormalizedW(2);
543 dbgPoint.color.r = pclPoint.r;
544 dbgPoint.color.g = pclPoint.g;
545 dbgPoint.color.b = pclPoint.b;
547 dbgPcl.points.emplace_back(dbgPoint);
552 "PointClouds",
getName() +
"::PointCloud", dbgPcl);
570 bool renderOK =
false;
572 auto l =
simVisu->getScopedLock();
573 auto start = IceUtil::Time::now();
576 renderOK = VirtualRobot::CoinVisualizationFactory::renderOffscreenRgbDepthPointcloud(
594 << (IceUtil::Time::now() -
start).toMilliSecondsDouble() <<
" ms";
602 auto start = std::chrono::high_resolution_clock::now();
605 int noiseOffset =
noise > 0 ? rand() % randValuesSize : 0;
611 for (
int y = 0; y <
height; y++)
615 float value = depthBufferEndOfRow[-
x];
616 value = std::max(value, 0.0f);
617 value = std::min(value,
static_cast<float>(0xffffff));
618 dFloatImageRow[
x] = value;
620 dFloatImageRow +=
width;
621 depthBufferEndOfRow +=
width;
627 std::uint8_t* rgbImageRow =
rgbImage->pixels;
628 std::uint8_t* rgbBufferEndOfRow =
rgbBuffer.data() + (
width - 1) * 3;
629 std::uint8_t* dImageRow =
dImage->pixels;
630 for (
int y = 0; y <
height; ++y)
634 memcpy(
static_cast<void*
>(&(rgbImageRow[
x * 3])),
635 static_cast<const void*
>(&(rgbBufferEndOfRow[-
x * 3])),
638 float valueF = depthBufferEndOfRow[-
x];
639 valueF = std::max(0.0f, valueF);
640 valueF = std::min(valueF,
static_cast<float>(0xffffff));
641 std::uint32_t value =
static_cast<std::uint32_t
>(valueF);
642 memcpy(
static_cast<void*
>(&(dImageRow[
x * 3])),
643 static_cast<const void*
>(&value),
647 rgbImageRow +=
width * 3;
648 rgbBufferEndOfRow +=
width * 3;
649 dImageRow +=
width * 3;
650 depthBufferEndOfRow +=
width;
656 std::uint8_t* rgbBufferEntry =
rgbBuffer.data();
659 for (
int y = 0; y <
height; ++y)
664 PointT& point = outputEndOfRow[-
x];
665 Eigen::Vector3f pointCloudBufferPoint = inputRow[
x];
667 int noiseIndex = (y *
width +
x) + noiseOffset;
669 noise > 0.0f ? randValuesData[(noiseIndex) % randValuesSize] : 0.0f;
671 noise > 0.0f ? randValuesData[(noiseIndex + 1) % randValuesSize] : 0.0f;
673 noise > 0.0f ? randValuesData[(noiseIndex + 2) % randValuesSize] : 0.0f;
675 point.x = pointCloudBufferPoint[0] + noiseX;
676 point.y = pointCloudBufferPoint[1] + noiseY;
677 point.z = pointCloudBufferPoint[2] + noiseZ;
678 point.r = rgbBufferEntry[0];
679 point.g = rgbBufferEntry[1];
680 point.b = rgbBufferEntry[2];
685 outputEndOfRow +=
width;
688 auto end = std::chrono::high_resolution_clock::now();
689 std::int64_t timeDiff =
690 std::chrono::duration_cast<std::chrono::microseconds>(end -
start).count();
700 double stddevTime = std::sqrt(averageSquaredTime - averageTime * averageTime);
702 ARMARX_DEBUG <<
"Copying depth buffer data took: " << averageTime <<
"ms +- "
703 << stddevTime <<
"ms";
721 simVisu->synchronizeVisualizationData();
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
static TPtr create(Ice::PropertiesPtr properties=Ice::createProperties(), const std::string &configName="", const std::string &configDomain="ArmarX")
Factory method for a component.
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Property< PropertyType > getProperty(const std::string &name)
DepthImageProviderDynamicSimulationPropertyDefinitions(std::string prefix)
std::string getReferenceFrame(const Ice::Current &c=Ice::emptyCurrent) override
bool hasSharedMemorySupport(const Ice::Current &c=Ice::emptyCurrent) override
void onInitComponent() override
Pure virtual hook for the subclass.
std::vector< Eigen::Vector3f > pointCloudBuffer
~DepthImageProviderDynamicSimulation() override
std::vector< unsigned char > rgbBuffer
std::normal_distribution< double > distribution
bool doCapture() override
Main capturing function.
std::default_random_engine generator
void onExitCapturingPointCloudProvider() override
This is called when the Component::onExitComponent() setup is called.
std::shared_ptr< SoOffscreenRenderer > offscreenRenderer
std::vector< float > randValues
void onDisconnectComponent() override
Hook for subclass.
std::int32_t renderTimesCount
std::size_t pointCloudPointSize
visionx::StereoCalibration getStereoCalibration(const Ice::Current &c=Ice::emptyCurrent) override
std::chrono::high_resolution_clock::time_point lastUpdate
CFloatImage * imgPtrFlt[1]
void onStartCapture(float frameRate) override
This is called when the point cloud provider capturing has been started.
std::unique_ptr< CFloatImage > dFloatImage
std::vector< float > depthBuffer
std::unique_ptr< CByteImage > rgbImage
unsigned int pointCloudDrawDelay
void onInitCapturingPointCloudProvider() override
This is called when the Component::onInitComponent() is called.
std::int64_t sumRenderTimes
bool getImagesAreUndistorted(const Ice::Current &c=Ice::emptyCurrent) override
std::unique_ptr< CByteImage > dImage
void onConnectComponent() override
Pure virtual hook for the subclass.
void onStopCapture() override
This is called when the point cloud provider capturing has been stopped.
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
VirtualRobot::RobotNodePtr cameraNode
static std::string GetDefaultName()
void onInitImageProvider() override
This is called when the Component::onInitComponent() is called.
pcl::PointCloud< PointT >::Ptr pointcloud
SoSeparator * visualization
ArmarXPhysicsWorldVisualizationPtr simVisu
void onExitComponent() override
Hook for subclass.
void onExitImageProvider() override
This is called when the Component::onExitComponent() setup is called.
std::string debugDrawerTopicName
std::int64_t sumRenderTimesSquared
std::string getDefaultName() const override
Retrieve default name of component.
DebugDrawerInterfacePrx debugDrawer
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
TopicProxyType getTopic(const std::string &name)
Returns a proxy of the specified topic.
std::string getName() const
Retrieve name of object.
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
std::string prefix
Prefix of the properties such as namespace, domain, component name, etc.
PropertyDefinition< PropertyType > & defineOptionalProperty(const std::string &name, PropertyType defaultValue, const std::string &description="", PropertyDefinitionBase::PropertyConstness constness=PropertyDefinitionBase::eConstant)
Ice::PropertiesPtr getIceProperties() const
Returns the set of Ice properties.
static bool HasTimeServer()
check if we have been initialized with a Timeserver
CapturingPointCloudProviderPropertyDefinitions(std::string prefix)
float frameRate
Required frame rate.
void updateTimestamp(Ice::Long timestamp, bool threadSafe=true)
Updates the timestamp of the currently captured image.
void start(const Ice::Current &c) override
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 setNumberImages(int numberImages)
Sets the number of images on each capture.
void providePointCloud(PointCloudPtrT pointCloudPtr)
offer the new point cloud.
#define ARMARX_INFO
The normal logging level.
#define ARMARX_ERROR_S
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.