diff --git a/include/aman/types/Inbound.h b/include/aman/types/Inbound.h index 930575e..2a8a31c 100644 --- a/include/aman/types/Inbound.h +++ b/include/aman/types/Inbound.h @@ -36,14 +36,17 @@ namespace aman { std::size_t m_nextStarWaypoint; std::vector m_arrivalRoute; Time m_timeToLose; + UtcTime::Point m_waypointEstimatedTimeOfArrival; + Length m_trackmiles; + Time m_flighttime; - void updatePrediction(EuroScopePlugIn::CRadarTarget& target, const aman::AircraftSchedule& inbound, bool forceUpdate); + void updatePrediction(EuroScopePlugIn::CRadarTarget& target, const aman::AircraftSchedule& inbound); 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 matchToPredictedPath(const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions, const GeoCoordinate& position, Length& trackmiles); - void predictETA(const EuroScopePlugIn::CRadarTarget& target, const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions, bool resetTTL); + void predictETA(const EuroScopePlugIn::CRadarTarget& target, const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions); public: Inbound(EuroScopePlugIn::CRadarTarget& target, const aman::AircraftSchedule& inbound, const google::protobuf::RepeatedPtrField& wind); @@ -52,6 +55,10 @@ namespace aman { void update(EuroScopePlugIn::CRadarTarget& target); void update(EuroScopePlugIn::CFlightPlan& plan); bool fixedPlan() const noexcept; + UtcTime::Point eta() const; + UtcTime::Point pta() const; const Time& timeToLose() const noexcept; + const Length& trackmiles() const noexcept; + const Time& flighttime() const noexcept; }; } diff --git a/src/types/Inbound.cpp b/src/types/Inbound.cpp index cfcd153..e36a205 100644 --- a/src/types/Inbound.cpp +++ b/src/types/Inbound.cpp @@ -33,9 +33,11 @@ Inbound::Inbound(EuroScopePlugIn::CRadarTarget& target, const aman::AircraftSche m_runway(inbound.arrivalrunway()), m_nextStarWaypoint(), m_arrivalRoute(), - m_timeToLose() { + m_timeToLose(), + m_trackmiles(), + m_flighttime() { this->createWindTables(wind); - this->updatePrediction(target, inbound, true); + this->updatePrediction(target, inbound); auto flightplan = target.GetCorrelatedFlightPlan(); this->update(flightplan); } @@ -58,7 +60,7 @@ void Inbound::createWindTables(const google::protobuf::RepeatedPtrFieldm_performanceData.speedAboveFL240 = static_cast(inbound.performance().iasabovefl240()) * knot; @@ -66,7 +68,7 @@ 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; - bool updateEuroscopePlan = true == forceUpdate && 0 != this->m_star.length() && 0 != this->m_runway.length(); + bool updateEuroscopePlan = 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) { @@ -95,33 +97,31 @@ void Inbound::updatePrediction(EuroScopePlugIn::CRadarTarget& target, const aman updatedFlightplan = true; } - if (true == forceUpdate || true == updatedFlightplan) { - this->m_arrivalRoute.clear(); - this->m_arrivalRoute.reserve(inbound.waypoints_size()); - auto route = target.GetCorrelatedFlightPlan().GetExtractedRoute(); - int lastExtractedIndex = 0; + this->m_arrivalRoute.clear(); + this->m_arrivalRoute.reserve(inbound.waypoints_size()); + auto route = target.GetCorrelatedFlightPlan().GetExtractedRoute(); + int lastExtractedIndex = 0; - for (int i = 0; i < inbound.waypoints_size(); ++i) { - const auto& plannedPoint = inbound.waypoints(i); + for (int i = 0; i < inbound.waypoints_size(); ++i) { + const auto& plannedPoint = inbound.waypoints(i); - const auto pta = UtcTime::stringToTime(plannedPoint.pta()); - const auto altitude = static_cast(plannedPoint.altitude()) * feet; - const auto ias = static_cast(plannedPoint.indicatedairspeed()) * knot; - GeoCoordinate coordinate; + const auto pta = UtcTime::stringToTime(plannedPoint.pta()); + const auto altitude = static_cast(plannedPoint.altitude()) * feet; + const auto ias = static_cast(plannedPoint.indicatedairspeed()) * knot; + GeoCoordinate coordinate; - bool found = false; - for (int c = lastExtractedIndex; c < route.GetPointsNumber(); ++c) { - if (route.GetPointName(c) == plannedPoint.name()) { - coordinate = __convert(route.GetPointPosition(c)); - lastExtractedIndex = c; - found = true; - break; - } + bool found = false; + for (int c = lastExtractedIndex; c < route.GetPointsNumber(); ++c) { + if (route.GetPointName(c) == plannedPoint.name()) { + coordinate = __convert(route.GetPointPosition(c)); + lastExtractedIndex = c; + found = true; + break; } - - if (true == found) - this->m_arrivalRoute.push_back(ArrivalWaypoint(plannedPoint.name(), coordinate, altitude, ias, pta)); } + + if (true == found) + this->m_arrivalRoute.push_back(ArrivalWaypoint(plannedPoint.name(), coordinate, altitude, ias, pta)); } } @@ -132,7 +132,7 @@ void Inbound::update(EuroScopePlugIn::CRadarTarget& target, const aman::Aircraft this->m_runway = inbound.arrivalrunway(); this->createWindTables(wind); - this->updatePrediction(target, inbound, false); + this->updatePrediction(target, inbound); auto flightplan = target.GetCorrelatedFlightPlan(); this->update(flightplan); } @@ -243,7 +243,7 @@ int Inbound::matchToPredictedPath(const EuroScopePlugIn::CFlightPlanPositionPred const auto prev = lastPosition.bearingTo(position); const auto next = coordinate.bearingTo(position); const auto delta = __normalize(prev - next); - if (100_deg <= delta.abs()) { + if (90_deg <= delta.abs() || 2.0_nm >= lastPosition.distanceTo(position)) { trackmiles += lastPosition.distanceTo(position); return i - 1; } @@ -255,7 +255,7 @@ int Inbound::matchToPredictedPath(const EuroScopePlugIn::CFlightPlanPositionPred return predictions.GetPointsNumber(); } -void Inbound::predictETA(const EuroScopePlugIn::CRadarTarget& target, const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions, bool resetTTL) { +void Inbound::predictETA(const EuroScopePlugIn::CRadarTarget& target, const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions) { if (this->m_arrivalRoute.size() <= this->m_nextStarWaypoint || 1 >= predictions.GetPointsNumber()) { this->m_timeToLose = 0_s; return; @@ -264,6 +264,7 @@ void Inbound::predictETA(const EuroScopePlugIn::CRadarTarget& target, const Euro const auto& destination = gsl::at(this->m_arrivalRoute, this->m_nextStarWaypoint); Length distanceToNextWaypoint = 0_m; Inbound::matchToPredictedPath(predictions, destination.position(), distanceToNextWaypoint); + this->m_trackmiles = distanceToNextWaypoint; /* predict the flight and the descend */ Velocity groundSpeed = static_cast(target.GetPosition().GetReportedGS()) * knot; @@ -292,22 +293,20 @@ void Inbound::predictETA(const EuroScopePlugIn::CRadarTarget& target, const Euro flightTime += 1_s; } + this->m_waypointEstimatedTimeOfArrival = UtcTime::currentUtc() + std::chrono::seconds(static_cast(flightTime.convert(second))); const auto delta = std::chrono::duration_cast(destination.plannedArrivalTime() - UtcTime::currentUtc()); const auto plannedFlightTime = static_cast(delta.count()) * second; const auto newTTL = plannedFlightTime - flightTime; + this->m_flighttime = flightTime; - if (true == resetTTL) - this->m_timeToLose = newTTL; - else - this->m_timeToLose = 0.9f * this->m_timeToLose + 0.1f * newTTL; + this->m_timeToLose = newTTL; } void Inbound::update(EuroScopePlugIn::CRadarTarget& target) { - this->predictETA(target, target.GetCorrelatedFlightPlan().GetPositionPredictions(), false); + this->predictETA(target, target.GetCorrelatedFlightPlan().GetPositionPredictions()); } void Inbound::update(EuroScopePlugIn::CFlightPlan& plan) { - const auto lastStarWaypoint = this->m_nextStarWaypoint; this->m_nextStarWaypoint = 0; if (0 == this->m_arrivalRoute.size()) { @@ -383,13 +382,29 @@ void Inbound::update(EuroScopePlugIn::CFlightPlan& plan) { } const auto target = plan.GetCorrelatedRadarTarget(); - this->predictETA(target, plan.GetPositionPredictions(), this->m_nextStarWaypoint != lastStarWaypoint); + this->predictETA(target, plan.GetPositionPredictions()); } bool Inbound::fixedPlan() const noexcept { return this->m_fixedPlan; } +UtcTime::Point Inbound::eta() const { + return this->m_waypointEstimatedTimeOfArrival; +} + +UtcTime::Point Inbound::pta() const { + return gsl::at(this->m_arrivalRoute, this->m_nextStarWaypoint).plannedArrivalTime(); +} + const Time& Inbound::timeToLose() const noexcept { return this->m_timeToLose; } + +const Length& Inbound::trackmiles() const noexcept { + return this->m_trackmiles; +} + +const Time& Inbound::flighttime() const noexcept { + return this->m_flighttime; +}