示例#1
0
static void
Run(DebugReplay &replay, Result &result,
    Trace &full_trace, Trace &triangle_trace, Trace &sprint_trace)
{
  CirclingSettings circling_settings;
  circling_settings.SetDefaults();

  bool released = false;

  GeoPoint last_location = GeoPoint::Invalid();
  constexpr Angle max_longitude_change = Angle::Degrees(30);
  constexpr Angle max_latitude_change = Angle::Degrees(1);

  while (replay.Next()) {
    ComputeCircling(replay, circling_settings);

    const MoreData &basic = replay.Basic();

    Update(basic, replay.Calculated(), result);
    flight_phase_detector.Update(replay.Basic(), replay.Calculated());

    if (!basic.time_available || !basic.location_available ||
        !basic.NavAltitudeAvailable())
      continue;

    if (last_location.IsValid() &&
        ((last_location.latitude - basic.location.latitude).Absolute() > max_latitude_change ||
         (last_location.longitude - basic.location.longitude).Absolute() > max_longitude_change))
      /* there was an implausible warp, which is usually triggered by
         an invalid point declared "valid" by a bugged logger; if that
         happens, we stop the analysis, because the IGC file is
         obviously broken */
      break;

    last_location = basic.location;

    if (!released && !negative(replay.Calculated().flight.release_time)) {
      released = true;

      full_trace.EraseEarlierThan(replay.Calculated().flight.release_time);
      triangle_trace.EraseEarlierThan(replay.Calculated().flight.release_time);
      sprint_trace.EraseEarlierThan(replay.Calculated().flight.release_time);
    }

    if (released && !replay.Calculated().flight.flying)
      /* the aircraft has landed, stop here */
      /* TODO: at some point, we might want to emit the analysis of
         all flights in this IGC file */
      break;

    const TracePoint point(basic);
    full_trace.push_back(point);
    triangle_trace.push_back(point);
    sprint_trace.push_back(point);
  }

  Update(replay.Basic(), replay.Calculated(), result);
  Finish(replay.Basic(), replay.Calculated(), result);
  flight_phase_detector.Finish();
}
示例#2
0
int main(int argc, char **argv)
{
  Args args(argc, argv, "DRIVER FILE");
  DebugReplay *replay = CreateDebugReplay(args);
  if (replay == NULL)
    return EXIT_FAILURE;

  args.ExpectEnd();

  Result result;
  Run(*replay, result);
  delete replay;

  const ContestStatistics olc_plus = SolveContest(Contest::OLC_PLUS);
  const ContestStatistics dmst = SolveContest(Contest::DMST);

  TextWriter writer("/dev/stdout", true);

  {
    JSON::ObjectWriter root(writer);

    WriteResult(root, result);
    root.WriteElement("phases", WritePhaseList,
                      flight_phase_detector.GetPhases());
    root.WriteElement("performance", WritePerformanceStats,
                      flight_phase_detector.GetTotals());
    root.WriteElement("contests", WriteContests, olc_plus, dmst);
  }
}
示例#3
0
void
Run(DebugReplay &replay, FlightPhaseDetector &flight_phase_detector,
    WindList &wind_list,
    const BrokenDateTime &takeoff_time,
    const BrokenDateTime &scoring_start_time,
    const BrokenDateTime &scoring_end_time,
    const BrokenDateTime &landing_time,
    Trace &full_trace, Trace &triangle_trace, Trace &sprint_trace,
    ComputerSettings &computer_settings)
{
    GeoPoint last_location = GeoPoint::Invalid();
    constexpr Angle max_longitude_change = Angle::Degrees(30);
    constexpr Angle max_latitude_change = Angle::Degrees(1);

    CirclingSettings circling_settings;
    circling_settings.SetDefaults();
    CirclingComputer circling_computer;
    circling_computer.Reset();

    GlidePolar glide_polar(0);

    WindSettings wind_settings;
    wind_settings.SetDefaults();

    WindComputer wind_computer;
    wind_computer.Reset();

    Validity last_wind;
    last_wind.Clear();

    const Waypoints waypoints;
    AutoQNH auto_qnh(5);
    auto_qnh.Reset();

    const int64_t takeoff_unix = takeoff_time.ToUnixTimeUTC();
    const int64_t landing_unix = landing_time.ToUnixTimeUTC();


    int64_t scoring_start_unix, scoring_end_unix;

    if (scoring_start_time.IsPlausible())
        scoring_start_unix = scoring_start_time.ToUnixTimeUTC();
    else
        scoring_start_unix = std::numeric_limits<int64_t>::max();

    if (scoring_end_time.IsPlausible())
        scoring_end_unix = scoring_end_time.ToUnixTimeUTC();
    else
        scoring_end_unix = 0;


    while (replay.Next()) {
        const MoreData &basic = replay.Basic();
        const int64_t date_time_utc = basic.date_time_utc.ToUnixTimeUTC();

        if (date_time_utc < takeoff_unix)
            continue;

        if (date_time_utc > landing_unix)
            break;

        circling_computer.TurnRate(replay.SetCalculated(),
                                   replay.Basic(),
                                   replay.Calculated().flight);
        circling_computer.Turning(replay.SetCalculated(),
                                  replay.Basic(),
                                  replay.Calculated().flight,
                                  circling_settings);

        flight_phase_detector.Update(replay.Basic(), replay.Calculated());

        wind_computer.Compute(wind_settings, glide_polar, basic,
                              replay.SetCalculated());

        if (replay.Calculated().estimated_wind_available.Modified(last_wind)) {
            wind_list.push_back(WindListItem(basic.date_time_utc, basic.gps_altitude,
                                             replay.Calculated().estimated_wind));
        }

        last_wind = replay.Calculated().estimated_wind_available;

        auto_qnh.Process(basic, replay.SetCalculated(), computer_settings, waypoints);

        if (!computer_settings.pressure_available && replay.Calculated().pressure_available) {
            computer_settings.pressure = replay.Calculated().pressure;
            computer_settings.pressure_available = replay.Calculated().pressure_available;
        }

        if (!basic.time_available || !basic.location_available ||
                !basic.NavAltitudeAvailable())
            continue;

        if (last_location.IsValid() &&
                ((last_location.latitude - basic.location.latitude).Absolute() > max_latitude_change ||
                 (last_location.longitude - basic.location.longitude).Absolute() > max_longitude_change))
            /* there was an implausible warp, which is usually triggered by
               an invalid point declared "valid" by a bugged logger; if that
               happens, we stop the analysis, because the IGC file is
               obviously broken */
            break;

        last_location = basic.location;

        if (date_time_utc >= scoring_start_unix && date_time_utc <= scoring_end_unix) {
            const TracePoint point(basic);
            full_trace.push_back(point);
            triangle_trace.push_back(point);
            sprint_trace.push_back(point);
        }
    }

    flight_phase_detector.Finish();
}
示例#4
0
int main(int argc, char **argv)
{
  unsigned full_max_points = 512,
           triangle_max_points = 1024,
           sprint_max_points = 64;

  Args args(argc, argv,
            "[options] DRIVER FILE\n"
            "Options:\n"
            "  --full-points=512        Maximum number of full trace points (default = 512)\n"
            "  --triangle-points=1024   Maximum number of triangle trace points (default = 1024)\n"
            "  --sprint-points=64       Maximum number of sprint trace points (default = 64)");

  const char *arg;
  while ((arg = args.PeekNext()) != nullptr && *arg == '-') {
    args.Skip();

    const char *value;
    if ((value = StringAfterPrefix(arg, "--full-points=")) != nullptr) {
      unsigned _points = strtol(value, NULL, 10);
      if (_points > 0)
        full_max_points = _points;
      else {
        fputs("The start parameter could not be parsed correctly.\n", stderr);
        args.UsageError();
      }

    } else if ((value = StringAfterPrefix(arg, "--triangle-points=")) != nullptr) {
      unsigned _points = strtol(value, NULL, 10);
      if (_points > 0)
        triangle_max_points = _points;
      else {
        fputs("The start parameter could not be parsed correctly.\n", stderr);
        args.UsageError();
      }

    } else if ((value = StringAfterPrefix(arg, "--sprint-points=")) != nullptr) {
      unsigned _points = strtol(value, NULL, 10);
      if (_points > 0)
        sprint_max_points = _points;
      else {
        fputs("The start parameter could not be parsed correctly.\n", stderr);
        args.UsageError();
      }

    } else {
      args.UsageError();
    }
  }

  DebugReplay *replay = CreateDebugReplay(args);
  if (replay == NULL)
    return EXIT_FAILURE;

  args.ExpectEnd();

  static Trace full_trace(0, Trace::null_time, full_max_points);
  static Trace triangle_trace(0, Trace::null_time, triangle_max_points);
  static Trace sprint_trace(0, 9000, sprint_max_points);

  Result result;
  Run(*replay, result, full_trace, triangle_trace, sprint_trace);
  delete replay;

  const ContestStatistics olc_plus = SolveContest(Contest::OLC_PLUS, full_trace, triangle_trace, sprint_trace);
  const ContestStatistics dmst = SolveContest(Contest::DMST, full_trace, triangle_trace, sprint_trace);

  TextWriter writer("/dev/stdout", true);

  {
    JSON::ObjectWriter root(writer);

    WriteResult(root, result);
    root.WriteElement("phases", WritePhaseList,
                      flight_phase_detector.GetPhases());
    root.WriteElement("performance", WritePerformanceStats,
                      flight_phase_detector.GetTotals());
    root.WriteElement("contests", WriteContests, olc_plus, dmst);
  }
}