An extensible Python framework for simulating autonomous multirotor drones with modular components, protocol-based controller architecture and replaceable physics backends.
This project is an extensible simulation engine for autonomous multirotor drones.
Unlike many simulation projects focused on a single drone implementation, this engine was designed as a reusable platform for experimenting with flight controllers, battery models, mission planning and optimization algorithms.
The architecture separates the simulation into independent subsystems responsible for:
- drone components
- flight control
- mission execution
- physics simulation
- experiment management
- simulation history
Each subsystem has a single responsibility and communicates through well-defined interfaces, making the engine easy to extend without modifying existing functionality.
The project was designed around the following principles:
- Components should have a single responsibility.
- High-level behavior should be composed instead of hard-coded.
- Controllers should expose capabilities rather than implementation details.
- Mission logic should not depend on motors or physics.
- Simulation orchestration should remain independent from the physics implementation.
- Storage and visualization should not affect the simulation core.
The goal is to make the simulation engine reusable for different engineering workflows while keeping the domain model independent from infrastructure.
The engine can visualize and analyze simulation results including:
- drone trajectory
- orientation
- roll / pitch / yaw
- battery State of Charge (SOC)
- linear velocity
- mission execution
The same simulation data may later be stored in files, databases or any custom storage backend through the history storage abstraction.
A drone is represented as an aggregate of independent components.
Drone
├── Controller
├── Battery
├── Motors
├── Payloads
└── Missions
Each component owns only its own behaviour and may be replaced independently.
Current components include:
- Battery
- BatteryCell
- Motors
- Propellers
- Payloads
- Flight Controller
The project separates primitive control capabilities from high-level behaviour.
Mission commands never manipulate motors directly.
Instead, they communicate only with controller capabilities exposed through Protocols.
Mission
│
▼
Commands
│
▼
Capability Protocols
│
▼
Controller
│
▼
Drone Components
The controller owns primitive operations such as movement and stabilization.
Commands describe only the sequence of controller actions required to perform a mission.
This provides several advantages:
- reusable controller implementations
- reusable commands
- low coupling
- clear responsibility boundaries
- easy addition of new mission behaviours
A controller implementing the same capability protocols can immediately execute the existing command library.
Simulation orchestration depends only on the AbstractPhysicsEngine interface.
Current implementation:
- Python physics engine
Planned:
- native C++ backend using pybind11
This allows different physics implementations to be exchanged without modifying the simulation runner.
External physical effects are isolated from the drone model.
Current implementation includes:
- gravity
- aerodynamic drag
Planned extensions:
- wind
- atmospheric models
- external disturbances
- weather conditions
Different users may require different ways of storing simulation results.
Instead of embedding a single persistence mechanism, the engine defines the AbstractHistoryStorage interface.
Available implementations include:
- Console output
- Text storage
- Database storage
This abstraction allows different teams to integrate the simulation engine into their own workflows without changing the simulation core.
Examples:
- Console output for interactive debugging
- Text storage for notebooks and lightweight experiments
- Database storage for large engineering datasets
The engine is intended not only for running simulations but also for conducting engineering experiments.
ExperimentManager combines:
- SimulationRunner
- OptimizationStrategy
to automate iterative experiments, parameter tuning and controller evaluation.
The project follows ideas inspired by
- Domain-Driven Design
- Hexagonal Architecture
- Onion Architecture
- Clean Architecture
while keeping the focus on the simulation domain instead of framework-specific code.
src/
├── domain/
│ ├── geometry/
│ ├── drone/
│ ├── commands/
│ ├── controller/
│ ├── battery/
│ └── physics/
│
├── application/
│ ├── simulation/
│ ├── history/
│ └── experiments/
│
├── infrastructure/
│ ├── physics/
│ ├── storage/
│ └── optimization/
│
└── presentation/
Responsibilities are separated as follows:
| Layer | Responsibility |
|---|---|
| Domain | Drone model and business logic |
| Application | Simulation orchestration |
| Infrastructure | Replaceable implementations |
| Presentation | Visualization and notebooks |
Every simulation step follows the same execution flow.
Mission update
│
▼
Payload update
│
▼
Controller update
│
▼
Motor update
│
▼
Physics engine
│
▼
History manager
│
▼
Next simulation step
The simulation runner coordinates the process but does not implement the behavior of individual subsystems.
Each subsystem remains responsible only for its own domain.
drone = DroneFactory.get_base_drone(
missions=[
MoveToPointCommand(x=10, y=0, z=5),
StayInPointCommand(x=10, y=0, z=5),
]
)
simulation = SimulationRunner(
drones=[drone],
delta_t=0.01,
)
simulation.execute()The project includes unit tests covering the core mathematical and physical models.
Current test suite validates:
- vector algebra
- quaternion operations
- battery discharge model
- battery pack behavior
- drag force calculation
- force and torque computation
- physics integration
- controller behaviour
The tests focus on mathematical invariants and physically meaningful scenarios rather than only checking individual methods.
The current implementation intentionally uses a simplified physical model.
Known limitations include:
- simplified rotational dynamics
- simplified aerodynamic model
- no wind simulation
- no battery degradation model
- no sensor noise
These simplifications keep the architecture flexible while providing a solid foundation for future extensions.
Planned improvements include:
- native C++ physics backend (pybind11)
- improved aerodynamic model
- wind simulation
- battery degradation
- sensor noise models
- additional optimization strategies
- interactive visualization
- hardware-in-the-loop experiments
MIT License.

