@@ -19,52 +19,93 @@ def test_gaussIOD():
1919 #vectors_obs = vectors.reshape(1, -1)
2020 vectors_obs = np .array ([[1. , 0. , 0. , 0. , - np .sqrt (MU ), 0. ]])
2121
22+ # Set an initial epoch
2223 t0 = np .array (epoch , dtype = float )
24+
25+ # Set propagation epochs: 10 years at 1 day intervals
2326 t1 = epoch [0 ] + np .arange (1 , 365 * 10 , 1 , dtype = float )
2427
28+ # Propagate the observer to each epoch and grab its state
2529 states_observer = propagateUniversal (vectors_obs , t0 , t1 , mu = MU , max_iter = 1000 , tol = 1e-15 )
2630 states_observer = states_observer [:, 2 :]
2731
28- targets = ["Ceres" , "Eros" , "1719" ]
32+ # Run IOD on the following targets
33+ targets = ["Ceres" , "Eros" , "1719" , "Amor" ]
2934
30- for target in targets :
31- target = Horizons (id = target , epochs = epoch , location = "@sun" )
35+ for name in targets :
36+
37+ # Grab target's state at t0 from Horizons
38+ target = Horizons (id = name , epochs = epoch , location = "@sun" )
3239 vectors = target .vectors ()
3340 vectors = np .array (vectors ["x" , "y" , "z" , "vx" , "vy" , "vz" ]).view ("float64" )
3441 vectors_target = vectors .reshape (1 , - 1 )
35-
42+
43+ # Propagate target to each t1 epoch from the initial state
3644 states_target = propagateUniversal (vectors_target , t0 , t1 , mu = MU , max_iter = 1000 , tol = 1e-15 )
3745 states_target = states_target [:, 2 :]
3846
47+ # Calculate the distance from observer to target at each epoch
3948 delta = states_target [:, :3 ] - states_observer [:, :3 ]
4049
50+ # Calculate the line of sight vectors at each t1 epoch
4151 rho = np .zeros_like (delta )
4252 for i , j in enumerate (delta ):
4353 rho [i ] = j / np .linalg .norm (j )
4454
55+ # Using line of sight vectors, calculate the on-sky location of the target
56+ # from the point of view of the observer in both ecliptic and equatorial
57+ # coordinates
4558 rho_eq = np .array (c .TRANSFORM_EC2EQ @ rho .T ).T
46-
4759 coords_ec = _cartesianToAngular (* rho .T )[:, :2 ]
4860 coords_ec = np .degrees (coords_ec )
4961
5062 coords_eq = _cartesianToAngular (* rho_eq .T )[:, :2 ]
5163 coords_eq = np .degrees (coords_eq )
5264
65+ # Iterate over different selections of "observations"
5366 for selected_obs in [[0 , 5 , 10 ],
5467 [100 , 120 , 140 ],
5568 [22 , 23 , 24 ],
5669 [1000 , 1005 , 1010 ],
5770 [3600 , 3620 , 3630 ],
5871 [1999 , 2009 , 2034 ]]:
72+
73+ print ("Target Name: {}" .format (name ))
74+ print ("Observations Indices: \n \t {}" .format (selected_obs ))
75+
76+ # Grab truth position and velocity vectors
5977 truth_r = states_target [selected_obs , :3 ]
6078 truth_v = states_target [selected_obs , 3 :]
79+
80+ # Grab observables: on-sky location of the target
6181 coords_obs = states_observer [selected_obs , :3 ]
6282 coords_ec_ang = coords_ec [selected_obs ]
6383 coords_eq_ang = coords_eq [selected_obs ]
6484 t = t1 [selected_obs ]
85+
86+ print ("Observations:" )
87+ for i , observation in enumerate (coords_eq_ang ):
88+ print ("\t t [MJD]: {}, RA [Deg]: {}, Dec [Deg]: {}, obs_x [AU]: {}, obs_y [AU]: {}, obs_z [AU]: {}" .format (t [i ], * observation , * coords_obs [i ]))
89+
90+ print ("Actual State [AU, AU/d]:\n \t {}" .format (states_target [selected_obs [1 ]]))
91+
92+ # Using observables, run IOD without iteration
93+ orbits = gaussIOD (coords_eq_ang , t , coords_obs , velocity_method = "gibbs" , iterate = False , mu = MU , max_iter = 100 , tol = 1e-15 )
94+
95+ print ("Predicted States (without iteration) [AU, AU/d]:" )
96+ for orbit in orbits :
97+ print ("\t {}" .format (orbit ))
6598
66- orbits = gaussIOD (coords_eq_ang , t , coords_obs , velocity_method = "gibbs" , iterate = True , mu = MU , max_iter = 1000 , tol = 1e-15 )
99+ # Using observables, run IOD
100+ orbits = gaussIOD (coords_eq_ang , t , coords_obs , velocity_method = "gibbs" , iterate = True , mu = MU , max_iter = 100 , tol = 1e-15 )
101+
102+ print ("Predicted States (with iteration) [AU, AU/d]:" )
103+ for orbit in orbits :
104+ print ("\t {}" .format (orbit ))
67105
106+ # IOD returns up to 3 solutions, iterate over each one and find the one with the closest
107+ # prediction in position, if the position is within 100 meters and the velocity is within
108+ # 10 cm/s we are happy
68109 closest_r = 1e10
69110 closest_v = 1e10
70111
@@ -79,13 +120,17 @@ def test_gaussIOD():
79120 r2_truth_mag = np .linalg .norm (r2_truth )
80121 v2_truth_mag = np .linalg .norm (v2_truth )
81122
82-
83123 r_diff = np .abs (r2_mag - r2_truth_mag ) / r2_truth_mag
84124 v_diff = np .abs (v2_mag - v2_truth_mag ) / v2_truth_mag
85125
86126 if closest_r > np .abs (r_diff ):
87127 closest_r = r_diff
88128 closest_v = v_diff
129+
130+ print ("(Actual - Predicted) / Actual:" )
131+ for orbit in orbits :
132+ print ("\t {}" .format ((states_target [selected_obs [1 ]] - orbit ) / states_target [selected_obs [1 ]]))
133+ print ("" )
89134
90135 # Test position to within 100 meters and velocity to within 10 cm/s
91136 np .testing .assert_allclose (closest_r , 0.0 , atol = 6.68459e-10 , rtol = 6.68459e-10 )
0 commit comments