Rig Launcher#
A typical Isaac Teleop setup is three processes on one machine: the CloudXR
runtime, one or more producer plugins that publish device data, and one or
more consumer apps (a Python TeleopSession script or a C++ example
binary) that read the streams. Such a configured set is a rig — the same
shape serves demos, production teleop, and data collection.
isaacteleop.rig starts a rig in a single tmux session from a small YAML
file, instead of you juggling three terminals by hand:
# from the Teleop repository root
python -m isaacteleop.rig rigs/se3_tracker.yaml
The module ships in the isaacteleop wheel; the rig files are part of the
source checkout under rigs/ (they reference install/ binaries, so they
only make sense next to a built tree).
Prerequisites#
tmuxinstalled (sudo apt install tmux).A built and installed Teleop tree (see 2. Install the isaacteleop pip package and the build reference) — the rig references binaries under
install/plugins/andinstall/examples/.The
isaacteleopwheel installed in the current Python environment. tmux panes do not inherit your venv; the launcher bakes the absolute path of its own interpreter (and yourPYTHONPATH, if set) into the pane commands, so whatever environment you launch from is the one the rig runs in.
Run a rig#
# from the Teleop repository root
python -m isaacteleop.rig rigs/se3_tracker.yaml
# a CloudXR runtime is already running elsewhere (skip the runtime pane):
python -m isaacteleop.rig rigs/se3_tracker.yaml --no-runtime
What happens:
Preflight — the launcher verifies tmux is available, the referenced binaries exist and are executable (with the exact
cmakeremedy if not), and the interpreter can importisaacteleop.cloudxr. Nothing is created until preflight passes.Runtime pane starts immediately (a slim full-width strip on top — 25% of the window; it only prints status lines — with the worker panes tiled below). It runs
python -m isaacteleop.cloudxr --accept-eulaby default and prints the web-client URL. The runtime is a host singleton — one per machine.Worker panes load the CloudXR environment automatically. Each producer/consumer pane waits (up to two minutes) for the runtime’s
runtime_startedsentinel, then runssource <install-dir>/run/cloudxr.envsoXR_RUNTIME_JSONand friends point at the runtime — you never source it by hand. The install dir follows the runtime command’s--cloudxr-install-dir(default~/.cloudxr).Producer/consumer panes then run their commands automatically. As soon as the CloudXR environment is loaded, each pane prints a banner (
[producer: ...] running: <command>) and runs its command — no Enter needed. When the command exits, the pane reports[rig] command exited with status N — press Enter to rerunand drops to an interactive shell with the same command pre-typed at the prompt. Anything that callsxrGetSystembefore a headset connects exits withFailed to get OpenXR system— so if a pane’s app started before you connected the headset to the printed URL, connect it and press Enter in that pane to rerun. If the runtime never comes up (or its environment fails to load), the pane does not run the command; it prints a remedy and leaves the command pre-typed instead.The launcher then attaches (from a plain shell) or switches your current client (from inside tmux — no nesting).
Re-running the same rig just switches to the existing session; it does
not re-apply --no-runtime or pick up edits to the rig file. Start
over with:
python -m isaacteleop.rig rigs/se3_tracker.yaml --kill
which kills the rig’s tmux session and every process in it (equivalent to
tmux kill-session -t se3_tracker, without needing to know the session
name). Killing a rig that is not running is a no-op.
The rig YAML#
rigs/se3_tracker.yaml is the annotated exemplar — copy it to write your
own:
name: se3_tracker # rig id AND tmux session name (letters/digits/-/_)
description: CloudXR runtime + SE3 controller tracker plugin + pose printer
cwd: .. # pane working dir, relative to this file
params: # shared values, substituted into the commands below
hand: right
collection_id: se3_tracker # defined ONCE, referenced by both sides below
# runtime: optional full-command override for the runtime pane; default:
# {python} -m isaacteleop.cloudxr --accept-eula
producers: # publish device data into the runtime
- name: se3 tracker plugin (requires headset + controller)
command: "install/plugins/controller_se3_tracker/controller_se3_tracker_plugin {hand} {collection_id}"
consumers: # read the streams — a TeleopSession script or a C++ binary
- name: se3 printer (requires headset)
command: "install/examples/schemaio/se3_printer {collection_id}"
Top-level keys:
Key |
Required |
Meaning |
|---|---|---|
|
yes |
Rig id and tmux session name. Letters, digits, |
|
no |
Free text, printed when the session is created. |
|
no |
Working directory for every pane and the base for relative command paths, resolved relative to the YAML file’s directory (default: the YAML’s directory). |
|
no |
Flat mapping of |
|
no |
Full-command override for the runtime pane (e.g. to add
|
|
at least one entry total |
Lists of |
Commands are plain shell strings. {python} always expands to the absolute
path of the launching interpreter; every other {placeholder} must be
declared under params (literal braces are written {{ / }}).
Unknown top-level keys, unknown entry keys, and unknown placeholders are hard
errors — a typo fails loudly at load time instead of misbehaving in a pane.
Important
Producers and consumers rendezvous on a shared collection_id, and a
mismatch is silent no-data by design. Define it once under params
and reference it as {collection_id} in every command — then one edit
in one place changes both sides together.
Warning
Python TeleopSession example scripts launch their own CloudXR
runtime by default (--launch-cloudxr-runtime defaults to true). The
runtime is a host singleton, so auto-running such a consumer kills the
runtime pane — the headset drops and every producer stalls. Always add
--no-launch-cloudxr-runtime to Python consumer commands in a rig; the
launcher prints a warning (and repeats it in the pane banner) when a
command looks like it is missing the flag.
See Dedicated CloudXR Runtime for more on standalone runtime workflows.
Troubleshooting#
Symptom |
Likely cause |
|---|---|
|
The rig references |
|
You launched from an environment without the |
A worker pane sits idle without running its command |
The pane is still waiting for the runtime’s |
|
The runtime came up but its |
|
The app auto-ran before the headset connected (classic:
|
Runtime pane dies when a consumer starts |
The consumer self-launched a second runtime; add
|
Edits to the rig file seem ignored |
The session already existed; relaunch after
|