Loading...
Current Version 1 — April 2026

DMD HUB GPX Extension

Pre-rendered route data for instant GPX loading across all platforms

Namespace
https://dmdnavigation.com/ns/gpx/1

Overview

The DMD HUB GPX Extension (dmd: namespace) embeds pre-computed route data directly inside standard GPX 1.1 files. This eliminates the need for routing API calls, on-device surface extraction, and elevation computation when loading a file — routes display instantly.

The extension is placed inside the <extensions> block of <rte> or <trk> elements and is fully compliant with the GPX 1.1 specification. Applications that don't understand the dmd: namespace will simply ignore it.

Benefits

Instant Route Loading

No routing API calls needed. The full routed geometry is embedded in the file, ready to render immediately.

Turn-by-Turn Instructions

Navigation instructions are pre-computed and stored with road names, eliminating on-device processing.

Surface Classification

Paved/unpaved segments with OSM surface and highway tags — no map tile extraction required.

Integrity Verification

SHA-256 hash ensures data validity. If the file is edited externally, apps know to re-compute.

Schema Structure

Add the namespace declaration to your <gpx> root element:

<gpx version="1.1" creator="YourApp"
     xmlns="http://www.topografix.com/GPX/1/1"
     xmlns:dmd="https://dmdnavigation.com/ns/gpx/1">

The extension is placed inside <rte><extensions> or <trk><extensions>:

<rte>
  <name>My Route</name>
  <extensions>
    <dmd:PreRendered version="1" hash="sha256:abc123..." profile="road-fast-all">
      <dmd:CalculatedRoute>...</dmd:CalculatedRoute>
      <dmd:Instructions>...</dmd:Instructions>
      <dmd:Surface>...</dmd:Surface>
      <dmd:Warnings>...</dmd:Warnings>
      <dmd:Regulations>...</dmd:Regulations>
      <dmd:Stats .../>
    </dmd:PreRendered>
  </extensions>
  <rtept lat="..." lon="..."></rtept>
</rte>

Element Reference

<dmd:PreRendered>

Root container for all pre-rendered data.

AttributeTypeDescription
versionIntegerSchema version (currently 1). If a reader encounters a higher version, it should fall back to normal routing.
hashStringIntegrity hash. Format: sha256:<16 hex chars>
profileStringThe routing profile used to generate this data (e.g., road-fast-all, offroad-medium)

<dmd:CalculatedRoute>

Routes only (tracks already have <trkpt> geometry). Contains the full routed geometry as a semicolon-separated text node:

<dmd:CalculatedRoute>48.123456,16.456789,312.5;48.123470,16.456900,313.1;...</dmd:CalculatedRoute>

Each point is lat,lon,ele with 6 decimal places for coordinates and 1 for elevation (meters). Whitespace between points is allowed and should be stripped before parsing.

<dmd:Instructions>

Turn-by-turn navigation instructions enriched with OSM-derived data so consumers don't need offline tile lookups to render rich navigation UI:

<dmd:Instructions>
  <dmd:I lat="48.123" lon="16.456" type="LEFT" dist="1250"
         road="Hauptstrasse" ref="B17" lanes="left|through" stop="1" maxspeed="50"/>
  <dmd:I lat="48.200" lon="16.500" type="ROUNDABOUT" dist="3400"
         exit="3" rba="42.7" maxspeed="50"/>
  <dmd:I lat="48.250" lon="16.520" type="EXIT_RIGHT" dist="4200"
         jref="21A" dest="Wien Mitte" destref="A4" lanes="none|none|right" maxspeed="100"/>
  <dmd:I lat="48.300" lon="16.600" type="DESTINATION" dist="5200"/>
