TensorAeroSpace
Open-source aerospace simulation + adaptive control toolkit. Trim, fly, fail, recover — all in pure NumPy.
Why TensorAeroSpace?¶
-
Real airframes, not toys
Every model is transcribed from peer-reviewed source data: NASA CR-2144 (B-747), NASA TM X-1669 (X-15), CEAS Aeronautical Journal 2025 (Skywalker X8), JSBSim (B-737), Roskam Vol VI + class-II UAV literature (RQ-7 Shadow). Trim points reach machine precision; cross-validated against published derivatives.
-
Pure NumPy core
No proprietary simulators, no MATLAB licence, no compiled binaries. The 6-DoF Newton-Euler ODE is an order of magnitude faster than JSBSim for control-synthesis sweeps, and trivially differentiable for adjoint-based methods.
-
Unique adaptive-control catalogue
The standard RL stack (PPO, SAC, DDPG, DQN, A2C, A3C, GAIL) plus the full incremental-ADP family (IHDP, IM-GDHP, ET-DHP, iADP, AA-INDI, AIDI) — rarely co-located in a single open-source package. All wrapped in the same Gymnasium API.
-
Damage subsystem built-in
Per-surface effectiveness loss, hard-overs, jam events, asymmetric-thrust engine-out, flap-jam configuration override — all composable into
DamageProfileinstances. Runs out of the box on B-747 and F-16; parity hooks on every other airframe. -
Gymnasium-native
Every env implements the standard
reset()/step()/action_space/observation_spacecontract. Drop-in replaceable in any Gymnasium / Stable Baselines3 / CleanRL pipeline. -
Continuously verified
Trim convergence, surface-deflection sign conventions, propellant burnout times — all locked down by 894 unit tests with regression coverage on every push.
30-second start¶
import gymnasium as gym
import tensoraerospace # registers all envs
import numpy as np
env = gym.make("NonlinearB747-v0", trim_at=(20_000.0, 674.0),
number_time_steps=2000, dt=0.01)
obs, _ = env.reset()
trim_action = np.array([-0.0126, 0.0, 0.0, 0.555]) # rad / [0, 1]
for _ in range(2000):
obs, _, _, trunc, _ = env.step(trim_action)
if trunc: break
print(f"V={float(np.linalg.norm(obs[:3])):.1f} ft/s, "
f"alt={-float(obs[11]):.0f} ft")
# → V=674.0 ft/s, alt=20000 ft (perfect trim hold)
import gymnasium as gym
import numpy as np
from tensoraerospace.agent.pid import PID
from tensoraerospace.utils import generate_time_period
from tensoraerospace.signals.standard import unit_step
dt = 0.01
tp = generate_time_period(tn=10, dt=dt)
ref = unit_step(degree=5, tp=tp, time_step=2.0,
output_rad=True).reshape(1, -1)
env = gym.make('LinearLongitudinalF16-v0',
number_time_steps=len(tp),
initial_state=[[0], [0]],
reference_signal=ref, use_reward=False)
pid = PID(env, kp=-14.29, ki=-8.24, kd=-1.30, dt=dt)
obs, _ = env.reset()
for t in range(len(tp) - 1):
u = pid.select_action(ref[0, t], float(obs[0]))
obs, _, term, trunc, _ = env.step(np.array([[float(u)]],
dtype=np.float32))
if term or trunc: break
from tensoraerospace.aerospacemodel.b747.nonlinear import trim
from tensoraerospace.envs.b747_nonlinear import NonlinearB747Env
from tensoraerospace.agent.ihdp.model import IHDPAgent
import numpy as np, math
# Trim at FL200 cruise
r = trim(altitude_ft=20_000.0, V_ft_s=674.0)
env = NonlinearB747Env(trim_at=(20_000.0, 674.0),
number_time_steps=3000, dt=0.02)
agent = IHDPAgent(actor_settings={...}, critic_settings={...},
incremental_settings={...},
tracking_states=["d_theta"],
selected_states=["d_theta", "q"],
selected_input=["d_elev"],
number_time_steps=3000,
indices_tracking_states=[0])
# Single-pass online learning — no offline pre-training
obs, _ = env.reset()
# ... run rollout ...
# → Late-half MAE θ = 0.043° on a 1° step (4.3% of amplitude)
python example/reinforcement_learning/deep_rl/sac-b747-render.py \
--render --dt 0.1 --tn 200 \
--repo TensorAeroSpace/sac-b747 --device cuda
Or via Python:
from tensoraerospace.agent.sac import SAC
from tensoraerospace.envs.b747 import ImprovedB747Env
agent = SAC.from_pretrained("TensorAeroSpace/sac-b747")
env = ImprovedB747Env(dt=0.1, number_time_steps=200)
obs, _ = env.reset()
while True:
action = agent.select_action(obs, evaluate=True)
obs, _, term, trunc, _ = env.step(action)
env.render(mode="human")
if term or trunc: break
Aircraft library¶
Every model has a Gymnasium env, a trim solver, full 6-DoF dynamics, and peer-reviewed source data.
| Airframe | Class | Configurations | Aerodynamic source | Speciality |
|---|---|---|---|---|
| F-16 Fighting Falcon | Fighter | longitudinal · 6-DoF angular · damage | NASA / Stevens-Lewis tables | Cubic-spline aero, full damage subsystem |
| Boeing 747-100 | Heavy transport | NOMINAL · POWER_APPROACH · LANDING | NASA CR-2144 (Heffley & Jewell) | Per-engine asymmetric thrust + flap jam |
| Boeing 737-100/800 | Mid-size transport | 737-100 · 737-800 (NG) | JSBSim + Roskam Vol VI | Coordinated-turn benchmarks |
| X-15 | Hypersonic research | BASIC · A2 record | NASA TM X-1669 + Thompson 2000 | Mach-tabulated 0.4–6.7, XLR99 rocket, variable mass |
| Skywalker X8 | Small UAV (3.4 kg) | flying-wing | CEAS Aeronautical Journal 2025 | Peer-reviewed flight-test ID |
| AAI RQ-7 Shadow | Class-II UAV (170 kg) | RQ-7B | Beard & McLain + NASA TM-2014-218686 | V-tail mixed control |
| Quadrotor | Multirotor | nonlinear 6-DoF + damage | Standard quad-X derivation | Per-rotor failure, X-config allocator |
| F-4C, ELV, ComSat, GeoSat, LSU, Ultrastick, UAV, Missile | Linear / improved | various | Roskam, AIAA conf | Classical state-space + RL-friendly wrapper |
Control catalogue¶
20 algorithms, organised by family:
| Algorithm | Description |
|---|---|
| PID | Classical PID with multiple tuning workflows |
| MPC | Model-Predictive Control with MLP / NARX / Transformer plant models |
Classical batch-trained ADP family:
| Algorithm | Notebook |
|---|---|
| HDP (Heuristic Dynamic Programming) | acd_hdp_b747.ipynb |
| DHP (Dual Heuristic Programming) | acd_dhp_b747.ipynb |
| GDHP (Globalized Dual HP) | acd_gdhp_b747.ipynb |
| AD-HDP | acd_adhdp_b747.ipynb |
| AD-GDHP | acd_adgdhp_b747.ipynb |
| AD-DHP | acd_addhp_b747.ipynb |
Online single-pass adaptive critic — the unique part of the catalogue:
| Algorithm | Pitch-step / cruise tracking | Damage scenarios |
|---|---|---|
| IHDP | F-16 sin-α, B-747 θ-step, B-737 90° turn, quadrotor | failure recovery |
| IM-GDHP | F-16 nonlinear | — |
| ET-DHP | F-16 sinusoid | B-747 engine-out (0.28° ψ-error), F-16 damage |
| iADP | F-16 nonlinear | F-16 damage |
| AA-INDI | F-16 nonlinear | — |
| AIDI | — | F-16 damage |
Standard model-free RL stack:
| Algorithm | Type | Pretrained checkpoint |
|---|---|---|
| SAC | Off-policy actor-critic | HF: TensorAeroSpace/sac-b747 |
| DSAC | Distributional SAC | step-response & tracking variants |
| PPO | On-policy clipped objective | 8 airframes |
| DDPG | Deterministic policy gradient | B-747 |
| DQN | Discrete value iteration | B-747, Unity |
| A2C | Synchronous actor-critic | B-747 + NARX critic |
| A3C | Asynchronous A-C | B-747 |
| GAIL | Generative imitation | F-16 dataset |
Architecture¶
┌────────────────────────────────────────────────────────────────────────┐
│ tensoraerospace package │
├──────────────────┬──────────────────────┬───────────────────────────────┤
│ aerospacemodel │ envs │ agent │
├──────────────────┼──────────────────────┼───────────────────────────────┤
│ pure-NumPy │ Gymnasium-spec │ Classical · ADP · Deep RL │
│ 6-DoF dynamics │ wrappers │ PID, IHDP, ET-DHP, SAC, ... │
│ Trim solvers │ "virtual" / │ All consume Gym env API │
│ Damage subsys. │ "normalized" │ │
│ │ action modes │ │
└──────────────────┴──────────────────────┴───────────────────────────────┘
│
▼
Gymnasium / SB3 / CleanRL ← any RL pipeline plugs in
The three packages are weakly coupled. You can use the dynamics standalone (no Gym), the env without an agent (just a wrapper), or build your own controller against any model. Same Gymnasium API across linear / nonlinear / damaged models means the controller code is portable.
Use cases¶
"I need a faithful 6-DoF aircraft model to design a controller against."
- Pick an airframe from the model gallery.
- Use the trim solver (
trim(altitude, V)) to find your operating point. - Linearise around trim or run nonlinear simulation directly.
- Validate against the published cruise / loiter / hypersonic conditions in the docs.
Example: Boeing 747 nonlinear, B-737 coordinated turn.
"I want to benchmark a new agent on aerospace tasks."
- Drop-in any of the 20+ envs registered with
gym.make("...-v0"). - Use the included PID / IHDP / SAC baselines for fair comparison.
- Compare metrics with the published comparison studies.
- Push your trained model to Hugging Face under the same wrapper.
Example: SAC on B-747, IHDP vs PID on F-16.
"I'm researching control reconfiguration after damage."
- Use the damage subsystem — surface jam, effectiveness loss, engine flameout, flap jam, RCS thruster failure.
- Compose
DamageProfileinstances declaratively. - Run an online ADP agent (ET-DHP, iADP, AIDI) that adapts to the change in real time.
Example: ET-DHP B-747 engine-out yaw hold (0.28°).
"I'm learning flight dynamics or adaptive control."
- Start with the cookbook — 16 step-by-step recipes from "hello world" to FTC under damage.
- Read the 11 lessons on state-space, controllability, RL fundamentals, and a hands-on practical (XFLR5 → Simulink → Python).
- Open any notebook from the example gallery and run it locally.
Example: Lesson 1 — State-Space Intro, Cookbook — Online-adaptive agents.
What's new¶
-
AAI RQ-7 Shadow nonlinear
Class-II tactical UAV, 170 kg, V-tail mixed convention, 4-channel control. Synthesised from Beard & McLain + NASA TM-2014-218686 + Roskam Vol VI.
-
Boeing 737 nonlinear
737-100 / 737-800 with JSBSim aerodynamic data, JT8D / CFM56-7B engine models, machine-precision trim, MIMO IHDP coordinated turn example.
-
X-15 hypersonic
M = 0.4 → 6.7, XLR99 rocket engine, variable mass, 13-state vector with propellant channel. Burnout time 79.8 s — matches Thompson 2000 to 0.2 %.
-
Skywalker X8 small UAV
Peer-reviewed flight-test identification (CEAS Aeronautical Journal 2025). 3.4 kg flying-wing, 3-channel control, propeller-airframe drag coupling.
-
B-747 damage subsystem v2
Per-engine asymmetric thrust + flap-jam configuration override + 5 ready-made presets including
LEFT_OUTER_ENGINE_FAILURE. -
Restructured
example/Top-level grouped by controller class;
reinforcement_learning/split intoincremental_adp/anddeep_rl/. 101 notebooks, all paths updated in docs.
Featured benchmarks¶
Real numbers from runnable example notebooks:
| Scenario | Result | Source |
|---|---|---|
| B-747 ET-DHP heading hold under engine flameout | ψ-error 0.28° vs open-loop −85.5° | notebook |
| B-737 MIMO IHDP 90° coordinated turn | final ψ-error 0.98°, max sideslip 0.11° | notebook |
| B-747 IHDP θ step (1°) | late-half MAE 0.043° | notebook |
| X-15 boost-burnout (full throttle) | burnout 79.8 s vs Thompson 2000: 80 s | model |
| Skywalker X8 cruise trim | machine precision (residual 1e-15) | model |
Installation¶
Python 3.10–3.12, no MATLAB required, no proprietary code paths.
Resources¶
| 📦 Package | PyPI · GitHub · Hugging Face |
| 📚 Documentation | Models · Algorithms · Cookbook · Lessons |
| 🧪 Examples | 101 notebooks on GitHub |
| 📊 Benchmarks | Comparison studies · Metrics |
| 💬 Community | Issues · DeepWiki Q&A |
Citation¶
If you use TensorAeroSpace in your research, please cite:
@software{tensoraerospace,
title = {TensorAeroSpace: An Open-Source Aerospace Simulation and Adaptive Control Toolkit},
author = {Mazaev, A. and contributors},
year = {2026},
url = {https://github.com/TensorAeroSpace/TensorAeroSpace},
note = {Pure-NumPy 6-DoF aerospace dynamics + Gymnasium envs + classical/adaptive/deep RL agents}
}
For the underlying aerodynamic data sources — NASA CR-2144 (B-747), NASA TM X-1669 (X-15), CEAS Aeronautical Journal 2025 (Skywalker X8), JSBSim (B-737), Beard & McLain (Aerosonde / Shadow), Roskam Vol VI — please also cite the original references listed in each model's documentation page.
MIT licensed · built with NumPy, PyTorch, Gymnasium · powered by the aerospace research community.