daidalus

Note

This documentation concerns version 2 of DAIDALUS. Documentation on version 1 is available from https://nasa.github.io/WellClear.

Reference Manual - DAIDALUS-v2.0.x

Introduction

DAIDALUS (Detect and AvoID Alerting Logic for Unmanned Systems) is a reference implementation of the detect and avoid (DAA) functional requirements described in RTCA’s Minimum Operational Performance Standards (MOPS) DO-365 and RTCA DO-365A developed by RTCA Special Committee 228 (SC-228).

At the core of the RTCA SC-228 DAA concept, there is a mathematical definition of the well-clear concept. Two aircraft are considered to be well clear of each other if appropriate distance and time variables determined by the relative aircraft states remain outside a set of predefined threshold values. These distance and time variables are closely related to variables used in the Resolution Advisory (RA) logic of the Traffic Alert and Collision Avoidance System Version II (TCAS II).

DAIDALUS core logic is based on ownship-centric, state-less algorithms that

The following diagram illustrates the high-level architecture of the DAIDALUS library.

DAIDALUS’ maneuver guidance logic assumes non-maneuvering traffic aircraft and supports, by configuration, either instantaneous or kinematic maneuvers by the ownship. Manuever guidance is provided as suggestive guidance (i.e., bands) and directive guidance (i.e., preferred direction and velocity vector). Suggestive guidance is computed in the form of range of track, ground speed, vertical speed, and altitude values called bands. These bands represent ranges of ownship maneuvers tha maintain well-clear status with respect to traffic aircraft. In the case of a loss of well-clear, or when a well-clear violation is unavoidable, well-clear recovery bands represent ranges of ownship maneuvers to regain well-clear status. Recovery bands are designed so that they improve the distance at closest point of approach in a timely manner. DAIDALUS’ alerting logic assumes non-maneuvering ownship and traffic aircraft. It computes a numerical alert level based on a set set of increasingly larger alert thresholds.

Software Library

DAIDALUS is provided as a software library implemented in both Java and C++. Except for programming language idiosyncrasies, both Java and C++ application programming interfaces are identical. This document uses Java as example, but diferences with the C++ code are noted.

DAIDALUS code is available under NASA’s Open Source Agreement. The library is highly configurable and configuration can be done either programmatically or by loading a configuration file. The core algorithms have been formally specified and verified in the Prototype Verification System (PVS).

DAIDALUS v2 vs. DAIDALUS v1

DAIDALUS v2 and v1 share the same logic and, by design, configuration files are backward compatible. DAIDALUS v2 application programming interface differs from DAIDALUS v1 and provides new and enhanced functionality. In particular, DAIDALUS v2 implements

The application DAA-Displays provides a graphical interface that enables the side-by-side comparison of (possibly) different versions of DAIDALUS on (possibly) different configurations on a given encounter.

Getting the Code

The source code of DAIDALUS is available at GitHub/daidalus. The following git command gets the development version of DAIDALUS (the dollar sign $ represents the prompt of a Unix terminal):

$ git clone https://github.com/nasa/daidalus.git

In addition to the development version, three other releases are available: v1.0.1 (October 11, 2017), v1.0.2 (April 21, 2019), and v2.0.1 (August 12, 2020). These releases are available as branches in the Git repository, e.g.,

$ git checkout v2.0.1

This documentation concerns version 2 of DAIDALUS. Documentation on version 1 is available from https://nasa.github.io/WellClear.

Compiling the Code

The code is self-contained and does not require any particular library.

The Java code has been compiled in Mac OSX and Linux using

Java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

The C++ code has been compiled in Mac OSX using

Apple clang version 11.0.0 (clang-1100.0.33.17)
Target: x86_64-apple-darwin18.7.0
Thread model: posix

and in Linux using:

g++ 7.4.0

The library and example applications can be compiled using the Unix utility make with the provided Makefile in both the Java and C++ directories. In Java, the make command will produce the jar file lib/DAIDALUSv2.X.x.jar, where X.x are the major and minor release numbers, e.g.,

