Beispiel #1
0
TEST_F(BodyTest, RotatingSerializationSuccess) {
  EXPECT_FALSE(rotating_body_.is_massless());
  EXPECT_FALSE(rotating_body_.is_oblate());

  serialization::Body message;
  RotatingBody<World> const* cast_rotating_body;
  rotating_body_.WriteToMessage(&message);
  EXPECT_TRUE(message.has_massive_body());
  EXPECT_FALSE(message.has_massless_body());
  EXPECT_TRUE(message.massive_body().HasExtension(
                  serialization::RotatingBody::rotating_body));
  EXPECT_EQ(17, message.massive_body().gravitational_parameter().magnitude());
  serialization::RotatingBody const rotating_body_extension =
      message.massive_body().GetExtension(
          serialization::RotatingBody::rotating_body);
  EXPECT_EQ(3, rotating_body_extension.reference_angle().magnitude());
  EXPECT_EQ(4,
            rotating_body_extension.reference_instant().scalar().magnitude());
  EXPECT_EQ(angular_velocity_,
            AngularVelocity<World>::ReadFromMessage(
                rotating_body_extension.angular_velocity()));

  // Dispatching from |MassiveBody|.
  not_null<std::unique_ptr<MassiveBody const>> const massive_body =
      MassiveBody::ReadFromMessage(message);
  EXPECT_EQ(rotating_body_.gravitational_parameter(),
            massive_body->gravitational_parameter());
  cast_rotating_body = dynamic_cast<RotatingBody<World> const*>(&*massive_body);
  EXPECT_THAT(cast_rotating_body, NotNull());
  EXPECT_EQ(rotating_body_.gravitational_parameter(),
            cast_rotating_body->gravitational_parameter());
  EXPECT_EQ(rotating_body_.angular_velocity(),
            cast_rotating_body->angular_velocity());
  EXPECT_EQ(rotating_body_.AngleAt(Instant()),
            cast_rotating_body->AngleAt(Instant()));

  // Dispatching from |Body|.
  not_null<std::unique_ptr<Body const>> const body =
      Body::ReadFromMessage(message);
  cast_rotating_body = dynamic_cast<RotatingBody<World> const*>(&*body);
  EXPECT_THAT(cast_rotating_body, NotNull());
  EXPECT_EQ(rotating_body_.gravitational_parameter(),
            cast_rotating_body->gravitational_parameter());
  EXPECT_EQ(rotating_body_.angular_velocity(),
            cast_rotating_body->angular_velocity());
  EXPECT_EQ(rotating_body_.AngleAt(Instant()),
            cast_rotating_body->AngleAt(Instant()));
}
Beispiel #2
0
  void TestRotatingBody() {
    using F = Frame<Tag, tag, true>;

    AngularVelocity<F> const angular_velocity =
        AngularVelocity<F>({-1 * Radian / Second,
                            2 * Radian / Second,
                            5 * Radian / Second});
    auto const rotating_body =
        RotatingBody<F>(17 * SIUnit<GravitationalParameter>(),
                        typename RotatingBody<F>::Parameters(
                            3 * Radian,
                            Instant() + 4 * Second,
                            angular_velocity));

    serialization::Body message;
    RotatingBody<F> const* cast_rotating_body;
    rotating_body.WriteToMessage(&message);
    EXPECT_TRUE(message.has_massive_body());
    EXPECT_FALSE(message.has_massless_body());
    EXPECT_TRUE(message.massive_body().HasExtension(
                    serialization::RotatingBody::rotating_body));

    not_null<std::unique_ptr<MassiveBody const>> const massive_body =
        MassiveBody::ReadFromMessage(message);
    EXPECT_EQ(rotating_body.gravitational_parameter(),
              massive_body->gravitational_parameter());
    cast_rotating_body = dynamic_cast<RotatingBody<F> const*>(&*massive_body);
    EXPECT_THAT(cast_rotating_body, NotNull());
  }
