Skip to content

Missions

Lyrebird accepts a mission the way any MAVLink autopilot does: QGroundControl’s Plan view uploads a list of MISSION_ITEM_INT messages, and pressing Start flies it. What happens between those two moments — how the plan is stored, and how it is actually flown on an airframe with no MAVLink autopilot underneath — is what this page covers. Why QGC shows the Plan and Start controls at all is a separate, prerequisite trick; this page assumes that part already works and focuses on the mission itself.

  1. Enable lb_mav_0_enabled and lb_mav_0_allow_flight (both preferences, off by default — see MAVLink 2 Interface). The RC and QGC need to share a LAN; QGC listens on UDP 14550.
  2. Build a plan in QGC’s Plan view: waypoints, and optionally a leading Takeoff, a trailing Land or RTL, Camera (photo/video) items, Gimbal Pitch items, a Change Speed item, and a ROI Location item.
  3. Upload it. Lyrebird’s upload handshake (MavlinkMissionStore) requests each item, refuses the whole transfer if any item’s command is not one it understands, and — deliberately — stores every accepted item exactly as MAVLink sent it, in wire format. Translation to DJI’s shape happens only when the mission starts, on a copy, which is what lets a later download return precisely what was uploaded regardless of how it was flown.
  4. Arm and switch to Mission mode (or press QGC’s Start Mission). SET_MODE(AUTO.MISSION) and the MISSION_START that follows both route to whichever executor lb_mission_exec selects.
  5. Watch progress in QGC as usual: MISSION_CURRENT and MISSION_ITEM_REACHED are reported by both executors, though not with identical precision — see the comparison below.

MAVLink has one mission protocol; Lyrebird has two ways to fly what it uploads. Which one runs is a preference (lb_mission_exec, values onboard or dji_native), because a ground station has no MAVLink concept for picking one — there is nothing to negotiate over the wire.

dji_native (default)onboard
Who flies itDJI’s own wayline engine, on the flight controllerLyrebird’s app, sequencing legs through its PID waypoint controllers
Survives the phone losing focus / being backgroundedYes — the mission lives on the aircraft once pushedNo — the sequencing loop lives in the app
Take-off, land, RTLHandled by DJI, from the plan’s leading NAV_TAKEOFF altitude and trailing NAV_LAND/NAV_RETURN_TO_LAUNCHHandled item-by-item like any other plan item
Per-item heading (param4)Honoured, as a fixed wayline yawHonoured
Per-leg speed (DO_CHANGE_SPEED)Honoured, as a per-waypoint speedHonoured
Camera / gimbal actionsTranslated to wayline actions, triggered on reaching the waypoint they sit afterExecuted directly, in plan order
Region of interest (DO_SET_ROI*)Static target only — see belowFull continuous tracking
Progress reportingMISSION_CURRENT per waypoint reached; no per-item MISSION_ITEM_REACHEDExact MISSION_ITEM_REACHED per item
MAV_CMD_SET_CAMERA_MODENo wayline equivalent — skippedHonoured

Default is dji_native. A mission that keeps running on DJI’s own flight controller is not at the mercy of the app being backgrounded, the phone locking, or Android killing a background process mid-flight — the failure mode that matters most for an unattended or long mission. Switch to onboard for a plan that leans on something only it can do: a continuously-tracking ROI, or exact per-item arrival reporting.

Switching it. lb_mission_exec is an Android SharedPreferences value (file LyrebirdPrefs, package com.lyrebird.rc), the same way every other lb_* preference in this app is set — by hand in the field, via adb or the settings backup file, not through a settings screen or a MAVLink parameter. There is nothing to edit for the default.

Pushing a plan to DJI’s wayline engine means building a WPML mission (a KMZ file), not reusing MAVLink’s own item list, so each plan item becomes whichever WPML construct has the matching meaning:

MAVLink itemWayline construct
NAV_WAYPOINTA wpml:waypoint, at the item’s lat/lon/alt
NAV_TAKEOFF (leading item, altitude)Mission config securityTakeOffHeight — DJI climbs to it before flying to the first waypoint, on its own, as part of every wayline mission
NAV_LAND / NAV_RETURN_TO_LAUNCH (trailing item)Mission config finishAction: autoLand / goHome
param4 (heading)Waypoint yaw mode FIXED, holding that heading
DO_CHANGE_SPEEDThe waypoint’s own speed field, applying to the legs that follow it, exactly like the onboard executor’s running-speed variable
IMAGE_START_CAPTURE / VIDEO_START_CAPTURE / VIDEO_STOP_CAPTUREA takePhoto / startRecord / stopRecord wayline action, triggered on reaching the waypoint the item sits after
DO_GIMBAL_MANAGER_PITCHYAWA gimbalRotate wayline action, absolute pitch/yaw
DO_SET_ROI_LOCATION / DO_SET_ROI (location mode)Waypoint yaw mode towardPOI + gimbal heading mode towardPOI, both pointed at the ROI coordinate — see below
DO_SET_ROI_NONE / DO_SET_ROI (non-location mode)Clears the active ROI for waypoints that follow
SET_CAMERA_MODENo wayline equivalent — skipped

An action item with no later waypoint to attach to (one that sits after the last leg, before a trailing land) rides along with the last waypoint instead of being lost.

Region of interest, compiled rather than dropped

Section titled “Region of interest, compiled rather than dropped”

MAVLink’s ROI is modal: DO_SET_ROI_LOCATION puts the vehicle into “point at this coordinate” until a later DO_SET_ROI_NONE (or a non-location DO_SET_ROI) clears it — the same kind of state a ground station itself has to track across a plan. The native translator carries the same state across the item list while it builds waypoints, and every waypoint built while an ROI is active gets DJI’s own towardPOI yaw mode plus towardPOI gimbal heading mode, both referencing the same target coordinate.

That is a real, native DJI mechanism, not an approximation: towardPOI computes the aircraft’s heading and the gimbal’s pitch/yaw toward the target continuously while flying the leg, on the flight controller, the same way it would for a manually-built wayline mission in DJI’s own app — not a value calculated once and held fixed until the next waypoint. What it cannot do is track a moving target: a wayline mission is compiled once before flight, so an ROI that MAVLink would keep updating in real time can only be captured as wherever it was when the plan was built. A mission that needs a moving ROI has to use onboard, which re-reads the live ROI command like a normal autonomous action.

The onboard executor is the simpler of the two conceptually: a loop in the app walks the item list in order, flies each waypoint through Lyrebird’s own PID controllers (flyToWaypointNoseForward for param4 = NaN, flyToWaypointHoldHeading otherwise), and executes every non-waypoint item in place — camera, gimbal, ROI, speed change — before moving to the next leg. NAV_TAKEOFF blocks the sequencer until the aircraft is confirmed airborne before it lets the loop continue to the first waypoint, the same transition climbAfterTakeoff waits for elsewhere in the app — issuing a waypoint leg while DJI’s own take-off climb is still running would have the two fight each other for the sticks. Because the loop lives in the app, it reports an exact MISSION_CURRENT/MISSION_ITEM_REACHED for every single item, and it is the only executor that can track a live-updating ROI target — at the cost of the mission depending on the app staying alive and in the foreground for its whole duration.

Neither executor changes what a download reports: MavlinkMissionStore always answers with the verbatim uploaded items, regardless of which executor flew them or what it turned them into. Reading a plan back after flying it is the fastest way to confirm nothing about the stored mission changed — the translation lives entirely between MISSION_START and the aircraft’s motion.