</dmd:Instructions>
AttributeDescription
lat, lonInstruction point coordinates (required)
typeInstruction type enum (see below) (required)
distCumulative distance from route start in meters (required)
roadOSM name tag of the road at this instruction (optional)
refOSM ref tag — road reference number, e.g. "A1", "M25" (optional)
destOSM destination tag — destination sign text, e.g. "Wien, Salzburg" (optional)
destrefOSM destination:ref tag — destination road codes, e.g. "A1;IC2" (optional)
jrefOSM junction:ref tag — highway exit number, e.g. "21A" (optional). Most useful on EXIT_RIGHT/EXIT_LEFT.
exitRoundabout exit number (1-based positive integer). Only present when type=ROUNDABOUT.
rbaRoundabout turn angle in degrees, signed: positive = right turn, negative = left turn (relative to entry direction). Computed from the route polyline. Only meaningful for type=ROUNDABOUT. Consumers can use it to draw an exit-direction icon that matches the geometry instead of a generic exit-number layout.
lanesOSM turn:lanes tokens, pipe-separated (e.g. "left|through|through;right"). Multi-direction lanes use ; as separator. Empty/unmarked lanes are written as "none" so the lane count round-trips. The producer is direction-aware: it prefers turn:lanes:forward/:backward based on the rider's bearing on the way.
stop"1" if a highway=stop node sits within ~35m of the instruction. Absent otherwise. Useful for showing a STOP badge on the navigation banner.
gw"1" if a highway=give_way node sits within ~35m. Absent otherwise. Same use case as stop.
pass"1" for synthesized passthrough instructions — emitted at multi-way junctions / motorway entries where the router gave a "continue" but lane / destination data is worth surfacing. Absent on real turn instructions.
maxspeedPosted speed limit on the road at this instruction, normalized to integer km/h. Producers convert before writing: bare numbers and "N km/h" stay as-is, "N mph" becomes round(N × 1.609344), "walk" becomes 7. Values that cannot be resolved confidently are omitted — including "none" (explicit no-limit) and country-implicit tags like "RU:urban" or "RO:trunk". Consumers should treat absence as "unknown" and either fall back to a local lookup or keep the device's last-known limit.

Backward compatibility: all attributes after dist are optional. Consumers reading older files (without exit/rba/destref/stop/gw/lanes/pass/maxspeed) should treat missing attributes as absent — no defaults beyond what the type implies.

Roundabout note: if exit is missing on a ROUNDABOUT instruction (legacy file), consumers should fall back to displaying a generic "Take exit" without a number rather than guessing.

Instruction Types:

LEFT
RIGHT
SLIGHT_LEFT
SLIGHT_RIGHT
SHARP_LEFT
SHARP_RIGHT
KEEP_LEFT
KEEP_RIGHT
U_TURN
ROUNDABOUT
STRAIGHT
EXIT_RIGHT
EXIT_LEFT
DESTINATION

<dmd:Surface>

Paved/unpaved classification segments:

<dmd:Surface>
  <dmd:S s="0" e="142" sf="asphalt" hw="secondary" p="1"/>
  <dmd:S s="143" e="380" sf="gravel" hw="track" p="0"/>
</dmd:Surface>
AttributeDescription
sStart point index (into CalculatedRoute or trkpt sequence)
eEnd point index (inclusive)
sfOSM surface tag value (e.g., asphalt, gravel, dirt)
hwOSM highway tag value (e.g., secondary, track, path)
pPaved flag: 1 = paved, 0 = unpaved

<dmd:Timing>

Per-segment travel time breakdown. Enables point-accurate ETA calculations to any waypoint along the route. The sum of all segment t values equals <dmd:Stats>'s time attribute.

<dmd:Timing>
  <dmd:T s="0" e="142" t="310" spd="52.1"/>
  <dmd:T s="143" e="380" t="480" spd="31.8"/>
</dmd:Timing>
AttributeUnitDescription
sindexStart point index (inclusive). Same index space as <dmd:Surface>
eindexEnd point index (inclusive)
tsecondsSegment travel time
spdkm/hSegment average speed (optional, informational)

<dmd:Warnings>

Pre-computed hazard warnings along the route:

<dmd:Warnings>
  <dmd:W type="SLOPE" lat="48.5" lon="16.8" dist="12500" val="18.5"/>
  <dmd:W type="UNPAVED" lat="48.6" lon="16.9" dist="15000" len="3200"/>
</dmd:Warnings>
AttributeDescription
typeSLOPE (gradient ≥ 15%) or UNPAVED (unpaved run ≥ 250m)
lat, lonWarning location
distCumulative distance from route start (meters)
valSlope percentage (SLOPE type only)
lenUnpaved section length in meters (UNPAVED type only)

