Files
rtabmap_ros/rtabmap_util/doc/point_cloud_xyz.md
T
matlabbeandmathieu86 11edc01d6a rtabmap_odom tests and doc (#1456)
* rtabmap_odom tests and doc

* opengv note

* added ci checks or humble-latest flaky dep cmake errors

* Added real data tests for rgbd_odom and stereo_odom

* added real data for icp_odometry's deskewing test

* fixing json cmake error on lyrical/rolling

* test 2d icp odom deskewing branch

* first review of existing OdometryROS tests

* testing with imu used as guess

* tested imu arrivals sync

* Fixed odom reset on right pose when guess frame id is used

* fixing header errors in ci >=lyrical

* Added support for input rgbd_image topic with features for odom, added multicam rgbd_odometry test

* Added stereo odom support for features-only frames. Added multicam stereo tests.

* forcing latest rtabmap version

* updated OdometryROS API

* ci: dont build non-latest docker in pull requests

* splitting docker jobs

* doc edit

* Making publish_null_when_lost:=false continous when guess is provided (using guess covariance when we cannot register yet)

* updated stereo doc

* ficing rolling ci (rviz Ogre header)

* Added test coverage of alll rgbd_image callbacks

* fixing rolling ci

* making docker ci build/run the tests on pull requests

* fixing ros2 ci testing

* improved sync callback coverage

* improving stereo_odometry test coverage

* improved icp_odometry test coverage

* lyrical voxel_grid ptr error

* make multicam tests working as well without opengv

* removing deps of missing packages on rolling

* PCL empty cloud  conversion compiler errors fix

* fixing icp_odometry test failure on ci witohut libpointmatcher

* fixing nav2 costmap plugin build on lyrical

* joining thread when exiting

* updating icp test to work the same on pcl 1.15 (lyrical)

* Fix parallel tests seg fault

---------

Co-authored-by: mathieu86 <[email protected]>
2026-09-21 17:02:45 -07:00

5.6 KiB

point_cloud_xyz

Projects a depth or disparity image into a point cloud.

The node takes a depth image and its calibration and produces a sensor_msgs/msg/PointCloud2, with optional decimation, range limits, voxel and radius filtering, and normal estimation — the same preprocessing RTAB-Map would do internally, done once and shared.

depth_image_proc's own point_cloud_xyz does the bare projection; this node exists for the filtering, and for accepting disparity directly.

See point_cloud_xyzrgb for the colored equivalent.

Contents

Usage

ros2 run rtabmap_util point_cloud_xyz --ros-args \
  -r depth/image:=/camera/depth/image_raw \
  -r depth/camera_info:=/camera/depth/camera_info \
  -p decimation:=4 -p max_depth:=5.0 -p voxel_size:=0.05
ComposableNode(
    package='rtabmap_util',
    plugin='rtabmap_util::PointCloudXYZ',
    name='point_cloud_xyz',
    parameters=[{'decimation': 4, 'max_depth': 5.0, 'voxel_size': 0.05}],
    remappings=[('depth/image', '/camera/depth/image_raw'),
                ('depth/camera_info', '/camera/depth/camera_info')])

Subscribed Topics

The node listens on two independent input sets and uses whichever one is being published. Only one of them should be connected.

Depth

Topic Type Description
depth/image sensor_msgs/msg/Image 32FC1 (meters), 16UC1 (millimeters) or mono16. Goes through image_transport, see depth_transport parameter below.
depth/camera_info sensor_msgs/msg/CameraInfo

Disparity

Topic Type Description
disparity/image stereo_msgs/msg/DisparityImage 32FC1 or 16SC1. The 16-bit form is fixed point, 16 units per pixel of disparity.
disparity/camera_info sensor_msgs/msg/CameraInfo

Published Topics

Topic Type Description
cloud sensor_msgs/msg/PointCloud2 In the frame of the input image, stamped with it. Carries normal_* fields when normals are enabled.

Nothing is computed unless cloud has a subscriber.

Parameters

Synchronization

Parameter Type Default Description
approx_sync bool true Match image and camera info by nearest stamp. Set false when they are published with identical stamps, which is stricter and cheaper.
approx_sync_max_interval double 0.0 With approx_sync, reject pairs further apart than this many seconds. 0 disables the check.
topic_queue_size int 1 Queue depth of each input subscription.
sync_queue_size int 10 Queue depth of the synchronizer.
qos int 0 Reliability of the image and disparity subscriptions: 0 system default, 1 reliable, 2 best effort.
qos_camera_info int value of qos Reliability of the camera info subscriptions.
depth_transport string "raw" image_transport plugin for depth/image, e.g. compressedDepth.

Projection and filtering, applied in this order

Parameter Type Default Description
decimation int 1 Keep one pixel in decimation, in each direction. 2 gives a quarter of the points. The image dimensions must divide by it.
roi_ratios string "" Crop before projecting, as four ratios "left right top bottom", e.g. "0.1 0.1 0 0.2".
min_depth double 0.0 Discard points nearer than this, in meters. 0 disables.
max_depth double 0.0 Discard points further than this, in meters. 0 disables.
voxel_size double 0.0 Downsample to one point per voxel of this size, in meters. 0 disables.
noise_filter_radius double 0.0 Radius outlier removal, in meters. 0 disables.
noise_filter_min_neighbors int 5 Neighbors a point needs within noise_filter_radius to survive.
normal_k int 0 Estimate normals from this many nearest neighbors. 0 disables.
normal_radius double 0.0 Estimate normals from all neighbors within this radius, in meters. 0 disables.
filter_nans bool false See Organized output.

Organized output

By default the cloud stays organized: one point per pixel, in image order, with out-of-range points set to NaN rather than removed. That layout is what lets consumers treat the cloud as an image, and it is why a cloud with max_depth set still reports the full point count.

Set filter_nans to true to drop the invalid points instead. The cloud becomes unorganized and its size reflects what is actually in range — including being empty when nothing is.

Voxel and radius filtering also produce unorganized clouds, since both remove points.

Notes

decimation is by far the cheapest way to cut the cost of everything downstream, and on a depth image it loses very little: neighboring pixels of a surface are nearly redundant. Reach for it before voxel_size.