Issue 22 Β· Pick 03 Robotics β read
Crazyflow: An Accurate, GPU-Accelerated, Differentiable Drone Simulator in JAX
This is an abstract-plus-full-text paper about a drone simulator, and normally "we built a faster simulator" is a yawn. The reason to pay attention: Crazyflow is fast and accurate and differentiable enough that the authors collapse the entire train-then-deploy loop into the duration of a single maneuver β they throw a Crazyflie into the air, train a recovery policy from scratch in 0.38 seconds of wall time while it tumbles, upload it, and the drone catches itself. That's a qualitatively different way to use simulation: not as an offline data factory, but as an in-execution computational primitive, like a planner.
The three-way tradeoff simulators have been stuck in
Drone simulators have historically let you pick at most two of three properties:
- Fidelity β model the actual motor dynamics, thrust curves, and onboard controller stack well enough that policies transfer to hardware. Tools like RotorS, CrazyS, and software-in-the-loop setups do this, but they're CPU-bound and serial.
- Throughput β Aerial Gym (Isaac), Flightmare, gym_pybullet_drones with process parallelism. Fast, but typically not differentiable, and often with simplified physics.
- Differentiability β DiffPhysDrone and DiffAero give you gradients via PyTorch, but mostly through point-mass or idealized rigid-body models, punting the sim-to-real complexity to an assumed-perfect low-level controller.
The framing insight of the paper is that these three properties aren't just independently nice β they multiply. Fidelity means you don't need domain randomization; no domain randomization means the optimization landscape is a single clean deterministic problem; a clean deterministic problem plus analytic gradients means backpropagation-through-time (BPTT) converges with tiny batch sizes in a few hundred thousand samples; and raw throughput turns those samples into sub-second wall time. Each property amplifies the others, and the endpoint is training times short enough to fit inside the physical event you're controlling.
How they get all three at once
Two design decisions do most of the work.
First: specialize, and drop the constraint solver. General-purpose GPU physics engines (MJX, Isaac) spend most of their time in an iterative contact-constraint solve. A drone in free flight has no contacts. Crazyflow just integrates the equations of motion directly β a rigid body with quaternion attitude \mathbf{q}, driven by rotor speeds \Omega_i mapped to forces and torques through identified second-order thrust curves, plus linear body-frame drag. No solver loop means faster forward passes and better-conditioned gradients on the backward pass (iterative solvers are notoriously ugly to differentiate through).
Second: put everything in one JAX computation graph. Physics, the reimplemented Crazyflie onboard controller stack (a Mellinger-style geometric controller), the RL environment logic, reward computation, and even the training loop itself are all traced and JIT-compiled by XLA into a single fused kernel. This is the difference between PyTorch's eager execution β every op is a kernel launch with Python-interpreter synchronization in between β and one monolithic kernel with zero Python in the loop.
A subtle but important detail: they reimplemented the actual Crazyflie firmware controllers inside the graph. Gradients therefore flow through the same cascaded control stack that runs on the real hardware β the sim-to-real gap of "assume a perfect low-level controller" simply doesn't exist. They also identified a practically important physics detail most models miss: quadrotor motor controllers only apply positive torque, so rotor spin-up and spin-down have different dynamics. Their motor model (Eq. 6) uses separate velocity/drag coefficients for acceleration (\hat{c}_v, \hat{c}_d) and deceleration (\check{c}_v, \check{c}_d). These small asymmetries are apparently what make transfer work without domain randomization.
For users who don't want first-principles parameter identification (which required load cells and careful flight experiments), there's an abstracted model: assume a well-tuned inner loop, model attitude \bm{\Psi} as a second-order linear system and collective thrust as a first-order lag, and fit the whole thing from under four minutes of flight data. This is the piece most likely to see broad adoption β it worked on a 660 g custom PX4 drone, not just Crazyflies.
The numbers
Throughput: ~700 million simulation steps per second at one million parallel worlds on a consumer GPU (peaking over 900M), scaling to 4.2 million simultaneous drones, and 9 million gradients per second when differentiating through 10-step rollouts. Against DiffAero (the state-of-the-art differentiable drone sim), they report >10Γ gradient throughput at nearly all parallelization levels β while differentiating through full dynamics plus controllers, versus DiffAero's simplified models. They match flightning, which uses a simplified single-drone model with no controllers in the gradient. Swarms of 4,000 full-fidelity drones per world, thousands of worlds.
Accuracy is where this earns credibility. The sim-to-real gap β RMS position difference between simulated and real flights under identical control:
Notably, Crazyflow beats CrazySim β a software-in-the-loop simulator running the actual latest firmware β by up to 82.8%. Their JAX reimplementation of the control stack plus identified physics is more faithful to the real closed-loop system than the real firmware running against someone else's physics.
That accuracy is what enables the headline training results. On a Lissajous tracking task deployed on real hardware, with zero domain randomization:
Sub-centimeter tracking from a policy trained in 1.56 seconds β reportedly the fastest training times for learning-based quadrotor control on these tasks. A delicious detail: the BPTT training runs on CPU, because analytic gradients have such low variance that 16 parallel environments suffice, and at that batch size the CPU beats the GPU. The gradient quality, not raw parallelism, is doing the work.
They also train motor-level policies (raw rotor speed commands, no onboard controller at all) in 12.16 s β 14Γ faster than a specialized C implementation β and run MPPI with the full nonlinear simulator as the internal model: 500k parallel 25-step rollouts at 50 Hz, over half a billion steps per second, for real-time multi-modal obstacle avoidance on hardware.
The throw: learning inside the execution window
Here's the demonstration that reframes what a simulator is for. A human throws a Crazyflie into the air. Within 500 ms of the throw, the system predicts the drone's state at a future "takeover" moment. It then trains a stabilization policy from scratch with BPTT β 180k samples, 0.38 s of wall time β initialized on that predicted state, uploads the parameters, and the policy stabilizes the drone before it hits the ground.
Why this matters beyond the stunt value: it demonstrates that simulation can now serve as an online computational resource inside a control loop, the way MPC solvers do β except the "solve" is training a full neural policy tailored to the exact current situation. The authors gesture at where this goes: online opponent modeling in drone racing, real-time swarm replanning, gradient-based auto-tuning at scale. One could imagine robots that, when they encounter a novel disturbance, spin up a policy for it in the time it takes the disturbance to unfold.
The evidence is real but bounded: Figure 6 reports mean success rate over 12 runs, with success limited by the room's ceiling height (which caps how much airtime the training has to work with). This is a lab demo with motion capture, not a field capability.
What to be skeptical about
The quadrotor is a best-case system. Free-flight quadrotor dynamics are smooth, low-dimensional (~17 states), contact-free, and among the best-understood in robotics. Every headline number leans on that. The core architectural bet β drop the constraint solver β by construction excludes contact-rich tasks, manipulation, or legged locomotion. Whether "train a policy in 0.38 s mid-execution" generalizes to systems where dynamics are hybrid, stiff, or hard to identify is entirely open. BPTT itself is known to struggle with contact discontinuities.
No domain randomization β no engineering. The transfer results rest on painstaking system identification: load-cell thrust measurements per motor and battery, inertia estimation from flight data, asymmetric motor models. The abstracted model's 4-minute sys-ID pipeline mitigates this, but it assumes a "stable and well-tuned low-level control loop" β it fits the closed loop, so a poorly tuned controller poisons the model. And all real-world experiments use a 240 Hz motion capture system; state estimation error, a dominant real-world issue, is largely absent.
The 0.38 s excludes compilation. All timings are measured after warming the JIT cache. Fair for the claim being made (the compiled kernel is reusable), but the first run pays XLA compilation costs that can be substantial for large fused graphs.
Perception is thin. Rendering is depth-only raycasting via MJX (350k fps at 64Γ64, but at high memory cost). Vision-based flight β arguably where massive parallel simulation matters most β is future work.
One curious data point: the motor-level policy (bypassing onboard controllers) achieves 16.6 cm RMS on the 5.5 s Lissajous, versus ~1.2 cm for the attitude-level BPTT policy. Even with motor-level fidelity in the simulator, end-to-end motor control transfers an order of magnitude worse than policies that keep the onboard controller in the loop β a useful reminder that cascaded control structure is doing real work for sim-to-real, not just legacy convention.
Where to spend your reading time
The Materials and Methods section is the best part: the asymmetric rotor model (Eq. 6) and the reasoning behind it, the abstracted model and its two-stage system identification (rotational dynamics fit by closed-loop rollout with JAX gradients; translational dynamics fit via the thrust-norm trick to avoid divergent open-loop rollouts), and the BPTT setup (Table 4 β 16 environments, 40-step rollouts, \gamma = 1.0) reward close reading. Then Figure 6 and the accompanying video for the throw experiment. The simulator is open source (pip install crazyflow), and given that gym_pybullet_drones β its predecessor from the same broader community β became the default Crazyflie simulator, this has a clear path to being the standard tool in aerial robot learning.