What EKF3 is in ArduCopter
EKF3 (Extended Kalman Filter version 3) is ArduCopter’s main state estimator. It takes raw sensor data and produces a fused estimate of position / velocity / attitude.
Without EKF3, no arming → no flight. Indoor (no GPS) — EKF3 must build on rangefinder + optical flow + IMU.
EKF3 sources — EK3_SRC1_* parameters
| Parameter | What | Indoor value |
|---|---|---|
EK3_SRC1_POSXY |
XY-position source | 0 (none — no GPS) |
EK3_SRC1_VELXY |
XY-velocity source | 5 (optical flow PMW3901/CXOF) |
EK3_SRC1_POSZ |
Z-position source | 2 (rangefinder TF-Luna down) |
EK3_SRC1_VELZ |
Z-velocity source | 0 (none, derive from POSZ) |
EK3_SRC1_YAW |
Yaw source | 1 (compass) or 0 (gyro-only) |
Typical issue — EKF doesn’t initialize
Symptom: AP: EKF3 IMU0 initialised appears, then AP: Arm: Accels inconsistent / Gyros inconsistent for 15-25 seconds (normal for SITL without accel calib) → then either armed succeed, or stuck.
Stuck if:
EK3_SRC1_VELXY=5(optical flow) but flow data isn’t arriving (sensor offline) → EKF3 has no XY velocity → doesn’t converge.EK3_SRC1_POSZ=2(rangefinder) butRNGFND1_TYPE=0→ no data for Z.- EKF3 expects all sources online before init completes. One missing source → infinite wait.
Fix: first verify via param show EK3_SRC1* + param show RNGFND1* + param show FLOW* that all sources are configured. Then param show STAT_BOOTCNT after reboot — if it grows, EKF can’t finish init.
Minimal EKF3 indoor configuration (for SITL)
# From indoor.parm:
GPS1_TYPE 0
ARMING_SKIPCHK 1
EK3_SRC1_POSXY 0
EK3_SRC1_VELXY 5 # optical flow
EK3_SRC1_POSZ 2 # rangefinder
FLOW_TYPE 6 # MAVLink-based optical flow (CXOF/external)
RNGFND1_TYPE 10 # MAVLink-based rangefinder
RNGFND1_ORIENT 25 # downward facing (POSZ source)
Detailed line-by-line breakdown — see arducopter-params-indoor.
EKF3 init timeline (normal)
t=0: SITL boots
t=2s: AP: EKF3 IMU0 initialised
t=5s: AP: GPS unhealthy (expected for indoor)
t=5-25s: AP: Arm: Accels inconsistent (×3-5)
AP: Arm: Gyros inconsistent (×3-5) ← EKF3 settling
t=25s: EKF healthy, ready to ARM
When EKF3 sources don’t match
If EK3_SRC1_POSZ=2 (rangefinder) but the rangefinder isn’t connected — you need either:
- Change
EK3_SRC1_POSZ=0(fallback to baro) — not accurate indoor - Bring up the rangefinder bridge (MAVROS publishes
/mavros/rangefinder/rangefinder→ ArduPilot consumes viaRNGFND1_TYPE=10)
Sensor sources matrix (by type)
| EK3_SRC1_* | Value | Source |
|---|---|---|
*_POSXY=0 |
None | no GPS |
*_POSXY=3 |
GPS | outdoor |
*_POSXY=5 |
ExternalNav | ROS 2 + SLAM publish via MAVROS |
*_VELXY=0 |
None | derive |
*_VELXY=5 |
OpticalFlow | PMW3901/CXOF |
*_VELXY=3 |
GPS | outdoor |
*_POSZ=2 |
Rangefinder | TF-Luna down |
*_POSZ=1 |
Baro | default outdoor |
*_POSZ=3 |
GPS | outdoor |
Sources
- ArduPilot wiki — EK3 estimator overview + parameters
- ArduPilot wiki — Non-GPS Navigation (indoor)
- ArduPilot discourse — EKF3 troubleshooting threads
- Source code
libraries/AP_NavEKF3/— implementation reference