Skip to content

Commit

Permalink
Implemented Airborne Velocity
Browse files Browse the repository at this point in the history
  • Loading branch information
Douglasdc3 committed Nov 16, 2020
1 parent a1e1d94 commit 8178323
Show file tree
Hide file tree
Showing 8 changed files with 271 additions and 109 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package aero.t2s.modes.constants;

public enum NavigationUncertaintyCategory {
UNKNOWN("Unknown"),
NUC1("Horizontal: < 10 m/s | Vertical: < 15.2 m/s (50fps)"),
NUC2("Horizontal: < 3 m/s | Vertical: < 4.6 m/s (15fps)"),
NUC3("Horizontal: < 1 m/s | Vertical: < 1.5 m/s (5fps)"),
NUC4("Horizontal: < 0.3 m/s | Vertical: < 13786 m/s (1.5fps)"),
;

private String probability;

NavigationUncertaintyCategory(String probability) {
this.probability = probability;
}

public static NavigationUncertaintyCategory from(int code) {
switch (code) {
case 0: return UNKNOWN;
case 1: return NUC1;
case 2: return NUC2;
case 3: return NUC3;
case 4: return NUC4;
default: throw new IllegalArgumentException("NUC " + code + " is not valid");
}
}

@Override
public String toString() {
return probability;
}
}
7 changes: 7 additions & 0 deletions src/main/java/aero/t2s/modes/constants/RocdSource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package aero.t2s.modes.constants;

public enum RocdSource {
BARO,
GNSS,
;
}
11 changes: 11 additions & 0 deletions src/main/java/aero/t2s/modes/constants/Speed.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package aero.t2s.modes.constants;

public enum Speed {
KTS,
KMH,

IAS,
TAS,
GS,
;
}
151 changes: 78 additions & 73 deletions src/main/java/aero/t2s/modes/decoder/df/df17/AirborneVelocity.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,83 +2,24 @@

import aero.t2s.modes.NotImplementedException;
import aero.t2s.modes.Track;
import org.slf4j.LoggerFactory;
import aero.t2s.modes.constants.NavigationUncertaintyCategory;
import aero.t2s.modes.constants.RocdSource;

