Example #1
0
void Plugin::UpdateCelestialHierarchy(Index const celestial_index,
                                      Index const parent_index) const {
  VLOG(1) << __FUNCTION__ << '\n'
          << NAMED(celestial_index) << '\n' << NAMED(parent_index);
  CHECK(!initializing_);
  FindOrDie(celestials_, celestial_index)->set_parent(
      FindOrDie(celestials_, parent_index).get());
}
Example #2
0
void Plugin::EndInitialization() {
  CHECK(initializing_);
  if (hierarchical_initialization_) {
    std::uint64_t system_fingerprint = 0;
    for (std::uint64_t fingerprint : celestial_jacobi_keplerian_fingerprints_) {
      system_fingerprint = FingerprintCat2011(system_fingerprint, fingerprint);
    }
    LOG(INFO) << "System fingerprint is " << std::hex << system_fingerprint;
    if (system_fingerprint == ksp_stock_system_fingerprint) {
      is_ksp_stock_system_ = true;
      LOG(WARNING) << "This appears to be the dreaded KSP stock system!";
    } else if (system_fingerprint == ksp_fixed_system_fingerprint) {
      LOG(INFO) << "This is the fixed KSP system, all hail retrobop!";
    }

    HierarchicalSystem<Barycentric>::BarycentricSystem system =
        hierarchical_initialization_->system.ConsumeBarycentricSystem();
    std::map<not_null<MassiveBody const*>, Index> bodies_to_indices;
    for (auto const& index_body :
         hierarchical_initialization_->indices_to_bodies) {
      bodies_to_indices[index_body.second] = index_body.first;
    }
    auto const parents = std::move(hierarchical_initialization_->parents);
    hierarchical_initialization_ = std::experimental::nullopt;
    for (int i = 0; i < system.bodies.size(); ++i) {
      Index const celestial_index = bodies_to_indices[system.bodies[i].get()];
      InsertCelestialAbsoluteCartesian(
          celestial_index,
          FindOrDie(parents, celestial_index),
          system.degrees_of_freedom[i],
          std::move(system.bodies[i]));
    }
  }
  CHECK(absolute_initialization_);
  CHECK_NOTNULL(sun_);
  main_body_ = CHECK_NOTNULL(
      dynamic_cast<RotatingBody<Barycentric> const*>(&*sun_->body()));
  initializing_.Flop();

  InitializeEphemerisAndSetCelestialTrajectories();

  // Log the serialized ephemeris.
  serialization::Ephemeris ephemeris_message;
  ephemeris_->WriteToMessage(&ephemeris_message);
  std::string const bytes = ephemeris_message.SerializeAsString();
  base::UniqueArray<std::uint8_t> const hex((bytes.size() << 1) + 1);
  base::HexadecimalEncode(
      base::Array<std::uint8_t const>(
          reinterpret_cast<std::uint8_t const*>(bytes.data()), bytes.size()),
      hex.get());
  hex.data[hex.size - 1] = 0;
  // Begin and end markers to make sure the hex did not get clipped (this might
  // happen if the message is very big).
  LOG(INFO) << "Ephemeris at initialization:\nbegin\n"
            << reinterpret_cast<char const*>(hex.data.get()) << "\nend";
}
Example #3
0
Rotation<BodyWorld, World> Plugin::CelestialRotation(
    Index const index) const {
  // |BodyWorld| with its y and z axes swapped (so that z is the polar axis).
  // The basis is right-handed.
  struct BodyFixed;
  Permutation<BodyWorld, BodyFixed> const body_mirror(
      Permutation<BodyWorld, BodyFixed>::XZY);

  auto const& body = dynamic_cast<RotatingBody<Barycentric> const&>(
      *FindOrDie(celestials_, index)->body());

  Bivector<double, BodyFixed> z({0, 0, 1});
  Bivector<double, BodyFixed> x({1, 0, 0});

  Rotation<BodyFixed, Barycentric> body_orientation(
      π / 2 * Radian + body.right_ascension_of_pole(),
      π / 2 * Radian - body.declination_of_pole(),
      body.AngleAt(current_time_),
      EulerAngles::ZXZ,
      DefinesFrame<BodyFixed>{});
Example #4
0
void Plugin::SetMainBody(Index const index) {
  main_body_ = dynamic_cast<RotatingBody<Barycentric> const*>(
      &*FindOrDie(celestials_, index)->body());
  LOG_IF(FATAL, main_body_ == nullptr) << index;
}
void GenerateKopernicusForSlippist1(
    std::string const& gravity_model_stem,
    std::string const& initial_state_stem) {
  std::filesystem::path const directory =
      SOLUTION_DIR / "astronomy";
  SolarSystem<Sky> solar_system(
      (directory / gravity_model_stem).replace_extension(proto_txt),
      (directory / initial_state_stem).replace_extension(proto_txt),
      /*ignore_frame=*/true);

  std::ofstream kopernicus_cfg(
      (directory / (gravity_model_stem + "_slippist1")).replace_extension(cfg));
  CHECK(kopernicus_cfg.good());

  // Find the star.  This is needed to construct Kepler orbits below.
  std::optional<serialization::GravityModel::Body> star;
  for (std::string const& name : solar_system.names()) {
    serialization::GravityModel::Body const& body =
        solar_system.gravity_model_message(name);
    bool const is_star =
        !solar_system.keplerian_initial_state_message(name).has_parent();
    if (is_star) {
      star = body;
    }
  }

  kopernicus_cfg << "@Kopernicus:AFTER[aSLIPPIST-1] {\n";
  for (std::string const& name : solar_system.names()) {
    serialization::GravityModel::Body const& body =
        solar_system.gravity_model_message(name);
    serialization::InitialState::Keplerian::Body::Elements const& elements =
        solar_system.keplerian_initial_state_message(name).elements();
    bool const is_star =
        !solar_system.keplerian_initial_state_message(name).has_parent();
    bool const is_kerbin =
        FindOrDie(body_name_map, name) == kerbin;
    kopernicus_cfg << "  @Body[" << FindOrDie(body_name_map, name) << "] {\n";
    if (is_kerbin) {
      kopernicus_cfg << "    %cbNameLater = " << name << "\n";
    } else if (!is_star) {
      kopernicus_cfg << "    @name = " << name << "\n";
    }
    kopernicus_cfg << "    @Properties {\n";
    if (is_star) {
      kopernicus_cfg << "      !mass = delete\n";
    } else {
      kopernicus_cfg << "      !geeASL = delete\n";
    }
    kopernicus_cfg << "      @displayName = " << name << "\n";
    kopernicus_cfg << "      %gravParameter = "
                   << DebugString(ParseQuantity<GravitationalParameter>(
                                      body.gravitational_parameter()) /
                                  SIUnit<GravitationalParameter>())
                   << "\n";
    kopernicus_cfg << "      %radius = "
                   << DebugString(ParseQuantity<Length>(body.mean_radius()) /
                                  Metre)
                   << "\n";
    kopernicus_cfg << "      %description = "
                   << FindOrDie(body_description_map, name) << "\n";
    if (!is_star) {
      kopernicus_cfg << "      %tidallyLocked = false\n";
    }
    kopernicus_cfg << "    }\n";
    if (is_star) {
      kopernicus_cfg << "    @ScaledVersion {\n";
      kopernicus_cfg << "      @Light {\n";
      for (char const* const curve :
           {"ScaledIntensityCurve", "IntensityCurve", "IVAIntensityCurve"}) {
        kopernicus_cfg << "        @" << curve << " {\n";
        kopernicus_cfg << "          @key,*[0, ] *= 10\n";
        kopernicus_cfg << "        }\n";
      }
      kopernicus_cfg << "      }\n";
      kopernicus_cfg << "    }\n";
    } else {
      CHECK(star.has_value());
      auto const keplerian_elements =
          solar_system.MakeKeplerianElements(elements);
      KeplerOrbit<Sky> const kepler_orbit(*solar_system.MakeMassiveBody(*star),
                                          *solar_system.MakeMassiveBody(body),
                                          keplerian_elements,
                                          solar_system.epoch());
      kopernicus_cfg << "    @Orbit {\n";
      kopernicus_cfg << "      %semiMajorAxis = "
                     << DebugString(
                            *kepler_orbit.elements_at_epoch().semimajor_axis /
                            Metre)
                     << "\n";
      kopernicus_cfg << "      %eccentricity = "
                     << DebugString(elements.eccentricity()) << "\n";
      kopernicus_cfg << "      %longitudeOfAscendingNode = "
                     << DebugString(
                            ParseQuantity<Angle>(
                                elements.longitude_of_ascending_node()) /
                            Degree)
                     << "\n";
      kopernicus_cfg << "      %argumentOfPeriapsis = "
                     << DebugString(ParseQuantity<Angle>(
                                        elements.argument_of_periapsis()) /
                                    Degree)
                     << "\n";
      kopernicus_cfg << "      %meanAnomalyAtEpoch = "
                     << DebugString(ParseQuantity<Angle>(
                                        elements.mean_anomaly()) / Radian)
                     << "\n";
      kopernicus_cfg << "    }\n";
      kopernicus_cfg << "    @Atmosphere {\n";
      kopernicus_cfg << "      @altitude *= 2\n";
      for (char const* const curve :
           {"temperatureCurve", "temperatureSunMultCurve", "pressureCurve"}) {
        kopernicus_cfg << "      @" << curve << " {\n";
        kopernicus_cfg << "        @key,*[0, ] *= 2\n";
        kopernicus_cfg << "      }\n";
      }
      kopernicus_cfg << "    }\n";
    }
    kopernicus_cfg << "  }\n";
  }
  kopernicus_cfg << "}\n";

  kopernicus_cfg << "@principia_gravity_model:FOR[Principia] {\n";
  for (std::string const& name : solar_system.names()) {
    serialization::GravityModel::Body const& body =
        solar_system.gravity_model_message(name);
    serialization::InitialState::Keplerian::Body::Elements const& elements =
        solar_system.keplerian_initial_state_message(name).elements();
    bool const is_star =
        !solar_system.keplerian_initial_state_message(name).has_parent();
    kopernicus_cfg << "  @body[" << name << "] {\n";
    if (!is_star) {
      kopernicus_cfg << "      @reference_angle = "
                     << Mod(FindOrDie(body_angle, name) +
                                ParseQuantity<Angle>(
                                    elements.argument_of_periapsis()) +
                                ParseQuantity<Angle>(elements.mean_anomaly()),
                            2 * π * Radian)
                     << "\n";
    }
    kopernicus_cfg << "  }\n";
  }
  kopernicus_cfg << "}\n";
  for (std::string const& name : solar_system.names()) {
    bool const is_star =
        !solar_system.keplerian_initial_state_message(name).has_parent();
    if (!is_star) {
      kopernicus_cfg << "@Scatterer_atmosphere:HAS[@Atmo["
                     << body_name_map.at(name) << "]]:AFTER[aSLIPPIST-1] {\n";
      kopernicus_cfg << "  @Atmo[" << body_name_map.at(name) << "] {\n";
      kopernicus_cfg << "    @name = " << name << "\n";
      kopernicus_cfg << "    @configPoints {\n";
      kopernicus_cfg << "      @Item,* {\n";
      kopernicus_cfg << "        @altitude *= 2\n";
      kopernicus_cfg << "      }\n";
      kopernicus_cfg << "    }\n";
      kopernicus_cfg << "  }\n";
      kopernicus_cfg << "}\n";
      kopernicus_cfg << "@Scatterer_ocean:HAS[@Ocean[" << body_name_map.at(name)
                     << "]]:AFTER[aSLIPPIST-1] {\n";
      kopernicus_cfg << "  @Ocean[" << body_name_map.at(name) << "] {\n";
      kopernicus_cfg << "    @name = " << name << "\n";
      kopernicus_cfg << "  }\n";
      kopernicus_cfg << "}\n";
    }
  }
  kopernicus_cfg << "@Scatterer_planetsList:AFTER[aSLIPPIST-1] {\n";
  kopernicus_cfg << "  @scattererCelestialBodies {\n";
  for (std::string const& name : solar_system.names()) {
    bool const is_star =
        !solar_system.keplerian_initial_state_message(name).has_parent();
    bool const is_kerbin = body_name_map.at(name) == kerbin;
    std::string const slippist_name =
        is_kerbin ? "Echo" : body_name_map.at(name);
    if (!is_star) {
      kopernicus_cfg << "    @Item[" << slippist_name << "] {\n";
      kopernicus_cfg << "      @celestialBodyName = " << name << "\n";
      kopernicus_cfg << "      @transformName = " << name << "\n";
      kopernicus_cfg << "    }\n";
    }
  }
  kopernicus_cfg << "  }\n";
  kopernicus_cfg << "}\n";
  kopernicus_cfg << "@EVE_CLOUDS:AFTER[aSLIPPIST-1] {\n";
  for (std::string const& name : solar_system.names()) {
    bool const is_star =
        !solar_system.keplerian_initial_state_message(name).has_parent();
    if (!is_star) {
      kopernicus_cfg << "  @OBJECT:HAS[#body[" << body_name_map.at(name)
                     << "]] {\n";
      kopernicus_cfg << "    @body = " << name << "\n";
      kopernicus_cfg << "    @altitude *= 2\n";
      kopernicus_cfg << "  }\n";
    }
  }
  kopernicus_cfg << "}\n";
  kopernicus_cfg << "@EVE_SHADOWS:AFTER[aSLIPPIST-1] {\n";
  for (std::string const& name : solar_system.names()) {
    bool const is_star =
        !solar_system.keplerian_initial_state_message(name).has_parent();
    if (!is_star) {
      kopernicus_cfg << "  @OBJECT:HAS[#body[" << body_name_map.at(name)
                     << "]] {\n";
      kopernicus_cfg << "    @body = " << name << "\n";
      kopernicus_cfg << "    !caster,* = delete\n";
      auto const elements = SolarSystem<Sky>::MakeKeplerianElements(
          solar_system.keplerian_initial_state_message(name).elements());
      for (std::string const& caster_name : solar_system.names()) {
        bool const caster_is_star =
            !solar_system.keplerian_initial_state_message(caster_name)
                 .has_parent();
        if (!caster_is_star) {
          auto const caster_elements = SolarSystem<Sky>::MakeKeplerianElements(
              solar_system.keplerian_initial_state_message(caster_name)
                  .elements());
          if (caster_elements.period < elements.period) {
            kopernicus_cfg << "    caster = " << caster_name << "\n";
          }
        }
      }
      kopernicus_cfg << "  }\n";
    }
  }
  kopernicus_cfg << "}\n";
}
Example #6
0
int Ephemeris<Frame>::serialization_index_for_body(
    not_null<MassiveBody const*> const body) const {
  return FindOrDie(unowned_bodies_indices_, body);
}
Example #7
0
not_null<ContinuousTrajectory<Frame> const*> Ephemeris<Frame>::trajectory(
    not_null<MassiveBody const*> body) const {
  return FindOrDie(bodies_to_trajectories_, body).get();
}
serialization::GravityModel::Body const&
SolarSystem<Frame>::gravity_model_message(std::string const& name) const {
  return *FindOrDie(gravity_model_map_, name);
}
serialization::InitialState::Body const&
SolarSystem<Frame>::initial_state_message(std::string const& name) const {
  return *FindOrDie(initial_state_map_, name);
}