コード例 #1
0
ファイル: FlyingComputer.cpp プロジェクト: alon/xcsoar
void
FlyingComputer::Compute(fixed takeoff_speed,
                        const NMEAInfo &basic, const NMEAInfo &last_basic,
                        const DerivedInfo &calculated,
                        FlyingState &flying)
{
  if (basic.HasTimeRetreatedSince(last_basic)) {
    Reset();
    flying.Reset();
  }

  // GPS not lost
  if (!basic.location_available)
    return;

  // Speed too high for being on the ground
  const fixed speed = basic.airspeed_available
    ? std::max(basic.true_airspeed, basic.ground_speed)
    : basic.ground_speed;

  if (speed > takeoff_speed ||
      (calculated.altitude_agl_valid && calculated.altitude_agl > fixed(300)))
    Moving(flying, basic.time, basic.location);
  else
    Stationary(flying, basic.time, basic.location);
}
コード例 #2
0
ファイル: FlyingComputer.cpp プロジェクト: Adrien81/XCSoar
void
FlyingComputer::Compute(fixed takeoff_speed,
                        const NMEAInfo &basic,
                        const DerivedInfo &calculated,
                        FlyingState &flying)
{
  if (!basic.time_available || !basic.location_available)
    return;

  const fixed dt = delta_time.Update(basic.time, fixed(0.5), fixed(20));
  if (negative(dt)) {
    Reset();
    flying.Reset();
  }

  if (!positive(dt))
    return;

  const auto any_altitude = basic.GetAnyAltitude();

  if (!basic.airspeed_available && !calculated.altitude_agl_valid &&
      any_altitude.first && !negative(last_ground_altitude) &&
      any_altitude.second > last_ground_altitude + fixed(250)) {
    /* lower the threshold for "not moving" when the aircraft is high
       above the take-off airfield and there's no airspeed probe; this
       shall reduce the risk of false landing detection when flying in
       strong head wind (e.g. ridge or wave) */
    fixed dh = any_altitude.second - last_ground_altitude;

    if (dh > fixed(1000))
      takeoff_speed /= 4;
    else if (dh > fixed(500))
      takeoff_speed /= 2;
    else
      takeoff_speed = takeoff_speed * 2 / 3;
  }

  if (CheckTakeOffSpeed(takeoff_speed, basic) ||
      CheckAltitudeAGL(calculated))
    Moving(flying, basic.time, dt, basic.location);
  else if (!flying.flying ||
           (CheckLandingSpeed(takeoff_speed, basic) &&
            (!any_altitude.first || !CheckClimbing(dt, any_altitude.second))))
    Stationary(flying, basic.time, dt, basic.location);

  if (basic.engine_noise_level_available)
    CheckPowered(dt, basic, flying);

  if (any_altitude.first) {
    if (flying.on_ground)
      last_ground_altitude = any_altitude.second;

    CheckRelease(flying, basic.time, basic.location, any_altitude.second);
  } else
    sinking_since = fixed(-1);

  if (flying.flying && flying.release_location.IsValid()) {
    fixed distance = basic.location.Distance(flying.release_location);
    if (distance > flying.far_distance) {
      flying.far_location = basic.location;
      flying.far_distance = distance;
    }
  }
}
コード例 #3
0
ファイル: WaveComputer.cpp プロジェクト: Advi42/XCSoar
void
WaveComputer::Compute(const NMEAInfo &basic,
                      const FlyingState &flight,
                      WaveResult &result,
                      const WaveSettings &settings)
{
  const bool new_enabled = settings.enabled;
  if (new_enabled != last_enabled) {
    last_enabled = new_enabled;

    if (new_enabled) {
      /* the WaveComputer has just been enabled - initialise internal
         state */
      Initialise();
    } else
      /* the WaveComputer has just been disabled - clear the result */
      result.Clear();
  }

  if (!new_enabled) {
    /* we're disabled: bail out */
    assert(result.waves.empty());
    return;
  }

  if (!flight.IsGliding()) {
    /* no wave calculations while not in gliding free-flight */
    ResetCurrent();
    return;
  }

  const auto netto_vario_available = GetNettoVarioAvailable(basic);
  if (!basic.location_available.Modified(last_location_available) ||
      !netto_vario_available.Modified(last_netto_vario_available))
    /* no new data since the last call; need both a new GPS location
       and a vario value */
    return;

  const auto dt = delta_time.Update(basic.time, 0.5, 20);
  if (dt < 0)
    /* time warp */
    Reset();

  if (dt <= 0)
    /* throttle */
    return;

  const auto vario = basic.netto_vario;

  constexpr double threshold(0.5);
  if (vario > threshold) {
    /* positive vario value - feed it to the #LeastSquares instance */

    if (ls.IsEmpty())
      /* initialise the projection each time we inspect a new wave
         "candidate" */
      projection.SetCenter(basic.location);

    auto flat = projection.ProjectFloat(basic.location);
    ls.Update(flat.x, flat.y, vario - threshold / 2);
  }

  if (vario < 0)
    sinking_clock.Add(dt);
  else
    sinking_clock.Subtract(dt);

  const bool sinking = sinking_clock >= dt + 1;
  if (sinking) {
    /* we've been sinking; stop calculating the current wave; prepare
       to flush the #LeastSquares instance */
    if (ls.GetCount() > 30) {
      /* we've been lifting in the wave for some time; see if we
         really spotted a wave */
      const WaveInfo wave = GetWaveInfo(ls, projection,
                                        basic.time_available ? basic.time : 0);
      if (wave.IsDefined())
        /* yes, spotted a wave: copy it from the #LeastSquares
           instance to the list of waves */
        FoundWave(wave);
    }

    ls.Reset();
  }

  if (basic.time_available)
    /* forget all waves which are older than 8 hours */
    Decay(basic.time - 8 * 3600);

  /* fill the #WaveResult */

  result.Clear();

  /* first copy the wave that is currently being calculated (partial
     data) */
  WaveInfo wave = GetWaveInfo(ls, projection,
                              basic.time_available ? basic.time : 0);
  if (wave.IsDefined())
    result.waves.push_back(wave);

  /* now copy the rest */
  for (auto i = waves.begin(), end = waves.end();
       i != end && !result.waves.full(); ++i)
    result.waves.push_back(*i);

  /* remember some data for the next iteration */
  last_location_available = basic.location_available;
  last_netto_vario_available = netto_vario_available;
}