$ make
** Building library lib/DAIDALUSv2.X.x.jar
javac src/gov/nasa/larcfm/IO/*.java src/gov/nasa/larcfm/Util/*.java src/gov/nasa/larcfm/ACCoRD/*.java
...
** Building example applications
javac -cp lib/DAIDALUSv2.X.x.jar src/*.java

In C++, the make command will generate the static library lib/lib/DAIDALUSv2.X.x.a.

Example Applications

In addition to Jar and library files, the make command compiles several example applications. The applications DaidalusExample, whose source code is available in Java and C++, illustrates the main functionalities provided by DAIDALUS including reading/writing configuration files, detection logic, alerting logic, maneuver guidance logic, and computation of loss of well-clear contours for hard coded ownship and traffic states. To run this program in a Unix environment, type

$ <dir>/DaidalusExample

This very simple program can be executed with several configurations. For a list of options, type

$ <dir>/DaidalusExample --help

More sophisticated applications are also provided in the DAIDALUS distribution (see Batch Simulation and Analysis Tools).

Preliminaries

Packages and Name Space

In Java, DAIDALUS consists of three packages in the hierarchy gov.nasa.larcfm: IO, Util, and ACCoRD. In C++, the DAIDALUS code is provided under the name space larcfm. This document will refer to classes in these packages and name space through unqualified names. The following table lists the main DAIDALUS classes (including interfaces and enumerations) and, in the case of Java, the package under which the class is defined.

Java Class Java Package C++ Header C++ Code
Alerter.java ACCoRD .h .cpp
AlertThresholds.java ACCoRD .h .cpp
BandsRange.java ACCoRD .h .cpp
BandsRegion.java ACCoRD .h .cpp
CD3DTable.java ACCoRD .h .cpp
CDCylinder.java ACCoRD .h .cpp
ConflictData.java ACCoRD .h .cpp
Daidalus.java ACCoRD .h .cpp
DaidalusFileWalker.java ACCoRD .h .cpp
DaidalusParameters.java ACCoRD .h .cpp
Detection3D.java ACCoRD .h .cpp
Horizontal.java ACCoRD .h .cpp
RecoveryInformation.java ACCoRD .h .cpp
TCASTable.java ACCoRD .h .cpp
TCAS3D.java ACCoRD .h .cpp
TrafficState.java ACCoRD .h .cpp
Vertical.java ACCoRD .h .cpp
WCVTable.java ACCoRD .h .cpp
WCV_TAUMOD.java ACCoRD .h .cpp
WCV_TAUMOD_SUM.java ACCoRD .h .cpp
WCV_TCPA.java ACCoRD .h .cpp
WCV_TEP.java ACCoRD .h .cpp
Interval.java Util .h .cpp
Position.java Util .h .cpp
Units.java Util .h .cpp
Vect2.java Util .h .cpp
Vect3.java Util .h .cpp
Velocity.java Util .h .cpp

Units

DAIDALUS core algorithms use as internal units meters, seconds, and radians. However, interface methods that set or get a value have a string argument, where the units are explicitly specified. The following table provides a list of symbols and the corresponding string representation supported by DAIDALUS.

Units String
milliseconds "ms"
seconds "s", "sec"
minutes "min"
hours "h", "hr"
meters "m"
kilometers "km"
nautical miles "nmi", "NM"
feet "ft"
knots "knot", "kn", "kts"
meters per second "m/s"
kilometers per hour "kph", "km/h"
feet per minute "fpm", "ft/min"
meters per second2 "m/s^2"
9.80665 m/s2 "G"
degrees "deg"
radians "rad"
degrees per second "deg/s"
radians per second "rad/s"

The class Units provides the following static methods for converting to/from internal units and from one unit into another one.

Earth Projection and Aircraft States

The main DAIDALUS interface methods support inputs in geodesic coordinates (latitude, longitude, and altitude) and this is the preferred way to provide inputs to DAIDALUS. Internally, the core algorithms use a Euclidean local East, North, Up (ENU) Cartesian coordinate system. DAIDALUS uses an orthogonal projection of the ownship and traffic geodesic coordinates onto a plane tangent to the projected ownship position on the surface of the earth. The vertical component is not transformed.

Aircraft positions are represented by the class Position. Positions are specified in geodesic coordinates using the following static method, where northern latitudes and eastern longitudes are positive.

Aircraft velocities are represented by the class Velocity. Velocities are specified relative to the ground in polar coordinates using the following static method, where track is given in true north clockwise convention.

For testing and debugging purposes, position and velocities can alternatively be given using a Euclidean local ENU Cartesian coordinate system. In this case, DAIDALUS assumes that all traffic aircraft states are provided using the same coordinate system as the one used by the ownship . The static methods to create Position and Velocity objects using a Cartesian system are:

Winds

DAIDALUS implements a simple wind model that is globally applied using a velocity vector. When a wind vector is provided, DAIDALUS uniformly applies the wind vector to all current and future aircraft states until another vector (possibly zero, i.e., “no-wind”) is set. This vector can be provided using either a “TO” (wind blowing direction) or a “FROM” (direction wind source from ownship’s point of view) convention. An important consequence of setting a wind vector is that all computations and outputs become relative to the wind.

Invalid Values

Methods in DAIDALUS fail silently and return invalid values when called with invalid parameters. The following tables list methods that check the validity of values in DAIDALUS classes.

Class/Type Validity Check (Java) Invalidity Check (Java)
double d; Double.isFinite(d), Double.isInfinite(d) Double.isNaN(d)
AlertThresholds athr athr.isValid()  
Alerter a; a.isValid()  
BandsRegion r; r.isValidBand()  
Interval i; i.isEmpty()  
Velocity v;   v.isInvalid()
Position p;   p.isInvalid()
TrafficState s; s.isValid()  

In C++, the methods are the same except in the following cases.

Class/Type Validity Check (C++) Invalidity Check (C++)
double d; ISFINITE(d), ISINF(d) ISNAN(d)
BandsRegion r; BandsRegion::isValidBand(r)  

Furthermore, a negative integer value is returned as an invalid value in methods that under normal conditions return a natural number, e.g., int aircraftIndex(String name) returns the index of an aircraft state given an aircraft identifier, e.g., name. The index is 0 if name is the ownship identifier and a positive number if name is the identifier of a traffic state. A negative value -1 is returned when there is no aircraft identified with the string name.

DAIDALUS Inputs

The DAIDALUS software library is ownship centric. Its main functional features are provided through the class Daidalus, which maintains the global configuration, the wind configuration, and the current ownship and traffic aircraft states. In a multi-threaded application, there should only a Daidalus object per ownship and it should not be simultaneously written by different threads.

Except for the configuration maintained in a Daidalus object, DAIDALUS functions are memoryless, i.e., they compute information using the current aircraft states and do not keep memory of previous aircraft states. However, DAIDALUS uses an eager computational approach, where some information is pre-computed and cached, and then reused when needed. The cache memory is conservatively cleared by methods that modify the configuration of the Daidalus object.

DAIDALUS assumes that there is a notion of time-step that is provide by the host application using the DAIDALUS library. At every time step the ownship state is first set and then traffic aircraft states are provided. DAIDALUS does not provide any functionality to filter, fuse, or pre-process aircraft state information. If needed, any pre-processing has to be implemented by the host application. Within the same time-step, alerting and guidance information is computed. A typical DAIDALUS application has the following steps:

  1. Create a Daidalus object, e.g., daa, to provide DAA functionality to the ownship.
  2. Configure daa. This object can be reconfigured at any time. However, in a typical application, a Daidalus object is configured at the beginning of the application and the configuration remains invariant through the execution of the program.
  3. At every time-step:
    1. Provide Inputs
      1. If available, set wind vector. This wind vector is applied to current and future aircraft states (ownship and traffic) until another wind vector is set.
      2. Set ground-based state information for ownship into daa. If available, set standard and co-standard deviations for ownship position and velocity information.
      3. Set ground-based state information for all traffic aircraft into daa. If available, set standard and co-standard deviations for traffic position and velocity information.
    2. Compute Outputs
      1. Get detection, alerting, and guidance information from daa.
      2. Use output information as appropriate. DAIDALUS does not provide any functionality to display or post-process its outputs. If needed, any post-processing has to be implemented by the host application.

Because of the eager computational approach used by DAIDALUS, the steps above are the preferred way to use DAIDALUS: at each time step there is a first phase where all inputs for a given time-step are provided and then a second phase where all outputs for the given time-step are computed and processed. If outputs are computed before all inputs are provided, cache memory may be clear resulting in a sound but more inefficient computation. Furthermore, if hysteresis logic is enabled clearing the cache memory will also result in clearing hysteresis information.

In a real DAA application, not every input is available at the same time. Different sensors may have different frequencies and traffic information is available in an asynchronous way. In that case, synchrony could be introduced by the host application, for example by running a process that executes at a given frequency (e.g., 1hz).

Creating a Daidalus Object

In Java, a Daidalus object is created through the call

Daidalus daa = new Daidalus();

The same can be accomplished in C++, using stack memory:

Daidalus daa;

In both cases, the variable daa is initialized to an empty DAA logic.

Configuring Daidalus Object

A Daidalus object can be configured either programmatically or via a configuration file. For instance,

daa.set_DO_365A();

set daa to DO 365A default values, i.e.,

The same configuration can be achieved by loading the configuration file DO_365A_SUM.conf provided in the distribution, e.g.,

daa.loadFromFile("DO_365A_SUM.conf");

The more general method call

daa.set_DO_365A(type,sum);

where both type and sum are boolean variables, set daa to DO 365A default values but

For instance, the call

daa. set_DO_365A(true,false);

is equivalent to loading the configuration file DO_365A_no_SUM.conf provided in the distribution, e.g.,

daa.loadFromFile("DO_365A_no_SUM.conf");

DAIDALUS supports a large set of configurable parameters that govern the behavior of the detection, alerting, and maneuver guidance logics. The simplest way to configure a Daidalus object is through a configuration file. Examples of configuration files are provided in the directory Configurations. These configurations and programatic methods to achieve them are explained in the Section Pre-Defined Configurations.

As seen in previous examples, the method call

daa.loadFromFile(filename);

loads a configuration file, whose name is indicated by filename, into the Daidalus object daa. Generally, a configuration file set values to all configurable parameters. However, a configuration file may only provide values to the parameters that change with respect to the current configuration in daa. At any time, the current configurations can be written into a file using the method call

daa.saveToFile(filename);

The methods loadFromFile and saveToFile of the class Daidalus return a boolean value. The value false indicates that an input/output error has occurred, e.g., a file cannot be read because it does not exist or a file cannot be written because of insufficient permissions.

Providing Wind Information

If available, a wind vector can be provided to a Daidalus object daa using the method call

daa.setWindVelocityTo(wind_to);

or, alternatively,

daa.setWindVelocityFrom(wind_from);

where wind_to and wind_from are Velocity objects. The vector wind_to specifies the clockwise true north direction the wind blows. The vector wind_from specifies the clockwise true north direction of the wind source from the point of view of the ownship. The wind vector is applied to current and future aircraft states (ownship and traffic) until another wind vector is set.

The method call daa.setNoWind() disables wind computations for current and future aircraft states (ownship and traffic) until a wind vector is configured.

Adding Aircraft States

A Daidalus object daa maintains the ownship state and a list of traffic aircraft states at a given time of applicability, which is the time of the ownship state. Aircraft identifiers are assumed to be unique within a daa object. The order in which traffic aircraft are added is relevant. Indeed, several Daidalus methods use the index of an aircraft in the list of aircraft as a reference to the aircraft. The index 0 is reserved for the ownship. It should be noted that aircraft indices may change from time-step to time-step. The following methods are provided by the class Daidalus.

Adding Ownship State

The ownship state can be added into a Daidalus object daa using the method call

daa.setOwnshipState(ido,so,vo,to);

where ido is the ownship identifier (string), so is a Position object that indicates ownship position, vo is a Velocity object that indicates ownship velocity, and to is an absolute time stamp in seconds of the ownship state, i.e., the time of applicability. Setting the ownship state into a daa object clear the list of traffic aircraft states. Thus, for a given time of applicability, the ownship state has to be added before any other aircraft state.

Adding Traffic State

Traffic states can be added into daa using the method call

aci_idx = daa.addTrafficState(idi,si,vi);

where idi, si, and vi are the traffic identifier, position, and velocity, respectively. Traffic states do not require a time stamp since it is assumed to be the same the ownship’s. If a time stamp is provided, e.g.,

daa.addTrafficState(idi,si,vi,ti);

the position of the traffic aircraft is linearly projected (forwards or backwards in time) from ti to to, the time stamp of the ownship, so that all traffic states are synchronized in time with the ownship. The returned value aci_idx is the index of an aircraft idi after it has been added to the list of aircraft.

Adding Sensor Uncertainty

If a SUM configuration is enabled and sensor uncertainties for the ownship/traffic aircraft are available, they can be set as follows.

daa.setHorizontalPositionUncertainty(ac_idx, s_EW, s_NS, s_EN, xy_units);
daa.setVerticalPositionUncertainty(ac_idx, sz, z_units);
daa.setHorizontalVelocityUncertainty(ac_idx, v_EW, v_NS, v_EN, vxy_units);
daa.setVerticalSpeedUncertainty(ac_idx, vz, vz_units);

where

Dealing with Asynchronous Inputs

The following figure illustrates a hypothetical situation where sensors for different aircraft are providing information in an asynchronous way.

In this case, synchrony can be introduced by having a process that executes at a given frequency (e.g., 1hz). The execution of that process is represented by the blue markers in the picture above. The time between two consecutive executions of this process represents a time step (the gray area on the time line in the figure). For example, during the current time step, ownship information is received at time town, state information for traffic aircraft A is received at time tA and for traffic aircraft C at time tC. In this example, there is a traffic aircraft B, whose last state information was received at time tB, but no information was not received during the current time step. At the end of the current time step, when the synchronous process executes, the following can be done:

daa.setOwnshipState(own,...,t_own);
daa.addTrafficState(A,...,t_A); 
daa.addTrafficState(C,...,t_C); 

DAIDALUS will project forwards the state of A (town - tA) seconds and the state of C (tC - town) to synchronize with ownship time, the time of applicability of the current time step. The synchronous process could just ignore aircraft B for the current time step. However, if B is still relevant, but the frequency of its sensor works at a slower rate, the synchronous process could provide the old state information and DAIDALUS will project that state information forward (town-tB) seconds, e.g.,

daa.addTrafficState(B,...,t_C); 

For this schema to work, the host application is responsible for queueing the state information that is received during a time step and to provide this information to DAIDALUS as needed. As explained before, DAIDALUS does not keep aircraft state information from one time-step to the next. Furthermore, this schema assumes that ownship information is always available during a time step. If that is not true, the synchronous process could either skip the current time step or, alternatively, project the previous ownship information to current time. DAIDALUS utility code provides functions to project aircraft states forward and backward in time.

DAIDALUS Outputs

The class Daidalus is the main interface to the core DAA capabilities provided by DAIDALUS: detection, alerting, and maneuver guidance. As in previous example, the following examples assume that daa is an object of type Daidalus. These outputs depend on the configuration of the daa object and in particular the configuration of the alerting logic. An important element of this configuration is the corrective volume, which is defined by a set of distance and time thresholds. Most of the detection and maneuver guidance functionality in DAIDALUS are computed with respect to this volume.

Detection Logic

The time, in seconds, to violation of the corrective volume between the ownship and the traffic aircraft at index ac_idx can be computed as follows

double t2v = daa.timeToCorrectiveVolume(ac_idx);

If t2v is zero, the aircraft are in violation at current time. It t2v is positive, it is the time to violation of the corrective volume relative to ownship’s time.

The time returned by timeToCorrectiveVolume is positive infinity when the aircraft are not in conflict within the lookahead time. It returns the Not-A-Number (NaN) value when ac_idx is not a valid aircraft index.

Alerting Logic

The alert level between the ownship and the traffic aircraft at index ac_idx can be computed as follows

int alert_level = daa.alertLevel(ac_idx);

The value of alert_level is negative when ac_idx is not a valid aircraft index in daa. If alert_level is zero, no alert is issued for the ownship and the traffic aircraft at index ac_idx at time of applicability. Otherwise, alert_level is a positive numerical value that indicates an alert level, which for DO-365A configurations is defined as follows.

alert_level DO-365A Alert Level
1 Preventive
2 Corrective
3 Warning

The following method, in the class Daidalus,

ConflictData violationOfAlertThresholds(int ac_idx, int alert_level);

computes the time interval of violation, with respect to aircraft at index ac_idx, to the volume defined by alert_level. It returns an object of type ConflictData, which provides, among others, the following functions.

The following code uses these functions to print for each traffic aircraft alert level, the predicted time to violation of the corrective volume, and for each alert level the time to loss of the corresponding alert thresholds.

 for (int ac_idx=1; ac_idx <= daa.lastTrafficIndex(); ++ac_idx) {
	TrafficState intruder = daa.getAircraftStateAt(ac_idx);
	int alert = daa.alertLevel(ac_idx);
	if (alert > 0) {
		System.out.println("Alert Level "+alert+" with "+intruder.getId());
	}
	double t2los = daa.timeToCorrectiveVolume(ac_idx);
	if (Double.isFinite(t2los)) {
		System.out.println("Predicted Time to Violation of Corrective Volume with "
		+intruder.getId()+": "+f.Fm2(t2los)+" [s]");
	}
 	for (int alert_level=1;alert_level <= daa.mostSevereAlertLevel(ac_idx);++alert_level) {
		ConflictData det = daa.violationOfAlertThresholds(ac_idx, alert_level);
		if (det.conflict()) {
			System.out.println("Predicted Time to Violation of Alert Thresholds at Level "
			+alert_level+" with "+intruder.getId()+": "+f.Fm2(det.getTimeIn())+" [s]");
	    }	
	}
}

The Daidalus object daa can be configured to an arbitrary number of alert levels and the alert logic is highly configurable.

Maneuver Guidance Logic

DAIDALUS provides sugestive maneuver guidance in the form of ranges of ownship maneuvers called bands. Four independent dimensions of bands are computed by DAIDALUS:

  1. Horizontal Direction: ranges of track or heading maneuvers, depending on configuration of wind vector.
  2. Horizontal Speed: ranges of ground speed or airspeed maneuvers, depending on configuration of wind vector.
  3. Vertical Speed: ranges of vertical speed maneuvers.
  4. Altitude: ranges of altitude maneuvers.

In each dimension, bands are represented by an ordered list of intervals that are disjoint except at the boundaries. These intervals completely partition a range of values from a configurable minimum value to a configurable maximum value. Each interval is associated with a BandsRegion, which is defined as an enumerated type consisting of the following values.

Ownship performance limits and other parameters that govern the maneuver guidance logic can be configured in the Daidalus object.

Horizontal Direction Bands

The computation of horizontal speed bands (track or, when wind information is provided, heading maneuvers) uses either turn rate or bank angle, which are provided by configuration. If both the turn rate and the bank angle are zero, horizontal direction bands are computed assuming instantaneous manevuers. The following loop iterates the list of intervals in the horizontal direction bands and for each interval gets its upper and lower bounds and its type.

  for (int i = 0; i < daa.horizontalDirectionBandsLength(); ++i ) {  
    Interval iv = daa.horizontalDirectionIntervalAt(i,"deg"); //i-th interval in degrees
    double lower_trk = iv.low; //[deg]
    double upper_trk = iv.up;  //[deg]
    BandsRegion regionType = daa.horizontalDirectionRegionAt(i);
	...
  } 

Horizontal Speed Bands

The computation of horizontal speed bands (ground speed or, when wind information is provided, air speed maneuvers) user horizontal acceleration, which is provided by configuration. If this acceleration is zero, horizontal speed bands are computed assuming instantaneous manevuers. The following loop iterates the list of intervals in the horizontal speed bands and for each interval gets its upper and lower bounds and its type.

  for (int i = 0; i < daa.horizontalSpeedBandsLength(); ++i ) {  
    Interval iv = daa.horizontalSpeedIntervalAt(i,"knot"); //i-th interval in knots
    double lower_hs = iv.low; //[knot]
    double upper_hs = iv.up;  //[knot]
    BandsRegion regionType = daa.horizontalSpeedRegionAt(i);
    ... 
  } 

Vertical Speed Bands

The computation of vertical speed bands uses vertical acceleration, which is provided by configuration. If this acceleration is zero, vertical speed bands are computed assuming instantaneous manevuers. The following loop iterates the list of intervals in the vertical speed bands and for each interval gets its upper and lower bounds and its type.

  for (int i = 0; i < daa.verticalSpeedBandsLength(); i++ ) {  
    Interval iv = daa.verticalSpeedIntervalAt(i,"fpm"); //i-th interval in fpm
    double lower_vs = iv.low; //[fpm]
    double upper_vs = iv.up;  //[fpm]
    BandsRegion regionType = daa.verticalSpeedRegionAt(i);
    ... 
  } 

Altitude Bands

The computation of altitude bands uses vertical acceleration and vertical rate, which are provided by configuration. If both the vertical acceleration and the vertical rate are zero, altitude bands are computed assuming instantaneous manevuers. The following loop iterates the list of intervals in the altitude bands and for each interval gets its upper and lower bounds and its type.

  for (int i = 0; i < daa.altitudeBandsLength(); i++ ) {  
    Interval iv = daa.altitudeIntervalAt(i,"ft"); //i-th interval in ft
    double lower_alt = iv.low; //[ft]
    double upper_alt = iv.up;  //[ft]
    BandsRegion regionType = daa.altitudeRegionAt(i);
    ... 
  } 

Recovery Bands Information

When a loss of a the corrective volume cannot be avoided, the maneuver guidance logic turns from maintaining well-clear into regaining well-clear. The method interfaces that provide bands do not change, but the bands algorithms compute recovery bands instead of well-clear bands. The types of regions that can be returned by the recovery bands algorithms, depending on configuration, are RECOVERY, FAR, MID, NEAR, and UNKNOWN.

The regain well-clear logic attempts to recover from well-clear by maximizing a recovery volume and minimizing the time to recovery. The original size of the recovery volume is provided by configuration. The size of the computed recovery volume and the time to recovery can be accessed through the class RecoveryInformation. The code below returns an object RecoveryInformation for each dimension of suggestive maneuver guidance.

RecoveryInformation recovery_hdir = daa.horizontalDirectionRecoveryInformation();
RecoveryInformation recovery_hs = daa.horizontalSpeedRecoveryInformation();
RecoveryInformation recovery_vs = daa.verticalSpeedRecoveryInformation();
RecoveryInformation recovery_alt = daa.altitudeRecoveryInformation();

The following methods are available in the class RecoveryInformation. Times and distance are returned in u units. If units are not provided, the values are returned in internal units, i.e., meters, seconds, etc.

Aircraft Contributing to Bands

Bands that are in the current path of the ownship are called conflict bands. Conflict bands simultaneously appear for all type of maneuvers, e.g., horizontal direction, horizontal speed, vertical speed, and altitude. The list of identifiers of aircraft contributing to conflict bands for a particular region can be obtained as follows.

List<String> acs = new ArrayList<String>();
daa.conflictBandsAircraft(acs,region);

The list of strings acs is passed by reference. The variable region has the type BandsRegion and is one of FAR, MID, or NEAR.

Bands that are not in the current path of the ownship are called peripheral bands. Peripheral bands are different for different type of maneuvers. The list of aircraft contributing to each type of peripheral bands for a particular region can be obtained as follows:

List<String> acs = new ArrayList<String>();
daa.peripheralHorizontalDirectionBandsAircraft(acs,region);
daa.peripheralHorizontalSpeedBandsAircraft(acs,region);
daa.peripheralVerticalSpeedBandsAircraft(acs,region);
daa.peripheralAltitudeBandsAircraft(acs,region);

Directive Guidance

In addition to suggestive guidance, i.e., bands, DAIDALUS computes directive guidance, e.g, velocity vectors that solve an impending conflict or that recover from a loss of separation. These velocity vectors are computed from the maneuver bands and, unless persistence logic is enabled, they correspond to the maneuvers that are free of conflict for the lookahead time and that are geometrically closest to the current velocity of the ownship for the given dimension (horizontal direction, horizontal speed, vertical speed, and altitude).

Directive guidance is provided by the following Daidalus methods.

The resolution maneuvers returned by these methods are conflict free with respect to all aircraft at least until lookahead time. They return the Not-A-Number (NaN) value when the ownship is not in conflict and an infinite value (either positive or negative infinite) if a resolution in the dir is not available (for example, because of performance limits of the ownship).

DAIDALUS also computes a preferred resolution for each dimension that can be used to provide a value to the dir parameter in the methods above. For instance, the following code computes preferred resolution maneuvers for horizontal direction in degrees, horizontal speed in knots, vertical speed in feet per minute, and altitude in feet.

double hdir_deg = daa.horizontalDirectionResolution(daa.preferredHorizontalDirectionRightOrLeft(),"deg"); 
double hs_knot = daa. horizontalSpeedResolution(daa.preferredHorizontalSpeedUpOrDown(),"knot"); 
double vs_fpm = daa. verticalSpeedResolution(daa.preferredVerticalSpeedUpOrDown(),"fpm");
double alt_ft = altitudeResolution(daa.preferredAltitudeUpOrDown(),"ft");

DAA Performance Metrics

(Note, some of these methods are only available in release v2.0.2 and up)

Assuming daa is an object of type Daidalus, the following methods compute DAA performance metrics between ownship and aircraft at index ac_idx in u units. These methods return the Not-A-Number (NaN) value if ac_idx is not a valid index. If the unit parameters are not provided the returned values are in internal units, i.e., meters, seconds, etc.

For each type of manevuer, the following methods return the last time to maneuver, relative to current time, before a loss of the corrective volume cannot avoided according to aircraft performance limits. These methods return Not-A-Number (NaN) value if ac_idx is not a valid index. They return positive infinity if the aircraft are not in conflict and return negative infinity if there is no time to maneuver.

** DOCUMENTS HAS BEEN UPDATED UPTO THIS POINT **

Alerters

DAIDALUS also enables the configuration of alert level thresholds. The following parameters can be configured per alert level (The first level is 1) in a configuration file.

Sensor Uncertainty Mitigation

Hysteresis Logic

DTA Logic

Configurable Parameters

DAIDALUS DAA capabilities can be configured either programmatically, i.e., using getter/setter methods ìn the class Daidalus or via a configuration file, using the method loadFromFile in the class `Daidalus.

Bands Parameters

The following is a list of parameters that can be configured in DAIDALUS.

Configuration Parameter Programatic Getter/Setter Description (Type)
lookahead_time get/setLookaheadTime Time horizon of all DAIDALUS functions (Time)
left_trk get/setLeftTrack Relative maximum horizontal direction maneuver to the left of current ownship direction (Angle)
right_trk get/setRightTrack Relative maximum horizontal direction maneuver to the right of current ownship direction (Angle)
min_hs get/setMinHorizontalSpeed Absolute minimum horizontal speed maneuver (Speed)
max_hs get/setMaxHorizontalSpeed Absolute maximum horizontal speed maneuver (Speed)
min_vs get/setMinVerticalSpeed Absolute minimum vertical speed maneuver (Speed)
max_vs get/setMaxVerticalSpeed Absolute maximum vertical speed maneuver (Speed)
min_alt get/setMinAltitude Absolute minimum altitude maneuver (Altitude)
max_alt get/setMaxAltitude Absolute maximum altitude maneuver (Altitude)
trk_step get/setTrackStep Granularity of horizontal direction maneuvers (Angle)
hs_step get/setHorizontalSpeedStep Granularity of horizontal speed maneuvers (Speed)
vs_step get/setVerticalSpeedStep Granularity of vertical speed maneuvers (Speed)
alt_step get/setAltitudeStep Granularity of altitude maneuvers (Altitude)

Kinematic Parameters

Configuration Parameter Programatic Getter/Setter Description (Type)  
horizontal_accel get/setHorizontalAcceleration Horizontal acceleration used in the computation of horizontal speed maneuvers (Acceleration)  
vertical_accel get/setVerticalAcceleration Vertical acceleration used in the computation of horizontal speed maneuvers (Acceleration)  
turn_rate get/setTurnRate Turn rate used in the computation of horizontal direction manevuers (Angle/Time)  
bank_angle get/setBankAngle Bank angle used in the computation of horizontal direction manevuers (Angle)  
vertical_rate get/setVerticalRate Vertical rate used in the computation of altitude maneuvers (Speed)  
recovery_stability_time get/setRecoveryStabilityTime Time Time delay to stabilize recovery manevuers

Recovery Bands Parameters

Configuration Parameter Programatic Getter/Setter Description (Type)
min_horizontal_recovery get/setMinHorizontalRecovery Minimum horizontal separation used in the computation of recovery maneuvers (Distance)
min_vertical_recovery get/setMinVerticalRecovery Minimum vertical separation used in the computation of recovery maneuvers (Distance)
recovery_trk isEnabled/setRecoveryTrackBands Enable computation of horizontal direction recovery maneuvers (Boolean)
recovery_hs isEnabled/setRecoveryHorizontalSpeedBands Enable computation of horizontal speed recovery maneuvers (Boolean)
recovery_vs isEnabled/setRecoveryVerticalSpeedBands Enable computation of vertical speed recovery maneuvers (Boolean)
recovery_alt isEnabled/setRecoveryAltitudeBands Enable computation of altitude recovery maneuvers (Boolean)

Collision Avoidance Bands Parameters

Configuration Parameter Programatic Getter/Setter Description (Type)
ca_bands isEnabled/setCollisionAvoidanceBands Enable computation of collision avoidance maneuvers (Boolean)
ca_factor get/setCollisionAvoidanceBandsFactor Factor to reduce min horizontal/vertical recovery separation when computing collision avoidance maneuvers (Scalar in (0,1])
horizontal_nmac get/setHorizontalNMAC Horizontal NMAC (Distance)
vertical_nmac get/setVerticalNMAC Vertical NMAC (Distance)
contour_thr get/setHorizontalContourThreshold Threshold
relative to ownship horizontal direction for the computation of    
horizontal contours a.k.a. “blobs” (Angle)    

Alerting Logic Parameters

Hysteresis Parameters

Sensor Uncertainty Mitigation Parameters

DAA Terminal Area (DTA) Parameters

Considerations

The following restrictions apply to these parameters.

When appropriate, explicit units can be provided when configuring these parameters either using a file or programmatically. For example, in a configuration file, units can be provided as follows:

max_hs = 700.0 [knot]

The following configuration can also be achieved using the method

daa.setMaxGroundSpeed(700.0,"knot");

If no units are provided, internal units are assumed, i.e., meters for distance, seconds for time, radians for angles, and so on.

Pre-Defined Configurations

The directory Configurations includes the following configurations files that are related to RTCA SC-228 MOPS Phase I.

Batch Simulation and Analysis Tools

DAIDALUS includes utilities for batch simulation and for computing alerting and maneuver guidance from pre-defined encounters.

Creating DAA Encounters from DAIDALUS Logs with daidalize

DAIDALUS’ batch utilities work with two text files: a DAIDALUS configuration file name.conf such as DO_365B_no_SUM.conf and an encounter file name.daa such as H1.daa. The encounter file may list multiple aircraft; the first one is considered to be the ownship. Aircraft states can also be given in local Euclidean coordinates, e.g., H0_0_120.xyz. The extensions .daa and .xyz for geodesic vs Euclidean coordinates, respectively, is just a convention.

Configuration and encounter files can be generated from a Daidalus log file. A Daidalus log file is produced by writing into a text file the string daa.toString(), where daa is a Daidalus object. The script daidalize can be used to generate the configuration and encounter file from a Daidalus log file, i.e., name.log, e.g.,

$ <DAIDALUS_DIR>/Scripts/daidalize.pl name.log 
Processing name.log
Writing traffic file: name.daa
Writing configuration file: name.conf 

The script daidalize assumes that the time of the aircraft states strictly increases at every time step. If this this is not the case, the script fails. The option --fixtimes forces the script to fix the problem by artificially increasing the time of contiguous time steps so that the time column of the generated encounter strictly increases at every time step.

Generating DAA Encounters with DAAGenerator

The application DAAGenerator, which is available in Java, can be used to generate simple encounters by applying forward and backward projections to aircraft states. The initial aircraft states can be provided directly from a DAA encounter file. For example, to create a 90 degree collision scenario, one could write a simple DAA file with the ownship and intruder aircraft at the collision state and project the state backward in time.

For example, the file C0.txt specifies a collision state between two aircraft at the location 40.67233 [deg] (latitude), -74.04466 [deg] (longitude), 15000 [ft] (altitude). At the collision state, the ownship has a ground speed of 150 [knot] and ground track of 0 [deg] (with respect to true north) and the intruder has a ground speed of 120 [knot] and ground track of 90 [deg] (clockwise with respect to true north). The command

$ <DAIDALUS_DIR>/Java/DAAGenerator --backward 120 C0.txt

linearly projects the aircraft states at time 0, from C0.txt, 120 seconds backward in time and generates the encounter file C0_0_120.daa.

The initial state could also be provided in Euclidean local coordinates. For example, to create a head-on encounter with a closest approach of 0.5 [nmi], one could linearly project the state at the time of closest point of approach forward and backward in time. For example, the file H0.txt specifies, in local Euclidean coordinates, a head-on encounter with a closest approach of 0.5 [nmi]. The command

$ <DAIDALUS_DIR>/Java/DAAGenerator --backward 100 --forward 20 H0.txt

linearly projects the aircraft states at time 0, from H0.txt, 100 seconds backward and 20 seconds forward in time, and generates the encounter file H0_0_120.xyz. Since the input is in local Euclidean coordinates, the output scenario is also in Euclidean coordinates. However, for convenience, the output scenario can be generated in geodesic coordinates if a latitude and longitude for the origin of the Euclidean coordinate system is provided. For example, the command

$ <DAIDALUS_DIR>/Java/DAAGenerator --backward 100 --forward 20 --lat 40.67233 --lon -74.04466 H0.txt

generates the encounter file H0_0_120.daa, where local Euclidean coordinates have been translated to geodesic coordinates using the provided latitude and longitude as origin of the local Euclidean coordinate system.

Wind can be added to generated scenarios. The command

$ <DAIDALUS_DIR>/Java/DAAGenerator -backward 100 -forward 20 -lat 40.754377 -lon -74.007436 --wind_norm='40[kn]' --wind_from='170[deg]' --out C1_0_120_W.daa C1.txt

generates the file C0_1_120_W.daa from C1.txt, where the states at time 0 are projected 100 seconds backward and 20 seconds forward with a southerly wind blowing from 170 degrees at 40 knots.

A complete list of options accepted by DAAGenerator is provided using the option ‘–help’.

Computing Alerting and DAA Metrics with DaidalusAlerting

The application DaidalusAlerting, which is available in Java and C++, computes alerting and DAA metrics in a comma separated value (CSV) format, for given encounter and configuration files. For example,

$ <DAIDALUS_DIR>/Java/DaidalusAlerting --conf Configurations/DO_365B_no_SUM.conf Scenarios/H1.daa 
Generating CSV file H1.csv 

generates the file H1.csv with alerting information computed by DAIDALUS for the encounter H1.daa assuming DO-365B (without Sensor Uncertainty Mitigation) configuration.

Running DAIDALUS in Batch Mode with DaidalusBatch

The program DaidalusBatch, which is available in Java and C++, runs DAIDALUS on a given encounter using a specified configuration and prints time-step by time-step alerting and banding information computed by DAIDALUS. For example,

$ <DAIDALUS_DIR>/Java/DaidalusBatch --conf Configurations/DO_365B_no_SUM.conf Scenarios/H1.daa

runs DAIDALUS on the encounter H1.daa assuming DO-365B (without Sensor Uncertainty Mitigation) configuration and prints second-by-second information computed by DAIDALUS.

Drawing Bands with DrawMultiBands

The program DrawMultiBands, which is available in Java, produces guidance and alerting information in a graphical form. For example,

<DAIDALUS_DIR>/Java/DrawMultiBands --conf Configurations/DO_365B_no_SUM.conf Scenarios/H1.daa 
Writing file H1.draw, which can be processed with the Python script drawmultibands.py 

produces the file H1.draw, which can be processed with the Python script drawmultibands.py, e.g.,

<DAIDALUS_DIR>/Scripts/drawmultibands.py H1.draw 
Writing H1.pdf 

to generate a PDF file displaying manuever guidance information for the encounter H1.daa assuming DO-365B (without Sensor Uncertainty Mitigation)

DAA Simulations with DAA-Displays

For better visualization of DAIDALUS encounters, the utility DAA-Displays provides graphical simulation tools designed to support DAA configuration and analysis. DAA-Displays is available under NASA Open Source Agreement at GitHub.

Contact

Cesar A. Munoz (cesar.a.munoz@nasa.gov)