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

Commits on Oct 17, 2021

  1. Writing a complete trajectory.

    pleroy committed Oct 17, 2021
    Copy the full SHA
    eecabca View commit details
  2. Copy the full SHA
    142c0c5 View commit details
  3. Reading without compatibility.

    pleroy committed Oct 17, 2021
    Copy the full SHA
    4036430 View commit details
  4. Copy the full SHA
    4ddc9d7 View commit details

Commits on Oct 18, 2021

  1. A test that passes.

    pleroy committed Oct 18, 2021
    Copy the full SHA
    5528110 View commit details
  2. Complete test.

    pleroy committed Oct 18, 2021
    Copy the full SHA
    df2cb13 View commit details
  3. Merge pull request #3158 from pleroy/TrajectorySerialization

    Serialization of DiscreteTrajectory
    pleroy authored Oct 18, 2021
    Copy the full SHA
    61d13ba View commit details
Showing with 148 additions and 27 deletions.
  1. +2 −8 physics/discrete_trajectory2.hpp
  2. +83 −14 physics/discrete_trajectory2_body.hpp
  3. +48 −1 physics/discrete_trajectory2_test.cpp
  4. +2 −2 physics/discrete_trajectory_body.hpp
  5. +13 −2 serialization/physics.proto
10 changes: 2 additions & 8 deletions physics/discrete_trajectory2.hpp
Original file line number Diff line number Diff line change
@@ -101,17 +101,11 @@ class DiscreteTrajectory2 : public Trajectory<Frame> {
not_null<serialization::DiscreteTrajectory*> message,
std::vector<SegmentIterator> const& tracked,
std::vector<iterator> const& exact) const;
void WriteToMessage(
not_null<serialization::DiscreteTrajectory*> message,
iterator begin, iterator end,
std::vector<SegmentIterator> const& tracked,
std::vector<iterator> const& exact) const;

template<typename F = Frame,
typename = std::enable_if_t<base::is_serializable_v<F>>>
static not_null<std::unique_ptr<DiscreteTrajectory2>> ReadFromMessage(
static DiscreteTrajectory2 ReadFromMessage(
serialization::DiscreteTrajectory const& message,
std::vector<DiscreteTrajectory2**> const& tracked);
std::vector<SegmentIterator*> const& tracked);

private:
using Segments = internal_discrete_trajectory_types::Segments<Frame>;
97 changes: 83 additions & 14 deletions physics/discrete_trajectory2_body.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#pragma once
#pragma once

#include "physics/discrete_trajectory2.hpp"

#include <vector>

#include "absl/container/flat_hash_map.h"
#include "astronomy/epoch.hpp"

