|
@@ -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.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;
|
|
|
|
|
|
- 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 route(target.GetCorrelatedFlightPlan().GetFlightPlanData().GetRoute());
|
|
std::string arrival = this->m_star + "/" + this->m_runway;
|
|
std::string arrival = this->m_star + "/" + this->m_runway;
|
|
|
|
|
|
@@ -92,7 +95,7 @@ void Inbound::updatePrediction(EuroScopePlugIn::CRadarTarget& target, const aman
|
|
updatedFlightplan = true;
|
|
updatedFlightplan = true;
|
|
}
|
|
}
|
|
|
|
|
|
- if (true == updatedFlightplan) {
|
|
|
|
|
|
+ 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();
|
|
@@ -225,7 +228,10 @@ static __inline Angle __normalize(const Angle& angle) {
|
|
return retval;
|
|
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())
|
|
if (0 == predictions.GetPointsNumber())
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -237,39 +243,27 @@ int Inbound::findIndexInPredictedPath(const EuroScopePlugIn::CFlightPlanPosition
|
|
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())
|
|
|
|
- return i;
|
|
|
|
|
|
+ if (100_deg <= delta.abs()) {
|
|
|
|
+ trackmiles += lastPosition.distanceTo(position);
|
|
|
|
+ return i - 1;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ trackmiles += lastPosition.distanceTo(coordinate);
|
|
lastPosition = coordinate;
|
|
lastPosition = coordinate;
|
|
}
|
|
}
|
|
|
|
|
|
return predictions.GetPointsNumber();
|
|
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;
|
|
this->m_timeToLose = 0_s;
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
const auto& destination = gsl::at(this->m_arrivalRoute, this->m_nextStarWaypoint);
|
|
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;
|
|
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 */
|
|
/* predict the flight and the descend */
|
|
Velocity groundSpeed = static_cast<float>(target.GetPosition().GetReportedGS()) * knot;
|
|
Velocity groundSpeed = static_cast<float>(target.GetPosition().GetReportedGS()) * knot;
|
|
@@ -298,33 +292,71 @@ void Inbound::update(EuroScopePlugIn::CRadarTarget& target) {
|
|
flightTime += 1_s;
|
|
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) {
|
|
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()) {
|
|
|
|
+ this->m_timeToLose = 0_s;
|
|
return;
|
|
return;
|
|
|
|
+ }
|
|
|
|
|
|
/* find the point on the route */
|
|
/* find the point on the route */
|
|
- std::string_view direct(plan.GetControllerAssignedData().GetDirectToPointName());
|
|
|
|
|
|
+ std::string direct(plan.GetControllerAssignedData().GetDirectToPointName());
|
|
auto route = plan.GetExtractedRoute();
|
|
auto route = plan.GetExtractedRoute();
|
|
int starEntry = route.GetPointsNumber(), directEntry = route.GetPointsNumber();
|
|
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) {
|
|
for (int c = 0; c < route.GetPointsNumber(); ++c) {
|
|
std::string_view waypointName(route.GetPointName(c));
|
|
std::string_view waypointName(route.GetPointName(c));
|
|
-
|
|
|
|
- if (waypointName == this->m_arrivalRoute.front().name())
|
|
|
|
|
|
+ if (waypointName == this->m_arrivalRoute.front().name()) {
|
|
starEntry = c;
|
|
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 */
|
|
/* search the direct to entry */
|
|
@@ -345,13 +377,13 @@ void Inbound::update(EuroScopePlugIn::CFlightPlan& plan) {
|
|
break;
|
|
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 {
|
|
bool Inbound::fixedPlan() const noexcept {
|