fix some issues with the path prediction and add some addional information

This commit is contained in:
Sven Czarnian
2021-12-15 13:23:33 +01:00
parent f053ead918
commit e108d3de57
2 changed files with 60 additions and 38 deletions

View File

@@ -36,14 +36,17 @@ namespace aman {
std::size_t m_nextStarWaypoint; std::size_t m_nextStarWaypoint;
std::vector<ArrivalWaypoint> m_arrivalRoute; std::vector<ArrivalWaypoint> m_arrivalRoute;
Time m_timeToLose; 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 indicatedAirspeed(const Length& altitude) const noexcept;
Velocity groundSpeed(const Length& altitude, const Velocity& ias, const Angle& heading); Velocity groundSpeed(const Length& altitude, const Velocity& ias, const Angle& heading);
void createWindTables(const google::protobuf::RepeatedPtrField<aman::WindData>& wind); void createWindTables(const google::protobuf::RepeatedPtrField<aman::WindData>& wind);
static int matchToPredictedPath(const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions, const GeoCoordinate& position, static int matchToPredictedPath(const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions, const GeoCoordinate& position,
Length& trackmiles); 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: public:
Inbound(EuroScopePlugIn::CRadarTarget& target, const aman::AircraftSchedule& inbound, const google::protobuf::RepeatedPtrField<aman::WindData>& wind); Inbound(EuroScopePlugIn::CRadarTarget& target, const aman::AircraftSchedule& inbound, const google::protobuf::RepeatedPtrField<aman::WindData>& wind);
@@ -52,6 +55,10 @@ namespace aman {
void update(EuroScopePlugIn::CRadarTarget& target); void update(EuroScopePlugIn::CRadarTarget& target);
void update(EuroScopePlugIn::CFlightPlan& plan); void update(EuroScopePlugIn::CFlightPlan& plan);
bool fixedPlan() const noexcept; bool fixedPlan() const noexcept;
UtcTime::Point eta() const;
UtcTime::Point pta() const;
const Time& timeToLose() const noexcept; const Time& timeToLose() const noexcept;
const Length& trackmiles() const noexcept;
const Time& flighttime() const noexcept;
}; };
} }

View File

