Ejemplo n.º 1
0
/**
 * Attempt to compute airspeed when it is not yet available from:
 * 1) dynamic pressure and air density derived from some altitude.
 * 2) pitot pressure and static pressure.
 * 3) ground speed and wind.
 */
static void
ComputeAirspeed(NMEAInfo &basic, const DerivedInfo &calculated)
{
  if (basic.airspeed_available && basic.airspeed_real)
    /* got it already */
    return;

  const auto any_altitude = basic.GetAnyAltitude();

  if (!basic.airspeed_available && any_altitude.first) {
    fixed dyn; bool available = false;
    if (basic.dyn_pressure_available) {
      dyn = basic.dyn_pressure.GetHectoPascal();
      available = true;
    } else if (basic.pitot_pressure_available && basic.static_pressure_available) {
      dyn = basic.pitot_pressure.GetHectoPascal() - basic.static_pressure.GetHectoPascal();
      available = true;
    }
    if (available) {
      basic.indicated_airspeed = sqrt(fixed(163.2653061) * dyn);
      basic.true_airspeed = basic.indicated_airspeed *
                            AirDensityRatio(any_altitude.second);

      basic.airspeed_available.Update(basic.clock);
      basic.airspeed_real = true; // Anyway not less real then any other method.
      return;
    }
  }

  if (!basic.ground_speed_available || !calculated.wind_available ||
      !calculated.flight.flying) {
    /* impossible to calculate */
    basic.airspeed_available.Clear();
    return;
  }

  fixed TrueAirspeedEstimated = fixed(0);

  const SpeedVector wind = calculated.wind;
  if (positive(basic.ground_speed) || wind.IsNonZero()) {
    fixed x0 = basic.track.fastsine() * basic.ground_speed;
    fixed y0 = basic.track.fastcosine() * basic.ground_speed;
    x0 += wind.bearing.fastsine() * wind.norm;
    y0 += wind.bearing.fastcosine() * wind.norm;

    TrueAirspeedEstimated = SmallHypot(x0, y0);
  }

  basic.true_airspeed = TrueAirspeedEstimated;

  basic.indicated_airspeed = TrueAirspeedEstimated;
  if (any_altitude.first)
    basic.indicated_airspeed /= AirDensityRatio(any_altitude.second);

  basic.airspeed_available.Update(basic.clock);
  basic.airspeed_real = false;
}
Ejemplo n.º 2
0
void
GlideComputerAirData::Heading(const NMEAInfo &basic, DerivedInfo &calculated)
{
  const SpeedVector wind = calculated.wind;

  if (calculated.wind_available &&
      (positive(basic.ground_speed) || wind.IsNonZero()) &&
      calculated.flight.flying) {
    fixed x0 = basic.track.fastsine() * basic.ground_speed;
    fixed y0 = basic.track.fastcosine() * basic.ground_speed;
    x0 += wind.bearing.fastsine() * wind.norm;
    y0 += wind.bearing.fastcosine() * wind.norm;

    calculated.heading = Angle::Radians(atan2(x0, y0)).AsBearing();
  } else {
    calculated.heading = basic.track;
  }
}
Ejemplo n.º 3
0
/*
!w,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>,<13>*hh<CR><LF>
<1>  Vector wind direction in degrees
<2>  Vector wind speed in 10ths of meters per second
<3>  Vector wind age in seconds
<4>  Component wind in 10ths of Meters per second + 500 (500 = 0, 495 = 0.5 m/s tailwind)
<5>  True altitude in Meters + 1000
<6>  Instrument QNH setting
<7>  True airspeed in 100ths of Meters per second
<8>  Variometer reading in 10ths of knots + 200
<9>  Averager reading in 10ths of knots + 200
<10> Relative variometer reading in 10ths of knots + 200
<11> Instrument MacCready setting in 10ths of knots
<12> Instrument Ballast setting in percent of capacity
<13> Instrument Bug setting
*hh  Checksum, XOR of all bytes
*/
static bool
cai_w(NMEAInputLine &line, NMEAInfo &info)
{
  SpeedVector wind;
  if (ReadSpeedVector(line, wind))
    info.ProvideExternalWind(wind.Reciprocal());

  line.skip(2);

  fixed value;
  if (line.read_checked(value))
    info.ProvideBaroAltitudeTrue(value - fixed(1000));

  if (line.read_checked(value))
    info.settings.ProvideQNH(value, info.clock);

  if (line.read_checked(value))
    info.ProvideTrueAirspeed(value / 100);

  if (line.read_checked(value))
    info.ProvideTotalEnergyVario(Units::ToSysUnit((value - fixed(200)) / 10,
                                                  unKnots));

  line.skip(2);

  int i;

  if (line.read_checked(i))
    info.settings.ProvideMacCready(Units::ToSysUnit(fixed(i) / 10, unKnots),
                                   info.clock);

  if (line.read_checked(i))
    info.settings.ProvideBallastFraction(fixed(i) / 100, info.clock);

  if (line.read_checked(i))
    info.settings.ProvideBugs(fixed(i) / 100, info.clock);

  return true;
}
Ejemplo n.º 4
0
void
GlideState::CalcSpeedups(const SpeedVector _wind)
{
  if (_wind.IsNonZero()) {
    wind = _wind;
    effective_wind_angle = wind.bearing.Reciprocal() - vector.bearing;
    wind_speed_squared = sqr(wind.norm);
    head_wind = -wind.norm * effective_wind_angle.cos();
  } else {
    wind = SpeedVector::Zero();
    effective_wind_angle = Angle::Zero();
    head_wind = fixed(0);
    wind_speed_squared = fixed(0);
  }
}
Ejemplo n.º 5
0
fixed
GlidePolar::GetLDOverGround(Angle track, SpeedVector wind) const
{
  if (wind.IsZero())
    return bestLD;

  const fixed c_theta = (wind.bearing.Reciprocal() - track).cos();

  /* convert the wind speed into some sort of "virtual L/D" to put it
     in relation to the polar's best L/D */
  const fixed wind_ld = wind.norm / GetSBestLD();

  Quadratic q(- Double(wind_ld * c_theta),
              sqr(wind_ld) - sqr(bestLD));

  if (q.Check())
    return std::max(fixed(0), q.SolutionMax());

  return fixed(0);
}
Ejemplo n.º 6
0
static void
DrawThermalSources(Canvas &canvas, const MaskedIcon &icon,
                   const WindowProjection &projection,
                   const T &sources,
                   const double aircraft_altitude,
                   const SpeedVector &wind)
{
  for (const auto &source : sources) {
    // find height difference
    if (aircraft_altitude < source.ground_height)
      continue;

    // draw thermal at location it would be at the glider's height
    GeoPoint location = wind.IsNonZero()
      ? source.CalculateAdjustedLocation(aircraft_altitude, wind)
      : source.location;

    // draw if it is in the field of view
    PixelPoint pt;
    if (projection.GeoToScreenIfVisible(location, pt))
      icon.Draw(canvas, pt);
  }
}