Skip to main content

Python-first native multibody simulation for reinforcement learning

Project description

LavenderSim

LavenderSim is a Python-first native robotics simulator for reinforcement learning. You describe bodies, joints, sensors, rewards, and interaction loops in Python; a compact C++17 engine runs the physics on macOS, Linux, and the web.

Documentation · Environment guide · Examples · Development guide

AI provenance: Almost the entire project was generated by GPT-5.6 Sol under human direction. Treat the implementation as AI-generated software: review it, test it for your application, and do not assume MuJoCo-level numerical validation or safety guarantees.

Why LavenderSim?

  • Python-first worlds: create complete articulated scenes without XML.
  • RL-ready API: seeded reset, bounded spaces, flat observations, and Gymnasium-style five-value step results without requiring Gymnasium.
  • 13 registered tasks: ten benchmark environments plus the walker, quadruped, and ball-pushing tasks developed with the simulator.
  • Robotics features: revolute, prismatic, fixed, and spherical joints; effort, position, velocity, and impedance control; named sites; IMUs; tactile, range, force, and torque sensors; actuator dynamics; fixed tendons; heightfields; cameras; and contact materials.
  • Deterministic branching: serialize snapshot() state, try an action sequence, restore, and branch again.
  • CPU parallelism: the included vectorizer runs independent native simulators in separate processes; PPO defaults to 32 environments.
  • Python-controlled web UI: stream authoritative native poses to a browser, receive direction/speed or floor-click targets, and control overlays from Python.
  • One physics source: engine/physics.cpp builds as a macOS/Linux shared library and as WebAssembly.

Beginner quick start

Python 3.9 or newer is supported. Install the native package from PyPI:

python -m pip install lavendersim

The release includes native wheels for Linux x86-64, macOS Intel, and macOS arm64.

Create and step your first environment:

import numpy as np
from lavendersim.env import make

env = make("CartPoleBalance-v0", control_hz=60, horizon_seconds=3, seed=7)
observation, info = env.reset(seed=7)

for _ in range(180):
    # Replace this with your policy. Every action component is in [-1, 1].
    action = np.zeros(env.action_space.shape, dtype=np.float32)
    observation, reward, terminated, truncated, info = env.step(action)
    if terminated or truncated:
        observation, info = env.reset()

env.close()

What the values mean:

  • observation: the flat float32 policy input.
  • reward: the task-specific learning signal.
  • terminated: a physical success or failure condition occurred.
  • truncated: the episode reached its time limit.
  • info: diagnostics such as tracking error and contact counts.

List every environment or run an example:

python examples/envs/list_envs.py
python examples/envs/rover_waypoint.py --steps 300 --headless
python examples/envs/cartpole_balance.py --steps 600 --web

Environment catalog

ID Goal Notable features
CartPoleBalance-v0 Balance a pole on a moving cart Effort actuator, activation dynamics, snapshots
AcrobotSwingup-v0 Swing an underactuated arm upright Named sites, actuator friction
ReactionWheelCube-v0 Stabilize a cube with internal wheels IMU, armature, delayed actuation
TiltMaze-v0 Roll a ball to a target and settle Low friction, goal dwell reward
RoverWaypoint-v0 Drive to a randomized waypoint Ray-fan lidar, heightfield terrain
HopperCommand-v0 Track a requested planar speed Fixed tendon, IMU, terrain probe
QuadrupedTerrain-v0 Track randomized direction and speed 12 joints, range probes, command input
ArmReach-v0 Reach randomized 3-D targets End-effector sites and velocities
TactileGripperLift-v0 Grasp, lift, and hold a payload Tactile arrays, coupled jaw tendon
PegInsertion-v0 Align and seat a peg Site errors, filtered force/torque sensing
WalkerCommand-v0 Follow a body-relative motion command IMU and joint proprioception
QuadrupedCommand-v0 Follow planar commands Randomized command-conditioned locomotion
ManipulatorPush-v0 Push a ball to a clicked target and stop Goal-conditioned interaction and web target UI

Use an ID with lavendersim.env.make() or the PPO trainer. The short aliases walker, quadruped, and manipulator remain supported.

Author a Python scene

from lavendersim import PD, Scene
from lavendersim.runtime import CodeSceneEnv

scene = Scene("Two-link robot")
base = scene.box("base", size=(0.3, 0.2, 0.3), position=(0, 0.1, 0), mass=0)
link = scene.capsule("link", radius=0.05, length=0.8, position=(0, 0.55, 0), mass=1)
joint = scene.revolute(
    "shoulder", base, link,
    anchor=(0, 0.2, 0), axis=(0, 0, 1),
    limits=(-1.5, 1.5), pd=PD(kp=30, kd=2, max_torque=20),
)
tip = scene.site("tip", body=link, position=(0, 0.4, 0))

with CodeSceneEnv(scene, control_dt=1 / 60) as sim:
    observation, info = sim.reset(seed=1)
    observation, reward, terminated, truncated, info = sim.step({"shoulder": 0.4})
    print(observation["sites"]["tip"])

Scenes support boxes, spheres, capsules, cylinders, convex bodies, articulated actors, collision exclusions, materials, cameras, motion generators, UI metadata, and the sensor/actuator features listed above.

PPO training on CPU

Install the RL extra from a checkout:

python -m pip install -e '.[dev,rl]'
./build_native.sh
python -m experiment.train_ppo \
  --task QuadrupedTerrain-v0 \
  --num-envs 32 \
  --control-hz 60 \
  --horizon-seconds 3 \
  --rollout-steps 180 \
  --output-dir experiment/runs/quadruped-terrain

