-
Notifications
You must be signed in to change notification settings - Fork 69
/
Copy pathkepler_orbit.hpp
145 lines (125 loc) · 5.48 KB
/
kepler_orbit.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#pragma once
#include <experimental/optional>
#include <ostream>
#include <string>
#include "physics/body.hpp"
#include "physics/degrees_of_freedom.hpp"
namespace principia {
namespace physics {
namespace internal_kepler_orbit {
using base::not_null;
using geometry::Instant;
using quantities::Angle;
using quantities::AngularFrequency;
using quantities::GravitationalParameter;
using quantities::Length;
using quantities::SpecificAngularMomentum;
using quantities::SpecificEnergy;
using quantities::Speed;
using quantities::Time;
template<typename Frame>
struct KeplerianElements final {
// I. These elements determine the shape and size of the conic. Two are
// needed, from two different numbered categories below.
// 1. eccentricity.
std::experimental::optional<double> eccentricity;
// The following two elements are NaN for elliptic orbits.
std::experimental::optional<Angle> asymptotic_true_anomaly;
std::experimental::optional<Angle> turning_angle;
// 2. semimajor axis.
std::experimental::optional<Length> semimajor_axis;
std::experimental::optional<SpecificEnergy> specific_energy;
std::experimental::optional<SpecificEnergy> characteristic_energy;
// The following two elements are NaN for hyperbolic orbits.
std::experimental::optional<AngularFrequency> mean_motion;
std::experimental::optional<Time> period;
// The following two elements are NaN for elliptic orbits.
std::experimental::optional<AngularFrequency> hyperbolic_mean_motion;
std::experimental::optional<Speed> hyperbolic_excess_velocity;
// 3. semiminor axis. The |semiminor_axis| is NaN for hyperbolic orbits, the
// |impact_parameter| is NaN for elliptic orbits.
std::experimental::optional<Length> semiminor_axis;
std::experimental::optional<Length> impact_parameter;
// 4. semilatus rectum.
std::experimental::optional<Length> semilatus_rectum;
std::experimental::optional<SpecificAngularMomentum>
specific_angular_momentum;
// 5. periapsis distance.
std::experimental::optional<Length> periapsis_distance;
// 6. apoapsis distance.
std::experimental::optional<Length> apoapsis_distance;
// II. These elements determine the orientation of the conic. Three are
// needed.
Angle inclination;
Angle longitude_of_ascending_node;
std::experimental::optional<Angle> argument_of_periapsis;
std::experimental::optional<Angle> longitude_of_periapsis;
// III. These elements determine a point on the conic. One is needed.
std::experimental::optional<Angle> true_anomaly;
#if NOT_YET_IMPLEMENTED
std::experimental::optional<Angle> true_longitude;
std::experimental::optional<Time> time_since_periapsis;
#endif
// The mean anomaly and mean longitude are NaN for hyperbolic orbits.
std::experimental::optional<Angle> mean_anomaly;
#if NOT_YET_IMPLEMENTED
std::experimental::optional<Angle> mean_longitude;
#endif
// The hyperbolic mean anomaly is NaN for elliptic orbits.
std::experimental::optional<Angle> hyperbolic_mean_anomaly;
void WriteToMessage(
not_null<serialization::KeplerianElements*> message) const;
};
template<typename Frame>
std::string DebugString(KeplerianElements<Frame> const& elements);
template<typename Frame>
std::ostream& operator<<(std::ostream& out,
KeplerianElements<Frame> const& elements);
template<typename Frame>
class KeplerOrbit final {
static_assert(Frame::is_inertial, "Frame must be inertial");
public:
// Exactly one of the |optional|s must be filled in the given
// |KeplerianElements|.
KeplerOrbit(MassiveBody const& primary,
Body const& secondary,
KeplerianElements<Frame> const& elements_at_epoch,
Instant const& epoch);
KeplerOrbit(MassiveBody const& primary,
Body const& secondary,
RelativeDegreesOfFreedom<Frame> const& state_vectors,
Instant const& epoch);
// The |DegreesOfFreedom| of the secondary minus those of the primary.
RelativeDegreesOfFreedom<Frame> StateVectors(Instant const& t) const;
// All |optional|s are filled in the result.
KeplerianElements<Frame> const& elements_at_epoch() const;
private:
// |elements| must be minimally specified. Fills all |optional|s in
// |elements|.
static void CompleteElements(KeplerianElements<Frame>& elements,
GravitationalParameter const& μ);
// For each category in section I of |elements|, either one, none, or all of
// the |optional|s must be filled. If one is filled, fills the others in that
// category.
static void CompleteConicParametersByCategory(
KeplerianElements<Frame>& elements,
GravitationalParameter const& μ);
// Section I of |elements| must be minimally specified. Fills it.
static void CompleteConicParameters(KeplerianElements<Frame>& elements,
GravitationalParameter const& μ);
// Section II of |elements| must be minimally specified. Fills it.
static void CompleteOrientationParameters(KeplerianElements<Frame>& elements);
// Sections I and II of |elements| must be filled; section III must be
// minimally specified. Fills section III.
static void CompleteAnomalies(KeplerianElements<Frame>& elements);
GravitationalParameter const gravitational_parameter_;
KeplerianElements<Frame> elements_at_epoch_;
Instant const epoch_;
};
} // namespace internal_kepler_orbit
using internal_kepler_orbit::KeplerianElements;
using internal_kepler_orbit::KeplerOrbit;
} // namespace physics
} // namespace principia
#include "physics/kepler_orbit_body.hpp"