[FSD] Add slowfast and stopped packets for Velocity

This commit is contained in:
Mat Sutcliffe
2022-02-16 19:49:50 +00:00
parent edc175d133
commit f945f296c8
9 changed files with 392 additions and 6 deletions

View File

@@ -31,6 +31,8 @@
#include "blackcore/fsd/servererror.h"
#include "blackcore/fsd/interimpilotdataupdate.h"
#include "blackcore/fsd/visualpilotdataupdate.h"
#include "blackcore/fsd/visualpilotdataperiodic.h"
#include "blackcore/fsd/visualpilotdatastopped.h"
#include "blackcore/fsd/visualpilotdatatoggle.h"
#include "blackcore/fsd/planeinforequest.h"
#include "blackcore/fsd/planeinformation.h"
@@ -411,6 +413,7 @@ namespace BlackCore::Fsd
{
if (m_stoppedSendingVisualPositions) { return; }
m_stoppedSendingVisualPositions = true;
m_visualPositionUpdateSentCount = 0;
}
else
{
@@ -436,7 +439,19 @@ namespace BlackCore::Fsd
myAircraft.getVelocity().getPitchVelocity(CAngleUnit::rad(), CTimeUnit::s()),
myAircraft.getVelocity().getRollVelocity(CAngleUnit::rad(), CTimeUnit::s()),
myAircraft.getVelocity().getHeadingVelocity(CAngleUnit::rad(), CTimeUnit::s()));
sendQueudedMessage(visualPilotDataUpdate);
if (m_stoppedSendingVisualPositions)
{
sendQueudedMessage(visualPilotDataUpdate.toStopped());
}
else if (m_visualPositionUpdateSentCount++ % 25 == 0)
{
sendQueudedMessage(visualPilotDataUpdate.toPeriodic());
}
else
{
sendQueudedMessage(visualPilotDataUpdate);
}
}
void CFSDClient::sendAtcDataUpdate(double latitude, double longitude)
@@ -1068,6 +1083,8 @@ namespace BlackCore::Fsd
m_messageTypeMapping["$!!"] = MessageType::KillRequest;
m_messageTypeMapping["@"] = MessageType::PilotDataUpdate;
m_messageTypeMapping["^"] = MessageType::VisualPilotDataUpdate;
m_messageTypeMapping["#SL"] = MessageType::VisualPilotDataPeriodic;
m_messageTypeMapping["#ST"] = MessageType::VisualPilotDataStopped;
m_messageTypeMapping["$SF"] = MessageType::VisualPilotDataToggle;
m_messageTypeMapping["$PI"] = MessageType::Ping;
m_messageTypeMapping["$PO"] = MessageType::Pong;
@@ -1268,9 +1285,16 @@ namespace BlackCore::Fsd
emit euroscopeSimDataUpdatedReceived(situation, parts, currentOffsetTime(data.sender()), data.m_model, data.m_livery);
}
void CFSDClient::handleVisualPilotDataUpdate(const QStringList &tokens)
void CFSDClient::handleVisualPilotDataUpdate(const QStringList &tokens, MessageType messageType)
{
const VisualPilotDataUpdate dataUpdate = VisualPilotDataUpdate::fromTokens(tokens);
VisualPilotDataUpdate dataUpdate;
switch (messageType)
{
case MessageType::VisualPilotDataUpdate: dataUpdate = VisualPilotDataUpdate::fromTokens(tokens); break;
case MessageType::VisualPilotDataPeriodic: dataUpdate = VisualPilotDataPeriodic::fromTokens(tokens).toUpdate(); break;
case MessageType::VisualPilotDataStopped: dataUpdate = VisualPilotDataStopped::fromTokens(tokens).toUpdate(); break;
default: qFatal("Precondition violated"); break;
}
const CCallsign callsign(dataUpdate.sender(), CCallsign::Aircraft);
CAircraftSituation situation(
@@ -1866,6 +1890,7 @@ namespace BlackCore::Fsd
{
m_stoppedSendingVisualPositions = false;
m_serverWantsVisualPositions = false;
m_visualPositionUpdateSentCount = 0;
m_textMessagesToConsolidate.clear();
m_pendingAtisQueries.clear();
m_lastPositionUpdate.clear();
@@ -2217,7 +2242,9 @@ namespace BlackCore::Fsd
case MessageType::TextMessage: handleTextMessage(tokens); break;
case MessageType::PilotClientCom: handleCustomPilotPacket(tokens); break;
case MessageType::RevBClientParts: handleRevBClientPartsPacket(tokens); break;
case MessageType::VisualPilotDataUpdate: handleVisualPilotDataUpdate(tokens); break;
case MessageType::VisualPilotDataUpdate:
case MessageType::VisualPilotDataPeriodic:
case MessageType::VisualPilotDataStopped: handleVisualPilotDataUpdate(tokens, messageType); break;
case MessageType::VisualPilotDataToggle: handleVisualPilotDataToggle(tokens); break;
case MessageType::EuroscopeSimData: handleEuroscopeSimData(tokens); break;

View File

@@ -366,7 +366,7 @@ namespace BlackCore::Fsd
void handleDeletePilot(const QStringList &tokens);
void handleTextMessage(const QStringList &tokens);
void handlePilotDataUpdate(const QStringList &tokens);
void handleVisualPilotDataUpdate(const QStringList &tokens);
void handleVisualPilotDataUpdate(const QStringList &tokens, MessageType messageType);
void handleVisualPilotDataToggle(const QStringList &tokens);
void handleEuroscopeSimData(const QStringList &tokens);
void handlePing(const QStringList &tokens);
@@ -574,6 +574,7 @@ namespace BlackCore::Fsd
static int constexpr c_sendFsdMsgIntervalMsec = 10; //!< interval for FSD send messages
bool m_stoppedSendingVisualPositions = false; //!< for when velocity drops to zero
bool m_serverWantsVisualPositions = false; //!< there are interested clients in range
unsigned m_visualPositionUpdateSentCount = 0; //!< for choosing when to send a periodic (slowfast) packet
};
} // ns

View File

@@ -40,6 +40,8 @@ enum class MessageType
KillRequest,
PilotDataUpdate,
VisualPilotDataUpdate,
VisualPilotDataPeriodic,
VisualPilotDataStopped,
VisualPilotDataToggle,
Ping,
Pong,

View File

@@ -0,0 +1,90 @@
/* Copyright (C) 2019
* swift project community / contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
* or distributed except according to the terms contained in the LICENSE file.
*/
#include "visualpilotdataperiodic.h"
#include "visualpilotdataupdate.h"
#include "pbh.h"
#include "serializer.h"
#include "blackmisc/logmessage.h"
using namespace BlackMisc;
using namespace BlackMisc::Aviation;
namespace BlackCore::Fsd
{
VisualPilotDataPeriodic::VisualPilotDataPeriodic() : MessageBase()
{ }
VisualPilotDataPeriodic::VisualPilotDataPeriodic(const QString &sender, double latitude, double longitude, double altitudeTrue, double heightAgl,
double pitch, double bank, double heading, double xVelocity, double yVelocity, double zVelocity,
double pitchRadPerSec, double bankRadPerSec, double headingRadPerSec, double noseGearAngle)
: MessageBase(sender, {}),
m_latitude(latitude),
m_longitude(longitude),
m_altitudeTrue(altitudeTrue),
m_heightAgl(heightAgl),
m_pitch(pitch),
m_bank(bank),
m_heading(heading),
m_xVelocity(xVelocity),
m_yVelocity(yVelocity),
m_zVelocity(zVelocity),
m_pitchRadPerSec(pitchRadPerSec),
m_bankRadPerSec(bankRadPerSec),
m_headingRadPerSec(headingRadPerSec),
m_noseGearAngle(noseGearAngle)
{ }
QStringList VisualPilotDataPeriodic::toTokens() const
{
std::uint32_t pbh;
packPBH(m_pitch, m_bank, m_heading, false/*! \todo check if needed? */, pbh);
QStringList tokens;
tokens.push_back(m_sender);
tokens.push_back(QString::number(m_latitude, 'f', 7));
tokens.push_back(QString::number(m_longitude, 'f', 7));
tokens.push_back(QString::number(m_altitudeTrue, 'f', 2));
tokens.push_back(QString::number(m_heightAgl, 'f', 2));
tokens.push_back(QString::number(pbh));
tokens.push_back(QString::number(m_xVelocity, 'f', 4));
tokens.push_back(QString::number(m_yVelocity, 'f', 4));
tokens.push_back(QString::number(m_zVelocity, 'f', 4));
tokens.push_back(QString::number(m_pitchRadPerSec, 'f', 4));
tokens.push_back(QString::number(m_headingRadPerSec, 'f', 4));
tokens.push_back(QString::number(m_bankRadPerSec, 'f', 4));
tokens.push_back(QString::number(m_noseGearAngle, 'f', 2));
return tokens;
}
VisualPilotDataPeriodic VisualPilotDataPeriodic::fromTokens(const QStringList &tokens)
{
if (tokens.size() < 12)
{
CLogMessage(static_cast<VisualPilotDataPeriodic *>(nullptr)).debug(u"Wrong number of arguments.");
return {};
}
double pitch = 0.0;
double bank = 0.0;
double heading = 0.0;
bool unused = false; //! \todo check if needed?
unpackPBH(tokens[5].toUInt(), pitch, bank, heading, unused);
return VisualPilotDataPeriodic(tokens[0], tokens[1].toDouble(), tokens[2].toDouble(), tokens[3].toDouble(), tokens[4].toDouble(),
pitch, bank, heading, tokens[6].toDouble(), tokens[7].toDouble(), tokens[8].toDouble(), tokens[9].toDouble(),
tokens[11].toDouble(), tokens[10].toDouble(), tokens.value(12, QStringLiteral("0")).toDouble());
}
VisualPilotDataUpdate VisualPilotDataPeriodic::toUpdate() const
{
return VisualPilotDataUpdate(m_sender, m_latitude, m_longitude, m_altitudeTrue, m_heightAgl, m_pitch, m_bank, m_heading,
m_xVelocity, m_yVelocity, m_zVelocity, m_pitchRadPerSec, m_bankRadPerSec, m_headingRadPerSec, m_noseGearAngle);
}
}

View File

@@ -0,0 +1,90 @@
/* Copyright (C) 2019
* swift project community / contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
* or distributed except according to the terms contained in the LICENSE file.
*/
//! \file
#ifndef BLACKCORE_FSD_VISUALPILOTDATAPERIODIC_H
#define BLACKCORE_FSD_VISUALPILOTDATAPERIODIC_H
#include "messagebase.h"
#include "enums.h"
namespace BlackCore::Fsd
{
class VisualPilotDataUpdate;
//! Every 25th VisualPilotDataUpdate is actually one of these ("slowfast").
class BLACKCORE_EXPORT VisualPilotDataPeriodic : public MessageBase
{
public:
//! Constructor
VisualPilotDataPeriodic(const QString &sender, double latitude, double longitude, double altitudeTrue, double heightAgl,
double pitch, double bank, double heading, double xVelocity, double yVelocity, double zVelocity,
double pitchRadPerSec, double bankRadPerSec, double headingRadPerSec, double noseGearAngle = 0.0);
//! Message converted to tokens
QStringList toTokens() const;
//! Construct from tokens
static VisualPilotDataPeriodic fromTokens(const QStringList &tokens);
//! PDU identifier
static QString pdu() { return "#SL"; }
//! Return a regular visual update with the same values
VisualPilotDataUpdate toUpdate() const;
//! Properties
//! @{
double m_latitude = 0.0;
double m_longitude = 0.0;
double m_altitudeTrue = 0.0;
double m_heightAgl = 0.0;
double m_pitch = 0.0;
double m_bank = 0.0;
double m_heading = 0.0;
double m_xVelocity = 0.0;
double m_yVelocity = 0.0;
double m_zVelocity = 0.0;
double m_pitchRadPerSec = 0.0;
double m_bankRadPerSec = 0.0;
double m_headingRadPerSec = 0.0;
double m_noseGearAngle = 0.0;
//! @}
private:
VisualPilotDataPeriodic();
};
//! Equal to operator
inline bool operator==(const VisualPilotDataPeriodic &lhs, const VisualPilotDataPeriodic &rhs)
{
return qFuzzyCompare(lhs.m_latitude, rhs.m_latitude) &&
qFuzzyCompare(lhs.m_longitude, rhs.m_longitude) &&
qFuzzyCompare(lhs.m_altitudeTrue, rhs.m_altitudeTrue) &&
qFuzzyCompare(lhs.m_heightAgl, rhs.m_heightAgl) &&
qFuzzyCompare(lhs.m_pitch, rhs.m_pitch) &&
qFuzzyCompare(lhs.m_bank, rhs.m_bank) &&
qFuzzyCompare(lhs.m_heading, rhs.m_heading) &&
qFuzzyCompare(lhs.m_xVelocity, rhs.m_xVelocity) &&
qFuzzyCompare(lhs.m_yVelocity, rhs.m_yVelocity) &&
qFuzzyCompare(lhs.m_zVelocity, rhs.m_zVelocity) &&
qFuzzyCompare(lhs.m_pitchRadPerSec, rhs.m_pitchRadPerSec) &&
qFuzzyCompare(lhs.m_bankRadPerSec, rhs.m_bankRadPerSec) &&
qFuzzyCompare(lhs.m_headingRadPerSec, rhs.m_headingRadPerSec) &&
qFuzzyCompare(lhs.m_noseGearAngle, rhs.m_noseGearAngle);
}
//! Not equal to operator
inline bool operator!=(const VisualPilotDataPeriodic &lhs, const VisualPilotDataPeriodic &rhs)
{
return !(lhs == rhs);
}
}
#endif // guard

View File

@@ -0,0 +1,76 @@
/* Copyright (C) 2019
* swift project community / contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
* or distributed except according to the terms contained in the LICENSE file.
*/
#include "visualpilotdatastopped.h"
#include "visualpilotdataupdate.h"
#include "pbh.h"
#include "serializer.h"
#include "blackmisc/logmessage.h"
using namespace BlackMisc;
using namespace BlackMisc::Aviation;
namespace BlackCore::Fsd
{
VisualPilotDataStopped::VisualPilotDataStopped() : MessageBase()
{ }
VisualPilotDataStopped::VisualPilotDataStopped(const QString &sender, double latitude, double longitude, double altitudeTrue, double heightAgl,
double pitch, double bank, double heading, double noseGearAngle)
: MessageBase(sender, {}),
m_latitude(latitude),
m_longitude(longitude),
m_altitudeTrue(altitudeTrue),
m_heightAgl(heightAgl),
m_pitch(pitch),
m_bank(bank),
m_heading(heading),
m_noseGearAngle(noseGearAngle)
{ }
QStringList VisualPilotDataStopped::toTokens() const
{
std::uint32_t pbh;
packPBH(m_pitch, m_bank, m_heading, false/*! \todo check if needed? */, pbh);
QStringList tokens;
tokens.push_back(m_sender);
tokens.push_back(QString::number(m_latitude, 'f', 7));
tokens.push_back(QString::number(m_longitude, 'f', 7));
tokens.push_back(QString::number(m_altitudeTrue, 'f', 2));
tokens.push_back(QString::number(m_heightAgl, 'f', 2));
tokens.push_back(QString::number(pbh));
tokens.push_back(QString::number(m_noseGearAngle, 'f', 2));
return tokens;
}
VisualPilotDataStopped VisualPilotDataStopped::fromTokens(const QStringList &tokens)
{
if (tokens.size() < 6)
{
CLogMessage(static_cast<VisualPilotDataStopped *>(nullptr)).debug(u"Wrong number of arguments.");
return {};
}
double pitch = 0.0;
double bank = 0.0;
double heading = 0.0;
bool unused = false; //! \todo check if needed?
unpackPBH(tokens[5].toUInt(), pitch, bank, heading, unused);
return VisualPilotDataStopped(tokens[0], tokens[1].toDouble(), tokens[2].toDouble(), tokens[3].toDouble(), tokens[4].toDouble(),
pitch, bank, heading, tokens.value(12, QStringLiteral("0")).toDouble());
}
VisualPilotDataUpdate VisualPilotDataStopped::toUpdate() const
{
return VisualPilotDataUpdate(m_sender, m_latitude, m_longitude, m_altitudeTrue, m_heightAgl, m_pitch, m_bank, m_heading,
0, 0, 0, 0, 0, 0, m_noseGearAngle);
}
}

View File

@@ -0,0 +1,77 @@
/* Copyright (C) 2019
* swift project community / contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
* or distributed except according to the terms contained in the LICENSE file.
*/
//! \file
#ifndef BLACKCORE_FSD_VISUALPILOTDATASTOPPED_H
#define BLACKCORE_FSD_VISUALPILOTDATASTOPPED_H
#include "messagebase.h"
#include "enums.h"
namespace BlackCore::Fsd
{
class VisualPilotDataUpdate;
//! VisualPilotDataUpdate with velocity assumed to be zero.
class BLACKCORE_EXPORT VisualPilotDataStopped : public MessageBase
{
public:
//! Constructor
VisualPilotDataStopped(const QString &sender, double latitude, double longitude, double altitudeTrue, double heightAgl,
double pitch, double bank, double heading, double noseGearAngle = 0.0);
//! Message converted to tokens
QStringList toTokens() const;
//! Construct from tokens
static VisualPilotDataStopped fromTokens(const QStringList &tokens);
//! PDU identifier
static QString pdu() { return "#ST"; }
//! Return a regular visual update with the same values
VisualPilotDataUpdate toUpdate() const;
//! Properties
//! @{
double m_latitude = 0.0;
double m_longitude = 0.0;
double m_altitudeTrue = 0.0;
double m_heightAgl = 0.0;
double m_pitch = 0.0;
double m_bank = 0.0;
double m_heading = 0.0;
double m_noseGearAngle = 0.0;
//! @}
private:
VisualPilotDataStopped();
};
//! Equal to operator
inline bool operator==(const VisualPilotDataStopped &lhs, const VisualPilotDataStopped &rhs)
{
return qFuzzyCompare(lhs.m_latitude, rhs.m_latitude) &&
qFuzzyCompare(lhs.m_longitude, rhs.m_longitude) &&
qFuzzyCompare(lhs.m_altitudeTrue, rhs.m_altitudeTrue) &&
qFuzzyCompare(lhs.m_heightAgl, rhs.m_heightAgl) &&
qFuzzyCompare(lhs.m_pitch, rhs.m_pitch) &&
qFuzzyCompare(lhs.m_bank, rhs.m_bank) &&
qFuzzyCompare(lhs.m_heading, rhs.m_heading) &&
qFuzzyCompare(lhs.m_noseGearAngle, rhs.m_noseGearAngle);
}
//! Not equal to operator
inline bool operator!=(const VisualPilotDataStopped &lhs, const VisualPilotDataStopped &rhs)
{
return !(lhs == rhs);
}
}
#endif // guard

View File

@@ -7,6 +7,8 @@
*/
#include "visualpilotdataupdate.h"
#include "visualpilotdataperiodic.h"
#include "visualpilotdatastopped.h"
#include "pbh.h"
#include "serializer.h"
@@ -80,4 +82,16 @@ namespace BlackCore::Fsd
pitch, bank, heading, tokens[6].toDouble(), tokens[7].toDouble(), tokens[8].toDouble(), tokens[9].toDouble(),
tokens[11].toDouble(), tokens[10].toDouble(), tokens.value(12, QStringLiteral("0")).toDouble());
}
VisualPilotDataPeriodic VisualPilotDataUpdate::toPeriodic() const
{
return VisualPilotDataPeriodic(m_sender, m_latitude, m_longitude, m_altitudeTrue, m_heightAgl, m_pitch, m_bank, m_heading,
m_xVelocity, m_yVelocity, m_zVelocity, m_pitchRadPerSec, m_bankRadPerSec, m_headingRadPerSec, m_noseGearAngle);
}
VisualPilotDataStopped VisualPilotDataUpdate::toStopped() const
{
return VisualPilotDataStopped(m_sender, m_latitude, m_longitude, m_altitudeTrue, m_heightAgl, m_pitch, m_bank, m_heading,
m_noseGearAngle);
}
}

View File

@@ -16,6 +16,9 @@
namespace BlackCore::Fsd
{
class VisualPilotDataPeriodic;
class VisualPilotDataStopped;
//! Pilot data update broadcasted to pilots in range every 0.2 seconds.
class BLACKCORE_EXPORT VisualPilotDataUpdate : public MessageBase
{
@@ -34,6 +37,12 @@ namespace BlackCore::Fsd
//! PDU identifier
static QString pdu() { return "^"; }
//! Return a periodic update with the same values
VisualPilotDataPeriodic toPeriodic() const;
//! Return a stopped update with the same values
VisualPilotDataStopped toStopped() const;
//! Properties
//! @{
double m_latitude = 0.0;
@@ -52,7 +61,7 @@ namespace BlackCore::Fsd
double m_noseGearAngle = 0.0;
//! @}
private:
//private: // not private: used in CFSDClient::handleVisualPilotDataUpdate
VisualPilotDataUpdate();
};