Image Echo — C++ Example
Source: rbq_sdk/cpp/example/src/rbq_image_echo.cpp
A minimal, read-only diagnostic that subscribes to a compressed camera topic and prints the receive rate, last frame size, and image format once per second. Use it to confirm a camera stream is actually being published and is reachable from your SDK host.
How it works
The program:
- Reads the topic name from
argv[1](defaultrt/rbq/vision/sensor_front/rgb/compressed). - Initializes the DDS
ChannelFactoryand creates aSubscriber<CompressedImage_>. - On every received sample, updates a counter plus the last byte size and image format.
- Once per second, prints elapsed time, total samples, the 1-second rate, last frame size, and format.
- Exits cleanly on
Ctrl+C(SIGINT/SIGTERM), printing the total sample count.
It never publishes, so it is safe to run alongside a live robot or the simulator.
Prerequisites
- RBQ SDK built and installed — see C++ SDK Overview.
- A publisher of the compressed image topic running — the robot's vision stack, or the MuJoCo simulator with vision (
bash scripts/sim.bash --vision).
Build
From rbq_sdk/cpp/example/:
bash scripts/setup.bash
bash scripts/build.bashBinary: bin/rbq_image_echo
Run
On the real robot
The defaults are set for the robot, so run it as-is:
./bin/rbq_image_echoThis subscribes to rt/rbq/vision/sensor_front/rgb/compressed over the robot's enp45s0 interface — both are baked into the example (ChannelFactory::Instance().Init(0, "enp45s0") in main(), plus the default topic). To watch a different camera, pass its topic as the first argument.
In the MuJoCo simulator
The simulator runs on your PC instead of on the robot, so two things differ.
1. Launch the sim on a network interface you actually have. Without -i, sim.bash --vision leaves the vision/camera publisher on the robot's enp45s0, which doesn't exist on your PC — so the client finds nothing. List your interfaces with ip link (e.g. enp3s0) and pass it, so the whole sim shares it:
bash scripts/sim.bash --vision -i enp3s02. Point this client at the same interface, then run it. The interface is hard-coded in the example's source, so override it with a CycloneDDS config. The SDK only uses CYCLONEDDS_URI when it is set, so create the file first (replacing enp3s0 with your interface):
cat > /tmp/cyclonedds.xml <<'EOF'
<?xml version="1.0" encoding="utf-8" ?>
<CycloneDDS xmlns="https://cdds.io/config">
<Domain Id="any">
<General>
<Interfaces><NetworkInterface name="enp3s0" priority="default" multicast="default"/></Interfaces>
<AllowMulticast>spdp</AllowMulticast>
</General>
</Domain>
</CycloneDDS>
EOF
export CYCLONEDDS_URI=file:///tmp/cyclonedds.xmlThen subscribe to a numbered camera topic (the sim publishes sensor_N, not sensor_front):
./bin/rbq_image_echo rt/rbq/vision/sensor_4/rgb/compressed # front camera
./bin/rbq_image_echo rt/rbq/vision/sensor_5/rgb/compressed # rear camerasensor_4 is the front camera and sensor_5 is the rear camera; sensor_0–sensor_3 publish only depth and ir.
The sim and this client must use the same interface — if they differ, or if you leave both on
lo(usually not multicast-capable), you'll seerate=0 Hz.
Example output
Against the MuJoCo simulator (sim.bash --vision), subscribing to sensor_4 (front camera):
[rbq_image_echo] subscribed to 'rt/rbq/vision/sensor_4/rgb/compressed'
[rbq_image_echo] waiting for samples (Ctrl+C to exit)...
[rbq_image_echo] 1.0s total=15 rate=15 Hz last=13053 bytes fmt='jpeg'
[rbq_image_echo] 2.0s total=29 rate=14 Hz last=13080 bytes fmt='jpeg'
[rbq_image_echo] 3.0s total=44 rate=15 Hz last=13067 bytes fmt='jpeg'
[rbq_image_echo] exiting, total samples = 44A steady rate with non-zero byte sizes and fmt='jpeg' confirms the stream is live. rate=0 Hz means no publisher was found on that topic/interface — check the topic name and the DDS interface.
