Explorar el Código

fix some changes and add a low pass filter to avoid fast ETA changes

Sven Czarnian hace 3 años
padre
commit
055cf900fb
Se han modificado 2 ficheros con 75 adiciones y 41 borrados
  1. 3 1
      include/aman/types/Inbound.h
  2. 72 40
      src/types/Inbound.cpp

+ 3 - 1
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<aman::WindData>& 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<aman::WindData>& wind);

+ 72 - 40
src/types/Inbound.cpp

@@ -66,7 +66,10 @@ void Inbound::updatePrediction(EuroScopePlugIn::CRadarTarget& target, const aman
     this->m_performanceData.speedBelowFL100 = static_cast<float>(inbound.performance().iasbelowfl100()) * knot;
     this->m_performanceData.speedApproach = static_cast<float>(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<float>(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<int>(flightTime.convert(second))));
-    auto delta = std::chrono::duration_cast<std::chrono::seconds>(destination.plannedArrivalTime() - currentUtc);
-    auto plannedFlightTime = static_cast<float>(delta.count()) * second;
-    this->m_timeToLose = plannedFlightTime - flightTime;
+    const auto delta = std::chrono::duration_cast<std::chrono::seconds>(destination.plannedArrivalTime() - UtcTime::currentUtc());
+    const auto plannedFlightTime = static_cast<float>(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 {