Skip to content

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:

  1. Reads the topic name from argv[1] (default rt/rbq/vision/sensor_front/rgb/compressed).
  2. Initializes the DDS ChannelFactory and creates a Subscriber<CompressedImage_>.
  3. On every received sample, updates a counter plus the last byte size and image format.
  4. Once per second, prints elapsed time, total samples, the 1-second rate, last frame size, and format.
  5. 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
bash scripts/setup.bash
bash scripts/build.bash

Binary: bin/rbq_image_echo

Run

On the real robot

The defaults are set for the robot, so run it as-is:

bash
./bin/rbq_image_echo

This 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
bash scripts/sim.bash --vision -i enp3s0

2. 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):

bash
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.xml

Then subscribe to a numbered camera topic (the sim publishes sensor_N, not sensor_front):

bash
./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 camera

sensor_4 is the front camera and sensor_5 is the rear camera; sensor_0sensor_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 see rate=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 = 44

A 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.

This user manual is intended for RBQ users.