AI Grand Prix — AI Integration Plan

VADR-TS-001 compliance, training strategy, submission pipeline • Grounded in the official spec • v1.0 — 2026-03-31

This document is the definitive playbook for training, integrating, testing, and submitting the autonomous drone AI for the AI Grand Prix Virtual Qualifier. Every requirement traces back to the VADR-TS-001 specification (Issue 00.01, 2026-03-09). Every parameter value references the actual codebase. Follow it top-to-bottom.

1. VADR-TS-001 Compliance Checklist

Every spec requirement mapped to our implementation. Fix all GAP items before submission.

Spec Requirement§StatusImplementation / Fix
MAVLink v2 over UDP4.1-4.2DONEmavsdk_bridge.pySimBridge.connect() via udpin://
HEARTBEAT reception4.3DONEconnection_state() async stream, waits for HEARTBEAT before race
ATTITUDE telemetry4.3, 4.5DONE_subscribe_attitude() → Euler angles + angular rates
HIGHRES_IMU telemetry4.3, 4.5DONE_subscribe_imu() → body-frame accel + gyro
ODOMETRY telemetry4.3DONE_subscribe_odometry() → NED position + velocity
SET_POSITION_TARGET_LOCAL_NED4.3DONEsend_velocity_ned(), send_velocity_body(), send_position_ned()
SET_ATTITUDE_TARGET4.3DONEsend_attitude(), send_attitude_rate()
TIMESYNC handling4.3GAPMentioned in docstring but no subscription. Fix: add _subscribe_timesync() or verify MAVSDK handles transparently.
Python 3.14.2 runtime5.1PARTIALCode runs on 3.14 but uses asyncio.ensure_future() (deprecated). Fix: replace with asyncio.create_task().
120 Hz physics rate4.4DONErace_config.py command_hz=120.0
50–120 Hz command rate4.4DONERate-limited async loop in race_pipeline.py
2 Hz minimum heartbeat4.4PARTIALMAVSDK auto-sends heartbeat. Verify: confirm with DCL sim that 2 Hz is maintained.
Local Cartesian only (no GPS)3.3DONENED frame throughout. No GPS references.
Forward-facing FPV camera only3.4DONEcamera_adapter.py single camera source
Vision → Perception → Planning → Control5.3GAPPipeline goes Perception → Control directly. Fix: integrate trajectory_optimizer.py as Planning layer, or document state machine as planning.
Max 8 minutes per run8.3DONEmax_time_s=480.0 enforced in race loop
No human interaction7DONErace_main() is fully autonomous
Navigate start → intermediate → finish gates8.1-8.2DONEState machine: SEEK → APPROACH → TRANSIT → FINISHED
Dependency manifest5.1GAPNo requirements.txt. Fix: generate with pinned versions.
3 Critical Gaps: TIMESYNC subscription, Planning layer, asyncio.ensure_future() deprecation. Fix before any submission.
2 Moderate Gaps: Missing requirements.txt, heartbeat rate verification. Fix during Week 1.

2. Training Strategy — Three Tiers

Tier 1 — Vision Models (no simulator needed)

Train detection models offline using captured frames or synthetic data.

Sim Frames 640x480 BGR Auto-Label yolo-auto-label.py Train U-Net / YOLO Export ONNX / TensorRT Deploy VisionPipeline

U-Net Gate Segmentation

python gate_segmentation.py train --data dataset_gates_seg
ParameterValue
ArchitectureGateSegNet (3→32→64→128→256 encoder)
Parameters~3.7M
LossDice + BCE combined
OptimizerAdam, lr=1e-3
Epochs100
Batch size8
Input size480 × 640
Exportgate_seg.onnx (opset 17)

Dataset: dataset_gates_seg/{train,val}/{images,masks}/
Masks: binary (white = gate, black = background)

YOLO Auto-Label → Train

# Step 1: auto-label from VQ1 color detection
python yolo-auto-label.py

# Step 2: train YOLOv8
python yolo-train.py train

# Step 3: export TensorRT
python yolo-train.py export
ParameterValue
Base modelyolov8n (nano)
Epochs150
Conf threshold0.5
Export priority.engine > .onnx > .pt

Auto-labeler uses ColorGateDetector to generate ground-truth bounding boxes from VQ1 highlighted-gate footage.

Tier 2 — Classical Controller (simulator needed)

The safe baseline for Round 1. Proportional pursuit controller with aggressive tuning.

