Strategic Conflict Resolution
Use our platform to help with strategic conflict resolution either against your own submitted flight plans, or against all flight plans others have opted-in to share across our network.
Strategic Flight Deconfliction API
This service provides pre-flight deconfliction of flight plans that have been submitted to Altitude Angel. During implementation, one can choose to have their flight plan evaluated against just their own flight plans, or against all flight plans that have been shared publicly in the Altitude Angel network (see ConflictResolutionScope
).
A key tenet of aviation safety is planning to avoid coming into proximity with other air users before one starts a flight. This is often referred to as "plan-to-avoid", and should be among the minimum initial checks conducted prior to taking-off. In traditional aviation, deconfliction is handled differently for different classes of air traffic, but not always uniformly. For example, commercial airlines typically share their flight plans ahead of time with each other, but general aviation may only share flight plans at a local flying-club level.
This API can be used to store your flight plans securely on the Altitude Angel network up to fourteen days in the future, privately (just for your use), or publicly (for deconfliction across public flights shared via the Altitude Angel network). Each subsequent flight plan you submit will be evaluated for conflicts with other flight plans, according to the parameters you set.
Caution
Before using this service, you should study this documentation carefully and, in particular, familiarise yourself with the limitations and performance characteristics which are explained below.
If you have questions before you use the service, please contact us.
Scenarios
The service has been designed to cater for usage in both single-tenant and multi-tenant scenarios, and is ideally suited to the following specific use cases:
-
You are building a fleet management solution and wish to ensure that, pre-flight, your flights are guaranteed never to conflict with each other or with other flights published via and available to others on the Altitude Angel network.
-
You are building a single-tenant or multi-tenant flight-planning or process management system to facilitate best practices for drone flight, and you want to provide your users with the capability to plan flights that are conflict-free.
-
You are a drone manufacturer and building flight control software which features automated flight, or flight-path based control modes, and you want to ensure that a) none of your other customers' flights will conflict with each other, or b) none of your customer's flights will conflict with each other or any flight published on the Altitude Angel network.
Limitations
This service does not have knowledge about every flight.
This service does not have knowledge of every manned or unmanned flight. It is opt-in only, and we continue to see more and more flights each month. Depending on the
ConflictResolutionScope
you have requested, the service does provide guarantees that your flight plan is free from conflicts with any others if the conditions have been met.
The service currently checks against:
-
Valid flights that you have submitted into the API which are within their validity period and
-
Valid flights which other users of this API have indicated may be shared publicly, via any of Altitude Angel's first-party flight planning products (such as via www.dronesafetymap.com), or that another developer using this API has agreed to share with others (i.e. the
ConflictResolutionScope
is set toGlobal
).
What is a 'valid flight'?
A Valid flight is a flight which has been registered and accepted into the Altitude Angel Network, is scheduled to start in the future, or has started but has not yet expired. Developers who submit flights to this service will receive a
FlightId
andoutcomeCode
, together with a200 OK
HTTP response once a flight has been accepted as 'valid'.
Use by drones only
This service is intended primarily for use by drone operators. In a future release, we'll add support for flight plans by manned aircraft. This service does not currently receive flight plans for commercial routes operated by airlines, but this is a planned feature.
At this time, we provide de-confliction only for flights which have opted-in to receive this service and as such, is not intended to be used as the sole source of information used in determining whether a flight in any location at any given time shall be free from conflict or not.
Getting started
To access this API, you must first:
- Register for a Developer Account
- Obtain your API key to authenticate with this service.
If you already have a developer account registered before 23 July 2019
Your existing API key will need manual activation in order to utilise this new service. Please contact us for assistance.
Minimum Requirements and API Characteristics
Minimum TLS Version
This service is accessed via HTTPS using TLS 1.2 or above. Connections from clients running TLS 1.1 or weaker will be rejected.
Base URI
The URIs referenced in this documentation are relative to the base of https://flight.altitudeangel.com
.
Always use DNS
Never store the IP address returned through resolution of the DNS Query. We deliver the service via multiple datacentre locations and across a range of IP addresses, and regularly rotate clusters for security and performance reasons. Always resolve the location of the service by making a fresh DNS query (respecting the TTL of the record).
HTTP response codes related only to the status of the HTTP request
A response code of 200 means we have processed your request successfully, not that your flight hasn't conflicted with another. Always inspect the result of the OutcomeCode
property in the response.
How this service works
In this section, we explain precisely how the service works by exploring the types of conflict scenarios we can evaluate, how we do this, what responses can be expected and what the limitations of the service are.
Please carefully understand this section before implementation
It is important that you understand exactly what scenarios this service can, and cannot, evaluate. Management of risk within the airspace is not about the elimination of all risk; it is about the quantification and mitigation of those risks. This service will help to mitigate many associate risks if implemented correctly, but due to its opt-in nature, cannot mitigate all risk associated with a drone operation.
This API receives flight plans and evaluates them against conflicts on a first in wins
basis.
Evaluated Conditions - Other Flight Plans
When a flight plan is submitted, it is first checked for conflicts against other flight plans that have been submitted ahead of yours. For a conflict to occur, the submitted flight plan must first intersect with another one temporally; i.e. it is scheduled to take place at the same time as another previously registered flight plan.
Once this condition is met, there are two possible ways the flight plan may conflict with another:
By Proximity
On submission, the entirety of the submitted flight plan (i.e. all of its constituent Parts
) are merged, and then have a 'buffer' added to them. If the buffers of any two valid flight plans intersect, or the buffer region of one intersects with the buffer-less region of another, then a conflict of level 2000 (ProximityWarning)
will be generated. This means that while the two flight plans come close, according to the data provided to the flight plan service, the operators of the two flights are not planning paths that directly conflict.
The diagram below gives a logical example of how a Proximity Warning is generated:
By Direct Conflict
In this case, if the paths of two flight plans intersect (without a buffer region), then a conflict of level 3000 (DirectConflict)
will be returned, and the last-in flight plan will not be stored by Altitude Angel, and no flightPlanId
will be issued for the flight.
The diagram below gives a logical example of how a Direct Conflict is generated:
Altitude is ignored
In the current release version of this service, the conflict resolver does not take into account 'vertical separation'. Instead, all flight plans are treated as if they existed solely on a two-dimensional plane. We will continue to monitor use of this service, international guidance and best practices, and have prepared the service for three-dimensional resolution and plan to release this type of evaluation condition soon.
Evaluated Conditions - Approvals
The submitted Flight Plan is also checked for intersections with areas which require approval from a GuardianUTM-enabled facility.
These intersections are not buffered, and will always result in a conflict of level 3000 (DirectConflict)
.
Airspace
If the area intersected with is an airspace that requires approval, then any intersection with that airspace will generate a conflict.
Land
If the area intersected is an area which only requires take-off or landing permission, a conflict will be generated if:
- The first part of the Flight Plan is a
Point
and thatPoint
is within one metre of the area. - The first part of the Flight Plan is a
LineString
, and the first or last point of thatLineString
is within one metre area. - The first part of a Flight Plan is a
Polygon
, and the centre of thePolygon
is within one metre of the area.
Creating and submitting your flight plan
This service begins with the submission of a valid Flight Plan, which consists of several key pieces of data.
Not all information is mandatory
Please note that the service has been designed to collect more data than is required for the functionality currently provided, to assist with "future-proofing". We have a roadmap of future development for this service, and developers who are able to provide additional data above the minimum requirements may find it easier to avail of enhancements to this service.
Minimum required fields are indicated in the property description below the sample request.
Below is a conceptual description of the data that we request as part of a flight plan:
- Metadata about the flight, primarily used for your own reference, such as a
description
andsummary
of the flight. - One (or more)
parts
, which are effectively 'legs' of a journey that can be detailed routes, or more specific geographies encompassing a general area. - A scheduled
start
date/time andend
date/time, and a maximum altitude (maxAltitude
). - Your own token, called
externalOperatorId
, to enable you to deliver multi-tenant solutions and separate flights belonging from one customer to another. - Any
identifiers
that might help others in the vicinity identify you, such as an ICAO ADS-B identifier, if your drone or aircraft is equipped with such a piece of equipment. droneDetails
, which describes the phsyical properties of your drone (only required for unmanned aircraft).- The desired
conflictResolutionScope
, i.e.global
orlocal
. - Whether the flight plan is
draft
orfinal
, which enables you to submit "what-if?" queries against the service without committing to conduct an actual flight.
Refer to the property definition below to determine which parameters are mandatory and which are optional.
Submit exactly one Flight for each aircraft that will conduct a logical flight.
For example, if you plan to fly a swarm of drones, you could submit one
flight
for each drone participating in the swarm (if you want this service to provide conflict separation for each individual drone participating in the swarm). Or, you could submit oneflight
to cover the whole area in which the swarm will fly, but you will then have to provide separation within that area for each individual drone.
In either case, if you choose global
scope, others will be informed of your operation so that their flights are not permitted by this service to conflict with yours.
Request
Make an HTTP request to the following URL:
POST https://flight.altitudeangel.com/v1/conflict-resolution/strategic/flight-plans
Authorization: X-AA-ApiKey YOUR_API_KEY_HERE
Don't forget to include the full URL in the POST instruction
... And don't forget to include the prefix "X-AA-ApiKey", plus a space character, before inserting the API key generated via the Developer Portal. If your API key was "123", then the full string value to insert for the "Authorization" header would be "X-AA-ApiKey 123".
Construct the payload of your HTTP request as a JSON document using UTF-8 encoding as follows. The JSON messages below show the minimum and maximum that will be accepted by the API.
{
"summary": "Flight Title",
"parts": [
{
"id": "1",
"geography": {
"type": "LineString",
"coordinates": [
[
-1.007995,
51.473791
],
[
-0.982933,
51.472722
]
]
},
"start": "2010-07-31T12:00:00Z",
"end": "2010-07-31T13:00:00Z",
"maxAltitude": {
"datum": "agl",
"meters": 50
}
},
{
"id": "2",
"geography": {
"type": "LineString",
"coordinates": [
[
-0.982933,
51.472722
],
[
-0.987138,
51.467897
]
]
},
"start": "2010-07-31T13:00:00Z",
"end": "2010-07-31T14:00:00Z",
"maxAltitude": {
"datum": "agl",
"meters": 50
}
}
],
"pointOfContact": {
"firstName": "John",
"lastName": "Smith",
"phoneNumber": "+447700900123"
},
"conflictResolutionScope": "global"
}
{
"summary": "Flight Title",
"description": "Flight Description",
"parts": [
{
"id": "1",
"geography": {
"type": "LineString",
"coordinates": [
[
-1.007995,
51.473791
],
[
-0.982933,
51.472722
]
]
},
"start": "2010-07-31T12:00:00Z",
"end": "2010-07-31T13:00:00Z",
"maxAltitude": {
"datum": "agl",
"meters": 50
}
},
{
"id": "2",
"geography": {
"type": "LineString",
"coordinates": [
[
-0.982933,
51.472722
],
[
-0.987138,
51.467897
]
]
},
"start": "2010-07-31T13:00:00Z",
"end": "2010-07-31T14:00:00Z",
"maxAltitude": {
"datum": "agl",
"meters": 50
}
}
],
"externalOperatorId": "ABC123",
"identifiers": {
"ADSB": "AAA111"
},
"pointOfContact": {
"firstName": "John",
"lastName": "Smith",
"phoneNumber": "+447700900123"
},
"droneDetails": {
"color": "Purple",
"markings": "Go faster stripes",
"airFrame": "rotary",
"weight": 150,
"maxWeight": 250
},
"conflictResolutionScope": "global",
"isDraft": false
}
Anatomy of a Flight Plan
An explanation of the properties in the above JSON document is provided below. Required properties are marked with an asterisk *.
Parameter Name | Datatype | Description |
---|---|---|
summary* | string | Summary of the flight or operation. This may be shared with others if you choose the global scope. |
description | string | More details about the flight, such as the nature of the activity being undertaken. |
parts* | flightPart[] | Each constituent segment that makes up the entire flight. |
externalOperatorId | string | An identifier for the user that 'owns' the flight that is specific to your implementation, eg "user-123456". We use these to help you correlate in a multi-tenant scenario. |
identifiers | Dictionary[string, string] | Identifiers/signals given off by the craft that can be used to identify it. |
pointOfContact* | contactDetails | The details for the point of contact that will be responsible for the drone's flight. |
droneDetails | droneDetails | The physical and performance characteristics of the drone that will be making the flight. |
conflictResolutionScope* | string | The scope under which the flight plan will be tested for conflictions against. |
isDraft | bool | Whether or not the flight plan should be tangibly submitted. |
A whole flight plan consists of one or many flight parts, where each is a distinct geographical, spatial, and altitudinal segment.
parts
The parts
property is an array of flightPart
objects.
A flightPart
is logically a specific 'leg' of a journey. It's entirely your choice whether you wish to use multiple parts to break-up a journey and this is largely included for future compatibility. Please note that a flightPart
is not a mechanism to specify multiple vehicles.
flightPart
Parameter Name | Datatype | Description |
---|---|---|
id* | string | A unique identifier for this part of the flight. |
geography* | geoJSON | The spatial area that this part will occupy. It should be formatted as GeoJSON, and can be either a LineString, Polygon, or Point. |
start* | dateTime | The ISO8601 date and time, including timezone specifier, at which this flight segment will begin. |
end* | dateTime | The ISO8601 date and time, including timezone specifier, at which this flight segment will be completed. |
maxAltitude* | altitude | The highest point that will be reached in this part. |
Depending on the type of flight and how you want to express it, different GeoJSON objects may be used. Any of:
- Polygon: The flight will be taking place throughout a given area;
- LineString/Point: The flight will be travelling through a set of waypoints.
altitude
An altitude is a combination of both height, and the datum against it was measured. It takes the following structure:
Parameter Name | Datatype | Description |
---|---|---|
datum* | datum | The datum that the altitude is measured against. |
meters* | double | The height, in meters. |
The following datums are supported:
Value | Name | Description |
---|---|---|
wgs84 | WGS-84 | Altitude expressed in meters above the WGS-84 ellipsoid (most commonly, this is used by GPS chips in a raw NMEA stream). |
agl | Above ground level | The altitude is given as a positive offset 'above ground level' at the specified coordinates. |
contactDetails
Contact details give information on the individual responsible for the flight, who should be available to contact for the duration of the it.
Parameter Name | Datatype | Description |
---|---|---|
firstName* | string | First name of the contact. |
lastName* | string | Last name of the contact. |
phoneNumber* | string | Phone number of the contact, in international format without any whitespace/digit separators. |
droneDetails
Drone details give information on the characteristics of the drone that will be undertaking the flight.
Parameter Name | Datatype | Description |
---|---|---|
color | string | The drone's primary color. |
markings | string | Any distinctive markings on the drone. |
airframe | airframeType | The airframe/performance characteristics of the drone. |
weight | double | The weight of the drone that will be used, in kilograms. |
maxWeight | double | The maximum take-off weight of the drone, in kilograms. |
As present, there are two possible values for airframe
:
Value | Name | Description |
---|---|---|
fixedWing | Fixed Wing | A craft with a rigid wing/airfoil - it generates lift through its forward airspeed. |
rotary | Rotary | A craft with one or more rotorblades - it generates lift through the rotation of the blades. |
Validation
All requests made to this API must meet certain validation criteria as shown below.
If any of these are not met, the request will be invalid
, and an HTTP response code of 400 - Bad Request
will be returned.
- All required (*) fields must be present;
- All string properties have a maximum length of 255 characters, apart from
firstName
andlastName
inpointOfContact
which have a maximum of 60; pointOfContact.phoneNumber
should be in international (E.123) format without whitespace/digit separators;- The
id
of eachflightPart
must be unique in the context of the flight plan; - Each
flightPart
'sgeography
should be either aLineString
,Polygon
, orPoint
; - The flight plan's total duration cannot exceed twelve (12) hours;
- The flight plan cannot take place more than fourteen (14) days in the future;
- The flight plan cannot exceed an area of 10km2;
- The flight plan cannot be longer than 30km.
We will continue to listen to monitor use of the service and listen to user feedback with respect to maximum area and distance limitations.
Values in the request body are case in-sensitive
Values sent in the request are case-insensitive, so casing will not cause a validation error.
Create Response
Response Code | Reason |
---|---|
200 OK | Successful request, further details are in the body. |
400 Bad Request | Request was invalid, specific errors are detailed in the body. |
401 Unauthorized | A valid API key was not present on the request. |
503 Service Unavailable | The request could not be processed. |
Example response body to a successful service call, indicating a conflict
{
"operationId": "ca59943d-b6b5-4862-b883-0aaca027f6d6",
"outcomeCode": 3000,
"outcome": "DirectConflict",
"conflicts": [
{
"severity": "DirectConflict",
"geography": {
"type": "Polygon",
"coordinates": [
[
[
-0.985035,
51.472776
],
[
-0.987803,
51.472094
],
[
-0.984327,
51.471252
],
[
-0.985035,
51.472776
]
]
]
},
"start": "2010-07-31T13:30:00Z",
"end": "2010-07-31T13:45:00Z",
"description": "Flightplan conflicts with an existing flightplan between 2010-07-31T13:30:00Z and 2010-07-31T13:45:00Z"
}
]
}
Note: the description
property provides a human-readable description of the conflict and the time-window in which the conflict is expected to occur (the dates and times are all in UTC). The start
and end
property contain just the DateTime
values, if you wish to use these programatically.
Successful response with no conflict indicated:
{
"operationId": "0d251e61-d43b-4deb-8d91-658397e7e874",
"flightPlanId": "d31094b0-3ab5-4b0d-97c7-d5b642c56f6c",
"outcomeCode": 1000,
"outcome": "NoConflictingReportsFound",
"conflicts": []
}
The
outcomeCode
of1000
indicates that we could not find any other conflicting flight reports in our system. That doesn't mean that somebody else won't be operating their drone or flying nearby! When implementing this feature for your external users, you should ensure that they are fully aware that this is not an 'all clear', and we draw your attention to the Terms of Service for this API which require that you inform your users of the service's characteristics and limitations.
Definition of response properties
Parameter Name | Datatype | Description |
---|---|---|
operationId | guid | A unique identifier for the request that was made. |
flightPlanId | guid | A unique identifier for the flight plan, which is only issued if there are no DirectConflicts . |
outcomeCode | int | A numeric code to describe the overall status of the flight plan. |
outcome | string | A human-readable description of outcomeCode . |
conflicts | conflict[] | An array describing precisely what conflicts we have detected with your submission, if any. |
A single conflict
represents an intersection with another flight plan spatially and temporally, and describes the specific aspects where the conflict occurs.
Parameter Name | Datatype | Description |
---|---|---|
severity | string | A description of the level of conflict. |
geography | geoJSON | The area where there is a conflict. |
start | dateTime | The time window during which the conflict is anticipated to exist. |
end | dateTime | The time at which the conflict is expected to pass. |
description | string | A human-readable description of the conflict. |
The service assumes that people comply with their own flight plans.
By it's very nature, any service operating pre-flight for "strategic separation" must rely on the data submitted to it. Because the flights have not actually taken place yet, the service must treat the information submitted "as if" they will be faithfully executed. To help mitigate the risk of providing false positives, we apply "padding" and "buffering" in both time and space, but this process alone does not provide any guarantee that a particular flight at any given time and location will be free from conflict, or indeed conflict with any other air traffic.
Outcome/Severity is description of the extent of the overlap we have detected.
Current possible values are:
Code | Name | Description |
---|---|---|
1000 | NoConflictingReportsFound | No conflicting reports exist in our network. |
2000 | ProximityWarning | Your flight is expected to come close, but not into direct contact, with at least one other flight. |
3000 | DirectConflict | Your flight is expected to come into direct conflict with at least one other flight. |
Conflict Resolution Scope
The use of the conflictResolutionScope
(local
or global
) sent as part of the submitted flight plan is to allow selection of the comprehensiveness of conflict detection process:
global
scope means that the flight plan will be evaluated for conflicts against all other flight plans available in our network;local
scope means that the flight plan will only be evaluated for conflict against flight plans that originate from the same account. Otherglobal
flights will still be deconflicted against theselocal
plans.
Draft Flight Plans
Flight plans can be submitted with isDraft
set to true
to perform a "what-if" operation. These flight plans permit one to query the system, but even if there is no conflict, the service won't store the flight plan.
Invalid Request
Requests that arrive in an invalid format will receive a 400 Bad Request
response with the specific errors detailed in the request body keyed by the JSONPath of the erroneous field. For example:
{
"flightPlanRequest.Summary": {
"errors": [
{
"errorMessage": "'Summary' should not be empty."
}
]
},
"flightPlanRequest.Parts[1].Start": {
"errors": [
{
"errorMessage": "Start time cannot be in the past."
}
]
},
"flightPlanRequest.Parts": {
"errors": [
{
"errorMessage": "Flight Part IDs must be unique."
},
{
"errorMessage": "Flight plan duration must be less than 12 hours."
}
]
}
}
In this case, the errors are:
- The
summary
field is missing; - The second flight part has a start time in the past;
- There are flight part IDs that share IDs;
- The duration of the flight provided by the flight parts is greater than twelve hours.
The individual fields that error (in this case; summary, and the second flight part) will be mapped to specifically, while errors that occur over a set of fields (in this case; the flight parts) will be mapped to the set itself.
Cancel a Flight Plan
It's good practice to 'de-register' your flight plan if you no longer intend to take the flight. Doing so clears the route you were expecting to take for others to transit.
Flight plans are immutable
You cannot submit a change to a flight plan. You may only cancel it, and then resubmit an altered or updated one. Note that at the point of re-submission, your flight plan will be treated as a new flight plan, and will therefore be evaluated as such.
Example of a cancellation request
POST https://flight.altitudeangel.com/v1/conflict-resolution/strategic/flight-plans/{flightPlanId}/cancel
Authorization: X-AA-ApiKey YOUR_API_KEY
Parameter Name | Datatype | Description |
---|---|---|
flightPlanId* | guid | The ID of the flight plan to be cancelled. |
Cancel Response
{
"operationId": "9c516ab5-bfc9-4dc6-96a3-dffa37c501d5",
"flightPlanId": "d31094b0-3ab5-4b0d-97c7-d5b642c56f6c",
"message": "The flightplan has been cancelled."
}
Definition of response properties
Parameter Name | Datatype | Description |
---|---|---|
operationId | guid | A unique identifier for the request that was made. |
flightPlanId | guid | The ID of the flight plan that was cancelled. |
message | string | A human-readable description the outcome of the request. |
Updated 10 months ago