drones_sim
Composable quadcopter simulation for control and state-estimation experiments. It combines a nonlinear quaternion rigid-body model, bounded actuators, SE(3) geometric control, innovation-gated sensor fusion, reproducible sensor models, and result-native 2D/3D visualization.
Install
cd drones_sim
pip install -e ".[dev]"
RL extras (Gymnasium env, SB3 PPO, TensorBoard):
pip install -e ".[rl]"
Full RL dev stack (adds Weights & Biases, Optuna, moviepy):
pip install -e ".[rl-dev]"
Legacy Viser mission-control examples:
pip install -e ".[viser]"
Quick start
The high-level runner owns timing, sensing, estimation, control, logging, and aligned outputs:
from drones_sim import ClosedLoopSimulator, SimulationConfig, visualize
from drones_sim.trajectory import generate_circular
reference = generate_circular(duration=10.0, sample_rate=100, radius=2.0)
simulator = ClosedLoopSimulator(
config=SimulationConfig(dt=0.01, use_estimator=True, seed=7)
)
result = simulator.run(reference)
print(result.summary())
visualize(result) # Rerun is the default backend
For custom experiments, compose QuadcopterConfig, QuadcopterDynamics,
GeometricController, IMUSimulator, GPSSimulator, and
ExtendedKalmanFilter, then inject them into ClosedLoopSimulator.
Working examples
| # | Script | Install | Description |
|---|---|---|---|
| 01 | 01_imu_ekf_basic.py |
Base | IMU simulation and 16-state EKF sensor fusion |
| 02 | 02_ekf_adaptive.py |
Base | Adaptive EKF with temperature-dependent sensor models |
| 03 | 03_waypoint_nav.py |
Base | Minimum-snap waypoint navigation with cascaded PID |
| 04 | 04_viser_viewer.py |
[viser] |
Interactive Viser 3D playback |
| 05 | 05_full_pipeline.py |
[viser] |
Dynamics, sensors, EKF, PID control, and interactive viewer |
| 06 | 06_trajectory_following.py |
[viser] |
EKF-fused trajectory tracking with mission controls |
| 07 | 07_rl_hover.py |
[rl] |
Train and evaluate a PPO hover policy |
| 08 | 08_rl_vs_pid.py |
[rl] |
Compare a trained RL policy with cascaded PID |
| 09 | 09_unified_simulation.py |
Base | Typed end-to-end simulation and diagnostic dashboard |
| 10 | 10_rerun_viewer.py |
Base | Rerun 3D scene, telemetry, streaming, and .rrd export |
Run a base example directly:
python examples/09_unified_simulation.py
The default visualize(result) call opens Rerun. It can also stream to an
existing gRPC server or save a portable recording:
python examples/10_rerun_viewer.py
python examples/10_rerun_viewer.py --save flight.rrd
rerun flight.rrd
Matplotlib and Viser remain available explicitly:
visualize(result, backend="matplotlib", title="Flight report")
visualize(result, backend="viser", port=8080) # requires drones-sim[viser]
Package structure
src/drones_sim/
├── state.py # Typed state, setpoint, and control contracts
├── simulation.py # Reproducible closed-loop orchestration and results
├── math_utils.py # Quaternion ops, rotation matrices, Euler helpers
├── trajectory.py # Trajectory generators (hover-cruise, circular, waypoints, min-snap)
├── models/
│ ├── urdf_loader.py # Pure-stdlib URDF parser (no external deps)
│ └── quadcopter.urdf # Bundled quadcopter model
├── sensors/
│ ├── imu.py # 9-axis IMU simulator (accel, gyro, mag)
│ ├── gps.py # GNSS receiver simulator (position + velocity)
│ └── models.py # SensorNoiseModel (Gauss-Markov bias), TemperatureModel
├── estimation/
│ ├── ekf.py # 16-state EKF + 9-state adaptive EKF + AHRS
│ └── ahrs.py # Complementary-filter AHRS
├── dynamics/
│ ├── quadcopter.py # 13-state quaternion Newton-Euler rigid body
│ └── disturbances.py # Wind, gust, ground effect, motor failure, payload drop
├── control/
│ ├── pid.py # Scalar PID with anti-windup
│ ├── cascaded.py # Position → Velocity → Attitude cascaded PID
│ ├── geometric.py # Nonlinear SE(3) trajectory controller
│ ├── allocation.py # Bounded weighted least-squares motor allocation
│ └── lqr.py # Full-state feedback LQR (CARE solution)
├── rl/
│ ├── env.py # QuadcopterEnv (gymnasium.Env wrapper)
│ ├── actions.py # MotorSpeedAction, ThrustBodyRatesAction, VelocityLevelAction, LQRResidualAction
│ ├── observations.py # RelativeStateObs (17-D observation)
│ ├── tasks.py # HoverTask, WaypointTask, TrackingTask
│ └── reward.py # Weighted multi-term reward function
├── logging/
│ ├── csv_logger.py # CSV telemetry logger
│ └── json_logger.py # JSON Lines telemetry logger
└── visualization/
├── api.py # visualize(); Rerun is the default backend
├── plots.py # Matplotlib multi-panel comparison plots
├── dashboard.py # SimulationResult engineering dashboard
├── rerun_viewer.py # Default synchronized 3D, telemetry, events, and replay
└── viewer.py # Optional Viser mission-control UI (`[viser]`)
training/
├── train_ppo.py # PPO training entry point (YAML config, CPU default, W&B)
├── eval_policy.py # Policy evaluation with success/crash metrics
├── configs/
│ ├── ppo_hover.yaml # Config for thrust_rates / lqr_residual actions
│ └── ppo_hover_vel.yaml # Config for velocity-level action
└── checkpoints/ # Saved models and VecNormalize stats
Features
Project status
| Area | Status |
|---|---|
| Quaternion dynamics, bounded allocation, geometric/PID/LQR control | ✅ Implemented and tested |
| Sensor simulation, EKF/AHRS estimation, closed-loop orchestration | ✅ Implemented and tested |
| CI, disturbances, CSV/JSON telemetry, Rerun replay | ✅ Implemented and tested |
| Gymnasium environment, PPO training/evaluation, RL examples | ✅ Baseline implemented |
| ULog export and RL domain randomization/curriculum | 🟡 Partially implemented / planned |
| MPC, Monte Carlo evaluation, VIO, obstacle planning, swarms, SITL | ⬜ Planned |
See the development roadmap for acceptance criteria and remaining work.
State estimation
| Filter | States | Description |
|---|---|---|
| Extended Kalman Filter | 16-state | Position(3), velocity(3), quaternion(4), accel bias(3), gyro bias(3). Analytical Jacobians, Joseph form covariance, GPS/baro/velocity corrections |
| Adaptive EKF | 9-state | Position(3), velocity(3), accel bias(3). Innovation-window adaptive noise, Gauss-Markov bias |
| AHRS | Complementary filter | Fuses accel, gyro, mag with gyro bias learning |
Control
| Controller | Type | Description |
|---|---|---|
| Geometric | Nonlinear SE(3) | Quaternion-safe trajectory tracking with velocity/acceleration feedforward and bounded allocation |
| Cascaded PID | 3-loop cascade | Position → Velocity → Attitude. 9 PID instances, motor-speed output |
| LQR | Full-state feedback | Linearized around hover, CARE solution, wrench → motor allocation |
Disturbances (6 types)
| Disturbance | Category | Description |
|---|---|---|
ConstantWind |
Wind | Steady world-frame drag force |
StepWind |
Wind | Wind that switches on at a given time |
DrydenGust |
Wind | Continuous turbulence — Gauss-Markov process (MIL-F-8785C) |
MotorFailure |
Failure | Degraded rotor thrust coefficient |
PayloadDrop |
Failure | Instantaneous mass change |
GroundEffect |
Environment | Thrust augmentation near ground (Cheeseman & Bennett) |
Reinforcement learning
- QuadcopterEnv — Gymnasium
Envcompatible with SB3, CleanRL, Tianshou, RLlib - Four action parameterizations — three levels of abstraction plus a residual:
| Action | Policy outputs | Stabilization |
|---|---|---|
MotorSpeedAction |
Raw motor speeds (4× rad/s) | None (hardest) |
ThrustBodyRatesAction |
Thrust delta + body rates (ωx,ωy,ωz) | Rate → torque P-controller |
VelocityLevelAction |
World-frame velocity (vx,vy,vz) + yaw rate | Built-in cascaded P-controller (velocity → attitude → torque) |
LQRResidualAction |
Delta on LQR motor speeds (in [-1,1]) | Full-state LQR feedback (CARE solution) |
- Three tasks: hover, waypoint sequence, trajectory tracking
- Weighted multi-term reward (position, velocity, attitude, action smoothness, alive/crash)
- PPO training in
training/train_ppo.pywith YAML configs, TensorBoard logging, and optional W&B tracking - Policy evaluation in
training/eval_policy.py(RMSE, success rate, crash rate)
Training
The training script defaults to CPU for small MLP policies (GPU transfer overhead dominates):
# LQR residual (recommended — 75%+ success rate at 500k steps)
python -m training.train_ppo \
--config training/configs/ppo_hover.yaml \
--timesteps 500000 \
--action-type lqr_residual
# Velocity-level (0% crash, 1.5m RMSE)
python -m training.train_ppo \
--config training/configs/ppo_hover_vel.yaml \
--timesteps 200000 \
--action-type velocity
# Thrust + body rates (legacy)
python -m training.train_ppo \
--config training/configs/ppo_hover.yaml \
--timesteps 200000 \
--action-type thrust_rates
Track training with Weights & Biases:
python -m training.train_ppo \
--config training/configs/ppo_hover.yaml \
--action-type lqr_residual \
--track --wandb-project drones-sim-ppo
Open TensorBoard (logs are saved to ./tb/):
tensorboard --logdir tb/
Evaluation
# Evaluate a trained checkpoint
python -m training.eval_policy \
--path training/checkpoints/final.zip \
--episodes 20 \
--action-type lqr_residual
# Expected output:
# pos_rmse: 0.1370
# success_rate: 0.7500
# crash_rate: 0.0000
# mean_reward: 6390.6716
Logging
| Logger | Format | Description |
|---|---|---|
CsvLogger |
CSV | Full state + motor speeds + estimate per row |
JsonLogger |
JSON Lines | Per-line JSON objects; machine-readable |
Tests
pytest tests/ -v
Release history is maintained in CHANGELOG.md.
License
MIT — see LICENSE.
Dependencies
| Dependency | Purpose |
|---|---|
| numpy, scipy | Numerical computation |
| matplotlib | 2D plotting |
| Rerun | Default synchronized 3D telemetry, replay, and .rrd export |
| viser | Optional interactive mission controls ([viser]) |
| torch, stable-baselines3, gymnasium | RL training ([rl] extra) |
| tensorboard, pyyaml | RL logging & config ([rl] extra) |
Metadata
Release files for drones-sim 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| drones_sim-0.2.0.tar.gz | 84.4 kB | Without provenance | Details for drones_sim-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| drones_sim-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for drones_sim-0.2.0-py3-none-any.whl |
Total release size: 161.7 kB
Release files / drones_sim-0.2.0.tar.gz
| Download URL | drones_sim-0.2.0.tar.gz |
|---|---|
| Size | 84.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c75dd19e1fdf2e7f12ce4a07461af9f095129273afb39c1ed4fae2f76909be87
|
|
BLAKE2b-256 checksum How to use checksums |
2ee49212392f30ae98c4d83c0b8e53faa21d181895945cb3b7a6088347255345
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.5
|
Release files / drones_sim-0.2.0-py3-none-any.whl
| Download URL | drones_sim-0.2.0-py3-none-any.whl |
|---|---|
| Size | 77.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
535d3c87b41f6efec5094a4006bc108a6e083c8090d505eee6c39d6b06e63333
|
|
BLAKE2b-256 checksum How to use checksums |
12cf50d75a3ecdb46448e56cfcc50980cc9a87e905ac2b63f57d87b8ec905466
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.5
|
Security for drones-sim 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.