namespace principia {
@@ -271,26 +272,94 @@ void DiscreteTrajectory2<Frame>::WriteToMessage(
not_null<serialization::DiscreteTrajectory*> message,
std::vector<SegmentIterator> const& tracked,
std::vector<iterator> const& exact) const {
// TODO(phl): Implement.
}
// Construct a map to efficiently find if a segment must be tracked. The
// keys are pointers to segments in |tracked|, the values are the
// corresponding indices.
absl::flat_hash_map<DiscreteTrajectorySegment<Frame> const*, int>
segment_to_position;
for (int i = 0; i < tracked.size(); ++i) {
segment_to_position.emplace(&*tracked[i], i);
}

template<typename Frame>
void DiscreteTrajectory2<Frame>::WriteToMessage(
not_null<serialization::DiscreteTrajectory*> message,
iterator begin,
iterator end,
std::vector<SegmentIterator> const& tracked,
std::vector<iterator> const& exact) const {
// TODO(phl): Implement.
// Initialize the tracked positions to be able to recognize if some are
// missing.
message->mutable_tracked_position()->Resize(
tracked.size(),
serialization::DiscreteTrajectory::MISSING_TRACKED_POSITION);

// The position of a segment in the repeated field |segment|.
int segment_position = 0;
for (auto sit = segments_->begin();
sit != segments_->end();
++sit, ++segment_position) {
sit->WriteToMessage(message->add_segment(), exact);

if (auto const position_it = segment_to_position.find(&*sit);
position_it != segment_to_position.end()) {
// The field |tracked_position| is indexed by the indices in |tracked|.
// Its value is the position of a tracked segment in the field |segment|.
message->set_tracked_position(position_it->second, segment_position);
}
}

for (auto const& [t, _] : segment_by_left_endpoint_) {
t.WriteToMessage(message->add_left_endpoint());
}

// Check that all the segments in |tracked| were mapped.
// NOTE(phl): This might be too strong a constraint in Entwurf.
for (auto const tracked_position : message->tracked_position()) {
CHECK_NE(serialization::DiscreteTrajectory::MISSING_TRACKED_POSITION,
tracked_position);
}
}

template<typename Frame>
template<typename F, typename>
not_null<std::unique_ptr<DiscreteTrajectory2<Frame>>>
DiscreteTrajectory2<Frame>
DiscreteTrajectory2<Frame>::ReadFromMessage(
serialization::DiscreteTrajectory const& message,
std::vector<DiscreteTrajectory2**> const& tracked) {
// TODO(phl): Implement.
std::vector<SegmentIterator*> const& tracked) {
DiscreteTrajectory2 trajectory(uninitialized);

bool const is_pre_ζήνων = message.segment_size() == 0;
if (is_pre_ζήνων) {
// TODO(phl): Implement.
LOG(FATAL) << "Pre-Ζήνων compatibility NYI";
}

// First restore the segments themselves. This vector will be used to restore
// the tracked segments.
std::vector<SegmentIterator> segment_iterators;
segment_iterators.reserve(message.segment_size());
for (auto const& serialized_segment : message.segment()) {
trajectory.segments_->emplace_back();
auto const sit = --trajectory.segments_->end();
auto const self = SegmentIterator(trajectory.segments_.get(), sit);
*sit = DiscreteTrajectorySegment<Frame>::ReadFromMessage(serialized_segment,
self);
segment_iterators.push_back(self);
}

// Restore the tracked segments.
CHECK_EQ(tracked.size(), message.tracked_position_size());
for (int i = 0; i < message.tracked_position_size(); ++i) {
int const tracked_position = message.tracked_position(i);
CHECK_NE(serialization::DiscreteTrajectory::MISSING_TRACKED_POSITION,
tracked_position);
*tracked[i] = segment_iterators[tracked_position];
}

// Finally restore the left endpoints.
auto sit = trajectory.segments_->begin();
for (auto const& serialized_t : message.left_endpoint()) {
auto const t = Instant::ReadFromMessage(serialized_t);
trajectory.segment_by_left_endpoint_.emplace_hint(
trajectory.segment_by_left_endpoint_.end(), t, sit);
++sit;
}

return trajectory;
}

template<typename Frame>
49 changes: 48 additions & 1 deletion physics/discrete_trajectory2_test.cpp
Original file line number Diff line number Diff line change
@@ -7,27 +7,36 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "quantities/si.hpp"
#include "serialization/physics.pb.h"
#include "testing_utilities/almost_equals.hpp"
#include "testing_utilities/componentwise.hpp"
#include "testing_utilities/discrete_trajectory_factories.hpp"
#include "testing_utilities/matchers.hpp"

namespace principia {
namespace physics {

using geometry::Displacement;
using geometry::Frame;
using geometry::Handedness;
using geometry::Inertial;
using geometry::Instant;
using geometry::Velocity;
using quantities::si::Metre;
using quantities::si::Second;
using testing_utilities::AlmostEquals;
using testing_utilities::Componentwise;
using testing_utilities::EqualsProto;
using testing_utilities::NewLinearTrajectoryTimeline;
using ::testing::ElementsAre;

class DiscreteTrajectory2Test : public ::testing::Test {
protected:
using World = Frame<enum class WorldTag>;
using World = Frame<serialization::Frame::TestTag,
Inertial,
Handedness::Right,
serialization::Frame::TEST>;


// Constructs a trajectory with three 5-second segments starting at |t0| and
// the given |degrees_of_freedom|.
@@ -469,5 +478,43 @@ TEST_F(DiscreteTrajectory2Test, TMinTMaxEvaluate) {
0 * Metre / Second}), 0)));
}

