Reference for this directory. The step-by-step guide — setup, headset, recording, what to
do when it goes wrong — is ../README.md.
record.sh records one take of the hand script through TeleopSession — both hand
channels and both controllers — into ~/isaaccapture-cts/<device>_<date>_<time>/.
The files repeat the directory's name:
| File | What |
|---|---|
*-hand.mcap |
the recording |
*-hand.labels.json |
one window per step, on the recording's sample clock |
*-hand.json |
provenance: device, hand source, plugin versions, wrist source, pacing, notes, commit |
*-hand.log |
the panel's terminal output, including the label audit |
./setup_env.sh # after ../checker/setup_env.sh
./record.sh DEVICE [options] # options are capture_panel.py's, below
.venv/bin/python make_labels.py TAKE.mcap # re-run the label audit on an existing takeDEVICE is required and comes first. It names the output directory and files and is
stored as device in the provenance file.
| Option | Effect |
|---|---|
--plugin NAME |
Launch a hand plugin, repeatable. NAME is the plugin's name in its plugin.yaml (manus_hand_plugin, wuji_glove_plugin), looked up in plugins/ and install/plugins/. Without it the take uses the headset's hands. |
--plugin-version NAME=VERSION |
Record this version instead of the one in plugin.yaml. |
--wrist-source SOURCE |
Record where a glove's wrist came from, e.g. hand_tracking or controller. Defaults to each --plugin NAME's $NAME_WRIST_SOURCE, upper-cased without a trailing _plugin ($WUJI_GLOVE_WRIST_SOURCE for wuji_glove_plugin); required when two plugins' variables disagree. It labels the take; the plugin reads the variable itself. |
--note TEXT |
Free text kept in the provenance file. |
--host HOST / --port PORT |
Where the panel listens; 0.0.0.0 and 8081 by default. A busy port moves to the next free one. |
| CloudXR flags | --accept-eula, --cloudxr-install-dir, --cloudxr-device-profile, --cloudxr-env-config, --[no-]launch-cloudxr-runtime, --[no-]host-client, --[no-]launch-wss-proxy |
session.py is the script. The performer sits at a table. Each step is
the spoken cue, a 3-2-1 count (count.wav), the beep that opens the window (beep.wav),
the hold, and the tick that closes it (tick.wav). The move into each pose happens
during the cue and the count, so the hold covers the pose only. The script starts once
both hands have had a valid joint.
| # | Label | Hold | Cue |
|---|---|---|---|
| 1 | flat_on_table_open |
4 s | Rest both hands flat on the table, palms down, fingers together. |
| 2 | fist |
4 s | Make two tight fists. |
| 3 | pinch_index |
3 s | Thumb to index fingertip. |
| 4 | pinch_middle |
3 s | Thumb to middle fingertip. |
| 5 | pinch_ring |
3 s | Thumb to ring fingertip. |
| 6 | pinch_little |
3 s | Thumb to little fingertip. |
| 7 | palms_together |
4 s | Press your palms together, fingers up. |
| 8 | tips_together |
3 s | Raise both hands, palms facing you. Touch middle fingertips. |
| 9 | right_tip_roll |
6 s | Fingertips touching. At the tone, turn the right palm out, then back. |
| 10 | left_tip_roll |
6 s | Fingertips touching. At the tone, turn the left palm out, then back. |
| 11 | flat_on_table_close |
4 s | Hands flat on the table again. |
A window opens on the timer whether or not the performer is in the pose. The checker measures the settled end of each held window and asks for a retake when a pose was not held.
When the script ends the recording closes and make_labels.py writes the sidecar and
audits it against the file: both hand channels present, every window inside the recorded
span, and the checker's own "was the step performed" result. A BAD row there means a
step was missed.
cues/*.wav are pre-rendered speech and three tones, played with aplay; nothing is
synthesised at run time. Without aplay on PATH the panel shows a notice and plays
nothing; the pacing comes from the WAV lengths either way. cues/index.json holds a
hash of each cue's wording, and the panel exits at start-up when a cue in session.py
no longer matches its WAV. The script is part of the specification: do not edit it.
A WAV that is a Git LFS pointer (a clone without git-lfs) stops the panel with a message
to run git lfs pull.
To re-render a cue after changing its wording, use the voice and length scale recorded in
cues/index.json (en_GB-alba-medium, 1.25) and update that cue's text_sha1:
printf '%s' "TEXT" | piper --model en_GB-alba-medium.onnx --length_scale 1.25 \
--output_file cues/LABEL.wav
printf '%s' "TEXT" | sha1sum | cut -c1-16 # the new text_sha1../checker/.venv/bin/python -m pytestNo isaaccapture or viser needed. The sidecar tests use the oracle's fixtures and skip
until ../oracle/generate.sh has built them.