Protocol Simulation#
Overview#
Protocol simulation emulates a robot communication stack (for example, Unitree SDK2 DDS) against a simulator-backed robot.
This lets you run an existing real-robot controller unchanged, while replacing the robot hardware with a MetaSim robot instance.
Typical use cases:
Validate a deployment controller before running on hardware.
Debug command/state mismatches between simulator and real stack.
Reproduce bring-up issues (startup, standby/takeover, torque limits) in a safer loop.
Package Structure#
Protocol simulation is split into two layers:
Core framework (vendor-agnostic):
metasim/protocol_sim/coreConcrete protocol plugins (vendor-specific):
roboverse_pack/protocol_sim/protocols
Current concrete plugin:
Unitree SDK2 plugin:
roboverse_pack/protocol_sim/protocols/unitree_sdk2
Current CLI entrypoint:
scripts/protocol_sim/unitree_sdk2_sim_server.py
Data Flow#
Each control step in RobotProtocolServer follows this sequence:
Read observation from simulator (
MetaSimAdapter.read_observation).Pull latest inbound protocol command (
Transport.get_latest_command_with_token).Decode command into canonical representation (
ProtocolCodec.decode_command).Choose standby or protocol control path (based on standby config and command activity).
Compute torque/effort (
ActuationModel.compute_effortorStandbyController.compute_effort).Apply effort to simulator (
MetaSimAdapter.apply_effort), then step simulator.Encode outbound state messages (
ProtocolCodec.encode_messages) and publish by channel.
Core Interfaces#
Core interface definitions live in metasim/protocol_sim/core/interfaces.py:
Transport: messaging I/O boundary (DDS/ROS/LCM/etc.)ProtocolCodec: semantic conversion between vendor messages and canonical command/stateActuationModel: canonical command -> simulator effortStandbyController: safe controller before external controller takeoverExternalAssist: optional safety assist (for example, elastic-band force)
Core server and adapter:
metasim/protocol_sim/core/server.pymetasim/protocol_sim/core/sim_adapter.py
Canonical data models:
metasim/protocol_sim/core/types.pyCanonicalRobotCommandSimRobotObservation
Unitree SDK2 Plugin#
Unitree-specific implementation is intentionally kept out of metasim core:
roboverse_pack/protocol_sim/protocols/unitree_sdk2/transport.pyroboverse_pack/protocol_sim/protocols/unitree_sdk2/codec.pyroboverse_pack/protocol_sim/protocols/unitree_sdk2/actuation.pyroboverse_pack/protocol_sim/protocols/unitree_sdk2/standby_policy.pyroboverse_pack/protocol_sim/protocols/unitree_sdk2/server.py
The plugin depends on unitree_sdk2py for DDS transport and IDL message types.
Supported robot profiles are defined in:
roboverse_pack/protocol_sim/protocols/unitree_sdk2/spec_registry.py
At the time of writing, the registry includes g1_dof29.
Quick Start#
Run the Unitree SDK2 simulation server:
python scripts/protocol_sim/unitree_sdk2_sim_server.py \
--sim mujoco \
--robot g1_dof29 \
--domain-id 1 \
--iface lo \
--auto-remote \
--elastic-band \
--elastic-band-height 2.5 \
--elastic-band-length 0.1
Then run the controller (unchanged) against the same DDS domain:
python scripts/unitree_deploy/deploy_real.py lo g1_dof29.yaml --domain-id 1
Important Runtime Options#
Main options from scripts/protocol_sim/unitree_sdk2_sim_server.py:
--match-task: align dt/scenario/initial state to a task (registry_keyormodule:TaskClass)--actuation-gains {cmd,robot_cfg}: use gains from incoming LowCmd or from RobotCfg--no-standby: disable standby controller--standby-cmd-timeout: revert to standby after command stream timeout--elastic-band: enable external safety assist--elastic-band-height,--elastic-band-length: anchor and rest length tuning
Live Elastic-Band Control#
When --elastic-band is enabled and the server runs in an interactive terminal (TTY),
you can tune assist strength live without restarting.
Key mode (single-key input):
7: stronger assist (shorter rest length)8: weaker assist (longer rest length)]: move anchor up[: move anchor downr: release elastic band immediatelys: print current height/lengthh: print help
Line mode commands (fallback when key mode is unavailable):
length <m>height <m>release(immediate)showhelp
Notes:
Live tuning is disabled when stdin is not a TTY.
Adjustment increment for
7/8/[ ]is controlled by--elastic-band-key-step(meters).Rest length is clamped to
>= 0.
Programmatic Usage#
from roboverse_pack.protocol_sim.protocols.unitree_sdk2.server import (
UnitreeServerArgs,
build_unitree_sdk2_server,
)
args = UnitreeServerArgs(
sim="mujoco",
robot="g1_dof29",
domain_id=1,
iface="lo",
auto_remote=True,
standby=True,
)
server = build_unitree_sdk2_server(args)
server.start()
try:
server.run_forever()
finally:
server.close()
Extending to New Protocols#
To add another vendor protocol:
Create a new plugin package under
roboverse_pack/protocol_sim/protocols/<vendor>.Implement
Transport,ProtocolCodec, andActuationModel.Optionally implement
StandbyControllerand/orExternalAssist.Assemble these pieces into
RobotProtocolServer.Add a script entrypoint under
scripts/protocol_sim/.
Keep dependency direction one-way:
Plugin code may import
metasim.protocol_sim.core.Core code must not import plugin-specific modules.