Astro  0.0.0
A C++ library for space dynamics
Loading...
Searching...
No Matches
OrbitalElements.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
2 * Copyright (c) 2025, Davide Stocco and Enrico Bertolazzi. *
3 * *
4 * The Astro project is distributed under the GNU GPLv3. *
5 * *
6 * Davide Stocco Enrico Bertolazzi *
7 * University of Trento University of Trento *
8 * e-mail: davide.stocco@unitn.it e-mail: enrico.bertolazzi@unitn.it *
9\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10
11#pragma once
12
13#ifndef ASTRO_ORBITALELEMENTS_HH
14#define ASTRO_ORBITALELEMENTS_HH
15
16#include "Astro.hh"
17#include "Astro/Utilities.hh"
18
19namespace Astro
20{
22 using Factor = enum class Factor : Integer {
23 POSIGRADE = 1, UNDEFINED = 0, RETROGRADE = -1
24 };
25
27 using Type = enum class Type : Integer {
28 UNDEFINED = 0, HYPERBOLIC = 1, ELLIPTIC = 2, CIRCULAR = 3, PARABOLIC = 4
29 };
30
37 {
38
39 /*\
40 | ____ _ _
41 | / ___|__ _ _ __| |_ ___ ___(_) __ _ _ __
42 | | | / _` | '__| __/ _ \/ __| |/ _` | '_ \
43 | | |__| (_| | | | || __/\__ \ | (_| | | | |
44 | \____\__,_|_| \__\___||___/_|\__,_|_| |_|
45 |
46 \*/
47
58 struct Cartesian
59 {
62
67
73 Cartesian(Vector3 const &t_r, Vector3 const &t_v) : r(t_r), v(t_v) {}
74
80 Cartesian(Vector6 const &t_cart) : r(t_cart.head<3>()), v(t_cart.tail<3>()) {}
81
91 Cartesian(Real r_x, Real r_y, Real r_z, Real v_x, Real v_y, Real v_z) :
92 r(r_x, r_y, r_z), v(v_x, v_y, v_z) {}
93
97 Cartesian(Cartesian const &) = default;
98
102 Cartesian(Cartesian &&) = default;
103
107 Cartesian & operator=(const Cartesian &) = default;
108
113
118 Vector6 vector() const {
119 Vector6 vec;
120 vec << this->r, this->v;
121 return vec;
122 }
123
128 std::string info() const {
129 std::ostringstream os;
130 os <<
131 "r = " << this->r.transpose() << " (UA)" << std::endl <<
132 "v = " << this->v.transpose() << " (UA/day)" << std::endl;
133 return os.str();
134 }
135
140 void info(std::ostream & os) {os << this->info();}
141
145 void reset() {
146 this->r = NAN_VEC3;
147 this->v = NAN_VEC3;
148 }
149
153 bool sanity_check() const {
154 #define CMD "Astro::OrbitalElements::Cartesian::sanity_check(...): "
155
156 if (!(this->r.allFinite())) {
157 ASTRO_WARNING(CMD "invalid position vector detected." << r.transpose());
158 return false;
159 }
160 if (!(this->v.allFinite())) {
161 ASTRO_WARNING(CMD "invalid velocity vector detected.");
162 return false;
163 }
164 return true;
165
166 #undef CMD
167 }
168
173 Vector3 h() const {return this->r.cross(this->v);}
174
182 Real e(Real const mu) const
183 {
184 return ((this->v.cross(this->h()) / mu) - (this->r / this->r.norm())).norm();
185 }
186
195 Vector3 spherical_coordinates() const
196 {
197 Real r = this->r.norm();
198 Real theta = std::acos(this->r.z() / r); // polar angle (colatitude)
199 Real phi = std::atan2(this->r.y(), this->r.x()); // azimuthal angle
200 return Vector3(r, theta, phi);
201 }
202
203
204 }; // struct Cartesian
205
206 /*\
207 | _ __ _ _
208 | | |/ /___ _ __ | | ___ _ __(_) __ _ _ __
209 | | ' // _ \ '_ \| |/ _ \ '__| |/ _` | '_ \
210 | | . \ __/ |_) | | __/ | | | (_| | | | |
211 | |_|\_\___| .__/|_|\___|_| |_|\__,_|_| |_|
212 | |_|
213 \*/
214
230 {
236
241
250 Keplerian(Real const t_a, Real const t_e, Real const t_i, Real const t_Omega, Real const t_omega)
251 : a(t_a), e(t_e), i(t_i), Omega(t_Omega), omega(t_omega)
252 {}
253
259 Keplerian(Vector5 const & t_kepl)
260 : a(t_kepl(0)), e(t_kepl(1)), i(t_kepl(2)), Omega(t_kepl(3)), omega(t_kepl(4))
261 {}
262
266 Keplerian(Keplerian const &) = default;
267
271 Keplerian(Keplerian &&) = default;
272
276 Keplerian & operator=(const Keplerian &) = default;
277
282
288 {
289 Vector5 vec;
290 vec << this->a, this->e, this->i, this->Omega, this->omega;
291 return vec;
292 }
293
298 std::string info() const {
299 std::ostringstream os;
300 os <<
301 "a : semi-major axis = " << this->a << " (UA)" << std::endl <<
302 "e : eccentricity = " << this->e << " (-)" << std::endl <<
303 "i : inclination = " << this->i << " (rad) = " << Rad_To_Deg(this->i) << " (deg)" << std::endl <<
304 "Ω : right ascension … = " << this->Omega << " (rad) = " << Rad_To_Deg(this->Omega) << " (deg)" << std::endl <<
305 "ω : arg. of periapsis = " << this->omega << " (rad) = " << Rad_To_Deg(this->omega) << " (deg)" << std::endl;
306 return os.str();
307 }
308
313 void info(std::ostream & os) {os << this->info();}
314
318 void reset() {
319 this->a = QUIET_NAN;
320 this->e = QUIET_NAN;
321 this->i = QUIET_NAN;
322 this->Omega = QUIET_NAN;
323 this->omega = QUIET_NAN;
324 }
325
333 bool sanity_check() const
334 {
335 #define CMD "Astro::OrbitalElements::Keplerian::sanity_check(...): "
336
337 if (!std::isfinite(this->a) && this->a > 0.0) {
338 ASTRO_WARNING(CMD "invalid semi-major axis, a = " << this->a << ".");
339 return false;
340 }
341 if (!std::isfinite(this->e) && this->e > 0.0 && this->e < 1.0) {
342 ASTRO_WARNING(CMD "invalid eccentricity, e = " << this->e << ".");
343 return false;
344 }
345 if (!std::isfinite(this->i)) {
346 ASTRO_WARNING(CMD "invalid inclination, i = " << this->i << ".");
347 return false;
348 }
349 if (!std::isfinite(this->Omega)) {
350 ASTRO_WARNING(CMD "invalid right ascension of the ascending node, Ω = " << this->Omega << ".");
351 return false;
352 }
353 if (!std::isfinite(this->omega)) {
354 ASTRO_WARNING(CMD "invalid argument of periapsis, ω = " << this->omega << ".");
355 return false;
356 }
357 ASTRO_ASSERT_WARNING(this->is_nonsingular(), CMD "singular orbit detected.");
358 return true;
359
360 #undef CMD
361 }
362
370 bool is_singular(Real tol_i = EPSILON_LOW, Real tol_e = EPSILON_LOW) const
371 {
372 #define CMD "Astro::OrbitalElements::Keplerian::is_singular(...): "
373
374 Real i{AngleInRange(this->i)};
375 if (std::abs(i) < tol_i && std::abs(i - PI) < tol_i) {
376 ASTRO_WARNING(CMD "singular inclination detected.");
377 return true;
378 }
379 if (std::abs(this->e) < tol_e || std::abs(this->e - 1.0) < tol_e) {
380 ASTRO_WARNING(CMD "singular eccentricity detected.");
381 return true;
382 }
383 return false;
384
385 #undef CMD
386 }
387
395 bool is_nonsingular(Real tol_i = EPSILON_LOW, Real tol_e = EPSILON_LOW) const
396 {
397 return !this->is_singular(tol_i, tol_e);
398 }
399
404 Real u() const {return this->omega + this->Omega;}
405
410 Real p() const {return this->a * (1.0 - this->e * this->e);}
411
412 }; // struct Keplerian
413
414 /*\
415 | _____ _ _ _ _
416 | | ____|__ _ _ _(_)_ __ ___ ___| |_(_) __ _| |
417 | | _| / _` | | | | | '_ \ / _ \ / __| __| |/ _` | |
418 | | |__| (_| | |_| | | | | | (_) | (__| |_| | (_| | |
419 | |_____\__, |\__,_|_|_| |_|\___/ \___|\__|_|\__,_|_|
420 | |_|
421 \*/
422
439 {
445
446 public:
451
460 Equinoctial(Real const t_p, Real const t_f, Real const t_g, Real const t_h, Real const t_k)
461 : p(t_p), f(t_f), g(t_g), h(t_h), k(t_k) {}
462
468 Equinoctial(Vector5 const & t_equi)
469 : p(t_equi(0)), f(t_equi(1)), g(t_equi(2)), h(t_equi(3)), k(t_equi(4))
470 {}
471
475 Equinoctial(Equinoctial const &) = default;
476
481
485 Equinoctial & operator=(const Equinoctial &) = default;
486
491
496 Vector5 vector() const {
497 Vector5 vec;
498 vec << this->p, this->f, this->g, this->h, this->k;
499 return vec;
500 }
501
506 std::string info() const {
507 std::ostringstream os;
508 os <<
509 "p : semi-latus rectum = " << this->p << " (UA)" << std::endl <<
510 "f : x-axis ecc. vector = " << this->f << " (-)" << std::endl <<
511 "g : y-axis ecc. vector = " << this->g << " (-)" << std::endl <<
512 "h : x-axis node vector = " << this->h << " (-)" << std::endl <<
513 "k : y-axis node vector = " << this->k << " (-)" << std::endl;
514 return os.str();
515 }
516
521 void info(std::ostream & os) {os << this->info();}
522
526 void reset() {
527 this->p = QUIET_NAN;
528 this->f = QUIET_NAN;
529 this->g = QUIET_NAN;
530 this->h = QUIET_NAN;
531 this->k = QUIET_NAN;
532 }
533
538 bool sanity_check() const
539 {
540 #define CMD "Astro::OrbitalElements::Keplerian::sanity_check(...): "
541
542 if (!std::isfinite(this->p) && this->p > 0.0) {
543 ASTRO_WARNING(CMD "invalid semi-latus rectum, p = " << this->p << ".");
544 return false;
545 }
546 if (!std::isfinite(this->f)) {
547 ASTRO_WARNING(CMD "invalid x-axis component of the eccentricity vector, f = " << this->f << ".");
548 return false;
549 }
550 if (!std::isfinite(this->g)) {
551 ASTRO_WARNING(CMD "invalid y-axis component of the eccentricity vector, g = " << this->g << ".");
552 return false;
553 }
554 if (!std::isfinite(this->h)) {
555 ASTRO_WARNING(CMD "invalid x-axis component of the node vector, h = " << this->h << ".");
556 return false;
557 }
558 if (!std::isfinite(this->k)) {
559 ASTRO_WARNING(CMD "invalid y-axis component of the node vector, k = " << this->k << ".");
560 return false;
561 }
562
563 // Check if it is singular
564 ASTRO_ASSERT_WARNING(this->is_nonsingular(), CMD "singular orbit detected.");
565
566 return true;
567
568 #undef CMD
569 }
570
577 bool is_singular(Real tol_i = EPSILON_LOW) const
578 {
579 #define CMD "Astro::OrbitalElements::Keplerian::is_singular(...): "
580
581 Real i{AngleInRange(this->i())};
582 if (i < PI + tol_i && i > PI - tol_i) {
583 ASTRO_WARNING(CMD "singular inclination detected.");
584 return true;
585 }
586 return false;
587
588 #undef CMD
589 }
590
596 bool is_nonsingular(Real tol_i = EPSILON_LOW) const
597 {
598 return !this->is_singular(tol_i);
599 }
600
607 Real u(Real L) const
608 {
609 Real s_L{std::sin(L)}, c_L{std::cos(L)};
610 return std::atan2(this->h*s_L - this->k*c_L, this->h*c_L + this->k*s_L);
611 }
612
617 Real a() const {return this->p / (1.0 - this->f*this->f - this->g*this->g);}
618
623 Real e() const {return std::sqrt(this->f*this->f + this->g*this->g);}
624
629 Real i() const
630 {
631 Real h2{this->h * this->h}, k2{this->k * this->k};
632 return std::atan2(2.0*std::sqrt(h2 + k2), 1.0 - h2 - k2);
633 }
634
639 Real omega() const
640 {
641 return std::atan2(
642 this->g*this->h - this->f*this->k,
643 this->f*this->h + this->g*this->k
644 );
645 }
646
651 Real Omega() const {return std::atan2(this->k, this->h);}
652
653 }; // struct Equinoctial
654
655
656 /*\
657 | ___ _ _ _
658 | / _ \ _ _ __ _| |_ ___ _ __ _ __ (_) ___ _ __ (_) ___
659 | | | | | | | |/ _` | __/ _ \ '__| '_ \| |/ _ \| '_ \| |/ __|
660 | | |_| | |_| | (_| | || __/ | | | | | | (_) | | | | | (__
661 | \__\_\\__,_|\__,_|\__\___|_| |_| |_|_|\___/|_| |_|_|\___|
662 |
663 \*/
664
676 {
678
683
688 Quaternionic(Quaternion const &t_q) : q(t_q) {}
689
697 Quaternionic(Real const t_q_1, Real const t_q_2, Real const t_q_3, Real const t_q_4)
698 : q(t_q_1, t_q_2, t_q_3, t_q_4) {}
699
703 Quaternionic(Quaternionic const &) = default;
704
709
713 Quaternionic & operator=(const Quaternionic &) = default;
714
719
724 Vector4 vector() const {
725 Vector4 vec;
726 vec << this->q.x(), this->q.y(), this->q.z(), this->q.w();
727 return vec;
728 }
729
735 Rotation r;
736 r << 1.0 - 2.0*(q.y()*q.y() + q.z()*q.z()),
737 2.0*(q.x()*q.y() - q.z()*q.w()),
738 2.0*(q.x()*q.z() + q.y()*q.w()),
739 2.0*(q.x()*q.y() + q.z()*q.w()),
740 1.0 - 2.0*(q.x()*q.x() + q.z()*q.z()),
741 2.0*(q.y()*q.z() - q.x()*q.w()),
742 2.0*(q.x()*q.z() - q.y()*q.w()),
743 2.0*(q.y()*q.z() + q.x()*q.w()),
744 1.0 - 2.0*(q.x()*q.x() + q.y()*q.y());
745 return r;
746 }
747
752 std::string info() const {
753 std::ostringstream os;
754 os <<
755 "q¹ : 1st parameter = " << this->q.x() << " (-)" << std::endl <<
756 "q² : 2nd parameter = " << this->q.y() << " (-)" << std::endl <<
757 "q³ : 3rd parameter = " << this->q.z() << " (-)" << std::endl <<
758 "q⁴ : 4th parameter = " << this->q.w() << " (-)" << std::endl;
759 return os.str();
760 }
761
766 void info(std::ostream & os) {os << this->info();}
767
771 void reset() {this->q = NAN_VEC4;}
772
777 bool sanity_check() const
778 {
779 #define CMD "Astro::OrbitalElements::Quaternionic::sanity_check(...): "
780
781 if (!(std::isfinite(this->q.x()) && std::isfinite(this->q.y()) &&
782 std::isfinite(this->q.z()) && std::isfinite(this->q.w()))) {
783 ASTRO_WARNING(CMD "invalid quaternionic orbital elements.");
784 return false;
785 }
786 return true;
787
788 #undef CMD
789 }
790
791 }; // struct Quaternionic
792
805 Real nu_to_M(Real const nu, Real const e)
806 {
807 Real beta{(1.0 + std::sqrt(1.0 - e*e)) / e};
808 return AngleInRange(nu - 2.0 * std::atan(std::sin(nu) / (beta + std::cos(nu))) -
809 (e * std::sqrt(1.0 - e*e) * std::sin(nu)) / (1.0 + e * std::cos(nu)));
810 }
811
824 Real nu_to_M(Real const nu, Keplerian const & kepl) {return nu_to_M(nu, kepl.e);}
825
838 Real nu_to_E(Real const nu, Keplerian const & kepl)
839 {
840 Real beta{(1.0 + std::sqrt(1.0 - kepl.e*kepl.e)) / kepl.e};
841 return AngleInRange(nu - 2.0 * std::atan(std::sin(nu) / (beta + std::cos(nu))));
842 }
843
852 Real nu_to_L(Real const nu, Keplerian const & kepl, Factor const I)
853 {
854 return AngleInRange(nu + kepl.omega + kepl.Omega*static_cast<Real>(I));
855 }
856
865 Real M_to_E(Real M, Real const e)
866 {
867 #define CMD "Astro::OrbitalElements::Anomaly::M_to_E(...): "
868
869 // Clamp the mean anomaly in the range [0, 2\pi]
870 M = AngleInRange(M);
871
872 // Solve Kepler equation through a basic Newton method
873 Real dE{0.0}, E{M};
874 for (Integer k{0}; k < 100; ++k)
875 {
876 dE = (E - e * std::sin(E) - M) / (1.0 - e * std::cos(E));
877 // Saturate if steps are too largex
878 E -= std::max(std::min(dE, 0.1), -0.1);
879 // Break if the error is small enough
880 if (std::abs(dE) < EPSILON_HIGH || std::abs(E) < EPSILON_HIGH) {break;}
881 }
882
883 ASTRO_ASSERT(std::abs(dE) < EPSILON_HIGH, CMD "convergence not reached: E = " << E <<
884 ", dE = " << dE << ", M = " << M << ", e = " << e << ".");
885
886 return AngleInRange(E);
887
888 #undef CMD
889 }
890
899 Real M_to_E(Real M, Keplerian const & kepl)
900 {
901 return M_to_E(M, kepl.e);
902 }
903
914 Real M_to_H(Real const M, Keplerian const & kepl)
915 {
916
917 #define CMD "Astro::OrbitalElements::Anomaly::M_to_H(...): "
918
919 // Solve Kepler equation through a basic Newton method
920 Real e{kepl.e}, abs_M{M > 0 ? M : -M};
921 Real dH{0.0}, H{5.0*e-2.5 > abs_M ? std::pow(6.0*abs_M/e, 1.0/3.0) : std::log(2.0*abs_M/e)};
922 for (Integer k{0}; k < 100; ++k)
923 {
924 dH = (e * std::sinh(H) - H - abs_M) / (e * std::cosh(H) - 1.0);
925 H -= dH;
926 // Break if the error is small enough
927 if (std::abs(dH) < EPSILON_MEDIUM || std::abs(H) < EPSILON_MEDIUM) {break;}
928 }
929
930 ASTRO_ASSERT(std::abs(dH) < EPSILON_MEDIUM, CMD "convergence not reached: H = " << H <<
931 ", dH = " << dH << ", M = " << M << ", e = " << e << ".");
932
933 return AngleInRange(H > 0 ? H : -H); // Return the positive value
934
935 #undef CMD
936 }
937
946 Real M_to_lambda(Real const M, Keplerian const & kepl, Factor const I)
947 {
948 return AngleInRange(M + kepl.omega + kepl.Omega*static_cast<Real>(I));
949 }
950
963 Real E_to_nu(Real const E, Real const e)
964 {
965 Real beta{(1.0 + std::sqrt(1.0 - e*e)) / e};
966 return AngleInRange(E + 2.0 * std::atan(std::sin(E) / (beta - std::cos(E))));
967 }
968
981 Real E_to_nu(Real const E, Keplerian const & kepl)
982 {
983 return E_to_nu(E, kepl.e);
984 }
985
993 Real E_to_M(Real const E, Real const e)
994 {
995 return AngleInRange(E - e * std::sin(E));
996 }
997
1005 Real E_to_M(Real const E, Keplerian const & kepl)
1006 {
1007 return E_to_M(E, kepl.e);
1008 }
1009
1020 Real H_to_nu(Real const H, Keplerian const & kepl)
1021 {
1022 return AngleInRange(2.0*std::atan(std::sqrt((kepl.e+1.0)/(kepl.e-1.0)) * std::tanh(H/2.0)));
1023 }
1024
1032 Real H_to_M(Real const H, Keplerian const & kepl)
1033 {
1034 return AngleInRange(kepl.e * std::sinh(H) - H);
1035 }
1036
1045 Real L_to_nu(Real const L, Keplerian const & kepl, Factor const I)
1046 {
1047 return AngleInRange(L - kepl.omega - kepl.Omega*static_cast<Real>(I));
1048 }
1049
1058 Real L_to_lambda(Real const L, Real const nu, Real const M)
1059 {
1060 return AngleInRange(L - nu + M);
1061 }
1062
1071 Real lambda_to_M(Real const lambda, Keplerian const & kepl, Factor const I)
1072 {
1073 return AngleInRange(lambda - kepl.omega - static_cast<Real>(I)*kepl.Omega);
1074 }
1075
1084 Real lambda_to_L(Real const lambda, Real const nu, Real const M)
1085 {
1086 return AngleInRange(lambda + nu - M);
1087 }
1088
1089 /*\
1090 | _ _
1091 | / \ _ __ ___ _ __ ___ __ _| |_ _
1092 | / _ \ | '_ \ / _ \| '_ ` _ \ / _` | | | | |
1093 | / ___ \| | | | (_) | | | | | | (_| | | |_| |
1094 | /_/ \_\_| |_|\___/|_| |_| |_|\__,_|_|\__, |
1095 | |___/
1096 \*/
1097
1109 struct Anomaly
1110 {
1111 Real nu{0.0};
1112 Real M{0.0};
1113 Real E{0.0};
1114 Real H{0.0};
1115 Real L{0.0};
1117
1122
1126 Anomaly(Anomaly const &) = default;
1127
1131 Anomaly(Anomaly &&) = default;
1132
1136 Anomaly & operator=(const Anomaly &) = default;
1137
1141 Anomaly & operator=(Anomaly &&) = default;
1142
1150 template<bool Hyperbolic = false>
1151 void set_nu(Real t_nu, Keplerian const & kepl, Factor const I)
1152 {
1153 t_nu = AngleInRange(t_nu);
1154 kepl.sanity_check();
1155 this->nu = t_nu;
1156 this->M = nu_to_M(this->nu, kepl);
1157 this->E = nu_to_E(this->nu, kepl);
1158 this->L = nu_to_L(this->nu, kepl, I);
1159 this->lambda = M_to_lambda(this->M, kepl, I);
1160 this->H = QUIET_NAN;
1161 if constexpr (Hyperbolic) {this->H = M_to_H(this->M, kepl);}
1162 }
1163
1164
1172 template<bool Hyperbolic = false>
1173 void set_M(Real t_M, Keplerian const & kepl, Factor const I)
1174 {
1175 t_M = AngleInRange(t_M);
1176 kepl.sanity_check();
1177 this->E = M_to_E(t_M, kepl);
1178 this->nu = E_to_nu(this->E, kepl);
1179 this->M = t_M;
1180 this->L = nu_to_L(this->nu, kepl, I);
1181 this->lambda = M_to_lambda(this->M, kepl, I);
1182 this->H = QUIET_NAN;
1183 if constexpr (Hyperbolic) {this->H = M_to_H(this->M, kepl);}
1184 }
1185
1199 template<bool Hyperbolic = false>
1200 void set_E(Real t_E, Keplerian const & kepl, Factor const I)
1201 {
1202 t_E = AngleInRange(t_E);
1203 kepl.sanity_check();
1204 this->nu = E_to_nu(t_E, kepl);
1205 this->M = E_to_M(t_E, kepl);
1206 this->E = t_E;
1207 this->L = nu_to_L(this->nu, kepl, I);
1208 this->lambda = M_to_lambda(this->M, kepl, I);
1209 this->H = QUIET_NAN;
1210 if constexpr (Hyperbolic) {this->H = M_to_H(this->M, kepl);}
1211 }
1212
1223 template<bool Hyperbolic = false>
1224 void set_L(Real t_L, Keplerian const & kepl, Factor const I)
1225 {
1226 #define CMD "Astro::OrbitalElements::Anomaly::L(...): "
1227
1228 t_L = AngleInRange(t_L);
1229 this->set_nu<Hyperbolic>(L_to_nu(t_L, kepl, I) , kepl, I);
1230
1231 ASTRO_ASSERT(std::abs(this->L - t_L) < EPSILON_MEDIUM || std::abs(this->L - t_L - PIMUL2) < EPSILON_MEDIUM,
1232 CMD "conversion error, L = " << t_L << " ≠ " << this->L << ".");
1233
1234 #undef CMD
1235 }
1236
1247 template<bool Hyperbolic = false>
1248 void set_lambda(Real t_lambda, Keplerian const & kepl, Factor const I)
1249 {
1250 #define CMD "Astro::OrbitalElements::Anomaly::lambda(...): "
1251
1252 t_lambda = AngleInRange(t_lambda);
1253 this->set_M<Hyperbolic>(lambda_to_M(t_lambda, kepl, I), kepl, I);
1254
1255 ASTRO_ASSERT(std::abs(this->lambda - t_lambda) < EPSILON_HIGH,
1256 CMD "conversion error, lambda = " << t_lambda << " ≠ " << this->lambda << ".");
1257
1258 #undef CMD
1259 }
1260
1270 void set_H(Real const t_H, Keplerian const & kepl, Factor const I)
1271 {
1272 #define CMD "Astro::OrbitalElements::Anomaly::H(...): "
1273
1274 this->set_nu<true>(H_to_nu(t_H, kepl), kepl, I);
1275
1276 ASTRO_ASSERT(std::abs(this->H - t_H) < EPSILON_HIGH,
1277 CMD "conversion error, H = " << t_H << " ≠ " << this->H << ".");
1278
1279 #undef CMD
1280 }
1281
1286 std::string info() const {
1287 std::ostringstream os;
1288 os <<
1289 "v : true anomaly = " << this->nu << " (rad) = " << Rad_To_Deg(this->nu) << " (deg)" << std::endl <<
1290 "M : mean anomaly = " << this->M << " (rad) = " << Rad_To_Deg(this->M) << " (deg)" << std::endl <<
1291 "E : eccentric anomaly = " << this->E << " (rad) = " << Rad_To_Deg(this->E) << " (deg)" << std::endl <<
1292 "L : true longitude = " << this->L << " (rad) = " << Rad_To_Deg(this->L) << " (deg)" << std::endl <<
1293 "λ : mean longitude = " << this->lambda << " (rad) = " << Rad_To_Deg(this->lambda) << " (deg)" << std::endl <<
1294 "H : hyperbolic anomaly = " << this->H << " (rad) = " << Rad_To_Deg(this->H) << " (deg)" << std::endl;
1295 return os.str();
1296 }
1297
1302 void info(std::ostream & os) {os << this->info();}
1303
1307 void reset()
1308 {
1309 this->nu = QUIET_NAN;
1310 this->M = QUIET_NAN;
1311 this->E = QUIET_NAN;
1312 this->L = QUIET_NAN;
1313 this->lambda = QUIET_NAN;
1314 this->H = QUIET_NAN;
1315 }
1316
1322 template<bool Hyperbolic = false>
1323 bool sanity_check() const
1324 {
1325 #define CMD "Astro::OrbitalElements::Anomaly::sanity_check(...): "
1326
1327 if (!(std::isfinite(this->nu))) {
1328 ASTRO_ERROR(CMD "invalid true anomaly.");
1329 return false;
1330 }
1331 if (!(std::isfinite(this->M))) {
1332 ASTRO_ERROR(CMD "invalid mean anomaly.");
1333 return false;
1334 }
1335 if (!(std::isfinite(this->E))) {
1336 ASTRO_ERROR(CMD "invalid eccentric anomaly.");
1337 return false;
1338 }
1339 if (!(std::isfinite(this->L))) {
1340 ASTRO_ERROR(CMD "invalid true longitude.");
1341 return false;
1342 }
1343 if (!(std::isfinite(this->lambda))) {
1344 ASTRO_ERROR(CMD "invalid mean longitude.");
1345 return false;
1346 }
1347 if constexpr (Hyperbolic) {
1348 if (!(std::isfinite(this->H))) {
1349 ASTRO_ERROR(CMD "invalid hyperbolic anomaly.");
1350 return false;
1351 }
1352 }
1353 return true;
1354
1355 #undef CMD
1356 }
1357
1358 }; // struct Anomaly
1359
1367 Real cartesian_to_keplerian(Cartesian const & cart, Real const mu, Keplerian & kepl)
1368 {
1369 #define CMD "Astro::OrbitalElements::cartesian_to_keplerian(...): "
1370
1371 // Reset the keplerian orbital elements
1372 kepl.reset();
1373
1374 // Retrieve the position and velocity vectors
1375 Vector3 const & r{cart.r};
1376 Vector3 const & v{cart.v};
1377 Real r_norm{r.norm()};
1378
1379 // Compute the orbital momentum vector
1380 Vector3 h_vec{cart.h()};
1381 Real r_dot_v{r.dot(v)};
1382
1383 // Compute the eccentricity
1384 Vector3 e_vec{1.0/mu*((v.squaredNorm() - mu/r_norm)*r - r_dot_v*v)};
1385 Real e{e_vec.norm()};
1386
1387 // Determine the vector pointing towards the ascending node
1388 Vector3 n_vec{(Vector3::UnitZ().cross(h_vec)).normalized()};
1389
1390 // Compute the inclination
1391 Real i{std::acos(h_vec.z() / h_vec.norm())};
1392
1393 // Set the node vector to the x-axis if the orbit is circular
1394 if (std::abs(i) < EPSILON_LOW || std::abs(i - PI) < EPSILON_LOW) {n_vec << 1.0, 0.0, 0.0;}
1395
1396 // Compute the longitude of the ascending node
1397 Real Omega{std::acos(n_vec.x())};
1398 if (n_vec.y() < 0.0) {Omega = 2.0*PI - Omega;}
1399
1400 // Compute the argument of the periapsis
1401 Real omega{std::acos(n_vec.dot(e_vec)/e)};
1402 if (e_vec.z() < 0.0) {omega = 2.0*PI - omega;}
1403
1404 // Compute the true anomaly
1405 Real nu{std::acos(e_vec.dot(r) / (e * r_norm))};
1406 if (r_dot_v < 0.0) {nu = 2.0*PI - nu;}
1407
1408 if (std::abs(e) < EPSILON_LOW) {omega = nu = 0.0;}
1409
1410 // Compute the semi-major axis
1411 Real a{1.0 / (2.0/r_norm - v.squaredNorm()/mu)};
1412
1413 // Assign the keplerian orbital elements
1414 kepl.a = a;
1415 kepl.e = e;
1416 kepl.i = i;
1417 kepl.Omega = Omega;
1418 kepl.omega = omega;
1419
1420 ASTRO_ASSERT(kepl.sanity_check(), CMD "conversion error.");
1421
1422 return nu;
1423
1424 #undef CMD
1425 }
1426
1434 void keplerian_to_cartesian(Keplerian const & kepl, Real const nu, Real const mu, Cartesian & cart)
1435 {
1436 #define CMD "Astro::OrbitalElements::keplerian_to_cartesian(...): "
1437
1438 // Reset the cartesian state vectors
1439 cart.reset();
1440
1441 // Retrieve some keplerian orbital elements
1442 Real const & e{kepl.e};
1443 Real const & i{kepl.i};
1444 Real const & Omega{kepl.Omega};
1445 Real const & omega{kepl.omega};
1446
1447 // Compute the semi-latus rectum
1448 Real p{kepl.p()};
1449
1450 // Compute the distance to the central body
1451 Real r{p/(1.0 + e*std::cos(nu))};
1452
1453 // Position and velocity vectors in the perifocal coordinate system
1454 Vector3 r_vec(r*std::cos(nu), r*std::sin(nu), 0.0);
1455 Vector3 v_vec(-std::sin(nu), e + std::cos(nu), 0.0);
1456 v_vec *= std::sqrt(mu/p);
1457
1458 // Rotation matrices for the transformation from the perifocal to the inertial frame
1459 Matrix3 R_z, R_i, R_h, R;
1460 R_z << std::cos(Omega), std::sin(Omega), 0.0,
1461 -std::sin(Omega), std::cos(Omega), 0.0,
1462 0.0, 0.0, 1.0;
1463 R_i << 1.0, 0.0, 0.0,
1464 0.0, std::cos(i), std::sin(i),
1465 0.0, -std::sin(i), std::cos(i);
1466 R_h << std::cos(omega), std::sin(omega), 0.0,
1467 -std::sin(omega), std::cos(omega), 0.0,
1468 0.0, 0.0, 1.0;
1469 R = (R_h*R_i*R_z).transpose(); // Transpose to convert from column-major to row-major
1470
1471 // Obtain the position and velocity vector r_of and v_of in the orbital frame
1472 cart.r = R*r_vec;
1473 cart.v = R*v_vec;
1474
1475 ASTRO_ASSERT(cart.sanity_check(), CMD "conversion error.");
1476
1477 #undef CMD
1478 }
1479
1487 void equinoctial_to_cartesian(Equinoctial const & equi, Real const L, Real const mu,
1488 Cartesian & cart)
1489 {
1490 #define CMD "Astro::OrbitalElements::equinoctial_to_cartesian(...): "
1491
1492 // Reset the cartesian state vectors
1493 cart.reset();
1494
1495 // Retrieve the equinoctial orbital elements
1496 Real const & f{equi.f};
1497 Real const & g{equi.g};
1498 Real const & h{equi.h};
1499 Real const & k{equi.k};
1500 Real const & p{equi.p};
1501
1502 // Compute the distance to the central body
1503 Real c_L{std::cos(L)}, s_L{std::sin(L)};
1504 Real alpha_2{h*h - k*k};
1505 Real s_2{1.0 + h*h + k*k};
1506 Real w{1.0 + f*c_L + g*s_L};
1507 Real r_c{p / w};
1508
1509 // Compute the position and velocity vectors in the inertial frame
1510 Real tmp{r_c/s_2};
1511 cart.r <<
1512 tmp * (c_L + alpha_2*c_L + 2.0*h*k*s_L),
1513 tmp * (s_L - alpha_2*s_L + 2.0*h*k*c_L),
1514 2.0*tmp * (h*s_L - k*c_L);
1515
1516 tmp = -1.0/s_2 * std::sqrt(mu/p);
1517 cart.v <<
1518 tmp * ( s_L + alpha_2*s_L - 2.0*h*k*c_L + g - 2.0*f*h*k + alpha_2*g),
1519 tmp * (-c_L + alpha_2*c_L + 2.0*h*k*s_L - f + 2.0*g*h*k - alpha_2*f),
1520 2.0*tmp * (-h*c_L - k*s_L + f*h - g*k);
1521
1522 ASTRO_ASSERT(cart.sanity_check(), CMD "conversion error.");
1523
1524 #undef CMD
1525 }
1526
1533 void keplerian_to_equinoctial(Keplerian const & kepl, Factor const I, Equinoctial & equi)
1534 {
1535 #define CMD "Astro::OrbitalElements::keplerian_to_equinoctial(...): "
1536
1537 // Reset the equinoctial orbital elements
1538 equi.reset();
1539
1540 // Retrieve the keplerian orbital elements
1541 Real const & e{kepl.e};
1542 Real const & i{kepl.i};
1543 Real const & Omega{kepl.Omega};
1544 Real const & omega{kepl.omega};
1545
1546 // Compute the semi-latus rectum
1547 equi.p = kepl.p();
1548
1549 // Compute the x-axis component of the eccentricity vector in the orbital frame f
1550 Real omega_plus_Omega{omega + static_cast<Real>(I)*Omega};
1551 equi.f = e*std::cos(omega_plus_Omega);
1552
1553 // Compute the y-axis component of the eccentricity vector in the orbital frame g
1554 equi.g = e*std::sin(omega_plus_Omega);
1555
1556 // Compute the x- and y-axis components of the node vector in the orbital frame h
1557 Real tmp{std::tan(i/2.0)};
1558 if (I == Factor::RETROGRADE) {tmp = 1.0/tmp;} // 1/tan(x) = cot(x)
1559 equi.h = tmp*std::cos(Omega);
1560 equi.k = tmp*std::sin(Omega);
1561
1562 ASTRO_ASSERT(equi.sanity_check(), CMD "conversion error.");
1563
1564 #undef CMD
1565 }
1566
1577 {
1578 #define CMD "Astro::OrbitalElements::cartesian_to_equinoctial(...): "
1579
1580 // Reset the equinoctial orbital elements
1581 equi.reset();
1582
1583 // Retrieve the cartesian state vectors
1584 Vector3 const & r{cart.r};
1585 Vector3 const & v{cart.v};
1586
1587 // Compute the equinoctial orbital elements
1588 Real r_dot_v{r.dot(v)};
1589 Real r_norm{r.norm()};
1590 Vector3 r_unit(r.normalized());
1591
1592 Vector3 hvec(r.cross(v));
1593 Real h_norm{hvec.norm()};
1594 Vector3 h_unit(hvec.normalized());
1595
1596 Vector3 v_unit((r_norm*v - r_dot_v*r_unit)/h_norm);
1597
1598 Real p{h_norm*h_norm/mu};
1599
1600 Real k{h_unit.x()/(1.0 + h_unit.z())};
1601 Real h{-h_unit.y()/(1.0 + h_unit.z())};
1602
1603 Real kk{k*k};
1604 Real hh{h*h};
1605 Real s2{1.0 + hh + kk};
1606 Real tkh{2.0*k*h};
1607
1608 Vector3 ecc(v.cross(hvec)/mu - r_unit);
1609
1610 Vector3 f_unit(1.0 - kk + hh, tkh, -2.0*k);
1611 Vector3 g_unit(tkh, 1.0 + kk - hh, 2.0*h);
1612
1613 // Normalize the f and g vectors
1614 f_unit /= s2;
1615 g_unit /= s2;
1616
1617 Real f{ecc.dot(f_unit)};
1618 Real g{ecc.dot(g_unit)};
1619
1620 Real L{std::atan2(r_unit.y() - v_unit.x(), r_unit.x() + v_unit.y())};
1621
1622 // Assign the equinoctial orbital elements
1623 equi.p = p;
1624 equi.f = f;
1625 equi.g = g;
1626 equi.h = h;
1627 equi.k = k;
1628
1629 ASTRO_ASSERT(equi.sanity_check(), CMD "conversion error.");
1630
1631 // Return the true longitude
1632 return L;
1633
1634 #undef CMD
1635 }
1636
1645 void equinoctial_to_cartesian(Equinoctial const & equi, Real const L, Factor const I, Real const mu,
1646 Cartesian & cart)
1647 {
1648 #define CMD "Astro::OrbitalElements::equinoctial_to_cartesian(...): "
1649
1650 // Reset the cartesian state vectors
1651 cart.reset();
1652
1653 // Retrieve the equinoctial orbital elements
1654 Real p{equi.p};
1655 Real f{equi.f};
1656 Real g{equi.g};
1657 Real h{equi.h};
1658 Real k{equi.k};
1659
1660 // Compute the distance to the central body
1661 Real c_L{std::cos(L)}, s_L{std::sin(L)};
1662 Real h2{h*h}, k2{k*k}, hk{h*k};
1663 Real bf{p / ((1.0+f*c_L+g*s_L) * (1.0+h2+k2))};
1664 Real x{bf*c_L}, y{bf*s_L};
1665 Real bf1{std::sqrt(mu/p) / (1.0+h2+k2)};
1666 Real c_Lf{bf1 * (c_L+f)};
1667 Real s_Lg{bf1 * (s_L+g)};
1668
1669 // Compute the position and velocity vectors in the inertial frame
1670 cart.r <<
1671 (1.0+h2-k2)*x + 2.0*static_cast<Real>(I)*hk*y,
1672 static_cast<Real>(I)*(1.0-h2+k2)*y + 2.0*hk*x,
1673 2.0*(h*y-static_cast<Real>(I)*k*x);
1674 cart.v <<
1675 static_cast<Real>(I)*2.0*hk*c_Lf - (1.0+h2-k2)*s_Lg,
1676 static_cast<Real>(I)*(1.0-h2+k2)*c_Lf - 2.0*hk*s_Lg,
1677 2.0*(h*c_Lf + static_cast<Real>(I)*k*s_Lg);
1678
1679 ASTRO_ASSERT(cart.sanity_check(), CMD "conversion error.");
1680
1681 #undef CMD
1682 }
1683
1691 {
1692 #define CMD "Astro::OrbitalElements::equinoctial_to_keplerian(...): "
1693
1694 // Reset the keplerian orbital elements
1695 kepl.reset();
1696
1697 // Assign the keplerian orbital elements
1698 kepl.a = equi.a();
1699 kepl.e = equi.e();
1700 kepl.i = equi.i();
1701 kepl.Omega = equi.Omega();
1702 kepl.omega = equi.omega();
1703
1704 ASTRO_ASSERT(kepl.sanity_check(), CMD "conversion error.");
1705
1706 #undef CMD
1707 }
1708
1709 } // namespace OrbitalElements
1710
1711} // namespace Astro
1712
1713#endif // ASTRO_ORBITALELEMENTS_HH
#define ASTRO_ASSERT(COND, MSG)
Definition Astro.hh:43
#define ASTRO_WARNING(MSG)
Definition Astro.hh:52
#define ASTRO_ERROR(MSG)
Definition Astro.hh:32
#define ASTRO_ASSERT_WARNING(COND, MSG)
Definition Astro.hh:60
#define CMD
The namespace for the orbital elements definition and conversion.
Definition OrbitalElements.hh:37
Real E_to_nu(Real const E, Real const e)
Definition OrbitalElements.hh:963
Real E_to_M(Real const E, Real const e)
Definition OrbitalElements.hh:993
Real nu_to_L(Real const nu, Keplerian const &kepl, Factor const I)
Definition OrbitalElements.hh:852
Real cartesian_to_keplerian(Cartesian const &cart, Real const mu, Keplerian &kepl)
Definition OrbitalElements.hh:1367
Real L_to_nu(Real const L, Keplerian const &kepl, Factor const I)
Definition OrbitalElements.hh:1045
Real nu_to_E(Real const nu, Keplerian const &kepl)
Definition OrbitalElements.hh:838
Real M_to_lambda(Real const M, Keplerian const &kepl, Factor const I)
Definition OrbitalElements.hh:946
Real M_to_E(Real M, Real const e)
Definition OrbitalElements.hh:865
Real H_to_M(Real const H, Keplerian const &kepl)
Definition OrbitalElements.hh:1032
void equinoctial_to_keplerian(Equinoctial const &equi, Keplerian &kepl)
Definition OrbitalElements.hh:1690
Real lambda_to_M(Real const lambda, Keplerian const &kepl, Factor const I)
Definition OrbitalElements.hh:1071
Real cartesian_to_equinoctial(Cartesian const &cart, Real const mu, Equinoctial &equi)
Definition OrbitalElements.hh:1576
void keplerian_to_cartesian(Keplerian const &kepl, Real const nu, Real const mu, Cartesian &cart)
Definition OrbitalElements.hh:1434
Real lambda_to_L(Real const lambda, Real const nu, Real const M)
Definition OrbitalElements.hh:1084
void equinoctial_to_cartesian(Equinoctial const &equi, Real const L, Real const mu, Cartesian &cart)
Definition OrbitalElements.hh:1487
Real nu_to_M(Real const nu, Real const e)
Definition OrbitalElements.hh:805
Real H_to_nu(Real const H, Keplerian const &kepl)
Definition OrbitalElements.hh:1020
Real M_to_H(Real const M, Keplerian const &kepl)
Definition OrbitalElements.hh:914
Real L_to_lambda(Real const L, Real const nu, Real const M)
Definition OrbitalElements.hh:1058
void keplerian_to_equinoctial(Keplerian const &kepl, Factor const I, Equinoctial &equi)
Definition OrbitalElements.hh:1533
The namespace for the Astro library.
Definition Astro.hh:73
static Real const PI
Definition Utilities.hh:60
Eigen::Matrix< Real, 3, 3 > Matrix3
Definition Astro.hh:94
Eigen::Quaternion< Real > Quaternion
Definition Astro.hh:112
static Real const EPSILON_HIGH
Definition Astro.hh:130
int Integer
Definition Astro.hh:85
Eigen::Vector< Real, 5 > Vector5
Definition Astro.hh:97
static Vector3 const NAN_VEC3
Definition Astro.hh:152
Eigen::Matrix< Real, 3, 3 > Rotation
Definition Astro.hh:111
static Real const EPSILON_LOW
Definition Astro.hh:132
static Real const QUIET_NAN
Definition Astro.hh:134
Real AngleInRange(Real x)
Definition Utilities.hh:88
Eigen::Vector< Real, 6 > Vector6
Definition Astro.hh:99
Real Rad_To_Deg(Real x)
Definition Utilities.hh:80
static Vector4 const NAN_VEC4
Definition Astro.hh:160
Eigen::Vector< Real, 4 > Vector4
Definition Astro.hh:95
double Real
Definition Astro.hh:84
enum class Type :Integer { UNDEFINED=0, HYPERBOLIC=1, ELLIPTIC=2, CIRCULAR=3, PARABOLIC=4 } Type
Definition OrbitalElements.hh:27
enum class Factor :Integer { POSIGRADE=1, UNDEFINED=0, RETROGRADE=-1 } Factor
Definition OrbitalElements.hh:22
Eigen::Vector< Real, 3 > Vector3
Definition Astro.hh:93
static Real const PIMUL2
Definition Utilities.hh:61
static Real const EPSILON_MEDIUM
Definition Astro.hh:131
void set_H(Real const t_H, Keplerian const &kepl, Factor const I)
Set the hyperbolic anomaly .
Definition OrbitalElements.hh:1270
void info(std::ostream &os)
Definition OrbitalElements.hh:1302
bool sanity_check() const
Definition OrbitalElements.hh:1323
void set_E(Real t_E, Keplerian const &kepl, Factor const I)
Set the eccentric anomaly .
Definition OrbitalElements.hh:1200
std::string info() const
Definition OrbitalElements.hh:1286
Real H
Definition OrbitalElements.hh:1114
Real nu
Definition OrbitalElements.hh:1111
void set_lambda(Real t_lambda, Keplerian const &kepl, Factor const I)
Set the mean longitude .
Definition OrbitalElements.hh:1248
Anomaly()
Definition OrbitalElements.hh:1121
Real lambda
Definition OrbitalElements.hh:1116
void reset()
Definition OrbitalElements.hh:1307
Anomaly & operator=(Anomaly &&)=default
Anomaly & operator=(const Anomaly &)=default
void set_M(Real t_M, Keplerian const &kepl, Factor const I)
Definition OrbitalElements.hh:1173
void set_nu(Real t_nu, Keplerian const &kepl, Factor const I)
Definition OrbitalElements.hh:1151
Anomaly(Anomaly const &)=default
Real E
Definition OrbitalElements.hh:1113
Real L
Definition OrbitalElements.hh:1115
Real M
Definition OrbitalElements.hh:1112
Anomaly(Anomaly &&)=default
void set_L(Real t_L, Keplerian const &kepl, Factor const I)
Set the true longitude .
Definition OrbitalElements.hh:1224
Structure container for the cartesian orbital elements.
Definition OrbitalElements.hh:59
void info(std::ostream &os)
Definition OrbitalElements.hh:140
Cartesian(Cartesian const &)=default
Vector3 v
Definition OrbitalElements.hh:61
void reset()
Definition OrbitalElements.hh:145
Cartesian(Cartesian &&)=default
Cartesian()
Definition OrbitalElements.hh:66
Cartesian & operator=(Cartesian &&)=default
Cartesian(Vector3 const &t_r, Vector3 const &t_v)
Definition OrbitalElements.hh:73
Cartesian(Vector6 const &t_cart)
Definition OrbitalElements.hh:80
bool sanity_check() const
Definition OrbitalElements.hh:153
Vector6 vector() const
Definition OrbitalElements.hh:118
Cartesian(Real r_x, Real r_y, Real r_z, Real v_x, Real v_y, Real v_z)
Definition OrbitalElements.hh:91
Vector3 h() const
Definition OrbitalElements.hh:173
Vector3 r
Definition OrbitalElements.hh:60
std::string info() const
Definition OrbitalElements.hh:128
Cartesian & operator=(const Cartesian &)=default
Struct container for the (modified) equinoctial orbital elements.
Definition OrbitalElements.hh:439
Real Omega() const
Definition OrbitalElements.hh:651
Real h
Definition OrbitalElements.hh:443
Vector5 vector() const
Definition OrbitalElements.hh:496
Real g
Definition OrbitalElements.hh:442
bool is_singular(Real tol_i=EPSILON_LOW) const
Definition OrbitalElements.hh:577
Real a() const
Definition OrbitalElements.hh:617
Equinoctial & operator=(Equinoctial &&)=default
Equinoctial(Vector5 const &t_equi)
Definition OrbitalElements.hh:468
Real omega() const
Definition OrbitalElements.hh:639
Real p
Definition OrbitalElements.hh:440
Real u(Real L) const
Definition OrbitalElements.hh:607
Real e() const
Definition OrbitalElements.hh:623
Real f
Definition OrbitalElements.hh:441
std::string info() const
Definition OrbitalElements.hh:506
bool sanity_check() const
Definition OrbitalElements.hh:538
void reset()
Definition OrbitalElements.hh:526
Real i() const
Definition OrbitalElements.hh:629
void info(std::ostream &os)
Definition OrbitalElements.hh:521
Equinoctial(Real const t_p, Real const t_f, Real const t_g, Real const t_h, Real const t_k)
Definition OrbitalElements.hh:460
Equinoctial(Equinoctial const &)=default
Equinoctial(Equinoctial &&)=default
Equinoctial & operator=(const Equinoctial &)=default
Real k
Definition OrbitalElements.hh:444
Equinoctial()
Definition OrbitalElements.hh:450
bool is_nonsingular(Real tol_i=EPSILON_LOW) const
Definition OrbitalElements.hh:596
Structure container for the (modified) Keplerian orbital elements.
Definition OrbitalElements.hh:230
Keplerian(Keplerian const &)=default
Real i
Definition OrbitalElements.hh:233
Keplerian(Real const t_a, Real const t_e, Real const t_i, Real const t_Omega, Real const t_omega)
Definition OrbitalElements.hh:250
std::string info() const
Definition OrbitalElements.hh:298
Keplerian(Keplerian &&)=default
Real p() const
Definition OrbitalElements.hh:410
Vector5 vector() const
Definition OrbitalElements.hh:287
bool is_nonsingular(Real tol_i=EPSILON_LOW, Real tol_e=EPSILON_LOW) const
Definition OrbitalElements.hh:395
void reset()
Definition OrbitalElements.hh:318
Real omega
Definition OrbitalElements.hh:235
Keplerian(Vector5 const &t_kepl)
Definition OrbitalElements.hh:259
Keplerian & operator=(Keplerian &&)=default
Keplerian & operator=(const Keplerian &)=default
Real e
Definition OrbitalElements.hh:232
Real Omega
Definition OrbitalElements.hh:234
void info(std::ostream &os)
Definition OrbitalElements.hh:313
Real a
Definition OrbitalElements.hh:231
bool sanity_check() const
Definition OrbitalElements.hh:333
Real u() const
Definition OrbitalElements.hh:404
Keplerian()
Definition OrbitalElements.hh:240
bool is_singular(Real tol_i=EPSILON_LOW, Real tol_e=EPSILON_LOW) const
Definition OrbitalElements.hh:370
Quaternionic()
Definition OrbitalElements.hh:682
Quaternionic(Quaternion const &t_q)
Definition OrbitalElements.hh:688
void reset()
Definition OrbitalElements.hh:771
Quaternionic(Quaternionic &&)=default
Vector4 vector() const
Definition OrbitalElements.hh:724
Quaternion q
Definition OrbitalElements.hh:677
Quaternionic & operator=(const Quaternionic &)=default
std::string info() const
Definition OrbitalElements.hh:752
bool sanity_check() const
Definition OrbitalElements.hh:777
Quaternionic & operator=(Quaternionic &&)=default
void info(std::ostream &os)
Definition OrbitalElements.hh:766
Quaternionic(Real const t_q_1, Real const t_q_2, Real const t_q_3, Real const t_q_4)
Definition OrbitalElements.hh:697
Rotation rotation() const
Definition OrbitalElements.hh:734
Quaternionic(Quaternionic const &)=default