A NumPy port of the structure of the
L2F simulator
with fixed-wing physics in fixed_wing/airplane/ (aerodynamics, actuator lag, trim, wind with gusts, thermals and turbulence). fixed_wing/multirotor/ is the L2F quadrotor core, which I used to check the skeleton.
fixed_wing/airplane/environment.py is the RL task (hold an airspeed, an altitude and a course) and pid.py its PID baseline.
examples/train_sac.py trains SAC with an asymmetric actor-critic and the L2F reward curriculum; savio/README.md runs it on Savio.
examples/plot_training.py, compare_flights.py (RL against PID over time), make_videos.py and make_3d_videos.py (GIFs), ui_policy.py and ui_fleet.py (live 3D viewer, one or many airplanes) show the results.
examples/reward_saturation.py checks a reward before a long run (how often it is nearly flat under exploration noise).
examples/diagnose_flights.py measures attitude in straight flight and describes every failure.
Results: results/sac_run1 (first run) and
results/sac_gated_curriculum (3 seeds in calm air, 3 in wind).
DIFFERENCES_L2F.md lists what changed from L2F. PARAMETERS.md gives the source of every parameter.
Conventions are the same as L2F (world z up, body x forward / y left / z up, quaternion [w, x, y, z], RK4 at 100 Hz).
The aerodynamic coefficients keep the aerospace convention, converted in airplane_aerodynamics only.
python -m venv ~/.venvs/fixed-wing
~/.venvs/fixed-wing/Scripts/python -m pip install -e ".[dev]"
~/.venvs/fixed-wing/Scripts/python -m pytest
~/.venvs/fixed-wing/Scripts/python examples/validate.py # flight performance vs the Strix numbers from the lab papers
~/.venvs/fixed-wing/Scripts/python examples/benchmark.py # simulation speedUses the rl-tools ui-server with the same protocol as L2F.
~/.venvs/fixed-wing/Scripts/python -m pip install -e ".[ui]"
~/.venvs/fixed-wing/Scripts/ui-server # then open http://localhost:13337
~/.venvs/fixed-wing/Scripts/python examples/ui.pyAfter changing fixed_wing/airplane/ui.js, reload the page.
from fixed_wing.airplane.parameters import aerosonde
from fixed_wing.airplane.trim import trim
from fixed_wing.airplane.operations import normalize_action, step
parameters = aerosonde()
state = trim(parameters, airspeed=25.0)
action = normalize_action(parameters, state.actuators) # [aileron, elevator, rudder, throttle] in [-1, 1]
for _ in range(1000):
state = step(parameters, state, action)