Python simulation environment Stable

Simulation, visualization, and the pipeline around them

The stack the lab simulates with: an engine that steps N agents at once, a GPU viewer for the runs it produces, a link layer that makes a simulated vehicle and a real one look the same downstream, and the tooling that keeps a dozen repositories building the same way.

Python simulation environment
← All projects

Everything the lab simulates runs through these repositories. They are separate because they answer separate questions, and the separation is what lets a paper reuse the parts it needs without inheriting the rest.

How the pieces fit

ssl_simulator is the engine. State lives in a World as component arrays, and behaviour is System callables vectorized over all N agents at once rather than looped per robot; a scheduler orders them by their dependencies and an Engine ticks and logs.

ssl_link is what everything else agrees on. Its two contracts are worth learning before anything else: a frame is (time, {name: array}) (a snapshot of named, entity-indexed arrays) and data flows through a DataSource while commands flow back through a Commander. Because a frame is the same whether it came from a solver an hour ago or a radio a millisecond ago, a simulated vehicle and a flying one look identical to everything downstream, and a plot that reads "p" does not care which it was.

ssl_simulator_vista reads those runs back. lieplusplus_py is pulled in only where Lie group operations are needed, which is why it sits behind the engine’s lie extra rather than in its dependencies.

Starting something new

Every Python project here is generated from ssl_py_template, developed through ssl_pydev, and tested and deployed by ssl_ci. That is deliberate: the build, publish and docs logic exists once, in ssl_pydev, and both a laptop and a CI runner execute that same code rather than two copies that start identical and drift.

gvf_so3 is the end-to-end example. It is a real paper’s simulation code, and it shows the whole chain in use: the engine for the dynamics, Lie++ for the attitude work, vista for the figures, with dependencies exact-pinned and the lockfile committed so the environment behind the published figures can be reproduced.

Work that turns out to be generally useful moves down into ssl_simulator or ssl_simulator_vista. What stays in a project like gvf_so3 is what is only true of that paper.

What it is made of

Core

  • ssl_simulator needs ssl_link

    The engine. A data-oriented core: mutable state lives in a World as component arrays, behaviour is Systems that vectorize over N agents, and a scheduler orders them by their dependencies.

  • ssl_simulator_vista needs ssl_simulator, ssl_link

    The viewer, published as ssl_vista. Loads a run and plays it back through configurable multi-panel windows, PyVista for the 2D and 3D scenes.

  • The ground data plane, and the reason the rest composes. One interface for reading robot data - a log, a running simulation, a vehicle over telemetry - and one for sending commands back. It owns the log format, so every producer writes what every consumer reads.

  • Lie group operations - SO(3) and friends - as a Python wrapper over Lie++. Optional: the engine pulls it in through its `lie` extra, for the work that needs it.

Tooling

  • Where a new project starts. A Copier template wiring up uv, just, ruff and pytest; `project_kind` chooses between a publishable package and a notebook-driven research project.

  • The command every Python project here is developed through. Installed once per machine rather than copied into each project, and it is the same code the CI runs, not a second copy of it.

  • One source of truth for CI across the organisation. Projects call into its reusable workflows instead of each carrying its own YAML.

Examples

  • gvf_so3 needs ssl_simulator, ssl_simulator_vista, lieplusplus_py

    A worked end-to-end example, and the simulation code behind the singularity-free SO(3) path following paper.

Papers

  1. [U1] Singularity-Free Guiding Vector Fields on SO(3) with Designer-Specified Progression Behavior