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: 1bd3d975eaa6
Choose a base ref
...
head repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 97f5ef75d58d
Choose a head ref
  • 5 commits
  • 11 files changed
  • 1 contributor

Commits on Aug 19, 2021

  1. Copy the full SHA
    81c5499 View commit details
  2. A test.

    pleroy committed Aug 19, 2021
    Copy the full SHA
    30ba546 View commit details
  3. Copy the full SHA
    46eb351 View commit details

Commits on Aug 20, 2021

  1. Fix the clients.

    pleroy committed Aug 20, 2021
    Copy the full SHA
    fb3e64c View commit details
  2. Merge pull request #3103 from pleroy/Exact

    Add support for storing the exact degrees of freedom at some points of a trajectory
    pleroy authored Aug 20, 2021
    Copy the full SHA
    97f5ef7 View commit details
3 changes: 2 additions & 1 deletion ksp_plugin/part.cpp
Original file line number Diff line number Diff line change
@@ -253,7 +253,8 @@ void Part::WriteToMessage(not_null<serialization::Part*> const message,
}
rigid_motion_.WriteToMessage(message->mutable_rigid_motion());
prehistory_->WriteToMessage(message->mutable_prehistory(),
/*forks=*/{history_, psychohistory_});
/*forks=*/{history_, psychohistory_},
/*exact=*/{});
}

not_null<std::unique_ptr<Part>> Part::ReadFromMessage(
3 changes: 2 additions & 1 deletion ksp_plugin/pile_up.cpp
Original file line number Diff line number Diff line change
@@ -177,7 +177,8 @@ void PileUp::WriteToMessage(not_null<serialization::PileUp*> message) const {
message->add_part_id(part->part_id());
}
history_->WriteToMessage(message->mutable_history(),
/*forks=*/{psychohistory_});
/*forks=*/{psychohistory_},
/*exact=*/{});
for (auto const& [part, rigid_motion] : actual_part_rigid_motion_) {
rigid_motion.WriteToMessage(&(
(*message->mutable_actual_part_rigid_motion())[part->part_id()]));
3 changes: 2 additions & 1 deletion ksp_plugin/vessel.cpp
Original file line number Diff line number Diff line change
@@ -389,7 +389,8 @@ void Vessel::WriteToMessage(not_null<serialization::Vessel*> const message,
DiscreteTrajectory<Barycentric>* empty_prediction =
psychohistory_->NewForkAtLast();
history_->WriteToMessage(message->mutable_history(),
/*forks=*/{psychohistory_, empty_prediction});
/*forks=*/{psychohistory_, empty_prediction},
/*exact=*/{});
psychohistory_->DeleteFork(empty_prediction);
if (flight_plan_ != nullptr) {
flight_plan_->WriteToMessage(message->mutable_flight_plan());
9 changes: 6 additions & 3 deletions physics/discrete_trajectory.hpp
Original file line number Diff line number Diff line change
@@ -164,10 +164,12 @@ class DiscreteTrajectory : public Forkable<DiscreteTrajectory<Frame>,

// This trajectory must be a root. Only the given |forks| are serialized.
// They must be descended from this trajectory. The pointers in |forks| may
// be null at entry.
// be null at entry. The points denoted by |exact| are written and re-read
// exactly and are not affected by any errors introduced by zfp compression.
void WriteToMessage(
not_null<serialization::DiscreteTrajectory*> message,
std::vector<DiscreteTrajectory<Frame>*> const& forks) const;
std::vector<DiscreteTrajectory<Frame>*> const& forks,
std::vector<Iterator> const& exact) const;

// |forks| must have a size appropriate for the |message| being deserialized
// and the orders of the |forks| must be consistent during serialization and
@@ -248,7 +250,8 @@ class DiscreteTrajectory : public Forkable<DiscreteTrajectory<Frame>,

void FillSubTreeFromMessage(
serialization::DiscreteTrajectory const& message,
std::vector<DiscreteTrajectory<Frame>**> const& forks);
std::vector<DiscreteTrajectory<Frame>**> const& forks,
Timeline const& exact);

// Returns the Hermite interpolation for the left-open, right-closed
// trajectory segment bounded above by |upper|.
37 changes: 32 additions & 5 deletions physics/discrete_trajectory_body.hpp
Original file line number Diff line number Diff line change
@@ -313,7 +313,8 @@ DegreesOfFreedom<Frame> DiscreteTrajectory<Frame>::EvaluateDegreesOfFreedom(
template<typename Frame>
void DiscreteTrajectory<Frame>::WriteToMessage(
not_null<serialization::DiscreteTrajectory*> const message,
std::vector<DiscreteTrajectory<Frame>*> const& forks)
std::vector<DiscreteTrajectory<Frame>*> const& forks,
std::vector<Iterator> const& exact)
const {
CHECK(this->is_root());

@@ -324,6 +325,13 @@ void DiscreteTrajectory<Frame>::WriteToMessage(
[](DiscreteTrajectory<Frame>* const fork) {
return fork == nullptr;
}));

for (auto const& it : exact) {
auto* const serialized_exact = message->add_exact();
it->time.WriteToMessage(serialized_exact->mutable_instant());
it->degrees_of_freedom.WriteToMessage(
serialized_exact->mutable_degrees_of_freedom());
}
}

template<typename Frame>
@@ -332,13 +340,23 @@ not_null<std::unique_ptr<DiscreteTrajectory<Frame>>>
DiscreteTrajectory<Frame>::ReadFromMessage(
serialization::DiscreteTrajectory const& message,
std::vector<DiscreteTrajectory<Frame>**> const& forks) {
// We use a Timeline as a convenient container for the exact points.
Timeline exact;
for (auto const& instantaneous_degrees_of_freedom : message.exact()) {
auto const t =
Instant::ReadFromMessage(instantaneous_degrees_of_freedom.instant());
auto const degrees_of_freedom = DegreesOfFreedom<Frame>::ReadFromMessage(
instantaneous_degrees_of_freedom.degrees_of_freedom());
exact.emplace_hint(exact.end(), t, degrees_of_freedom);
}

auto trajectory = make_not_null_unique<DiscreteTrajectory>();
CHECK(std::all_of(forks.begin(),
forks.end(),
[](DiscreteTrajectory<Frame>** const fork) {
return fork != nullptr && *fork == nullptr;
}));
trajectory->FillSubTreeFromMessage(message, forks);
trajectory->FillSubTreeFromMessage(message, forks, exact);
return trajectory;
}

@@ -570,7 +588,8 @@ void DiscreteTrajectory<Frame>::WriteSubTreeToMessage(
template<typename Frame>
void DiscreteTrajectory<Frame>::FillSubTreeFromMessage(
serialization::DiscreteTrajectory const& message,
std::vector<DiscreteTrajectory<Frame>**> const& forks) {
std::vector<DiscreteTrajectory<Frame>**> const& forks,
Timeline const& exact) {
bool const is_pre_frobenius = !message.has_zfp();
LOG_IF(WARNING, is_pre_frobenius)
<< "Reading pre-Frobenius DiscreteTrajectory";
@@ -610,7 +629,15 @@ void DiscreteTrajectory<Frame>::FillSubTreeFromMessage(
Velocity<Frame> const p({px[i] * (Metre / Second),
py[i] * (Metre / Second),
pz[i] * (Metre / Second)});
Append(Instant() + t[i] * Second, DegreesOfFreedom<Frame>(q, p));

// See if this is a point whose degrees of freedom must be restored
// exactly.
Instant const time = Instant() + t[i] * Second;
if (auto it = exact.find(time); it == exact.cend()) {
Append(time, DegreesOfFreedom<Frame>(q, p));
} else {
Append(time, it->second);
}
}
}
if (message.has_downsampling()) {
@@ -619,7 +646,7 @@ void DiscreteTrajectory<Frame>::FillSubTreeFromMessage(
Downsampling::ReadFromMessage(message.downsampling(), timeline_));
}
Forkable<DiscreteTrajectory, Iterator, DiscreteTrajectoryTraits<Frame>>::
FillSubTreeFromMessage(message, forks);
FillSubTreeFromMessage(message, forks, exact);
}

template<typename Frame>
33 changes: 27 additions & 6 deletions physics/discrete_trajectory_test.cpp
Original file line number Diff line number Diff line change
@@ -678,7 +678,7 @@ TEST_F(DiscreteTrajectoryDeathTest, TrajectorySerializationError) {
not_null<DiscreteTrajectory<World>*> const fork =
massive_trajectory_->NewForkWithCopy(t1_);
serialization::DiscreteTrajectory message;
fork->WriteToMessage(&message, /*forks=*/{});
fork->WriteToMessage(&message, /*forks=*/{}, /*exact=*/{});
}, "is_root");
}

@@ -701,9 +701,12 @@ TEST_F(DiscreteTrajectoryTest, TrajectorySerializationSuccess) {
serialization::DiscreteTrajectory reference_message;

// Don't serialize |fork0| and |fork4|.
massive_trajectory_->WriteToMessage(&message, {fork1, fork3, fork2});
massive_trajectory_->WriteToMessage(&message,
{fork1, fork3, fork2},
/*exact=*/{});
massive_trajectory_->WriteToMessage(&reference_message,
{fork1, fork3, fork2});
{fork1, fork3, fork2},
/*exact=*/{});

DiscreteTrajectory<World>* deserialized_fork1 = nullptr;
DiscreteTrajectory<World>* deserialized_fork2 = nullptr;
@@ -721,7 +724,8 @@ TEST_F(DiscreteTrajectoryTest, TrajectorySerializationSuccess) {
deserialized_trajectory->WriteToMessage(&message,
{deserialized_fork1,
deserialized_fork3,
deserialized_fork2});
deserialized_fork2},
/*exact=*/{});
EXPECT_THAT(reference_message, EqualsProto(message));
EXPECT_THAT(message.children_size(), Eq(2));
EXPECT_THAT(message.zfp().timeline_size(), Eq(3));
@@ -888,12 +892,17 @@ TEST_F(DiscreteTrajectoryTest, DownsamplingSerialization) {
deserialized_circle->Append(t.value, dof);
}
serialization::DiscreteTrajectory message;
deserialized_circle->WriteToMessage(&message, /*forks=*/{});
deserialized_circle->WriteToMessage(
&message,
/*forks=*/{},
/*exact=*/{circle.LowerBound(t0_ + 2 * Second),
circle.LowerBound(t0_ + 3 * Second)});
deserialized_circle =
DiscreteTrajectory<World>::ReadFromMessage(message, /*forks=*/{});

// Serialization/deserialization preserves the size, the times, and nudges the
// positions by less than the tolerance.
// positions by less than the tolerance. It also preserve the degrees of
// freedom at the "exact" iterators.
EXPECT_THAT(circle.Size(), Eq(39));
EXPECT_THAT(deserialized_circle->Size(), circle.Size());
for (auto it1 = circle.begin(), it2 = deserialized_circle->begin();
@@ -907,6 +916,18 @@ TEST_F(DiscreteTrajectoryTest, DownsamplingSerialization) {
AbsoluteErrorFrom(it1->degrees_of_freedom.velocity(),
Lt(1.1 * Milli(Metre) / Second)));
}
EXPECT_NE(
deserialized_circle->LowerBound(t0_ + 1 * Second)->degrees_of_freedom,
circle.LowerBound(t0_ + 1 * Second)->degrees_of_freedom);
EXPECT_EQ(
deserialized_circle->LowerBound(t0_ + 2 * Second)->degrees_of_freedom,
circle.LowerBound(t0_ + 2 * Second)->degrees_of_freedom);
EXPECT_EQ(
deserialized_circle->LowerBound(t0_ + 3 * Second)->degrees_of_freedom,
circle.LowerBound(t0_ + 3 * Second)->degrees_of_freedom);
EXPECT_NE(
deserialized_circle->LowerBound(t0_ + 4 * Second)->degrees_of_freedom,
circle.LowerBound(t0_ + 4 * Second)->degrees_of_freedom);

