* Supporting ros depth compression formats passthrough * Added image_compression_format (support jpg,png). Use Compression.h constants. * Bridging gap with #1457 * CoreWrapper: decode_images_on_demand * rgbd_sync->rgbd_split encoding/decoding test with image_transport validation. rgbd_split color passthrough * more tests * fixing ci on kilted+ * fixing test * fixing lyrical tests * fixing rolling ci * Improved test coverage * fixing some tf waitForTransform deadlocks when sim time is used in tests * CI: build rtabmap_slam on rolling rtabmap_slam builds without nav2_msgs, which is not on resolute yet: skip its key instead of leaving the package out. Only rtabmap_costmap_plugins (and the rtabmap_ros metapackage pulling it in) still need nav2.
9.5 KiB
rgbd_split
Splits an rtabmap_msgs/msg/RGBDImage back into the standard ROS image topics.
RGBDImage bundles color, depth and both camera infos into one message so they arrive together, which is what RTAB-Map wants. Everything else in the ROS ecosystem — RViz, image_view, depth_image_proc — expects separate Image and CameraInfo topics. This node unpacks the bundle for them.
It is the inverse of rtabmap_sync's rgbd_sync, and of its stereo_sync when stereo is set — those two are what produce an RGBDImage in the first place.
Contents
Usage
ros2 run rtabmap_util rgbd_split --ros-args -r rgbd_image:=/camera/rgbd_image
ComposableNode(
package='rtabmap_util',
plugin='rtabmap_util::RGBDSplit',
name='rgbd_split',
remappings=[('rgbd_image', '/camera/rgbd_image')])
Unpacking a bundle for RViz:
flowchart LR
RGBD(["/camera/rgbd_image"])
SPLIT["rgbd_split"]
RVIZ["RViz"]
RGBD --> SPLIT
SPLIT -->|"rgb/image,<br>rgb/camera_info"| RVIZ
SPLIT -->|"depth/image,<br>depth/camera_info"| RVIZ
Subscribed Topics
| Topic | Type | Description |
|---|---|---|
rgbd_image |
rtabmap_msgs/msg/RGBDImage |
Queue depth queue_sub, 5 by default. Raw or compressed images are both accepted. |
Published Topics
The output topics are named after the resolved input topic, so remapping rgbd_image moves the outputs with it. With rgbd_image remapped to /camera/rgbd_image they are /camera/rgbd_image/rgb/image and so on. Setting stereo: true renames the two halves left and right, see Stereo messages.
| Topic | Type | Description |
|---|---|---|
<rgbd_image>/rgb/image |
sensor_msgs/msg/Image |
The color image, decompressed if needed. |
<rgbd_image>/rgb/camera_info |
sensor_msgs/msg/CameraInfo |
|
<rgbd_image>/depth/image |
sensor_msgs/msg/Image |
The depth image, or the right image of a stereo pair. |
<rgbd_image>/depth/camera_info |
sensor_msgs/msg/CameraInfo |
For a stereo pair this is the right camera, and its P(0,3) carries the baseline. |
<rgbd_image>/rgb/image/compressed |
sensor_msgs/msg/CompressedImage |
The color image in compressed_image_transport's format, published by the node itself unless compressed_passthrough is false. Same for <rgbd_image>/right/image/compressed with stereo: true. See Compressed images. |
<rgbd_image>/depth/image/compressedDepth |
sensor_msgs/msg/CompressedImage |
The depth image in compressed_depth_image_transport's format, published by the node itself unless compressed_depth_passthrough is false. See Compressed images. |
Each half is only unpacked if something is subscribed to it, so subscribing to color alone does not pay for depth decompression.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
qos |
int |
0 |
Reliability of both sides: 0 system default, 1 reliable, 2 best effort. |
qos_sub |
int |
value of qos |
Reliability of the rgbd_image subscription alone. |
qos_pub |
int |
value of qos |
Reliability of the four output publishers alone. |
queue_sub |
int |
5 |
Queue depth of the rgbd_image subscription. Must be at least 1. |
queue_pub |
int |
1 |
Queue depth of every publisher. Must be at least 1. |
stereo |
bool |
false |
Name the outputs left/right instead of rgb/depth. See Stereo messages. |
compressed_passthrough |
bool |
true |
Publish the compressed topics (color, left and right images) from the compressed images of the input without decompressing them, in place of the compressed image_transport plugin. See Compressed images. |
compressed_depth_passthrough |
bool |
compressed_passthrough |
Same for the compressedDepth topic (depth), in place of the compressedDepth image_transport plugin. |
<color topic>.compressed.format |
string |
"jpeg" |
jpeg or png. With compressed_passthrough, used only when an image (color, left or right) has to be compressed. <color topic> is the color (or left) topic with . instead of /, e.g. rgbd_image.rgb.image. |
<depth topic>.compressedDepth.format |
string |
"png" |
png or rvl (Jazzy and later). With compressed_depth_passthrough, used only when the depth has to be compressed. <depth topic> is the depth topic with . instead of /, e.g. rgbd_image.depth.image. |
<depth topic>.compressedDepth.depth_max |
double |
10.0 |
Same, maximum depth (m) of a 32FC1 depth image. |
<depth topic>.compressedDepth.depth_quantization |
double |
100.0 |
Same, depth quantization of a 32FC1 depth image. |
Stereo messages
The node handles stereo RGBDImage messages as well as RGB-D ones. In a stereo message the "depth" slot holds the right image, and the second camera info carries the baseline; the depth topics then carry the right camera, correctly typed as mono8 or bgr8 rather than mislabeled as depth.
That works, but the topic names lie. Set stereo: true and the outputs are named for what they hold:
stereo |
Output topics |
|---|---|
false (default) |
<rgbd_image>/rgb/image, <rgbd_image>/rgb/camera_info, <rgbd_image>/depth/image, <rgbd_image>/depth/camera_info |
true |
<rgbd_image>/left/image, <rgbd_image>/left/camera_info, <rgbd_image>/right/image, <rgbd_image>/right/camera_info |
ros2 run rtabmap_util rgbd_split --ros-args \
-r rgbd_image:=/camera/rgbd_image \
-p stereo:=true
Only the names change — the message contents and the order of the two halves are the same either way, so the rgb slot always becomes the left image. The two namings are exclusive: with stereo: true nothing is published on rgb/depth.
The node checks the setting against what actually arrives, going by the encoding of the second half: 16UC1, 32FC1 and mono16 are depth, anything else is an image. If the two disagree it logs a warning once and keeps forwarding — a mismatch makes the topic name misleading, not the data wrong, so it is never worth dropping a frame over.
Compressed images
rgb_compressed of an RGBDImage holds a JPEG or PNG image, and so does depth_compressed for the right image of a stereo pair. With compressed_passthrough (the default), the node republishes them as they are on <rgbd_image>/rgb/image/compressed (and <rgbd_image>/right/image/compressed), readable with the compressed transport. Their format is set from the image header, with the encoding (e.g. "bgr8; jpeg compressed bgr8"), which producers before 0.24 did not set. Raw images, or images whose header cannot be read, are compressed with <color topic>.compressed.format.
depth_compressed of an RGBDImage holds depth in compressed_depth_image_transport's format, or, from rtabmap_ros before 0.24 or with depth_compression_format: "legacy", in rtabmap's own format (png, rvl, png:<max>:<q>, rvl:<max>:<q>), which image_transport plugins cannot read. The node republishes both on <rgbd_image>/depth/image/compressedDepth, readable with the compressedDepth transport:
ros2 run image_transport republish compressedDepth raw --ros-args \
-r in/compressedDepth:=/camera/rgbd_image/depth/image/compressedDepth -r out:=/depth
With compressed_depth_passthrough (the default), the depth is not decompressed when that can be avoided:
| Input depth | compressedDepth output |
|---|---|
compressed_depth_image_transport format |
Republished as is (RVL re-compressed as PNG before Jazzy). |
rtabmap's legacy png (16UC1), rvl, png:<max>:<q>, rvl:<max>:<q> |
Only the header is converted, the compressed payload is copied. Before Jazzy, compressed_depth_image_transport cannot decode RVL, so RVL payloads are re-compressed as PNG, losslessly. |
Raw, or rtabmap's legacy png of 32FC1 depth (4 channels) |
Compressed with the <depth topic>.compressedDepth.* parameters. |
The passthrough does not support the plugins' jpeg_quality and png_level parameters: to set them, set compressed_passthrough: false (compressed plugin) or compressed_depth_passthrough: false (compressedDepth plugin), and the plugin decompresses and re-compresses every frame instead. compressed_depth_passthrough follows compressed_passthrough unless set, so e.g. compressed_passthrough: false with compressed_depth_passthrough: true sets jpeg_quality of the color image while still passing the depth through.
Notes
If a message has no frame_id on one of its sub-messages, the node fills it in from the other one so the output is always usable by TF.