GainValueWhat it doesTune if...
kp_yaw50.0Yaw snap to gate headingOscillates: lower. Sluggish: raise.
kp_pitch30.0Forward pitch authorityNosedive: lower. Won't approach: raise.
kp_roll25.0Banking into turnsRoll oscillation: lower.
cruise_pitch-25.0°Forward tilt when gate farToo fast/crash: reduce. Too slow: increase.
approach_pitch-15.0°Forward tilt near gateOvershoot: reduce. Stalls: increase.
hover_thrust0.50Thrust to hold altitudeCALIBRATE FIRST. Descends: raise. Climbs: lower.
seek_yaw_rate180°/sSpin speed when searchingBlur kills detection: lower to 90-120.
hover_thrust=0.50 is uncalibrated. This is the #1 crash cause. Run the hover test BEFORE any race attempt. Tune in 0.02 increments.
# Test classical controller
python test_race_standalone.py

# With YAML config override
python race_pipeline.py my_config.yaml attitude

Tier 3 — RL Policy (advanced, needs training time)

Phase A: Privileged Ground-truth gates, 2-5M steps PPO Phase B: Vision-in-Loop Real VisionPipeline in obs, 2M steps Phase C: Domain Rand. Lighting, colors, noise, FOV jitter PPO Hyperparameters (rl_train.py) n_steps=2048 batch_size=256 n_epochs=10 lr=3e-4 gamma=0.99 gae_lambda=0.95 net_arch=[256, 256] clip_range=0.2 Observation Space (13D) [bearing_x, bearing_y, distance, detected, vfwd, vright, vdown, roll, pitch, roll_rate, pitch_rate, yaw_rate, confidence] Action Space (4D continuous) [thrust, roll_rate, pitch_rate, yaw_rate]
# Phase A: privileged training
python rl_train.py train --steps 5000000

# Export to ONNX
python rl_train.py export

# Deploy in race pipeline
# Set controller to "rl" mode (requires code change in race_pipeline.py)
Critical gap: DroneRaceEnv currently uses privileged=True (ground-truth gate positions). Phase B requires modifying _get_obs() to feed real VisionPipeline detections. This is the hardest integration step.
RewardValuePurpose
Closer to gate+1.0 per meterDrive toward gate
Gate passage+50.0Reward transit
Crash-100.0Punish collision
Time penalty-0.01 per stepEncourage speed

3. Integration Architecture

DCL Simulator MAVLink v2 (UDP) SimBridge mavsdk_bridge.py telemetry camera frames VisionPipeline (U-Net) vision_pipeline.py GateTracker (EMA 0.65) race_pipeline.py State Machine (SEEK/APPROACH/TRANSIT) Planning Layer (GAP) trajectory_optimizer.py — not wired in Controller (Classical / RL Policy) RaceController or NeuralController attitude
velocity

Timing Budget (120 Hz = 8.33ms per frame)

StageTargetMethod
Camera capture<1 msUSB/CSI/sim pipe
U-Net inference<5 msGPU (RTX/Jetson)
RANSAC corners + PnP<2 msCPU (OpenCV)
Gate tracker<0.1 msEMA update
State machine<0.1 msBranch logic
Controller compute<0.5 msProportional math / ONNX inference
MAVLink send<1 msAsync UDP
Total<8.7 msFits 120 Hz with margin
Budget analysis: At 120 Hz we have 8.33 ms. The pipeline fits. If U-Net inference exceeds 5 ms (e.g., on Jetson), drop to 60 Hz vision + 120 Hz control by running vision every 2nd frame.

4. Submission Pipeline

Required files

From submit_check.py — these are packaged into submission.zip:

FilePurposeRequired
race_pipeline.pyMain orchestratorYes
vision_pipeline.pyGate detection + PnPYes
mavsdk_bridge.pyMAVLink communicationYes
race_config.pyConfigurationYes
gate_segmentation.pyU-Net model + RANSACYes (if mode=unet)
camera_adapter.pyCamera sourcesYes
race_logger.pyJSONL loggingYes
drone_mpc_foundation.pySchemas + MPCYes
sim_drone.pyPhysics (standalone mode)Optional
rl_controller.pyRL inferenceOptional (if using RL)
trajectory_optimizer.pyPath planningOptional
gate_seg_best.ptU-Net weightsYes (if mode=unet)
policy.onnxRL policy weightsOptional (if using RL)
requirements.txtDependenciesYes

Generate requirements.txt

mavsdk>=2.0
opencv-python>=4.8
numpy>=1.26
torch>=2.2
onnxruntime>=1.17
ultralytics>=8.1
stable-baselines3>=2.2
gymnasium>=0.29
casadi>=3.6
scipy>=1.12
pyyaml>=6.0

Config switch for DCL environment

