void GlideComputerTask::ProcessBasicTask(const MoreData &basic, const MoreData &last_basic, DerivedInfo &calculated, const DerivedInfo &last_calculated, const ComputerSettings &settings_computer) { if (basic.HasTimeAdvancedSince(last_basic) && basic.location_available) trace.Update(settings_computer, ToAircraftState(basic, calculated)); ProtectedTaskManager::ExclusiveLease _task(task); _task->SetTaskBehaviour(settings_computer.task); if (basic.HasTimeAdvancedSince(last_basic) && basic.location_available) { const AircraftState current_as = ToAircraftState(basic, calculated); const AircraftState last_as = ToAircraftState(last_basic, last_calculated); _task->Update(current_as, last_as); const fixed fallback_mc = calculated.last_thermal.IsDefined() && positive(calculated.last_thermal_average_smooth) ? calculated.last_thermal_average_smooth : fixed_zero; if (_task->UpdateAutoMC(current_as, fallback_mc)) calculated.ProvideAutoMacCready(basic.clock, _task->GetGlidePolar().GetMC()); } calculated.task_stats = _task->GetStats(); calculated.common_stats = _task->GetCommonStats(); calculated.glide_polar_safety = _task->GetSafetyPolar(); }
void BasicComputer::Compute(MoreData &data, const MoreData &last, const MoreData &last_gps, const DerivedInfo &calculated) { ComputeTrack(data, last_gps); if (data.HasTimeAdvancedSince(last_gps)) { ComputeGroundSpeed(data, last_gps); ComputeAirspeed(data, calculated); } #ifndef NDEBUG // For testing without gps. // When CPU load is low enough it can be done for every sample. else if (data.dyn_pressure_available) ComputeAirspeed(data, calculated); #endif ComputeHeading(data.attitude, data, calculated); ComputeEnergyHeight(data); ComputeGPSVario(data, last, last_gps); ComputeBruttoVario(data); ComputeNettoVario(data, calculated); ComputeDynamics(data, calculated); }
void GlideComputerAirData::Average30s(const MoreData &basic, const NMEAInfo &last_basic, DerivedInfo &calculated, const DerivedInfo &last_calculated) { const bool time_advanced = basic.HasTimeAdvancedSince(last_basic); if (!time_advanced || calculated.circling != last_calculated.circling) { vario_30s_filter.reset(); netto_30s_filter.reset(); calculated.average = basic.brutto_vario; calculated.netto_average = basic.netto_vario; } if (!time_advanced) return; const unsigned Elapsed(basic.time - last_basic.time); if (Elapsed == 0) return; for (unsigned i = 0; i < Elapsed; ++i) { vario_30s_filter.update(basic.brutto_vario); netto_30s_filter.update(basic.netto_vario); } calculated.average = vario_30s_filter.average(); calculated.netto_average = netto_30s_filter.average(); }
void WarningComputer::Update(const ComputerSettings &settings_computer, const MoreData &basic, const MoreData &last_basic, const DerivedInfo &calculated, AirspaceWarningsInfo &result) { if (!basic.HasTimeAdvancedSince(last_basic) || !clock.check_advance(basic.time)) return; airspaces.set_flight_levels(settings_computer.pressure); AirspaceActivity day(calculated.date_time_local.day_of_week); airspaces.set_activity(day); if (!settings_computer.airspace.enable_warnings || !basic.location_available || !basic.NavAltitudeAvailable()) { if (initialised) { initialised = false; protected_manager.clear(); } return; } const AircraftState as = ToAircraftState(basic, calculated); ProtectedAirspaceWarningManager::ExclusiveLease lease(protected_manager); if (!initialised) { initialised = true; lease->Reset(as); } if (lease->Update(as, settings_computer.glide_polar_task, calculated.task_stats, calculated.circling, uround(basic.time - last_basic.time))) result.latest.Update(basic.clock); }
void GlideComputerAirData::GR(const MoreData &basic, const MoreData &last_basic, const DerivedInfo &calculated, VarioInfo &vario_info) { if (!basic.NavAltitudeAvailable() || !last_basic.NavAltitudeAvailable()) { vario_info.ld_vario = INVALID_GR; vario_info.gr = INVALID_GR; return; } if (basic.HasTimeRetreatedSince(last_basic)) { vario_info.ld_vario = INVALID_GR; vario_info.gr = INVALID_GR; } const bool time_advanced = basic.HasTimeAdvancedSince(last_basic); if (time_advanced) { fixed DistanceFlown = basic.location.Distance(last_basic.location); // Glide ratio over ground vario_info.gr = UpdateGR(vario_info.gr, DistanceFlown, last_basic.nav_altitude - basic.nav_altitude, fixed(0.1)); if (calculated.flight.flying && !calculated.circling) gr_calculator.Add((int)DistanceFlown, (int)basic.nav_altitude); } // Lift / drag instantaneous from vario, updated every reading.. if (basic.total_energy_vario_available && basic.airspeed_available && calculated.flight.flying) { vario_info.ld_vario = UpdateGR(vario_info.ld_vario, basic.indicated_airspeed, -basic.total_energy_vario, fixed(0.3)); } else { vario_info.ld_vario = INVALID_GR; } }
void CirclingComputer::Turning(CirclingInfo &circling_info, const MoreData &basic, const MoreData &last_basic, const DerivedInfo &calculated, const DerivedInfo &last_calculated, const ComputerSettings &settings_computer) { // You can't be circling unless you're flying if (!calculated.flight.flying || !basic.HasTimeAdvancedSince(last_basic)) return; // JMW limit rate to 50 deg per second otherwise a big spike // will cause spurious lock on circling for a long time fixed turn_rate = max(fixed(-50), min(fixed(50), calculated.turn_rate)); // Make the turn rate more smooth using the LowPassFilter turn_rate = LowPassFilter(last_calculated.turn_rate_smoothed, turn_rate, fixed(0.3)); circling_info.turn_rate_smoothed = turn_rate; circling_info.turning = fabs(turn_rate) >= min_turn_rate; // Force cruise or climb mode if external device says so bool force_cruise = false; bool force_circling = false; if (settings_computer.external_trigger_cruise_enabled && !basic.gps.replay) { switch (basic.switch_state.flight_mode) { case SwitchInfo::FlightMode::UNKNOWN: force_circling = false; force_cruise = false; break; case SwitchInfo::FlightMode::CIRCLING: force_circling = true; force_cruise = false; break; case SwitchInfo::FlightMode::CRUISE: force_circling = false; force_cruise = true; break; } } switch (calculated.turn_mode) { case CirclingMode::CRUISE: // If (in cruise mode and beginning of circling detected) if (circling_info.turning || force_circling) { // Remember the start values of the turn circling_info.turn_start_time = basic.time; circling_info.turn_start_location = basic.location; circling_info.turn_start_altitude = basic.nav_altitude; circling_info.turn_start_energy_height = basic.energy_height; circling_info.turn_mode = CirclingMode::POSSIBLE_CLIMB; } if (!force_circling) break; case CirclingMode::POSSIBLE_CLIMB: if (force_cruise) { circling_info.turn_mode = CirclingMode::CRUISE; break; } if (circling_info.turning || force_circling) { if (((basic.time - calculated.turn_start_time) > cruise_climb_switch) || force_circling) { // yes, we are certain now that we are circling circling_info.circling = true; // JMW Transition to climb circling_info.turn_mode = CirclingMode::CLIMB; // Remember the start values of the climbing period circling_info.climb_start_location = circling_info.turn_start_location; circling_info.climb_start_altitude = circling_info.turn_start_altitude + circling_info.turn_start_energy_height; circling_info.climb_start_time = circling_info.turn_start_time; } } else { // nope, not turning, so go back to cruise circling_info.turn_mode = CirclingMode::CRUISE; } break; case CirclingMode::CLIMB: if (!circling_info.turning || force_cruise) { // Remember the end values of the turn circling_info.turn_start_time = basic.time; circling_info.turn_start_location = basic.location; circling_info.turn_start_altitude = basic.nav_altitude; circling_info.turn_start_energy_height = basic.energy_height; // JMW Transition to cruise, due to not properly turning circling_info.turn_mode = CirclingMode::POSSIBLE_CRUISE; } if (!force_cruise) break; case CirclingMode::POSSIBLE_CRUISE: if (force_circling) { circling_info.turn_mode = CirclingMode::CLIMB; break; } if (!circling_info.turning || force_cruise) { if (((basic.time - circling_info.turn_start_time) > climb_cruise_switch) || force_cruise) { // yes, we are certain now that we are cruising again circling_info.circling = false; // Transition to cruise circling_info.turn_mode = CirclingMode::CRUISE; circling_info.cruise_start_location = circling_info.turn_start_location; circling_info.cruise_start_altitude = circling_info.turn_start_altitude; circling_info.cruise_start_time = circling_info.turn_start_time; } } else { // nope, we are circling again // JMW Transition back to climb, because we are turning again circling_info.turn_mode = CirclingMode::CLIMB; } break; } }