From 055cf900fbbc10bd8e882b27b26afbaf4602fe88 Mon Sep 17 00:00:00 2001 From: Sven Czarnian Date: Mon, 29 Nov 2021 19:21:29 +0100 Subject: [PATCH] fix some changes and add a low pass filter to avoid fast ETA changes --- include/aman/types/Inbound.h | 4 +- src/types/Inbound.cpp | 112 ++++++++++++++++++++++------------- 2 files changed, 75 insertions(+), 41 deletions(-) diff --git a/include/aman/types/Inbound.h b/include/aman/types/Inbound.h index 400ee19..930575e 100644 --- a/include/aman/types/Inbound.h +++ b/include/aman/types/Inbound.h @@ -41,7 +41,9 @@ namespace aman { Velocity indicatedAirspeed(const Length& altitude) const noexcept; Velocity groundSpeed(const Length& altitude, const Velocity& ias, const Angle& heading); void createWindTables(const google::protobuf::RepeatedPtrField& wind); - static int findIndexInPredictedPath(const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions, const GeoCoordinate& position); + static int matchToPredictedPath(const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions, const GeoCoordinate& position, + Length& trackmiles); + void predictETA(const EuroScopePlugIn::CRadarTarget& target, const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions, bool resetTTL); public: Inbound(EuroScopePlugIn::CRadarTarget& target, const aman::AircraftSchedule& inbound, const google::protobuf::RepeatedPtrField& wind); diff --git a/src/types/Inbound.cpp b/src/types/Inbound.cpp index c040c15..cfcd153 100644 --- a/src/types/Inbound.cpp +++ b/src/types/Inbound.cpp @@ -66,7 +66,10 @@ void Inbound::updatePrediction(EuroScopePlugIn::CRadarTarget& target, const aman this->m_performanceData.speedBelowFL100 = static_cast(inbound.performance().iasbelowfl100()) * knot; this->m_performanceData.speedApproach = static_cast(inbound.performance().iasapproach()) * knot; - if (true == forceUpdate || this->m_star != target.GetCorrelatedFlightPlan().GetFlightPlanData().GetStarName() || this->m_runway != target.GetCorrelatedFlightPlan().GetFlightPlanData().GetArrivalRwy()) { + bool updateEuroscopePlan = true == forceUpdate && 0 != this->m_star.length() && 0 != this->m_runway.length(); + updateEuroscopePlan &= this->m_star != target.GetCorrelatedFlightPlan().GetFlightPlanData().GetStarName() || this->m_runway.length() && this->m_runway != target.GetCorrelatedFlightPlan().GetFlightPlanData().GetArrivalRwy(); + + if (true == updateEuroscopePlan) { std::string route(target.GetCorrelatedFlightPlan().GetFlightPlanData().GetRoute()); std::string arrival = this->m_star + "/" + this->m_runway; @@ -92,7 +95,7 @@ void Inbound::updatePrediction(EuroScopePlugIn::CRadarTarget& target, const aman updatedFlightplan = true; } - if (true == updatedFlightplan) { + if (true == forceUpdate || true == updatedFlightplan) { this->m_arrivalRoute.clear(); this->m_arrivalRoute.reserve(inbound.waypoints_size()); auto route = target.GetCorrelatedFlightPlan().GetExtractedRoute(); @@ -225,7 +228,10 @@ static __inline Angle __normalize(const Angle& angle) { return retval; } -int Inbound::findIndexInPredictedPath(const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions, const GeoCoordinate& position) { +int Inbound::matchToPredictedPath(const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions, const GeoCoordinate& position, + Length& trackmiles) { + trackmiles = 0_m; + if (0 == predictions.GetPointsNumber()) return 0; @@ -237,39 +243,27 @@ int Inbound::findIndexInPredictedPath(const EuroScopePlugIn::CFlightPlanPosition const auto prev = lastPosition.bearingTo(position); const auto next = coordinate.bearingTo(position); const auto delta = __normalize(prev - next); - if (100_deg <= delta.abs()) - return i; + if (100_deg <= delta.abs()) { + trackmiles += lastPosition.distanceTo(position); + return i - 1; + } + trackmiles += lastPosition.distanceTo(coordinate); lastPosition = coordinate; } return predictions.GetPointsNumber(); } -void Inbound::update(EuroScopePlugIn::CRadarTarget& target) { - if (this->m_arrivalRoute.size() <= this->m_nextStarWaypoint) { +void Inbound::predictETA(const EuroScopePlugIn::CRadarTarget& target, const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions, bool resetTTL) { + if (this->m_arrivalRoute.size() <= this->m_nextStarWaypoint || 1 >= predictions.GetPointsNumber()) { this->m_timeToLose = 0_s; return; } const auto& destination = gsl::at(this->m_arrivalRoute, this->m_nextStarWaypoint); - const auto& predictions = target.GetCorrelatedFlightPlan().GetPositionPredictions(); - GeoCoordinate lastPosition(__convert(target.GetPosition().GetPosition())); Length distanceToNextWaypoint = 0_m; - - /* calculate the distance to the correct waypoint */ - for (int i = 0; i < predictions.GetPointsNumber(); ++i) { - GeoCoordinate coordinate(__convert(predictions.GetPosition(i))); - - const auto prev = lastPosition.bearingTo(destination.position()); - const auto next = coordinate.bearingTo(destination.position()); - const auto delta = __normalize(prev - next); - if (100_deg <= delta.abs()) - break; - - distanceToNextWaypoint += coordinate.distanceTo(lastPosition); - lastPosition = coordinate; - } + Inbound::matchToPredictedPath(predictions, destination.position(), distanceToNextWaypoint); /* predict the flight and the descend */ Velocity groundSpeed = static_cast(target.GetPosition().GetReportedGS()) * knot; @@ -298,33 +292,71 @@ void Inbound::update(EuroScopePlugIn::CRadarTarget& target) { flightTime += 1_s; } - auto currentUtc = UtcTime::currentUtc(); - auto pta = UtcTime::timeToString(destination.plannedArrivalTime()); - auto estimated = UtcTime::timeToString(currentUtc + std::chrono::seconds(static_cast(flightTime.convert(second)))); - auto delta = std::chrono::duration_cast(destination.plannedArrivalTime() - currentUtc); - auto plannedFlightTime = static_cast(delta.count()) * second; - this->m_timeToLose = plannedFlightTime - flightTime; + const auto delta = std::chrono::duration_cast(destination.plannedArrivalTime() - UtcTime::currentUtc()); + const auto plannedFlightTime = static_cast(delta.count()) * second; + const auto newTTL = plannedFlightTime - flightTime; + + if (true == resetTTL) + this->m_timeToLose = newTTL; + else + this->m_timeToLose = 0.9f * this->m_timeToLose + 0.1f * newTTL; +} + +void Inbound::update(EuroScopePlugIn::CRadarTarget& target) { + this->predictETA(target, target.GetCorrelatedFlightPlan().GetPositionPredictions(), false); } void Inbound::update(EuroScopePlugIn::CFlightPlan& plan) { + const auto lastStarWaypoint = this->m_nextStarWaypoint; this->m_nextStarWaypoint = 0; - if (0 == this->m_arrivalRoute.size()) + + if (0 == this->m_arrivalRoute.size()) { + this->m_timeToLose = 0_s; return; + } /* find the point on the route */ - std::string_view direct(plan.GetControllerAssignedData().GetDirectToPointName()); + std::string direct(plan.GetControllerAssignedData().GetDirectToPointName()); auto route = plan.GetExtractedRoute(); int starEntry = route.GetPointsNumber(), directEntry = route.GetPointsNumber(); - /* TODO search point if direct is empty */ - + /* find the star entry on the route */ for (int c = 0; c < route.GetPointsNumber(); ++c) { std::string_view waypointName(route.GetPointName(c)); - - if (waypointName == this->m_arrivalRoute.front().name()) + if (waypointName == this->m_arrivalRoute.front().name()) { starEntry = c; - else if (waypointName == direct) - directEntry = c; + break; + } + } + + if (0 != direct.length()) { + /* find the DIRECT waypoint */ + for (int c = 0; c < route.GetPointsNumber(); ++c) { + std::string_view waypointName(route.GetPointName(c)); + if (waypointName == direct) { + directEntry = c; + break; + } + } + } + else { + const auto& acPosition = __convert(plan.GetCorrelatedRadarTarget().GetPosition().GetPosition()); + Length minDistance(10000_nm); + + /* search the next waypoint on the route */ + for (int c = route.GetPointsNumber() - 1; c >= 0; --c) { + const auto& position = __convert(route.GetPointPosition(c)); + const auto distance = position.distanceTo(acPosition); + + if (distance < minDistance) { + direct = route.GetPointName(c); + minDistance = distance; + directEntry = c; + } + + if (c < starEntry) + break; + } } /* search the direct to entry */ @@ -345,13 +377,13 @@ void Inbound::update(EuroScopePlugIn::CFlightPlan& plan) { break; } - direct = std::string_view(route.GetPointName(directEntry)); + direct = std::string(route.GetPointName(directEntry)); } } } - EuroScopePlugIn::CRadarTarget target = plan.GetCorrelatedRadarTarget(); - this->update(target); + const auto target = plan.GetCorrelatedRadarTarget(); + this->predictETA(target, plan.GetPositionPredictions(), this->m_nextStarWaypoint != lastStarWaypoint); } bool Inbound::fixedPlan() const noexcept {