@@ -33,9 +33,11 @@ Inbound::Inbound(EuroScopePlugIn::CRadarTarget& target, const aman::AircraftSche
m_runway(inbound.arrivalrunway()), m_runway(inbound.arrivalrunway()),
m_nextStarWaypoint(), m_nextStarWaypoint(),
m_arrivalRoute(), m_arrivalRoute(),
m_timeToLose() { m_timeToLose(),
m_trackmiles(),
m_flighttime() {
this->createWindTables(wind); this->createWindTables(wind);
this->updatePrediction(target, inbound, true); this->updatePrediction(target, inbound);
auto flightplan = target.GetCorrelatedFlightPlan(); auto flightplan = target.GetCorrelatedFlightPlan();
this->update(flightplan); this->update(flightplan);
} }
@@ -58,7 +60,7 @@ void Inbound::createWindTables(const google::protobuf::RepeatedPtrField<aman::Wi
} }
} }
void Inbound::updatePrediction(EuroScopePlugIn::CRadarTarget& target, const aman::AircraftSchedule& inbound, bool forceUpdate) { void Inbound::updatePrediction(EuroScopePlugIn::CRadarTarget& target, const aman::AircraftSchedule& inbound) {
bool updatedFlightplan = false; bool updatedFlightplan = false;
this->m_performanceData.speedAboveFL240 = static_cast<float>(inbound.performance().iasabovefl240()) * knot; this->m_performanceData.speedAboveFL240 = static_cast<float>(inbound.performance().iasabovefl240()) * knot;
@@ -66,7 +68,7 @@ void Inbound::updatePrediction(EuroScopePlugIn::CRadarTarget& target, const aman
this->m_performanceData.speedBelowFL100 = static_cast<float>(inbound.performance().iasbelowfl100()) * knot; this->m_performanceData.speedBelowFL100 = static_cast<float>(inbound.performance().iasbelowfl100()) * knot;
this->m_performanceData.speedApproach = static_cast<float>(inbound.performance().iasapproach()) * knot; this->m_performanceData.speedApproach = static_cast<float>(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(); updateEuroscopePlan &= this->m_star != target.GetCorrelatedFlightPlan().GetFlightPlanData().GetStarName() || this->m_runway.length() && this->m_runway != target.GetCorrelatedFlightPlan().GetFlightPlanData().GetArrivalRwy();
if (true == updateEuroscopePlan) { if (true == updateEuroscopePlan) {
@@ -95,33 +97,31 @@ void Inbound::updatePrediction(EuroScopePlugIn::CRadarTarget& target, const aman
updatedFlightplan = true; updatedFlightplan = true;
} }
if (true == forceUpdate || true == updatedFlightplan) { this->m_arrivalRoute.clear();
this->m_arrivalRoute.clear(); this->m_arrivalRoute.reserve(inbound.waypoints_size());
this->m_arrivalRoute.reserve(inbound.waypoints_size()); auto route = target.GetCorrelatedFlightPlan().GetExtractedRoute();
auto route = target.GetCorrelatedFlightPlan().GetExtractedRoute(); int lastExtractedIndex = 0;
int lastExtractedIndex = 0;
for (int i = 0; i < inbound.waypoints_size(); ++i) { for (int i = 0; i < inbound.waypoints_size(); ++i) {
const auto& plannedPoint = inbound.waypoints(i); const auto& plannedPoint = inbound.waypoints(i);
const auto pta = UtcTime::stringToTime(plannedPoint.pta()); const auto pta = UtcTime::stringToTime(plannedPoint.pta());
const auto altitude = static_cast<float>(plannedPoint.altitude()) * feet; const auto altitude = static_cast<float>(plannedPoint.altitude()) * feet;
const auto ias = static_cast<float>(plannedPoint.indicatedairspeed()) * knot; const auto ias = static_cast<float>(plannedPoint.indicatedairspeed()) * knot;
GeoCoordinate coordinate; GeoCoordinate coordinate;
bool found = false; bool found = false;
for (int c = lastExtractedIndex; c < route.GetPointsNumber(); ++c) { for (int c = lastExtractedIndex; c < route.GetPointsNumber(); ++c) {
if (route.GetPointName(c) == plannedPoint.name()) { if (route.GetPointName(c) == plannedPoint.name()) {
coordinate = __convert(route.GetPointPosition(c)); coordinate = __convert(route.GetPointPosition(c));
lastExtractedIndex = c; lastExtractedIndex = c;
found = true; found = true;
break; 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->m_runway = inbound.arrivalrunway();
this->createWindTables(wind); this->createWindTables(wind);
this->updatePrediction(target, inbound, false); this->updatePrediction(target, inbound);
auto flightplan = target.GetCorrelatedFlightPlan(); auto flightplan = target.GetCorrelatedFlightPlan();
this->update(flightplan); this->update(flightplan);
} }
@@ -243,7 +243,7 @@ int Inbound::matchToPredictedPath(const EuroScopePlugIn::CFlightPlanPositionPred
const auto prev = lastPosition.bearingTo(position); const auto prev = lastPosition.bearingTo(position);
const auto next = coordinate.bearingTo(position); const auto next = coordinate.bearingTo(position);
const auto delta = __normalize(prev - next); 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); trackmiles += lastPosition.distanceTo(position);
return i - 1; return i - 1;
} }
@@ -255,7 +255,7 @@ int Inbound::matchToPredictedPath(const EuroScopePlugIn::CFlightPlanPositionPred
return predictions.GetPointsNumber(); 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()) { if (this->m_arrivalRoute.size() <= this->m_nextStarWaypoint || 1 >= predictions.GetPointsNumber()) {
this->m_timeToLose = 0_s; this->m_timeToLose = 0_s;
return; 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); const auto& destination = gsl::at(this->m_arrivalRoute, this->m_nextStarWaypoint);
Length distanceToNextWaypoint = 0_m; Length distanceToNextWaypoint = 0_m;
Inbound::matchToPredictedPath(predictions, destination.position(), distanceToNextWaypoint); Inbound::matchToPredictedPath(predictions, destination.position(), distanceToNextWaypoint);
this->m_trackmiles = distanceToNextWaypoint;
/* predict the flight and the descend */ /* predict the flight and the descend */
Velocity groundSpeed = static_cast<float>(target.GetPosition().GetReportedGS()) * knot; Velocity groundSpeed = static_cast<float>(target.GetPosition().GetReportedGS()) * knot;
@@ -292,22 +293,20 @@ void Inbound::predictETA(const EuroScopePlugIn::CRadarTarget& target, const Euro
flightTime += 1_s; flightTime += 1_s;
} }
this->m_waypointEstimatedTimeOfArrival = UtcTime::currentUtc() + std::chrono::seconds(static_cast<long long>(flightTime.convert(second)));
const auto delta = std::chrono::duration_cast<std::chrono::seconds>(destination.plannedArrivalTime() - UtcTime::currentUtc()); 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 plannedFlightTime = static_cast<float>(delta.count()) * second;
const auto newTTL = plannedFlightTime - flightTime; const auto newTTL = plannedFlightTime - flightTime;
this->m_flighttime = flightTime;
if (true == resetTTL) this->m_timeToLose = newTTL;
this->m_timeToLose = newTTL;
else
this->m_timeToLose = 0.9f * this->m_timeToLose + 0.1f * newTTL;
} }
void Inbound::update(EuroScopePlugIn::CRadarTarget& target) { 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) { void Inbound::update(EuroScopePlugIn::CFlightPlan& plan) {
const auto lastStarWaypoint = this->m_nextStarWaypoint;
this->m_nextStarWaypoint = 0; this->m_nextStarWaypoint = 0;
if (0 == this->m_arrivalRoute.size()) { if (0 == this->m_arrivalRoute.size()) {
@@ -383,13 +382,29 @@ void Inbound::update(EuroScopePlugIn::CFlightPlan& plan) {
} }
const auto target = plan.GetCorrelatedRadarTarget(); const auto target = plan.GetCorrelatedRadarTarget();
this->predictETA(target, plan.GetPositionPredictions(), this->m_nextStarWaypoint != lastStarWaypoint); this->predictETA(target, plan.GetPositionPredictions());
} }
bool Inbound::fixedPlan() const noexcept { bool Inbound::fixedPlan() const noexcept {
return this->m_fixedPlan; 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 { const Time& Inbound::timeToLose() const noexcept {
return this->m_timeToLose; return this->m_timeToLose;
} }
const Length& Inbound::trackmiles() const noexcept {
return this->m_trackmiles;
}
const Time& Inbound::flighttime() const noexcept {
return this->m_flighttime;
}