Metadata-Version: 2.4
Name: lavendersim
Version: 0.2.0
Summary: Python-first native multibody simulation for reinforcement learning
License-Expression: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: C++
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Project-URL: Homepage, https://github.com/cloneofsimo/lavendersim
Project-URL: Repository, https://github.com/cloneofsimo/lavendersim
Project-URL: Issues, https://github.com/cloneofsimo/lavendersim/issues
Requires-Python: >=3.9
Requires-Dist: numpy>=1.23
Provides-Extra: rl
Requires-Dist: torch>=2.1; extra == "rl"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: twine>=5; extra == "dev"
Requires-Dist: cmake>=3.18; extra == "dev"
Requires-Dist: ninja>=1.11; extra == "dev"
Description-Content-Type: text/markdown

# 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](https://cloneofsimo.github.io/lavendersim/) ·
[Environment guide](https://cloneofsimo.github.io/lavendersim/environments/) ·
[Examples](examples/) · [Development guide](docs/development.md)

> **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:

```bash
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:

```python
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:

```bash
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

```python
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:

```bash
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:

```bash
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.

```bash
./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

```python
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

```bash
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`](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](LICENSE).
