drones-sim 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. drones_sim-0.2.0/LICENSE +21 -0
  2. drones_sim-0.2.0/PKG-INFO +323 -0
  3. drones_sim-0.2.0/README.md +288 -0
  4. drones_sim-0.2.0/pyproject.toml +52 -0
  5. drones_sim-0.2.0/setup.cfg +4 -0
  6. drones_sim-0.2.0/src/drones_sim/__init__.py +15 -0
  7. drones_sim-0.2.0/src/drones_sim/control/__init__.py +15 -0
  8. drones_sim-0.2.0/src/drones_sim/control/allocation.py +76 -0
  9. drones_sim-0.2.0/src/drones_sim/control/cascaded.py +204 -0
  10. drones_sim-0.2.0/src/drones_sim/control/geometric.py +170 -0
  11. drones_sim-0.2.0/src/drones_sim/control/lqr.py +174 -0
  12. drones_sim-0.2.0/src/drones_sim/control/pid.py +50 -0
  13. drones_sim-0.2.0/src/drones_sim/dynamics/__init__.py +13 -0
  14. drones_sim-0.2.0/src/drones_sim/dynamics/config.py +117 -0
  15. drones_sim-0.2.0/src/drones_sim/dynamics/disturbances.py +262 -0
  16. drones_sim-0.2.0/src/drones_sim/dynamics/quadcopter.py +317 -0
  17. drones_sim-0.2.0/src/drones_sim/estimation/__init__.py +2 -0
  18. drones_sim-0.2.0/src/drones_sim/estimation/ahrs.py +79 -0
  19. drones_sim-0.2.0/src/drones_sim/estimation/ekf.py +594 -0
  20. drones_sim-0.2.0/src/drones_sim/logging/__init__.py +13 -0
  21. drones_sim-0.2.0/src/drones_sim/logging/csv_logger.py +76 -0
  22. drones_sim-0.2.0/src/drones_sim/logging/json_logger.py +53 -0
  23. drones_sim-0.2.0/src/drones_sim/math_utils.py +119 -0
  24. drones_sim-0.2.0/src/drones_sim/models/__init__.py +21 -0
  25. drones_sim-0.2.0/src/drones_sim/models/quadcopter.urdf +296 -0
  26. drones_sim-0.2.0/src/drones_sim/models/urdf_loader.py +444 -0
  27. drones_sim-0.2.0/src/drones_sim/rl/__init__.py +16 -0
  28. drones_sim-0.2.0/src/drones_sim/rl/actions.py +219 -0
  29. drones_sim-0.2.0/src/drones_sim/rl/env.py +195 -0
  30. drones_sim-0.2.0/src/drones_sim/rl/observations.py +40 -0
  31. drones_sim-0.2.0/src/drones_sim/rl/reward.py +69 -0
  32. drones_sim-0.2.0/src/drones_sim/rl/tasks.py +73 -0
  33. drones_sim-0.2.0/src/drones_sim/sensors/__init__.py +3 -0
  34. drones_sim-0.2.0/src/drones_sim/sensors/gps.py +158 -0
  35. drones_sim-0.2.0/src/drones_sim/sensors/imu.py +196 -0
  36. drones_sim-0.2.0/src/drones_sim/sensors/models.py +113 -0
  37. drones_sim-0.2.0/src/drones_sim/simulation.py +283 -0
  38. drones_sim-0.2.0/src/drones_sim/state.py +133 -0
  39. drones_sim-0.2.0/src/drones_sim/trajectory.py +391 -0
  40. drones_sim-0.2.0/src/drones_sim/visualization/__init__.py +23 -0
  41. drones_sim-0.2.0/src/drones_sim/visualization/api.py +50 -0
  42. drones_sim-0.2.0/src/drones_sim/visualization/dashboard.py +74 -0
  43. drones_sim-0.2.0/src/drones_sim/visualization/plots.py +183 -0
  44. drones_sim-0.2.0/src/drones_sim/visualization/rerun_viewer.py +411 -0
  45. drones_sim-0.2.0/src/drones_sim/visualization/viewer.py +452 -0
  46. drones_sim-0.2.0/src/drones_sim.egg-info/PKG-INFO +323 -0
  47. drones_sim-0.2.0/src/drones_sim.egg-info/SOURCES.txt +64 -0
  48. drones_sim-0.2.0/src/drones_sim.egg-info/dependency_links.txt +1 -0
  49. drones_sim-0.2.0/src/drones_sim.egg-info/requires.txt +24 -0
  50. drones_sim-0.2.0/src/drones_sim.egg-info/top_level.txt +1 -0
  51. drones_sim-0.2.0/tests/test_cascaded.py +130 -0
  52. drones_sim-0.2.0/tests/test_disturbances.py +132 -0
  53. drones_sim-0.2.0/tests/test_dynamics.py +65 -0
  54. drones_sim-0.2.0/tests/test_dynamics_quaternion.py +169 -0
  55. drones_sim-0.2.0/tests/test_ekf.py +169 -0
  56. drones_sim-0.2.0/tests/test_gps.py +118 -0
  57. drones_sim-0.2.0/tests/test_logging.py +138 -0
  58. drones_sim-0.2.0/tests/test_lqr.py +61 -0
  59. drones_sim-0.2.0/tests/test_math_utils.py +58 -0
  60. drones_sim-0.2.0/tests/test_pid.py +34 -0
  61. drones_sim-0.2.0/tests/test_rerun_visualization.py +114 -0
  62. drones_sim-0.2.0/tests/test_reworked_architecture.py +102 -0
  63. drones_sim-0.2.0/tests/test_rl_env.py +135 -0
  64. drones_sim-0.2.0/tests/test_rl_training.py +102 -0
  65. drones_sim-0.2.0/tests/test_sensor_models.py +143 -0
  66. drones_sim-0.2.0/tests/test_trajectory.py +75 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 thanhndv212
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,323 @@
1
+ Metadata-Version: 2.4
2
+ Name: drones-sim
3
+ Version: 0.2.0
4
+ Summary: Composable quadcopter modeling, control, estimation, and visualization
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://github.com/thanhndv212/drones-sim
7
+ Project-URL: Documentation, https://github.com/thanhndv212/drones-sim#readme
8
+ Project-URL: Changelog, https://github.com/thanhndv212/drones-sim/blob/master/CHANGELOG.md
9
+ Project-URL: Issues, https://github.com/thanhndv212/drones-sim/issues
10
+ Project-URL: Source, https://github.com/thanhndv212/drones-sim
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: numpy>=1.24
15
+ Requires-Dist: scipy>=1.10
16
+ Requires-Dist: matplotlib>=3.7
17
+ Requires-Dist: rerun-sdk<1,>=0.27
18
+ Provides-Extra: dev
19
+ Requires-Dist: pytest>=7.0; extra == "dev"
20
+ Requires-Dist: ruff; extra == "dev"
21
+ Provides-Extra: viser
22
+ Requires-Dist: viser>=0.2; extra == "viser"
23
+ Provides-Extra: rl
24
+ Requires-Dist: torch>=2.2; extra == "rl"
25
+ Requires-Dist: stable-baselines3>=2.3; extra == "rl"
26
+ Requires-Dist: gymnasium>=0.29; extra == "rl"
27
+ Requires-Dist: tensorboard>=2.15; extra == "rl"
28
+ Requires-Dist: pyyaml>=6.0; extra == "rl"
29
+ Provides-Extra: rl-dev
30
+ Requires-Dist: drones-sim[rl]; extra == "rl-dev"
31
+ Requires-Dist: wandb; extra == "rl-dev"
32
+ Requires-Dist: optuna>=3.5; extra == "rl-dev"
33
+ Requires-Dist: moviepy; extra == "rl-dev"
34
+ Dynamic: license-file
35
+
36
+ # drones_sim
37
+
38
+ 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.
39
+
40
+ [![CI](https://github.com/thanhndv212/drones-sim/actions/workflows/ci.yml/badge.svg)](https://github.com/thanhndv212/drones-sim/actions/workflows/ci.yml)
41
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/thanhndv212/drones-sim)
42
+
43
+ ## Install
44
+
45
+ ```bash
46
+ cd drones_sim
47
+ pip install -e ".[dev]"
48
+ ```
49
+
50
+ RL extras (Gymnasium env, SB3 PPO, TensorBoard):
51
+
52
+ ```bash
53
+ pip install -e ".[rl]"
54
+ ```
55
+
56
+ Full RL dev stack (adds Weights & Biases, Optuna, moviepy):
57
+
58
+ ```bash
59
+ pip install -e ".[rl-dev]"
60
+ ```
61
+
62
+ Legacy Viser mission-control examples:
63
+
64
+ ```bash
65
+ pip install -e ".[viser]"
66
+ ```
67
+
68
+ ## Quick start
69
+
70
+ The high-level runner owns timing, sensing, estimation, control, logging, and aligned outputs:
71
+
72
+ ```python
73
+ from drones_sim import ClosedLoopSimulator, SimulationConfig, visualize
74
+ from drones_sim.trajectory import generate_circular
75
+
76
+ reference = generate_circular(duration=10.0, sample_rate=100, radius=2.0)
77
+ simulator = ClosedLoopSimulator(
78
+ config=SimulationConfig(dt=0.01, use_estimator=True, seed=7)
79
+ )
80
+ result = simulator.run(reference)
81
+
82
+ print(result.summary())
83
+ visualize(result) # Rerun is the default backend
84
+ ```
85
+
86
+ For custom experiments, compose `QuadcopterConfig`, `QuadcopterDynamics`,
87
+ `GeometricController`, `IMUSimulator`, `GPSSimulator`, and
88
+ `ExtendedKalmanFilter`, then inject them into `ClosedLoopSimulator`.
89
+
90
+ ### Working examples
91
+
92
+ | # | Script | Install | Description |
93
+ |---|--------|---------|-------------|
94
+ | 01 | `01_imu_ekf_basic.py` | Base | IMU simulation and 16-state EKF sensor fusion |
95
+ | 02 | `02_ekf_adaptive.py` | Base | Adaptive EKF with temperature-dependent sensor models |
96
+ | 03 | `03_waypoint_nav.py` | Base | Minimum-snap waypoint navigation with cascaded PID |
97
+ | 04 | `04_viser_viewer.py` | `[viser]` | Interactive Viser 3D playback |
98
+ | 05 | `05_full_pipeline.py` | `[viser]` | Dynamics, sensors, EKF, PID control, and interactive viewer |
99
+ | 06 | `06_trajectory_following.py` | `[viser]` | EKF-fused trajectory tracking with mission controls |
100
+ | 07 | `07_rl_hover.py` | `[rl]` | Train and evaluate a PPO hover policy |
101
+ | 08 | `08_rl_vs_pid.py` | `[rl]` | Compare a trained RL policy with cascaded PID |
102
+ | 09 | `09_unified_simulation.py` | Base | Typed end-to-end simulation and diagnostic dashboard |
103
+ | 10 | `10_rerun_viewer.py` | Base | Rerun 3D scene, telemetry, streaming, and `.rrd` export |
104
+
105
+ Run a base example directly:
106
+
107
+ ```bash
108
+ python examples/09_unified_simulation.py
109
+ ```
110
+
111
+ The default `visualize(result)` call opens Rerun. It can also stream to an
112
+ existing gRPC server or save a portable recording:
113
+
114
+ ```bash
115
+ python examples/10_rerun_viewer.py
116
+ python examples/10_rerun_viewer.py --save flight.rrd
117
+ rerun flight.rrd
118
+ ```
119
+
120
+ Matplotlib and Viser remain available explicitly:
121
+
122
+ ```python
123
+ visualize(result, backend="matplotlib", title="Flight report")
124
+ visualize(result, backend="viser", port=8080) # requires drones-sim[viser]
125
+ ```
126
+
127
+ ## Package structure
128
+
129
+ ```
130
+ src/drones_sim/
131
+ ├── state.py # Typed state, setpoint, and control contracts
132
+ ├── simulation.py # Reproducible closed-loop orchestration and results
133
+ ├── math_utils.py # Quaternion ops, rotation matrices, Euler helpers
134
+ ├── trajectory.py # Trajectory generators (hover-cruise, circular, waypoints, min-snap)
135
+ ├── models/
136
+ │ ├── urdf_loader.py # Pure-stdlib URDF parser (no external deps)
137
+ │ └── quadcopter.urdf # Bundled quadcopter model
138
+ ├── sensors/
139
+ │ ├── imu.py # 9-axis IMU simulator (accel, gyro, mag)
140
+ │ ├── gps.py # GNSS receiver simulator (position + velocity)
141
+ │ └── models.py # SensorNoiseModel (Gauss-Markov bias), TemperatureModel
142
+ ├── estimation/
143
+ │ ├── ekf.py # 16-state EKF + 9-state adaptive EKF + AHRS
144
+ │ └── ahrs.py # Complementary-filter AHRS
145
+ ├── dynamics/
146
+ │ ├── quadcopter.py # 13-state quaternion Newton-Euler rigid body
147
+ │ └── disturbances.py # Wind, gust, ground effect, motor failure, payload drop
148
+ ├── control/
149
+ │ ├── pid.py # Scalar PID with anti-windup
150
+ │ ├── cascaded.py # Position → Velocity → Attitude cascaded PID
151
+ │ ├── geometric.py # Nonlinear SE(3) trajectory controller
152
+ │ ├── allocation.py # Bounded weighted least-squares motor allocation
153
+ │ └── lqr.py # Full-state feedback LQR (CARE solution)
154
+ ├── rl/
155
+ │ ├── env.py # QuadcopterEnv (gymnasium.Env wrapper)
156
+ │ ├── actions.py # MotorSpeedAction, ThrustBodyRatesAction, VelocityLevelAction, LQRResidualAction
157
+ │ ├── observations.py # RelativeStateObs (17-D observation)
158
+ │ ├── tasks.py # HoverTask, WaypointTask, TrackingTask
159
+ │ └── reward.py # Weighted multi-term reward function
160
+ ├── logging/
161
+ │ ├── csv_logger.py # CSV telemetry logger
162
+ │ └── json_logger.py # JSON Lines telemetry logger
163
+ └── visualization/
164
+ ├── api.py # visualize(); Rerun is the default backend
165
+ ├── plots.py # Matplotlib multi-panel comparison plots
166
+ ├── dashboard.py # SimulationResult engineering dashboard
167
+ ├── rerun_viewer.py # Default synchronized 3D, telemetry, events, and replay
168
+ └── viewer.py # Optional Viser mission-control UI (`[viser]`)
169
+
170
+ training/
171
+ ├── train_ppo.py # PPO training entry point (YAML config, CPU default, W&B)
172
+ ├── eval_policy.py # Policy evaluation with success/crash metrics
173
+ ├── configs/
174
+ │ ├── ppo_hover.yaml # Config for thrust_rates / lqr_residual actions
175
+ │ └── ppo_hover_vel.yaml # Config for velocity-level action
176
+ └── checkpoints/ # Saved models and VecNormalize stats
177
+ ```
178
+
179
+ ## Features
180
+
181
+ ### Project status
182
+
183
+ | Area | Status |
184
+ |------|--------|
185
+ | Quaternion dynamics, bounded allocation, geometric/PID/LQR control | ✅ Implemented and tested |
186
+ | Sensor simulation, EKF/AHRS estimation, closed-loop orchestration | ✅ Implemented and tested |
187
+ | CI, disturbances, CSV/JSON telemetry, Rerun replay | ✅ Implemented and tested |
188
+ | Gymnasium environment, PPO training/evaluation, RL examples | ✅ Baseline implemented |
189
+ | ULog export and RL domain randomization/curriculum | 🟡 Partially implemented / planned |
190
+ | MPC, Monte Carlo evaluation, VIO, obstacle planning, swarms, SITL | ⬜ Planned |
191
+
192
+ See the [development roadmap](docs/development-roadmap.md) for acceptance criteria and remaining work.
193
+
194
+ ### State estimation
195
+
196
+ | Filter | States | Description |
197
+ |--------|--------|-------------|
198
+ | 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 |
199
+ | Adaptive EKF | 9-state | Position(3), velocity(3), accel bias(3). Innovation-window adaptive noise, Gauss-Markov bias |
200
+ | AHRS | Complementary filter | Fuses accel, gyro, mag with gyro bias learning |
201
+
202
+ ### Control
203
+
204
+ | Controller | Type | Description |
205
+ |------------|------|-------------|
206
+ | Geometric | Nonlinear SE(3) | Quaternion-safe trajectory tracking with velocity/acceleration feedforward and bounded allocation |
207
+ | Cascaded PID | 3-loop cascade | Position → Velocity → Attitude. 9 PID instances, motor-speed output |
208
+ | LQR | Full-state feedback | Linearized around hover, CARE solution, wrench → motor allocation |
209
+
210
+ ### Disturbances (6 types)
211
+
212
+ | Disturbance | Category | Description |
213
+ |-------------|----------|-------------|
214
+ | `ConstantWind` | Wind | Steady world-frame drag force |
215
+ | `StepWind` | Wind | Wind that switches on at a given time |
216
+ | `DrydenGust` | Wind | Continuous turbulence — Gauss-Markov process (MIL-F-8785C) |
217
+ | `MotorFailure` | Failure | Degraded rotor thrust coefficient |
218
+ | `PayloadDrop` | Failure | Instantaneous mass change |
219
+ | `GroundEffect` | Environment | Thrust augmentation near ground (Cheeseman & Bennett) |
220
+
221
+ ### Reinforcement learning
222
+
223
+ - **QuadcopterEnv** — Gymnasium `Env` compatible with SB3, CleanRL, Tianshou, RLlib
224
+ - **Four action parameterizations** — three levels of abstraction plus a residual:
225
+
226
+ | Action | Policy outputs | Stabilization |
227
+ |--------|---------------|---------------|
228
+ | `MotorSpeedAction` | Raw motor speeds (4× rad/s) | None (hardest) |
229
+ | `ThrustBodyRatesAction` | Thrust delta + body rates (ωx,ωy,ωz) | Rate → torque P-controller |
230
+ | `VelocityLevelAction` | World-frame velocity (vx,vy,vz) + yaw rate | Built-in cascaded P-controller (velocity → attitude → torque) |
231
+ | `LQRResidualAction` | Delta on LQR motor speeds (in [-1,1]) | Full-state LQR feedback (CARE solution) |
232
+
233
+ - **Three tasks**: hover, waypoint sequence, trajectory tracking
234
+ - **Weighted multi-term reward** (position, velocity, attitude, action smoothness, alive/crash)
235
+ - **PPO training** in `training/train_ppo.py` with YAML configs, TensorBoard logging, and optional W&B tracking
236
+ - **Policy evaluation** in `training/eval_policy.py` (RMSE, success rate, crash rate)
237
+
238
+ #### Training
239
+
240
+ The training script defaults to CPU for small MLP policies (GPU transfer overhead dominates):
241
+
242
+ ```bash
243
+ # LQR residual (recommended — 75%+ success rate at 500k steps)
244
+ python -m training.train_ppo \
245
+ --config training/configs/ppo_hover.yaml \
246
+ --timesteps 500000 \
247
+ --action-type lqr_residual
248
+
249
+ # Velocity-level (0% crash, 1.5m RMSE)
250
+ python -m training.train_ppo \
251
+ --config training/configs/ppo_hover_vel.yaml \
252
+ --timesteps 200000 \
253
+ --action-type velocity
254
+
255
+ # Thrust + body rates (legacy)
256
+ python -m training.train_ppo \
257
+ --config training/configs/ppo_hover.yaml \
258
+ --timesteps 200000 \
259
+ --action-type thrust_rates
260
+ ```
261
+
262
+ Track training with Weights & Biases:
263
+
264
+ ```bash
265
+ python -m training.train_ppo \
266
+ --config training/configs/ppo_hover.yaml \
267
+ --action-type lqr_residual \
268
+ --track --wandb-project drones-sim-ppo
269
+ ```
270
+
271
+ Open TensorBoard (logs are saved to `./tb/`):
272
+
273
+ ```bash
274
+ tensorboard --logdir tb/
275
+ ```
276
+
277
+ #### Evaluation
278
+
279
+ ```bash
280
+ # Evaluate a trained checkpoint
281
+ python -m training.eval_policy \
282
+ --path training/checkpoints/final.zip \
283
+ --episodes 20 \
284
+ --action-type lqr_residual
285
+
286
+ # Expected output:
287
+ # pos_rmse: 0.1370
288
+ # success_rate: 0.7500
289
+ # crash_rate: 0.0000
290
+ # mean_reward: 6390.6716
291
+ ```
292
+
293
+
294
+
295
+ ### Logging
296
+
297
+ | Logger | Format | Description |
298
+ |--------|--------|-------------|
299
+ | `CsvLogger` | CSV | Full state + motor speeds + estimate per row |
300
+ | `JsonLogger` | JSON Lines | Per-line JSON objects; machine-readable |
301
+
302
+ ## Tests
303
+
304
+ ```bash
305
+ pytest tests/ -v
306
+ ```
307
+
308
+ Release history is maintained in [CHANGELOG.md](CHANGELOG.md).
309
+
310
+ ## License
311
+
312
+ MIT — see [LICENSE](LICENSE).
313
+
314
+ ## Dependencies
315
+
316
+ | Dependency | Purpose |
317
+ |------------|---------|
318
+ | numpy, scipy | Numerical computation |
319
+ | matplotlib | 2D plotting |
320
+ | [Rerun](https://rerun.io/) | Default synchronized 3D telemetry, replay, and `.rrd` export |
321
+ | [viser](https://github.com/nerfstudio-project/viser) | Optional interactive mission controls (`[viser]`) |
322
+ | torch, stable-baselines3, gymnasium | RL training (`[rl]` extra) |
323
+ | tensorboard, pyyaml | RL logging & config (`[rl]` extra) |
@@ -0,0 +1,288 @@
1
+ # drones_sim
2
+
3
+ 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.
4
+
5
+ [![CI](https://github.com/thanhndv212/drones-sim/actions/workflows/ci.yml/badge.svg)](https://github.com/thanhndv212/drones-sim/actions/workflows/ci.yml)
6
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/thanhndv212/drones-sim)
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ cd drones_sim
12
+ pip install -e ".[dev]"
13
+ ```
14
+
15
+ RL extras (Gymnasium env, SB3 PPO, TensorBoard):
16
+
17
+ ```bash
18
+ pip install -e ".[rl]"
19
+ ```
20
+
21
+ Full RL dev stack (adds Weights & Biases, Optuna, moviepy):
22
+
23
+ ```bash
24
+ pip install -e ".[rl-dev]"
25
+ ```
26
+
27
+ Legacy Viser mission-control examples:
28
+
29
+ ```bash
30
+ pip install -e ".[viser]"
31
+ ```
32
+
33
+ ## Quick start
34
+
35
+ The high-level runner owns timing, sensing, estimation, control, logging, and aligned outputs:
36
+
37
+ ```python
38
+ from drones_sim import ClosedLoopSimulator, SimulationConfig, visualize
39
+ from drones_sim.trajectory import generate_circular
40
+
41
+ reference = generate_circular(duration=10.0, sample_rate=100, radius=2.0)
42
+ simulator = ClosedLoopSimulator(
43
+ config=SimulationConfig(dt=0.01, use_estimator=True, seed=7)
44
+ )
45
+ result = simulator.run(reference)
46
+
47
+ print(result.summary())
48
+ visualize(result) # Rerun is the default backend
49
+ ```
50
+
51
+ For custom experiments, compose `QuadcopterConfig`, `QuadcopterDynamics`,
52
+ `GeometricController`, `IMUSimulator`, `GPSSimulator`, and
53
+ `ExtendedKalmanFilter`, then inject them into `ClosedLoopSimulator`.
54
+
55
+ ### Working examples
56
+
57
+ | # | Script | Install | Description |
58
+ |---|--------|---------|-------------|
59
+ | 01 | `01_imu_ekf_basic.py` | Base | IMU simulation and 16-state EKF sensor fusion |
60
+ | 02 | `02_ekf_adaptive.py` | Base | Adaptive EKF with temperature-dependent sensor models |
61
+ | 03 | `03_waypoint_nav.py` | Base | Minimum-snap waypoint navigation with cascaded PID |
62
+ | 04 | `04_viser_viewer.py` | `[viser]` | Interactive Viser 3D playback |
63
+ | 05 | `05_full_pipeline.py` | `[viser]` | Dynamics, sensors, EKF, PID control, and interactive viewer |
64
+ | 06 | `06_trajectory_following.py` | `[viser]` | EKF-fused trajectory tracking with mission controls |
65
+ | 07 | `07_rl_hover.py` | `[rl]` | Train and evaluate a PPO hover policy |
66
+ | 08 | `08_rl_vs_pid.py` | `[rl]` | Compare a trained RL policy with cascaded PID |
67
+ | 09 | `09_unified_simulation.py` | Base | Typed end-to-end simulation and diagnostic dashboard |
68
+ | 10 | `10_rerun_viewer.py` | Base | Rerun 3D scene, telemetry, streaming, and `.rrd` export |
69
+
70
+ Run a base example directly:
71
+
72
+ ```bash
73
+ python examples/09_unified_simulation.py
74
+ ```
75
+
76
+ The default `visualize(result)` call opens Rerun. It can also stream to an
77
+ existing gRPC server or save a portable recording:
78
+
79
+ ```bash
80
+ python examples/10_rerun_viewer.py
81
+ python examples/10_rerun_viewer.py --save flight.rrd
82
+ rerun flight.rrd
83
+ ```
84
+
85
+ Matplotlib and Viser remain available explicitly:
86
+
87
+ ```python
88
+ visualize(result, backend="matplotlib", title="Flight report")
89
+ visualize(result, backend="viser", port=8080) # requires drones-sim[viser]
90
+ ```
91
+
92
+ ## Package structure
93
+
94
+ ```
95
+ src/drones_sim/
96
+ ├── state.py # Typed state, setpoint, and control contracts
97
+ ├── simulation.py # Reproducible closed-loop orchestration and results
98
+ ├── math_utils.py # Quaternion ops, rotation matrices, Euler helpers
99
+ ├── trajectory.py # Trajectory generators (hover-cruise, circular, waypoints, min-snap)
100
+ ├── models/
101
+ │ ├── urdf_loader.py # Pure-stdlib URDF parser (no external deps)
102
+ │ └── quadcopter.urdf # Bundled quadcopter model
103
+ ├── sensors/
104
+ │ ├── imu.py # 9-axis IMU simulator (accel, gyro, mag)
105
+ │ ├── gps.py # GNSS receiver simulator (position + velocity)
106
+ │ └── models.py # SensorNoiseModel (Gauss-Markov bias), TemperatureModel
107
+ ├── estimation/
108
+ │ ├── ekf.py # 16-state EKF + 9-state adaptive EKF + AHRS
109
+ │ └── ahrs.py # Complementary-filter AHRS
110
+ ├── dynamics/
111
+ │ ├── quadcopter.py # 13-state quaternion Newton-Euler rigid body
112
+ │ └── disturbances.py # Wind, gust, ground effect, motor failure, payload drop
113
+ ├── control/
114
+ │ ├── pid.py # Scalar PID with anti-windup
115
+ │ ├── cascaded.py # Position → Velocity → Attitude cascaded PID
116
+ │ ├── geometric.py # Nonlinear SE(3) trajectory controller
117
+ │ ├── allocation.py # Bounded weighted least-squares motor allocation
118
+ │ └── lqr.py # Full-state feedback LQR (CARE solution)
119
+ ├── rl/
120
+ │ ├── env.py # QuadcopterEnv (gymnasium.Env wrapper)
121
+ │ ├── actions.py # MotorSpeedAction, ThrustBodyRatesAction, VelocityLevelAction, LQRResidualAction
122
+ │ ├── observations.py # RelativeStateObs (17-D observation)
123
+ │ ├── tasks.py # HoverTask, WaypointTask, TrackingTask
124
+ │ └── reward.py # Weighted multi-term reward function
125
+ ├── logging/
126
+ │ ├── csv_logger.py # CSV telemetry logger
127
+ │ └── json_logger.py # JSON Lines telemetry logger
128
+ └── visualization/
129
+ ├── api.py # visualize(); Rerun is the default backend
130
+ ├── plots.py # Matplotlib multi-panel comparison plots
131
+ ├── dashboard.py # SimulationResult engineering dashboard
132
+ ├── rerun_viewer.py # Default synchronized 3D, telemetry, events, and replay
133
+ └── viewer.py # Optional Viser mission-control UI (`[viser]`)
134
+
135
+ training/
136
+ ├── train_ppo.py # PPO training entry point (YAML config, CPU default, W&B)
137
+ ├── eval_policy.py # Policy evaluation with success/crash metrics
138
+ ├── configs/
139
+ │ ├── ppo_hover.yaml # Config for thrust_rates / lqr_residual actions
140
+ │ └── ppo_hover_vel.yaml # Config for velocity-level action
141
+ └── checkpoints/ # Saved models and VecNormalize stats
142
+ ```
143
+
144
+ ## Features
145
+
146
+ ### Project status
147
+
148
+ | Area | Status |
149
+ |------|--------|
150
+ | Quaternion dynamics, bounded allocation, geometric/PID/LQR control | ✅ Implemented and tested |
151
+ | Sensor simulation, EKF/AHRS estimation, closed-loop orchestration | ✅ Implemented and tested |
152
+ | CI, disturbances, CSV/JSON telemetry, Rerun replay | ✅ Implemented and tested |
153
+ | Gymnasium environment, PPO training/evaluation, RL examples | ✅ Baseline implemented |
154
+ | ULog export and RL domain randomization/curriculum | 🟡 Partially implemented / planned |
155
+ | MPC, Monte Carlo evaluation, VIO, obstacle planning, swarms, SITL | ⬜ Planned |
156
+
157
+ See the [development roadmap](docs/development-roadmap.md) for acceptance criteria and remaining work.
158
+
159
+ ### State estimation
160
+
161
+ | Filter | States | Description |
162
+ |--------|--------|-------------|
163
+ | 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 |
164
+ | Adaptive EKF | 9-state | Position(3), velocity(3), accel bias(3). Innovation-window adaptive noise, Gauss-Markov bias |
165
+ | AHRS | Complementary filter | Fuses accel, gyro, mag with gyro bias learning |
166
+
167
+ ### Control
168
+
169
+ | Controller | Type | Description |
170
+ |------------|------|-------------|
171
+ | Geometric | Nonlinear SE(3) | Quaternion-safe trajectory tracking with velocity/acceleration feedforward and bounded allocation |
172
+ | Cascaded PID | 3-loop cascade | Position → Velocity → Attitude. 9 PID instances, motor-speed output |
173
+ | LQR | Full-state feedback | Linearized around hover, CARE solution, wrench → motor allocation |
174
+
175
+ ### Disturbances (6 types)
176
+
177
+ | Disturbance | Category | Description |
178
+ |-------------|----------|-------------|
179
+ | `ConstantWind` | Wind | Steady world-frame drag force |
180
+ | `StepWind` | Wind | Wind that switches on at a given time |
181
+ | `DrydenGust` | Wind | Continuous turbulence — Gauss-Markov process (MIL-F-8785C) |
182
+ | `MotorFailure` | Failure | Degraded rotor thrust coefficient |
183
+ | `PayloadDrop` | Failure | Instantaneous mass change |
184
+ | `GroundEffect` | Environment | Thrust augmentation near ground (Cheeseman & Bennett) |
185
+
186
+ ### Reinforcement learning
187
+
188
+ - **QuadcopterEnv** — Gymnasium `Env` compatible with SB3, CleanRL, Tianshou, RLlib
189
+ - **Four action parameterizations** — three levels of abstraction plus a residual:
190
+
191
+ | Action | Policy outputs | Stabilization |
192
+ |--------|---------------|---------------|
193
+ | `MotorSpeedAction` | Raw motor speeds (4× rad/s) | None (hardest) |
194
+ | `ThrustBodyRatesAction` | Thrust delta + body rates (ωx,ωy,ωz) | Rate → torque P-controller |
195
+ | `VelocityLevelAction` | World-frame velocity (vx,vy,vz) + yaw rate | Built-in cascaded P-controller (velocity → attitude → torque) |
196
+ | `LQRResidualAction` | Delta on LQR motor speeds (in [-1,1]) | Full-state LQR feedback (CARE solution) |
197
+
198
+ - **Three tasks**: hover, waypoint sequence, trajectory tracking
199
+ - **Weighted multi-term reward** (position, velocity, attitude, action smoothness, alive/crash)
200
+ - **PPO training** in `training/train_ppo.py` with YAML configs, TensorBoard logging, and optional W&B tracking
201
+ - **Policy evaluation** in `training/eval_policy.py` (RMSE, success rate, crash rate)
202
+
203
+ #### Training
204
+
205
+ The training script defaults to CPU for small MLP policies (GPU transfer overhead dominates):
206
+
207
+ ```bash
208
+ # LQR residual (recommended — 75%+ success rate at 500k steps)
209
+ python -m training.train_ppo \
210
+ --config training/configs/ppo_hover.yaml \
211
+ --timesteps 500000 \
212
+ --action-type lqr_residual
213
+
214
+ # Velocity-level (0% crash, 1.5m RMSE)
215
+ python -m training.train_ppo \
216
+ --config training/configs/ppo_hover_vel.yaml \
217
+ --timesteps 200000 \
218
+ --action-type velocity
219
+
220
+ # Thrust + body rates (legacy)
221
+ python -m training.train_ppo \
222
+ --config training/configs/ppo_hover.yaml \
223
+ --timesteps 200000 \
224
+ --action-type thrust_rates
225
+ ```
226
+
227
+ Track training with Weights & Biases:
228
+
229
+ ```bash
230
+ python -m training.train_ppo \
231
+ --config training/configs/ppo_hover.yaml \
232
+ --action-type lqr_residual \
233
+ --track --wandb-project drones-sim-ppo
234
+ ```
235
+
236
+ Open TensorBoard (logs are saved to `./tb/`):
237
+
238
+ ```bash
239
+ tensorboard --logdir tb/
240
+ ```
241
+
242
+ #### Evaluation
243
+
244
+ ```bash
245
+ # Evaluate a trained checkpoint
246
+ python -m training.eval_policy \
247
+ --path training/checkpoints/final.zip \
248
+ --episodes 20 \
249
+ --action-type lqr_residual
250
+
251
+ # Expected output:
252
+ # pos_rmse: 0.1370
253
+ # success_rate: 0.7500
254
+ # crash_rate: 0.0000
255
+ # mean_reward: 6390.6716
256
+ ```
257
+
258
+
259
+
260
+ ### Logging
261
+
262
+ | Logger | Format | Description |
263
+ |--------|--------|-------------|
264
+ | `CsvLogger` | CSV | Full state + motor speeds + estimate per row |
265
+ | `JsonLogger` | JSON Lines | Per-line JSON objects; machine-readable |
266
+
267
+ ## Tests
268
+
269
+ ```bash
270
+ pytest tests/ -v
271
+ ```
272
+
273
+ Release history is maintained in [CHANGELOG.md](CHANGELOG.md).
274
+
275
+ ## License
276
+
277
+ MIT — see [LICENSE](LICENSE).
278
+
279
+ ## Dependencies
280
+
281
+ | Dependency | Purpose |
282
+ |------------|---------|
283
+ | numpy, scipy | Numerical computation |
284
+ | matplotlib | 2D plotting |
285
+ | [Rerun](https://rerun.io/) | Default synchronized 3D telemetry, replay, and `.rrd` export |
286
+ | [viser](https://github.com/nerfstudio-project/viser) | Optional interactive mission controls (`[viser]`) |
287
+ | torch, stable-baselines3, gymnasium | RL training (`[rl]` extra) |
288
+ | tensorboard, pyyaml | RL logging & config (`[rl]` extra) |
@@ -0,0 +1,52 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "drones-sim"
7
+ version = "0.2.0"
8
+ description = "Composable quadcopter modeling, control, estimation, and visualization"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.10"
13
+ dependencies = [
14
+ "numpy>=1.24",
15
+ "scipy>=1.10",
16
+ "matplotlib>=3.7",
17
+ "rerun-sdk>=0.27,<1",
18
+ ]
19
+
20
+ [project.optional-dependencies]
21
+ dev = ["pytest>=7.0", "ruff"]
22
+ viser = ["viser>=0.2"]
23
+ rl = ["torch>=2.2", "stable-baselines3>=2.3", "gymnasium>=0.29", "tensorboard>=2.15", "pyyaml>=6.0"]
24
+ rl-dev = ["drones-sim[rl]", "wandb", "optuna>=3.5", "moviepy"]
25
+
26
+ [project.urls]
27
+ Homepage = "https://github.com/thanhndv212/drones-sim"
28
+ Documentation = "https://github.com/thanhndv212/drones-sim#readme"
29
+ Changelog = "https://github.com/thanhndv212/drones-sim/blob/master/CHANGELOG.md"
30
+ Issues = "https://github.com/thanhndv212/drones-sim/issues"
31
+ Source = "https://github.com/thanhndv212/drones-sim"
32
+
33
+ [tool.setuptools.packages.find]
34
+ where = ["src"]
35
+
36
+ [tool.ruff]
37
+ line-length = 100
38
+ target-version = "py310"
39
+ src = ["src", "tests", "examples"]
40
+ extend-exclude = [".venv"]
41
+
42
+ [tool.ruff.lint]
43
+ select = ["E", "F", "W", "I", "UP"]
44
+ ignore = ["E501"] # long lines — not worth a mass reformat
45
+
46
+ [tool.pytest.ini_options]
47
+ testpaths = ["tests"]
48
+ addopts = "-q"
49
+ markers = ["slow: marks tests as slow (deselect with '-m \"not slow\"')"]
50
+
51
+ [tool.setuptools.package-data]
52
+ "drones_sim.models" = ["*.urdf"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+