Skip to content

Comments

Overhaul WPOverlay (and add arc wp)#3668

Open
robertlong13 wants to merge 17 commits intoArduPilot:masterfrom
robertlong13:pr/overhaul-wpoverlay
Open

Overhaul WPOverlay (and add arc wp)#3668
robertlong13 wants to merge 17 commits intoArduPilot:masterfrom
robertlong13:pr/overhaul-wpoverlay

Conversation

@robertlong13
Copy link
Collaborator

Note

Sorry in advance for the wall of text. This is a big PR and it needs some explanation.

WPOverlay is due for an overhaul. It's mostly one giant method with deeply nested conditions, there's no separation between mission logic and rendering, and every command touches some inline shared state. There was a lot of complexity with the handling of jumps and splines (because it is a complex subject).

I've tried to work with it a couple times, but I was never able to get it to do what I wanted without subtly breaking something. Arc waypoints were recently introduced in ArduPilot, and I was dreading slotting them into the old structure. That was the final push to do this rewrite.

I've rewritten it as WPOverlay2 and, for now, it coexists as an optional alternative renderer to WPOverlay

Screenshots

comparison_1
Plane mission with figure-8s. A jump tag (T0) in orange, and a DO_LAND_START (LS) in orange.
The entire landing sequence is colored green


comparison_2
Copter spline tests


comparison_3
Copter splines with jumps


