Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3a6d4df53cbe
Choose a base ref
...
head repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 37005d9700d7
Choose a head ref
  • 12 commits
  • 5 files changed
  • 1 contributor

Commits on Oct 30, 2021

  1. Start changing Vessel.

    pleroy committed Oct 30, 2021
    Copy the full SHA
    b976384 View commit details
  2. Prognostication.

    pleroy committed Oct 30, 2021
    Copy the full SHA
    4591cdc View commit details

Commits on Oct 31, 2021

  1. Copy the full SHA
    f71d37d View commit details

Commits on Nov 2, 2021

  1. Copy the full SHA
    c10a0ce View commit details
  2. Vessel compiles.

    pleroy committed Nov 2, 2021
    Copy the full SHA
    0cc8e3b View commit details
  3. The test compiles.

    pleroy committed Nov 2, 2021
    Copy the full SHA
    6fabec4 View commit details
  4. Fix a bug.

    pleroy committed Nov 2, 2021
    Copy the full SHA
    f71eeb1 View commit details
  5. Tests passing.

    pleroy committed Nov 2, 2021
    Copy the full SHA
    c293386 View commit details
  6. Copy the full SHA
    b22c9b2 View commit details

Commits on Nov 3, 2021

  1. Comments.

    pleroy committed Nov 3, 2021
    Copy the full SHA
    0a12427 View commit details
  2. More comments.

    pleroy committed Nov 3, 2021
    Copy the full SHA
    ab39a5a View commit details
  3. Merge pull request #3189 from pleroy/Vessel

    Convert Vessel and its test to DiscreteTraject0ry
    pleroy authored Nov 3, 2021
    Copy the full SHA
    37005d9 View commit details
Showing with 206 additions and 151 deletions.
  1. +87 −70 ksp_plugin/vessel.cpp
  2. +29 −21 ksp_plugin/vessel.hpp
  3. +72 −60 ksp_plugin_test/vessel_test.cpp
  4. +7 −0 testing_utilities/discrete_trajectory_factories.hpp
  5. +11 −0 testing_utilities/discrete_trajectory_factories_body.hpp
157 changes: 87 additions & 70 deletions ksp_plugin/vessel.cpp
Original file line number Diff line number Diff line change
@@ -68,7 +68,9 @@ Vessel::Vessel(GUID guid,
return FlowPrognostication(parameters);
},
20ms), // 50 Hz.
history_(make_not_null_unique<DiscreteTrajectory<Barycentric>>()) {
history_(trajectory_.segments().begin()),
psychohistory_(trajectory_.segments().end()),
prediction_(trajectory_.segments().end()) {
// Can't create the |psychohistory_| and |prediction_| here because |history_|
// is empty;
}
@@ -159,10 +161,10 @@ void Vessel::ClearAllIntrinsicForcesAndTorques() {

void Vessel::PrepareHistory(
Instant const& t,
DiscreteTrajectory<Barycentric>::DownsamplingParameters const&
DiscreteTrajectorySegment<Barycentric>::DownsamplingParameters const&
downsampling_parameters) {
CHECK(!parts_.empty());
if (history_->Empty()) {
if (trajectory_.empty()) {
LOG(INFO) << "Preparing history of vessel " << ShortDebugString()
<< " at " << t;
BarycentreCalculator<DegreesOfFreedom<Barycentric>, Mass> calculator;
@@ -171,11 +173,11 @@ void Vessel::PrepareHistory(
part.rigid_motion()({RigidPart::origin, RigidPart::unmoving}),
part.mass());
});
CHECK(psychohistory_ == nullptr);
CHECK(psychohistory_ == trajectory_.segments().end());
history_->SetDownsampling(downsampling_parameters);
history_->Append(t, calculator.Get());
psychohistory_ = history_->NewForkAtLast();
prediction_ = psychohistory_->NewForkAtLast();
trajectory_.Append(t, calculator.Get());
psychohistory_ = trajectory_.NewSegment();
prediction_ = trajectory_.NewSegment();
}
}

@@ -198,12 +200,16 @@ void Vessel::ForAllParts(std::function<void(Part&)> action) const {
}
}

DiscreteTrajectory<Barycentric> const& Vessel::psychohistory() const {
return *psychohistory_;
DiscreteTrajectorySegmentIterator<Barycentric> Vessel::history() const {
return history_;
}

DiscreteTrajectory<Barycentric> const& Vessel::prediction() const {
return *prediction_;
DiscreteTrajectorySegmentIterator<Barycentric> Vessel::psychohistory() const {
return psychohistory_;
}

DiscreteTrajectorySegmentIterator<Barycentric> Vessel::prediction() const {
return prediction_;
}

void Vessel::set_prediction_adaptive_step_parameters(
@@ -229,18 +235,18 @@ bool Vessel::has_flight_plan() const {
void Vessel::AdvanceTime() {
// Squirrel away the prediction so that we can reattach it if we don't have a
// prognostication.
auto prediction = prediction_->DetachFork();
prediction_ = nullptr;
auto prediction = trajectory_.DetachSegments(prediction_);
prediction_ = trajectory_.segments().end();

// Read the wall of text below and realize that this can happen for the
// history as well as the psychohistory, if the history of the part was
// obtained using an adaptive step integrator, which is the case during a
// burn. See #2931.
history_->DeleteFork(psychohistory_);
trajectory_.DeleteSegments(psychohistory_);
AppendToVesselTrajectory(&Part::history_begin,
&Part::history_end,
*history_);
psychohistory_ = history_->NewForkAtLast();
psychohistory_ = trajectory_.NewSegment();

// The reason why we may want to skip the start of the psychohistory is
// subtle. Say that we have a vessel A with points at t₀, t₀ + 10 s,
@@ -331,9 +337,9 @@ absl::Status Vessel::RebaseFlightPlan(Mass const& initial_mass) {
}

void Vessel::RefreshPrediction() {
// The |prognostication| is a root trajectory which is computed asynchronously
// and may be used as a prediction;
std::unique_ptr<DiscreteTrajectory<Barycentric>> prognostication;
// The |prognostication| is a trajectory which is computed asynchronously and
// may be used as a prediction;
std::optional<DiscreteTraject0ry<Barycentric>> prognostication;

// Note that we know that |RefreshPrediction| is called on the main thread,
// therefore the ephemeris currently covers the last time of the
@@ -351,16 +357,16 @@ void Vessel::RefreshPrediction() {
} else {
prognosticator_.Put(std::move(prognosticator_parameters));
prognosticator_.Start();
prognostication = prognosticator_.Get().value_or(nullptr);
prognostication = prognosticator_.Get();
}
if (prognostication != nullptr) {
AttachPrediction(std::move(prognostication));
if (prognostication.has_value()) {
AttachPrediction(std::move(prognostication).value());
}
}

void Vessel::RefreshPrediction(Instant const& time) {
RefreshPrediction();
prediction_->ForgetAfter(time);
trajectory_.ForgetAfter(trajectory_.upper_bound(time));
}

void Vessel::StopPrognosticator() {
@@ -387,14 +393,13 @@ void Vessel::WriteToMessage(not_null<serialization::Vessel*> const message,
message->add_kept_parts(part_id);
}
// Starting with Gateaux we don't save the prediction, see #2685. Instead we
// save an empty prediction that we re-read as a prediction. This is a bit
// hacky, but hopefully we can remove this hack once #2400 is solved.
DiscreteTrajectory<Barycentric>* empty_prediction =
psychohistory_->NewForkAtLast();
history_->WriteToMessage(message->mutable_history(),
/*forks=*/{psychohistory_, empty_prediction},
/*exact=*/{});
psychohistory_->DeleteFork(empty_prediction);
// just save its first point and re-read as if it was the whole prediction.
trajectory_.WriteToMessage(
message->mutable_history(),
/*begin=*/trajectory_.begin(),
/*end=*/std::next(prediction_->begin()),
/*tracked=*/{history_, psychohistory_, prediction_},
/*exact=*/{});
if (flight_plan_ != nullptr) {
flight_plan_->WriteToMessage(message->mutable_flight_plan());
}
@@ -408,10 +413,13 @@ not_null<std::unique_ptr<Vessel>> Vessel::ReadFromMessage(
bool const is_pre_cesàro = message.has_psychohistory_is_authoritative();
bool const is_pre_chasles = message.has_prediction();
bool const is_pre_陈景润 = !message.history().has_downsampling();
LOG_IF(WARNING, is_pre_陈景润)
<< "Reading pre-" << (is_pre_cesàro ? u8"Cesàro"
: is_pre_chasles ? "Chasles"
: u8"陈景润") << " Vessel";
bool const is_pre_ζήνων = message.history().segment_size() == 0;
LOG_IF(WARNING, is_pre_ζήνων)
<< "Reading pre-"
<< (is_pre_cesàro ? u8"Cesàro"
: is_pre_chasles ? "Chasles"
: is_pre_陈景润 ? u8"陈景润"
: u8"Ζήνων") << " Vessel";

// NOTE(egg): for now we do not read the |MasslessBody| as it can contain no
// information.
@@ -439,37 +447,46 @@ not_null<std::unique_ptr<Vessel>> Vessel::ReadFromMessage(

if (is_pre_cesàro) {
auto const psychohistory =
DiscreteTrajectory<Barycentric>::ReadFromMessage(message.history(),
DiscreteTraject0ry<Barycentric>::ReadFromMessage(message.history(),
/*forks=*/{});
// The |history_| has been created by the constructor above. Reconstruct
// it from the |psychohistory|.
for (auto it = psychohistory->begin(); it != psychohistory->end();) {
for (auto it = psychohistory.begin(); it != psychohistory.end();) {
auto const& [time, degrees_of_freedom] = *it;
++it;
if (it == psychohistory->end() &&
if (it == psychohistory.end() &&
!message.psychohistory_is_authoritative()) {
vessel->psychohistory_ = vessel->history_->NewForkAtLast();
vessel->psychohistory_->Append(time, degrees_of_freedom);
} else {
vessel->history_->Append(time, degrees_of_freedom);
vessel->psychohistory_ = vessel->trajectory_.NewSegment();
}
vessel->trajectory_.Append(time, degrees_of_freedom);
}
if (message.psychohistory_is_authoritative()) {
vessel->psychohistory_ = vessel->history_->NewForkAtLast();
vessel->psychohistory_ = vessel->trajectory_.NewSegment();
}
vessel->prediction_ = vessel->psychohistory_->NewForkAtLast();
vessel->prediction_ = vessel->trajectory_.NewSegment();
} else if (is_pre_chasles) {
vessel->history_ = DiscreteTrajectory<Barycentric>::ReadFromMessage(
vessel->trajectory_ = DiscreteTraject0ry<Barycentric>::ReadFromMessage(
message.history(),
/*forks=*/{&vessel->psychohistory_});
vessel->prediction_ = vessel->psychohistory_->NewForkAtLast();
} else {
vessel->history_ = DiscreteTrajectory<Barycentric>::ReadFromMessage(
/*tracked=*/{&vessel->psychohistory_});
vessel->history_ = vessel->trajectory_.segments().begin();
vessel->prediction_ = vessel->trajectory_.NewSegment();
} else if (is_pre_ζήνων) {
vessel->trajectory_ = DiscreteTraject0ry<Barycentric>::ReadFromMessage(
message.history(),
/*forks=*/{&vessel->psychohistory_, &vessel->prediction_});
/*tracked=*/{&vessel->psychohistory_, &vessel->prediction_});
vessel->history_ = vessel->trajectory_.segments().begin();
// Necessary after Εὔδοξος because the ephemeris has not been prolonged
// during deserialization. Doesn't hurt prior to Εὔδοξος.
ephemeris->Prolong(vessel->prediction_->back().time);
} else {
vessel->trajectory_ = DiscreteTraject0ry<Barycentric>::ReadFromMessage(
message.history(),
/*tracked=*/{&vessel->history_,
&vessel->psychohistory_,
&vessel->prediction_});
// Necessary after Εὔδοξος because the ephemeris has not been prolonged
// during deserialization.
ephemeris->Prolong(vessel->prediction_->back().time);
}

if (is_pre_陈景润) {
@@ -548,19 +565,21 @@ Vessel::Vessel()
prediction_adaptive_step_parameters_(DefaultPredictionParameters()),
parent_(testing_utilities::make_not_null<Celestial const*>()),
ephemeris_(testing_utilities::make_not_null<Ephemeris<Barycentric>*>()),
history_(make_not_null_unique<DiscreteTrajectory<Barycentric>>()),
history_(trajectory_.segments().begin()),
psychohistory_(trajectory_.segments().end()),
prediction_(trajectory_.segments().end()),
prognosticator_(nullptr, 20ms) {}

absl::StatusOr<std::unique_ptr<DiscreteTrajectory<Barycentric>>>
absl::StatusOr<DiscreteTraject0ry<Barycentric>>
Vessel::FlowPrognostication(
PrognosticatorParameters prognosticator_parameters) {
auto prognostication = std::make_unique<DiscreteTrajectory<Barycentric>>();
prognostication->Append(
DiscreteTraject0ry<Barycentric> prognostication;
prognostication.Append(
prognosticator_parameters.first_time,
prognosticator_parameters.first_degrees_of_freedom);
absl::Status status;
status = ephemeris_->FlowWithAdaptiveStep(
prognostication.get(),
&prognostication,
Ephemeris<Barycentric>::NoIntrinsicAcceleration,
ephemeris_->t_max(),
prognosticator_parameters.adaptive_step_parameters,
@@ -569,15 +588,15 @@ Vessel::FlowPrognostication(
if (reached_t_max) {
// This will prolong the ephemeris by |max_ephemeris_steps_per_frame|.
status = ephemeris_->FlowWithAdaptiveStep(
prognostication.get(),
&prognostication,
Ephemeris<Barycentric>::NoIntrinsicAcceleration,
InfiniteFuture,
prognosticator_parameters.adaptive_step_parameters,
FlightPlan::max_ephemeris_steps_per_frame);
}
LOG_IF_EVERY_N(INFO, !status.ok(), 50)
<< "Prognostication from " << prognosticator_parameters.first_time
<< " finished at " << prognostication->back().time << " with "
<< " finished at " << prognostication.back().time << " with "
<< status.ToString() << " for " << ShortDebugString();
if (absl::IsCancelled(status)) {
return status;
@@ -591,10 +610,10 @@ Vessel::FlowPrognostication(
void Vessel::AppendToVesselTrajectory(
TrajectoryIterator const part_trajectory_begin,
TrajectoryIterator const part_trajectory_end,
DiscreteTrajectory<Barycentric>& trajectory) {
DiscreteTrajectorySegment<Barycentric> const& segment) {
CHECK(!parts_.empty());
std::vector<DiscreteTrajectory<Barycentric>::Iterator> its;
std::vector<DiscreteTrajectory<Barycentric>::Iterator> ends;
std::vector<DiscreteTraject0ry<Barycentric>::iterator> its;
std::vector<DiscreteTraject0ry<Barycentric>::iterator> ends;
its.reserve(parts_.size());
ends.reserve(parts_.size());
for (auto const& [_, part] : parts_) {
@@ -604,7 +623,7 @@ void Vessel::AppendToVesselTrajectory(

// We cannot append a point before this time, see the comments in AdvanceTime.
Instant const last_time =
trajectory.Empty() ? InfinitePast : trajectory.back().time;
segment.empty() ? InfinitePast : segment.back().time;

// Loop over the times of the trajectory.
for (;;) {
@@ -637,22 +656,20 @@ void Vessel::AppendToVesselTrajectory(
if (can_be_appended) {
DegreesOfFreedom<Barycentric> const vessel_degrees_of_freedom =
calculator.Get();
trajectory.Append(first_time, vessel_degrees_of_freedom);
trajectory_.Append(first_time, vessel_degrees_of_freedom);
}
}
}

void Vessel::AttachPrediction(
not_null<std::unique_ptr<DiscreteTrajectory<Barycentric>>> trajectory) {
trajectory->ForgetBefore(psychohistory_->back().time);
if (trajectory->Empty()) {
prediction_ = psychohistory_->NewForkAtLast();
void Vessel::AttachPrediction(DiscreteTraject0ry<Barycentric>&& trajectory) {
trajectory.ForgetBefore(psychohistory_->back().time);
if (trajectory.empty()) {
prediction_ = trajectory_.NewSegment();
} else {
if (prediction_ != nullptr) {
psychohistory_->DeleteFork(prediction_);
if (prediction_ != trajectory_.segments().end()) {
trajectory_.DeleteSegments(prediction_);
}
prediction_ = trajectory.get();
psychohistory_->AttachFork(std::move(trajectory));
prediction_ = trajectory_.AttachSegments(std::move(trajectory));
}
}

Loading