66import Basilisk .utilities .orbitalMotion as om
77from datetime import datetime , timedelta , timezone
88
9- A_TOL = 1e-14 #[-]
9+ A_TOL = 1e-9 #[-]
10+ A_TOL_ROUNDTRIP = 1e-4 #[-] Tolerance for eccentricity (roundtrip error)
11+ A_TOL_DEG_ROUNDTRIP = 1.5 # [deg] Tolerance for angles in degrees (roundtrip error)
12+
1013DATA_DIR = pathlib .Path (__file__ ).parent / 'data'
1114
1215###################################################################
1316# Expected orbital elements for oneWeb (if testing multiple satellites)
1417EXPECTED_OE_ONE_WEB = {
1518 'a' : [
16- 7575817.78380046 , # 0
17- 7575897.531671279 , # 1
18- 7575896.775957426 , # 2
19- 7579911.683283668 , # 3
20- 7579911.241546285 , # 4
21- 7579912.336286875 # 5
22- ],
19+ np . float64 ( 7578544.80840588 ),
20+ np . float64 ( 7581725.314320893 ),
21+ np . float64 ( 7581725.090937277 ),
22+ np . float64 ( 7585736.508260437 ),
23+ np . float64 ( 7585735.9677996775 ),
24+ np . float64 ( 7585737.120163768 )
25+ ],
2326 'e' : [
24- 0.000175 , 0.0001764 , 0.0002086 , 0.0001581 , 0.0001714 ,
25- 0.0002029
26- ],
27+ np .float64 (0.0008817590462989669 ),
28+ np .float64 (0.001210093768077448 ),
29+ np .float64 (0.001258633728769965 ),
30+ np .float64 (0.0011981313722308415 ),
31+ np .float64 (0.001206952489243135 ),
32+ np .float64 (0.001239828742668404 )
33+ ],
2734 'i' : [
28- 1.534083325979196 , 1.5340868166376997 , 1.534083325979196 ,
29- 1.5341409218445117 , 1.5341496484907717 , 1.5341409218445117
30- ] ,
31- 'f' : [
32- 2.2017240215026246 , 4.489410705143804 , 4.744271057621696 ,
33- 4.549972500184758 , 4.511343702990637 , 4.567673118903615
34- ],
35+ 1.531618126589653 ,
36+ 1.5316291459001932 ,
37+ 1.5316258452568352 ,
38+ 1.5322241554919225 ,
39+ 1.5322307739504486 ,
40+ 1.5322225935006697
41+ ],
3542 'Omega' : [
36- 4.888890636980372 , 4.888930779553168 , 4.889318242647111 ,
37- 5.4216838070781765 , 5.420380046126938 , 5.4207134040140685
38- ],
43+ 4.8831623958720565 ,
44+ 4.883186443196075 ,
45+ 4.883574022425417 ,
46+ 5.415984679757847 ,
47+ 5.414680762509103 ,
48+ 5.415014177551135
49+ ],
3950 'omega' : [
40- 1.372734617949328 , 1.7957483234259417 , 1.5408883647327218 ,
41- 1.7351853983817387 , 1.773814770716129 , 1.717484269108012
42- ]
51+ 1.4377465022195557 ,
52+ 1.2801901375990692 ,
53+ 1.2537640336417852 ,
54+ 1.2645835093359827 ,
55+ 1.2744200510794836 ,
56+ 1.278331704552413
57+ ],
58+ 'f' : [
59+ 2.1381866215235528 ,
60+ 5.002606275268809 ,
61+ 5.029031746586543 ,
62+ 5.017006771870916 ,
63+ 5.0071733437393355 ,
64+ 5.003259952527291
65+ ],
4366}
4467
4568EXPECTED_OE_2LE = {
46- 'a' : [
47- 6796012.0083837 ,
48- 6763487.620700561 ,
49- 6796034.881033647
50- ],
51- 'e' : [
52- 0.0001066 ,
53- 0.0001842 ,
54- 0.0001045
55- ],
56- 'i' : [
57- 0.9011588713652241 ,
58- 0.7236833210469288 ,
59- 0.9011606166944762
60- ],
61- 'f' : [
62- 3.019032029543272 ,
63- 3.4280122815833245 ,
64- 3.0304383654813503
65- ],
66- 'Omega' : [
67- 2.3957855389445846 ,
68- 1.6320242222841097 ,
69- 2.4180821201388114
70- ],
71- 'omega' : [
72- 3.2658775496243098 ,
73- 2.8566379826044352 ,
74- 3.2544735682917785
75- ]
69+ 'a' : [np .float64 (6802505.842859207 ), np .float64 (6770009.6048538275 ), np .float64 (6802528.7123854 )],
70+ 'e' : [np .float64 (0.0011264735370325686 ), np .float64 (0.0011530055595853114 ), np .float64 (0.001128835473051786 )],
71+ 'i' : [0.903248948599224 , 0.7265482390037918 , 0.9032099423215613 ],
72+ 'Omega' : [2.3886009471482503 , 1.6261518262462817 , 2.410867356948434 ],
73+ 'omega' : [0.8571434002531804 , 0.7478010900864719 , 0.8567388460152983 ],
74+ 'f' : [5.428341410047342 , 5.535537401708238 , 5.428797206538743 ],
7675}
7776
7877# Values to generate TLE for HYPSO 1
7978oeHypso1 = om .ClassicElements ()
80- oeHypso1 .i = np . deg2rad ( 97.3197 )
81- oeHypso1 .e = 0.0004257 # [-]
82- oeHypso1 .a = ( om . RP_EARTH + 445.195971181338 ) * 1e3 # [m]
83- oeHypso1 .Omega = np . deg2rad ( 349.0390 ) # [rad]
84- oeHypso1 .omega = np . deg2rad ( 136.0807 ) # [rad]
85- oeHypso1 .f = np . deg2rad ( 224.04427854247686 ) # [rad]
79+ oeHypso1 .i = 1.6979291907417804
80+ oeHypso1 .e = 0.0013996087479637449
81+ oeHypso1 .a = 6808434.893655814
82+ oeHypso1 .Omega = 6.085804103135117
83+ oeHypso1 .omega = 1.43544167146666
84+ oeHypso1 .f = 4.845270389715793
8685hypso1noradId = 51053 # [-]
8786hypso1launch = datetime (2022 , 1 , 13 , 0 , 0 , 0 ) # [UTC]
8887hypso1tleEpoch = datetime (2025 , 1 , 1 , tzinfo = timezone .utc ) + timedelta (days = 279.47924866 - 1 ) # [UTC]
@@ -153,7 +152,15 @@ def test_write_tle(satName, orbitalElements, noradID, launchDate, launch_Noyear,
153152 # String compaire (line 1)
154153 eCountTle += int ((generatedTle .splitlines ()[1 ] != expectedTLE .splitlines ()[1 ]))
155154 # String compaire (line 2)
156- eCountTle += int ((generatedTle .splitlines ()[2 ][0 :63 ] != expectedTLE .splitlines ()[2 ][0 :63 ])) # Ignore revolutions count and checksum
155+ for i , (field_expected , field_generated ) in enumerate (zip (expectedTLE .splitlines ()[2 ].split (), generatedTle .splitlines ()[2 ].split ())):
156+ if i in [4 ]: # 4 = eccentricity (leading decimal point assumed), 5 = argument of perigee, 6 = mean anomaly
157+ # Eccentricity -> leading decimal point assume -> max tolerance is A_TOL_ROUNDTRIP * 1e7 => 1e-4 physical eccentricity tolerance
158+ eCountTle += abs (float (field_expected ) - float (field_generated )) > A_TOL_ROUNDTRIP * 1e7
159+ elif i in [5 ,6 ]: # 5 = argument of perigee, 6 = mean anomaly (degrees)
160+ eCountTle += abs (float (field_expected ) - float (field_generated )) > A_TOL_DEG_ROUNDTRIP
161+ else :
162+ eCountTle += abs (float (field_expected ) - float (field_generated )) > A_TOL_ROUNDTRIP
163+
157164 assert eCountTle < 1 , f"{ eCountTle } functions failed in tleHandling.py script, generateTleDataString() method"
158165
159166@pytest .mark .parametrize ("tlePath" , [
@@ -174,7 +181,15 @@ def test_read_write_tle(tlePath):
174181 # String compaire (line 1)
175182 eCountTle += int ((generatedTle .splitlines ()[1 ] != tleToBeTested .splitlines ()[1 ]))
176183 # String compaire (line 2)
177- eCountTle += int ((generatedTle .splitlines ()[2 ][0 :63 ] != tleToBeTested .splitlines ()[2 ][0 :63 ])) # Ignore revolutions count and checksum
184+ for i , (field_expected , field_generated ) in enumerate (zip (tleToBeTested .splitlines ()[2 ].split (), generatedTle .splitlines ()[2 ].split ())):
185+ if i in [4 ]: # 4 = eccentricity (leading decimal point assumed), 5 = argument of perigee, 6 = mean anomaly
186+ # Eccentricity -> leading decimal point assume -> max tolerance is A_TOL_ROUNDTRIP * 1e7 => 1e-4 physical eccentricity tolerance
187+ eCountTle += abs (float (field_expected ) - float (field_generated )) > A_TOL_ROUNDTRIP * 1e7
188+ elif i in [5 ,6 ]: # 5 = argument of perigee, 6 = mean anomaly (degrees)
189+ eCountTle += abs (float (field_expected ) - float (field_generated )) > A_TOL_DEG_ROUNDTRIP
190+ else :
191+ eCountTle += abs (float (field_expected ) - float (field_generated )) > A_TOL_ROUNDTRIP
192+
178193 assert eCountTle < 1 , f"{ eCountTle } functions failed in tleHandling.py script, generateTleDataString() method"
179194
180195if __name__ == "__main__" :
0 commit comments