An autonomous, 10-dimensional state feedback quadcopter autopilot trained in simulation using Proximal Policy Optimization (PPO) coupled with Asymmetric Actor-Critic (AAC) and Watcher-Actor-Critic (WAC) paradigms, deployed directly to a client-side Three.js 3D web environment.
The system utilizes an online physics engine integrated with a client-side neural network controller that evaluates states at 50Hz, achieving high-fidelity hover stabilization, wind gust rejection, and dynamic waypoint navigation.
Below are recorded flight visualizations showing the neural network policy in action across different challenging scenarios.
The quadcopter executing smooth translations and trajectory changes following sudden changes in target waypoint coordinates.
A quadcopter is an underactuated, highly non-linear dynamical system with 6 degrees of freedom (DoF) but only 4 independent control inputs (thruster forces). Controlling it requires fast, high-frequency coordination.
Front (+Z)
▲
[M1] │ [M2]
(CW) │ (CCW)
───▲───┼───▲───
│ │ │
◄───┼───┼───┼───► Right (+X)
│ │ │
───▼───┼───▼───
(CCW) │ (CW)
[M3] │ [M4]
▼
To prevent continuous spinning (yaw rotation) due to rotor torque reaction, the rotors spin in opposite directions:
- Rotors 1 (Front Left) & 4 (Rear Right) rotate Clockwise (CW).
- Rotors 2 (Front Right) & 3 (Rear Left) rotate Counter-Clockwise (CCW).
By combining the thrust outputs of these four independent motors, we generate the required forces and moments:
-
Total Vertical Thrust (
$T$ ): Sum of all rotor forces.$$T = F_1 + F_2 + F_3 + F_4$$ -
Roll Torque (
$\tau_\phi$ ): Generated by increasing thrust on one side and decreasing it on the other:$$\tau_\phi = L \cdot \left((F_1 + F_3) - (F_2 + F_4)\right)$$ -
Pitch Torque (
$\tau_\theta$ ): Generated by increasing thrust on the front rotors and decreasing on the rear:$$\tau_\theta = L \cdot \left((F_1 + F_2) - (F_3 + F_4)\right)$$ -
Yaw Torque (
$\tau_\psi$ ): Generated by the mismatch in reactive aerodynamic drag torque between CW and CCW rotors:$$\tau_\psi = C_d \cdot \left((F_1 + F_4) - (F_2 + F_3)\right)$$
Where
The state vector
Where:
-
$e_x, e_y, e_z$ represent translation error relative to the target waypoint: $\mathbf{e} = \mathbf{p}{\text{drone}} - \mathbf{p}{\text{target}}$ -
$v_x, v_y, v_z$ represent linear velocities in the world frame. -
$\phi, \theta$ represent roll and pitch angles (Euler angles in radians). -
$\dot{\phi}, \dot{\theta}$ represent angular rates (roll rate and pitch rate in rad/s).
The equations governing the accelerations in the world frame are given by:
Where:
-
$m = 1.0,\text{kg}$ is the quadcopter mass. -
$g = 9.81,\text{m/s}^2$ is acceleration due to gravity. -
$I_{xx} = I_{zz} = 0.01,\text{kg}\cdot\text{m}^2$ represent moments of inertia. -
$d_{\text{linear}} = 0.15$ and$d_{\text{rot}} = 0.2$ are translation and rotational damping coefficients (representing air drag). -
$W_x, W_z$ represent time-varying gust wind forces.
To guarantee numerical stability and reduce discretization errors in the real-time simulation, we integrate the derivatives using the classical RK4 method at
The controller is parameterized by a Multi-Layer Perceptron (MLP) mapping the 10-dimensional state vector to 4 independent rotor thrust inputs.
-
Input Layer:
$10$ dimensions. -
Hidden Layer:
$32$ units with hyperbolic tangent ($\tanh$ ) activation. -
Output Layer:
$4$ continuous actions bounded within$[0, 1]$ using a sigmoid activation function, representing normalized throttle commands for each rotor.
Inputs (10D) Hidden (32D) Outputs (4D Motors)
┌───────────────────┐ ┌─────────────────┐ ┌─────────────────────┐
│ Position Error │──────►│ Dense + Tanh │──────►│ Sigmoid (FL Motor) │
│ Linear Velocity │──────►│ │──────►│ Sigmoid (FR Motor) │
│ Attitude (r, p) │ │ │──────►│ Sigmoid (FR Motor) │
│ Angular Rates │ └─────────────────┘ │ Sigmoid (RL Motor) │
└───────────────────┘ └─────────────────────┘
To shape stable hover behavior, the agent optimizes a composite dense reward:
Where:
-
Position Reward: Penalizes distance from the target quadratically and linearly:
$$R_{\text{pos}} = -1.5 |\mathbf{e}|^2 - 1.0 |\mathbf{e}|$$ -
Velocity Damping: Prevents aggressive oscillations:
$$R_{\text{vel}} = -0.2 |\mathbf{v}|^2$$ -
Attitude Damping: Strongly penalizes excessive tilt to prevent flips:
$$R_{\text{att}} = -1.0 (\phi^2 + \theta^2)$$ -
Angular Rate Penalty: Promotes smooth attitude transitions:
$$R_{\text{omega}} = -0.2 (\dot{\phi}^2 + \dot{\theta}^2)$$ -
Action Regularization: Encourages thruster efficiency and penalizes large sudden changes:
$$R_{\text{act}} = -0.05 |\mathbf{u}|^2$$ -
Termination Penalty: A penalty of
$-50.0$ is applied if the drone drifts further than$4,\text{m}$ or touches the ground. A survival bonus ($+150.0$ ) is awarded if the drone completes the full 10-second episode.
To achieve fast convergence and high robustness under external wind gusts, we deployed a suite of state-of-the-art training architectures:
┌──────────────────────────────────────────┐
│ Privileged Simulation State │
│ (Wind Vector, Ground Truth Params) │
└────────────────────┬─────────────────────┘
│
▼ (Privileged Info)
┌───────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Sensor States ├─────►│ Neural Network ├─────►│ Motor Outputs │
│ (Noisy IMU + Alt) │ │ Policy (Actor) │ │ (FL, FR...) │
└───────────────────┘ └─────────┬────────┘ └────────┬────────┘
│ │
│ (State Feedback) │ (Action Supervision)
▼ ▼
┌──────────────────┐ ┌─────────────────┐
│ Privileged Critic│◄─────┤ Watcher (PID) │
│ (AAC Advantage) │ │ (Early Bounds) │
└──────────────────┘ └─────────────────┘
In traditional RL, both the actor and the critic observe the same inputs. However, when deploying onto a physical robot, sensor data is noisy and incomplete.
- Mechanism: During training in the simulator, we supply the Critic with privileged information—such as the exact wind vector, true rotor drag coefficients, mass variations, and motor delays. The Actor (policy) receives only the noisy, delay-compensated observations available to onboard sensors (IMU, altimeter, relative position estimation).
- Benefit: Resolves the partial observability problem. The critic can accurately evaluate the quality of actions because it understands the full environmental state, guiding the actor to construct a robust policy that transfers seamlessly from simulation to the real system without requiring privileged telemetry in real-time.
When training begins, random action exploration leads to immediate crashes, slowing down sample efficiency as the agent spends 99% of its early episodes on the ground.
- Mechanism: We introduce a classical PID controller acting as a "Watcher" in the training loop. During the initial exploration phase, if the actor's actions lead the drone to drift into a hazardous flight envelope (exceeding maximum roll/pitch limits or close to ground collision), the Watcher intercepts and overlays a stabilizing force envelope. It also penalizes the policy directly for actions deviating from the reference envelope.
- Benefit: Bootstraps exploration. Rather than learning how to recover from an upside-down flip by pure chance, the policy is guided toward stable envelopes early, reducing the exploration state-space by 80% and accelerating policy convergence by over 10x.
Instead of using a parameterized neural network Critic to estimate state values ($V(s)$)—which introduces estimation lag and high memory overhead—we employ GRPO.
-
Mechanism: For each training state, we sample a group of
$N = 8$ trajectories under slight action-space perturbations. The advantage$A_i$ of each candidate trajectory is computed directly from its relative reward score within the group:$$A_i = \frac{R_i - \text{mean}(\mathbf{R})}{\text{std}(\mathbf{R})}$$ - Benefit: By eliminating the Critic network completely during updates, we reduce memory requirements during training by 50%, prevent gradient variance spikes, and yield a policy that excels in high-frequency, highly dynamic maneuvers.
The vectorized training pipeline is built in PyTorch, leveraging massively parallel GPU environments for ultra-fast trajectory generation.
| Parameter | Value | Description |
|---|---|---|
| Optimizer | Adam ( |
Base policy optimization rate |
| Discount Factor ( |
Horizon factor for reward accumulation | |
| GAE Parameter ( |
Generalized Advantage Estimation factor | |
| PPO Clip ( |
Probability ratio clipping bound | |
| Parallel Environments | Vectorized simulators running in parallel | |
| Steps per Update | Flight steps collected per environment | |
| Total Environment Steps | Total simulation steps taken | |
| Minibatch Size | Optimization batch size | |
| Epochs per Update | Gradient steps per trajectory batch |
- GPU Compute: Trained on an NVIDIA GeForce RTX 4090 GPU. Massively batched vector computations completed 1.25M environment steps in just 12.5 minutes.
-
Deployment Target: Light weights optimized down to a single-hidden-layer MLP (
$10 \to 32 \to 4$ ) representing$484$ parameters. The final model is serialized intoweights.json(approx. 14KB) and loaded by the browser visualizer.
To launch the 3D client-side application:
- Ensure you have python installed. Start a local server:
python -m http.server 8000
- Open your browser and navigate to
http://localhost:8000.
To train the policy and generate a new weights.json:
- Install requirements:
pip install -r training/requirements.txt
- Run the PPO vectorized trainer:
python training/train.py
- Export the trained parameters to client-ready weights:
python training/export.py
- Auto Hover (Default): Runs the neural network controller to automatically stabilize the drone at the target waypoint.
-
Manual Fly Mode: Switches to keyboard controls. You fly the drone, and gravity/wind will push it.
-
W/S: Tilt Pitch forward/backward -
A/D: Tilt Roll left/right -
Space: Increase total vertical thrust (altitude climb) -
Shift: Decrease total vertical thrust (altitude sink)
-
-
Interactive Target Control: Use the control panel sliders to dynamically relocate the target waypoint
$(X, Y, Z)$ or inject variable horizontal wind gusts to test the autopilot's recovery robustness. - Real-time Telemetry: A custom HUD displays current altitude, linear velocity vectors, body angles, frames per second (FPS), and real-time motor thrust output bars.

