@@ -44,10 +44,8 @@ pub struct Maneuver {
44
44
/// Thrust level, if 1.0 use all thruster available at full power
45
45
/// TODO: Convert this to a common polynomial as well to optimize throttle, throttle rate (and accel?)
46
46
pub thrust_prct : f64 ,
47
- /// The interpolation polynomial for the azimuth (in-plane) angle
48
- pub alpha_inplane_radians : CommonPolynomial ,
49
- /// The interpolation polynomial for the elevation (out-of-plane) angle
50
- pub delta_outofplane_radians : CommonPolynomial ,
47
+ /// The representation of this maneuver.
48
+ pub representation : MnvrRepr ,
51
49
/// The frame in which the maneuvers are defined.
52
50
pub frame : LocalFrame ,
53
51
}
@@ -67,11 +65,7 @@ impl fmt::Display for Maneuver {
67
65
self . end - self . start,
68
66
self . end,
69
67
) ?;
70
- write ! (
71
- f,
72
- "\n \t in-plane angle α: {}\n \t out-of-plane angle β: {}" ,
73
- self . alpha_inplane_radians, self . delta_outofplane_radians
74
- ) ?;
68
+ write ! ( f, "\n {}" , self . representation) ?;
75
69
write ! (
76
70
f,
77
71
"\n \t initial dir: [{:.6}, {:.6}, {:.6}]\n \t final dir : [{:.6}, {:.6}, {:.6}]" ,
@@ -80,13 +74,40 @@ impl fmt::Display for Maneuver {
80
74
} else {
81
75
write ! (
82
76
f,
83
- "Impulsive maneuver @ {}\n \t in-plane angle α: {} \n \t out-of-plane angle β: {}" ,
84
- self . start, self . alpha_inplane_radians , self . delta_outofplane_radians
77
+ "Impulsive maneuver @ {}\n {}" ,
78
+ self . start, self . representation
85
79
)
86
80
}
87
81
}
88
82
}
89
83
84
+ /// Defines the available maneuver representations.
85
+ #[ derive( Copy , Clone , Debug , PartialEq , Serialize , Deserialize ) ]
86
+ pub enum MnvrRepr {
87
+ /// Represents the maneuver as a fixed vector in the local frame.
88
+ Vector ( Vector3 < f64 > ) ,
89
+ /// Represents the maneuver as a polynominal of azimuth (right ascension / in-plane) and elevation (declination / out of plane)
90
+ Angles {
91
+ azimuth : CommonPolynomial ,
92
+ elevation : CommonPolynomial ,
93
+ } ,
94
+ }
95
+
96
+ impl fmt:: Display for MnvrRepr {
97
+ /// Prints the polynomial with the least significant coefficients first
98
+ #[ allow( clippy:: identity_op) ]
99
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
100
+ match self {
101
+ MnvrRepr :: Vector ( vector) => write ! ( f, "{vector}" ) ,
102
+ MnvrRepr :: Angles { azimuth, elevation } => write ! (
103
+ f,
104
+ "\t azimuth (in-plane) α: {}\n \t elevation (out-of-plane) β: {}" ,
105
+ azimuth, elevation
106
+ ) ,
107
+ }
108
+ }
109
+ }
110
+
90
111
impl Maneuver {
91
112
/// Creates an impulsive maneuver whose vector is the deltaV.
92
113
/// TODO: This should use William's algorithm
@@ -102,24 +123,26 @@ impl Maneuver {
102
123
vector : Vector3 < f64 > ,
103
124
frame : LocalFrame ,
104
125
) -> Self {
105
- // Convert to angles
106
- let ( alpha, delta) = ra_dec_from_unit_vector ( vector) ;
107
126
Self {
108
127
start,
109
128
end,
110
129
thrust_prct : thrust_lvl,
111
- alpha_inplane_radians : CommonPolynomial :: Constant ( alpha) ,
112
- delta_outofplane_radians : CommonPolynomial :: Constant ( delta) ,
130
+ representation : MnvrRepr :: Vector ( vector) ,
113
131
frame,
114
132
}
115
133
}
116
134
117
135
/// Return the thrust vector computed at the provided epoch
118
136
pub fn vector ( & self , epoch : Epoch ) -> Vector3 < f64 > {
119
- let t = ( epoch - self . start ) . to_seconds ( ) ;
120
- let alpha = self . alpha_inplane_radians . eval ( t) ;
121
- let delta = self . delta_outofplane_radians . eval ( t) ;
122
- unit_vector_from_ra_dec ( alpha, delta)
137
+ match self . representation {
138
+ MnvrRepr :: Vector ( vector) => vector,
139
+ MnvrRepr :: Angles { azimuth, elevation } => {
140
+ let t = ( epoch - self . start ) . to_seconds ( ) ;
141
+ let alpha = azimuth. eval ( t) ;
142
+ let delta = elevation. eval ( t) ;
143
+ unit_vector_from_ra_dec ( alpha, delta)
144
+ }
145
+ }
123
146
}
124
147
125
148
/// Return the duration of this maneuver
@@ -134,9 +157,14 @@ impl Maneuver {
134
157
135
158
/// Returns the direction of the burn at the start of the burn, useful for setting new angles
136
159
pub fn direction ( & self ) -> Vector3 < f64 > {
137
- let alpha = self . alpha_inplane_radians . coeff_in_order ( 0 ) . unwrap ( ) ;
138
- let delta = self . delta_outofplane_radians . coeff_in_order ( 0 ) . unwrap ( ) ;
139
- unit_vector_from_ra_dec ( alpha, delta)
160
+ match self . representation {
161
+ MnvrRepr :: Vector ( vector) => vector / vector. norm ( ) ,
162
+ MnvrRepr :: Angles { azimuth, elevation } => {
163
+ let alpha = azimuth. coeff_in_order ( 0 ) . unwrap ( ) ;
164
+ let delta = elevation. coeff_in_order ( 0 ) . unwrap ( ) ;
165
+ unit_vector_from_ra_dec ( alpha, delta)
166
+ }
167
+ }
140
168
}
141
169
142
170
/// Set the time-invariant direction for this finite burn while keeping the other components as they are
@@ -146,12 +174,15 @@ impl Maneuver {
146
174
147
175
/// Returns the rate of direction of the burn at the start of the burn, useful for setting new angles
148
176
pub fn rate ( & self ) -> Vector3 < f64 > {
149
- match self . alpha_inplane_radians . coeff_in_order ( 1 ) {
150
- Ok ( alpha) => {
151
- let delta = self . delta_outofplane_radians . coeff_in_order ( 1 ) . unwrap ( ) ;
152
- unit_vector_from_ra_dec ( alpha, delta)
153
- }
154
- Err ( _) => Vector3 :: zeros ( ) ,
177
+ match self . representation {
178
+ MnvrRepr :: Vector ( _) => Vector3 :: zeros ( ) ,
179
+ MnvrRepr :: Angles { azimuth, elevation } => match azimuth. coeff_in_order ( 1 ) {
180
+ Ok ( alpha) => {
181
+ let delta = elevation. coeff_in_order ( 1 ) . unwrap ( ) ;
182
+ unit_vector_from_ra_dec ( alpha, delta)
183
+ }
184
+ Err ( _) => Vector3 :: zeros ( ) ,
185
+ } ,
155
186
}
156
187
}
157
188
@@ -162,12 +193,15 @@ impl Maneuver {
162
193
163
194
/// Returns the acceleration of the burn at the start of the burn, useful for setting new angles
164
195
pub fn accel ( & self ) -> Vector3 < f64 > {
165
- match self . alpha_inplane_radians . coeff_in_order ( 2 ) {
166
- Ok ( alpha) => {
167
- let delta = self . delta_outofplane_radians . coeff_in_order ( 2 ) . unwrap ( ) ;
168
- unit_vector_from_ra_dec ( alpha, delta)
169
- }
170
- Err ( _) => Vector3 :: zeros ( ) ,
196
+ match self . representation {
197
+ MnvrRepr :: Vector ( _) => Vector3 :: zeros ( ) ,
198
+ MnvrRepr :: Angles { azimuth, elevation } => match azimuth. coeff_in_order ( 2 ) {
199
+ Ok ( alpha) => {
200
+ let delta = elevation. coeff_in_order ( 2 ) . unwrap ( ) ;
201
+ unit_vector_from_ra_dec ( alpha, delta)
202
+ }
203
+ Err ( _) => Vector3 :: zeros ( ) ,
204
+ } ,
171
205
}
172
206
}
173
207
@@ -183,48 +217,58 @@ impl Maneuver {
183
217
rate : Vector3 < f64 > ,
184
218
accel : Vector3 < f64 > ,
185
219
) -> Result < ( ) , GuidanceError > {
186
- let ( alpha, delta) = ra_dec_from_unit_vector ( dir) ;
187
- if alpha. is_nan ( ) || delta. is_nan ( ) {
188
- return Err ( GuidanceError :: InvalidDirection {
189
- x : dir[ 0 ] ,
190
- y : dir[ 1 ] ,
191
- z : dir[ 2 ] ,
192
- in_plane_deg : alpha. to_degrees ( ) ,
193
- out_of_plane_deg : delta. to_degrees ( ) ,
194
- } ) ;
195
- }
196
- if rate. norm ( ) < 2e-16 && accel. norm ( ) < 2e-16 {
197
- self . alpha_inplane_radians = CommonPolynomial :: Constant ( alpha) ;
198
- self . delta_outofplane_radians = CommonPolynomial :: Constant ( delta) ;
220
+ if rate. norm ( ) < f64:: EPSILON && accel. norm ( ) < f64:: EPSILON {
221
+ // Set as a vector
222
+ self . representation = MnvrRepr :: Vector ( dir)
199
223
} else {
200
- let ( alpha_dt , delta_dt ) = ra_dec_from_unit_vector ( rate ) ;
201
- if alpha_dt . is_nan ( ) || delta_dt . is_nan ( ) {
202
- return Err ( GuidanceError :: InvalidRate {
203
- x : rate [ 0 ] ,
204
- y : rate [ 1 ] ,
205
- z : rate [ 2 ] ,
206
- in_plane_deg_s : alpha_dt . to_degrees ( ) ,
207
- out_of_plane_deg_s : delta_dt . to_degrees ( ) ,
224
+ let ( alpha , delta ) = ra_dec_from_unit_vector ( dir ) ;
225
+ if alpha . is_nan ( ) || delta . is_nan ( ) {
226
+ return Err ( GuidanceError :: InvalidDirection {
227
+ x : dir [ 0 ] ,
228
+ y : dir [ 1 ] ,
229
+ z : dir [ 2 ] ,
230
+ in_plane_deg : alpha . to_degrees ( ) ,
231
+ out_of_plane_deg : delta . to_degrees ( ) ,
208
232
} ) ;
209
233
}
210
- if accel. norm ( ) < 2e-16 {
211
- self . alpha_inplane_radians = CommonPolynomial :: Linear ( alpha_dt, alpha) ;
212
- self . delta_outofplane_radians = CommonPolynomial :: Linear ( delta_dt, delta) ;
234
+ if rate. norm ( ) < f64:: EPSILON && accel. norm ( ) < f64:: EPSILON {
235
+ self . representation = MnvrRepr :: Angles {
236
+ azimuth : CommonPolynomial :: Constant ( alpha) ,
237
+ elevation : CommonPolynomial :: Constant ( delta) ,
238
+ } ;
213
239
} else {
214
- let ( alpha_ddt , delta_ddt ) = ra_dec_from_unit_vector ( accel ) ;
215
- if alpha_ddt . is_nan ( ) || delta_ddt . is_nan ( ) {
216
- return Err ( GuidanceError :: InvalidAcceleration {
217
- x : accel [ 0 ] ,
218
- y : accel [ 1 ] ,
219
- z : accel [ 2 ] ,
220
- in_plane_deg_s2 : alpha_ddt . to_degrees ( ) ,
221
- out_of_plane_deg_s2 : delta_ddt . to_degrees ( ) ,
240
+ let ( alpha_dt , delta_dt ) = ra_dec_from_unit_vector ( rate ) ;
241
+ if alpha_dt . is_nan ( ) || delta_dt . is_nan ( ) {
242
+ return Err ( GuidanceError :: InvalidRate {
243
+ x : rate [ 0 ] ,
244
+ y : rate [ 1 ] ,
245
+ z : rate [ 2 ] ,
246
+ in_plane_deg_s : alpha_dt . to_degrees ( ) ,
247
+ out_of_plane_deg_s : delta_dt . to_degrees ( ) ,
222
248
} ) ;
223
249
}
224
- self . alpha_inplane_radians =
225
- CommonPolynomial :: Quadratic ( alpha_ddt, alpha_dt, alpha) ;
226
- self . delta_outofplane_radians =
227
- CommonPolynomial :: Quadratic ( delta_ddt, delta_dt, delta) ;
250
+ if accel. norm ( ) < f64:: EPSILON {
251
+ self . representation = MnvrRepr :: Angles {
252
+ azimuth : CommonPolynomial :: Linear ( alpha_dt, alpha) ,
253
+ elevation : CommonPolynomial :: Linear ( delta_dt, delta) ,
254
+ } ;
255
+ } else {
256
+ let ( alpha_ddt, delta_ddt) = ra_dec_from_unit_vector ( accel) ;
257
+ if alpha_ddt. is_nan ( ) || delta_ddt. is_nan ( ) {
258
+ return Err ( GuidanceError :: InvalidAcceleration {
259
+ x : accel[ 0 ] ,
260
+ y : accel[ 1 ] ,
261
+ z : accel[ 2 ] ,
262
+ in_plane_deg_s2 : alpha_ddt. to_degrees ( ) ,
263
+ out_of_plane_deg_s2 : delta_ddt. to_degrees ( ) ,
264
+ } ) ;
265
+ }
266
+
267
+ self . representation = MnvrRepr :: Angles {
268
+ azimuth : CommonPolynomial :: Quadratic ( alpha_ddt, alpha_dt, alpha) ,
269
+ elevation : CommonPolynomial :: Quadratic ( delta_ddt, delta_dt, delta) ,
270
+ } ;
271
+ }
228
272
}
229
273
}
230
274
Ok ( ( ) )
0 commit comments