TEST_F(ManœuvreTest, TargetΔv) {
    Instant const t0 = Instant();
    Vector<double, World> e_y({0, 1, 0});
    Manœuvre<World> manœuvre(1 * Newton /*thrust*/,
                               2 * Kilogram /*initial_mass*/,
                               1 * Newton * Second / Kilogram /*specific_impulse*/,
                               e_y /*direction*/);
    EXPECT_EQ(1 * Newton, manœuvre.thrust());
    EXPECT_EQ(2 * Kilogram, manœuvre.initial_mass());
    EXPECT_EQ(1 * Metre / Second, manœuvre.specific_impulse());
    EXPECT_EQ(e_y, manœuvre.direction());
    EXPECT_EQ(1 * Kilogram / Second, manœuvre.mass_flow());

    manœuvre.set_Δv(1 * Metre / Second);
    EXPECT_EQ(1 * Metre / Second, manœuvre.Δv());
    EXPECT_EQ((2 - 2 / e) * Second, manœuvre.duration());
    EXPECT_EQ((2 - 2 / Sqrt(e)) * Second, manœuvre.time_to_half_Δv());
    EXPECT_EQ((2 / e) * Kilogram, manœuvre.final_mass());

    manœuvre.set_time_of_half_Δv(t0);
    EXPECT_EQ(t0 - (2 - 2 / Sqrt(e)) * Second, manœuvre.initial_time());
    EXPECT_EQ(t0 + (2 / Sqrt(e) - 2 / e) * Second, manœuvre.final_time());
    EXPECT_EQ(t0, manœuvre.time_of_half_Δv());
    EXPECT_EQ(
        0 * Metre / Pow<2>(Second),
        manœuvre.acceleration()(manœuvre.initial_time() - 1 * Second).Norm());
    EXPECT_EQ(0.5 * Metre / Pow<2>(Second),
              manœuvre.acceleration()(manœuvre.initial_time()).Norm());
    EXPECT_EQ(Sqrt(e) / 2 * Metre / Pow<2>(Second),
              manœuvre.acceleration()(manœuvre.time_of_half_Δv()).Norm());
    EXPECT_EQ((e / 2) * Metre / Pow<2>(Second),
              manœuvre.acceleration()(manœuvre.final_time()).Norm());
    EXPECT_EQ(0 * Metre / Pow<2>(Second),
              manœuvre.acceleration()(manœuvre.final_time() + 1 * Second).Norm());
}
std::unique_ptr<MassiveBody> SolarSystem<Frame>::MakeMassiveBody(
    serialization::GravityModel::Body const& body) {
  CHECK(body.has_gravitational_parameter());
  CHECK_EQ(body.has_j2(), body.has_reference_radius());
  CHECK_EQ(body.has_axis_declination(), body.has_axis_right_ascension());
  MassiveBody::Parameters massive_body_parameters(
                              ParseQuantity<GravitationalParameter>(
                                  body.gravitational_parameter()));
  if (body.has_axis_declination()) {
    // TODO(phl): Parse the additional parameters.
    typename RotatingBody<Frame>::Parameters
        rotating_body_parameters(
            0 * Radian,
            Instant(),
            Bivector<double, Frame>(
                RadiusLatitudeLongitude(
                    1.0,
                    ParseQuantity<Angle>(body.axis_declination()),
                    ParseQuantity<Angle>(body.axis_right_ascension())).
                ToCartesian()) * Radian / Second);
    if (body.has_j2()) {
      typename OblateBody<Frame>::Parameters oblate_body_parameters(
          ParseQuantity<double>(body.j2()),
          ParseQuantity<Length>(body.reference_radius()));
      return std::make_unique<OblateBody<Frame>>(massive_body_parameters,
                                                 rotating_body_parameters,
                                                 oblate_body_parameters);
    } else {
      return std::make_unique<RotatingBody<Frame>>(massive_body_parameters,
                                                   rotating_body_parameters);
    }
  } else {
    return std::make_unique<MassiveBody>(massive_body_parameters);
  }
}
Beispiel #5
0
double principia__IteratorGetTime(Iterator const* const iterator) {
  journal::Method<journal::IteratorGetTime> m({iterator});
  CHECK_NOTNULL(iterator);
  auto const typed_iterator = check_not_null(
      dynamic_cast<TypedIterator<DiscreteTrajectory<World>> const*>(iterator));
  return m.Return(typed_iterator->Get<double>(
      [](DiscreteTrajectory<World>::Iterator const& iterator) -> double {
        return (iterator.time() - Instant()) / Second;
      }));
}
Beispiel #6
0
Plugin* NewPlugin(double const initial_time,
                  int const sun_index,
                  double const sun_gravitational_parameter,
                  double const planetarium_rotation_in_degrees) {
  LOG(INFO) << "Constructing Principia plugin";
  std::unique_ptr<Plugin> result = std::make_unique<Plugin>(
      Instant(initial_time * Second),
      sun_index,
      sun_gravitational_parameter * SIUnit<GravitationalParameter>(),
      planetarium_rotation_in_degrees * Degree);
  LOG(INFO) << "Plugin constructed";
  return result.release();
}
Beispiel #7
0
void Ephemeris<Frame>::AppendMassiveBodiesState(
    typename NewtonianMotionEquation::SystemState const& state) {
  last_state_ = state;
  int index = 0;
  for (auto& trajectory : trajectories_) {
    trajectory->Append(
        state.time.value,
        DegreesOfFreedom<Frame>(state.positions[index].value,
                                state.velocities[index].value));
    ++index;
  }

  // Record an intermediate state if we haven't done so for too long.
  CHECK(!trajectories_.empty());
  Instant const t_last_intermediate_state =
      checkpoints_.empty()
          ? Instant() - std::numeric_limits<double>::infinity() * Second
          : checkpoints_.back().system_state.time.value;
  if (t_max() - t_last_intermediate_state > max_time_between_checkpoints) {
    checkpoints_.push_back(GetCheckpoint());
  }
}
Beispiel #8
0
void AdvanceTime(Plugin* const plugin,
                 double const t,
                 double const planetarium_rotation) {
  CHECK_NOTNULL(plugin)->AdvanceTime(Instant(t * Second),
                                     planetarium_rotation * Degree);
}
Beispiel #9
0
MockPlugin::MockPlugin()
    : Plugin(Instant(),
             Angle()) {}