The default geometry produces 5,760 transitions per PPO update. A tiny end-to-end smoke run is useful before a long experiment:

python -m experiment.train_ppo \
  --task CartPoleBalance-v0 --num-envs 2 --rollout-steps 30 \
  --updates 1 --epochs 1 --minibatch-size 60 \
  --output-dir /tmp/lavendersim-smoke

Live browser visualization

The Python server remains authoritative: it steps the native environment, runs the policy, streams body poses to the browser, and receives UI commands.

./build_web.sh
python -m experiment.serve_quadruped \
  --checkpoint experiment/runs/quadruped_ppo/checkpoint.pt

Open http://127.0.0.1:8765/?live=1. The quadruped page sends direction and speed back to Python. The manipulator page sends a clicked floor target. Python can also select visible bodies, colors, sites, contacts, joints, sensor rays, tendons, heightfields, camera state, and metrics through LiveViewer.

Snapshots

state = env.snapshot()
first_branch = env.step(action_a)
env.restore(state)
second_branch = env.step(action_b)

encoded = state.to_bytes()
env.restore(encoded)

Snapshots validate the scene fingerprint and include body/joint state, actuator activation, sensor filters and delays, simulation time, and RNG state.

Development

git clone https://github.com/cloneofsimo/lavendersim.git
cd lavendersim
python3 -m venv .venv
.venv/bin/pip install -e '.[dev,rl]'
./build_native.sh
.venv/bin/pytest -q

The same CMake definition builds macOS and Linux wheels. CI also builds the WebAssembly engine and tests isolated wheel installation. See docs/development.md for release details.

Project status and scope

LavenderSim is experimental alpha software, not a drop-in MuJoCo replacement. It does not currently implement MJCF import, deformables, spatial tendon wrapping, fluids, general equality constraints, or GPU simulation. Validate physics behavior and learned policies before using them in consequential or real-world systems.

Released under the MIT 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

lavendersim-0.2.0.tar.gz (229.2 kB view details)

Uploaded Source

Built Distributions

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

lavendersim-0.2.0-py3-none-musllinux_1_2_x86_64.whl (126.4 kB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

lavendersim-0.2.0-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl (126.1 kB view details)

Uploaded Python 3manylinux: glibc 2.28+ x86-64manylinux: glibc 2.5+ x86-64

lavendersim-0.2.0-py3-none-macosx_11_0_x86_64.whl (135.0 kB view details)

Uploaded Python 3macOS 11.0+ x86-64

lavendersim-0.2.0-py3-none-macosx_11_0_arm64.whl (116.7 kB view details)

Uploaded Python 3macOS 11.0+ ARM64

File details

Details for the file lavendersim-0.2.0.tar.gz.

File metadata

  • Download URL: lavendersim-0.2.0.tar.gz
  • Upload date:
  • Size: 229.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for lavendersim-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c15d8602e7375507774d854c064384743352c6a177df8a588f744658d386db1e
MD5 48d53555bcfcb0872c11bb91cb7b1b7e
BLAKE2b-256 1e10e39127483968ccd80153451a8540cb61d4b2a79f4fdb3ac7e30fed59330f

See more details on using hashes here.

Provenance

The following attestation bundles were made for lavendersim-0.2.0.tar.gz:

Publisher: publish.yml on cloneofsimo/lavendersim

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lavendersim-0.2.0-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for lavendersim-0.2.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 afb0b846666550d78f077b29ab1bd17f88d62574fcd9c3aabd5efb7457714658
MD5 6b2075cfa45c515e92632c5144c6d390
BLAKE2b-256 75190400f90d6335c6a6ce4db8caea8d6da36b3065b5c197ff983c528a5bfff8

See more details on using hashes here.

Provenance

The following attestation bundles were made for lavendersim-0.2.0-py3-none-musllinux_1_2_x86_64.whl:

Publisher: publish.yml on cloneofsimo/lavendersim

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lavendersim-0.2.0-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for lavendersim-0.2.0-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 380e154f82853b155622e116bbff426c1ebf4073a5ca43ea0c2e90360e39538a
MD5 fce1e6fb7de57d3ae7366512b06d306c
BLAKE2b-256 c8213da2aff06efbff309699ab91887fa9562aafd69891f5584b3bc4cf2fcda3

See more details on using hashes here.

Provenance

The following attestation bundles were made for lavendersim-0.2.0-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl:

Publisher: publish.yml on cloneofsimo/lavendersim

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lavendersim-0.2.0-py3-none-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for lavendersim-0.2.0-py3-none-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 077698d1f173d9a48f310d6ac25bb8f565c7f0c7f76f033d46358608d49433a8
MD5 bb6574da13fff83cce01e1a6cf9176e6
BLAKE2b-256 fb379bf4899321a7cc027ebef3740d5b4ca708c3ecdc319abd149aab3a3ddb42

See more details on using hashes here.

Provenance

The following attestation bundles were made for lavendersim-0.2.0-py3-none-macosx_11_0_x86_64.whl:

Publisher: publish.yml on cloneofsimo/lavendersim

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lavendersim-0.2.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for lavendersim-0.2.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 55dffb3a4455d9d228e0a9486ba9d7e8d046f9d73a6d5365600aceab5185ba16
MD5 c19c90494bddd7557fbc8311601409c7
BLAKE2b-256 84756926847720877a2d1caf015b3b1f3e96871c76547d7ef0f7528f12c3d8c4

See more details on using hashes here.

Provenance

The following attestation bundles were made for lavendersim-0.2.0-py3-none-macosx_11_0_arm64.whl:

Publisher: publish.yml on cloneofsimo/lavendersim

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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