Skip to main content

Reference simulator for the Open Robot Control Protocol (ORCP)

Project description

orcp-sim

Reference simulator for the Open Robot Control Protocol (ORCP).

orcp-sim emulates an ORCP-compliant motor controller on a virtual serial port (PTY). Point any ORCP host — a terminal, the orcp Python library, or a ROS 2 node — at the device path it prints, and develop against the protocol with no hardware.

It implements ORCP v1.1 and runs a 100 Hz control loop with PID, a motor model, encoder quantisation, the mandatory safety system, and streaming telemetry.

Requirements

Python 3.9+. No third-party dependencies — standard library only. (PTY support is Unix-only: macOS and Linux.)

Install

# Run straight from a checkout — no install needed:
python3 -m orcp_sim

# …or install the `orcp-sim` command:
pip install -e .
orcp-sim

Usage

orcp-sim                      # Level 2 controller, auto-created PTY
orcp-sim --level 1            # Level 1 controller
orcp-sim --link /tmp/orcp     # also create a symlink at this path
orcp-sim --vbat 11.1          # set simulated battery voltage
orcp-sim --estop              # start with the e-stop active

On start it prints the serial device path:

ORCP Reference Simulator — proto ORCP/1.1, fw 1.1.0, Level 2
Serial device: /dev/ttys004

Connect with any serial terminal (e.g. screen /dev/ttys004 115200) and type commands:

PING
<<< OK PONG t=1234
INFO
<<< OK INFO fw=1.1.0 hw=ORCP-SIM proto=ORCP/1.1 vendor=ORCP-Project model=reference-sim level=2 uuid=00SIMULATED00FF
PRESET NORMAL
<<< OK PRESET name=NORMAL timeout_ms=250 enable_required=1 hb_required=1 duty_limit=0.900
ENABLE ON
<<< OK ENABLE state=ON
WHEEL l=5.0 r=5.0
<<< OK WHEEL l=5.000 r=5.000

Conformance levels

The simulator emulates all conformance levels (ORCP spec §9); select one with --level. The controller declares its level in the INFO response, exactly as real hardware does, so a host can be tested against each tier by changing one flag. Commands above the active level return ERR code=BAD_CMD.

Level --level Commands available
1 — Basic 1 PING CMD_VEL WHEEL STOP STATUS ENABLE PRESET (motion + mandatory safety)
2 — Standard 2 (default) Level 1 + INFO HB STREAM GET SET SAVE LOAD DEFAULTS (runtime config with persistence, heartbeat & e-stop monitoring, telemetry streaming)
3 — Extended 3 CAN binary encoding is not emulated over a PTY; behaves as Level 2 on this ASCII transport

Notable v1.1 behaviours the simulator demonstrates:

  • WHEEL defaults to rad/s closed-loop velocity; open-loop duty is opt-in via the vendor extension mode=DUTY.
  • Closed-loop commands are rejected with ERR code=NO_FEEDBACK when kin.counts_per_rev=0 (no-encoder platform).
  • Heartbeat monitoring is a Level 2+ feature: the full preset reports hb_required=1 at Level 2 and hb_required=0 at Level 1, where the command timeout provides the dead-man.
  • Safety faults latch until ENABLE ON; ! FAULT and ! WARN push messages are emitted on transitions.

Profiles

A profile makes the simulator emulate a specific controller — its identity, config-key surface, vendor command modes, and push events — layered over the generic v1.1 core.

A profile is declarative data, not code. Exactly one profile — base, the standard reference — is built into the core; every other profile (including MC1) is a JSON data file. That keeps the simulator vendor-neutral: no manufacturer is privileged in the core, and adding a device is a data change, not a code change.

Select a bundled profile by name with --profile, or load your own file with --profile-file:

Profile Ships as What it emulates
base (default) built into the core Generic, fully-conformant ORCP v1.1 controller — the standard reference (15 standard §7 config keys).
mc1 orcp_sim/profiles/mc1.json First Layer Robotics MC1: the full 42-key config surface, hw=MC1 / bl= in INFO, band-label battery, and the ! WARN AUX5V vendor push.
orcp-sim --profile mc1 --ws 8765      # emulate an MC1 over WebSocket
orcp-sim --profile mc1 --aux5v-amps 6 # trip the 5V-rail warning (! WARN AUX5V)

The base profile is the pure standard reference and is kept free of any vendor-specific surface.

Creating a profile (third-party vendors)

There are three ways to ship a profile, in increasing order of permanence — all use the same JSON format:

Tier How Selector
Private / local Keep your own JSON file anywhere --profile-file acme.json
Bundled (contributed) Add orcp_sim/profiles/acme.json and open a PR — a data change, reviewed and shipped in the next release --profile acme
Independent (planned) A pip entry-point plugin, for profiles that need custom code --profile acme

MC1 is the worked example of the bundled tier — copy orcp_sim/profiles/mc1.json and you have a vendor profile that ships first-class, exactly like it. For a private profile:

orcp-sim --profile-file acme.json          # emulate your controller
orcp-sim --profile-file acme.json --ws 8765 # …and serve it to a browser tool

The fields are:

Field Required Meaning
name yes Short profile name (the --profile selector and the start-up banner)
identity yes INFO fields — must include hw, fw, level; optional vendor, model, and info_extra (e.g. {"bl": "1.0.0"})
config yes Ordered [name, default, min, max] rows — drives GET/SET/GET ALL. Must include the config keys the core requires (the §7 essentials); add vendor keys freely
int_keys no Config keys rendered as integers (others as %.3f)
wheel_modes no Vendor WHEEL modes beyond rad/s, e.g. ["DUTY"]
warns no ! WARN <type> events the device emits, e.g. ["BATT"]
battery no STATUS battery field: "percent" (default) or "band"
aux5v no true to model a 5 V aux rail + ! WARN AUX5V

A complete example is provided at docs/example-profile.json — copy it and edit. The loader validates on start-up and reports the common mistakes clearly (missing field, malformed config row, or a dropped key the core requires).

Getting your profile bundled

To turn a private profile into a first-class --profile <name> that ships with the simulator, contribute it back. The process:

  1. Write and validate it locally. Copy docs/example-profile.json, edit it to match your controller, and prove it loads:
    orcp-sim --profile-file your-device.json     # must start without error
    
    Connect a host (a terminal, the orcp library, the web configurator) and confirm INFO, GET ALL, and a PRESET/WHEEL exchange look right. Aim to mirror your shipping firmware's GET ALL output exactly — same keys, same order, same defaults — so the profile is a faithful stand-in for the device.
  2. Fork orcp-protocol/orcp-sim and add your file as orcp_sim/profiles/<name>.json. Use a short, unique, lowercase name (it becomes the --profile selector); don't touch base or another vendor's profile.
  3. List it by adding a row to the profile table in this README.
  4. (Encouraged) Add a quick test in tests/ — e.g. assert your profile is discovered and reports the identity / key-count you expect (see the mc1 tests for the pattern). The loader already validates every bundled file on import, so a broken profile fails the suite.
  5. Open a pull request. CI runs the test suite (which loads and validates every profiles/*.json). A maintainer reviews it as a data change — the bar is "does it accurately represent a real, shipping ORCP controller?". On merge it's in the next release and selectable as --profile <name> everywhere.

Because a bundled profile is pure data and the loader validates it on import, accepting one is low-risk: it cannot run vendor code or affect the base reference or any other profile.

Scope: a file profile describes a controller's declarative surface — identity, config keys, which standard behaviours are switched on. It cannot add genuinely new behaviour (custom telemetry physics, bespoke commands, new warn trigger logic); those live in the simulator core. A pip entry-point plugin mechanism for profiles that need custom code is a planned future direction.

Connecting from a browser (web configurator)

Browsers reach real boards over the Web Serial API (USB CDC) and cannot open a PTY, so to drive the simulator from a browser tool — such as the MC1 web configurator — run it over a WebSocket instead:

pip install 'orcp-sim[web]'
orcp-sim --ws 8765            # serve on ws://localhost:8765

The WebSocket carries the identical ORCP line protocol, so the host only needs a small transport switch (Web Serial for hardware, WebSocket for the simulator). See docs/websocket-transport.md for the full contract and a reference client.

Configuration persistence

SAVE/LOAD persist the standard configuration parameters (ORCP §7) to a JSON file. By default this is orcp_sim_config.json in the system temp directory; override with --config-file PATH. DEFAULTS restores factory values.

Tests

pip install -e ".[dev]"
pytest

The suite checks v1.1 compliance (response formats, error codes, level gating) and the dynamic safety behaviour (heartbeat/command-timeout faults, e-stop latching, streaming).

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

orcp_sim-0.1.0.tar.gz (26.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

orcp_sim-0.1.0-py3-none-any.whl (19.2 kB view details)

Uploaded Python 3

File details

Details for the file orcp_sim-0.1.0.tar.gz.

File metadata

  • Download URL: orcp_sim-0.1.0.tar.gz
  • Upload date:
  • Size: 26.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for orcp_sim-0.1.0.tar.gz
Algorithm Hash digest
SHA256 dad3c18eb104f20e7c35784e756b415f6670119f03fff6417c8ed52d19b21a95
MD5 26e5e89df8d48c829fe0868fe86307bf
BLAKE2b-256 68a14a0a694d90c0fd65f08a27ad4b75cb52a075a6473b2ef2a89d518145714d

See more details on using hashes here.

File details

Details for the file orcp_sim-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: orcp_sim-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 19.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for orcp_sim-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d406ddd45c53e1a18b25a81531309ec4bb3a4feb67bd9d90da72d92459f69758
MD5 89fca67567411e7feb13aeb73d89b3d1
BLAKE2b-256 3a36927f4553234bcac7c94f6f3ba4f749bb9acd05d50c127a02f0be4b8323d1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page