Skip to content

Commit

Permalink
ADSB: Handle Missing Data
Browse files Browse the repository at this point in the history
  • Loading branch information
HTRamsey committed Jan 7, 2025
1 parent eb2e314 commit 20a6f1b
Show file tree
Hide file tree
Showing 10 changed files with 201 additions and 102 deletions.
33 changes: 23 additions & 10 deletions src/ADSB/ADSB.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#pragma once

#include "MAVLinkLib.h"

#include <QtCore/QMetaType>
#include <QtPositioning/QGeoCoordinate>

Expand Down Expand Up @@ -38,24 +40,35 @@ Q_ENUM_NS(MessageType)

/// Enum for ADSB Info Types Available.
enum AvailableInfoType {
CallsignAvailable = 1 << 0,
LocationAvailable = 1 << 1,
AltitudeAvailable = 1 << 2,
HeadingAvailable = 1 << 3,
AlertAvailable = 1 << 4,
LocationAvailable = 1 << 0,
AltitudeAvailable = 1 << 1,
HeadingAvailable = 1 << 2,
VelocityAvailable = 1 << 3,
CallsignAvailable = 1 << 4,
SquawkAvailable = 1 << 5,
VerticalVelAvailable = 1 << 6,
AlertAvailable = 1 << 7
};
Q_FLAG_NS(AvailableInfoType)
Q_DECLARE_FLAGS(AvailableInfoTypes, AvailableInfoType)
Q_DECLARE_OPERATORS_FOR_FLAGS(AvailableInfoTypes)

struct VehicleInfo_t {
uint32_t icaoAddress;
AvailableInfoTypes availableFlags;
uint32_t icaoAddress = 0;
QString callsign;
QGeoCoordinate location;
double altitude; // TODO: Use Altitude in QGeoCoordinate?
double heading;
bool alert;
AvailableInfoTypes availableFlags;
double heading = 0.0;
uint16_t squawk = 0;
double velocity = 0.0;
double verticalVel = 0.0;
uint32_t lastContact = 0;
bool simulated = false;
bool baro = false;
bool alert = false;
ADSB_ALTITUDE_TYPE altitudeeType = ADSB_ALTITUDE_TYPE_PRESSURE_QNH;
ADSB_EMITTER_TYPE emitterType = ADSB_EMITTER_TYPE_NO_INFO;
// TODO: Use QGeoPositionInfo, QGeoPositionInfoSource, QGeoPositionInfoSourceFactory
};
} // namespace ADSB

