diff --git a/src/blackmisc/aviation/aircraftparts.cpp b/src/blackmisc/aviation/aircraftparts.cpp index a0fe42244..11ceb8b0e 100644 --- a/src/blackmisc/aviation/aircraftparts.cpp +++ b/src/blackmisc/aviation/aircraftparts.cpp @@ -71,15 +71,25 @@ namespace BlackMisc parts.setGearDown(onGround); engines.initEngines(engineNumber, !onGround || situation.isMoving()); + const double pitchDeg = situation.getPitch().value(CAngleUnit::deg()); + double nearGround1Ft = 750; + double nearGround2Ft = 1500; + if (pitchDeg > 10) + { + // likely starting + nearGround1Ft = 250; + nearGround2Ft = 500; + } + if (situation.hasGroundElevation()) { const double aGroundFt = situation.getHeightAboveGround().value(CLengthUnit::ft()); - if (aGroundFt < 1000) + if (aGroundFt < nearGround1Ft) { parts.setGearDown(true); parts.setFlapsPercent(25); } - else if (aGroundFt < 2000) + else if (aGroundFt < nearGround2Ft) { parts.setGearDown(true); parts.setFlapsPercent(10); diff --git a/src/blackmisc/aviation/aircraftsituation.cpp b/src/blackmisc/aviation/aircraftsituation.cpp index ea6ac8595..c1003766b 100644 --- a/src/blackmisc/aviation/aircraftsituation.cpp +++ b/src/blackmisc/aviation/aircraftsituation.cpp @@ -274,11 +274,26 @@ namespace BlackMisc m_onGroundFactor = gf; } + bool CAircraftSituation::shouldGuessOnGround() const + { + return (!this->isOnGroundInfoAvailable()); + } + bool CAircraftSituation::guessOnGround(bool vtol, const PhysicalQuantities::CLength &cg) { - if (this->getOnGroundDetails() == NotSet) { return false; } + if (!this->shouldGuessOnGround()) { return false; } + + // Non VTOL aircraft have to move to be not on ground + if (!vtol && !this->isMoving()) + { + this->setOnGround(OnGround, CAircraftSituation::OnGroundByGuessing); + return true; + } + + // by elevation + // we can detect "on ground" but not "not on ground" because of overflow IsOnGround og = this->isOnGroundByElevation(cg); - if (og != OnGroundSituationUnknown) + if (og == OnGround) { this->setOnGround(og, CAircraftSituation::OnGroundByGuessing); return true; @@ -306,6 +321,11 @@ namespace BlackMisc return groundDistance; } + bool CAircraftSituation::hasGroundDetailsForGndInterpolation() const + { + return this->getOnGroundDetails() != CAircraftSituation::NotSetGroundDetails; + } + const QString &CAircraftSituation::getOnDetailsAsString() const { return CAircraftSituation::onGroundDetailsToString(this->getOnGroundDetails()); @@ -352,9 +372,17 @@ namespace BlackMisc CAircraftSituation::IsOnGround CAircraftSituation::isOnGroundByElevation(const CLength &cg) const { + Q_ASSERT_X(!cg.isNegativeWithEpsilonConsidered(), Q_FUNC_INFO, "CG must not be negative"); const CLength groundDistance = this->getGroundDistance(cg); if (groundDistance.isNull()) { return OnGroundSituationUnknown; } - if (groundDistance.isNegativeWithEpsilonConsidered() || groundDistance.abs() < deltaNearGround()) { return OnGround; } + if (groundDistance.isNegativeWithEpsilonConsidered()) { return OnGround; } + if (groundDistance.abs() < deltaNearGround()) { return OnGround; } + if (!cg.isNull()) + { + // smaller than percentage from CG + const CLength cgFactor(cg * 0.1); + if (groundDistance.abs() < cgFactor) { return OnGround; } + } return NotOnGround; } @@ -363,7 +391,7 @@ namespace BlackMisc return !this->getGroundElevation().isNull(); } - bool CAircraftSituation::hasInboundGroundInformation() const + bool CAircraftSituation::hasInboundGroundDetails() const { return this->getOnGroundDetails() == CAircraftSituation::InFromParts || this->getOnGroundDetails() == CAircraftSituation::InFromNetwork; } @@ -453,7 +481,7 @@ namespace BlackMisc if (correctetion) { *correctetion = NoCorrection; } return groundPlusCG; } - const bool forceDragToGround = (enableDragToGround && this->getOnGround() == OnGround) && (this->hasInboundGroundInformation() || this->getOnGroundDetails() == OnGroundByGuessing); + const bool forceDragToGround = (enableDragToGround && this->getOnGround() == OnGround) && (this->hasInboundGroundDetails() || this->getOnGroundDetails() == OnGroundByGuessing); if (forceDragToGround) { if (correctetion) { *correctetion = DraggedToGround; } @@ -487,7 +515,7 @@ namespace BlackMisc bool CAircraftSituation::canLikelySkipNearGroundInterpolation() const { // those we can exclude - if (this->isOnGround() && this->hasInboundGroundInformation()) { return false; } + if (this->isOnGround() && this->hasInboundGroundDetails()) { return false; } // cases where we can skip if (this->isNull()) { return true; } diff --git a/src/blackmisc/aviation/aircraftsituation.h b/src/blackmisc/aviation/aircraftsituation.h index c25d45daf..50d59aaf6 100644 --- a/src/blackmisc/aviation/aircraftsituation.h +++ b/src/blackmisc/aviation/aircraftsituation.h @@ -184,6 +184,9 @@ namespace BlackMisc //! Set on ground factor 0..1 (on ground), -1 not set void setOnGroundFactor(double groundFactor); + //! Should we guess on ground? + bool shouldGuessOnGround() const; + //! Guess on ground flag bool guessOnGround(bool vtol = false, const PhysicalQuantities::CLength &cg = PhysicalQuantities::CLength::null()); @@ -193,6 +196,9 @@ namespace BlackMisc //! On ground reliability OnGroundDetails getOnGroundDetails() const { return static_cast(m_onGroundDetails); } + //! Do the ground details permit ground interpolation? + bool hasGroundDetailsForGndInterpolation() const; + //! On ground reliability as string const QString &getOnDetailsAsString() const; diff --git a/src/blackmisc/aviation/aircraftsituationlist.cpp b/src/blackmisc/aviation/aircraftsituationlist.cpp index 2714f93ff..3a7808cd9 100644 --- a/src/blackmisc/aviation/aircraftsituationlist.cpp +++ b/src/blackmisc/aviation/aircraftsituationlist.cpp @@ -43,6 +43,23 @@ namespace BlackMisc return c; } + int CAircraftSituationList::setGroundElevationCheckedAndGuessGround(const CElevationPlane &elevationPlane, bool isVtol, const CLength &cg) + { + if (elevationPlane.isNull()) { return 0; } + int c = 0; + for (CAircraftSituation &s : *this) + { + const bool set = s.setGroundElevationChecked(elevationPlane); + if (!set) { continue; } + if (s.shouldGuessOnGround()) + { + s.guessOnGround(isVtol, cg); + } + c++; + } + return c; + } + int CAircraftSituationList::adjustGroundFlag(const CAircraftParts &parts, double timeDeviationFactor) { int c = 0; @@ -76,7 +93,7 @@ namespace BlackMisc CAircraftSituationList CAircraftSituationList::findByInboundGroundInformation(bool hasGroundInfo) const { - return this->findBy(&CAircraftSituation::hasInboundGroundInformation, hasGroundInfo); + return this->findBy(&CAircraftSituation::hasInboundGroundDetails, hasGroundInfo); } bool CAircraftSituationList::hasSituationWithoutGroundElevation() const diff --git a/src/blackmisc/aviation/aircraftsituationlist.h b/src/blackmisc/aviation/aircraftsituationlist.h index 2b38c7786..2f4db283b 100644 --- a/src/blackmisc/aviation/aircraftsituationlist.h +++ b/src/blackmisc/aviation/aircraftsituationlist.h @@ -54,7 +54,10 @@ namespace BlackMisc //! Set ground elevation from elevation plane int setGroundElevationChecked(const Geo::CElevationPlane &elevationPlane, qint64 newerThanAdjustedMs = -1); - //! Adjust flag by using CAircraftSituation::adjustGroundFlag + //! Set ground elevation from elevation plane + int setGroundElevationCheckedAndGuessGround(const Geo::CElevationPlane &elevationPlane, bool isVtol, const PhysicalQuantities::CLength &cg); + + //! Adjust flag from parts by using CAircraftSituation::adjustGroundFlag int adjustGroundFlag(const CAircraftParts &parts, double timeDeviationFactor = 0.1); //! Extrapolate ground flag into the future