quadcopter-sim 0.1.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.
- quadcopter_sim-0.1.0/LICENSE +21 -0
- quadcopter_sim-0.1.0/PKG-INFO +589 -0
- quadcopter_sim-0.1.0/README.md +542 -0
- quadcopter_sim-0.1.0/pyproject.toml +84 -0
- quadcopter_sim-0.1.0/quadcopter/__init__.py +77 -0
- quadcopter_sim-0.1.0/quadcopter/__main__.py +332 -0
- quadcopter_sim-0.1.0/quadcopter/controllers.py +295 -0
- quadcopter_sim-0.1.0/quadcopter/dynamics.py +174 -0
- quadcopter_sim-0.1.0/quadcopter/env.py +119 -0
- quadcopter_sim-0.1.0/quadcopter/evaluation.py +419 -0
- quadcopter_sim-0.1.0/quadcopter/gym_env.py +145 -0
- quadcopter_sim-0.1.0/quadcopter/logging.py +717 -0
- quadcopter_sim-0.1.0/quadcopter/plotting.py +393 -0
- quadcopter_sim-0.1.0/quadcopter/simulation.py +202 -0
- quadcopter_sim-0.1.0/quadcopter/utils.py +152 -0
- quadcopter_sim-0.1.0/quadcopter_sim.egg-info/PKG-INFO +589 -0
- quadcopter_sim-0.1.0/quadcopter_sim.egg-info/SOURCES.txt +33 -0
- quadcopter_sim-0.1.0/quadcopter_sim.egg-info/dependency_links.txt +1 -0
- quadcopter_sim-0.1.0/quadcopter_sim.egg-info/entry_points.txt +2 -0
- quadcopter_sim-0.1.0/quadcopter_sim.egg-info/requires.txt +31 -0
- quadcopter_sim-0.1.0/quadcopter_sim.egg-info/top_level.txt +1 -0
- quadcopter_sim-0.1.0/setup.cfg +4 -0
- quadcopter_sim-0.1.0/test/test_academic_evaluation.py +100 -0
- quadcopter_sim-0.1.0/test/test_cli.py +86 -0
- quadcopter_sim-0.1.0/test/test_controllers.py +156 -0
- quadcopter_sim-0.1.0/test/test_dynamics.py +33 -0
- quadcopter_sim-0.1.0/test/test_enhanced_plotting.py +88 -0
- quadcopter_sim-0.1.0/test/test_gym_env.py +52 -0
- quadcopter_sim-0.1.0/test/test_hover_balance.py +15 -0
- quadcopter_sim-0.1.0/test/test_logging.py +109 -0
- quadcopter_sim-0.1.0/test/test_plotting.py +30 -0
- quadcopter_sim-0.1.0/test/test_public_api.py +22 -0
- quadcopter_sim-0.1.0/test/test_real_time_env.py +45 -0
- quadcopter_sim-0.1.0/test/test_simulation.py +7 -0
- quadcopter_sim-0.1.0/test/test_utils.py +119 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 Ardy Seto
|
|
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,589 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: quadcopter-sim
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Light‑weight quadcopter dynamics, PID control and visualisation in pure Python.
|
|
5
|
+
Author-email: 2black0 <2black0@gmail.com>
|
|
6
|
+
Maintainer-email: 2black0 <2black0@gmail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Keywords: quadcopter,simulation,control,PID,education
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Education
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
18
|
+
Classifier: Topic :: Education
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: numpy>=1.25
|
|
23
|
+
Requires-Dist: scipy>=1.11
|
|
24
|
+
Requires-Dist: matplotlib>=3.8
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=8.2; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
28
|
+
Requires-Dist: mypy; extra == "dev"
|
|
29
|
+
Requires-Dist: ruff; extra == "dev"
|
|
30
|
+
Requires-Dist: black; extra == "dev"
|
|
31
|
+
Provides-Extra: docs
|
|
32
|
+
Requires-Dist: sphinx; extra == "docs"
|
|
33
|
+
Requires-Dist: sphinx-rtd-theme; extra == "docs"
|
|
34
|
+
Provides-Extra: rl
|
|
35
|
+
Requires-Dist: gymnasium>=0.28; extra == "rl"
|
|
36
|
+
Provides-Extra: control
|
|
37
|
+
Requires-Dist: scipy>=1.11; extra == "control"
|
|
38
|
+
Provides-Extra: fuzzy
|
|
39
|
+
Requires-Dist: scikit-fuzzy; extra == "fuzzy"
|
|
40
|
+
Provides-Extra: data
|
|
41
|
+
Requires-Dist: scipy>=1.11; extra == "data"
|
|
42
|
+
Provides-Extra: all
|
|
43
|
+
Requires-Dist: gymnasium>=0.28; extra == "all"
|
|
44
|
+
Requires-Dist: scikit-fuzzy; extra == "all"
|
|
45
|
+
Requires-Dist: scipy>=1.11; extra == "all"
|
|
46
|
+
Dynamic: license-file
|
|
47
|
+
|
|
48
|
+
# Quadcopter‑Sim
|
|
49
|
+
|
|
50
|
+
Light‑weight, strictly‑typed Python toolkit for **6‑DoF quadrotor simulation**, 3‑D plotting and step‑wise control loops — perfect for control‑systems classes, flight‑code prototyping or RL research.
|
|
51
|
+
|
|
52
|
+
[](https://github.com/2black0/quadcopter-sim-python/actions)
|
|
53
|
+
[](https://pypi.org/project/quadcopter-sim)
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Installation
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# latest release
|
|
61
|
+
pip install quadcopter-sim
|
|
62
|
+
|
|
63
|
+
# dev install with all optional dependencies
|
|
64
|
+
git clone https://github.com/2black0/quadcopter-sim-python
|
|
65
|
+
cd quadcopter-sim-python
|
|
66
|
+
pip install -e .[all] # includes RL, control, and data analysis dependencies
|
|
67
|
+
|
|
68
|
+
# install specific optional dependencies
|
|
69
|
+
pip install -e .[rl] # Gymnasium for RL
|
|
70
|
+
pip install -e .[control] # SciPy for advanced control
|
|
71
|
+
pip install -e .[data] # SciPy for data export
|
|
72
|
+
pip install -e .[dev] # Development tools
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Comprehensive CLI
|
|
78
|
+
|
|
79
|
+
The package provides a comprehensive command-line interface for simulation, control, and analysis:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Basic hover simulation
|
|
83
|
+
python -m quadcopter --plot # 4 s hover + 3‑D figure
|
|
84
|
+
python -m quadcopter --duration 6 --csv run.csv --quiet
|
|
85
|
+
|
|
86
|
+
# PID position control
|
|
87
|
+
python -m quadcopter --controller pid --target-pos 1 1 2 --duration 10 --plot
|
|
88
|
+
|
|
89
|
+
# LQR control with custom parameters
|
|
90
|
+
python -m quadcopter --controller lqr --duration 5 --plot
|
|
91
|
+
|
|
92
|
+
# Academic analysis and logging
|
|
93
|
+
python -m quadcopter --controller pid --target-pos 1 1 2 --duration 10 --academic-log results
|
|
94
|
+
|
|
95
|
+
# Advanced PID tuning
|
|
96
|
+
python -m quadcopter --controller pid --target-pos 1 0 1 --duration 5
|
|
97
|
+
--pid-kp 3 3 5 --pid-ki 0.2 0.2 0.3 --pid-kd 0.6 0.6 1.2
|
|
98
|
+
--plot
|
|
99
|
+
|
|
100
|
+
# Custom initial conditions
|
|
101
|
+
python -m quadcopter --controller pid --target-pos 0 0 2 --duration 5
|
|
102
|
+
--init-pos 0 0 1 --init-vel 0 0 0.5
|
|
103
|
+
--csv trajectory.csv --json log.json --matlab data.mat
|
|
104
|
+
|
|
105
|
+
# Enhanced plotting options
|
|
106
|
+
python -m quadcopter --controller pid --target-pos 1 1 2 --duration 10 --plot-errors
|
|
107
|
+
python -m quadcopter --controller pid --target-pos 1 1 2 --duration 10 --plot-comparison
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### CLI Options
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
usage: python -m quadcopter [-h] [--duration DURATION] [--dt DT]
|
|
114
|
+
[--method {rk45,rk4}] [--rtol RTOL] [--atol ATOL]
|
|
115
|
+
[--controller {hover,pid,lqr}]
|
|
116
|
+
[--pid-kp PID_KP PID_KP PID_KP]
|
|
117
|
+
[--pid-ki PID_KI PID_KI PID_KI]
|
|
118
|
+
[--pid-kd PID_KD PID_KD PID_KD]
|
|
119
|
+
[--target-pos TARGET_POS TARGET_POS TARGET_POS]
|
|
120
|
+
[--plot] [--csv CSV] [--json JSON]
|
|
121
|
+
[--matlab MATLAB] [--academic-log ACADEMIC_LOG]
|
|
122
|
+
[--controller-type {pid,lqr,rl}]
|
|
123
|
+
[--init-pos INIT_POS INIT_POS INIT_POS]
|
|
124
|
+
[--init-vel INIT_VEL INIT_VEL INIT_VEL] [--quiet]
|
|
125
|
+
[--verbose]
|
|
126
|
+
|
|
127
|
+
Comprehensive quadcopter simulation and analysis tool.
|
|
128
|
+
|
|
129
|
+
options:
|
|
130
|
+
-h, --help show this help message and exit
|
|
131
|
+
--duration DURATION simulation time [s]
|
|
132
|
+
--dt DT integration step [s]
|
|
133
|
+
--method {rk45,rk4} integration method (adaptive RK45 or fixed‑step RK4)
|
|
134
|
+
--rtol RTOL solver rtol
|
|
135
|
+
--atol ATOL solver atol
|
|
136
|
+
--controller {hover,pid,lqr}
|
|
137
|
+
controller type to use
|
|
138
|
+
--pid-kp PID_KP PID_KP PID_KP
|
|
139
|
+
PID Kp gains for x, y, z axes
|
|
140
|
+
--pid-ki PID_KI PID_KI PID_KI
|
|
141
|
+
PID Ki gains for x, y, z axes
|
|
142
|
+
--pid-kd PID_KD PID_KD PID_KD
|
|
143
|
+
PID Kd gains for x, y, z axes
|
|
144
|
+
--target-pos TARGET_POS TARGET_POS TARGET_POS
|
|
145
|
+
target position [x, y, z] for position controller
|
|
146
|
+
--plot show matplotlib figure
|
|
147
|
+
--csv CSV save (t, state, control) to CSV
|
|
148
|
+
--json JSON save simulation log to JSON
|
|
149
|
+
--matlab MATLAB save simulation log to MATLAB .mat file
|
|
150
|
+
--academic-log ACADEMIC_LOG
|
|
151
|
+
enable academic logging and save to directory
|
|
152
|
+
--controller-type {pid,lqr,rl}
|
|
153
|
+
controller type for academic logging
|
|
154
|
+
--init-pos INIT_POS INIT_POS INIT_POS
|
|
155
|
+
initial position [x, y, z]
|
|
156
|
+
--init-vel INIT_VEL INIT_VEL INIT_VEL
|
|
157
|
+
initial velocity [vx, vy, vz]
|
|
158
|
+
--quiet suppress info output
|
|
159
|
+
--verbose enable verbose output
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Enhanced Features
|
|
165
|
+
|
|
166
|
+
### Advanced Control Systems
|
|
167
|
+
The library now includes comprehensive control system implementations:
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
from quadcopter.controllers import PIDController, PositionController, LQRController
|
|
171
|
+
|
|
172
|
+
# PID Position Control
|
|
173
|
+
position_ctrl = PositionController(
|
|
174
|
+
x_pid=PIDController(kp=2.0, ki=0.1, kd=0.5),
|
|
175
|
+
y_pid=PIDController(kp=2.0, ki=0.1, kd=0.5),
|
|
176
|
+
z_pid=PIDController(kp=4.0, ki=0.2, kd=1.0),
|
|
177
|
+
target_pos=np.array([1.0, -1.0, 2.0])
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# LQR Control
|
|
181
|
+
A = np.eye(12) # State matrix
|
|
182
|
+
B = np.eye(12, 4) # Input matrix
|
|
183
|
+
lqr_ctrl = LQRController(A=A, B=B, Q=np.eye(12), R=np.eye(4))
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Reinforcement Learning Integration
|
|
187
|
+
Gymnasium-compatible environment for RL research:
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
from quadcopter.gym_env import QuadcopterGymEnv
|
|
191
|
+
|
|
192
|
+
env = QuadcopterGymEnv()
|
|
193
|
+
obs, info = env.reset()
|
|
194
|
+
action = env.action_space.sample() # Random action
|
|
195
|
+
obs, reward, terminated, truncated, info = env.step(action)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Real-time Simulation
|
|
199
|
+
Enhanced environment with real-time capabilities:
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
from quadcopter.env import RealTimeQuadcopterEnv
|
|
203
|
+
|
|
204
|
+
# Run simulation at half real-time speed
|
|
205
|
+
env = RealTimeQuadcopterEnv(dt=0.02, real_time_factor=0.5)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### 5. Comprehensive Logging
|
|
209
|
+
Advanced logging with multiple export formats:
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
from quadcopter.logging import simulate_with_logging
|
|
213
|
+
|
|
214
|
+
log = simulate_with_logging(duration=5.0, dt=0.02, controller=my_controller)
|
|
215
|
+
log.save_csv("simulation.csv") # CSV for analysis
|
|
216
|
+
log.save_json("simulation.json") # JSON for structured data
|
|
217
|
+
log.save_matlab("simulation.mat") # MATLAB for advanced analysis
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### 6. Academic Evaluation and Visualization
|
|
221
|
+
Comprehensive academic evaluation tools for research publications:
|
|
222
|
+
|
|
223
|
+
```python
|
|
224
|
+
from quadcopter.logging import simulate_with_academic_logging
|
|
225
|
+
from quadcopter.evaluation import AcademicEvaluator
|
|
226
|
+
|
|
227
|
+
# Run simulation with academic logging
|
|
228
|
+
log = simulate_with_academic_logging(
|
|
229
|
+
duration=10.0,
|
|
230
|
+
dt=0.02,
|
|
231
|
+
controller=my_controller,
|
|
232
|
+
ref_position=np.array([1.0, -1.0, 2.0]),
|
|
233
|
+
controller_type="pid"
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
# Create academic evaluator
|
|
237
|
+
evaluator = AcademicEvaluator(log)
|
|
238
|
+
|
|
239
|
+
# Generate comprehensive analysis
|
|
240
|
+
metrics = evaluator.generate_comprehensive_analysis("results")
|
|
241
|
+
|
|
242
|
+
# Generate specific plots
|
|
243
|
+
evaluator.plot_3d_trajectory("trajectory.png")
|
|
244
|
+
evaluator.plot_state_tracking("tracking.png")
|
|
245
|
+
evaluator.plot_error_analysis("errors.png")
|
|
246
|
+
evaluator.plot_control_effort("control.png")
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Enhanced Visualization
|
|
250
|
+
Comprehensive plotting capabilities:
|
|
251
|
+
|
|
252
|
+
```python
|
|
253
|
+
from quadcopter.plotting import (
|
|
254
|
+
plot_trajectory,
|
|
255
|
+
plot_control_errors,
|
|
256
|
+
plot_3d_trajectory_comparison,
|
|
257
|
+
plot_frequency_analysis
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
# Control error analysis
|
|
261
|
+
plot_control_errors(t, states, targets)
|
|
262
|
+
|
|
263
|
+
# Trajectory comparison
|
|
264
|
+
plot_3d_trajectory_comparison([
|
|
265
|
+
(states1, "Controller A"),
|
|
266
|
+
(states2, "Controller B")
|
|
267
|
+
])
|
|
268
|
+
|
|
269
|
+
# Frequency domain analysis
|
|
270
|
+
plot_frequency_analysis(t, signals, ["X Position", "Y Position", "Z Position"])
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## API at a glance
|
|
276
|
+
|
|
277
|
+
| Function / class | Purpose | Key arguments |
|
|
278
|
+
| -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
|
|
279
|
+
| **`quadcopter.simulation.simulate`** | One‑shot trajectory generator (adaptive RK45 or fixed‑step RK4). Accepts **either** a controller object with `.update(t,state)` **or** a plain function `(t,state)→motor_ω`. | `duration`, `dt`, `controller`, `method` |
|
|
280
|
+
| **`quadcopter.env.QuadcopterEnv`** | Real‑time, fixed‑step RK4 environment – one `reset()`, then `step(motor_omega)`; ideal for PID / MPC / RL loops. | `dt`, `reset()`, `step()` |
|
|
281
|
+
| **`quadcopter.env.RealTimeQuadcopterEnv`** | Real-time environment with timing control and synchronization. | `dt`, `real_time_factor`, `reset()`, `step()` |
|
|
282
|
+
| **`quadcopter.gym_env.QuadcopterGymEnv`** | Gymnasium-compatible environment for RL training. | `dt`, `max_steps` |
|
|
283
|
+
| **`quadcopter.dynamics.Params`** | Physical constants (mass, arm length, thrust factor …). | edit attributes to match your air‑frame |
|
|
284
|
+
| **`quadcopter.dynamics.QuadState`** | Minimal dataclass for the 13‑dim state. | `.from_vector(vec)` / `.as_vector()` |
|
|
285
|
+
| **`quadcopter.controllers.PIDController`** | PID controller with anti-windup and output limits. | `kp`, `ki`, `kd`, `max_output` |
|
|
286
|
+
| **`quadcopter.controllers.PositionController`** | 3D position controller using PID for each axis. | `x_pid`, `y_pid`, `z_pid`, `target_pos` |
|
|
287
|
+
| **`quadcopter.controllers.LQRController`** | Linear Quadratic Regulator controller. | `A`, `B`, `Q`, `R` matrices |
|
|
288
|
+
| **`quadcopter.logging.SimulationLog`** | Comprehensive logging with multiple export formats. | `save_csv()`, `save_json()`, `save_matlab()` |
|
|
289
|
+
| **`quadcopter.logging.AcademicLog`** | Academic-grade logging for research publications with comprehensive data capture. | `add_entry()`, `save_csv()`, `save_json()`, `save_matlab()` |
|
|
290
|
+
| **`quadcopter.logging.simulate_with_academic_logging`** | Simulation with academic-grade logging. | `duration`, `dt`, `controller`, `ref_position` |
|
|
291
|
+
| **`quadcopter.evaluation.AcademicEvaluator`** | Academic evaluation tools for performance analysis and visualization. | `plot_3d_trajectory()`, `plot_state_tracking()`, `generate_performance_report()` |
|
|
292
|
+
| **`quadcopter.plotting.plot_trajectory`** | Static 3‑D + time‑series figure. | `t, states, controls` |
|
|
293
|
+
| **`quadcopter.plotting.plot_control_errors`** | Control error analysis over time. | `t, states, targets` |
|
|
294
|
+
| **`quadcopter.plotting.plot_3d_trajectory_comparison`** | Compare multiple trajectories in 3D. | `trajectories` |
|
|
295
|
+
| **`quadcopter.plotting.plot_frequency_analysis`** | Frequency domain analysis of signals. | `t, signals, signal_names` |
|
|
296
|
+
| **`quadcopter.plotting.animate_trajectory`** | Matplotlib animation (MP4 / Jupyter). | `t, states`, `fps`, `save_path` |
|
|
297
|
+
| **`quadcopter.utils.create_pid_position_controller`** | Create PID position controller with default or custom gains. | `target_pos`, `kp`, `ki`, `kd` |
|
|
298
|
+
| **`quadcopter.utils.create_pid_attitude_controller`** | Create PID attitude controller with default or custom gains. | `target_attitude`, `kp`, `ki`, `kd` |
|
|
299
|
+
| **`quadcopter.utils.create_lqr_controller`** | Create LQR controller with default matrices. | `params`, `Q`, `R` |
|
|
300
|
+
| **`quadcopter.utils.create_hover_controller`** | Create simple hover controller. | `params` |
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
### Minimal one‑liner
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
import numpy as np
|
|
308
|
+
from quadcopter.simulation import simulate, Params
|
|
309
|
+
from quadcopter.plotting import plot_trajectory
|
|
310
|
+
|
|
311
|
+
p = Params()
|
|
312
|
+
hover_speed = np.sqrt(p.m * p.g / (4 * p.b)) # rad/s
|
|
313
|
+
|
|
314
|
+
t, s, u = simulate(
|
|
315
|
+
4.0, 0.02,
|
|
316
|
+
controller=lambda *_: np.full(4, hover_speed),
|
|
317
|
+
method="rk4",
|
|
318
|
+
)
|
|
319
|
+
plot_trajectory(t, s, u)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Simplified PID Position Control Example
|
|
323
|
+
|
|
324
|
+
```python
|
|
325
|
+
from quadcopter import simulate, create_pid_position_controller
|
|
326
|
+
from quadcopter.dynamics import QuadState
|
|
327
|
+
from quadcopter.plotting import plot_trajectory
|
|
328
|
+
import numpy as np
|
|
329
|
+
|
|
330
|
+
# Create position controller using utility function
|
|
331
|
+
controller = create_pid_position_controller(
|
|
332
|
+
target_pos=[1.0, -1.0, 2.0],
|
|
333
|
+
kp=(2.0, 2.0, 4.0),
|
|
334
|
+
ki=(0.1, 0.1, 0.2),
|
|
335
|
+
kd=(0.5, 0.5, 1.0)
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
# Set up initial state
|
|
339
|
+
initial_state = QuadState(
|
|
340
|
+
pos=np.array([0.0, 0.0, 0.0]),
|
|
341
|
+
vel=np.array([0.0, 0.0, 0.0]),
|
|
342
|
+
quat=np.array([1.0, 0.0, 0.0, 0.0]),
|
|
343
|
+
ang_vel=np.array([0.0, 0.0, 0.0])
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
# Run simulation
|
|
347
|
+
t, states, controls = simulate(
|
|
348
|
+
duration=10.0,
|
|
349
|
+
dt=0.02,
|
|
350
|
+
controller=controller,
|
|
351
|
+
initial_state=initial_state,
|
|
352
|
+
method="rk4"
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
# Plot results
|
|
356
|
+
plot_trajectory(t, states, controls)
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### PID Position Control Example
|
|
360
|
+
|
|
361
|
+
```python
|
|
362
|
+
from quadcopter import simulate, PositionController
|
|
363
|
+
from quadcopter.dynamics import QuadState
|
|
364
|
+
from quadcopter.plotting import plot_trajectory
|
|
365
|
+
import numpy as np
|
|
366
|
+
|
|
367
|
+
# Create position controller
|
|
368
|
+
controller = PositionController(
|
|
369
|
+
x_pid=PIDController(kp=2.0, ki=0.1, kd=0.5),
|
|
370
|
+
y_pid=PIDController(kp=2.0, ki=0.1, kd=0.5),
|
|
371
|
+
z_pid=PIDController(kp=4.0, ki=0.2, kd=1.0),
|
|
372
|
+
target_pos=np.array([1.0, -1.0, 2.0])
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
# Set up initial state
|
|
376
|
+
initial_state = QuadState(
|
|
377
|
+
pos=np.array([0.0, 0.0, 0.0]),
|
|
378
|
+
vel=np.array([0.0, 0.0, 0.0]),
|
|
379
|
+
quat=np.array([1.0, 0.0, 0.0, 0.0]),
|
|
380
|
+
ang_vel=np.array([0.0, 0.0, 0.0])
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
# Run simulation
|
|
384
|
+
t, states, controls = simulate(
|
|
385
|
+
duration=10.0,
|
|
386
|
+
dt=0.02,
|
|
387
|
+
controller=controller,
|
|
388
|
+
initial_state=initial_state,
|
|
389
|
+
method="rk4"
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
# Plot results
|
|
393
|
+
plot_trajectory(t, states, controls)
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Reinforcement Learning Example
|
|
397
|
+
|
|
398
|
+
```python
|
|
399
|
+
from quadcopter.gym_env import QuadcopterGymEnv
|
|
400
|
+
import numpy as np
|
|
401
|
+
|
|
402
|
+
# Create RL environment
|
|
403
|
+
env = QuadcopterGymEnv()
|
|
404
|
+
|
|
405
|
+
# Simple policy
|
|
406
|
+
def simple_policy(observation):
|
|
407
|
+
# Simple hover policy
|
|
408
|
+
hover_speed = np.sqrt(0.65 * 9.81 / (4 * 3.25e-5))
|
|
409
|
+
return np.full(4, hover_speed)
|
|
410
|
+
|
|
411
|
+
# Training loop
|
|
412
|
+
obs, info = env.reset()
|
|
413
|
+
for _ in range(1000):
|
|
414
|
+
action = simple_policy(obs)
|
|
415
|
+
obs, reward, terminated, truncated, info = env.step(action)
|
|
416
|
+
if terminated or truncated:
|
|
417
|
+
obs, info = env.reset()
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### Real-time Simulation Example
|
|
421
|
+
|
|
422
|
+
```python
|
|
423
|
+
from quadcopter.env import RealTimeQuadcopterEnv
|
|
424
|
+
import numpy as np
|
|
425
|
+
|
|
426
|
+
# Create real-time environment (half speed)
|
|
427
|
+
env = RealTimeQuadcopterEnv(dt=0.02, real_time_factor=0.5)
|
|
428
|
+
obs = env.reset()
|
|
429
|
+
|
|
430
|
+
# Simple hover controller
|
|
431
|
+
hover_speed = np.sqrt(0.65 * 9.81 / (4 * 3.25e-5))
|
|
432
|
+
motor_speeds = np.full(4, hover_speed)
|
|
433
|
+
|
|
434
|
+
# Run simulation
|
|
435
|
+
for _ in range(200): # 4 seconds
|
|
436
|
+
obs = env.step(motor_speeds)
|
|
437
|
+
print(f"t={obs['t'][0]:.2f}s, pos={obs['pos']}")
|
|
438
|
+
|
|
439
|
+
print("Simulation completed!")
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### Comprehensive Logging Example
|
|
443
|
+
|
|
444
|
+
```python
|
|
445
|
+
from quadcopter.logging import simulate_with_logging
|
|
446
|
+
from quadcopter.controllers import PositionController, PIDController
|
|
447
|
+
import numpy as np
|
|
448
|
+
|
|
449
|
+
# Create controller
|
|
450
|
+
controller = PositionController(
|
|
451
|
+
x_pid=PIDController(kp=2.0, ki=0.1, kd=0.5),
|
|
452
|
+
y_pid=PIDController(kp=2.0, ki=0.1, kd=0.5),
|
|
453
|
+
z_pid=PIDController(kp=4.0, ki=0.2, kd=1.0),
|
|
454
|
+
target_pos=np.array([1.0, -1.0, 2.0])
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
# Run simulation with logging
|
|
458
|
+
log = simulate_with_logging(
|
|
459
|
+
duration=5.0,
|
|
460
|
+
dt=0.02,
|
|
461
|
+
controller=controller,
|
|
462
|
+
method="rk4"
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
# Export data in multiple formats
|
|
466
|
+
log.save_csv("trajectory_data.csv")
|
|
467
|
+
log.save_json("trajectory_data.json")
|
|
468
|
+
log.save_matlab("trajectory_data.mat")
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
### Academic Evaluation Example
|
|
472
|
+
|
|
473
|
+
```python
|
|
474
|
+
from quadcopter.logging import simulate_with_academic_logging
|
|
475
|
+
from quadcopter.evaluation import AcademicEvaluator
|
|
476
|
+
from quadcopter.controllers import PositionController, PIDController
|
|
477
|
+
from quadcopter.dynamics import QuadState
|
|
478
|
+
import numpy as np
|
|
479
|
+
|
|
480
|
+
# Create position controller
|
|
481
|
+
controller = PositionController(
|
|
482
|
+
x_pid=PIDController(kp=2.0, ki=0.1, kd=0.5),
|
|
483
|
+
y_pid=PIDController(kp=2.0, ki=0.1, kd=0.5),
|
|
484
|
+
z_pid=PIDController(kp=4.0, ki=0.2, kd=1.0),
|
|
485
|
+
target_pos=np.array([1.0, -1.0, 2.0])
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
# Set up initial state
|
|
489
|
+
initial_state = QuadState(
|
|
490
|
+
pos=np.array([0.0, 0.0, 0.0]),
|
|
491
|
+
vel=np.array([0.0, 0.0, 0.0]),
|
|
492
|
+
quat=np.array([1.0, 0.0, 0.0, 0.0]),
|
|
493
|
+
ang_vel=np.array([0.0, 0.0, 0.0])
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
# Run simulation with academic logging
|
|
497
|
+
log = simulate_with_academic_logging(
|
|
498
|
+
duration=10.0,
|
|
499
|
+
dt=0.02,
|
|
500
|
+
controller=controller,
|
|
501
|
+
initial_state=initial_state,
|
|
502
|
+
ref_position=np.array([1.0, -1.0, 2.0]),
|
|
503
|
+
controller_type="pid"
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
# Create academic evaluator
|
|
507
|
+
evaluator = AcademicEvaluator(log)
|
|
508
|
+
|
|
509
|
+
# Generate comprehensive analysis with all plots and metrics
|
|
510
|
+
metrics = evaluator.generate_comprehensive_analysis("academic_results")
|
|
511
|
+
|
|
512
|
+
print("Academic evaluation completed! Results saved to 'academic_results' directory.")
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
## Verification
|
|
518
|
+
|
|
519
|
+
```bash
|
|
520
|
+
pytest -q # unit + perf tests (should be all dots)
|
|
521
|
+
mypy quadcopter # static typing gate (should be 'Success')
|
|
522
|
+
python -m quadcopter --quiet # CLI smoke test
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
All three finish without errors; a 4 s RK4 run takes ≈ 0.05–0.08 s on a 2020‑era laptop.
|
|
526
|
+
|
|
527
|
+
---
|
|
528
|
+
|
|
529
|
+
## Examples
|
|
530
|
+
|
|
531
|
+
The library includes comprehensive examples demonstrating various features:
|
|
532
|
+
|
|
533
|
+
### Python Examples
|
|
534
|
+
- `examples/pid_control_example.py` - PID position control
|
|
535
|
+
- `examples/lqr_control_example.py` - LQR control
|
|
536
|
+
- `examples/rl_training_example.py` - Reinforcement learning
|
|
537
|
+
- `examples/real_time_simulation.py` - Real-time simulation
|
|
538
|
+
- `examples/enhanced_plotting_example.py` - Advanced visualization
|
|
539
|
+
- `examples/enhanced_logging_example.py` - Comprehensive logging
|
|
540
|
+
- `examples/academic_evaluation_example.py` - Academic evaluation and analysis
|
|
541
|
+
|
|
542
|
+
### Jupyter Notebooks
|
|
543
|
+
- `notebooks/control_system_design.ipynb` - Interactive PID/LQR tuning
|
|
544
|
+
- `notebooks/rl_training_tutorial.ipynb` - RL experimentation
|
|
545
|
+
- `notebooks/data_analysis.ipynb` - Log analysis and visualization
|
|
546
|
+
- `notebooks/performance_comparison.ipynb` - Comparing control methods
|
|
547
|
+
|
|
548
|
+
Run any Python example with:
|
|
549
|
+
```bash
|
|
550
|
+
python examples/pid_control_example.py
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
Run any Jupyter notebook with:
|
|
554
|
+
```bash
|
|
555
|
+
jupyter notebook notebooks/control_system_design.ipynb
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
---
|
|
559
|
+
|
|
560
|
+
## Road‑map
|
|
561
|
+
|
|
562
|
+
✅ Advanced control systems (PID, LQR, Fuzzy Logic)
|
|
563
|
+
✅ Gymnasium‑compatible wrapper for RL training
|
|
564
|
+
✅ Comprehensive logging for academic research
|
|
565
|
+
✅ Real-time simulation capabilities
|
|
566
|
+
✅ Enhanced visualization and analysis tools
|
|
567
|
+
✅ Academic evaluation and analysis tools for research publications
|
|
568
|
+
✅ Optional aerodynamic drag model
|
|
569
|
+
✅ Notebook benchmark for tuning PID / LQR / MPC / RL policies
|
|
570
|
+
|
|
571
|
+
---
|
|
572
|
+
|
|
573
|
+
## Academic Use
|
|
574
|
+
|
|
575
|
+
This library is designed for academic research and education. When using in research publications, please cite:
|
|
576
|
+
|
|
577
|
+
```bibtex
|
|
578
|
+
@software{quadcopter_dynamics_2025,
|
|
579
|
+
author = {2black0},
|
|
580
|
+
title = {Quadcopter-Sim: A Python Toolkit for 6-DoF Quadrotor Simulation},
|
|
581
|
+
year = {2025},
|
|
582
|
+
doi = {TBD},
|
|
583
|
+
url = {https://github.com/2black0/quadcopter-sim-python}
|
|
584
|
+
```
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
Released under the **MIT License**. Contributions and issues are very welcome!
|