<dmd:Regulations>

Regulatory road features encountered along the full route polyline — not just at turn instructions. Lets consumers (e.g., DMD2PlayGround's navigation card and SpeedLimitDetector) drive stop/yield heads-ups and a route-aware speed-limit display without falling back to offline OSM tile lookups.

<dmd:Regulations>
  <dmd:R type="MAXSPEED" lat="48.123" lon="16.456" dist="0"    val="50"/>
  <dmd:R type="STOP"     lat="48.130" lon="16.459" dist="820"/>
  <dmd:R type="MAXSPEED" lat="48.140" lon="16.470" dist="1480" val="90"/>
  <dmd:R type="GIVE_WAY" lat="48.150" lon="16.480" dist="2310"/>
</dmd:Regulations>
AttributeDescription
typeSTOP (highway=stop node), GIVE_WAY (highway=give_way node), or MAXSPEED (point where the posted speed limit changes)
lat, lonFeature location, snapped to the nearest polyline point
distCumulative distance from route start (meters). Entries are sorted by dist ascending.
valMAXSPEED only — integer km/h. Same normalization rules as dmd:I@maxspeed (mph → km/h, "walk" → 7, country-implicit tags omitted entirely).
Consumer rules
  • STOP / GIVE_WAY: independent of dmd:I@stop/@gw. Those flag stops at the turn; this section flags stops anywhere along the polyline, including between turns. Both should be surfaced.
  • MAXSPEED: the active limit at distance D is the entry with the largest dist ≤ D. Producers SHOULD emit a dist=0 entry when the route starts inside a speed-limited area so consumers don't display "unknown" until the first transition.
  • Failure-safe: the section is optional. Consumers that don't find dmd:Regulations should fall back to whatever local lookup they had before.

<dmd:Stats>

Aggregate statistics (self-closing element with attributes):

<dmd:Stats dist="185420" gain="2340" loss="2180" eleMin="120" eleMax="1845"
           time="14400" paved="72" maxSlope="22.5" minSlope="-18.3"/>
AttributeUnitDescription
distmetersTotal route distance
gainmetersTotal elevation gain
lossmetersTotal elevation loss
eleMinmetersMinimum elevation
eleMaxmetersMaximum elevation
timesecondsEstimated travel time
paved%Percentage of route that is paved (0–100)
maxSlope%Maximum uphill slope
minSlope%Maximum downhill slope (negative value)

Travel Time & ETAs

The extension provides travel-time data at two levels of granularity:

  • Aggregate<dmd:Stats>'s time attribute gives the total estimated travel time for the route/track. Sufficient for "ETA to end of route" displays.
  • Per-segment<dmd:Timing> breaks the total time into contiguous runs so a reader can compute the ETA to any arbitrary point along the route (tap-to-info, next-waypoint, etc.) without assuming a flat average speed.
Reader Fallback Order
  1. If <dmd:Timing> is present and indices are valid — sum segment times from the user's current index to the target index.
  2. Else, if <dmd:Stats>'s time is present — distribute proportionally by distance fraction.
  3. Else, fall back to a profile-based speed model (e.g., the profile specified on <dmd:PreRendered>) or the device's observed average speed.

Integrity Hash

The hash ensures that pre-rendered data matches the current route waypoints. If a file is edited in another application (waypoints moved/added/removed), the hash will not match and readers should discard the pre-rendered data and re-route.

Algorithm
  1. Build a canonical string from the source waypoints:
    lat1,lon1;lat2,lon2;...;latN,lonN;profile=road-fast-all
    • For <rte>: use all <rtept> coordinates
    • For <trk>: use all <trkpt> coordinates
    • Coordinates truncated to 6 decimal places
    • Append ;profile= followed by the routing profile string
  2. Compute SHA-256 of the canonical string (UTF-8 encoded)
  3. Take the first 16 hex characters of the hash
  4. Store as: sha256:<16 hex chars>
Reader Behavior
ScenarioAction
Hash matchesUse pre-rendered data directly. No routing needed.
Hash mismatchDiscard pre-rendered data. Route via normal method (DMD Router, etc.)
No hash presentTreat as no pre-rendered data.
Unknown versionFall back to normal routing.

Implementation Guide

For Readers (GPX Viewers)

  1. Parse the GPX file normally (tracks, routes, waypoints)
  2. For each <rte> or <trk>, check for <dmd:PreRendered> in <extensions>
  3. If found, compute the expected hash from the source coordinates + profile
  4. If hash matches: use <dmd:CalculatedRoute> for display geometry, <dmd:Stats> for metadata, etc.
  5. If hash doesn't match: ignore the extension and route normally

For Writers (Route Planners / Navigation Apps)

  1. After computing a route (via DMD Router or your routing engine), collect:
    • Full routed geometry (the dense point array)
    • Surface/highway classification per segment
    • Turn instructions (if your router provides them)
    • Elevation statistics
  2. Compute the hash from the source waypoints + routing profile
  3. Write the <dmd:PreRendered> block inside <extensions>
  4. Continue writing normal <rtept> / <trkpt> elements as usual

Full Example

<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.1" creator="DMD HUB GPX Planner"
     xmlns="http://www.topografix.com/GPX/1/1"
     xmlns:dmd="https://dmdnavigation.com/ns/gpx/1">
  <metadata>
    <name>Mountain Loop</name>
  </metadata>
  <rte>
    <name>Route 1</name>
    <extensions>
      <dmd:PreRendered version="1" hash="sha256:f28a213d70082096" profile="offroad-medium">
        <dmd:CalculatedRoute>41.651310,-8.249183,114.5;41.651327,-8.249231,114.3;41.650449,-8.249211,110.8;41.649858,-8.247084,127.0;41.648490,-8.245994,134.5</dmd:CalculatedRoute>
        <dmd:Instructions>
          <dmd:I lat="41.651296" lon="-8.250214" type="SHARP_LEFT" dist="91" road="Rua das Camélias" maxspeed="50"/>
          <dmd:I lat="41.648015" lon="-8.245977" type="SLIGHT_RIGHT" dist="658" maxspeed="40"/>
          <dmd:I lat="41.632462" lon="-8.244647" type="DESTINATION" dist="3980"/>
        </dmd:Instructions>
        <dmd:Surface>
          <dmd:S s="0" e="2" sf="asphalt" hw="tertiary" p="1"/>
          <dmd:S s="3" e="4" sf="" hw="track" p="0"/>
        </dmd:Surface>
        <dmd:Timing>
          <dmd:T s="0" e="2" t="138" spd="52.5"/>
          <dmd:T s="3" e="4" t="220" spd="38.0"/>
        </dmd:Timing>
        <dmd:Warnings>
          <dmd:W type="SLOPE" lat="41.651274" lon="-8.250075" dist="79" val="15.4"/>
          <dmd:W type="UNPAVED" lat="41.648490" lon="-8.245994" dist="658" len="2364"/>
        </dmd:Warnings>
        <dmd:Regulations>
          <dmd:R type="MAXSPEED" lat="41.651310" lon="-8.249183" dist="0"   val="50"/>
          <dmd:R type="STOP"     lat="41.650449" lon="-8.249211" dist="142"/>
          <dmd:R type="MAXSPEED" lat="41.648490" lon="-8.245994" dist="658" val="40"/>
        </dmd:Regulations>
        <dmd:Stats dist="3980" gain="396" loss="48" eleMin="105.0" eleMax="465.0"
                 time="358" paved="51" maxSlope="33.8" minSlope="-24.9"/>
      </dmd:PreRendered>
    </extensions>
    <rtept lat="41.65131" lon="-8.249183"></rtept>
    <rtept lat="41.632462" lon="-8.244647"></rtept>
  </rte>
</gpx>

Compatibility

The extension is currently supported by:

  • DMD HUB GPX Planner (web) — writer + reader
  • DMD HUB GPX Browser (web) — reader
  • DMD HUB iOS App — reader
  • DMD2 Android App — writer + reader

Any GPX application can add support by following the implementation guide above. The extension does not interfere with standard GPX processing — non-supporting apps will simply ignore the dmd: namespace elements.

Top