UNITE

Core concepts

Three ideas explain how UNITE works: the teleoperation loop it runs, what a module is, and how a study is described as configuration. Understand these and the module reference reads itself.

The teleoperation loop

UNITE models teleoperation as a loop with two directions. Uplink carries the operator's commands to the robot; downlink carries the robot's feedback back to the operator's display. Each direction can have its own communication condition, which determines when packages are released to the next stage. With no condition configured, the channel delivers packages immediately, providing a baseline for comparison.

One component drives everything. Every study scene contains a single empty GameObject named TeleroboticsAgent, and its UNITE runtime component (the Kernel) runs every module attached to it from Unity's FixedUpdate at a fixed update rate. Data moves between stages as typed Package envelopes; the two communication stages transport those packages and apply delay without ever reading the payload inside.

Uplink path · operator → robot
Input Provider reads the device
Command Mapping & Encoding device → command
Operator-side Assistance (uplink) shapes the command before transmission Optional
Uplink Communication Time-ordered queue per command stream Delay
Each channel may carry a study-provided communication condition. Optional: with none configured, the channel delivers immediately. UNITE prescribes no delay or loss model of its own.
Remote Observation & State Capture pre-update hook → refreshes current local observation
Remote-side Assistance acts locally, robot-side only Optional
Before processing each released command, reads the current local observation state.
Robot · vehicle update
Vehicle / Robot Model command → authoritative remote state
Downlink path · updated robot state → operator
Remote Observation & State Capture post-update hook → packages updated state for feedback
Downlink Communication Time-ordered queue per feedback stream Delay
The same extension point, configured independently of the uplink — each channel owns its own condition instance, so either direction can be degraded on its own or left untouched.
Operator-side State Reconstruction updates operator-side state from received feedback
Operator-side Assistance (downlink) operator-facing: overlays, warnings, filtering Optional
Operator Presentation visual / audio / haptic
Task Goal & Termination and Data Capture & Logging run alongside the loop. They observe state and events to end a trial and to record timestamped data, without sitting on the command or feedback path.
The full loop. The Robot lane is the vehicle update island. Remote Observation & State Capture appears at the edges of the loop: the pre-update hook supplies current state to Remote-side Assistance, and the post-update hook packages the new state for Downlink Communication. Stages marked Optional can be left empty. The two Delay stages are the transport modules: every package crosses them, and a communication condition configured inside one of their channels is what degrades that stream. Each module is documented in the Module reference.
In the paper: 5.1 Input Provider 5.2 Command Mapping & Encoding 5.3 Operator-side Assistance (uplink) 5.4 Uplink Communication 5.5 Remote-side Assistance 5.6 Vehicle/Robot Model 5.7 Remote Observation & State Capture 5.8 Downlink Communication 5.9 Operator-side State Reconstruction 5.10 Operator-side Assistance (downlink) 5.11 Operator Presentation 5.12 Task Goal & Termination 5.13 Data Capture & Logging

Remote Observation & State Capture appears twice because it has two jobs in one tick: it makes the current snapshot available to Remote-side Assistance, then packages the updated snapshot for feedback. The module reference shows this with concrete robot-pose, robot-state, and robot-view examples.

What a module is

A module is one small, replaceable responsibility in the loop — reading a device, mapping a command, applying a delay, whatever a single stage needs to do. In code it's a TeleroboticsModule attached to the TeleroboticsAgent, which runs every module it holds in a fixed, deterministic order each tick.

Modules communicate through typed contracts and published packages, so an implementation can be replaced without changing the rest of the loop. A selected implementation may also receive configured dependencies, such as a vehicle reference, sensor source, or condition asset. The study assigns those implementations and references in the agent's Inspector; optional assistance stages can simply be left empty.

For a concrete implementation, start with the shipped Input Provider example. It shows the class, contract, and placement in the project; the UNITE runtime supplies the timing and publishing.

Remote-side Assistance acts locally on the robot using local observations. Operator-side Assistance (downlink) acts after delayed feedback has been reconstructed and creates effects shown to the operator.

Implementation details

Contracts & packages

Between stages, payloads travel inside a minimal Package envelope — a payload object, a source timestamp, and a stream id. The communication and assistance stages pass packages along without interpreting them, which is why a delay model or a shared-control technique can be written once and reused across studies. Contracts themselves are generic — InputProvider<TOutputContract>, for instance — so a study can define its own payload type while reusing the shared framework code.

Reproducibility

The agent has an ID (a participant or condition identifier). At startup it derives a stable seed from that ID and seeds UnityEngine.Random, so the same ID replays the same pseudo-random sequence. If a study module needs randomness, draw it from that seeded source. Using the clock, Guid.NewGuid, or a new unseeded generator would make otherwise identical runs diverge.

Code dependencies

These are code dependencies, not runtime stages. Your study is built on the locked UNITE Kernel, and the Kernel uses shared types from UNITE Core.

Your study implements modules and configures the agent
depends on
UNITE Kernel runs the module lifecycle and loop Locked
depends on
UNITE Core defines shared types such as Package
At runtime, the locked Kernel schedules the configured study modules. Core provides shared types; it is not a step in the teleoperation loop. Study code configures the Kernel through the agent and implements its exposed contracts; it does not edit the Kernel or Core.

Configuration as a study

A study in UNITE is a configured Unity scene holding one wired TeleroboticsAgent and its selected module implementations. It may also use shared configuration assets when the same values must be reused across scenes or conditions.

A configuration asset is a saved instance of a Unity ScriptableObject. Its C# class defines the available fields, and its .asset file stores a named set of values. A module references the file through an Inspector field. The asset stores configuration data; it does not run a module or hold runtime state.

Use an asset when a parameter set is shared, named, or part of the experimental condition. For a value used by only one component, a normal serialized field is simpler. To create one, define a ScriptableObject class with CreateAssetMenu, create an instance from Unity's Assets > Create menu, assign it to the module, and commit the .asset file with the scene.

Unity asset
m_Name: Fixed-Uplink-2560ms
m_EditorClassIdentifier: Assembly-CSharp::Unite.Demo.EveryMoveYouMake.EveryMoveCommunicationConfiguration
uplinkDelayMilliseconds: 1280
downlinkDelayMilliseconds: 1280
direction: uplink
temporalForm: constant
affectedStream: command
nonDelayDegradation: none

This real demo asset is stored at Assets/UNITE/Demo/every-move-you-make/Configurations/Fixed-Uplink-2560ms.asset. The communication condition references it so the same 1,280 ms values can be used by the generated study scenes.

  • Fixed-Uplink-2560ms — the communication condition (a fixed 2.56 s round trip: 1.28 s uplink and 1.28 s downlink).
  • TurtleBot3-WafflePi-Moon — the vehicle model and its parameters.
  • Lunar-Target-300s — the task goal and termination rule.

The demo ships four scenes — condition-baseline, condition-network, condition-path, and condition-envelope. They share the same vehicle, communication, task, observation, and presentation configuration. They differ in the selected Operator-side Assistance (downlink) implementation and therefore in the feedback shown to the operator. That is the whole point: to compare techniques fairly, everything except the technique under test stays fixed.

Because this study uses shared assets, sharing it means committing the scene and those asset files together. A collaborator opens the scene and runs exactly what you ran, with no apparatus to rebuild.

Same ID, same run. Since the seed comes from the agent's ID, reusing an ID reproduces the same study-controlled random sequence — useful for re-running a participant or condition deterministically.