TEST_F(DiscreteTrajectory2Test, SerializationRoundTrip) {
auto const trajectory = MakeTrajectory();
auto const trajectory_first_segment = trajectory.segments().begin();
auto const trajectory_second_segment = std::next(trajectory_first_segment);

serialization::DiscreteTrajectory message1;
trajectory.WriteToMessage(&message1,
/*tracked=*/{trajectory_second_segment},
/*exact=*/
{trajectory.lower_bound(t0_ + 2 * Second),
trajectory.lower_bound(t0_ + 3 * Second)});

DiscreteTrajectorySegmentIterator<World> deserialized_second_segment;
auto const deserialized_trajectory =
DiscreteTrajectory2<World>::ReadFromMessage(
message1, /*tracked=*/{&deserialized_second_segment});

// Check that the tracked segment was properly retrieved.
EXPECT_EQ(t0_ + 4 * Second, deserialized_second_segment->begin()->first);
EXPECT_EQ(t0_ + 9 * Second, deserialized_second_segment->rbegin()->first);

// Check that the exact points are exact.
EXPECT_EQ(deserialized_trajectory.lower_bound(t0_ + 2 * Second)->second,
trajectory.lower_bound(t0_ + 2 * Second)->second);
EXPECT_EQ(deserialized_trajectory.lower_bound(t0_ + 3 * Second)->second,
trajectory.lower_bound(t0_ + 3 * Second)->second);

serialization::DiscreteTrajectory message2;
deserialized_trajectory.WriteToMessage(
&message2,
/*tracked=*/{deserialized_second_segment},
/*exact=*/
{deserialized_trajectory.lower_bound(t0_ + 2 * Second),
deserialized_trajectory.lower_bound(t0_ + 3 * Second)});

EXPECT_THAT(message2, EqualsProto(message1));
}

} // namespace physics
} // namespace principia
4 changes: 2 additions & 2 deletions physics/discrete_trajectory_body.hpp
Original file line number Diff line number Diff line change
@@ -486,10 +486,10 @@ typename DiscreteTrajectory<Frame>::Downsampling
DiscreteTrajectory<Frame>::Downsampling::ReadFromMessage(
serialization::DiscreteTrajectory::Downsampling const& message,
Timeline const& timeline) {
bool const is_pre_grotendieck_haar = message.has_start_of_dense_timeline();
bool const is_pre_haar = message.has_start_of_dense_timeline();
Downsampling downsampling({message.max_dense_intervals(),
Length::ReadFromMessage(message.tolerance())});
if (is_pre_grotendieck_haar) {
if (is_pre_haar) {
// No support for forks in legacy saves, so |find| will succeed and ++ is
// safe.
auto it = timeline.find(
15 changes: 13 additions & 2 deletions serialization/physics.proto
Original file line number Diff line number Diff line change
@@ -83,9 +83,9 @@ message DiscreteTrajectory {
required int64 max_dense_intervals = 2;
required Quantity tolerance = 3;
// The instant of the iterator; absent if it is the end of the timeline.
// Pre Grothendieck/Haar.
// Pre Haar.
optional Point start_of_dense_timeline = 1;
// Added in Grothendieck/Haar.
// Added in Haar.
repeated Point dense_timeline = 4;
}
message InstantaneousDegreesOfFreedom {
@@ -112,6 +112,17 @@ message DiscreteTrajectory {
required int32 timeline_size = 4;
}
optional Zfp zfp = 5;

// All the declarations above are pre-Ζήνων. All the declarations below were
// added in Ζήνων.

// A marker to indicate that a segment doesn't have its position tracked.
enum TrackedPosition {
MISSING_TRACKED_POSITION = -1;
}
repeated DiscreteTrajectorySegment segment = 7;
repeated Point left_endpoint = 8;
repeated int32 tracked_position = 9;
}

// Added in Ζήνων.