|
2 | 2 |
|
3 | 3 | #include "physics/discrete_trajectory_segment.hpp"
|
4 | 4 |
|
| 5 | +#include <iterator> |
| 6 | + |
| 7 | +#include "astronomy/epoch.hpp" |
5 | 8 | #include "glog/logging.h"
|
6 | 9 |
|
7 | 10 | namespace principia {
|
8 | 11 | namespace physics {
|
9 | 12 | namespace internal_discrete_trajectory_segment {
|
10 | 13 |
|
| 14 | +using astronomy::InfiniteFuture; |
| 15 | +using astronomy::InfinitePast; |
| 16 | + |
11 | 17 | template<typename Frame>
|
12 | 18 | DiscreteTrajectorySegment<Frame>::DiscreteTrajectorySegment(
|
13 | 19 | DiscreteTrajectorySegmentIterator<Frame> const self)
|
@@ -44,6 +50,18 @@ DiscreteTrajectorySegment<Frame>::rend() const {
|
44 | 50 | return reverse_iterator(begin());
|
45 | 51 | }
|
46 | 52 |
|
| 53 | +template<typename Frame> |
| 54 | +bool DiscreteTrajectorySegment<Frame>::empty() const { |
| 55 | + return timeline_.empty(); |
| 56 | +} |
| 57 | + |
| 58 | +template<typename Frame> |
| 59 | +std::int64_t DiscreteTrajectorySegment<Frame>::size() const { |
| 60 | + // NOTE(phl): This assumes that there are no repeated times *within* a |
| 61 | + // segment. This is enforced by Append. |
| 62 | + return timeline_.size(); |
| 63 | +} |
| 64 | + |
47 | 65 | template<typename Frame>
|
48 | 66 | typename DiscreteTrajectorySegment<Frame>::iterator
|
49 | 67 | DiscreteTrajectorySegment<Frame>::find(Instant const& t) const {
|
@@ -78,15 +96,51 @@ DiscreteTrajectorySegment<Frame>::upper_bound(Instant const& t) const {
|
78 | 96 | }
|
79 | 97 |
|
80 | 98 | template<typename Frame>
|
81 |
| -bool DiscreteTrajectorySegment<Frame>::empty() const { |
82 |
| - return timeline_.empty(); |
| 99 | +Instant DiscreteTrajectorySegment<Frame>::t_min() const { |
| 100 | + return empty() ? InfiniteFuture : timeline_.cbegin()->first; |
83 | 101 | }
|
84 | 102 |
|
85 | 103 | template<typename Frame>
|
86 |
| -std::int64_t DiscreteTrajectorySegment<Frame>::size() const { |
87 |
| - // NOTE(phl): This assumes that there are no repeated times *within* a |
88 |
| - // segment. This is enforced by Append. |
89 |
| - return timeline_.size(); |
| 104 | +Instant DiscreteTrajectorySegment<Frame>::t_max() const { |
| 105 | + return empty() ? InfinitePast : timeline_.crbegin()->first; |
| 106 | +} |
| 107 | + |
| 108 | +template<typename Frame> |
| 109 | +Position<Frame> DiscreteTrajectorySegment<Frame>::EvaluatePosition( |
| 110 | + Instant const& t) const { |
| 111 | + auto const it = timeline_.lower_bound(t); |
| 112 | + if (it->first == t) { |
| 113 | + return it->second.position(); |
| 114 | + } |
| 115 | + CHECK_LT(t_min(), t); |
| 116 | + CHECK_GT(t_max(), t); |
| 117 | + return GetInterpolation(it).Evaluate(t); |
| 118 | +} |
| 119 | + |
| 120 | +template<typename Frame> |
| 121 | +Velocity<Frame> DiscreteTrajectorySegment<Frame>::EvaluateVelocity( |
| 122 | + Instant const& t) const { |
| 123 | + auto const it = timeline_.lower_bound(t); |
| 124 | + if (it->first == t) { |
| 125 | + return it->second.velocity(); |
| 126 | + } |
| 127 | + CHECK_LT(t_min(), t); |
| 128 | + CHECK_GT(t_max(), t); |
| 129 | + return GetInterpolation(it).EvaluateDerivative(t); |
| 130 | +} |
| 131 | + |
| 132 | +template<typename Frame> |
| 133 | +DegreesOfFreedom<Frame> |
| 134 | +DiscreteTrajectorySegment<Frame>::EvaluateDegreesOfFreedom( |
| 135 | + Instant const& t) const { |
| 136 | + auto const it = timeline_.lower_bound(t); |
| 137 | + if (it->first == t) { |
| 138 | + return it->second; |
| 139 | + } |
| 140 | + CHECK_LT(t_min(), t); |
| 141 | + CHECK_GT(t_max(), t); |
| 142 | + auto const interpolation = GetInterpolation(it); |
| 143 | + return {interpolation.Evaluate(t), interpolation.EvaluateDerivative(t)}; |
90 | 144 | }
|
91 | 145 |
|
92 | 146 | template<typename Frame>
|
@@ -136,6 +190,22 @@ void DiscreteTrajectorySegment<Frame>::ForgetBefore(
|
136 | 190 | // TODO(phl): Downsampling.
|
137 | 191 | }
|
138 | 192 |
|
| 193 | +template<typename Frame> |
| 194 | +Hermite3<Instant, Position<Frame>> |
| 195 | +DiscreteTrajectorySegment<Frame>::GetInterpolation( |
| 196 | + typename Timeline::const_iterator const upper) const { |
| 197 | + CHECK(upper != timeline_.cbegin()); |
| 198 | + auto const lower = std::prev(upper); |
| 199 | + auto const& [lower_time, lower_degrees_of_freedom] = *lower; |
| 200 | + auto const& [upper_time, upper_degrees_of_freedom] = *upper; |
| 201 | + return Hermite3<Instant, Position<Frame>>{ |
| 202 | + {lower_time, upper_time}, |
| 203 | + {lower_degrees_of_freedom.position(), |
| 204 | + upper_degrees_of_freedom.position()}, |
| 205 | + {lower_degrees_of_freedom.velocity(), |
| 206 | + upper_degrees_of_freedom.velocity()}}; |
| 207 | +} |
| 208 | + |
139 | 209 | template<typename Frame>
|
140 | 210 | typename DiscreteTrajectorySegment<Frame>::Timeline::const_iterator
|
141 | 211 | DiscreteTrajectorySegment<Frame>::timeline_begin() const {
|
|
0 commit comments