/** * Is called by the CalculationThread and processes the received GPS data in Basic() */ bool GlideComputer::ProcessGPS(bool force) { const MoreData &basic = Basic(); DerivedInfo &calculated = SetCalculated(); const ComputerSettings &settings = GetComputerSettings(); const bool last_flying = calculated.flight.flying; calculated.date_time_local = basic.date_time_utc + settings.utc_offset; calculated.Expire(basic.clock); // Process basic information air_data_computer.ProcessBasic(Basic(), SetCalculated(), GetComputerSettings()); // Process basic task information task_computer.ProcessBasicTask(basic, LastBasic(), calculated, GetComputerSettings(), force); task_computer.ProcessMoreTask(basic, calculated, GetComputerSettings()); // Check if everything is okay with the gps time and process it if (!air_data_computer.FlightTimes(Basic(), LastBasic(), SetCalculated(), GetComputerSettings())) return false; TakeoffLanding(last_flying); if (!time_retreated()) task_computer.ProcessAutoTask(basic, calculated); // Process extended information air_data_computer.ProcessVertical(Basic(), LastBasic(), SetCalculated(), GetComputerSettings()); if (!time_retreated()) stats_computer.ProcessClimbEvents(calculated); // Calculate the team code CalculateOwnTeamCode(); // Calculate the bearing and range of the teammate CalculateTeammateBearingRange(); vegavoice.Update(basic, Calculated(), GetComputerSettings().voice); // update basic trace history if (time_advanced()) calculated.trace_history.append(basic); // Update the ConditionMonitors ConditionMonitorsUpdate(Basic(), Calculated(), settings); return idle_clock.CheckUpdate(500); }
void DeviceBlackboard::tick() { SetBasic().expire(); // calculate fast data to complete aircraft state computer.Compute(SetBasic(), LastBasic(), Calculated(), SettingsComputer()); if (Basic().Time!= LastBasic().Time) { state_last = Basic(); } }
/** * Process slow calculations. Called by the CalculationThread. */ void GlideComputer::ProcessIdle(bool exhaustive) { // Log GPS fixes for internal usage // (snail trail, stats, olc, ...) stats_computer.DoLogging(Basic(), LastBasic(), Calculated(), GetComputerSettings().logger); task_computer.ProcessIdle(Basic(), SetCalculated(), GetComputerSettings(), exhaustive); if (time_advanced()) warning_computer.Update(GetComputerSettings(), Basic(), LastBasic(), Calculated(), SetCalculated().airspace_warnings); }
/** * Logs GPS fixes for stats * @return True if valid fix (fix distance <= 200m), False otherwise */ bool GlideComputerStats::DoLogging() { /// @todo consider putting this sanity check inside Parser if (Distance(Basic().location, LastBasic().location) > fixed(200)) // prevent bad fixes from being logged or added to OLC store return false; // log points more often in circling mode if (Calculated().circling) log_clock.set_dt(fixed(SettingsComputer().LoggerTimeStepCircling)); else log_clock.set_dt(fixed(SettingsComputer().LoggerTimeStepCruise)); if (FastLogNum) { log_clock.set_dt(fixed_one); FastLogNum--; } if (log_clock.check_advance(Basic().time) && logger != NULL) logger->LogPoint(Basic()); if (Calculated().flight.flying && stats_clock.check_advance(Basic().time)) { flightstats.AddAltitudeTerrain(Calculated().flight.flight_time, Calculated().terrain_altitude); flightstats.AddAltitude(Calculated().flight.flight_time, Basic().NavAltitude); flightstats.AddTaskSpeed(Calculated().flight.flight_time, Calculated().task_stats.get_pirker_speed()); } return true; }
/** * Calculates location, altitude, average climb speed and * looks up the callsign of each target */ void DeviceBlackboard::ProcessFLARM() { const NMEA_INFO &basic = Basic(); FLARM_STATE &flarm = SetBasic().flarm; const FLARM_STATE &last_flarm = LastBasic().flarm; // if (FLARM data is available) if (!flarm.available || flarm.traffic.empty()) return; fixed FLARM_NorthingToLatitude(0); fixed FLARM_EastingToLongitude(0); if (basic.LocationAvailable) { // Precalculate relative east and north projection to lat/lon // for Location calculations of each target Angle delta_lat = Angle::degrees(fixed(0.01)); Angle delta_lon = Angle::degrees(fixed(0.01)); GeoPoint plat = basic.Location; plat.Latitude += delta_lat; GeoPoint plon = basic.Location; plon.Longitude += delta_lon; fixed dlat = Distance(basic.Location, plat); fixed dlon = Distance(basic.Location, plon); if (positive(fabs(dlat)) && positive(fabs(dlon))) { FLARM_NorthingToLatitude = delta_lat.value_degrees() / dlat; FLARM_EastingToLongitude = delta_lon.value_degrees() / dlon; } } // for each item in traffic for (unsigned i = 0; i < flarm.traffic.size(); i++) { FLARM_TRAFFIC &traffic = flarm.traffic[i]; // if we don't know the target's name yet if (!traffic.HasName()) { // lookup the name of this target's id const TCHAR *fname = FlarmDetails::LookupCallsign(traffic.id); if (fname != NULL) traffic.name = fname; } // Calculate distance traffic.distance = hypot(traffic.relative_north, traffic.relative_east); // Calculate Location traffic.location_available = basic.LocationAvailable; if (traffic.location_available) { traffic.location.Latitude = Angle::degrees(traffic.relative_north * FLARM_NorthingToLatitude) + basic.Location.Latitude; traffic.location.Longitude = Angle::degrees(traffic.relative_east * FLARM_EastingToLongitude) + basic.Location.Longitude; } // Calculate absolute altitude traffic.altitude_available = basic.GPSAltitudeAvailable; if (traffic.altitude_available) traffic.altitude = traffic.relative_altitude + basic.GPSAltitude; // Calculate average climb rate traffic.climb_rate_avg30s_available = traffic.altitude_available; if (traffic.climb_rate_avg30s_available) traffic.climb_rate_avg30s = flarmCalculations.Average30s(traffic.id, basic.Time, traffic.altitude); // The following calculations are only relevant for targets // where information is missing if (traffic.track_received || traffic.turn_rate_received || traffic.speed_received || traffic.climb_rate_received) continue; // Check if the target has been seen before in the last seconds const FLARM_TRAFFIC *last_traffic = last_flarm.FindTraffic(traffic.id); if (last_traffic == NULL || !last_traffic->valid) continue; // Calculate the time difference between now and the last contact fixed dt = traffic.valid.GetTimeDifference(last_traffic->valid); if (positive(dt)) { // Calculate the immediate climb rate if (!traffic.climb_rate_received) traffic.climb_rate = (traffic.relative_altitude - last_traffic->relative_altitude) / dt; } else { // Since the time difference is zero (or negative) // we can just copy the old values if (!traffic.climb_rate_received) traffic.climb_rate = last_traffic->climb_rate; } if (positive(dt) && traffic.location_available && last_traffic->location_available) { // Calculate the GeoVector between now and the last contact GeoVector vec = last_traffic->location.distance_bearing(traffic.location); if (!traffic.track_received) traffic.track = vec.Bearing; // Calculate the turn rate if (!traffic.turn_rate_received) traffic.turn_rate = (traffic.track - last_traffic->track).as_delta().value_degrees() / dt; // Calculate the speed [m/s] if (!traffic.speed_received) traffic.speed = vec.Distance / dt; } else { // Since the time difference is zero (or negative) // we can just copy the old values if (!traffic.track_received) traffic.track = last_traffic->track; if (!traffic.turn_rate_received) traffic.turn_rate = last_traffic->turn_rate; if (!traffic.speed_received) traffic.speed = last_traffic->speed; } } }
bool time_advanced() { return Basic().Time - LastBasic().Time > fixed_zero; }
fixed time_delta() const { return Basic().time - LastBasic().time; }
bool time_advanced() const { return Basic().HasTimeAdvancedSince(LastBasic()); }
bool time_advanced() { return (Basic().Time-LastBasic().Time>0); }