Skip to content

Latest commit

 

History

19 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Autonomous Drone Simulation System

C++20 quadrotor simulation with cascaded PID flight control, IMU sensor modeling, waypoint navigation, failsafe handling, and a JavaFX telemetry monitor with live 2D/3D visualization.


Build

Requires CMake 3.20+ and a C++20 compiler.

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
ctest --test-dir build

Test assertions are ordinary code rather than assert, so they hold in Release builds and a failure exits non-zero.

Run

# Basic run with CSV logging, as fast as the CPU allows
./build/adsim -c config/default.ini -o output.csv

# Stream telemetry and wait for the Java UI to connect before starting
./build/adsim -c config/default.ini --wait --port 5760

# Watch it at 4x speed
./build/adsim -c config/default.ini --wait --speed 4

Options: -c config (required), -o output (default: sim_output.csv), --stream, --wait, --host, --port, --realtime, --speed.

Unpaced, a 60 s mission finishes in well under a second, so streaming enables --realtime unless --speed says otherwise. Pass --speed 0 to stream unpaced.

Java UI

Requires Java 21+ and the included Gradle wrapper.

cd ui-java
./gradlew run

Provides a 2D top-down view and a 3D orbital view with live telemetry. Reconnects automatically if the simulation is restarted.

Architecture

The simulation is structured as a static library (adsim_core) consumed by a CLI executable (adsim). Each module has a clear boundary and communicates through value types with no shared mutable state.

adsim_core
├── math        — Vec3, Quaternion, and PID controller primitives
├── dynamics    — Rigid-body flight model: thrust, linear/angular drag,
│                 gyroscopic coupling, semi-implicit Euler integration
├── control     — Cascaded PID: position loops → desired attitude angles
│                 → angular rate setpoints → body torques
├── sensors     — IMU with Gaussian noise, random-walk bias instability,
│                 and configurable probabilistic dropout events
├── estimation  — Complementary filter fusing gyroscope integration with
│                 accelerometer gravity direction; slow gyro bias correction.
│                 The accelerometer correction is faded out as |a| departs
│                 from g, because a multirotor's specific force lies along
│                 the thrust axis and otherwise reads as "level" whenever
│                 the vehicle is manoeuvring
├── navigation  — Sequential waypoint tracker with per-waypoint acceptance
│                 radii; exposes current target as a ControlTarget
├── failsafe    — Three independent monitors: sustained IMU dropout →
│                 controlled descent; attitude limit violation → hover hold;
│                 position/altitude out of bounds → abort (sticky, terminal)
├── simulation  — Fixed-timestep orchestration loop; owns all subsystems;
│                 binds INI config to typed structs at startup; optional
│                 wall-clock pacing
├── logging     — Decimated CSV output: full state, IMU readings, estimated
│                 attitude, failsafe status, and active waypoint index
├── config      — Zero-dependency INI parser with typed getters and defaults
└── network     — TCP telemetry server (PIMPL, cross-platform Winsock/POSIX);
                  background accept thread; 30 Hz rate-limited line-delimited
                  JSON broadcast to a single connected client

ui-java is a standalone JavaFX application that connects over TCP, parses the JSON stream with Jackson, and renders a 2D top-down canvas and a 3D SubScene at 60 fps using an AnimationTimer. The 3D view applies the full quaternion orientation as a JavaFX Affine transform on the drone model.

Sensing in the loop

The controller flies on the estimated attitude and body rates, not on ground truth, so IMU noise, gyro bias drift and dropouts reach the control loop the way they would on real hardware. Position and velocity are still ground truth — there is no GPS or barometer model yet, so introducing uncertainty there would be arbitrary.

Set [estimator] use_for_control = false to hand the controller perfect sensing. That is the useful A/B when tuning: if a mission flies on ground truth but not on the estimate, the problem is estimation, not control. tests/test_mission.cpp runs the default mission both ways for exactly that reason.

Attitude estimate error against truth on the shipped configs is roughly 0.1–0.3 rad RMS in roll and pitch during manoeuvres. That is inherent to IMU-only attitude estimation on a multirotor: the accelerometer is the sole absolute reference and it is uninformative whenever the vehicle accelerates. Tightening it further needs velocity aiding, which is not modelled.

Configuration

[simulation]
timestep = 0.005
duration = 90.0

[flight_model]
mass = 1.5
gravity = 9.81

[imu]
accel_noise_std     = 0.05
dropout_probability = 0.0
seed                = 42     # fix or vary for repeated runs

[estimator]
alpha           = 0.02
use_for_control = true       # false flies on ground truth

[waypoint.0]
x = 0.0  y = 0.0  z = 8.0  yaw = 0.0  radius = 0.8

See config/default.ini and config/noisy_imu.ini for full examples.

About

C++20 quadrotor drone simulation with cascaded PID flight control, IMU sensor modeling, failsafe handling, and real-time JavaFX telemetry visualization over TCP.

Resources

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages