Delivery record

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.

60episodes
0crashes
193gusts recovered
0.5 sp95 gust recovery
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

Gate checks with their limits
CheckValueLimitResult
crashes0≤ 0pass
success_rate1≥ 0.95pass
p95_gust_recovery_s0.5≤ 1.5pass
mean_final_err0.055≤ 0.1pass
thrust_sat0.001≤ 0.2pass

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.

Self-test canaries
CanaryExpectedGate saidChecks that failed
baseline (healthy robot)PASSPASS-
zero_policy (does nothing)FAILcaughtcrashes, success_rate, p95_gust_recovery_s, mean_final_err
rotor 0 capped at 50% of HOVER thrust (can't hold attitude)FAILcaughtcrashes, success_rate, p95_gust_recovery_s, mean_final_err, thrust_sat
latency 0.5 s (5 steps)FAILcaughtcrashes, 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.

Sim-to-real readiness probes
ProbeKindResultChecks that failed
latency 1 steplatencyfailscrashes, success_rate, p95_gust_recovery_s, mean_final_err
latency 2 stepslatencyfailscrashes, success_rate, p95_gust_recovery_s, mean_final_err
sensor noise 0.02noiseholds-
sensor noise 0.05noisefailssuccess_rate, p95_gust_recovery_s, mean_final_err
gusts 2x the specgustholds-
gusts 4x the specgustfailsmean_final_err

04

What was trained

Robot

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

Training run

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
Mean episode rewardrsl_rl, mean over finished episodes
Mean episode lengthpolicy steps per episode

Parsed from train.log. Every iteration is in training/learning_curve.csv in the package.

05

Recorded runs

The policy flying the customer's own MuJoCo scene (the gate's physics). x2_customer_scene.mp4
ROS 2 loop: policy node driving the MuJoCo plant, target steered. x2_ros2_steered.mp4
Isaac Sim (PhysX) playback of the trained policy. clip_0000.mp4

06

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.json
  • README.md
  • gate/report.json
  • gate/summary.md
  • jetson-build-engine.sh
  • media/clip_0000.mp4
  • media/x2_customer_scene.mp4
  • media/x2_ros2_steered.mp4
  • policy/policy.onnx
  • policy/policy.onnx.data
  • report.html
  • robot/robot.json
  • selftest/selftest.json
  • selftest/selftest.md
  • training/learning_curve.csv
  • ros2/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/.

Upstream stages
StageManifestVerdictCostCreated (UTC)
importimport-a21283d7PASS$0.002026-11-05T09:02:44Z
traintrain-9e58650cPASS$0.002026-11-05T09:02:44Z
gategate-979a1e6aPASS$0.002026-11-05T09:02:53Z
deploydeploy-aff9479dPASS$0.002026-11-05T09:04:33Z
Recorded stage cost$0.00

Policy: run/exported/policy.onnx. Gate manifest: gate-979a1e6a.