OpenDroneKit

QGroundControl .plan file format

A .plan file is JSON: one mission, its geofence and its rally points. This page walks through every key, shows a file OpenDroneKit wrote, and flags the values that decide whether QGroundControl treats it as an ArduPilot or a PX4 mission.

Updated 2026-10-02Exporter: mission/exporters.py · examples written at 0ae10e4

Example files written by OpenDroneKit

opendronekit-example-grid.plan27 waypoints · 47.2 KB
sha256 2b084be9…e5f1
aukerman-grid.planAukerman Park grid · 253.8 KB
sha256 be023b45…6987

What is a QGC .plan file?

A QGroundControl .plan file is a JSON document holding a mission, a geofence and rally points. Its top-level keys are fileType ("Plan"), version (1), groundStation, mission, geoFence and rallyPoints. The mission holds a list of items: a SimpleItem is one MAVLink mission item; ComplexItems such as Survey, CorridorScan and StructureScan are QGroundControl’s own generators, expanded into simple items on upload.

QGroundControl reads and writes .plan files natively. ArduPilot’s Mission Planner uses the plain-text .waypoints format instead, which OpenDroneKit also writes.

Every key

KeyMeaning (QGC docs / MAVLink)What OpenDroneKit writes
fileType, version, groundStation"Plan", 1, the writer's name"Plan", 1, "OpenDroneKit"
mission.firmwareTypeA MAV_AUTOPILOT value: 3 = ArduPilot, 12 = PX412 (PX4), though the code intends ArduPilot; see known issues
mission.vehicleTypeA MAV_TYPE value: 2 = quadrotor2
mission.cruiseSpeed / hoverSpeedQGC's speed for time estimates (fixed wing / multirotor)Planned speed in both
mission.globalPlanAltitudeModeAltitude reference for the plan1 relative to home; 2 AMSL when the plan has a terrain model
mission.plannedHomePosition[lat, lon, AMSL alt]First item's position
mission.items[]SimpleItem: command (MAV_CMD), frame (MAV_FRAME), params[7], Altitude, AltitudeMode, autoContinue, doJumpIdOne SimpleItem per MAVLink item, same order as the .waypoints file without its home row
geoFence.polygons[]{inclusion, polygon: [[lat, lon]…], version}Inclusion fence 5 m outside the drawn area; one exclusion polygon per no-fly zone
geoFence.circlesCircular fences[]
rallyPoints.points[[lat, lon, alt]…]The plan's rally / emergency landing points

Example file

Written by OpenDroneKit’s exporter for a 90 x 60 m rectangle centred on 41.30420 N, 81.75200 W (Aukerman Park, Ohio): grid template, 55 m above take-off, 8 m/s, 27 waypoints. The first lines:

{
    "fileType": "Plan",
    "geoFence": {
        "circles": [],
        "polygons": [
            {
                "inclusion": true,
                "polygon": [
                    [
                        41.30388497139586,
                        -81.7525985094454
                    ],
                    [
                        41.30388497139586,
                        -81.75140149055458
                    ],
                    [
                        41.30451502860414,
                        -81.75140149055458
                    ],
                    [
                        41.30451502860414,
                        -81.7525985094454
                    ]
                ],
                "version": 1
            }
        ],
        "version": 2
    },
    "groundStation": "OpenDroneKit",
    "mission": {
        "cruiseSpeed": 8.0,
        "firmwareType": 12,
        "globalPlanAltitudeMode": 1,
        "hoverSpeed": 8.0,
        "items": [
            {
                "AMSLAltAboveTerrain": null,
                "Altitude": 55.0,

The full Aukerman Park files in the table above come from the run shown on the homepage: the public OpenDroneMap survey, 152 waypoints at 55 m, generated 2026-09-29. Every file’s SHA-256 is listed so a copy can be checked.

What OpenDroneKit writes

OpenDroneKit builds the full MAVLink item stream first (build_mission_items): take-off, a DO_CHANGE_SPEED with the planned speed, then for each viewpoint a DO_MOUNT_CONTROL for gimbal pitch, an optional CONDITION_YAW, the NAV_WAYPOINT (or NAV_LOITER_TIME for a hold) and a DO_DIGICAM_CONTROL to take the photo, ending with return-to-launch. The .plan carries exactly that stream as SimpleItems, so capture behaviour survives, not just the path.

The inclusion fence is offset 5 m outward because ArduPilot breaches a polygon fence within its FENCE_MARGIN (2 m by default) and a mapping grid flies its outer lines on the area’s edge.

Known issues

Checked against the format’s reference and the exporter code on 2026-10-02. Listed here rather than hidden, so you can correct a file before you fly it.

  • firmwareType is 12, which is PX4. The exporter’s default and its docstring say “ArduPilot multirotor (firmware 12, vehicle 2)”, but in MAVLink’s MAV_AUTOPILOT enum ArduPilot is 3 and 12 is PX4. QGroundControl may therefore open the file as a PX4 mission. Present on both branches; change the value to 3 for ArduPilot until it is fixed.

Public main versus the development branch

The example files were written by the development branch (0ae10e4), which is ahead of the public main you get from a source install (1ef6351). On main:

  • Public main concatenates every no-fly zone into one exclusion polygon (two rectangles become one self-intersecting shape); the integration branch writes one polygon per zone.
  • Public main writes the drawn area itself as the inclusion fence; the integration branch offsets it 5 m outward so a grid's outer lines do not breach ArduPilot's 2 m FENCE_MARGIN.
  • Public main reads cruiseSpeed/hoverSpeed from a key the planner does not set, so they fall back to 12 and 5 m/s; it has no DO_CHANGE_SPEED item and no AMSL mode (AltitudeMode always 1).

How do I import it into QGroundControl?

  1. In QGroundControl, open Plan view.
  2. Use the Plan view’s file menu to open the .plan file.
  3. Check the vehicle firmware shown for the plan, the home position and the fence, then upload.

Pitfalls

  • A firmwareType that does not match the connected vehicle makes QGroundControl warn or convert commands on upload.
  • Fence polygons are [lat, lon] pairs while GeoJSON is [lon, lat]; swapping them puts the fence on the other side of the world.
  • QGroundControl recalculates ComplexItems (Survey, StructureScan) on load; a file with only SimpleItems is flown exactly as written.

References

Other formats: .waypoints · DJI WPML · Litchi CSV. Missions come from the mission templates; see mission planning.