# race_config.py ConnectionSettings
# Local simulation:
sim_url: "udpin://0.0.0.0:14540"
camera_source: "synthetic"

# DCL simulator:
sim_url: "udpin://0.0.0.0:14540"   # verify with competition docs
camera_source: "gazebo_pipe"        # or per DCL vision stream spec

Package and validate

python submit_check.py          # run all checks
python submit_check.py package  # create submission.zip
The validator checks syntax, imports, vision smoke test, controller smoke test, config validation, and code quality. It does NOT test live MAVLink connectivity.

5. Pre-Submission Validation Checklist

Standalone race test (no simulator)
python test_race_standalone.py

Expected: Completes gates in <480s. Detection rate >50%.

MAVSDK bridge test (requires PX4 SITL or DCL sim)
python mavsdk_bridge.py

Expected: Connects, hovers at 5m for 30s, prints NED position and command rate.

Verify command rate

In race loop output, confirm command_rate reads ≥50 Hz. Target: 120 Hz per race_config.py.

Verify 8-minute timeout

Confirm race_config.py max_time_s=480.0. Run a deliberate slow test — pipeline should terminate at 8:00.

Check vision FPS
python vision_pipeline.py

Expected: Color mode >200 FPS, U-Net >100 FPS (GPU), YOLO >60 FPS (GPU).

Validate submission package
python submit_check.py package

Expected: 0 failures, creates submission.zip. Verify zip contents include all required files + weights.

6. Performance Optimization Targets

MetricTargetCurrentTuning Knob
Vision latency (U-Net)<5 ms~5ms GPUReduce base_ch or use TensorRT
Vision latency (YOLO)<12 ms~12ms GPUUse .engine TensorRT format
Control loop rate120 Hz120 Hz (config)command_hz in race_config.py
Gate detection rate>80% of framesvariesHSV range, U-Net training data, confidence threshold
Transit detection<1.5m + 3 closing frames1.5m defaulttransit_distance
Max speed30 m/s30 m/s (config)safety.max_speed
Max tilt70°70° (config)safety.max_tilt
PnP distance accuracy<10% error at 15mdepends on cornersU-Net RANSAC >> bbox corners
EMA tracker alpha0.650.65Higher = faster, noisier
hover_thrustcalibrated0.50 (uncalibrated!)MUST tune per sim

Lap Time Targets

Based on typical DCL indoor course (~11 gates, ~160m total track):
TierLap TimeAvg SpeedStrategy
Conservative (Round 1 pass)60–90s2–3 m/sSlow, safe, detect every gate
Competitive (top 50%)30–45s4–6 m/sAggressive pursuit, late braking
Top tier (podium)<25s7–10 m/sOptimal trajectory + RL policy + racing line

7. Risk Matrix

RiskLIMitigation
hover_thrust miscalibratedHHRun hover test first. Tune in 0.02 increments. Add auto-calibration that measures altitude error.
Sim-to-real gap (RL)HHRL Phase B (vision-in-loop) + Phase C (domain rand). Classical controller as fallback.
asyncio.ensure_future() removed in 3.14HHReplace with asyncio.create_task() at 4 call sites in mavsdk_bridge.py.
Unknown gate color in VQ1MHAuto-detect dominant saturated color in first 10 frames. Multiple HSV presets available.
Timeout before finishing (8 min)MHMonitor elapsed time. If >6 min and <50% gates, increase speed aggressiveness.
Camera stream not connectedMHpreflight_check() verifies camera produces frames. Add retry logic.
TIMESYNC not handledMMMAVSDK may handle transparently. If not, add _subscribe_timesync().
Gate partially visibleMMU-Net handles partial gates. RANSAC works with incomplete contours.
False transit triggersLMPredictive transit: distance_closing_count ≥ 3 + 0.3s cooldown.
No requirements.txtHMGenerate and include in submission. See Section 4.

8. Timeline — 8-Week Plan

W1W2 W3W4 W5W6 W7W8 Baseline Controller Fix spec gaps, calibrate hover_thrust, tune gains Vision Training U-Net + YOLO train, auto-label, TensorRT export RL Training Phase A (privileged) + Phase B (vision-in-loop) Integration + Submit End-to-end testing, submission package, final tune Ongoing: benchmark lap times, iterate on gains, retrain as sim environment updates

Weeks 1–2: Baseline

Weeks 3–4: Vision

Weeks 5–6: RL + Planning

Weeks 7–8: Submit

Bottom line: The classical controller (Tier 2) is your safe Round 1 pass. Vision training (Tier 1) improves PnP accuracy. RL (Tier 3) is the path to podium. Do them in order — never skip the baseline.