* 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]>
7.5 KiB
rgbdx_sync
Groups the rtabmap_msgs/msg/RGBDImage topics of 2 to 8 cameras into a single rtabmap_msgs/msg/RGBDImages.
For a robot carrying several RGB-D cameras. Each camera gets its own rgbd_sync (or stereo_sync), and this node synchronizes those outputs into one message so that the SLAM node sees all of them as one measurement.
Consider the alternative first. Rebuilt with RTABMAP_SYNC_MULTI_RGBD=ON, the SLAM node subscribes to each camera's RGBDImage and synchronizes them itself, with no node in between — one process and one full-frame copy per camera per frame less than passing through here. This node exists for the cases that rule that out: running against binary packages, or more than the 6 cameras the build option supports. See Feeding it to rtabmap.
The reason it is a build option at all is that each supported camera count is a separate synchronizer template, and instantiating them all costs build time and binary size.
This node only groups: it never touches the images, the calibrations or the individual stamps.
Each camera is packed by its own rgbd_sync first, and this node groups those into the one message the consumers subscribe to:
flowchart LR
CAM0["camera 0 driver"]
CAM1["camera 1 driver"]
SYNC0["rgbd_sync"]
SYNC1["rgbd_sync"]
XSYNC["rgbdx_sync"]
ODOM["rgbd_odometry"]
ODOMT(["odometry"])
MAP["rtabmap"]
VIZ["rtabmap_viz"]
CAM0 -->|"rgb, depth,<br>camera_info"| SYNC0
CAM1 -->|"rgb, depth,<br>camera_info"| SYNC1
SYNC0 -->|rgbd_image0| XSYNC
SYNC1 -->|rgbd_image1| XSYNC
XSYNC -->|rgbd_images| ODOM & MAP & VIZ
ODOM --> ODOMT
ODOMT --> MAP & VIZ
With odometry from elsewhere — a wheel encoder, a lidar, or an external VIO — the cameras feed only the mapping side:
flowchart LR
CAM0["camera 0 driver"]
CAM1["camera 1 driver"]
SYNC0["rgbd_sync"]
SYNC1["rgbd_sync"]
XSYNC["rgbdx_sync"]
ODOM["odometry source<br>wheel, lidar or external"]
ODOMT(["odometry"])
MAP["rtabmap"]
VIZ["rtabmap_viz"]
CAM0 -->|"rgb, depth,<br>camera_info"| SYNC0
CAM1 -->|"rgb, depth,<br>camera_info"| SYNC1
SYNC0 -->|rgbd_image0| XSYNC
SYNC1 -->|rgbd_image1| XSYNC
XSYNC -->|rgbd_images| MAP & VIZ
ODOM --> ODOMT
ODOMT --> MAP & VIZ
Contents
- Usage
- Subscribed Topics
- Published Topics
- Parameters
- Order matters
- Synchronization
- Feeding it to rtabmap
- Diagnostics
Usage
ros2 run rtabmap_sync rgbdx_sync --ros-args \
-p rgbd_cameras:=3 \
-r rgbd_image0:=/camera_front/rgbd_image \
-r rgbd_image1:=/camera_left/rgbd_image \
-r rgbd_image2:=/camera_right/rgbd_image
ComposableNode(
package='rtabmap_sync',
plugin='rtabmap_sync::RGBDXSync',
name='rgbdx_sync',
parameters=[{'rgbd_cameras': 3}],
remappings=[('rgbd_image0', '/camera_front/rgbd_image'),
('rgbd_image1', '/camera_left/rgbd_image'),
('rgbd_image2', '/camera_right/rgbd_image')])
The topics are numbered from 0, and only the first rgbd_cameras of them are subscribed.
Subscribed Topics
| Topic | Type | Description |
|---|---|---|
rgbd_image0 … rgbd_image7 |
rtabmap_msgs/msg/RGBDImage |
One per camera. Only the first rgbd_cameras are subscribed. |
Published Topics
| Topic | Type | Description |
|---|---|---|
rgbd_images |
rtabmap_msgs/msg/RGBDImages |
The set, in topic order. Stamped and framed with rgbd_image0's header; each camera keeps its own header inside the array. |
Unlike the other nodes in this package, this one publishes whether or not anyone is subscribed — it does no per-frame work worth skipping.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
rgbd_cameras |
int |
2 |
How many cameras to group, 2 to 8. Anything outside that range aborts at start-up. |
approx_sync |
bool |
true |
Match the cameras by nearest stamp. Set false only for hardware-triggered cameras. |
approx_sync_max_interval |
double |
0.0 |
Reject sets spanning more than this many seconds. 0 disables. Worth setting; see below. |
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 subscriptions and the publisher: 0 system default, 1 reliable, 2 best effort. |
rgbd_cameras outside 2–8 is a hard error rather than a clamp: one camera needs no grouping at all, and nine cannot be synchronized by any of the templates the node holds. For one camera, subscribe to its RGBDImage topic directly.
Order matters
The array is published in topic order — rgbd_image0 first — and consumers index into it. RTAB-Map matches each image against the calibration and the TF frame it saw at that index, so swapping two remappings places a camera's images at another camera's extrinsics, and the map comes out with the world duplicated at an angle.
The order is a naming convention, not something the node can check. Keep the numbering consistent with whatever else refers to those cameras.
Synchronization
Separate cameras are rarely triggered together, so approx_sync defaults to true. Nothing is published until every camera has contributed: a partial set would silently drop one camera's field of view from the map, which is worse than a dropped frame.
That also makes one silent camera stop the whole node. If rgbd_images goes quiet, check each input in turn:
ros2 topic hz /camera_front/rgbd_image
Set approx_sync_max_interval here as well. With several free-running cameras the synchronizer has more opportunities to pair a fresh frame with a stale one, and each camera's images are placed in the map using the robot's pose at the set's stamp — so a camera whose frame is 200 ms old is placed wherever the robot was not.
Feeding it to rtabmap
Set rgbd_cameras to 0 on the consumer, and remap its rgbd_images input to this node's output:
Node(
package='rtabmap_slam', executable='rtabmap',
parameters=[{'subscribe_rgbd': True, 'rgbd_cameras': 0}],
remappings=[('rgbd_images', '/rgbd_images')])
rgbd_cameras:=0 is what selects the RGBDImages interface: the count then comes from each message rather than from a parameter, so the same consumer handles any number of cameras without a rebuild.
With RTABMAP_SYNC_MULTI_RGBD=ON instead, drop this node and point the consumer straight at the cameras — rgbd_cameras:=3 and one remapping per rgbd_image0…rgbd_image2. Same topics, same order, one hop fewer.
Either way, every camera needs its extrinsics in TF — a transform from the robot's base frame to each camera's frame, at each frame's stamp.
Diagnostics
The node publishes to /diagnostics: the rate of rgbd_image0, the rate of published sets, and a warning in the log every 5 seconds while nothing is arriving. Since a set needs every camera, a healthy input rate with no output points at one of the other cameras.