Making drones fly
The drones in Arc Raiders got me wanting to build my own. My Bachelor's thesis was about drones under sensor attacks, so this felt like a good excuse to bring some of that into my games.
There's something nice about using proper physics in games. While difficult to get it to sit right with gameplay, it often makes the experience feel less scripted. A drone has to lean to accelerate, lean back to brake, and recover when something knocks it sideways. The weight you see is the weight the controller has to deal with. I'll probably cheat where the gameplay needs it, but I wanted to start here.
P, I and D
Let's begin by discussing how a drone is able to fly.
A controller measures the difference between where something should be and where it is. That's the error, $e$. A PID turns that error into a correction:
$$u(t) = K_p e(t) + K_i\int_0^t e(\tau)\,d\tau + K_d\frac{de(t)}{dt}$$
P pushes harder the further away you are. On its own, it can send you sailing past the target.
I adds up the error over time. If a constant force keeps you slightly off target, it builds up the extra push needed to get you there.
D reacts to how quickly the error changes. With a fixed target, it acts like a brake, damping the oscillation.
Four motors
It's not an accident that a drone has four motors. Obviously, increasing thrust on one side tilts the drone in the other direction, allowing for travel. But not as obvious is how it allows for attitude adjustments.
The two diagonal propeller pairs have opposite spin directions. This is what cancels out, or allows for, yaw torque.
$$m\mathbf a = m\mathbf g + R\sum_{i=1}^{4}\mathbf f_i, \qquad \boldsymbol\tau = \sum_{i=1}^{4}\left(\mathbf r_i\times\mathbf f_i + s_i k_y T_i\,\hat{\mathbf y}\right)$$
Each motor produces thrust $\mathbf f_i=T_i\hat{\mathbf y}$ at arm position $\mathbf r_i$. The cross product gives its turning torque; $s_i=\pm1$ gives the rotor's spin direction and $k_y$ its reaction-torque factor. These are body-frame quantities; $R$ rotates thrust into the world, where gravity acts.
Manipulating sensors
Another thing, besides the physics, which isn't faked in my game are sensors. A real drones relies on sensors which tell its attitude, velocity (angular and translational) etc.
This allows for a pretty fun damage model.
We can add bias and noise to our sensors, and the drones steering gets worse. Apply more noise and more bias and it'll crash.
Loading recorded flight…
Coupling to Godot
The flight code lives in a shared C++ library, plugged into Godot through a GDExtension. I can run it in a standalone simulator too, which makes it easy to test lots of flights. It's a simplified rigid-body model: four rotor forces and their torques, without a full aerodynamic simulation.
Loading recorded flight…
| PID result | |
|---|---|
| Median waypoint pass speed | 3.21 m/s |
| Crash rate | 1.46% |
| Median maximum overshoot at the end | 1.85 m |
These are the simulation results over thousands of randomly generated tracks.
In the next part of the series, we'll try to beat it with a trained drone using reinforcement learning.