CUP waypoints & tasks
v1.2.0 · SeeYou We-Fly

Interactive specification

The SeeYou CUP format, made legible.

A comma-separated file carrying two things at once: a list of waypoints, and a list of tasks built from them. Naviter maintains a real, versioned spec for it — but it stops exactly where observation zones get interesting. This reference covers both halves, and fills the gap from the implementation everyone actually interoperates with.

CSV, header-driven WGS-84, degrees + decimal minutes 22 waypoint styles Tasks & observation zones
01 Overview

One file, two halves

A .cup file holds a list of waypoints — one CSV row each, with a header row naming the columns — and, optionally, a list of tasks that reference those waypoints by name. A single literal line separates them:

file shape
name,code,country,lat,lon,elev,style,rwdir,rwlen,rwwidth,freq,desc
"Lesce","LJBL",SI,4621.379N,01410.467E,504.0m,5,144,1130.0m,,123.500,"Home Airfield"
…more waypoints…
-----Related Tasks-----
"300 km Triangle","Lesce","Sv Peter","Maier","Sv Peter","Lesce"
Options,TaskTime=03:00:00,WpDis=True
ObsZone=0,Style=2,R1=2500m,A1=180,Line=1

Most .cup files in circulation have no task section at all — they are pure waypoint databases, which is how site and turnpoint collections are distributed. A file that simply ends after the separator is valid and means "no tasks".

Encoding is UTF-8, or Windows-1252 for legacy files. Datum is WGS-84 throughout. Line endings are CRLF in practice; accept LF. There is no version marker inside the file — the format has only ever grown by adding optional trailing columns and optional key/value parameters, so a current reader parses a 2004-era file unchanged.

Where the spec stops. Naviter's CUP_file_format.md is authoritative for the waypoint half and for the syntax of the task half. It defines the observation-zone keys but not the shapes they produce, and never says which task column ObsZone=0 addresses. For both, this page follows XCSoar's TaskFileSeeYou.cpp — the behaviour instruments were written to interoperate with.

CUPX (.cupx) is two ZIP archives concatenated — pictures under pics/, then a POINTS.CUP whose pics column names them. The CUP grammar inside is identical; CUPX is purely packaging.

02 CSV grammar

The header row is load-bearing

CUP is CSV, in a permissive dialect. Fields are comma-separated; a field containing a comma must be double-quoted; embedded quotes are escaped by doubling them (""), per RFC 4180. Quoting is optional otherwise, and real files quote name and desc while leaving codes, coordinates and numerics bare.

Two rules turn the header from decoration into the thing you must actually parse:

RuleConsequence
Column order is arbitrarylat,lon,elev,name,code,country,style,… is a conforming header and must be honoured.
Trailing columns may be droppedAny column after style is optional and can be removed from both header and data.
The missing rwwidth. A very large body of files uses name,code,country,lat,lon,elev,style,rwdir,rwlen,freq,desc — eleven columns, no rwwidth. A positional reader written against the 14-column layout silently reads the frequency as a runway width on every one of them. The header is the only thing that tells the two apart.

Whitespace around fields is common and insignificant.   488.0m,   5   and 5103.117N   all appear in files shipped as reference test data. Trim every field before parsing it. Empty fields are legal and mean "not specified"; a row may end in a run of empty fields or a trailing comma.

Units

Numeric fields carry an optional unit suffix. When it is missing, metres are assumed. The decimal separator is always a point, and units may be mixed freely within one file.

FieldAccepted unitsExample
elevm (default), ft504.0m · 525ft
rwlen, rwwidthm (default), nm, ml1130.0m · 0.005NM · 0.01ml
R1, R2m (default), nm, ml35000m · 2.5nm
MaxAltm (default), ft1500m · 5000ft
03 Coordinates

Degrees and decimal minutes, fixed width

Latitude is 9 characters, longitude 10, each ending in a hemisphere letter. This is not decimal degrees, and it is not DMS — the digits after the point are thousandths of a minute.

FieldLayoutExampleDecodes to
LatitudeDDMM.mmm[N|S]5107.830N51° 07.830′ N = 51.1305°
LongitudeDDDMM.mmm[E|W]01410.467E014° 10.467′ E = 14.17445°
conversion
decimal = degrees + minutes / 60
if hemisphere is S or W: decimal = -decimal

The degrees field is zero-padded to a fixed width — 2 for latitude, 3 for longitude — and that is what makes the split unambiguous. Slice by position from the right: the two characters before the decimal point are whole minutes, everything before them is degrees.

