Coverage for src/gncpy/dynamics/basic/tschauner_hempel_orbit.py: 18%
61 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-13 06:15 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-13 06:15 +0000
1import numpy as np
2from .nonlinear_dynamics_base import NonlinearDynamicsBase
5class TschaunerHempelOrbit(NonlinearDynamicsBase):
6 """Implements the non-linear Tschauner-Hempel elliptical orbit model.
8 Notes
9 -----
10 It is the general elliptical orbit of an object around another target
11 object as defined in
12 :cite:`Tschauner1965_RendezvousZuEineminElliptischerBahnUmlaufendenZiel`.
13 The states are defined as positions in a
14 Local-Vertical-Local-Horizontal (LVLH) frame. Note, the true anomaly is
15 that of the target object. For more details see
16 :cite:`Okasha2013_GuidanceNavigationandControlforSatelliteProximityOperationsUsingTschaunerHempelEquations`
17 and :cite:`Lange1965_FloquetTheoryOrbitalPerturbations`
19 Attributes
20 ----------
21 mu : float, optional
22 gravitational parameter in :math:`m^3 s^{-2}`. The default is 3.986004418 * 10**14.
23 semi_major : float
24 semi-major axis in meters. The default is None.
25 eccentricity : float, optional
26 eccentricity. The default is 1.
27 """
29 state_names = (
30 "x pos",
31 "y pos",
32 "z pos",
33 "x vel",
34 "y vel",
35 "z vel",
36 "targets true anomaly",
37 )
39 def __init__(
40 self, mu=3.986004418 * 10**14, semi_major=None, eccentricity=1, **kwargs
41 ):
42 self.mu = mu
43 self.semi_major = semi_major
44 self.eccentricity = eccentricity
46 super().__init__(**kwargs)
48 @property
49 def control_model(self):
50 return self._control_model
52 @control_model.setter
53 def control_model(self, model):
54 self._control_model = model
56 @property
57 def cont_fnc_lst(self):
58 """Continuous time dynamics.
60 Returns
61 -------
62 list
63 functions of the form :code:`(t, x, *args)`.
64 """
66 # returns x velocity
67 def f0(t, x, *args):
68 return x[3]
70 # returns y velocity
71 def f1(t, x, *args):
72 return x[4]
74 # returns z velocity
75 def f2(t, x, *args):
76 return x[5]
78 # returns x acceleration
79 def f3(t, x, *args):
80 e = self.eccentricity
81 a = self.semi_major
82 mu = self.mu
84 e2 = e**2
85 R3 = ((a * (1 - e2)) / (1 + e * np.cos(x[6]))) ** 3
86 n = np.sqrt(mu / a**3)
88 C1 = mu / R3
89 wz = n * (1 + e * np.cos(x[6])) ** 2 / (1 - e2) ** (3.0 / 2.0)
90 wz_dot = -2 * mu * e * np.sin(x[6]) / R3
92 return (wz**2 + 2 * C1) * x[0] + wz_dot * x[1] + 2 * wz * x[4]
94 # returns y acceleration
95 def f4(t, x, *args):
96 e = self.eccentricity
97 a = self.semi_major
98 mu = self.mu
100 e2 = e**2
101 R3 = ((a * (1 - e2)) / (1 + e * np.cos(x[6]))) ** 3
102 n = np.sqrt(mu / a**3)
104 C1 = mu / R3
105 wz = n * (1 + e * np.cos(x[6])) ** 2 / (1 - e2) ** (3.0 / 2.0)
106 wz_dot = -2 * mu * e * np.sin(x[6]) / R3
108 return (wz**2 - C1) * x[1] - wz_dot * x[0] - 2 * wz * x[3]
110 # returns z acceleration
111 def f5(t, x, *args):
112 e = self.eccentricity
113 a = self.semi_major
114 mu = self.mu
116 e2 = e**2
117 R3 = ((a * (1 - e2)) / (1 + e * np.cos(x[6]))) ** 3
119 C1 = mu / R3
121 return -C1 * x[2]
123 # returns true anomaly ROC
124 def f6(t, x, *args):
125 e = self.eccentricity
126 a = self.semi_major
127 p = a * (1 - e**2)
129 H = np.sqrt(self.mu * p)
130 R = p / (1 + e * np.cos(x[6]))
131 return H / R**2
133 return [f0, f1, f2, f3, f4, f5, f6]