Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package de.serosystems.lib1090.msgs.adsb;
import de.serosystems.lib1090.decoding.Airspeed;
import de.serosystems.lib1090.exceptions.BadFormatException;
import de.serosystems.lib1090.exceptions.UnspecifiedFormatError;
import de.serosystems.lib1090.msgs.modes.ExtendedSquitter;
import java.io.Serializable;
/*
* This file is part of de.serosystems.lib1090.
*
* de.serosystems.lib1090 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* de.serosystems.lib1090 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with de.serosystems.lib1090. If not, see .
*/
/**
* Decoder for ADS-B airspeed and heading messages
* @author Matthias Schäfer ([email protected])
*/
public class AirspeedHeadingMsg extends ExtendedSquitter implements Serializable {
private static final long serialVersionUID = 6901092011249128775L;
private byte msg_subtype;
private boolean intent_change;
private boolean ifr_capability;
private byte navigation_accuracy_category;
private boolean heading_status_bit;
private double heading; // in degrees
private boolean true_airspeed; // 0 = indicated AS, 1 = true AS
private short airspeed; // in knots
private boolean airspeed_available;
private boolean vertical_source; // 0 = geometric, 1 = barometric
private boolean vertical_rate_down; // 0 = up, 1 = down
private short vertical_rate; // in ft/s
private boolean vertical_rate_info_available;
private int geo_minus_baro; // in ft
private boolean geo_minus_baro_available;
/** protected no-arg constructor e.g. for serialization with Kryo **/
protected AirspeedHeadingMsg() { }
/**
* @param raw_message raw ADS-B airspeed and heading message as hex string
* @throws BadFormatException if message has wrong format
* @throws UnspecifiedFormatError if message has format that is not further specified in DO-260B
*/
public AirspeedHeadingMsg(String raw_message) throws BadFormatException, UnspecifiedFormatError {
this(new ExtendedSquitter(raw_message));
}
/**
* @param raw_message raw ADS-B airspeed and heading message as byte array
* @throws BadFormatException if message has wrong format
* @throws UnspecifiedFormatError if message has format that is not further specified in DO-260B
*/
public AirspeedHeadingMsg(byte[] raw_message) throws BadFormatException, UnspecifiedFormatError {
this(new ExtendedSquitter(raw_message));
}
/**
* @param squitter extended squitter containing the airspeed and heading msg
* @throws BadFormatException if message has wrong format
*/
public AirspeedHeadingMsg(ExtendedSquitter squitter) throws BadFormatException {
super(squitter);
setType(subtype.ADSB_AIRSPEED);
if (this.getFormatTypeCode() != 19) {
throw new BadFormatException("Airspeed and heading messages must have typecode 19.");
}
byte[] msg = this.getMessage();
msg_subtype = (byte) (msg[0]&0x7);
if (msg_subtype != 3 && msg_subtype != 4) {
throw new BadFormatException("Airspeed and heading messages have subtype 3 or 4.");
}
intent_change = (msg[1]&0x80)>0;
ifr_capability = (msg[1]&0x40)>0;
navigation_accuracy_category = (byte) ((msg[1]>>>3)&0x7);
// check this later
vertical_rate_info_available = true;
geo_minus_baro_available = true;
// heading available in ADS-B version 1+, indicates true/magnetic north for version 0
heading_status_bit = (msg[1]&0x4)>0;
heading = ((msg[1]&0x3)<<8 | msg[2]&0xFF) * 360./1024.;
true_airspeed = (msg[3]&0x80)>0;
airspeed = (short) (((msg[3]&0x7F)<<3 | msg[4]>>>5&0x07)-1);
if (airspeed != -1) {
airspeed_available = true;
if (msg_subtype == 4) airspeed<<=2;
}
vertical_source = (msg[4]&0x10)>0;
vertical_rate_down = (msg[4]&0x08)>0;
vertical_rate = (short) ((((msg[4]&0x07)<<6 | msg[5]>>>2&0x3F)-1)<<6);
geo_minus_baro = (short) (((msg[6]&0x7F)-1)*25);
if ((msg[6]&0x80)>0) geo_minus_baro *= -1;
}
/**
* For ADS-B version 1 and 2 this must be checked before retrieving heading information.
*
* @return Depending on the ADS-B version, different interpretations:
*
*
Version 0 the flag indicates whether heading is relative to magnetic north (true) or
* true north (false)
*
Version 1+ the flag indicates whether heading information is available or not
*
*/
public boolean hasHeadingStatusFlag() {
return heading_status_bit;
}
/**
* Must be checked before accessing airspeed!
*
* @return whether airspeed info is available
*/
public boolean hasAirspeedInfo() {
return airspeed_available;
}
/**
* Must be checked before accessing vertical rate!
*
* @return whether vertical rate info is available
*/
public boolean hasVerticalRateInfo() {
return vertical_rate_info_available;
}
/**
* Must be checked before accessing geo minus baro!
*
* @return whether geo-baro difference info is available
*/
public boolean hasGeoMinusBaroInfo() {
return geo_minus_baro_available;
}
/**
* @return If supersonic, velocity has only 4 kts accuracy, otherwise 1 kt
*/
public boolean isSupersonic() {
return msg_subtype == 4;
}
/**
* @return true, if aircraft wants to change altitude for instance
*/
public boolean hasChangeIntent() {
return intent_change;
}
/**
* Note: only in ADS-B version 0 and 1 transponders!!
* @return true, iff aircraft has equipage class A1 or higher
*/
public boolean hasIFRCapability() {
return ifr_capability;
}
/**
* The 95% accuracy for horizontal velocity. We interpret the coding according to
* DO-260B Table 2-22 for all ADS-B versions.
* @return Navigation Accuracy Category for velocity according to RTCA DO-260B 2.2.3.2.6.1.5 in m/s, -1 means
* "unknown" or >10m
*/
public double getNACv() {
return Airspeed.decodeNACv(navigation_accuracy_category);
}
/**
* @return airspeed in knots or null if information is not available. The latter can also be checked using
* {@link #hasAirspeedInfo()}.
*/
public Integer getAirspeed() {
if (!airspeed_available) return null;
return (int) airspeed;
}
/**
* @return whether altitude is derived by barometric sensor or GNSS
*/
public boolean isBarometricVerticalSpeed() {
return vertical_source;
}
/**
* @return vertical rate in feet/min (negative value means descending) or null if information is not available. The
* latter can also be checked with {@link #hasVerticalRateInfo()}.
*/
public Integer getVerticalRate() {
if (!vertical_rate_info_available) return null;
return (vertical_rate_down ? -vertical_rate : vertical_rate);
}
/**
* @return difference between barometric and geometric altitude in feet or null if no information is available.
* The latter can also be checked using {@link #hasGeoMinusBaroInfo()}.
*/
public Integer getGeoMinusBaro() {
if (!geo_minus_baro_available) return null;
return geo_minus_baro;
}
/**
* @return heading in decimal degrees ([0, 360]). 0° = geographic north or null if no information is available.
* The latter can also be checked using {@link #hasHeadingStatusFlag()}.
*/
public Double getHeading() {
if (!heading_status_bit) return null;
return heading;
}
/**
* @return true if airspeed is true airspeed, false if airspeed is indicated airspeed
*/
public boolean isTrueAirspeed() {
return true_airspeed;
}
@Override
public String toString() {
return super.toString() + "\n\tAirspeedHeadingMsg{" +
"msg_subtype=" + msg_subtype +
", intent_change=" + intent_change +
", ifr_capability=" + ifr_capability +
", navigation_accuracy_category=" + navigation_accuracy_category +
", heading_status_bit=" + heading_status_bit +
", heading=" + heading +
", true_airspeed=" + true_airspeed +
", airspeed=" + airspeed +
", airspeed_available=" + airspeed_available +
", vertical_source=" + vertical_source +
", vertical_rate_down=" + vertical_rate_down +
", vertical_rate=" + vertical_rate +
", vertical_rate_info_available=" + vertical_rate_info_available +
", geo_minus_baro=" + geo_minus_baro +
", geo_minus_baro_available=" + geo_minus_baro_available +
'}';
}
}