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

1import numpy as np 

2from .nonlinear_dynamics_base import NonlinearDynamicsBase 

3 

4 

5class TschaunerHempelOrbit(NonlinearDynamicsBase): 

6 """Implements the non-linear Tschauner-Hempel elliptical orbit model. 

7 

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` 

18 

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 """ 

28 

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 ) 

38 

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 

45 

46 super().__init__(**kwargs) 

47 

48 @property 

49 def control_model(self): 

50 return self._control_model 

51 

52 @control_model.setter 

53 def control_model(self, model): 

54 self._control_model = model 

55 

56 @property 

57 def cont_fnc_lst(self): 

58 """Continuous time dynamics. 

59 

60 Returns 

61 ------- 

62 list 

63 functions of the form :code:`(t, x, *args)`. 

64 """ 

65 

66 # returns x velocity 

67 def f0(t, x, *args): 

68 return x[3] 

69 

70 # returns y velocity 

71 def f1(t, x, *args): 

72 return x[4] 

73 

74 # returns z velocity 

75 def f2(t, x, *args): 

76 return x[5] 

77 

78 # returns x acceleration 

79 def f3(t, x, *args): 

80 e = self.eccentricity 

81 a = self.semi_major 

82 mu = self.mu 

83 

84 e2 = e**2 

85 R3 = ((a * (1 - e2)) / (1 + e * np.cos(x[6]))) ** 3 

86 n = np.sqrt(mu / a**3) 

87 

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 

91 

92 return (wz**2 + 2 * C1) * x[0] + wz_dot * x[1] + 2 * wz * x[4] 

93 

94 # returns y acceleration 

95 def f4(t, x, *args): 

96 e = self.eccentricity 

97 a = self.semi_major 

98 mu = self.mu 

99 

100 e2 = e**2 

101 R3 = ((a * (1 - e2)) / (1 + e * np.cos(x[6]))) ** 3 

102 n = np.sqrt(mu / a**3) 

103 

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 

107 

108 return (wz**2 - C1) * x[1] - wz_dot * x[0] - 2 * wz * x[3] 

109 

110 # returns z acceleration 

111 def f5(t, x, *args): 

112 e = self.eccentricity 

113 a = self.semi_major 

114 mu = self.mu 

115 

116 e2 = e**2 

117 R3 = ((a * (1 - e2)) / (1 + e * np.cos(x[6]))) ** 3 

118 

119 C1 = mu / R3 

120 

121 return -C1 * x[2] 

122 

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) 

128 

129 H = np.sqrt(self.mu * p) 

130 R = p / (1 + e * np.cos(x[6])) 

131 return H / R**2 

132 

133 return [f0, f1, f2, f3, f4, f5, f6]