Repository navigation
Simulator Architecture
github-actions[bot] edited this page Nov 3, 2026
·
1 revision
The simulator runs the unmodified firmware against Python stand-ins (shims) for the hardware modules, and renders the droid in 3D.
flowchart LR
subgraph py["Python thread (embedded CPython via PyO3)"]
fw["PropMaker_Feather/code.py<br/>+ behaviours/"]
shims["shims/<br/>board, busio, pwmio, digitalio,<br/>adafruit_servokit, adafruit_lis3dh,<br/>audiomixer, …"]
rt["sim_runtime.py<br/>importer, virtual clock,<br/>strict getenv, State readout"]
fw --> shims
shims -- "simhw.*" --> simhw
end
simhw["simhw module<br/>(pyhost.rs)"] --> hw["HwState<br/>(hw.rs, shared, Mutex)"]
subgraph bevy["Bevy app (main thread)"]
scene["scene.rs / droid.rs / parts.rs<br/>3D model"]
ui["ui.rs, dock.rs, palette.rs …<br/>egui panels"]
audio["audio.rs"]
end
hw --> scene
hw --> ui
hw --> audio
ui -- "nudge, pause, speed …" --> hw
| Part | Files | Job |
|---|---|---|
| Python host | pyhost.rs |
Embeds CPython with PyO3, runs code.py on its own thread, restarts it, and exposes the simhw module. |
| Shared state | hw.rs |
HwState: PCA9685 duties, pins, accelerometer, audio, parts, run state. Python writes, Bevy reads, behind one Mutex. reset_for_run clears it on restart. |
| Shims | simulator/shims/*.py |
Mirror the CircuitPython/Adafruit API the firmware uses and forward to simhw. They do the real hardware maths (angle → pulse → duty at 50 Hz; LIS3DH clipping). |
| Runtime | shims/sim_runtime.py |
The import hook (CircuitPython-strict mode), virtual clock (speed, pause, step, board timing), getenv from settings.toml, and the State panel's coroutine readout. |
| 3D |
scene.rs, droid.rs, parts.rs
|
Bevy scene: the Lola glTF or primitive model, wing hinges from sim.toml, glowing eyes, parts. |
| UI |
ui.rs, dock.rs, layout.rs, palette.rs, theme.rs, toast.rs, overlay.rs, part_edit.rs
|
egui panels in an egui_dock layout, command palette, themes, notifications, overlays, parts editor. The SHORTCUTS table in ui.rs feeds keys, tooltips, the Shortcuts panel and the palette. |
| Accessibility |
a11y.rs, announce.rs
|
AccessKit names and the status-line live region. |
| Other |
audio.rs, wav.rs, capture.rs, deploy.rs, settings.rs, editor.rs, prefs.rs, config.rs
|
Sound, WAV checks, screenshots, Deploy, the Settings panel, opening tracebacks in an editor, saved preferences, sim.toml/parts.toml parsing. |
Pinned in simulator/Cargo.toml: Bevy =0.17.3, bevy_egui =0.38.1 (egui 0.33, AccessKit on), egui_plot =0.34.1, egui_dock =0.18.0, PyO3 =0.25.1 (abi3, Python 3.11+). Major version upgrades need the maintainer's OK.
- The firmware's clock is virtual: speed, pause and step act on it, and Board speed charges each hardware call the time it takes on the RP2040.
- The simulated CIRCUITPY drive is
PropMaker_Feather/withdist\fs\layered on top for writes, read-only to the firmware untilboot.pyremounts it, as on the board. - Rules for shims and when Rust is needed: the shim guide.
- Adding a kind of output: Adding a part kind.
DD-L0-LA59 Animatronics · Project on GitHub · Report a problem with this page · Edit these pages in the wiki/ folder
Start here
Using the simulator
- Get the simulator
- A tour of the window
- Make her breathe, boop and more
- Camera, overlays and recording
- Speed, scenarios and panels
- Layouts, themes and shortcuts
- Accessibility
- Troubleshooting and FAQ
Building the robot
- Safety first
- Parts list
- Wiring
- Install CircuitPython
- Copy the firmware
- Calibrate the wings
- Test it and read the log
Changing how she behaves
Adding new hardware
For developers
- Building the simulator
- Project layout
- CI and releases
- Contributing and branching
- Simulator architecture
- Adding a part kind
Reference