AI Grand Prix — Tuning & Configuration Reference

Every parameter, what it does, safe ranges, and how to tune

1. Configuration System

All tuning lives in race_config.py — 7 dataclass sections, YAML serializable. Every value flows into race_pipeline.py, vision_pipeline.py, and the rest of the stack.

Loading & Saving

from race_config import RaceConfig

cfg = RaceConfig()                        # all defaults
cfg = RaceConfig.from_yaml("config.yaml") # from file (missing keys fall back to defaults)
cfg.save_yaml("my_config.yaml")           # save current state

Sections

DataclassAttributePurpose
CameraSettingscfg.cameraResolution and FOV
GateSettingscfg.gatePhysical gate dimensions
VisionSettingscfg.visionDetection mode, HSV, YOLO thresholds
ControlSettingscfg.controlPID gains, speed profile, thrust
RaceSettingscfg.raceTiming, distances, command rate
SafetySettingscfg.safetyAltitude, speed, tilt limits
ConnectionSettingscfg.connectionMAVSDK URL, camera source

2. Camera Settings

ParameterDefaultRangeDescription
width640320 – 1920Frame width in pixels
height480240 – 1080Frame height in pixels
fov_h90.060 – 120Horizontal FOV in degrees
fov_v60.040 – 90Vertical FOV in degrees
Why 640x480? This is the sweet spot for 120 Hz inference. Higher resolutions give marginal detection improvement but cost frames — and frames are lap time.

3. Gate Settings

ParameterDefaultRangeDescription
width2.01.0 – 5.0Gate width in meters
height2.01.0 – 5.0Gate height in meters
CRITICAL: These values MUST match the actual gate dimensions. The PnP solver uses them to estimate depth. If the competition gates are 1.5 m and you leave this at 2.0 m, your distance estimate will be off by 33% — and your approach/transit logic will misfire.

4. Vision Settings

ParameterDefaultRangeDescription
mode"unet""color" / "yolo" / "unet"Detection pipeline mode
hsv_lower(40, 100, 100)(0,0,0) – (179,255,255)HSV lower bound (color mode only)
hsv_upper(90, 255, 255)(0,0,0) – (179,255,255)HSV upper bound (color mode only)
color_preset"green"green / cyan / magenta / red / yellow / whiteQuick HSV preset selector
min_area500100 – 5000Minimum contour area in pixels
min_aspect0.30.1 – 0.5Minimum width/height ratio
max_aspect3.02.0 – 10.0Maximum width/height ratio
yolo_model_path"gate_detector.pt"pathYOLO weights file path
yolo_conf_threshold0.50.1 – 0.9YOLO confidence cutoff
Tip: In color mode, use a color_preset instead of hand-tuning HSV bounds. The presets are tested across multiple lighting conditions.

5. Control Settings — most tuning happens here

ParameterDefaultPreviousSafe Range Too LowToo HighDescription
kp_yaw50.0was 3520 – 80 Sluggish headingOscillationYaw gain (deg / bearing error)
kp_pitch30.0was 2010 – 50 Won't pitch forwardNosedive riskPitch gain
kp_roll25.0was 155 – 40 Slow turnsRoll oscillationBank angle gain
kp_throttle0.45was 0.30.1 – 0.7 Altitude drop in turnsAltitude oscillationThrust per vertical error
cruise_pitch−25.0was −12−35 to −5 SlowCrash into groundForward tilt when gate is far (deg)
approach_pitch−15.0was −5−25 to −2 Slow approachOvershoot gateForward tilt when close (deg)
approach_dist2.0was 51.0 – 10.0 Late brakingSlow from far outStart braking distance (m)
hover_thrust0.500.3 – 0.7 DescendsAscendsCALIBRATE PER VEHICLE
seek_yaw_rate180.0was 2520 – 360 Slow searchBlur kills detectionYaw speed when seeking (deg/s)
lookahead_gates31 – 5 Reactive onlyWasted computeGates to plan ahead
hover_thrust is the #1 crash cause. If your drone slowly descends during hover, increase it. If it climbs, decrease it. Test in simulator FIRST.

6. Race Settings

