external_nav mode takes a pose that another installed plugin publishes on a shared topic, such as a planar LiDAR SLAM from the World Engine extension, and sends it to the flight controller’s own estimator. The flight controller keeps doing state estimation, control and avoidance; the companion supplies one more position source and switches the EKF to it and away from it as tracking quality changes.
An optional obstacle feed turns a shared planar scan into OBSTACLE_DISTANCE, so ArduPilot’s proximity avoidance sees what the LiDAR sees.
External navigation and the source-set switch need ArduPilot. PX4 has no EKF source sets.
What you need
- A plugin that publishes the pose topic (default
plugin.world-engine.pose) and, for the obstacle feed, the scan topic (defaultplugin.world-engine.scan). The World Engine extension publishes both from a planar LiDAR whenatlas.nav_poseisalways. - A downward rangefinder or barometer on the flight controller for height. A planar pose has no height: the plugin echoes the flight controller’s own height back.
- An EKF origin at the take-off site. Without GPS, the flight controller should set it itself at boot (see EKF origin);
origin_llain the plugin config is the last-resort copy the plugin sends when the flight controller has none.
Configure
Set the mode and the two blocks in the per-drone plugin config (see Install and configure):Flight controller setup
With
gps_primary: true, make the fallback set the GPS set (EK3_SRCn_POSXY 3, VELXY 3) and keep the ExternalNav set as extnav_set. Leave AHRS_OPTIONS bit 4 off: the GPS sets the origin.
EKF origin
ArduPilot’s EKF aligns its yaw at boot with the magnetic declination it has at that moment. An origin that arrives after the alignment makes it look up the site’s declination and step the earth field. WithCOMPASS_AUTODEC on (the default) that step turns into a gyro bias, and the vehicle yaws, on the ground or in flight. ArduPilot also accepts an origin while armed.
Without GPS, let the flight controller set the origin itself before the alignment:
- ArduPilot 4.7 and later:
AHRS_OPTIONSbit 4 withAHRS_ORIGIN_LAT/LON/ALTat the take-off site, andEK3_MAG_EF_LIMabove 0. The flight controller reports “AHRS: using recorded origin” at boot. - Before 4.7:
COMPASS_AUTODEC 0withCOMPASS_DECset to the site’s declination.
SET_GPS_GLOBAL_ORIGIN (#48) from origin_lla only as a last resort, when all of these hold:
- the flight controller has reported no origin 5 s after it booted (a heartbeat after 3 s of silence is a new boot);
- the vehicle is disarmed;
gps_primaryis false.
COMPASS_AUTODEC on, the ekf_origin check blocks until the flight controller is set up as above and rebooted.
What reaches the flight controller
ODOMETRY (#331) on component 197, one message per measured pose, up to rate_hz:
-
frame_idMAV_FRAME_LOCAL_FRD,child_frame_idMAV_FRAME_BODY_FRD, the pair ArduPilot accepts. - x, y and yaw from the pose. A pose in a forward-left-up map frame is converted to forward-right-down.
-
z and vertical speed from the flight controller’s own
LOCAL_POSITION_NED; roll and pitch from itsATTITUDE. - Horizontal velocity from the pose difference over the last 100 ms, rotated into the body frame.
-
Pose noise and
qualityby tracking health: -
reset_counterincrements when a pose lands more than 0.5 m from where the last velocity predicts it (from the last pose after a gap over 0.5 s or a loss): a relocalisation, not motion, so steady flight at any speed never counts.
SET_GPS_GLOBAL_ORIGIN (#48) from origin_lla, only as a last resort.
OBSTACLE_DISTANCE (#330), from the latest scan:
frameMAV_FRAME_BODY_FRD,increment_f=360 / sectorsdegrees, sector 0 straight ahead, clockwise.sensor_typeMAV_DISTANCE_SENSOR_LASER,min_distance5 cm,max_distance1200 cm.- Each sector carries the nearest return in centimetres; a sector with no return carries
max_distance + 1.
Source-set switching
The plugin sendsMAV_CMD_SET_EKF_SOURCE_SET (42007) when the inputs call for a change. Nothing is commanded before its first decision, so the flight controller keeps its boot set until then.
degraded holds whichever set is active. You can also switch by hand from the cockpit’s navigation-source chip, which sends the agent’s ekfSourceSet command.
Pre-arm checks
The plugin reads the parameters
fc_params and ekf_origin need (VISO_TYPE, VISO_DELAY_MS, COMPASS_AUTODEC, AHRS_OPTIONS, AHRS_ORIGIN_LAT/LON, EK3_MAG_EF_LIM and the two source sets’ POSXY, YAW and VELXY) with PARAM_REQUEST_READ, every 10 s while any is missing and again after the flight controller reboots.
The median age of a pose when its ODOMETRY is sent (over the last 50 poses) is published as navigation.poseAgeMs; set VISO_DELAY_MS to it.
As in the other modes, the pre-arm card is advisory and does not stop the flight controller from arming.
Navigation state
The plugin publishesnav.state on the event bus. The agent re-serves it as the nav kind of its navigation routes, and every operator surface reads it for the navigation-source chip.
Fields a mode does not produce are
null.
Permissions
Next steps
Modes and fallback
All four modes and their checks.
World Engine
The planar LiDAR pose and scan source.