void OrderedTask::GlideSolutionPlanned(const AircraftState &aircraft, const GlidePolar &glide_polar, GlideResult &total, GlideResult &leg, DistanceStat &total_remaining_effective, DistanceStat &leg_remaining_effective, const GlideResult &solution_remaining_total, const GlideResult &solution_remaining_leg) { TaskMacCreadyTotal tm(task_points, active_task_point, task_behaviour.glide, glide_polar); total = tm.glide_solution(aircraft); leg = tm.get_active_solution(); if (solution_remaining_total.IsOk()) total_remaining_effective.SetDistance(tm.effective_distance(solution_remaining_total.time_elapsed)); else total_remaining_effective.Reset(); if (solution_remaining_leg.IsOk()) leg_remaining_effective.SetDistance(tm.effective_leg_distance(solution_remaining_leg.time_elapsed)); else leg_remaining_effective.Reset(); }
static void CheckLegEqualsTotal(const GlideResult &leg, const GlideResult &total) { ok1(total.IsOk()); ok1(equals(total.height_climb, leg.height_climb)); ok1(equals(total.height_glide, leg.height_glide)); ok1(equals(total.altitude_difference, leg.altitude_difference)); ok1(equals(total.GetRequiredAltitudeWithDrift(), leg.GetRequiredAltitudeWithDrift())); }
/** * Function to optimise in search * * \note the f(x) is magnified because with fixed, find_min can * fail with too small df/dx * * @param V cruise true air speed (m/s) * @return Inverse LD */ double f(const double v) { res = mac.SolveGlide(task, v, allow_partial); if (!res.IsOk() || res.vector.distance <= 0) /* the solver failed: return a large value that will be discarded by ZeroFinder */ return 1000000; return res.height_glide * 1024 / res.vector.distance; }
void UnorderedTask::GlideSolutionPlanned(const AircraftState &state, GlideResult &total, GlideResult &leg, DistanceStat &total_remaining_effective, DistanceStat &leg_remaining_effective, const GlideResult &solution_remaining_total, const GlideResult &solution_remaining_leg) { total = solution_remaining_total; leg = solution_remaining_leg; if (total.IsOk()) total_remaining_effective.set_distance(total.vector.distance); else total_remaining_effective.Reset(); if (leg.IsOk()) leg_remaining_effective.set_distance(leg.vector.distance); else leg_remaining_effective.Reset(); }
void RoutePolar::Initialise(const GlidePolar& polar, const SpeedVector& wind, const bool is_glide) { for (unsigned i = 0; i < ROUTEPOLAR_POINTS; ++i) { const Angle ang = IndexToAngle(i); GlideResult res = SolveTask(polar, wind, ang, is_glide); if (res.IsOk()) { RoutePolarPoint point(res.time_elapsed, res.height_glide); points[i] = point; } else points[i].valid = false; } }
void RoutePolar::Initialise(const GlideSettings &settings, const GlidePolar& polar, const SpeedVector& wind, const bool is_glide) { static constexpr Angle ang_step = Angle::FullCircle() / ROUTEPOLAR_POINTS; Angle ang = Angle::QuarterCircle(); for (unsigned i = 0; i < ROUTEPOLAR_POINTS; ++i, ang -= ang_step) { GlideResult res = SolveTask(settings, polar, wind, ang, is_glide); if (res.IsOk()) { RoutePolarPoint point(res.time_elapsed, res.height_glide); points[i] = point; } else points[i].valid = false; } }
fixed TaskSolveTravelled::time_error() { GlideResult res = tm.glide_solution(aircraft); if (!res.IsOk()) /* what can we do if there's no solution? This is an attempt to make ZeroFinder ignore this call, by returning a large value. I'm not sure if this kludge is correct. */ return fixed(999999); #ifdef SOLVE_ZERO fixed d = res.time_elapsed-dt; #else fixed d = fabs(res.time_elapsed-dt); #endif d += res.time_virtual; return d*inv_dt; }
void CrossSectionRenderer::PaintGlide(ChartRenderer &chart) const { if (!gps_info.NavAltitudeAvailable() || !glide_polar.IsValid()) return; const fixed altitude = gps_info.nav_altitude; const MacCready mc(glide_settings, glide_polar); const GlideState task(vec, fixed(0), altitude, calculated_info.GetWindOrZero()); const GlideResult result = mc.SolveStraight(task); if (!result.IsOk()) return; chart.DrawLine(fixed(0), altitude, result.vector.distance, result.GetArrivalAltitude(), ChartLook::STYLE_BLUETHIN); }
void CalculateReachabilityDirect(const MoreData &basic, const SpeedVector &wind, const MacCready &mac_cready, const TaskBehaviour &task_behaviour) { assert(basic.location_available); assert(basic.NavAltitudeAvailable()); const auto elevation = waypoint->elevation + task_behaviour.safety_height_arrival; const GlideState state(GeoVector(basic.location, waypoint->location), elevation, basic.nav_altitude, wind); const GlideResult result = mac_cready.SolveStraight(state); if (!result.IsOk()) return; reach.direct = result.pure_glide_altitude_difference; if (result.pure_glide_altitude_difference > 0) reachable = WaypointRenderer::ReachableTerrain; }
/** * Specialisation of AirspaceAircraftPerformance for tasks where * part of the path is in cruise, part in final glide. This is * intended to be used temporarily only. * * This simplifies the path by assuming flight is constant altitude * or descent to the task point elevation. */ AirspaceAircraftPerformance(const GlidePolar &polar, const GlideResult &solution) :vertical_tolerance(0.001), cruise_speed(positive(solution.time_elapsed) ? solution.vector.distance / solution.time_elapsed : fixed(1)), cruise_descent(positive(solution.time_elapsed) ? (positive(solution.height_climb) ? -solution.height_climb : solution.height_glide) / solution.time_elapsed : fixed(0)), descent_rate(polar.GetSBestLD()), climb_rate(positive(solution.time_elapsed) && positive(solution.height_climb) ? polar.GetMC() : fixed(0)), max_speed(cruise_speed) { assert(polar.IsValid()); assert(solution.IsOk()); assert(solution.IsAchievable()); }