Esempio n. 1
0
  // Compute and log the measured periods of the moons.
  void LogPeriods(Ephemeris<KSP> const& ephemeris) {
    auto const position = [this, &ephemeris](
        not_null<MassiveBody const*> body, Instant const& t) {
      return ephemeris.trajectory(body)->EvaluatePosition(t, nullptr);
    };
    auto const barycentre = [this, &position](Instant const& t) {
      BarycentreCalculator<Position<KSP>, Mass> result;
      for (auto const body : jool_system_) {
        result.Add(position(body, t), body->mass());
      }
      return result.Get();
    };
    auto const barycentric_position =
        [this, &barycentre, &ephemeris, &position](
        not_null<MassiveBody const*> body,
        Instant const& t) {
      return position(body, t) - barycentre(t);
    };

    for (auto const moon : {laythe_, vall_, tylo_}) {
      auto const moon_y =
          [this, &barycentric_position, moon](Instant const& t) {
        return barycentric_position(moon, t).coordinates().y;
      };

      LOG(INFO) << (moon == laythe_ ? "Laythe" : moon == vall_ ? "Vall"
                                                               : "Tylo");

      Sign const s0(moon_y(game_epoch_));
      Instant t0 = game_epoch_;
      Time const Δt = 45 * Minute;
      while (Sign(moon_y(t0)) == s0) {
        t0 += Δt;
      }
      // The moon crosses the xz plane between t0 and t0 - Δt.
      Instant t1 = t0;
      int const orbits = moon == laythe_ ? 8 : moon == vall_ ? 4 : 2;
      for (int i = 0; i < orbits; ++i) {
        while (Sign(moon_y(t1)) != s0) {
          t1 += Δt;
        }
        // The crossing of the xz plane halfway through the orbit occurs between
        // t1 and t1 - Δt.
        while (Sign(moon_y(t1)) == s0) {
          t1 += Δt;
        }
        // The |i|th orbit ends between t1 and t1 - Δt.
      }
      Time const actual_period =
          (Bisect(moon_y, t1 - Δt, t1) - Bisect(moon_y, t0 - Δt, t0)) / orbits;
      Time const expected_period = (2 * π * Radian) /
                                   *elements_[moon].mean_motion;
      LOG(INFO) << "actual period   : " << actual_period;
      LOG(INFO) << "expected period : " << expected_period;
      LOG(INFO) << "error           : "
                << RelativeError(expected_period, actual_period);
    }
  }
Esempio n. 2
0
  void LogEphemeris(Ephemeris<KSP> const& ephemeris,
                    bool const reference,
                    std::string const& name) {
    Instant const begin = reference ? game_epoch_ : long_time_;
    Instant const end = reference ? reference_ : comparison_;
    std::string const purpose = reference ? "reference" : "comparison";
    // Mathematica tends to be slow when dealing with quantities, so we give
    // everything in SI units.
    std::vector<double> times;
    // Indexed chronologically, then by body.
    std::vector<std::vector<Vector<double, KSP>>> barycentric_positions;
    for (Instant t = begin; t < end; t += 45 * Minute) {
      auto const position = [&ephemeris, t](not_null<MassiveBody const*> body) {
        return ephemeris.trajectory(body)->
            EvaluatePosition(t, /*hint=*/nullptr);
      };

      times.emplace_back((t - game_epoch_) / Second);

      BarycentreCalculator<Position<KSP>, GravitationalParameter>
          jool_system_barycentre;
      for (auto const body : jool_system_) {
        jool_system_barycentre.Add(position(body),
                                   body->gravitational_parameter());
      }
      barycentric_positions.emplace_back();
      for (auto const body : jool_system_) {
        // TODO(egg): when our dynamic frames support that, it would make sense
        // to use a nonrotating dynamic frame centred at the barycentre of the
        // Jool system, instead of computing the barycentre and difference
        // ourselves.
        barycentric_positions.back().emplace_back(
            (position(body) - jool_system_barycentre.Get()) / Metre);
      }
    }
    std::ofstream file;
    file.open(name + "_" + purpose + ".generated.wl");
    file << mathematica::Assign(name + purpose + "q", barycentric_positions);
    file << mathematica::Assign(name + purpose + "t", times);
    file.close();
  }