bool DemoReplayGlue::Update(NMEAInfo &data, fixed time_scale) { if (!UpdateTime()) return true; fixed floor_alt = fixed_300; if (device_blackboard->Calculated().terrain_valid) { floor_alt += device_blackboard->Calculated().terrain_altitude; } bool retval; { ProtectedTaskManager::ExclusiveLease protected_task_manager(*task_manager); TaskAccessor ta(protected_task_manager, floor_alt); retval = DemoReplay::Update(time_scale, ta); } const AircraftState &s = aircraft.GetState(); data.clock = s.time; data.alive.Update(data.clock); data.ProvideTime(s.time); data.location = s.location; data.location_available.Update(data.clock); data.ground_speed = s.ground_speed; data.ground_speed_available.Update(data.clock); data.track = s.track; data.track_available.Update(data.clock); data.gps_altitude = s.altitude; data.gps_altitude_available.Update(data.clock); data.ProvidePressureAltitude(s.altitude); data.ProvideBaroAltitudeTrue(s.altitude); data.gps.real = false; data.gps.replay = true; data.gps.simulator = false; return retval; }
bool Replay::Update() { if (replay == nullptr) return false; if (time_scale <= 0) { /* replay is paused */ /* to avoid a big fast-forward with the next PeriodClock::ElapsedUpdate() call below after unpausing, update the clock each time we're called while paused */ clock.Update(); return true; } const double old_virtual_time = virtual_time; if (virtual_time >= 0) { /* update the virtual time */ assert(clock.IsDefined()); if (fast_forward < 0) { virtual_time += clock.ElapsedUpdate() * time_scale / 1000; } else { clock.Update(); virtual_time += 1; if (virtual_time >= fast_forward) fast_forward = -1; } } else { /* if we ever received a valid time from the AbstractReplay, then virtual_time must be initialised */ assert(!next_data.time_available); } if (cli == nullptr || fast_forward >= 0) { if (next_data.time_available && virtual_time < next_data.time) /* still not time to use next_data */ return true; { std::lock_guard<Mutex> lock(device_blackboard->mutex); device_blackboard->SetReplayState() = next_data; device_blackboard->ScheduleMerge(); } while (true) { if (!replay->Update(next_data)) { Stop(); return false; } assert(!next_data.gps.real); if (next_data.time_available) { if (virtual_time < 0) { virtual_time = next_data.time; if (fast_forward >= 0) fast_forward += virtual_time; clock.Update(); break; } if (next_data.time >= virtual_time) break; if (next_data.time < old_virtual_time) { /* time warp; that can happen on midnight wraparound during NMEA replay */ virtual_time = next_data.time; break; } } } } else { while (cli->NeedData(virtual_time)) { if (!replay->Update(next_data)) { Stop(); return false; } assert(!next_data.gps.real); if (next_data.time_available) cli->Update(next_data.time, next_data.location, next_data.gps_altitude, next_data.pressure_altitude); } if (virtual_time < 0) { virtual_time = cli->GetMaxTime(); if (fast_forward >= 0) fast_forward += virtual_time; clock.Update(); } const CatmullRomInterpolator::Record r = cli->Interpolate(virtual_time); const GeoVector v = cli->GetVector(virtual_time); NMEAInfo data = next_data; data.clock = virtual_time; data.alive.Update(data.clock); data.ProvideTime(virtual_time); data.location = r.location; data.location_available.Update(data.clock); data.ground_speed = v.distance; data.ground_speed_available.Update(data.clock); data.track = v.bearing; data.track_available.Update(data.clock); data.gps_altitude = r.gps_altitude; data.gps_altitude_available.Update(data.clock); data.ProvidePressureAltitude(r.baro_altitude); data.ProvideBaroAltitudeTrue(r.baro_altitude); { std::lock_guard<Mutex> lock(device_blackboard->mutex); device_blackboard->SetReplayState() = data; device_blackboard->ScheduleMerge(); } } return true; }
bool IgcReplay::Update(NMEAInfo &basic) { IGCFix fix; while (true) { if (!ReadPoint(fix, basic)) return false; if (fix.time.IsPlausible()) break; } basic.clock = fixed(fix.time.GetSecondOfDay()); basic.alive.Update(basic.clock); basic.ProvideTime(basic.clock); basic.location = fix.location; basic.location_available.Update(basic.clock); if (fix.gps_altitude != 0) { basic.gps_altitude = fixed(fix.gps_altitude); basic.gps_altitude_available.Update(basic.clock); } else basic.gps_altitude_available.Clear(); if (fix.pressure_altitude != 0) { basic.ProvidePressureAltitude(fixed(fix.pressure_altitude)); basic.ProvideBaroAltitudeTrue(fixed(fix.pressure_altitude)); } else { basic.pressure_altitude_available.Clear(); basic.baro_altitude_available.Clear(); } if (fix.enl >= 0) { basic.engine_noise_level = fix.enl; basic.engine_noise_level_available.Update(basic.clock); } else basic.engine_noise_level_available.Clear(); if (fix.trt >= 0) { basic.track = Angle::Degrees(fixed(fix.trt)); basic.track_available.Update(basic.clock); } else basic.track_available.Clear(); if (fix.gsp >= 0) { basic.ground_speed = Units::ToSysUnit(fixed(fix.gsp), Unit::KILOMETER_PER_HOUR); basic.ground_speed_available.Update(basic.clock); } else basic.ground_speed_available.Clear(); if (fix.ias >= 0) { fixed ias = Units::ToSysUnit(fixed(fix.ias), Unit::KILOMETER_PER_HOUR); if (fix.tas >= 0) basic.ProvideBothAirspeeds(ias, Units::ToSysUnit(fixed(fix.tas), Unit::KILOMETER_PER_HOUR)); else basic.ProvideIndicatedAirspeedWithAltitude(ias, basic.pressure_altitude); } else if (fix.tas >= 0) basic.ProvideTrueAirspeed(Units::ToSysUnit(fixed(fix.tas), Unit::KILOMETER_PER_HOUR)); if (fix.siu >= 0) { basic.gps.satellites_used = fix.siu; basic.gps.satellites_used_available.Update(basic.clock); } basic.gps.real = false; basic.gps.replay = true; basic.gps.simulator = false; return true; }