// Appending may result in different downsampling because the positions differ
// a bit.
2 changes: 1 addition & 1 deletion physics/ephemeris_test.cpp
Original file line number Diff line number Diff line change
@@ -1067,7 +1067,7 @@ TEST(EphemerisTestNoFixture, DiscreteTrajectoryCompression) {
EXPECT_EQ(1162, trajectory1.Size());

serialization::DiscreteTrajectory message;
trajectory1.WriteToMessage(&message, /*forks=*/{});
trajectory1.WriteToMessage(&message, /*forks=*/{}, /*exact=*/{});
std::string uncompressed;
message.SerializePartialToString(&uncompressed);
EXPECT_EQ(24'394, uncompressed.size());
4 changes: 3 additions & 1 deletion physics/forkable.hpp
Original file line number Diff line number Diff line change
@@ -148,6 +148,7 @@ class Forkable {
bool Empty() const;

protected:
using Timeline = typename Traits::Timeline;
using TimelineConstIterator = typename Traits::TimelineConstIterator;

// The API that must be implemented by subclasses.
@@ -206,7 +207,8 @@ class Forkable {
std::vector<Tr4jectory*>& forks) const;

void FillSubTreeFromMessage(serialization::DiscreteTrajectory const& message,
std::vector<Tr4jectory**> const& forks);
std::vector<Tr4jectory**> const& forks,
Timeline const& exact);

private:
// Constructs an Iterator by wrapping the timeline iterator
5 changes: 3 additions & 2 deletions physics/forkable_body.hpp
Original file line number Diff line number Diff line change
@@ -500,7 +500,8 @@ void Forkable<Tr4jectory, It3rator, Traits>::WriteSubTreeToMessage(
template<typename Tr4jectory, typename It3rator, typename Traits>
void Forkable<Tr4jectory, It3rator, Traits>::FillSubTreeFromMessage(
serialization::DiscreteTrajectory const& message,
std::vector<Tr4jectory**> const& forks) {
std::vector<Tr4jectory**> const& forks,
Timeline const& exact) {
// There were no fork positions prior to Буняковский.
bool const has_fork_position = message.fork_position_size() > 0;
std::int32_t index = 0;
@@ -510,7 +511,7 @@ void Forkable<Tr4jectory, It3rator, Traits>::FillSubTreeFromMessage(
for (serialization::DiscreteTrajectory const& child :
litter.trajectories()) {
not_null<Tr4jectory*> fork = NewFork(timeline_find(fork_time));
fork->FillSubTreeFromMessage(child, forks);
fork->FillSubTreeFromMessage(child, forks, exact);
if (has_fork_position) {
std::int32_t const fork_position = message.fork_position(index);
*forks[fork_position] = fork;
3 changes: 2 additions & 1 deletion physics/forkable_test.cpp
Original file line number Diff line number Diff line change
@@ -21,7 +21,8 @@ using quantities::si::Second;
using ::testing::ElementsAre;

struct FakeTrajectoryTraits : not_constructible {
using TimelineConstIterator = std::list<Instant>::const_iterator;
using Timeline = std::list<Instant>;
using TimelineConstIterator = Timeline::const_iterator;
static Instant const& time(TimelineConstIterator const it);
};

2 changes: 2 additions & 0 deletions serialization/physics.proto
Original file line number Diff line number Diff line change
@@ -101,6 +101,8 @@ message DiscreteTrajectory {
repeated int32 fork_position = 3;
// Added in 陈景润.
optional Downsampling downsampling = 4;
// Added in Haar.
repeated InstantaneousDegreesOfFreedom exact = 6;

// Added in Frobenius.
message Zfp {