bool AbstractTask::UpdateAutoMC(GlidePolar &glide_polar, const AircraftState& state, fixed fallback_mc) { if (!task_behaviour.auto_mc) { /* AutoMC disabled in configuration */ ResetAutoMC(); return false; } fixed mc_found; if (task_behaviour.IsAutoMCFinalGlideEnabled() && TaskStarted(true) && stats.flight_mode_final_glide) { /* calculate final glide MacCready */ if (CalcBestMC(state, glide_polar, mc_found)) { /* final glide MacCready found */ if (mc_lpf_valid) stats.mc_best = std::max(mc_lpf.Update(mc_found), fixed(0)); else { stats.mc_best = std::max(mc_lpf.Reset(mc_found), fixed(0)); mc_lpf_valid = true; } } else /* below final glide, but above margin */ stats.mc_best = fixed(0); glide_polar.SetMC(stats.mc_best); return true; } else if (task_behaviour.IsAutoMCCruiseEnabled()) { /* cruise: set MacCready to recent climb average */ if (!positive(fallback_mc)) { /* no climb average calculated yet */ ResetAutoMC(); return false; } stats.mc_best = fallback_mc; glide_polar.SetMC(stats.mc_best); return true; } else if (TaskStarted(true)) { /* no solution, but forced final glide AutoMacCready - converge to zero */ mc_found = fixed(0); if (mc_lpf_valid) stats.mc_best = std::max(mc_lpf.Update(mc_found), fixed(0)); else { stats.mc_best = std::max(mc_lpf.Reset(mc_found), fixed(0)); mc_lpf_valid = true; } glide_polar.SetMC(stats.mc_best); return true; } else { ResetAutoMC(); return false; } }
void GlidePolarTest::TestMC() { polar.SetMC(fixed(1)); ok1(equals(polar.GetVBestLD(), 33.482780452)); polar.SetMC(fixed(0)); ok1(equals(polar.GetVBestLD(), 25.830434162)); }
void RenderMacCready(Canvas &canvas, const PixelRect rc, const ChartLook &chart_look, const GlidePolar &glide_polar) { ChartRenderer chart(chart_look, canvas, rc); if (!glide_polar.IsValid()) { chart.DrawNoData(); return; } chart.ScaleXFromValue(0); chart.ScaleXFromValue(MAX_MACCREADY); chart.ScaleYFromValue(0); chart.ScaleYFromValue(glide_polar.GetVMax()); chart.DrawXGrid(Units::ToSysVSpeed(1), 1, ChartRenderer::UnitFormat::NUMERIC); chart.DrawYGrid(Units::ToSysSpeed(10), 10, ChartRenderer::UnitFormat::NUMERIC); GlidePolar gp = glide_polar; double m = 0; double m_last; gp.SetMC(m); double v_last = gp.GetVBestLD(); double vav_last = 0; do { m_last = m; m+= MAX_MACCREADY/STEPS_MACCREADY; gp.SetMC(m); const double v = gp.GetVBestLD(); const double vav = gp.GetAverageSpeed(); chart.DrawLine(m_last, v_last, m, v, ChartLook::STYLE_BLACK); chart.DrawLine(m_last, vav_last, m, vav, ChartLook::STYLE_BLUETHINDASH); v_last = v; vav_last = vav; } while (m<MAX_MACCREADY); // draw current MC setting chart.DrawLine(glide_polar.GetMC(), 0, glide_polar.GetMC(), glide_polar.GetVMax(), ChartLook::STYLE_REDTHICKDASH); // draw labels and other overlays gp.SetMC(0.9*MAX_MACCREADY); chart.DrawLabel(_T("Vopt"), 0.9*MAX_MACCREADY, gp.GetVBestLD()); gp.SetMC(0.9*MAX_MACCREADY); chart.DrawLabel(_T("Vave"), 0.9*MAX_MACCREADY, gp.GetAverageSpeed()); chart.DrawYLabel(_T("V"), Units::GetSpeedName()); chart.DrawXLabel(_T("MC"), Units::GetVerticalSpeedName()); RenderGlidePolarInfo(canvas, rc, chart_look, glide_polar); }
GlidePolar AbortTask::GetSafetyPolar() const { const fixed mc_safety = task_behaviour.safety_mc; GlidePolar polar = glide_polar; polar.SetMC(mc_safety); return polar; }
int main(int argc, char **argv) { plan_tests(728); task_behaviour.SetDefaults(); TestAll(); glide_polar.SetMC(fixed(1)); TestAll(); glide_polar.SetMC(fixed(2)); TestAll(); glide_polar.SetMC(fixed(4)); TestAll(); return exit_status(); }
int main(int argc, char **argv) { plan_tests(2095); glide_settings.SetDefaults(); TestAll(); glide_polar.SetMC(fixed(0.1)); TestAll(); glide_polar.SetMC(fixed(1)); TestAll(); glide_polar.SetMC(fixed(4)); TestAll(); glide_polar.SetMC(fixed(10)); TestAll(); return exit_status(); }
bool AbstractTask::UpdateAutoMC(GlidePolar &glide_polar, const AircraftState& state, fixed fallback_mc) { if (!positive(fallback_mc)) fallback_mc = glide_polar.GetMC(); if (!TaskStarted(true) || !task_behaviour.auto_mc) { ResetAutoMC(); return false; } if (task_behaviour.auto_mc_mode == TaskBehaviour::AutoMCMode::CLIMBAVERAGE) { stats.mc_best = mc_lpf.reset(fallback_mc); mc_lpf_valid = true; trigger_auto = false; return false; } fixed mc_found; if (CalcBestMC(state, glide_polar, mc_found)) { // improved solution found, activate auto fg mode if (mc_found > stats.mc_best) trigger_auto = true; } else { // no solution even at mc=0, deactivate auto fg mode trigger_auto = false; } if (!trigger_auto && task_behaviour.auto_mc_mode == TaskBehaviour::AutoMCMode::FINALGLIDE && stats.mc_best >= fixed(0.05)) { /* no solution, but forced final glide AutoMacCready - converge to zero */ mc_found = fixed_zero; trigger_auto = true; } if (trigger_auto && mc_lpf_valid) { // smooth out updates stats.mc_best = std::max(mc_lpf.update(mc_found), fixed_zero); glide_polar.SetMC(stats.mc_best); } else { // reset lpf so will be smooth next time it becomes active stats.mc_best = mc_lpf.reset(fallback_mc); mc_lpf_valid = true; } return trigger_auto; }
void InputEvents::eventNearestAirspaceDetails(gcc_unused const TCHAR *misc) { const MoreData &basic = CommonInterface::Basic(); const DerivedInfo &calculated = CommonInterface::Calculated(); const ComputerSettings &settings_computer = CommonInterface::GetComputerSettings(); ProtectedAirspaceWarningManager *airspace_warnings = GetAirspaceWarnings(); if (airspace_warnings != NULL && !airspace_warnings->warning_empty()) { // Prevent the dialog from closing itself without active warning // This is relevant if there are only acknowledged airspaces in the list // AutoClose will be reset when the dialog is closed again by hand dlgAirspaceWarningsShowModal(*XCSoarInterface::main_window, *airspace_warnings); return; } const AircraftState aircraft_state = ToAircraftState(basic, calculated); AirspaceVisiblePredicate visible(settings_computer.airspace, CommonInterface::GetMapSettings().airspace, aircraft_state); GlidePolar polar = settings_computer.polar.glide_polar_task; polar.SetMC(max(polar.GetMC(),fixed_one)); AirspaceAircraftPerformanceGlide perf(polar); AirspaceSoonestSort ans(aircraft_state, perf, fixed(1800), visible); const AbstractAirspace* as = ans.find_nearest(airspace_database); if (!as) { return; } dlgAirspaceDetails(*as, airspace_warnings); // clear previous warning if any XCSoarInterface::main_window->popup.Acknowledge(PopupMessage::MSG_AIRSPACE); // TODO code: No control via status data (ala DoStatusMEssage) // - can we change this? // Message::AddMessage(5000, Message::MSG_AIRSPACE, text); }
/** * Adjust MacCready value of internal glide polar * * @param mc MacCready value (m/s) */ void set_mc(fixed mc) { m_glide_polar.SetMC(mc); };