Files
rtabmap_ros/rtabmap_sync/doc/rgb_sync.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.3 KiB

rgb_sync

Groups a camera's color image and calibration into a single rtabmap_msgs/msg/RGBDImage, with no depth.

The monocular counterpart of rgbd_sync. It exists for pipelines that have no depth to offer: a single camera doing appearance-based loop closure detection and relocalization against a map built earlier, where images are used to recognize places rather than to reconstruct them.

Without depth, RTAB-Map cannot build a metric map from these frames alone. It can still detect that a place has been seen before, which is enough for relocalization in an existing map and for adding loop closure constraints to a graph whose geometry comes from odometry or a lidar.

The camera cannot supply a pose here — visual odometry needs depth or a stereo baseline — so the pose has to come from somewhere else:

flowchart LR
    CAM["camera driver"]
    SYNC["rgb_sync"]
    ODOM["odometry source<br>wheel, lidar or external"]
    MAP["rtabmap"]
    CAM -->|rgb/image| SYNC
    CAM -->|rgb/camera_info| SYNC
    SYNC -->|rgbd_image| MAP
    ODOM -->|odometry| MAP

Contents

Usage

ros2 run rtabmap_sync rgb_sync --ros-args \
  -r rgb/image:=/camera/image_raw \
  -r rgb/camera_info:=/camera/camera_info
ComposableNode(
    package='rtabmap_sync',
    plugin='rtabmap_sync::RGBSync',
    name='rgb_sync',
    remappings=[('rgb/image', '/camera/image_raw'),
                ('rgb/camera_info', '/camera/camera_info')])

Subscribed Topics

Topic Type Description
rgb/image sensor_msgs/msg/Image Color image. Goes through image_transport.
rgb/camera_info sensor_msgs/msg/CameraInfo Calibration of the camera.

Published Topics

Topic Type Description
rgbd_image rtabmap_msgs/msg/RGBDImage The image and its calibration. The depth slot is left empty unless fill_empty_depth. Published only when someone is subscribed.
rgbd_image/compressed rtabmap_msgs/msg/RGBDImage The same frame with the image as JPEG. Published only when someone is subscribed.

The output's header.frame_id comes from the camera_info; its header.stamp is the image's.

Parameters

Parameter Type Default Description
approx_sync bool false Match the image and its calibration by nearest stamp. Defaults to exact; see Synchronization.
approx_sync_max_interval double 0.0 Reject pairs spanning more than this many seconds. 0 disables.
topic_queue_size int 10 Queue depth of each input subscription.
sync_queue_size int 10 Queue depth of the synchronizer.
queue_size int — Deprecated, renamed to sync_queue_size.
qos int 0 Reliability of the subscription and the publishers: 0 system default, 1 reliable, 2 best effort.
qos_camera_info int value of qos Reliability of the rgb/camera_info subscription alone.
fill_empty_depth bool false Add an all-zero depth image the size of the color one. See below.
compressed_rate double 0.0 Maximum rate, in Hz, of rgbd_image/compressed. 0 means every frame.
image_transport string "raw" Transport for rgb/image, e.g. compressed.

fill_empty_depth

By default the output carries no depth image and no depth calibration, which is how a consumer tells "this camera has no depth" from "this frame's depth happens to be all zeros".

Some consumers refuse a message without one. fill_empty_depth gives them a depth image of the right size and encoding (16UC1) filled with zeros, registered to the color camera and sharing its calibration. Zero in a depth image means no reading, so the frame still carries no geometry — the flag changes the shape of the message, not its content. Leave it off unless something downstream requires it.

Synchronization

approx_sync defaults to false here. A driver built on image_transport's camera publisher sends the image and its camera_info as a pair carrying the same stamp, so there is nothing to approximate: the exact policy is cheaper and cannot mismatch.

Set approx_sync:=true when the two do not share a stamp — a camera_info republished on its own timer, or read from a YAML file and stamped with the current time. That is the case to watch for if the node is silent: the calibration values are constant and look fine, but their stamps never match an image.

ros2 topic echo --once /camera/image_raw --field header.stamp
ros2 topic echo --once /camera/camera_info --field header.stamp

Diagnostics

The node publishes to /diagnostics — input rate, output rate, and a warning in the log every 5 seconds while nothing is arriving.