comparison_4
Massive, needlessly complicated plane mission with zero-turn loiters
(the plane-man's arc waypoint) and a converging return path system (blue lines)


comparison_5
Copter arc waypoint support


What this PR Adds

New rendering pipeline

The mission is now processed through a three-stage pipeline:

  1. MissionGraph: builds a directed graph of waypoints and edges from the mission item list, resolving jumps, loiter exits, and control flow into explicit graph edges.
  2. MissionSegmentizer: walks the graph and produces typed geometry segments (straight legs, spline curves, arc segments, loiter circles, etc.).
  3. WPOverlay2: consumes the segments and renders them on the map.

Each stage has a single responsibility, and adding a new command mostly means just a new method in MissionSegmentizer. The arc waypoint commit in this PR is an example (though I actually had a couple placeholder lines in place beforehand). Another example is ArduPilot's off-spec implementation of DO_GO_AROUND as a bookmark item (like DO_LAND_START), but there are too many problems with it to include in this PR.

Themeable styles

Line color, marker color, circle transparency, dash pattern, midline arrow: all of the rendering properties that were previously hard-coded are now exposed through MissionStyle. A built-in style editor lets you customize and save presets.

Screenshot 2026-02-13 162026

Bonus

MissionGraph as a reusable structure

The graph representation is a generally useful model of mission structure and could come in handy elsewhere: validation, statistics, distance calculations, etc.

Spline3

Spline2 is a line-by-line port of ArduPilot's spline nav controller, carrying velocity ramping, acceleration, time-stepping, and a reached_destination flag that are needed for the real-time controller but don't affect the curve shape when used purely for rendering. Spline3 keeps the Hermite math (same tangent logic, same overshoot clamp) and drops the simulation scaffolding, coming out at about half the code.

VehicleClass enum

We throw around a lot of checks against the firmware enum, and for plane this always means checking ArduPlane and Ateryx separately. In almost every case, it's being used for something like "is a reasonable takeoff altitude 2 meters or 20 meters", and my renderer was going to have similar "does vehicle stop and wait at a LOITER, or does it fly in circles around it" questions. Firmware doesn't feel like the right check for these questions. I've added a VehicleClass property (Copter, Plane, Rover) and used it in the new pipeline. Eventually I'd like VehicleClass to come from MAV_TYPE (cached like we currently cache firmware), falling back to the firmware check only when needed, but that's future work.

Fallback toggle

The old overlay is still reachable via Map Tool > "Use Legacy Overlay". If anyone doesn't like the new behavior, or if someone finds some edge-case bug I didn't handle, they can flip back.

Drive-by fixes

  • DO_LAND_START: fix altitude unit type
  • Plane: add DO_RETURN_PATH command
  • GMapMarkerWP: adjust label text centering
  • FlightPlanner: null-safe tcell value check
  • FlightPlanner: use TryParse in groupmarkeradd

Reviewing

The branch is structured for commit-by-commit review. Foundation and prerequisites are at the bottom of the stack (drive-by fixes, GMapRoute cleanup, marker/enum changes), the core pipeline and renderer are in the middle, and the integration commit that wires everything up is near the top. GMapRoute: fix formatting is a whitespace-only commit that normalizes mixed indentation before the arrow-modes commit builds on top of it.

I'll follow up with a second comment walking through the style editor concepts, which will also help explain some terms in the code for reviewers.

@robertlong13
Copy link
Collaborator Author

Style system guide

This is the follow-up to the main PR description, covering the style editor and the terminology behind it.

Overview

Every line and marker on the map is now styled through an ordered list of rules. When the renderer needs to draw a segment or place a marker, it walks the rule list top to bottom: each matching rule overrides the properties it sets, and anything it leaves blank is inherited from earlier rules. The first rule in the default preset is "Base defaults" and sets every property, so nothing is ever truly unset.

When multiple rules match, the one lower in the list wins (but only for properties it explicitly sets). Blank properties show through from earlier rules.

Markers and segments

The style system has two independent rule lists: one for markers (the waypoint pins and their radius circles) and one for segments (the lines between waypoints).

Marker rules

A marker rule filters on the command ID of the waypoint, using one of these predefined groups:

Filter Matches Default style
All Every marker Green pin, white circle (25% alpha)
Home The home location (uses synthetic ID 0, since home has no real MAV_CMD)
Loiters LOITER_UNLIM, LOITER_TIME, LOITER_TURNS, LOITER_TO_ALT Transparent circle
Landings LAND, VTOL_LAND, LAND_LOCAL Transparent circle
Bookmarks JUMP_TAG, DO_LAND_START, DO_RETURN_PATH_START (see below) Orange pin, transparent circle
RegionsOfInterest DO_SET_ROI, DO_SET_ROI_LOCATION Purple pin, transparent circle
SpecificIds A custom list of MAV_CMD numeric IDs (the RawCommandIds field appears in the property editor when this filter is selected)

Bookmarks are commands that mark the start of a sequence or label a waypoint for jump targeting, without being navigated to themselves. The aircraft executes the mission starting from the next command after the bookmark, not at the bookmark's position. For the two DO_*_START commands, these can optionally carry their own lat/lon, which the autopilot uses for closest-sequence selection (e.g. two DO_LAND_START commands at different locations, the autopilot picks the nearest one), but the bookmark location itself is never a nav target. If the bookmark has no location (0,0), the renderer places its marker at the next nav command's position.

To illustrate this, here's a screenshot of how one might use a series of DO_LAND_STARTs to avoid RTLing through a no-fly-zone.

Screenshot 2026-02-13 172913

Whichever yellow marker you are closest to when the RTL is triggered, determines which waypoint gets loaded. The orange dotted line points to the waypoint that you will fly to, not necessarily the route you'll take to get there, and at no point does the aircraft actually try to navigate to any of those yellow markers.

Note

To make this example image, I added a rule to color ID 189 (DO_LAND_START) as a yellow marker. The default preset colors all bookmarks the same orange, with only the marker text to distinguish. You can always adjust to your taste.

Marker style properties

Property Type Default Effect
MarkerType GMarkerGoogleType green Pin color (green, red, orange, purple, etc.)
CircleColor Color White (25% alpha) WP/loiter radius circle fill. Set to Transparent to hide the circle entirely.

Segment rules

A segment rule can filter on two things:

  • Kind — the geometric shape of the segment
  • Flags — the segment's role in the mission

Both are optional. A rule with no filters matches everything (that's how "Base defaults" works). A rule can require specific flags, exclude specific flags, or both. RequiredFlags means the segment must have all of the specified flags. ExcludedFlags means it must have none of them. A rule with both only matches segments that satisfy both conditions.

Segment flags

Flags describe why a segment exists, not what shape it is. A segment can have multiple flags at once (e.g. a jump edge into a landing sequence would have both Alternate and LandSequence).

Flag Meaning Default style
Alternate Jump paths, and any segment whose shape depends on a jump (e.g. a spline whose tangent changes because it jumps into the start from a different direction or exits to a different destination). thin, dashed
UnknownCommand The destination command isn't recognized. Always rendered as a straight line. Red
FromTakeoff The segment starts at a takeoff command. The line is drawn from home (or the preceding land point) to the first nav command. thin, dashed
FromBookmark A pointer line connecting a bookmark marker to the waypoint it's attached to (e.g. DO_LAND_START pointing at its target). Orange
ReturnPath The segment is part of a return path sequence (reachable from a DO_RETURN_PATH_START bookmark). Light sky blue
LandSequence The segment is part of a landing sequence (reachable from a DO_LAND_START bookmark). Yellow-green

ReturnPath and LandSequence are mutually exclusive on any given segment — a segment belongs to one sequence or the other, never both.

Segment kinds

The segment kind defines the shape that is drawn. Most users won't need to filter on this, but it's there if you want it. For example, you could hide LoiterArc segments and re-enable the circle on loiter markers to get closer to the old rendering style.

Kind What it draws
Straight Direct line between two waypoints
Spline Cubic Hermite curve (copter SPLINE_WAYPOINT)
LoiterArc Arc along a loiter circle where the vehicle enters or exits
ArcTurn Signed arc between two waypoints (NAV_ARC_WAYPOINT)

Segment style properties

Property Type Default Effect
StrokeColor Color Yellow Line color
StrokeWidth float 3 Line width in pixels
DashStyle DashStyle Solid Solid, Dash, Dot, DashDot, DashDotDot
ShowArrow bool true Directional arrow at the midpoint of the segment

The "Default style" columns in the tables above show what the built-in [Default] preset does for each filter/flag. Open the style editor to see how the rules are ordered and interact — reordering and previewing is the fastest way to understand the cascade.

Using the editor

Open the editor from Map Tool > Edit Style. The window stays on top so you can see the map while editing.

Layout

  • Preset dropdown at the top — switch between saved presets or the built-in default.
  • Two tabs: Segment Rules and Marker Rules. Each shows an ordered list on the left and a property editor on the right.
  • Add / Duplicate / Delete / Move Up / Move Down buttons to manage rules.
  • Preview applies your current edits to the map without saving.
  • OK saves and closes. Cancel reverts to whatever was active before you opened the editor.

Editing a rule

Click a rule in the list. The property editor on the right shows two groups:

  • Filter — Which segments or markers this rule targets. Leave filters blank to match everything.
  • Style — Which visual properties to override. Leave a property blank to inherit from earlier rules.

For marker rules, the RawCommandIds field only appears when Filter is set to SpecificIds.

Presets

  • [Default] is the built-in preset. You can edit it in the editor, but you can't save over it — you'll be prompted to Save As.
  • Save overwrites the currently selected user preset.
  • Save As creates a new preset file.
  • Preset files are stored in the Mission Planner user data directory as *.mpmissionstyle (JSON).
  • The active preset is remembered across sessions.

Sharing presets

Preset files are self-contained JSON. To share a style with someone else, send them the .mpmissionstyle file and have them drop it in their Mission Planner user data directory (typically Documents\Mission Planner). It will appear in the preset dropdown on next open.

@robertlong13
Copy link
Collaborator Author

Note the Android failures (failing on restore) are happening on master. Looks like the winusb testing branch got merged in and the packages got added into the xamarin project, not just to Windows.

@meee1 meee1 force-pushed the pr/overhaul-wpoverlay branch from 18b949b to b01c3bc Compare February 18, 2026 05:00
@robertlong13
Copy link
Collaborator Author

@meee1 I've rebased this onto my Mac CI fix PR, and it's all passing now.

I've done a bit of trying to torture-test the renderer too with splineF_ck.waypoints. No noticeable issue, but I don't have a low-spec machine to test on. You might want to test that one out on the HereLink for me (although it's possibly unreasonably hard of a test). All the missions for my screenshots are in here too btw. I meant to attach them earlier.

test_missions.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant