Skydio X2 · skydio_x2-v1-2026-11-04
Gate PASS in simulation.
A trained control policy for the Skydio X2, judged by an automated gate in a second physics engine, and packaged for an NVIDIA Jetson running ROS 2. Not yet tested on hardware: 4 of 6 sim-to-real readiness probes fail. Read the limits before any real use.
Request the same test for your robot Limits How to run it
Published copy of a delivery record. The package itself (policy, TensorRT engine, ROS 2 node) went to the customer; the videos below are excerpts.
- Gate
- PASS
5 of 5 checks within limits
- Self-test
- OK
3 of 3 broken-robot canaries caught
- Hardware readiness
- 4 of 6 probes fail
Fails latency 1 step, latency 2 steps, sensor noise 0.05, gusts 4x the spec.
- On-device deploy
- PASS
deploy-aff9479d
01
Gate checks
60 episodes (3 seeds x 20): random launch offset ≤ 1.0 m, tilt ≤ 30.0 deg, drift ≤ 0.2 m/s, gusts 3.25 N (0.25 g) every [1.5, 3.0] s, 12.0 s each
| Check | Value | Limit | Result |
|---|---|---|---|
crashes | 0 | ≤ 0 | pass |
success_ | 1 | ≥ 0.95 | pass |
p95_ | 0.5 | ≤ 1.5 | pass |
mean_ | 0.055 | ≤ 0.1 | pass |
thrust_ | 0.001 | ≤ 0.2 | pass |
Success 60/60; 95% confidence the true rate is ≥ 0.94 (Wilson lower bound).
02
Who tests the tester
Canaries are deliberately broken robots flown with this policy. The gate must fail every one; a canary that passes would mean the gate has a blind spot, and nothing ships.
| Canary | Expected | Gate said | Checks that failed |
|---|---|---|---|
| baseline (healthy robot) | PASS | PASS | - |
| zero_policy (does nothing) | FAIL | caught | crashes, success_rate, p95_gust_recovery_s, mean_final_err |
| rotor 0 capped at 50% of HOVER thrust (can't hold attitude) | FAIL | caught | crashes, success_rate, p95_gust_recovery_s, mean_final_err, thrust_sat |
| latency 0.5 s (5 steps) | FAIL | caught | crashes, success_rate, p95_gust_recovery_s, mean_final_err |
03
Hardware readiness
Probes are faults a real robot will have. They are not part of the gate, so they do not block delivery, but each failure below is a reason this policy is not ready for hardware as is.
| Probe | Kind | Result | Checks that failed |
|---|---|---|---|
| latency 1 step | latency | fails | crashes, success_rate, p95_gust_recovery_s, mean_final_err |
| latency 2 steps | latency | fails | crashes, success_rate, p95_gust_recovery_s, mean_final_err |
| sensor noise 0.02 | noise | holds | - |
| sensor noise 0.05 | noise | fails | success_rate, p95_gust_recovery_s, mean_final_err |
| gusts 2x the spec | gust | holds | - |
| gusts 4x the spec | gust | fails | mean_final_err |
04
What was trained
- Robot
- Skydio X2 (customer model: MuJoCo Menagerie, Apache-2.0)
- Type
- multirotor
- Mass
- 1.325 kg
- Actuators
- 4 rotors, max 13.0 N each
- Source model
- customer MJCF
- Observation / action
- 17 / 4 floats at 10.0 Hz
- ONNX sha256
6c4d44aca57ce767b231e8fbb7941fe2fb3267676bfb06a546fc1db63b19319c
Robot
- Task
- Policyforge-TrackPosition-SkydioX2
- Simulator
- Isaac Sim, isaacsim_physx
- Learner
- rsl_rl
- Parallel robots
- 4,096
- Iterations
- 1,500
- Simulated steps
- 147,456,000
- Wall time
- 0:16:35
- GPU
- NVIDIA L40S
- Seed
- 1
Training run
Parsed from train.log. Every iteration is in training/learning_curve.csv in the package.
05
Recorded runs
x2_customer_scene.mp4x2_ros2_steered.mp4clip_0000.mp406
On-device deploy
Deploy PASS deploy-aff9479d. Jetson deploy OK (multirotor: TensorRT engine on the Orin GPU, parity vs ONNX, then 30 s ROS 2 flight loop on the GPU with 0.25 g gusts and a hover-target move; cost $0)
ENGINE_RC=0 parity TensorRT vs ONNX (CPU reference), 200 random obs: max |diff| = 2.86e-06 PASS t=15s rtf=1.00 mean_err=0.109m crashes=0 gusts_recovered=5/5 max_recovery_s=0.53 gust_gate=PASS lag_events=0 radius=0.150 gust_frac=0.25 backend=TensorRT-GPU infer_ms p50=0.672 p99=0.864 max=0.868 period_ms=100 t=20s rtf=1.00 mean_err=0.171m crashes=0 gusts_recovered=6/6 max_recovery_s=0.55 gust_gate=PASS lag_events=0 radius=0.150 gust_frac=0.25 backend=TensorRT-GPU infer_ms p50=0.639 p99=0.733 max=0.762 period_ms=100 t=25s rtf=1.00 mean_err=0.058m crashes=0 gusts_recovered=9/9 max_recovery_s=0.55 gust_gate=PASS lag_events=0 radius=0.150 gust_frac=0.25 backend=TensorRT-GPU infer_ms p50=0.639 p99=0.726 max=0.750 period_ms=100 t=30s rtf=1.00 mean_err=0.065m crashes=0 gusts_recovered=11/11 max_recovery_s=0.56 gust_gate=PASS lag_events=0 radius=0.150 gust_frac=0.25 backend=TensorRT-GPU infer_ms p50=0.635 p99=0.686 max=0.687 period_ms=100 t=34s rtf=1.00 mean_err=0.071m crashes=0 gusts_recovered=13/13 max_recovery_s=0.56 gust_gate=PASS lag_events=0 radius=0.150 gust_frac=0.25
07
The package
On the Jetson: build the TensorRT engine (it must match ONNX or the script stops), build the ROS 2 package, launch the
policy node. Topics, observation order and a simulator-only launch are in README.md.
unzip skydio_x2-v1-2026-11-04.zip && cd skydio_x2-v1-2026-11-04 && export PKG=$PWD
./jetson-build-engine.sh policy/policy.onnx fp32
cp -r ros2/pf_policy ~/pf_ws/src/ && (cd ~/pf_ws && colcon build --packages-select pf_policy)
ros2 launch pf_policy multirotor.launch.py role:=policy backend:=trt \
policy:=$PKG/policy/policy.engine robot_dir:=$PKG/robot
Contents of skydio_x2-v1-2026-11-04.zip
MANIFEST.jsonREADME.mdgate/report.jsongate/summary.mdjetson-build-engine.shmedia/clip_0000.mp4media/x2_customer_scene.mp4media/x2_ros2_steered.mp4policy/policy.onnxpolicy/policy.onnx.datareport.htmlrobot/robot.jsonselftest/selftest.jsonselftest/selftest.mdtraining/learning_curve.csvros2/pf_policy/(27 files)lineage/(4 manifests)
08
Limits
- Simulation only. Trained in Isaac Sim (PhysX) and gated in MuJoCo, a second physics engine. Nothing here has run on the physical robot; agreement between two simulators is not evidence about the real one.
- latency 1 step: fails. Gate checks that broke: crashes, success_rate, p95_gust_recovery_s, mean_final_err.
- latency 2 steps: fails. Gate checks that broke: crashes, success_rate, p95_gust_recovery_s, mean_final_err.
- sensor noise 0.05: fails. Gate checks that broke: success_rate, p95_gust_recovery_s, mean_final_err.
- gusts 4x the spec: fails. Gate checks that broke: mean_final_err.
- Latency. One policy step is 100 ms. The policy expects fresh state; measure your estimator and bus latency, and retrain with latency randomization if it reaches a step.
- Not tested: real sensors and state estimation, actuators/ESCs, battery sag, terrain or flight conditions outside the gate scenarios, communication loss, any other task.
- First hardware tests need a safety pilot or e-stop and a human sign-off.
09
Lineage
Each stage is a black box that wrote a hashed manifest; this delivery checked every one before reading it. The manifests
are in lineage/.
| Stage | Manifest | Verdict | Cost | Created (UTC) |
|---|---|---|---|---|
| import | import-a21283d7 | PASS | $0.00 | 2026-11-05T09:02:44Z |
| train | train-9e58650c | PASS | $0.00 | 2026-11-05T09:02:44Z |
| gate | gate-979a1e6a | PASS | $0.00 | 2026-11-05T09:02:53Z |
| deploy | deploy-aff9479d | PASS | $0.00 | 2026-11-05T09:04:33Z |
| Recorded stage cost | $0.00 | |||
Policy: run/exported/policy.onnx. Gate manifest: gate-979a1e6a.