Two ways to get this wrong. 4621.379N splits as 46 + 21.379, never 4621 + 379 — do not split on the decimal point. And .830 is 0.830 minutes (49.8 seconds), not 83 seconds; reading the decimals as seconds puts the waypoint about a kilometre out.

Three decimal minutes is roughly 1.85 m of latitude. That is the format's resolution — a round trip through CUP will not preserve more.

Try it · CUP coordinate → decimal
04 Field explorer

Every column and every key

Filter by name or meaning, or narrow by group. The waypoint columns are the CSV header keys; the task keys are the Options and ObsZone parameters below the separator.

Only name, lat and lon are practically required. name is doubly important: it must be unique, because it is the only key a task has for referencing a waypoint.

05 Waypoint styles

What kind of place this is

The style column is an integer 0–21. A value outside the table must be read as 0 (Unknown) rather than rejected — that is an explicit requirement of the spec, not a tolerance.

Styles 2–5 are the landable ones. They are the only styles for which rwdir, rwlen, rwwidth and freq carry meaning. Styles 20 and 21 — PG Take Off and PG Landing Zone — were added for free flight, and on those rwdir is re-used to declare the mid direction of the first take-off sector rather than a runway heading.
06 The task section

Routes built from names

Everything after -----Related Tasks----- describes tasks. A task is one task line, optionally followed by decoration lines that apply to it. The next task begins at the next line that is not a decoration line.

task line grammar
description, takeoff, 1st turnpoint, 2nd turnpoint, …, last turnpoint, landing

Every field after the description is a waypoint name that must match the name column of a waypoint defined above the separator, matched as an exact string. The number of points, and of tasks, is unlimited.

with and without a description
"1000km FAI Triangle","0LESCE","Sv Peter","1K MAIER","1K ZELTW","Sv Peter","0LESCE"
,"0LESCE","0Start","750 Huje","750 Brenner","0Start","0LESCE",

The description is optional; when it is empty the line simply begins with a comma, and the reading application infers the task type. That leading " or , is exactly how a reader recognises a task line — everything else in the section is decoration belonging to the task above it.

The first and last points are the takeoff and the landing — not the start and the finish. On the usual airfield task both are the home field, and the real start is the second point. Free-flight producers routinely ignore this and write the start first; see §08.

Decoration lines

LineMeaning
Options,Key=Value,…Task-wide settings — timing, distance basis, tolerances. One per task.
ObsZone=<i>,Key=Value,…Observation zone for task point i. 0 = start.
Point=<i>,<waypoint record>Defines a task point inline, for points with no waypoint above the separator. The payload is a full waypoint row.
STARTS=a,b,cAlternative start points, all defined as waypoints. They share one observation zone — the ObsZone=0 line applies to whichever start is used.
inline point definition
Point=1,"Point_3",PNT_3,,4627.136N,01412.856E,0.0m,1,,,,,,,

Point=1 is documented as "the first turnpoint (after takeoff)" — the index counts task-line columns with the takeoff at 0, so Point=1 is the third comma-separated field. Note this is offset by one from ObsZone= numbering; the two schemes are not interchangeable.

The Options line

options
Options,NoStart=12:34:56,TaskTime=01:45:12,WpDis=False,NearDis=0.7km,NearAlt=300.0m

WpDis is the most consequential key in the file: it decides whether this is a racing task (True — measure waypoint to waypoint) or an assigned-area task (False — measure through the actual fixes), and that in turn changes how the observation-zone parameters are interpreted. Every key is optional; an absent key means the application default. The full list is in the field explorer.

CUP has no speed section. There is no SSS/ESS concept and no start-gate interval beyond NoStart. A task imported from CUP is route + goal; anything richer has to come from another format.
07 Observation zones

From parameters to shapes

An ObsZone= line gives a point's zone as key/value pairs. Style names the orientation of the zone, not its shape — the shape comes from the combination of R1, A1, R2, A2 and Line.

StyleThe zone's bisector points…
0Fixed — along the bearing given in A12
1Symmetrical — bisecting the inbound and outbound legs
2To next point
3To previous point
4To start point

An unknown or unparsable Style falls back to 1 (Symmetrical). Defaults for absent keys: R1 = 500 m, R2 = 200 m, Line = false.

Two halves to internalise. A1 is a half-angle measured either side of the bisector — so a full cylinder is written A1=180, never A1=360. And on a line zone, R1 is a half-width — a 5 km start gate is R1=2500m,Line=1. Both mistakes fail silently and produce a plausible-looking wrong task.

