Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions docs/source/references/oob_teleop_control.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,42 @@ This will:
4. Accept the self-signed certificate and click CONNECT automatically
via Chrome DevTools Protocol (CDP)

Optionally, shape the page the run starts from. Each flag below is the
command-line spelling of the matching ``TELEOP_*`` variable in
:ref:`the environment table <oob-environment>`; omit them all and the headset
URL is exactly the one built today:

.. code-block:: bash

python -m isaaccapture.cloudxr.service run --accept-eula --setup-oob \
--oob-reference-space local \
--oob-replay-pacing frame \
--oob-recording latest \
--oob-recording-controls

``--oob-recording`` takes a host path, which is pushed to the headset, or
``latest``, which picks the newest recording already in its Download folder.
Either way the file is only *selected* in the client; starting the replay
remains an operator action.

When the OpenXR application starts after the service, add
``--defer-oob-connect``. The runtime and the WSS listener start as usual, but
the headset is left alone - no page is opened, no CONNECT is clicked and no
headset signalling is relayed to the runtime - until
``GET /api/oob/v1/connect``. Request it once the application has created its
OpenXR session, and the headset connects to a stream that is already there
instead of retrying against one that is not:

.. code-block:: bash

CONTROL_TOKEN=<secret> python -m isaaccapture.cloudxr.service run --accept-eula --setup-oob --defer-oob-connect
# start the application; once it has its OpenXR session:
curl -k -H "X-Control-Token: <secret>" https://localhost:48322/api/oob/v1/connect

Applications that embed the service get the same gate from
``CloudXRLauncher(run_embedded=True, setup_oob=True, defer_oob_connect=True)``
and ``connect_headset()``.

Ordinary headset absence, an ``offline`` or ``unauthorized`` transport, and
browser recovery failures leave the host running with a degraded OOB status.
The lifecycle retries for 60 seconds at a 5-second cadence, then keeps
Expand Down Expand Up @@ -498,6 +534,27 @@ Supported query keys: ``serverIP``, ``port``, ``panelHiddenAtStart``, ``codec``.
Optional ``targetClientId`` restricts the push to a single headset (returns 404
if not connected).

``GET /api/oob/v1/connect``
^^^^^^^^^^^^^^^^^^^^^^^^^^^

Releases headset setup on a service started with ``--defer-oob-connect``
(``defer_oob_connect=True``): the lifecycle opens the teleop page and clicks
CONNECT, and the proxy starts relaying headset signalling to the runtime.

.. code-block:: bash

curl -k -H "X-Control-Token: <CONTROL_TOKEN>" https://localhost:48322/api/oob/v1/connect

Example response:

.. code-block:: json

{"connectRequested": true, "alreadyRequested": false}

Repeating the request is harmless and reports ``"alreadyRequested": true``. A
service that was not started deferred answers 409: its headset setup began at
startup.

Authentication
--------------

Expand Down Expand Up @@ -546,6 +603,8 @@ exception: a saved device profile other than ``Custom`` is re-applied from the c
profile table at startup, so profile default updates (frame rate, bitrate, codec)
reach returning clients. Only ``Custom`` keeps manually edited values.

.. _oob-environment:

Environment variables
---------------------

Expand Down Expand Up @@ -574,6 +633,21 @@ Environment variables
- Default video codec for headset bookmarks
* - ``TELEOP_CLIENT_PANEL_HIDDEN_AT_START``
- Hide control panel on load (``true`` / ``false``)
* - ``TELEOP_CLIENT_IMMERSIVE_MODE``
- WebXR session mode for headset bookmarks: ``vr`` or ``ar``. Needed on
headsets that reject ``immersive-ar``, such as the PICO 4 Ultra.
* - ``TELEOP_CLIENT_REFERENCE_SPACE``
- XR reference space: ``auto``, ``local-floor``, ``local``, ``viewer`` or
``unbounded``. Recording and replay are only comparable across runs when
this is pinned.
* - ``TELEOP_CLIENT_REPLAY_PACING``
- Input replay pacing: ``frame`` or ``time``. ``frame`` advances one
recorded frame per XR frame callback, so a replay is reproducible
regardless of how fast the server renders.
* - ``TELEOP_CLIENT_SHOW_RECORDING_CONTROLS``
- Show the in-XR recording controls (``true`` / ``false``), which carry the
replay buttons an operator uses after ``TELEOP_OOB_RECORDING`` has loaded
a file.
* - ``TELEOP_CLIENT_ROUTE``
- HashRouter fragment appended to the bookmark URL. Default empty
(no fragment — the web client picks its own landing route). Set
Expand Down Expand Up @@ -608,6 +682,21 @@ Environment variables
Before each new browser launch, ADB must confirm
``mWakefulness=Awake``; wear or unlock the headset (or cover its
proximity sensor) when the service reports that it is asleep.
* - ``TELEOP_OOB_RECORDING``
- Host path of a recorded session to start the run with. The file is
pushed to the headset and selected in the client's recording file input
before CONNECT, so the operator only has to start the replay. Unset by
default, so nothing is loaded.
* - ``TELEOP_HEADSET_BROWSER_PACKAGE``
- Android package of the headset browser that opens the teleop page
(``--oob-browser-package``). Unset, the vendor's browser is picked:
``com.oculus.browser`` on Quest, ``com.pico.browser.overseas`` if
installed and otherwise ``com.pico.browser`` on PICO. On PICO OS, a VR
launch from an app that is neither a system app nor declares hand
tracking is held behind a "This app requires the use of controllers"
dialog whenever the headset is in hand-tracking mode, which an
unattended run cannot answer. ``com.pico.browser`` ships as a system
app and is not held.
* - ``TELEOP_OOB_RECOVERY_TIMEOUT_SEC``
- Positive finite recovery-episode duration in seconds (default ``60``).
Expiry changes to observation mode; it never stops the host. If this is
Expand Down
Loading