Getting started¶
Install¶
pip install flapsim # core: MuJoCo, NumPy, PyYAML
pip install "flapsim[rl]" # + Gymnasium (add stable-baselines3 for PPO)
pip install "flapsim[video,hdf5]" # + imageio/ffmpeg video, h5py export
From a checkout: pip install -e ".[dev]" then pytest -q.
Python 3.10 or newer; MuJoCo 3.3 or newer is installed automatically. On a
headless machine set MUJOCO_GL=osmesa or MUJOCO_GL=egl for rendering.
Run the example robot¶
The package ships a 30 g single-thrust flapper (two passive-feathering wings on a two-axis gimbal) with two setups:
flapsim run SingleThrustFlapper # sim.yaml: fixed base, quasi-steady aero
flapsim run SingleThrustFlapper --config hover # hover.yaml: floating base, hover PID
flapsim run SingleThrustFlapper --headless --duration 2 --frequency 40
flapsim run SingleThrustFlapper --describe # the assembled plugins and signals
Assemble a simulation in Python¶
from flapsim import Simulation
sim = Simulation("SingleThrustFlapper") # or a robot.yaml / URDF / MJCF path
sim.add(
{
"type": "actuator/sinusoidal_stroke",
"id": "stroke",
"joints": ["left_flapping_joint", "right_wing_flapping"],
"directions": [1, -1],
"frequency_hz": 40.0,
"amplitude_rad": 1.5,
}
)
sim.add("aero/quasi_steady")
sim.add({"type": "sensor/imu", "rate_hz": 500.0})
sim.add(
{"type": "recorder/memory", "signals": ["aero/F_world", "imu/*"], "every": 1e-3}
)
sim.run(1.0) # headless
rec = sim["recorder"]
print(rec["aero/F_world"][:, 2].mean())
rec.to_csv("run.csv")
Plugins are addressed by kind/name (flapsim plugins lists them). They
communicate through named signals: the aero plugin publishes
wings/left/alpha, the IMU publishes imu/gyro, a controller publishes
cmd/stroke/frequency_hz and the stroke actuator obeys it.
Or write a setup file¶
# my_sim.yaml
schema: flapsim.sim/1
robot: SingleThrustFlapper # or a path to robot.yaml / model file
plugins:
- type: actuator/sinusoidal_stroke
id: stroke
joints: [left_flapping_joint, right_wing_flapping]
directions: [1, -1]
frequency_hz: 40.0
amplitude_rad: 1.5
- type: atmosphere/standard
wind: [0.5, 0.0, 0.0]
- type: aero/stack
models: [quasi_steady, rotational_lift, added_mass]
- type: recorder/memory
signals: ["aero/F_world", "wings/*/alpha"]
every: 1.0e-3
run:
duration: 2.0
flapsim run my_sim.yaml --headless
flapsim record my_sim.yaml --output clip.gif --duration 0.1 --slow 20
Next steps¶
- Import your robot: write a manifest for your URDF.
- Aerodynamic models and Components.
- Write a plugin and ship it as a pip package.
- Learning and studies: Gymnasium wrapper and parameter sweeps.