The airport JSON file must be in “assets/airports”; the filename should be icao.json
where icao
is the lowercase four-letter ICAO airport identifier, such as ksfo
or kmsp
. If this is a new airport, an entry must also be added to airportLoadList.json in alphabetical order. See the airport load list documentation for information on the correct structure to use.
Note: The code block shown below is an abbreviated version of ksea.json.
{
"airac": 1801,
"radio": {
"twr": "Seatle Tower",
"app": "Seattle Approach",
"dep": "Seattle Departure"
},
"icao": "KSEA",
"iata": "SEA",
"magnetic_north": 16,
"ctr_radius": 110,
"ctr_ceiling": 15000,
"initial_alt": 15000,
"position": ["N47d26.99m0", "W122d18.71m0", "432ft"],
"rangeRings": {
"enabled": true,
"center": ["N47d26.99m0", "W122d18.71m0"],
"radius_nm": 5.0,
},
"has_terrain": true,
"wind": {
"angle": 150,
"speed": 9
},
"arrivalRunway": "16R",
"departureRunway": "16L",
"defaultMaps": ["Base Map"],
"airspace": [
{
"floor": 0,
"ceiling": 150,
"airspace_class": "B",
"poly": [
["N47.83333330", "W121.69999940"],
["N47.95335007", "W121.97603665"],
["N48.30000000", "W121.96666670"],
["N48.30000000", "W122.30000000"],
["N48.20000000", "W122.45000000"]
]
}
],
"fixes": {
"_NEZUG070010": ["N47d34.80m0", "W122d03.84m0"],
"_NEZUG070PAE139": ["N47d34.77m0", "W122d05.11m0"],
"_NICHY250SEA230": ["N47d19.92m0", "W122d42.78m0"],
"_OLM161026": ["N46d32.31m0", "W122d54.11m0"],
"_SEA161002": ["N47d24.12m0", "W122d18.58m0"],
"_SEA341004": ["N47d30.12m0", "W122d18.58m0"],
"_SUMMA326017": ["N46d53.20m0", "W122d07.08m0"],
"AAYRR": ["N46d38.81m0", "W123d43.34m0"],
"BOANE": ["N47d59.10m0", "W122d43.52m0"],
"EUG" : ["N44d07.25m0", "W123d13.37m0", "Eugene"],
"FEPOT": ["N47d04.85m0", "W123d13.13m0"],
"GEG" : ["N47d33.90m0", "W117d37.61m0"],
"KRUZR": ["N48d04.65m0", "W120d34.68m0", "cruiser"],
"ONSET": ["N48d57.48m0", "W118d00.00m0"],
"PAE" : ["N47d55.19m0", "W122d16.67m0", "Paine"],
"WESET": ["N47d24.35m0", "W122d19.10m0"],
"YXC" : ["N49d33.30m0", "W116d05.26m0"],
"ZUVEN": ["N47d47.98m0", "W122d25.15m0"]
},
"restricted": [
{
"name": "P-51",
"height": "2500ft",
"poly": [
["N47.7737128", "W122.7710456"],
["N47.7189169", "W122.7706794"],
["N47.6924411", "W122.7388044"],
["N47.6932556", "W122.6940508"],
["N47.7723906", "W122.6948667"]
]
}
],
"runways":[
{
"name": ["16L", "34R"],
"end": [
[47.463767, -122.307749, "432.5ft"],
[47.431201, -122.308035, "346.8ft"]
],
"ils": [true, true],
},
{
"name": ["16R", "34L"],
"end": [
[47.463806, -122.317884, "415.0ft"],
[47.440562, -122.318092, "356.3ft"]
],
"ils": [true, true],
}
],
"sids": {
"SUMMA1": {
"icao": "SUMMA1",
"name": "Summa One",
"altitude": 7000,
"rwy": {
"KSEA16L": ["NEVJO"],
"KSEA16R": ["NEVJO"],
"KSEA34L": [["NEZUG", "A40+"], "^_NEZUG070PAE139", "_SUMMA326017"],
"KSEA34R": [["NEZUG", "A40+"], "^_NEZUG070PAE139", "_SUMMA326017"]
},
"exitPoints": {
"BKE": ["SUMMA", "BKE"],
"LKV": ["SUMMA", "LKV"],
"SUMMA": ["SUMMA"]
},
"draw": [
["NEVJO", "SUMMA"],
["NEZUG", "_NEZUG070PAE139", "_SUMMA326017", "SUMMA"],
["SUMMA", "LKV*"],
["SUMMA*", "BKE*"]
]
}
},
"stars": {
"CHINS2": {
"icao": "CHINS2",
"name": "Chins Two",
"entryPoints": {
"CHINS": [],
"IMB": ["IMB", "SUNED", "YKM"],
"PDT": ["PDT", "BRUKK", "SUNED", "YKM"],
"SUNED": ["SUNED", "YKM"]
},
"body": ["CHINS"],
"rwy": {
"KSEA16L": [["RADDY", "A160+|S270"], ["HUMPP", "A150-"], ["AUBRN", "A120|S250"], "#343"],
"KSEA16R": [["RADDY", "A160+|S270"], ["HUMPP", "A150-"], ["AUBRN", "A120|S250"], "#343"],
"KSEA34L": [["RADDY", "A120|S250"], "HUMPP", "AUBRN", "#250"],
"KSEA34R": [["RADDY", "A120|S250"], "HUMPP", "AUBRN", "#250"]
},
"draw": [
["IMB*", "SUNED*", "YKM"],
["PDT*", "BRUKK", "SUNED", "YKM"],
["YKM", "CHINS*", "RADDY", "HUMPP", "AUBRN"]
]
}
},
"spawnPatterns": [
{
"origin": "KSEA",
"destination": "",
"category": "departure",
"route": "KSEA.SUMMA1.BKE",
"altitude": "",
"speed": "",
"method": "random",
"rate": 9,
"airlines": [
["aal", 4],
["aca", 1],
["asa", 3]
]
},
{
"origin": "",
"destination": "KSEA",
"category": "arrival",
"route": "PDT.CHINS2.KSEA",
"altitude": [18000, 36000],
"speed": 320,
"method": "random",
"rate": 15,
"airlines": [
["aal", 4],
["aca", 1],
["asa", 3]
]
},
{
"origin": "",
"destination": "",
"category": "overflight",
"route": "PDT..PSC..ELN..RADDY..AUBRN..GIGHR..ELMAA..HQM",
"altitude": [18000, 36000],
"speed": 320,
"method": "random",
"rate": 15,
"airlines": [
["aal", 4],
["aca", 1],
["asa", 3]
]
}
],
"maps": [
{
"name": "Base Map",
"lines": [
["N47.46706920", "W122.43465440", "N47.46816390", "W122.43651330"],
["N47.46635080", "W122.43369000", "N47.46706920", "W122.43465440"],
["N47.46975860", "W122.43977560", "N47.47109720", "W122.44296940"],
["N47.46816390", "W122.43651330", "N47.46975860", "W122.43977560"],
["N47.46549330", "W122.43386170", "N47.46635080", "W122.43369000"]
]
}
]
}
All properties in this section are required
"radio": {
"twr": "Seatle Tower",
"app": "Seattle Approach",
"dep": "Seattle Departure"
},
airspace
property is present, that value will take priority over this one..geoJSON
file in assets/airports/terrain."wind": {
"angle": 150,
"speed": 9
},
All properties in this section are required for each airspace section At least one airspace definition is required for an airport
"airspace": [
{
"floor": 0,
"ceiling": 150,
"airspace_class": "B",
"poly": [
["N47.83333330", "W121.69999940"],
["N47.95335007", "W121.97603665"],
["N48.30000000", "W121.96666670"],
["N48.30000000", "W122.30000000"],
["N48.20000000", "W122.45000000"]
]
}
],
Position definition of the airport airspace. Multiple airspace areas may be defined and will all be included in the airspace. This allows for advanced airspace stratification.
labelPositions
array may be supplied. It specifies one or more positions at which text labels are to be placed, which is useful for oddly shaped airspaces where the standard placement doesn’t look right. Here is an example of defining two positions:"labelPositions": [
["N48.20000000", "W122.45000000"],
["N47.83333330", "W121.69999940"]
],
All fixes listed within the Standard Routes need to be defined within this section
"fixes": {
"_NEZUG070010": ["N47d34.80m0", "W122d03.84m0"],
"_NEZUG070PAE139": ["N47d34.77m0", "W122d05.11m0"],
"_NICHY250SEA230": ["N47d19.92m0", "W122d42.78m0"],
"_OLM161026": ["N46d32.31m0", "W122d54.11m0"],
"_SEA161002": ["N47d24.12m0", "W122d18.58m0"],
"_SEA341004": ["N47d30.12m0", "W122d18.58m0"],
"_SUMMA326017": ["N46d53.20m0", "W122d07.08m0"],
"AAYRR": ["N46d38.81m0", "W123d43.34m0"],
"BOANE": ["N47d59.10m0", "W122d43.52m0"],
"EUG" : ["N44d07.25m0", "W123d13.37m0", "Eugene"],
"FEPOT": ["N47d04.85m0", "W123d13.13m0"],
"GEG" : ["N47d33.90m0", "W117d37.61m0"],
"KRUZR": ["N48d04.65m0", "W120d34.68m0", "cruiser"],
"ONSET": ["N48d57.48m0", "W118d00.00m0"],
"PAE" : ["N47d55.19m0", "W122d16.67m0", "Paine"],
"WESET": ["N47d24.35m0", "W122d19.10m0"],
"YXC" : ["N49d33.30m0", "W116d05.26m0"],
"ZUVEN": ["N47d47.98m0", "W122d25.15m0"]
},
Each navaid located within or around the airport airspace in latitude, longitude: see lat, lon, elev for formatting. Real life fixes are defined thusly:
"AAYRR": ["N46d38.81m0", "W123d43.34m0"]
Each fix can have an optional third parameter which defines how the name is pronounced by the speech engine. This parameter can either be a real place name (appearing on the charts) or a logical pronunciation of an arbitrary letter combination. Capitalization of this parameter does not affect the way the fix is pronounced in-sim.
"EUG" : ["N44d07.25m0", "W123d13.37m0", "Eugene"],
"KRUZR": ["N48d04.65m0", "W120d34.68m0", "cruiser"],
"PAE" : ["N47d55.19m0", "W122d16.67m0", "Paine"],
You will notice in the list above there is a fix definition preprended with an _
. This is called an invisible fix. A few examples of uses for these fixes include:
They’re used when we need aircraft to fly over a location that doesn’t have an actual fix or waypoint. A fix should be created and should be named using the following conventions:
"_RWY33L": [42.354662, -70.991598]
_RWY1805DME
would be 5.0nm north of the landing threshold of Runway 18. All of these should be marked as invisible fixes (via the underscore prefix)."_RWY33L01DME": [42.342838, -70.975751]
"_RWY12BSTER081": [25.810667, -80.322667]
_RWY33XYZ180
. Note that if the intersection were to be on the departure side of a given runway, the opposite runway should be used to keep with the convention of using the approach course."_RWY1LPIE116": [27.848198, -82.546200]
"_AUTUM220015": [42.324333, -71.736833]
"_FIXXA030FIXXB180"
FIXXA
, and northwest of FIXXB
, we could create _FIXXA050FIXXB320
, where the three digit numbers after the fix names are the direction from that fix to the described location."_SIPLY233STINS324": [37.47860, -122.60090]
_FIXXA050FIXXB05DME
, where the first fix has a three digit outbound radial, and the second fix has a two-digit distance in nm, followed by DME. Similarly, this can be done with runways using the same patterns as before, yielding _RWY22LFIXXB05DME
; just use the name of the runway whose approach course intersects the DME arc, and not the departure path."_SEA104TCM40DME": [47.074500, -121.516167],
"_RWY16LPAE10DME": [47.754500, -122.308000]
Areas of restricted airspace may be added to the restricted
property of the airport file. This is an array containing restricted areas such as the example below:
"restricted": [
{
"name": "P-51",
"height": "2500ft",
"poly": [
["N47.7737128", "W122.7710456"],
["N47.7189169", "W122.7706794"],
["N47.6924411", "W122.7388044"],
["N47.6932556", "W122.6940508"],
["N47.7723906", "W122.6948667"]
]
}
],
labelPositions
array may be supplied. It specifies one or more positions at which text labels are to be placed, which is useful for oddly shaped airspaces where the standard placement doesn’t look right. Here is an example of defining two positions:"labelPositions": [
["N47.7737128", "W122.7710456"],
["N47.7723906", "W122.6948667"]
],
"runways": [
{
"name": ["16L", "34R"],
"end": [
[47.463767, -122.307749, "432.5ft"],
[47.431201, -122.308035, "346.8ft"]
],
"ils": [false, true],
"ils_distance":[30, 25],
"loc_maxDist": [28, 20],
"glideslope": [3.00, 2.50]
}
],
"Runway 9"
(or "Runway 09"
, depending on the country) the other runway should be "Runway 27"
.Runways are defined in pairs because a runway can be used from either direction. This makes defining runways a little tricky, so special attention should be paid to how the data is set up. For each property, the first value will be considered part of the first runway and the second property for the second runway. If you were to take the above example and extract each runway’s properties, you would end up with the following two objects:
// Runway 16L
{
"name": "16L",
"end": [
[47.463767, -122.307749, "432.5ft"]
],
"ils": false
}
// Runway 34R
{
"name": "34R",
"end": [
[47.431201, -122.308035, "346.8ft"]
],
"ils": true
}
"airways": {
"J100": ["HEC", "CLARR", "LAS", "NORRA", "BCE"],
"J146": ["LAS", "NOOTN"],
"J9": ["HEC", "CLARR", "LAS", "NORRA", "AVERS", "URIAH", "BERYL", "MLF"],
"J92": ["BTY", "BLD", "KADDY", "PRFUM", "CADDU", "DRK"],
"Q15": ["CHILY", "DOVEE", "BIKKR"],
"V8": ["PHYLI", "MMM", "MEADS", "ACLAM", "WINDS", "LYNSY", "SHUSS", "GFS", "HEC"]
},
Each fix along each airway in successive order (direction does not matter). And of course, all fixes entered here must be defined in the fixes
section.
Supported Instrument Procedures currently include only SIDs and STARs, and each contain three components:
This structure is used to work with both SIDs and STARs within the app. Though it’s not important to know for an airport file, it is a good thing to keep in mind.
Fixes within a segment might include an instruction and/or restrictions. Fixes can be defined in several different ways:
// fix name only
"16L": ["IMB", "SUNED", "YKM"]
// fix name with fly-over instruction
"16L": ["IMB", "^SUNED", "YKM"]
// fix name with holding instruction
"16L": ["IMB", "@SUNED", "YKM"]
// fix name with altitude restriction
"16L": ["IMB", ["SUNED", "A70"], "YKM"]
// fix name with speed restriction
"16L": ["IMB", ["SUNED", "S200"], "YKM"]
// fix name with at/below and at/above altitude and speed restrictions
"16L": ["IMB", ["SUNED", "A70+|S250-"], "YKM"]
// fix name with ranged altitude and speed restrictions
"16L": ["IMB", ["SUNED", "A70+|A100-|S210+|S250-"], "YKM"]
These definitions can be used within any entryPoints
, body
or exitPoints
segment of a procedure.
All properties in this section are required for each route definition
"sids": {
"SUMMA1": {
"icao": "SUMMA1",
"name": "Summa One",
"altitude": 7000,
"rwy": {
"KSEA16L": ["NEVJO"],
"KSEA16R": ["NEVJO"],
"KSEA34L": [["NEZUG", "A40+"], "^_NEZUG070PAE139", "_SUMMA326017"],
"KSEA34R": [["NEZUG", "A40+"], "^_NEZUG070PAE139", "_SUMMA326017"]
},
"body": [],
"exitPoints": {
"BKE": ["SUMMA", "BKE"],
"LKV": ["SUMMA", "LKV"],
"SUMMA": ["SUMMA"]
},
"draw": [
["NEVJO", "SUMMA"],
["NEZUG", "_NEZUG070PAE139", "_SUMMA326017", "SUMMA"],
["SUMMA", "LKV*"],
["SUMMA*", "BKE*"]
]
}
},
SID is an acronym for Standard Instrument Departure.
"SUMMA1": {
"icao": "SUMMA1"
}
Entry
. Each key corresponds to a runway that can be used to enter the route.Body
segment. May be empty, but must be present.Exit
. Each key corresponds to and exit transition for a route.*
after it (e.g. ["SUMMA", "LKV*"]
). Please note that the ‘draw’ array must contain at least one array, even if it is empty: "draw": [[]]
Every possible rwy/body/exitPoint combination must result at least one fix. There must be at least one exitPoint, and it cannot be empty.
All properties in this section are required for each route definition
"stars": {
"CHINS2": {
"icao": "CHINS2",
"name": "Chins Two",
"entryPoints": {
"CHINS": [],
"IMB": ["IMB", "SUNED", "YKM"],
"PDT": ["PDT", "BRUKK", "SUNED", "YKM"],
"SUNED": ["SUNED", "YKM"]
},
"body": ["CHINS"],
"rwy": {
"KSEA16L": [["RADDY", "A160+|S270"], ["HUMPP", "A150-"], ["AUBRN", "A120|S250"], "#343"],
"KSEA16R": [["RADDY", "A160+|S270"], ["HUMPP", "A150-"], ["AUBRN", "A120|S250"], "#343"],
"KSEA34L": [["RADDY", "A120|S250"], "HUMPP", "AUBRN", "#250"],
"KSEA34R": [["RADDY", "A120|S250"], "HUMPP", "AUBRN", "#250"]
},
"draw": [
["IMB*", "SUNED*", "YKM"],
["PDT*", "BRUKK", "SUNED", "YKM"],
["YKM", "CHINS*", "RADDY", "HUMPP", "AUBRN"]
]
}
},
STAR is an acronym for Standard Terminal Arrival Route.
"CHINS2": {
"icao": "CHINS2"
}
Entry
. Each key corresponds to a route transition that can be used to enter the route.Body
segment. May be empty, but must be present.Exit
. Each key corresponds to a runway that is usable from this route*
after it (e.g. ["PDT*", "BRUKK"]
)At least one spawnPattern
is required to get aircraft populating into the app
"spawnPatterns": [
{
"origin": "KSEA",
"destination": "",
"category": "departure",
"route": "KSEA.SUMMA1.BKE",
"altitude": "",
"speed": "",
"method": "random",
"rate": 9,
"airlines": [
["aal", 4],
["aca", 1],
["asa", 3]
]
},
{
"origin": "",
"destination": "KSEA",
"category": "arrival",
"route": "PDT.CHINS2.KSEA",
"altitude": [18000, 36000],
"speed": 320,
"method": "random",
"rate": 15,
"airlines": [
["aal", 4],
["aca", 1],
["asa", 3]
]
},
{
"origin": "",
"destination": "",
"category": "overflight",
"route": "PDT..PSC..ELN..RADDY..AUBRN..GIGHR..ELMAA..HQM",
"altitude": [18000, 36000],
"speed": 320,
"method": "random",
"rate": 15,
"airlines": [
["aal", 4],
["aca", 1],
["asa", 3]
]
}
],
Contains the parameters used to determine how and where aircraft are spawned into the simulation. At least one spawnPattern
is required so that aircraft can be added to the simulation.
see spawnPatternReadme.md for more detailed descriptions on data shape and format of a spawnPattern
At least one map
is required for the airport to be loaded into the simulation. In addition to the maps, a defaultMaps
property is required to have at least one name
referenced. An maps not listed in defaultMaps
will not be rendered by default.
"maps": [
{
"name": "Base Map",
"lines": [
["N47.46706920", "W122.43465440", "N47.46816390", "W122.43651330"],
["N47.46635080", "W122.43369000", "N47.46706920", "W122.43465440"],
["N47.46975860", "W122.43977560", "N47.47109720", "W122.44296940"],
["N47.46816390", "W122.43651330", "N47.46975860", "W122.43977560"],
["N47.46549330", "W122.43386170", "N47.46635080", "W122.43369000"]
]
}
]
Markings on the scope that depict various characteristics of the airspace. When available, this will be an actual Radar Video Map used by the real-world facility.
For lat, lon, elev
values, these formats are acceptable:
Note: For lat, lon
values, just omit the elevation.
Identifiers are unique codes used to differentiate airports, fixes, aircraft, etc. (ex: “KSFO” for the San Francisco Airport). ICAO (the International Civil Aviation Organization) is an international aviation authority that sets safety and consistency standards that make worldwide travel more standardized. ICAO maintains many lists of things they assign their own identifiers (such as aircraft type designators, airport identifiers, etc). Wherever we have those identifiers stored, they will have the label “icao”.
IATA is another international aviation organization (like ICAO) which maintains their own set of identifiers. We include the IATA identifiers for airports in all airport .json
files, though they are not currently used for anything.
Flight levels are described by a number, which is this nominal altitude (or, pressure altitude) in hecto-feet, while being a multiple of 500 ft, therefore always ending on 0 or 5. Therefore, a pressure altitude of, for example, 32,000 feet is referred to as “flight level 320”.
Flight levels are usually designated in writing as FLxxx, where xxx is a two or three-digit number indicating the pressure altitude in units of 100 feet. In radio communications, FL290 would be pronounced as “flight level two nine(r) zero.” The phrase “flight level” makes it clear that this refers to the standardized pressure altitude.