TEST_F(SolarSystemTest, RealSolarSystem) {
  solar_system_.Initialize(
      SOLUTION_DIR / "astronomy" / "gravity_model.proto.txt",
      SOLUTION_DIR / "astronomy" /
          "initial_state_jd_2433282_500000000.proto.txt");

  EXPECT_EQ(Instant() - 50 * 365.25 * Day, solar_system_.epoch());
  EXPECT_THAT(solar_system_.names(),
              ElementsAreArray({"Ariel",
                                "Callisto",
                                "Ceres",
                                "Charon",
                                "Deimos",
                                "Dione",
                                "Earth",
                                "Enceladus",
                                "Eris",
                                "Europa",
                                "Ganymede",
                                "Iapetus",
                                "Io",
                                "Jupiter",
                                "Mars",
                                "Mercury",
                                "Mimas",
                                "Miranda",
                                "Moon",
                                "Neptune",
                                "Oberon",
                                "Phobos",
                                "Pluto",
                                "Rhea",
                                "Saturn",
                                "Sun",
                                "Tethys",
                                "Titan",
                                "Titania",
                                "Triton",
                                "Umbriel",
                                "Uranus",
                                "Venus",
                                "Vesta"}));
  EXPECT_EQ(1, solar_system_.index("Callisto"));
  EXPECT_EQ(32, solar_system_.index("Venus"));

  auto const ephemeris = solar_system_.MakeEphemeris(
      /*fitting_tolerance=*/1 * Metre,
      Ephemeris<ICRFJ2000Equator>::FixedStepParameters(
          integrators::McLachlanAtela1992Order4Optimal<
              Position<ICRFJ2000Equator>>(),
          /*step=*/1 * Second));
  auto const earth = solar_system_.massive_body(*ephemeris, "Earth");
  EXPECT_LT(RelativeError(5.97258 * Yotta(Kilogram), earth->mass()), 6E-9);
  auto const& earth_trajectory = solar_system_.trajectory(*ephemeris, "Earth");
  EXPECT_TRUE(earth_trajectory.empty());

  auto const& sun_initial_state = solar_system_.initial_state_message("Sun");
  EXPECT_EQ("+1.309126697236264E+05 km", sun_initial_state.x());
  EXPECT_EQ("-7.799754996220354E-03 km/s", sun_initial_state.vx());
  auto const& sun_gravity_model = solar_system_.gravity_model_message("Sun");
  EXPECT_EQ("286.13 deg", sun_gravity_model.axis_right_ascension());
  EXPECT_EQ("63.87 deg", sun_gravity_model.axis_declination());
}