Try it

Move the controls and watch the zone. The ObsZone line below is what a file would carry for the shape on screen; the bisector points up.

Zone previewR1 = 3000 m
Parameters
3000 m
45°
off

The full mapping

Naviter defines the keys; the geometry below is XCSoar's, and is the de-facto standard.

ConditionResulting zone
No ObsZone line for the pointFAI quadrant — 90°, 3 km
Line=1 on the start or finishLine of total width 2 × R1
A1 ≈ 180Cylinder of radius R1
Racing, Style=0Cylinder of radius R1 — fixed sectors are not representable
Racing, Style=1, R1 ≥ 3000 and 2 × A1 ≈ 90°FAI quadrant
Racing, Style=1, otherwiseSymmetric circular sector, radius R1, total angle 2 × A1
Area task, intermediate, R2 > 0 and A2 ≈ 0Annular sector between R2 and R1
Area task, intermediate, otherwiseSector of radius R1 spanning bisector ± A1
Anything elseCylinder of radius R1

Three parameter combinations are additionally recognised by value, within ±2 units, as named zones:

A1R1A2R2Zone
45°10 000 m180°500 mKeyhole
45°20 000 m180°500 mBGA fixed course
90°10 000 m180°500 mBGA enhanced option
Two de-facto keys. MaxAlt= (start-height ceiling, meaningful only on ObsZone=0) and Reduce= (zone may be auto-shrunk) are written and read by real tools but appear nowhere in the Naviter document. Skip keys you do not know — never fail a file over one.
08 Zone indexing

The format's sharpest edge

ObsZone=0 is the start, and the start is the second waypoint on the task line — because the first is the takeoff.

index mapping
task line:  desc , takeoff , start , tp1 , tp2 , … , finish , landing
column:      0        1        2      3     4          n-1       n
ObsZone:                       0      1     2          n-3      —

ObsZone=i addresses task-line column i + 2. Neither the takeoff nor the landing can carry a zone. This is what XCSoar implements, and it is consistent with the Naviter document's own "0 = Start".

It bites in both directions:

  • A reader that maps ObsZone=i onto the i-th waypoint after the description applies every radius one point too early — the start's gate width lands on the takeoff, and so on down the task.
  • Conversely, a great many free-flight files carry no takeoff column at all and begin the list at the start point. On those, index i really does address column i + 1, and the spec-conformant reader is the one that is wrong.

There is no flag distinguishing the two. The usable heuristic is to compare the highest ObsZone index against the number of waypoint columns C: a spec-conformant file tops out at C − 3, while a takeoff-less file reaches C − 2 or C − 1. When a file carries no zones at all, the question is moot.

The inspector below reports this. Paste a task and it will tell you which column each ObsZone line lands on under the spec reading, and flag an index that cannot be spec-conformant.
09 File inspector

Paste CUP, read it back in English

Edit the file on the left. Every line is parsed live — the header row drives the column mapping, coordinates are converted to decimal, styles and units are spelled out, task columns are labelled with their role, and each observation zone is resolved to a shape. Nothing is uploaded; it all runs in the page.

CUP source · editable
Parsed live
10 Parsing gotchas

Be permissive on input, strict on output

  • Zone indexing. The takeoff offset is the biggest source of disagreement between implementations. Detect it; do not assume it.
  • Halves. A1 is a half-angle and R1 on a line is a half-width. Both fail silently when doubled or halved.
  • Header-driven, not position-driven. Column order is arbitrary and trailing columns are droppable. The 11-column no-rwwidth layout is widespread enough to count as a second canonical order.
  • Unescaped quotes. Files exist whose description contains a bare ""Rabbit holes, 20" ditch south of rwy". Strict RFC 4180 parsing throws; be lenient on the trailing free-text field.
  • Names are the only key. Matching is exact and case-sensitive in practice. Preserve names byte-for-byte through a round trip — do not trim, re-case or truncate a name a task might reference.
  • Encoding. Legacy files are Windows-1252. A UTF-8 decode of one mangles accented site names rather than failing, so sniff for invalid sequences and fall back.
  • Unknown keys and columns. Both Options and ObsZone carry vendor extensions. Skip what you do not recognise; never fail the file.
  • Units default to metres when the suffix is absent, and may be mixed within one file. Never assume the file-wide unit from the first row.
  • An empty task section is valid. -----Related Tasks----- as the last line means "no tasks", not "malformed".
  • Style is clamped, not rejected. An out-of-range style must be read as 0 (Unknown).
11 Sources

What this reconciles