Behavior-to-source map
| I want to… | Read | Look for | Lesson |
|---|---|---|---|
| Author a scene | python/lavendersim/scene.py | Scene, body/joint/site/sensor/actuator builders | Ch. 2–5 |
| Validate and load | python/lavendersim/runtime.py | CodeSceneEnv and native ABI bindings | Ch. 1–12 |
| Apply controls | engine/physics.cpp | update_controller_targets, commanded_effort | Ch. 12 |
| Detect contacts | engine/physics.cpp | detect_contacts, collide_pair, GJK/EPA helpers | Ch. 8 |
| Reuse impulses | engine/physics.cpp | save_contact_cache, warm_start_contacts | Ch. 9, 11 |
| Solve joints/contact | engine/physics.cpp | solve_joint_velocity, solve_contact_velocity | Ch. 7, 9–11 |
| Integrate and project | engine/physics.cpp | integrate_orientation, project_joint, substep | Ch. 1, 7, 12 |
| Sample sensors | engine/physics.cpp | update_imu_sensors, update_tactile_sensors | Ch. 12 |
| Read diagnostics | python/lavendersim/runtime.py | observations, collision/solver/pipeline trace accessors | Ch. 7–12 |
| Define RL tasks | python/lavendersim/env/tasks.py | registered task reset, reward, termination | Environment catalog |
| Create by registry ID | python/lavendersim/env/core.py | register, make, spec, list_envs | Ch. 12 |
| Vectorize workers | experiment/vector_env.py | ProcessVectorEnv | Ch. 12 |
| Render in browser | engine/index.template.html | WebGL renderer, live Python messages, UI commands | Training & web |
| Verify WASM ABI | scripts/check_wasm_exports.mjs | semantic native-style checks inside WebAssembly | Ch. 7–12 |
Trace one env.step(action)
- The task validates a fixed-shape action and translates it into named joint commands.
CodeSceneEnv.stepwrites controls across the native ABI and requests the control interval.sim_stepdivides that interval into bounded substeps and resets public diagnostics.substepfollows the nine stages explained in Chapter 12.- The runtime exposes body, joint, site, contact, sensor, solver, collision, and pipeline buffers as NumPy arrays.
- The task flattens policy-visible signals, computes reward and termination, and may publish richer telemetry to the web server.
observation, reward, terminated, truncated, info = env.step(action)
# task observation: flat policy input
# env.sim.observe(): rich engine telemetry
# info: task reward terms and diagnosticsWho owns which truth?
| Layer | Owns | Does not own |
|---|---|---|
| Scene DSL | Topology, geometry, materials, sensors, actuator configuration | Episode reward or trained behavior |
| C++ engine | Rigid-body state, contacts, constraints, actuator response, native sensor samples | Task success or PPO policy |
lavendersim.env | Reset distribution, policy observation, reward, termination, horizon | Contact response implementation |
| Experiment tooling | Vector workers, PPO collection/update, checkpointing | Scene physics semantics |
| Python web server | Authoritative live state, commands, targets, overlays | Static Pages physics |
| Browser | WebGL view, controls, pointer targets, optional local WASM stepping | Training decisions when Python is authoritative |
Four source-reading routes
A falling body
Scene sphere → runtime step → gravity/force accumulation → integration → body observation.
A bouncing contact
Pair filtering → narrow phase → manifold → restitution bias → normal impulse → contact telemetry.
An articulated leg
Joint builder → coordinate measurement → actuator effort → joint row solve → projection → joint observation.
Python to browser
Environment telemetry → live server message → transform application → overlay draw → pointer command back to Python.
Read tests beside code
Search tests/ and tests/tutorials/ for the public behavior before trusting a comment or screenshot.
Keep models separate
Reference NumPy labs teach algorithms; they do not imply the C++ engine implements every reference algorithm.
Native and WebAssembly share a deliberately small ABI
scripts/build_wasm.sh exports the same scene-construction, stepping, control, and telemetry functions used by the web runtime. scripts/check_wasm_exports.mjs checks behavior—contacts, controls, solver state, and pipeline order—not merely that names exist. Old JSON scene fields receive defaults in the JavaScript loader.