ParameterDefaultPreviousSafe Range Too LowToo HighDescription
command_hz120.0was 10050 – 200 Control lagCPU-boundCommand rate (Hz)
max_time_s480.0120 – 600 Short raceWasted time8 min per spec
max_no_detection15was 305 – 60 False seek on blinkFly blind too longFrames before SEEK state
approach_distance15.0was 305 – 50 Late approachSpeed lost earlyEnter approach mode (m)
transit_distance1.5was 2.00.5 – 5.0 Miss detectionFalse transitGate pass threshold (m)
expected_gates00 – 50 Finish by timeout0 = unknown
seek_timeout30.0was 6010 – 120 False emergencyStuck searchingSeconds before emergency
approach_lost_timeout2.0was 50.5 – 10 Over-reactiveFly blindUnused currently
recovery_timeout0.0was 300 Wastes timeZERO = no recovery phase
no_gate_finish_timeout30.0was 6015 – 120 Premature finishWastes timeSeconds after last gate

7. Safety Settings

ParameterDefaultPreviousSafe RangeDescription
min_altitude0.50.5 – 2.0Floor check (meters AGL)
max_altitude80.010 – 100Ceiling check (meters AGL)
max_speed30.0was 2010 – 50Speed limit (m/s)
max_tilt70.0was 6030 – 80Bank angle limit (degrees)
geofence_radius500.0was 20050 – 1000Arena boundary (meters)
max_tilt at 70+ degrees means the drone can bank aggressively. If you see altitude loss in sharp turns, increase kp_throttle before reducing tilt. Tilt is speed.

8. Tuning Methodology

Follow this order. Skipping steps leads to compound errors that are impossible to diagnose.

Step 1 — Start with defaults

Load race_config.py with RaceConfig(). The defaults are a known-good aggressive baseline.

Step 2 — Calibrate hover_thrust

Hover test in the simulator. The drone should hold altitude with zero input. Adjust in increments of 0.02.

Step 3 — SEEK test

Does the drone spin and find gates? If it takes more than 3 seconds, increase seek_yaw_rate. If the camera is blurry during spin, decrease it.

Step 4 — APPROACH test

Does it fly to the gate smoothly? Adjust kp_yaw and kp_pitch. Watch for overshoot (gain too high) or sluggish correction (gain too low).

Step 5 — TRANSIT test

Does it register gate passage? If it flies through without triggering transit, lower transit_distance. Check if distance_closing_count logic fires correctly.

Step 6 — Speed test

Increase cruise_pitch by 5 degrees (more negative = faster). Run a full course. Check for crashes, missed gates, and altitude stability.

Step 7 — Iterate

One parameter at a time, 10-20% changes. Log telemetry. Compare lap times.

Golden rule: Change ONE parameter at a time. If something breaks, you know exactly what caused it.

9. Common Tuning Scenarios

SymptomFix
Drone oscillates left-right Lower kp_yaw and kp_roll by 20%
Drone flies past gates Lower cruise_pitch (less negative), increase approach_dist
Drone doesn't detect transit Lower transit_distance, check if distance_closing_count triggers
Drone spirals during seek Lower seek_yaw_rate — camera motion blur kills detection
Drone slowly descends during approach Increase hover_thrust by 0.05
Gates detected but PnP distance is wrong Check that gate.width and gate.height match the actual physical gates

10. YAML Config Example

A complete config file with all sections. Save as config.yaml and load with RaceConfig.from_yaml("config.yaml").

camera:
  width: 640
  height: 480
  fov_h: 90.0
  fov_v: 60.0

gate:
  width: 2.0
  height: 2.0

vision:
  mode: "unet"
  hsv_lower: [40, 100, 100]
  hsv_upper: [90, 255, 255]
  color_preset: "green"
  min_area: 500
  min_aspect: 0.3
  max_aspect: 3.0
  yolo_model_path: "gate_detector.pt"
  yolo_conf_threshold: 0.5

control:
  kp_yaw: 50.0
  kp_pitch: 30.0
  kp_roll: 25.0
  kp_throttle: 0.45
  cruise_pitch: -25.0
  approach_pitch: -15.0
  approach_dist: 2.0
  hover_thrust: 0.50
  seek_yaw_rate: 180.0
  lookahead_gates: 3

race:
  command_hz: 120.0
  max_time_s: 480.0
  max_no_detection: 15
  approach_distance: 15.0
  transit_distance: 1.5
  expected_gates: 0
  seek_timeout: 30.0
  approach_lost_timeout: 2.0
  recovery_timeout: 0.0
  no_gate_finish_timeout: 30.0

safety:
  min_altitude: 0.5
  max_altitude: 80.0
  max_speed: 30.0
  max_tilt: 70.0
  geofence_radius: 500.0

connection:
  sim_url: "udpin://0.0.0.0:14540"
  camera_source: "synthetic"
  camera_topic: "/camera"
  camera_exe: "~/grandprix/gz_camera_sub"