diff --git a/src/blackmisc/aviation/aircrafticaocode.cpp b/src/blackmisc/aviation/aircrafticaocode.cpp index 4df439e16..a227a3c69 100644 --- a/src/blackmisc/aviation/aircrafticaocode.cpp +++ b/src/blackmisc/aviation/aircrafticaocode.cpp @@ -198,11 +198,14 @@ namespace BlackMisc return score; } - void CAircraftIcaoCode::guessModelParameters(CLength &guessedCG, CSpeed &guessedLiftOffGs) const + void CAircraftIcaoCode::guessModelParameters(CLength &guessedCGOut, CSpeed &guessedVRotateOut) const { + // we do not override values + if (!guessedCGOut.isNull() && !guessedVRotateOut.isNull()) { return; } + // init to defaults - CLength guessedCG_ = CLength(1.5, CLengthUnit::m()); - CSpeed guessedLiftOffGs_ = this->isVtol() ? CSpeed::null() : CSpeed(70, CSpeedUnit::km_h()); + CLength guessedCG = CLength(1.5, CLengthUnit::m()); + CSpeed guessedVRotate = this->isVtol() ? CSpeed::null() : CSpeed(70, CSpeedUnit::km_h()); const int engines = this->getEnginesCount(); const QChar engineType = this->getEngineType()[0].toUpper(); @@ -210,31 +213,38 @@ namespace BlackMisc { if (engines == 1) { - if (engineType == 'T') { guessedCG_ = CLength(2.0, CLengthUnit::m()); break; } + if (engineType == 'T') { guessedCG = CLength(2.0, CLengthUnit::m()); break; } } else if (engines == 2) { - guessedCG_ = CLength(2.0, CLengthUnit::m()); - guessedLiftOffGs_ = CSpeed(80, CSpeedUnit::kts()); - if (engineType == 'T') { guessedCG_ = CLength(2.0, CLengthUnit::m()); break; } - if (engineType == 'J') { guessedCG_ = CLength(2.5, CLengthUnit::m()); break; } + guessedCG = CLength(2.0, CLengthUnit::m()); + guessedVRotate = CSpeed(100, CSpeedUnit::kts()); + if (engineType == 'T') { guessedCG = CLength(2.0, CLengthUnit::m()); break; } + if (engineType == 'J') + { + // a B737 has VR 105-160kts + guessedVRotate = CSpeed(120, CSpeedUnit::kts()); + guessedCG = CLength(2.5, CLengthUnit::m()); + break; + } } else if (engines > 2) { - guessedCG_ = CLength(4.0, CLengthUnit::m()); - guessedLiftOffGs_ = CSpeed(70, CSpeedUnit::kts()); + guessedCG = CLength(4.0, CLengthUnit::m()); + guessedVRotate = CSpeed(70, CSpeedUnit::kts()); if (engineType == 'J') { - guessedCG_ = CLength(6.0, CLengthUnit::m()); - guessedLiftOffGs_ = CSpeed(100, CSpeedUnit::kts()); + // A typical B747 has VR around 160kts + guessedCG = CLength(6.0, CLengthUnit::m()); + guessedVRotate = CSpeed(140, CSpeedUnit::kts()); break; } } } while (false); - if (!guessedCG_.isNull()) { guessedCG = guessedCG_; } - if (!guessedLiftOffGs_.isNull()) { guessedLiftOffGs = guessedLiftOffGs_; } + if (guessedCGOut.isNull()) { guessedCGOut = guessedCG; } + if (guessedVRotateOut.isNull()) { guessedVRotateOut = guessedVRotate; } } bool CAircraftIcaoCode::isNull() const diff --git a/src/blackmisc/aviation/aircrafticaocode.h b/src/blackmisc/aviation/aircrafticaocode.h index 4018fb76d..6d5d4234e 100644 --- a/src/blackmisc/aviation/aircrafticaocode.h +++ b/src/blackmisc/aviation/aircrafticaocode.h @@ -296,7 +296,8 @@ namespace BlackMisc int calculateScore(const CAircraftIcaoCode &otherCode, CStatusMessageList *log = nullptr) const; //! Guess aircraft model parameters - void guessModelParameters(PhysicalQuantities::CLength &guessedCG, PhysicalQuantities::CSpeed &guessedLiftOffGs) const; + //! \remark values will not be overridden, pass null values to obtain guessed values + void guessModelParameters(PhysicalQuantities::CLength &guessedCGOut, PhysicalQuantities::CSpeed &guessedVRotateOut) const; //! Null ICAO? bool isNull() const; diff --git a/src/blackmisc/aviation/aircraftsituation.h b/src/blackmisc/aviation/aircraftsituation.h index 720513b73..bd154de0d 100644 --- a/src/blackmisc/aviation/aircraftsituation.h +++ b/src/blackmisc/aviation/aircraftsituation.h @@ -293,7 +293,7 @@ namespace BlackMisc //! Set altitude void setAltitude(const CAltitude &altitude) { m_position.setGeodeticHeight(altitude); } - //! Add offset + //! Add offset to altitude CAltitude addAltitudeOffset(const PhysicalQuantities::CLength &offset); //! Get pressure altitude diff --git a/src/blackmisc/aviation/aircraftsituationlist.cpp b/src/blackmisc/aviation/aircraftsituationlist.cpp index 82148731e..418e94e18 100644 --- a/src/blackmisc/aviation/aircraftsituationlist.cpp +++ b/src/blackmisc/aviation/aircraftsituationlist.cpp @@ -14,6 +14,8 @@ #include "blackmisc/math/mathutils.h" #include "blackmisc/pq/speed.h" #include "blackmisc/verify.h" + +#include #include using namespace BlackMisc::Geo; @@ -122,7 +124,6 @@ namespace BlackMisc { for (const CAircraftSituation &situation : *this) { - if (!situation.hasGroundElevation()) { return true; } if (situation.getGroundElevationPlane().getRadius() > range) { return true; } } return false; @@ -195,6 +196,7 @@ namespace BlackMisc CAircraftSituation newerSituation = CAircraftSituation::null(); for (const CAircraftSituation &situation : sorted) { + // latest first if (!newerSituation.isNull()) { Q_ASSERT_X(situation.getAltitude().getReferenceDatum() == newerSituation.getAltitude().getReferenceDatum(), Q_FUNC_INFO, "Wrong reference"); @@ -305,6 +307,28 @@ namespace BlackMisc return c; } + int CAircraftSituationList::countOnGroundWithElevation(CAircraftSituation::IsOnGround og) const + { + int c = 0; + for (const CAircraftSituation &situation : *this) + { + if (situation.hasGroundElevation()) { continue; } + if (situation.getOnGround() == og) { c++; } + } + return c; + } + + CAircraftSituationList CAircraftSituationList::findOnGroundWithElevation(CAircraftSituation::IsOnGround og) const + { + CAircraftSituationList found; + for (const CAircraftSituation &situation : *this) + { + if (situation.hasGroundElevation()) { continue; } + if (situation.getOnGround() == og) { found.push_back(situation); } + } + return found; + } + int CAircraftSituationList::setOnGround(CAircraftSituation::IsOnGround og) { int c = 0; @@ -325,6 +349,15 @@ namespace BlackMisc return c; } + void CAircraftSituationList::addAltitudeOffset(const CLength &offset) + { + if (offset.isNull() || this->isEmpty()) { return; } + for (CAircraftSituation &s : *this) + { + s.addAltitudeOffset(offset); + } + } + bool CAircraftSituationList::isSortedAdjustedLatestFirstWithoutNullPositions() const { return this->isSortedAdjustedLatestFirst() && !this->containsNullPosition(); @@ -359,6 +392,7 @@ namespace BlackMisc return values; } + QList CAircraftSituationList::elevationValues(const CLengthUnit &unit) const { QList values; @@ -393,5 +427,55 @@ namespace BlackMisc } return values; } + + QPair CAircraftSituationList::groundSpeedStandardDeviationAndMean() const + { + const QList gsValues = this->groundSpeedValues(CSpeedUnit::kts()); + if (gsValues.size() != this->size()) { return QPair(CSpeed::null(), CSpeed::null()); } + const QPair gsKts = CMathUtils::standardDeviationAndMean(gsValues); + return QPair(CSpeed(gsKts.first, CSpeedUnit::kts()), CSpeed(gsKts.second, CSpeedUnit::kts())); + } + + QPair CAircraftSituationList::pitchStandardDeviationAndMean() const + { + const QList pitchValues = this->pitchValues(CAngleUnit::deg()); + if (pitchValues.size() != this->size()) { return QPair(CAngle::null(), CAngle::null()); } + const QPair pitchDeg = CMathUtils::standardDeviationAndMean(pitchValues); + return QPair(CAngle(pitchDeg.first, CAngleUnit::deg()), CAngle(pitchDeg.second, CAngleUnit::deg())); + } + + QPair CAircraftSituationList::elevationStandardDeviationAndMean() const + { + const QList elvValues = this->elevationValues(CLengthUnit::ft()); + if (elvValues.size() != this->size()) { return QPair(CAltitude::null(), CAltitude::null()); } + const QPair elvFt = CMathUtils::standardDeviationAndMean(elvValues); + return QPair(CAltitude(elvFt.first, CAltitude::MeanSeaLevel, CLengthUnit::ft()), CAltitude(elvFt.second, CAltitude::MeanSeaLevel, CLengthUnit::ft())); + } + + QPair CAircraftSituationList::altitudeStandardDeviationAndMean() const + { + const QList altValues = this->altitudeValues(CLengthUnit::ft()); + if (altValues.size() != this->size()) { return QPair(CAltitude::null(), CAltitude::null()); } + const QPair altFt = CMathUtils::standardDeviationAndMean(altValues); + return QPair(CAltitude(altFt.first, CAltitude::MeanSeaLevel, CLengthUnit::ft()), CAltitude(altFt.second, CAltitude::MeanSeaLevel, CLengthUnit::ft())); + } + + QPair CAircraftSituationList::altitudeAglStandardDeviationAndMean() const + { + const QList altValues = this->altitudeValues(CLengthUnit::ft()); + if (altValues.size() != this->size()) { return QPair(CAltitude::null(), CAltitude::null()); } + + const QList elvValues = this->elevationValues(CLengthUnit::ft()); + if (elvValues.size() != this->size()) { return QPair(CAltitude::null(), CAltitude::null()); } + + QList altElvDeltas; + for (int i = 0; i < altValues.size(); i++) + { + const double delta = altValues[i] - elvValues[i]; + altElvDeltas.push_back(delta); + } + const QPair deltaFt = CMathUtils::standardDeviationAndMean(altElvDeltas); + return QPair(CAltitude(deltaFt.first, CAltitude::MeanSeaLevel, CLengthUnit::ft()), CAltitude(deltaFt.second, CAltitude::MeanSeaLevel, CLengthUnit::ft())); + } } // namespace } // namespace diff --git a/src/blackmisc/aviation/aircraftsituationlist.h b/src/blackmisc/aviation/aircraftsituationlist.h index 22adcef1c..04407d88b 100644 --- a/src/blackmisc/aviation/aircraftsituationlist.h +++ b/src/blackmisc/aviation/aircraftsituationlist.h @@ -24,6 +24,7 @@ #include #include +#include namespace BlackMisc { @@ -72,7 +73,7 @@ namespace BlackMisc //! Any situation without ground info bool hasSituationWithoutGroundElevation() const; - //! Any situation outside range + //! Any situation outside range? bool hasGroundElevationOutsideRange(const PhysicalQuantities::CLength &range) const; //! Contains on ground details @@ -118,12 +119,21 @@ namespace BlackMisc //! Count the number of situations with CAircraftSituation::IsOnGround int countOnGround(CAircraftSituation::IsOnGround og) const; + //! Count the number of situations with CAircraftSituation::IsOnGround and elevation + int countOnGroundWithElevation(CAircraftSituation::IsOnGround og) const; + + //! Situations with CAircraftSituation::IsOnGround and elevation + CAircraftSituationList findOnGroundWithElevation(CAircraftSituation::IsOnGround og) const; + //! Set on ground int setOnGround(CAircraftSituation::IsOnGround og); //! Set on ground details for all situations int setOnGroundDetails(CAircraftSituation::OnGroundDetails details); + //! Add an offset to each altitude + void addAltitudeOffset(const PhysicalQuantities::CLength &offset); + //! Latest first and no null positions? bool isSortedAdjustedLatestFirstWithoutNullPositions() const; @@ -145,6 +155,22 @@ namespace BlackMisc //! All corrected altitude values QList correctedAltitudeValues(const PhysicalQuantities::CLengthUnit &unit, const PhysicalQuantities::CLength &cg) const; + + //! Pitch angles standard deviation and mean + QPair pitchStandardDeviationAndMean() const; + + //! Ground speed standard deviation and mean + QPair groundSpeedStandardDeviationAndMean() const; + + //! Elevation standard deviation and mean + QPair elevationStandardDeviationAndMean() const; + + //! Elevation standard deviation and mean + QPair altitudeStandardDeviationAndMean() const; + + //! Elevation standard deviation and mean + //! \note distance is without CG, so on ground it can also be used to calculate + QPair altitudeAglStandardDeviationAndMean() const; }; } // namespace } // namespace diff --git a/src/blackmisc/aviation/callsignset.cpp b/src/blackmisc/aviation/callsignset.cpp index 1859987f6..b21dbce5e 100644 --- a/src/blackmisc/aviation/callsignset.cpp +++ b/src/blackmisc/aviation/callsignset.cpp @@ -22,6 +22,12 @@ namespace BlackMisc { CCallsignSet::CCallsignSet() { } + CCallsignSet::CCallsignSet(const CCallsign &callsign) + { + if (callsign.isEmpty()) { return; } + this->push_back(callsign); + } + CCallsignSet::CCallsignSet(const CCollection &other) : CCollection(other) { } diff --git a/src/blackmisc/aviation/callsignset.h b/src/blackmisc/aviation/callsignset.h index 508bf320c..428409be9 100644 --- a/src/blackmisc/aviation/callsignset.h +++ b/src/blackmisc/aviation/callsignset.h @@ -32,6 +32,9 @@ namespace BlackMisc //! Default constructor. CCallsignSet(); + //! Construct from single callsign + CCallsignSet(const CCallsign &callsign); + //! Initializer list constructor. CCallsignSet(std::initializer_list il) : CCollection(il) {} diff --git a/src/blackmisc/aviation/registermetadataaviation.cpp b/src/blackmisc/aviation/registermetadataaviation.cpp index 2df662bcb..218bdc234 100644 --- a/src/blackmisc/aviation/registermetadataaviation.cpp +++ b/src/blackmisc/aviation/registermetadataaviation.cpp @@ -29,6 +29,7 @@ namespace BlackMisc qRegisterMetaType(); qRegisterMetaType(); CAircraftSituationChange::registerMetadata(); + qRegisterMetaType(); CAircraftSituationList::registerMetadata(); CAirlineIcaoCode::registerMetadata(); CAirlineIcaoCodeList::registerMetadata(); diff --git a/src/blackmisc/simulation/aircraftmodel.h b/src/blackmisc/simulation/aircraftmodel.h index 3363f152b..67f9cbe6c 100644 --- a/src/blackmisc/simulation/aircraftmodel.h +++ b/src/blackmisc/simulation/aircraftmodel.h @@ -268,6 +268,9 @@ namespace BlackMisc //! Get center of gravity void setCG(const PhysicalQuantities::CLength &cg) { m_cg = cg; } + //! CG value available? + bool hasCG() const { return !m_cg.isNull(); } + //! Model type ModelType getModelType() const { return m_modelType; } diff --git a/src/blackmisc/simulation/fscommon/vpilotmodelrule.h b/src/blackmisc/simulation/fscommon/vpilotmodelrule.h index 2b4fd655e..7a5f48231 100644 --- a/src/blackmisc/simulation/fscommon/vpilotmodelrule.h +++ b/src/blackmisc/simulation/fscommon/vpilotmodelrule.h @@ -31,8 +31,9 @@ namespace BlackMisc namespace FsCommon { //! Value object encapsulating information of software distributor. + //! \deprecated vPilot handling will be most likely removed in the future class BLACKMISC_EXPORT CVPilotModelRule : - public BlackMisc::CValueObject, + public CValueObject, public ITimestampBased { public: diff --git a/src/blackmisc/simulation/fscommon/vpilotmodelruleset.h b/src/blackmisc/simulation/fscommon/vpilotmodelruleset.h index 1399c7d9d..b1c4954d5 100644 --- a/src/blackmisc/simulation/fscommon/vpilotmodelruleset.h +++ b/src/blackmisc/simulation/fscommon/vpilotmodelruleset.h @@ -31,9 +31,10 @@ namespace BlackMisc namespace FsCommon { //! Value object reading a set of vPilot rules + //! \deprecated vPilot handling will be most likely removed in the future class BLACKMISC_EXPORT CVPilotModelRuleSet : public CCollection, - public BlackMisc::Mixin::MetaType + public Mixin::MetaType { public: BLACKMISC_DECLARE_USING_MIXIN_METATYPE(CVPilotModelRuleSet) @@ -67,7 +68,7 @@ namespace BlackMisc //! To aircraft models //! \note slow operation, can take a while - BlackMisc::Simulation::CAircraftModelList toAircraftModels() const; + Simulation::CAircraftModelList toAircraftModels() const; private: //! Convert values to upper case diff --git a/src/blackmisc/simulation/registermetadatasimulation.cpp b/src/blackmisc/simulation/registermetadatasimulation.cpp index c778cfba5..0dfd6adbd 100644 --- a/src/blackmisc/simulation/registermetadatasimulation.cpp +++ b/src/blackmisc/simulation/registermetadatasimulation.cpp @@ -29,6 +29,7 @@ namespace BlackMisc CDistributor::registerMetadata(); CDistributorList::registerMetadata(); CDistributorListPreferences::registerMetadata(); + qDBusRegisterMetaType(); CInterpolationAndRenderingSetupPerCallsign::registerMetadata(); CInterpolationAndRenderingSetupGlobal::registerMetadata(); CInterpolationSetupList::registerMetadata();