Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The vrobots command

Every subcommand and flag, and how to read the output column by column.

vrobots topic list

pip install ubicoders-vrsdk installs a command called vrobots, and it is the same command whichever language you write your programs in; the C bundle does not carry it. It needs no dev tooling, no configuration and no robot handle, and it is the first thing to run when a program is silent.

Global flags

Both are global, so they are accepted before or after a subcommand.

FlagDefaultNotes
-V, --versionPrints the build’s version block and exits 0. Nothing touches the wire.
--log <FILTER>warntracing filter, e.g. debug or vrobots_sdk=debug,zenoh=info. RUST_LOG overrides it.

topic list

Answers “is the simulator publishing at all, and under which ids”.

FlagDefaultNotes
-t, --timeout <SECS>1.5zenoh observation window. The iceoryx2 registry lookup ignores it.
-k, --keyword <STR>Case-insensitive substring filter on the topic name.
--router <ENDPOINT>An explicit zenoh router, e.g. tcp/192.168.1.10:7447.

A run against a live simulator prints one row per topic, then a footer:

wire       Hz     bytes  topic
[i]        -         -  vrobots/1/i/cam/front_left/720p_rgba8
[i]        -         -  vrobots/1/i/cam/front_right/720p_rgba8  (stale: no process attached)
[z]      1.3      1760  vrobots/1/z/frames
[z]     25.3     45600  vrobots/1/z/state

4 topic(s); zenoh observed over 1.5s
[z] zenoh, measured by listening.  [i] iceoryx2, read from the registry:
    it exists, but Hz/bytes were not measured -- same host only.

1 stale iceoryx2 record(s): the process that created them is gone. Once nothing is running, delete the leftover *.service files under the iceoryx2 root (/tmp/iceoryx2/) and they disappear.

Column by column:

ColumnMeaning
wire[z] zenoh, [i] iceoryx2. It repeats the transport segment in the topic name, so you can also read it off the key.
HzSamples divided by the window. A measurement for [z], and - for [i] because nothing was watched.
bytesTotal payload bytes seen during the window, not bytes per sample. - for [i].
topicThe full key. This is the exact string topic hz, measure_rate and CameraStream::service_name all use.

The rows are sorted by system id first and key second, which is why the two camera streams for sys_id 1 come before its zenoh topics.

Two things in that listing carry information beyond their numbers. 1.3 Hz on a topic that publishes at 1 Hz is the window being short, not the publisher being fast: three samples over 1.5 s of wall clock reads high because the window includes zenoh’s discovery latency at one end and a partial period at the other. And (stale: no process attached) marks an iceoryx2 service record whose owning process is gone. The stream is dead rather than idle, and the footer counts them separately.

The footer also names the remedy and the directory it applies to. A stale record is a file the SDK never deletes itself, so remove it by hand: once the simulator and every client have stopped, delete the leftover *.service files under the iceoryx2 root the footer prints. That root is /tmp/iceoryx2/ on Linux and C:\Temp\iceoryx2\ on Windows by default, and the next topic list no longer shows the row.

Gotcha. An empty list exits 0, because “nothing is publishing” is a legitimate answer to “what is publishing”. Only topic hz treats silence as a failure.

With nothing running, the command says so and tells you what to try:

(no topics)

Nothing published on `vrobots/**` in 1.5s, and no iceoryx2 camera
stream is registered. Usually one of:
  - the simulator is not in Play mode
  - it is on another machine (pass --router tcp/<host>:7447)
  - the window was too short for zenoh discovery (try -t 5)

topic hz

Answers “how fast, how steadily, and am I losing samples”. One key, no wildcards: a single rate across several interleaved topics is not a rate, and the SDK refuses it with InvalidArgument before opening a session.

vrobots topic hz vrobots/1/z/state -w 5
ArgumentDefaultNotes
<TOPIC>requiredThe exact key topic list printed. The transport is read off the name: an /i/ segment is iceoryx2, anything else is zenoh.
-w, --window <SECS>5.0How long to watch. Longer is more accurate.
--router <ENDPOINT>Ignored for iceoryx2 topics, which are always same-host.

A healthy state topic looks like this:

vrobots/1/z/state  [z]  watched 5.0 s

  rate          25.00 Hz      126 samples over a 5.000 s span
  interval   mean 40.00 ms    min 40.00   max 40.00   jitter 0.00 (sd)
  latency    mean 1.20 ms    min 0.80   max 2.10   publish stamp -> here
  seq        1 -> 126      0 gap(s), 0 missed
  payload        1200 B avg   30.2 kB/s over the window

Line by line:

LineWhat it says
rate(samples - 1) / span, where span is first arrival to last arrival. Not samples divided by the window, which would count zenoh’s discovery latency as dead air.
intervalThe gap distribution between arrivals, in ms. jitter is the population standard deviation of those gaps.
latencyArrival wall clock minus the publisher’s header.timestamp_ns. Printed only when the payloads carry a header.
seqFirst and last header.seq, how many separate forward jumps occurred, and how many samples those jumps imply were lost.
payloadMean payload size, and throughput computed over the window rather than the span.

max on the interval line and the gap count are the two numbers that explain a stuttering control loop. A mean of 40.00 ms says nothing about the 200 ms stall that broke it; the maximum interval is the worst stall the loop actually saw, and a non-zero gap count says the samples covering that stall were dropped rather than delayed. Read those two before the rate.

The block grows extra lines when there is something to say: a decode line when payloads failed to parse, a paragraph explaining that latency across machines measures clock offset and can go negative, a paragraph when gaps occurred, and a paragraph when seq went backwards. See Measuring rates for what each of those means.

record

Captures raw wire payloads to files, for tests that run with the simulator closed. Recording and testing without the simulator covers the workflow; the flags are here.

FlagDefaultNotes
--sys-id <U32>0The robot to record from.
--camera <NAME>Record raw iceoryx2 camera slices instead of zenoh state payloads.
--resolution <STR>360pUsed with --camera.
--format <STR>mono8Used with --camera.
--mountoffMount the camera first and unmount it afterwards. Requires --camera. Mutates the simulator.
-n, --count <USIZE>5Frames to capture.
-t, --timeout <SECS>10.0Give up after this long.
-o, --out <PATH>capturesWhere <prefix>_NNN.bin is written, created if missing. A relative path, the default included, is taken from the current directory.
--prefix <STR>stateFile name prefix.
--router <ENDPOINT>zenoh only. Camera slices are shared memory, so a router does not apply.

Exit codes

CodeMeaning
0Success, including --help and --version, and including topic list finding nothing.
1The command ran and failed. topic hz with no samples lands here, as does running vrobots with no subcommand.
2The arguments did not parse.

The command returns that code rather than calling process::exit, so an embedder such as the Python wheel’s console script keeps control of the process.

Next: Discovery from code

See also: Measuring rates, The topic namespace, Appendix A: Topic reference