Expand Down
45 changes: 21 additions & 24 deletions src/ADSB/ADSBTCPLink.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,26 @@ ADSBTCPLink::ADSBTCPLink(const QHostAddress &hostAddress, quint16 port, QObject
, _socket(new QTcpSocket(this))
, _processTimer(new QTimer(this))
{
#ifdef QT_DEBUG
(void) connect(_socket, &QTcpSocket::stateChanged, this, [](QTcpSocket::SocketState state) {
switch (state) {
case QTcpSocket::UnconnectedState:
qCDebug(ADSBTCPLinkLog) << "ADSB Socket disconnected";
break;
case QTcpSocket::SocketState::ConnectingState:
qCDebug(ADSBTCPLinkLog) << "ADSB Socket connecting...";
break;
case QTcpSocket::SocketState::ConnectedState:
qCDebug(ADSBTCPLinkLog) << "ADSB Socket connected";
break;
case QTcpSocket::SocketState::ClosingState:
qCDebug(ADSBTCPLinkLog) << "ADSB Socket closing...";
break;
default:
break;
}
}, Qt::AutoConnection);
#endif
if (ADSBTCPLinkLog().isDebugEnabled()) {
(void) connect(_socket, &QTcpSocket::stateChanged, this, [](QTcpSocket::SocketState state) {
switch (state) {
case QTcpSocket::UnconnectedState:
qCDebug(ADSBTCPLinkLog) << "ADSB Socket disconnected";
break;
case QTcpSocket::SocketState::ConnectingState:
qCDebug(ADSBTCPLinkLog) << "ADSB Socket connecting...";
break;
case QTcpSocket::SocketState::ConnectedState:
qCDebug(ADSBTCPLinkLog) << "ADSB Socket connected";
break;
case QTcpSocket::SocketState::ClosingState:
qCDebug(ADSBTCPLinkLog) << "ADSB Socket closing...";
break;
default:
break;
}
}, Qt::AutoConnection);
}

(void) QObject::connect(_socket, &QTcpSocket::errorOccurred, this, [this](QTcpSocket::SocketError error) {
qCDebug(ADSBTCPLinkLog) << error << _socket->errorString();
Expand All @@ -55,8 +55,6 @@ ADSBTCPLink::ADSBTCPLink(const QHostAddress &hostAddress, quint16 port, QObject
_processTimer->setInterval(_processInterval); // Set an interval for processing lines
(void) connect(_processTimer, &QTimer::timeout, this, &ADSBTCPLink::_processLines);

init();

// qCDebug(ADSBTCPLinkLog) << Q_FUNC_INFO << this;
}

Expand Down Expand Up @@ -209,10 +207,9 @@ void ADSBTCPLink::_parseAndEmitLocation(ADSB::VehicleInfo_t &adsbInfo, const QSt
}

const double altitude = modeCAltitude * 0.3048;
const QGeoCoordinate location(lat, lon);
const QGeoCoordinate location(lat, lon, altitude);

adsbInfo.location = location;
adsbInfo.altitude = altitude;
adsbInfo.alert = (alert == 1);
adsbInfo.availableFlags = ADSB::LocationAvailable | ADSB::AltitudeAvailable | ADSB::AlertAvailable;

Expand Down
52 changes: 37 additions & 15 deletions src/ADSB/ADSBVehicle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ QGC_LOGGING_CATEGORY(ADSBVehicleLog, "qgc.adsb.adsbvehicle")
ADSBVehicle::ADSBVehicle(const ADSB::VehicleInfo_t &vehicleInfo, QObject *parent)
: QObject(parent)
{
// qCDebug(ADSBVehicleLog) << Q_FUNC_INFO << this;

_info.icaoAddress = vehicleInfo.icaoAddress;
update(vehicleInfo);

// qCDebug(ADSBTCPLinkLog) << Q_FUNC_INFO << this;
}

ADSBVehicle::~ADSBVehicle()
{
// qCDebug(ADSBTCPLinkLog) << Q_FUNC_INFO << this;
// qCDebug(ADSBVehicleLog) << Q_FUNC_INFO << this;
}

void ADSBVehicle::update(const ADSB::VehicleInfo_t &vehicleInfo)
Expand All @@ -38,23 +38,17 @@ void ADSBVehicle::update(const ADSB::VehicleInfo_t &vehicleInfo)

qCDebug(ADSBVehicleLog) << "Updating" << QStringLiteral("%1 Flags: %2").arg(vehicleInfo.icaoAddress, 0, 16).arg(vehicleInfo.availableFlags, 0, 2);

if (vehicleInfo.availableFlags & ADSB::CallsignAvailable) {
if (vehicleInfo.callsign != callsign()) {
_info.callsign = vehicleInfo.callsign;
emit callsignChanged();
}
}

if (vehicleInfo.availableFlags & ADSB::LocationAvailable) {
if (vehicleInfo.location != coordinate()) {
_info.location = vehicleInfo.location;
if (!QGC::fuzzyCompare(vehicleInfo.location.latitude(), coordinate().latitude()) || !QGC::fuzzyCompare(vehicleInfo.location.longitude(), coordinate().longitude())) {
_info.location.setLatitude(vehicleInfo.location.latitude());
_info.location.setLongitude(vehicleInfo.location.longitude());
emit coordinateChanged();
}
}

if (vehicleInfo.availableFlags & ADSB::AltitudeAvailable) {
if (!QGC::fuzzyCompare(vehicleInfo.altitude, altitude())) {
_info.altitude = vehicleInfo.altitude;
if (!QGC::fuzzyCompare(vehicleInfo.location.altitude(), altitude())) {
_info.location.setAltitude(vehicleInfo.location.altitude());
emit altitudeChanged();
}
}
Expand All @@ -66,12 +60,40 @@ void ADSBVehicle::update(const ADSB::VehicleInfo_t &vehicleInfo)
}
}

if (vehicleInfo.availableFlags & ADSB::VelocityAvailable) {
if (!QGC::fuzzyCompare(vehicleInfo.velocity, velocity())) {
_info.velocity = vehicleInfo.velocity;
emit velocityChanged();
}
}

if (vehicleInfo.availableFlags & ADSB::CallsignAvailable) {
if (vehicleInfo.callsign != callsign()) {
_info.callsign = vehicleInfo.callsign;
emit callsignChanged();
}
}

if (vehicleInfo.availableFlags & ADSB::SquawkAvailable) {
if (!QGC::fuzzyCompare(vehicleInfo.velocity, squawk())) {
_info.squawk = vehicleInfo.squawk;
emit squawkChanged();
}
}

if (vehicleInfo.availableFlags & ADSB::VerticalVelAvailable) {
if (!QGC::fuzzyCompare(vehicleInfo.verticalVel, verticalVel())) {
_info.verticalVel = vehicleInfo.verticalVel;
emit verticalVelChanged();
}
}

if (vehicleInfo.availableFlags & ADSB::AlertAvailable) {
if (vehicleInfo.alert != alert()) {
_info.alert = vehicleInfo.alert;
emit alertChanged();
}
}

(void) _lastUpdateTimer.restart();
_lastUpdateTimer.start();
}
23 changes: 16 additions & 7 deletions src/ADSB/ADSBVehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@ class ADSBVehicle : public QObject
Q_OBJECT
QML_ELEMENT

Q_PROPERTY(uint icaoAddress READ icaoAddress CONSTANT)
Q_PROPERTY(QString callsign READ callsign NOTIFY callsignChanged)
Q_PROPERTY(QGeoCoordinate coordinate READ coordinate NOTIFY coordinateChanged)
Q_PROPERTY(double altitude READ altitude NOTIFY altitudeChanged)
Q_PROPERTY(double heading READ heading NOTIFY headingChanged)
Q_PROPERTY(bool alert READ alert NOTIFY alertChanged)
Q_PROPERTY(uint icaoAddress READ icaoAddress CONSTANT)
Q_PROPERTY(QString callsign READ callsign NOTIFY callsignChanged)
Q_PROPERTY(QGeoCoordinate coordinate READ coordinate NOTIFY coordinateChanged)
Q_PROPERTY(double altitude READ altitude NOTIFY altitudeChanged)
Q_PROPERTY(double heading READ heading NOTIFY headingChanged)
Q_PROPERTY(double velocity READ velocity NOTIFY velocityChanged)
Q_PROPERTY(double verticalVel READ verticalVel NOTIFY verticalVelChanged)
Q_PROPERTY(uint16_t squawk READ squawk NOTIFY squawkChanged)
Q_PROPERTY(bool alert READ alert NOTIFY alertChanged)

public:
explicit ADSBVehicle(const ADSB::VehicleInfo_t &vehicleInfo, QObject *parent = nullptr);
Expand All @@ -39,8 +42,11 @@ class ADSBVehicle : public QObject
uint32_t icaoAddress() const { return _info.icaoAddress; }
QString callsign() const { return _info.callsign; }
QGeoCoordinate coordinate() const { return _info.location; }
double altitude() const { return _info.altitude; }
double altitude() const { return _info.location.altitude(); }
double heading() const { return _info.heading; }
double velocity() const { return _info.velocity; }
double verticalVel() const { return _info.verticalVel; }
uint16_t squawk() const { return _info.squawk; }
bool alert() const { return _info.alert; }
bool expired() const { return _lastUpdateTimer.hasExpired(_expirationTimeoutMs); }
void update(const ADSB::VehicleInfo_t &vehicleInfo);
Expand All @@ -50,6 +56,9 @@ class ADSBVehicle : public QObject
void callsignChanged();
void altitudeChanged();
void headingChanged();
void velocityChanged();
void verticalVelChanged();
void squawkChanged();
void alertChanged();

private:
Expand Down
98 changes: 93 additions & 5 deletions src/ADSB/ADSBVehicleManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ ADSBVehicleManager::ADSBVehicleManager(ADSBVehicleManagerSettings *settings, QOb
, _adsbVehicleCleanupTimer(new QTimer(this))
, _adsbVehicles(new QmlObjectListModel(this))
{
// qCDebug(ADSBVehicleManagerLog) << Q_FUNC_INFO << this;

(void) qRegisterMetaType<ADSB::VehicleInfo_t>("ADSB::VehicleInfo_t");

_adsbVehicleCleanupTimer->setSingleShot(false);
Expand All @@ -51,20 +53,97 @@ ADSBVehicleManager::ADSBVehicleManager(ADSBVehicleManagerSettings *settings, QOb
if (adsbEnabled->rawValue().toBool()) {
_start(hostAddress->rawValue().toString(), port->rawValue().toUInt());
}

// qCDebug(ADSBTCPLinkLog) << Q_FUNC_INFO << this;
}

ADSBVehicleManager::~ADSBVehicleManager()
{
// qCDebug(ADSBTCPLinkLog) << Q_FUNC_INFO << this;
// qCDebug(ADSBVehicleManagerLog) << Q_FUNC_INFO << this;
}

ADSBVehicleManager *ADSBVehicleManager::instance()
{
return _adsbVehicleManager();
}

void ADSBVehicleManager::mavlinkMessageReceived(const mavlink_message_t &message)
{
if (message.msgid != MAVLINK_MSG_ID_ADSB_VEHICLE) {
return;
}

_handleADSBVehicle(message);
}

void ADSBVehicleManager::_handleADSBVehicle(const mavlink_message_t &message)
{
mavlink_adsb_vehicle_t adsbVehicleMsg{};
mavlink_msg_adsb_vehicle_decode(&message, &adsbVehicleMsg);

if (adsbVehicleMsg.tslc > kMaxTimeSinceLastSeen) {
return;
}

ADSB::VehicleInfo_t vehicleInfo{};

vehicleInfo.availableFlags = ADSB::AvailableInfoTypes::fromInt(0);

vehicleInfo.icaoAddress = adsbVehicleMsg.ICAO_address;
vehicleInfo.lastContact = adsbVehicleMsg.tslc;

if (adsbVehicleMsg.flags & ADSB_FLAGS_VALID_COORDS) {
vehicleInfo.availableFlags |= ADSB::LocationAvailable;
vehicleInfo.location.setLatitude(adsbVehicleMsg.lat / 1e7);
vehicleInfo.location.setLongitude(adsbVehicleMsg.lon / 1e7);
}

if (adsbVehicleMsg.flags & ADSB_FLAGS_VALID_ALTITUDE) {
vehicleInfo.availableFlags |= ADSB::AltitudeAvailable;
vehicleInfo.location.setAltitude(adsbVehicleMsg.altitude / 1e3);
}

if (adsbVehicleMsg.flags & ADSB_FLAGS_VALID_HEADING) {
vehicleInfo.availableFlags |= ADSB::HeadingAvailable;
vehicleInfo.heading = adsbVehicleMsg.heading / 1e2;
}

if (adsbVehicleMsg.flags & ADSB_FLAGS_VALID_VELOCITY) {
vehicleInfo.availableFlags |= ADSB::VelocityAvailable;
vehicleInfo.velocity = adsbVehicleMsg.hor_velocity / 1e2;
}

if (adsbVehicleMsg.flags & ADSB_FLAGS_VALID_CALLSIGN) {
vehicleInfo.availableFlags |= ADSB::CallsignAvailable;
vehicleInfo.callsign = QString::fromLatin1(adsbVehicleMsg.callsign, sizeof(adsbVehicleMsg.callsign));
}

if (adsbVehicleMsg.flags & ADSB_FLAGS_VALID_SQUAWK) {
vehicleInfo.availableFlags |= ADSB::SquawkAvailable;
vehicleInfo.squawk = adsbVehicleMsg.squawk;
}

if (adsbVehicleMsg.flags & ADSB_FLAGS_SIMULATED) {
vehicleInfo.simulated = true;
}

if (adsbVehicleMsg.flags & ADSB_FLAGS_VERTICAL_VELOCITY_VALID) {
vehicleInfo.availableFlags |= ADSB::VerticalVelAvailable;
vehicleInfo.verticalVel = adsbVehicleMsg.ver_velocity;
}

if (adsbVehicleMsg.flags & ADSB_FLAGS_BARO_VALID) {
vehicleInfo.baro = true;
}

if (adsbVehicleMsg.flags & ADSB_FLAGS_SOURCE_UAT) {

}

adsbVehicleMsg.altitude_type = adsbVehicleMsg.altitude_type;
adsbVehicleMsg.emitter_type = adsbVehicleMsg.emitter_type;

(void) QMetaObject::invokeMethod(this, [this, &vehicleInfo] { adsbVehicleUpdate(vehicleInfo); }, Qt::AutoConnection);
}

void ADSBVehicleManager::adsbVehicleUpdate(const ADSB::VehicleInfo_t &vehicleInfo)
{
const uint32_t icaoAddress = vehicleInfo.icaoAddress;
Expand All @@ -76,15 +155,24 @@ void ADSBVehicleManager::adsbVehicleUpdate(const ADSB::VehicleInfo_t &vehicleInf
if (vehicleInfo.availableFlags & ADSB::LocationAvailable) {
ADSBVehicle* const adsbVehicle = new ADSBVehicle(vehicleInfo, this);
_adsbICAOMap[icaoAddress] = adsbVehicle;
(void) _adsbVehicles->append(adsbVehicle);
_adsbVehicles->append(adsbVehicle);
qCDebug(ADSBVehicleManagerLog) << "Added" << QString::number(adsbVehicle->icaoAddress());
}
}

void ADSBVehicleManager::_start(const QString &hostAddress, quint16 port)
{
Q_ASSERT(!_adsbTcpLink);
_adsbTcpLink = new ADSBTCPLink(QHostAddress(hostAddress), port, this);

ADSBTCPLink *adsbTcpLink = new ADSBTCPLink(QHostAddress(hostAddress), port, this);
if (!adsbTcpLink->init()) {
delete adsbTcpLink;
adsbTcpLink = nullptr;
qCWarning(ADSBVehicleManagerLog) << "Failed to Initialize TCP Link at:" << hostAddress << port;
return;
}

_adsbTcpLink = adsbTcpLink;
(void) connect(_adsbTcpLink, &ADSBTCPLink::adsbVehicleUpdate, this, &ADSBVehicleManager::adsbVehicleUpdate, Qt::AutoConnection);
(void) connect(_adsbTcpLink, &ADSBTCPLink::errorOccurred, this, &ADSBVehicleManager::_linkError, Qt::AutoConnection);

Expand Down
Loading

0 comments on commit 20a6f1b

Please sign in to comment.