public class AirborneVelocity extends ExtendedSquitter {
private static final double HEADING_RESOLUTION = 360.0 / 1024.0;
protected NavigationUncertaintyCategory NACv;
private int subType;
private boolean supersonic;
private boolean intentChange;
private boolean ifrCapability;
private boolean rocdAvailable;
private RocdSource rocdSource;
private int rocd;
private boolean gnssAltitudeDifferenceFromBaroAvailable;
private int gnssAltitudeDifferenceFromBaro;

public AirborneVelocity(short[] data) {
super(data);
}
//
// @Override
// public void decode(Track track, int typeCode, short[] data) {
// int subType = data[4] & 0x7;
//
// boolean intentChange = (data[5] >>> 7) == 1;
// track.setNACv(data[5] >>> 3);
//
// int altitudeDifferenceBaroDirection = (data[10] >>> 7) == 0 ? 1 : -1;
// int geometricHeightDiffBaro = ((data[10] & 0x7F) - 1) * altitudeDifferenceBaroDirection;
// track.setGeometricHeightOffset(geometricHeightDiffBaro);
//
// int vsiDirection = ((data[8] >>> 3) & 0x1) == 0 ? 1 : -1;
// boolean verticalRateBaro = ((data[8] >>> 4) & 0x1) == 1;
// int rocd = (((data[8] & 0x7) << 6) | (data[9] >>> 2) - 1) * 64 * vsiDirection;
// track.setRocdAvailable(true);
// track.setRocdSourceBaro(verticalRateBaro);
// if (verticalRateBaro) {
// track.setBaroRocd(rocd);
// } else {
// track.setRocd(rocd);
// }
//
// if (subType == 1 || subType == 2) {
// decodeGroundSpeed(track, typeCode, subType, data);
// return;
// }
//
// if (subType == 3 || subType == 4) {
// decodeAirspeedGroundSpeed(track, typeCode, subType, data);
// return;
// }
//
// LoggerFactory.getLogger(getClass()).warn("{}: subtype {} is reserved.", getClass().getSimpleName(), subType);
// }
//
// private void decodeGroundSpeed(Track track, int typeCode, int subType, short[] data) {
// int xDirection = (data[5] >>> 2) == 1 ? 1 : -1;
// int yDirection = (data[7] >>> 7) == 1 ? 1 : -1;
//
// int x = ((((data[5] & 0x3) << 8) | (data[6])) - 1) * (subType == 1 ? 1 : 4) * xDirection;
// int y = ((((data[7] & 0x7F) << 3) | (data[8] >>> 5)) - 1) * (subType == 1 ? 1 : 4) * yDirection;
//
// track.setVx(x);
// track.setVy(y);
// track.setGs(Math.sqrt(x * x + y * y));
// }
//
// private void decodeAirspeedGroundSpeed(Track track, int typeCode, int subType, short[] data) {
// boolean headingAvailable = data[5] >>> 2 == 1;
// boolean ias = data[7] >>> 7 == 0;
//
// double heading = (((data[5] & 0x3) << 8) | data[6]) * HEADING_RESOLUTION;
// int airspeed = ((((data[7] & 0x7F) << 1) | (data[8] >>> 5)) - 1) * (subType == 1 ? 1 : 4);
//
// if (track.isMagneticHeading()) {
// track.setMagneticHeading(headingAvailable ? heading : 0);
// } else {
// track.setTrueHeading(headingAvailable ? heading : 0);
// }
//
// track.setIasAvailable(ias);
//
// if (ias) {
// track.setIas(airspeed);
// } else {
// track.setTas(airspeed);
// }
// }

@Override
public AirborneVelocity decode() {
Expand All @@ -87,10 +28,10 @@ public AirborneVelocity decode() {
switch (subType) {
case 1:
case 2:
return new AirborneVelocityVersion0(data).decode();
return new AirborneVelocityGroundspeed(data).decode();
case 3:
case 4:
return new AirborneVelocityVersion2(data).decode();
return new AirborneVelocityAirspeedHeading(data).decode();
default:
throw new NotImplementedException("BDS0,9 sub type " + subType + " is not implemented");
}
Expand All @@ -100,4 +41,68 @@ public AirborneVelocity decode() {
public void apply(Track track) {
// Nothing
}

protected void decodeCommonInformation() {
subType = data[4] & 0b00000111;
supersonic = subType == 2;
intentChange = (data[5] & 0b10000000) != 0;
ifrCapability = (data[5] & 0b01000000) != 0;

NACv = NavigationUncertaintyCategory.from((data[5] & 0b00111000) >>> 3);

rocdSource = (data[8] & 0b00010000) != 0 ? RocdSource.BARO : RocdSource.GNSS;
rocd = ((data[8] & 0b00000111) << 6) | (data[9] & 0b11111100) >>> 2;
rocdAvailable = rocd != 0;
rocd = (rocd - 1) * 64;
if ((data[8] & 0b00001000) != 0) {
rocd *= -1;
}

gnssAltitudeDifferenceFromBaro = data[10] * 0b01111111;
gnssAltitudeDifferenceFromBaroAvailable = gnssAltitudeDifferenceFromBaro != 0;
gnssAltitudeDifferenceFromBaro = (gnssAltitudeDifferenceFromBaro - 1) * 25;
if ((data[10] & 0b10000000) != 0) {
gnssAltitudeDifferenceFromBaro *= -1;
}
}

public NavigationUncertaintyCategory getNACv() {
return NACv;
}

public int getSubType() {
return subType;
}

public boolean isSupersonic() {
return supersonic;
}

public boolean isIntentChange() {
return intentChange;
}

public boolean isIfrCapability() {
return ifrCapability;
}

public boolean isRocdAvailable() {
return rocdAvailable;
}

public RocdSource getRocdSource() {
return rocdSource;
}

public int getRocd() {
return rocd;
}

public boolean isGnssAltitudeDifferenceFromBaroAvailable() {
return gnssAltitudeDifferenceFromBaroAvailable;
}

public int getGnssAltitudeDifferenceFromBaro() {
return gnssAltitudeDifferenceFromBaro;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package aero.t2s.modes.decoder.df.df17;

import aero.t2s.modes.Track;
import aero.t2s.modes.constants.RocdSource;
import aero.t2s.modes.constants.Speed;

public class AirborneVelocityAirspeedHeading extends AirborneVelocity {
private static final double HEADING_RESOLUTION = 360.0 / 1024.0;

private boolean headingAvailable;
private double heading;

private boolean airspeedAvailable;
private Speed airspeedType;
private int airspeed;

public AirborneVelocityAirspeedHeading(short[] data) {
super(data);
}

@Override
public AirborneVelocityAirspeedHeading decode() {
decodeCommonInformation();

headingAvailable = (data[5] & 0b00000100) != 0;
heading = (((data[5] & 0b00000011) << 8) | data[6]) * HEADING_RESOLUTION;

airspeed = ((data[7] & 0b01111111) << 3) | (data[8] & 0b11100000) >>> 5;
airspeedAvailable = airspeed != 0;
airspeed = (airspeed - 1) * (isSupersonic() ? 4 : 1);
airspeedType = ((data[7] & 0b10000000) != 0) ? Speed.TAS : Speed.IAS;

return this;
}

@Override
public void apply(Track track) {
track.setNACv(NACv.ordinal());

if (isGnssAltitudeDifferenceFromBaroAvailable()) {
track.setGeometricHeightOffset(getGnssAltitudeDifferenceFromBaro());
}

if (isRocdAvailable()) {
track.setRocdAvailable(true);
track.setRocdSourceBaro(getRocdSource() == RocdSource.BARO);
if (getRocdSource() == RocdSource.BARO) {
track.setBaroRocd(getRocd());
} else {
track.setRocd(getRocd());
}
}
}

public boolean isHeadingAvailable() {
return headingAvailable;
}

public double getHeading() {
return heading;
}

public boolean isAirspeedAvailable() {
return airspeedAvailable;
}

public Speed getAirspeedType() {
return airspeedType;
}

public int getAirspeed() {
return airspeed;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package aero.t2s.modes.decoder.df.df17;

import aero.t2s.modes.Track;
import aero.t2s.modes.constants.RocdSource;

public class AirborneVelocityGroundspeed extends AirborneVelocity {
private boolean xVelocityAvailable;
private int xVelocity;

private boolean yVelocityAvailable;
private int yVelocity;

public AirborneVelocityGroundspeed(short[] data) {
super(data);
}

@Override
public AirborneVelocityGroundspeed decode() {
decodeCommonInformation();

xVelocity = ((data[5] & 0b00000011) << 8) | data[6];
xVelocityAvailable = xVelocity != 0;
xVelocity = (xVelocity - 1) * (isSupersonic() ? 4 : 1);
if ((data[5] & 0b00000100) != 0) {
xVelocity *= -1;
}

yVelocity = ((data[7] & 0b01111111) << 3) | (data[8] & 0b11100000) >>> 5;
yVelocityAvailable = yVelocity != 0;
yVelocity = (yVelocity - 1) * (isSupersonic() ? 4 : 1);
if ((data[7] & 0b10000000) != 0) {
yVelocity *= -1;
}


return this;
}

@Override
public void apply(Track track) {
track.setNACv(NACv.ordinal());

if (isGnssAltitudeDifferenceFromBaroAvailable()) {
track.setGeometricHeightOffset(getGnssAltitudeDifferenceFromBaro());
}

if (isRocdAvailable()) {
track.setRocdAvailable(true);
track.setRocdSourceBaro(getRocdSource() == RocdSource.BARO);
if (getRocdSource() == RocdSource.BARO) {
track.setBaroRocd(getRocd());
} else {
track.setRocd(getRocd());
}
}

if (xVelocityAvailable) {
track.setVx(xVelocity);
}

if (yVelocityAvailable) {
track.setVy(yVelocity);
}

if (xVelocityAvailable && yVelocityAvailable) {
track.setGs(Math.sqrt(xVelocity * xVelocity + yVelocity * yVelocity));
}
}
}

This file was deleted.

Loading

0 comments on commit 8178323

Please sign in to comment.