ootk 5.1.0 → 6.0.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (599) hide show
  1. package/.claude/PROMPT.md +13 -0
  2. package/.claude/hooks/post-tool-use.ts +33 -0
  3. package/.claude/hooks/user-prompt-submit.ts +138 -0
  4. package/.claude/settings.local.json +13 -0
  5. package/.claude/skill-rules.json +11 -0
  6. package/.claude/skills/ootk-dev/SKILL.md +16 -0
  7. package/ADVANCED_FEATURES_GUIDE.md +1025 -0
  8. package/CHANGELOG.md +42 -3
  9. package/README.md +77 -45
  10. package/dist/body/Celestial.d.ts +2 -2
  11. package/dist/body/Celestial.js +2 -2
  12. package/dist/body/Celestial.js.map +1 -1
  13. package/dist/body/Earth.d.ts +4 -4
  14. package/dist/body/Earth.js +2 -2
  15. package/dist/body/Earth.js.map +1 -1
  16. package/dist/body/Moon.d.ts +3 -3
  17. package/dist/body/Moon.js +7 -7
  18. package/dist/body/Moon.js.map +1 -1
  19. package/dist/body/NutationAngles.d.ts +2 -2
  20. package/dist/body/NutationAngles.js +1 -1
  21. package/dist/body/PrecessionAngles.d.ts +2 -2
  22. package/dist/body/PrecessionAngles.js +1 -1
  23. package/dist/body/Sun.d.ts +2 -2
  24. package/dist/body/Sun.js +3 -3
  25. package/dist/body/Sun.js.map +1 -1
  26. package/dist/body/index.d.ts +5 -5
  27. package/dist/body/index.js +5 -5
  28. package/dist/body/index.js.map +1 -1
  29. package/dist/conjunction/ConjunctionAssessment.d.ts +156 -0
  30. package/dist/conjunction/ConjunctionAssessment.js +281 -0
  31. package/dist/conjunction/ConjunctionAssessment.js.map +1 -0
  32. package/dist/conjunction/ConjunctionEvent.d.ts +104 -0
  33. package/dist/conjunction/ConjunctionEvent.js +156 -0
  34. package/dist/conjunction/ConjunctionEvent.js.map +1 -0
  35. package/dist/conjunction/ProbabilityOfCollision.d.ts +102 -0
  36. package/dist/conjunction/ProbabilityOfCollision.js +240 -0
  37. package/dist/conjunction/ProbabilityOfCollision.js.map +1 -0
  38. package/dist/conjunction/index.d.ts +19 -0
  39. package/dist/conjunction/index.js +20 -0
  40. package/dist/conjunction/index.js.map +1 -0
  41. package/dist/coordinate/ClassicalElements.d.ts +7 -7
  42. package/dist/coordinate/ClassicalElements.js +7 -7
  43. package/dist/coordinate/ClassicalElements.js.map +1 -1
  44. package/dist/coordinate/EquinoctialElements.d.ts +5 -5
  45. package/dist/coordinate/EquinoctialElements.js +4 -4
  46. package/dist/coordinate/EquinoctialElements.js.map +1 -1
  47. package/dist/coordinate/FormatTle.d.ts +2 -2
  48. package/dist/coordinate/FormatTle.js +2 -2
  49. package/dist/coordinate/FormatTle.js.map +1 -1
  50. package/dist/coordinate/Geodetic.d.ts +4 -4
  51. package/dist/coordinate/Geodetic.js +7 -7
  52. package/dist/coordinate/Geodetic.js.map +1 -1
  53. package/dist/coordinate/Hill.d.ts +4 -4
  54. package/dist/coordinate/Hill.js +3 -3
  55. package/dist/coordinate/Hill.js.map +1 -1
  56. package/dist/coordinate/ITRF.d.ts +5 -5
  57. package/dist/coordinate/ITRF.js +6 -5
  58. package/dist/coordinate/ITRF.js.map +1 -1
  59. package/dist/coordinate/J2000.d.ts +5 -5
  60. package/dist/coordinate/J2000.js +5 -5
  61. package/dist/coordinate/J2000.js.map +1 -1
  62. package/dist/coordinate/RIC.d.ts +4 -4
  63. package/dist/coordinate/RIC.js +3 -3
  64. package/dist/coordinate/RIC.js.map +1 -1
  65. package/dist/coordinate/RelativeState.d.ts +5 -5
  66. package/dist/coordinate/RelativeState.js +2 -2
  67. package/dist/coordinate/RelativeState.js.map +1 -1
  68. package/dist/coordinate/StateVector.d.ts +2 -2
  69. package/dist/coordinate/StateVector.js +2 -2
  70. package/dist/coordinate/StateVector.js.map +1 -1
  71. package/dist/coordinate/TEME.d.ts +4 -4
  72. package/dist/coordinate/TEME.js +4 -4
  73. package/dist/coordinate/TEME.js.map +1 -1
  74. package/dist/coordinate/Tle.d.ts +5 -5
  75. package/dist/coordinate/Tle.js +9 -9
  76. package/dist/coordinate/Tle.js.map +1 -1
  77. package/dist/coordinate/index.d.ts +12 -12
  78. package/dist/coordinate/index.js +12 -12
  79. package/dist/coordinate/index.js.map +1 -1
  80. package/dist/coordinate/tle-format-data.d.ts +1 -1
  81. package/dist/coordinate/tle-format-data.js +1 -1
  82. package/dist/covariance/CovarianceSample.d.ts +5 -5
  83. package/dist/covariance/CovarianceSample.js +5 -5
  84. package/dist/covariance/CovarianceSample.js.map +1 -1
  85. package/dist/covariance/StateCovariance.d.ts +2 -2
  86. package/dist/covariance/StateCovariance.js +2 -2
  87. package/dist/covariance/StateCovariance.js.map +1 -1
  88. package/dist/covariance/index.d.ts +2 -2
  89. package/dist/covariance/index.js +2 -2
  90. package/dist/covariance/index.js.map +1 -1
  91. package/dist/data/DataHandler.d.ts +4 -4
  92. package/dist/data/DataHandler.js +5 -5
  93. package/dist/data/DataHandler.js.map +1 -1
  94. package/dist/data/values/Egm96Data.d.ts +1 -1
  95. package/dist/data/values/Egm96Data.js +3 -3
  96. package/dist/data/values/Egm96Data.js.map +1 -1
  97. package/dist/data/values/HpAtmosphereData.d.ts +2 -2
  98. package/dist/data/values/HpAtmosphereData.js +3 -3
  99. package/dist/data/values/HpAtmosphereData.js.map +1 -1
  100. package/dist/data/values/HpAtmosphereResult.d.ts +2 -2
  101. package/dist/data/values/HpAtmosphereResult.js +1 -1
  102. package/dist/data/values/Iau1980Data.d.ts +1 -1
  103. package/dist/data/values/Iau1980Data.js +2 -2
  104. package/dist/data/values/Iau1980Data.js.map +1 -1
  105. package/dist/data/values/LeapSecond.d.ts +1 -1
  106. package/dist/data/values/LeapSecond.js +1 -1
  107. package/dist/data/values/LeapSecondData.d.ts +2 -2
  108. package/dist/data/values/LeapSecondData.js +2 -2
  109. package/dist/data/values/LeapSecondData.js.map +1 -1
  110. package/dist/data/values/egm96.d.ts +2 -2
  111. package/dist/data/values/egm96.js +1 -1
  112. package/dist/data/values/hpAtmosphere.d.ts +2 -2
  113. package/dist/data/values/hpAtmosphere.js +1 -1
  114. package/dist/data/values/iau1980.d.ts +2 -2
  115. package/dist/data/values/iau1980.js +1 -1
  116. package/dist/enums/AngularDiameterMethod.d.ts +1 -1
  117. package/dist/enums/AngularDiameterMethod.js +1 -1
  118. package/dist/enums/AngularDistanceMethod.d.ts +1 -1
  119. package/dist/enums/AngularDistanceMethod.js +1 -1
  120. package/dist/enums/OrbitRegime.d.ts +1 -1
  121. package/dist/enums/OrbitRegime.js +1 -1
  122. package/dist/enums/PassType.d.ts +1 -1
  123. package/dist/enums/PassType.js +1 -1
  124. package/dist/enums/Sgp4OpsMode.d.ts +1 -1
  125. package/dist/enums/Sgp4OpsMode.js +1 -1
  126. package/dist/enums/index.d.ts +7 -7
  127. package/dist/enums/index.js +7 -7
  128. package/dist/enums/index.js.map +1 -1
  129. package/dist/fetch/horizons-constants.d.ts +43 -0
  130. package/dist/fetch/horizons-constants.js +50 -0
  131. package/dist/fetch/horizons-constants.js.map +1 -0
  132. package/dist/fetch/horizons-interfaces.d.ts +37 -0
  133. package/dist/fetch/horizons-interfaces.js +2 -0
  134. package/dist/fetch/horizons-interfaces.js.map +1 -0
  135. package/dist/fetch/horizons.d.ts +86 -0
  136. package/dist/fetch/horizons.js +237 -0
  137. package/dist/fetch/horizons.js.map +1 -0
  138. package/dist/force/AtmosphericDrag.d.ts +3 -3
  139. package/dist/force/AtmosphericDrag.js +2 -2
  140. package/dist/force/AtmosphericDrag.js.map +1 -1
  141. package/dist/force/EarthGravity.d.ts +3 -3
  142. package/dist/force/EarthGravity.js +2 -2
  143. package/dist/force/EarthGravity.js.map +1 -1
  144. package/dist/force/Force.d.ts +3 -3
  145. package/dist/force/Force.js +1 -10
  146. package/dist/force/Force.js.map +1 -1
  147. package/dist/force/ForceModel.d.ts +3 -3
  148. package/dist/force/ForceModel.js +7 -7
  149. package/dist/force/ForceModel.js.map +1 -1
  150. package/dist/force/Gravity.d.ts +3 -3
  151. package/dist/force/Gravity.js +2 -2
  152. package/dist/force/Gravity.js.map +1 -1
  153. package/dist/force/SolarRadiationPressure.d.ts +3 -3
  154. package/dist/force/SolarRadiationPressure.js +4 -4
  155. package/dist/force/SolarRadiationPressure.js.map +1 -1
  156. package/dist/force/ThirdBodyGravity.d.ts +3 -3
  157. package/dist/force/ThirdBodyGravity.js +2 -2
  158. package/dist/force/ThirdBodyGravity.js.map +1 -1
  159. package/dist/force/Thrust.d.ts +3 -3
  160. package/dist/force/Thrust.js +2 -2
  161. package/dist/force/Thrust.js.map +1 -1
  162. package/dist/force/index.d.ts +1 -1
  163. package/dist/force/index.js +1 -1
  164. package/dist/force/index.js.map +1 -1
  165. package/dist/interfaces/BaseObjectParams.d.ts +2 -2
  166. package/dist/interfaces/BaseObjectParams.js +1 -1
  167. package/dist/interfaces/ClassicalElementsParams.d.ts +2 -2
  168. package/dist/interfaces/ClassicalElementsParams.js +1 -1
  169. package/dist/interfaces/EquinoctialElementsParams.d.ts +2 -2
  170. package/dist/interfaces/EquinoctialElementsParams.js +1 -1
  171. package/dist/interfaces/GroundPositionParams.d.ts +2 -2
  172. package/dist/interfaces/GroundPositionParams.js +1 -1
  173. package/dist/interfaces/RfSensorParams.d.ts +2 -2
  174. package/dist/interfaces/SatelliteParams.d.ts +2 -2
  175. package/dist/interfaces/SensorParams.d.ts +2 -2
  176. package/dist/interfaces/StarObjectParams.d.ts +1 -1
  177. package/dist/interfaces/TimeVariables.d.ts +1 -1
  178. package/dist/interfaces/index.d.ts +9 -9
  179. package/dist/interpolator/ChebyshevCoefficients.d.ts +2 -2
  180. package/dist/interpolator/ChebyshevCoefficients.js +2 -2
  181. package/dist/interpolator/ChebyshevCoefficients.js.map +1 -1
  182. package/dist/interpolator/ChebyshevInterpolator.d.ts +4 -4
  183. package/dist/interpolator/ChebyshevInterpolator.js +3 -3
  184. package/dist/interpolator/ChebyshevInterpolator.js.map +1 -1
  185. package/dist/interpolator/CubicSpline.d.ts +2 -2
  186. package/dist/interpolator/CubicSpline.js +1 -1
  187. package/dist/interpolator/CubicSplineInterpolator.d.ts +4 -4
  188. package/dist/interpolator/CubicSplineInterpolator.js +4 -4
  189. package/dist/interpolator/CubicSplineInterpolator.js.map +1 -1
  190. package/dist/interpolator/FieldInterpolator.d.ts +3 -3
  191. package/dist/interpolator/FieldInterpolator.js +2 -12
  192. package/dist/interpolator/FieldInterpolator.js.map +1 -1
  193. package/dist/interpolator/Interpolator.d.ts +2 -2
  194. package/dist/interpolator/Interpolator.js +2 -2
  195. package/dist/interpolator/Interpolator.js.map +1 -1
  196. package/dist/interpolator/LagrangeInterpolator.d.ts +3 -3
  197. package/dist/interpolator/LagrangeInterpolator.js +3 -3
  198. package/dist/interpolator/LagrangeInterpolator.js.map +1 -1
  199. package/dist/interpolator/StateInterpolator.d.ts +4 -4
  200. package/dist/interpolator/StateInterpolator.js +2 -10
  201. package/dist/interpolator/StateInterpolator.js.map +1 -1
  202. package/dist/interpolator/VerletBlendInterpolator.d.ts +5 -5
  203. package/dist/interpolator/VerletBlendInterpolator.js +5 -5
  204. package/dist/interpolator/VerletBlendInterpolator.js.map +1 -1
  205. package/dist/main.d.ts +20 -20
  206. package/dist/main.js +21 -20
  207. package/dist/main.js.map +1 -1
  208. package/dist/maneuver/TwoBurnOrbitTransfer.d.ts +3 -3
  209. package/dist/maneuver/TwoBurnOrbitTransfer.js +3 -3
  210. package/dist/maneuver/TwoBurnOrbitTransfer.js.map +1 -1
  211. package/dist/maneuver/Waypoint.d.ts +5 -5
  212. package/dist/maneuver/Waypoint.js +7 -7
  213. package/dist/maneuver/Waypoint.js.map +1 -1
  214. package/dist/objects/BaseObject.d.ts +3 -3
  215. package/dist/objects/BaseObject.js +2 -2
  216. package/dist/objects/BaseObject.js.map +1 -1
  217. package/dist/objects/DetailedSatellite.d.ts +4 -4
  218. package/dist/objects/DetailedSatellite.js +4 -4
  219. package/dist/objects/DetailedSatellite.js.map +1 -1
  220. package/dist/objects/DetailedSensor.d.ts +5 -5
  221. package/dist/objects/DetailedSensor.js +2 -2
  222. package/dist/objects/DetailedSensor.js.map +1 -1
  223. package/dist/objects/GroundObject.d.ts +4 -4
  224. package/dist/objects/GroundObject.js +3 -3
  225. package/dist/objects/GroundObject.js.map +1 -1
  226. package/dist/objects/LandObject.d.ts +3 -3
  227. package/dist/objects/LandObject.js +2 -2
  228. package/dist/objects/LandObject.js.map +1 -1
  229. package/dist/objects/Marker.d.ts +2 -2
  230. package/dist/objects/Marker.js +2 -2
  231. package/dist/objects/Marker.js.map +1 -1
  232. package/dist/objects/RfSensor.d.ts +2 -2
  233. package/dist/objects/RfSensor.js +2 -2
  234. package/dist/objects/RfSensor.js.map +1 -1
  235. package/dist/objects/Satellite.d.ts +12 -12
  236. package/dist/objects/Satellite.js +14 -14
  237. package/dist/objects/Satellite.js.map +1 -1
  238. package/dist/objects/Sensor.d.ts +6 -6
  239. package/dist/objects/Sensor.js +5 -5
  240. package/dist/objects/Sensor.js.map +1 -1
  241. package/dist/objects/Star.d.ts +3 -3
  242. package/dist/objects/Star.js +3 -3
  243. package/dist/objects/Star.js.map +1 -1
  244. package/dist/objects/index.d.ts +10 -10
  245. package/dist/objects/index.js +10 -10
  246. package/dist/objects/index.js.map +1 -1
  247. package/dist/observation/Observation.d.ts +11 -11
  248. package/dist/observation/Observation.js +1 -52
  249. package/dist/observation/Observation.js.map +1 -1
  250. package/dist/observation/ObservationOptical.d.ts +6 -6
  251. package/dist/observation/ObservationOptical.js +4 -4
  252. package/dist/observation/ObservationOptical.js.map +1 -1
  253. package/dist/observation/ObservationRadar.d.ts +6 -6
  254. package/dist/observation/ObservationRadar.js +4 -4
  255. package/dist/observation/ObservationRadar.js.map +1 -1
  256. package/dist/observation/ObservationUtils.d.ts +2 -2
  257. package/dist/observation/ObservationUtils.js +2 -2
  258. package/dist/observation/ObservationUtils.js.map +1 -1
  259. package/dist/observation/PropagatorPairs.d.ts +2 -2
  260. package/dist/observation/PropagatorPairs.js +1 -1
  261. package/dist/observation/RAE.d.ts +6 -6
  262. package/dist/observation/RAE.js +6 -6
  263. package/dist/observation/RAE.js.map +1 -1
  264. package/dist/observation/RadecGeocentric.d.ts +6 -6
  265. package/dist/observation/RadecGeocentric.js +5 -5
  266. package/dist/observation/RadecGeocentric.js.map +1 -1
  267. package/dist/observation/RadecTopocentric.d.ts +6 -6
  268. package/dist/observation/RadecTopocentric.js +9 -7
  269. package/dist/observation/RadecTopocentric.js.map +1 -1
  270. package/dist/observation/index.d.ts +5 -5
  271. package/dist/observation/index.js +5 -5
  272. package/dist/observation/index.js.map +1 -1
  273. package/dist/operations/BoxMuller.d.ts +2 -2
  274. package/dist/operations/BoxMuller.js +2 -2
  275. package/dist/operations/BoxMuller.js.map +1 -1
  276. package/dist/operations/EulerAngles.d.ts +2 -2
  277. package/dist/operations/EulerAngles.js +2 -2
  278. package/dist/operations/EulerAngles.js.map +1 -1
  279. package/dist/operations/Matrix.d.ts +2 -2
  280. package/dist/operations/Matrix.js +2 -2
  281. package/dist/operations/Matrix.js.map +1 -1
  282. package/dist/operations/Quaternion.d.ts +2 -2
  283. package/dist/operations/Quaternion.js +2 -2
  284. package/dist/operations/Quaternion.js.map +1 -1
  285. package/dist/operations/Random.d.ts +1 -1
  286. package/dist/operations/Random.js +1 -1
  287. package/dist/operations/RandomGaussianSource.d.ts +2 -2
  288. package/dist/operations/RandomGaussianSource.js +3 -3
  289. package/dist/operations/RandomGaussianSource.js.map +1 -1
  290. package/dist/operations/Vector.d.ts +2 -2
  291. package/dist/operations/Vector.js +2 -2
  292. package/dist/operations/Vector.js.map +1 -1
  293. package/dist/operations/Vector3D.d.ts +5 -4
  294. package/dist/operations/Vector3D.js +5 -4
  295. package/dist/operations/Vector3D.js.map +1 -1
  296. package/dist/operations/index.d.ts +4 -4
  297. package/dist/operations/index.js +4 -4
  298. package/dist/operations/index.js.map +1 -1
  299. package/dist/operations/operations.d.ts +5 -5
  300. package/dist/operations/operations.js +5 -5
  301. package/dist/operations/operations.js.map +1 -1
  302. package/dist/optimize/ChebyshevCompressor.d.ts +3 -3
  303. package/dist/optimize/ChebyshevCompressor.js +4 -4
  304. package/dist/optimize/ChebyshevCompressor.js.map +1 -1
  305. package/dist/optimize/DownhillSimplex.d.ts +2 -2
  306. package/dist/optimize/DownhillSimplex.js +2 -2
  307. package/dist/optimize/DownhillSimplex.js.map +1 -1
  308. package/dist/optimize/GoldenSection.d.ts +2 -2
  309. package/dist/optimize/GoldenSection.js +1 -1
  310. package/dist/optimize/PolynomialRegression.d.ts +2 -2
  311. package/dist/optimize/PolynomialRegression.js +4 -4
  312. package/dist/optimize/PolynomialRegression.js.map +1 -1
  313. package/dist/optimize/PolynomicalRegressionResult.d.ts +1 -1
  314. package/dist/optimize/PolynomicalRegressionResult.js +1 -1
  315. package/dist/optimize/SimpleLinearRegression.d.ts +1 -1
  316. package/dist/optimize/SimpleLinearRegression.js +1 -1
  317. package/dist/optimize/SimplexEntry.d.ts +1 -1
  318. package/dist/optimize/SimplexEntry.js +2 -2
  319. package/dist/optimize/SimplexEntry.js.map +1 -1
  320. package/dist/orbit_determination/BatchLeastSquaresOD.d.ts +5 -5
  321. package/dist/orbit_determination/BatchLeastSquaresOD.js +8 -8
  322. package/dist/orbit_determination/BatchLeastSquaresOD.js.map +1 -1
  323. package/dist/orbit_determination/BatchLeastSquaresResult.d.ts +3 -3
  324. package/dist/orbit_determination/BatchLeastSquaresResult.js +1 -1
  325. package/dist/orbit_determination/GaussIOD.d.ts +98 -0
  326. package/dist/orbit_determination/GaussIOD.js +291 -0
  327. package/dist/orbit_determination/GaussIOD.js.map +1 -0
  328. package/dist/orbit_determination/GibbsIOD.d.ts +2 -2
  329. package/dist/orbit_determination/GibbsIOD.js +4 -4
  330. package/dist/orbit_determination/GibbsIOD.js.map +1 -1
  331. package/dist/orbit_determination/GoodingIOD.d.ts +58 -8
  332. package/dist/orbit_determination/GoodingIOD.js +225 -35
  333. package/dist/orbit_determination/GoodingIOD.js.map +1 -1
  334. package/dist/orbit_determination/HerrickGibbsIOD.d.ts +2 -2
  335. package/dist/orbit_determination/HerrickGibbsIOD.js +2 -2
  336. package/dist/orbit_determination/HerrickGibbsIOD.js.map +1 -1
  337. package/dist/orbit_determination/LambertIOD.d.ts +2 -2
  338. package/dist/orbit_determination/LambertIOD.js +2 -2
  339. package/dist/orbit_determination/LambertIOD.js.map +1 -1
  340. package/dist/orbit_determination/ModifiedGoodingIOD.d.ts +3 -3
  341. package/dist/orbit_determination/ModifiedGoodingIOD.js +8 -8
  342. package/dist/orbit_determination/ModifiedGoodingIOD.js.map +1 -1
  343. package/dist/orbit_determination/index.d.ts +7 -7
  344. package/dist/orbit_determination/index.js +7 -7
  345. package/dist/orbit_determination/index.js.map +1 -1
  346. package/dist/propagator/DormandPrince54Propagator.d.ts +2 -2
  347. package/dist/propagator/DormandPrince54Propagator.js +2 -2
  348. package/dist/propagator/DormandPrince54Propagator.js.map +1 -1
  349. package/dist/propagator/KeplerPropagator.d.ts +6 -6
  350. package/dist/propagator/KeplerPropagator.js +6 -7
  351. package/dist/propagator/KeplerPropagator.js.map +1 -1
  352. package/dist/propagator/Propagator.d.ts +5 -5
  353. package/dist/propagator/Propagator.js +5 -5
  354. package/dist/propagator/Propagator.js.map +1 -1
  355. package/dist/propagator/RkCheckpoint.d.ts +2 -2
  356. package/dist/propagator/RkCheckpoint.js +1 -1
  357. package/dist/propagator/RkResult.d.ts +2 -2
  358. package/dist/propagator/RkResult.js +1 -1
  359. package/dist/propagator/RungeKutta4Propagator.d.ts +6 -6
  360. package/dist/propagator/RungeKutta4Propagator.js +5 -5
  361. package/dist/propagator/RungeKutta4Propagator.js.map +1 -1
  362. package/dist/propagator/RungeKutta89Propagator.d.ts +2 -2
  363. package/dist/propagator/RungeKutta89Propagator.js +2 -2
  364. package/dist/propagator/RungeKutta89Propagator.js.map +1 -1
  365. package/dist/propagator/RungeKuttaAdaptive.d.ts +6 -6
  366. package/dist/propagator/RungeKuttaAdaptive.js +52 -9
  367. package/dist/propagator/RungeKuttaAdaptive.js.map +1 -1
  368. package/dist/propagator/Sgp4Propagator.d.ts +7 -7
  369. package/dist/propagator/Sgp4Propagator.js +4 -4
  370. package/dist/propagator/Sgp4Propagator.js.map +1 -1
  371. package/dist/propagator/index.d.ts +3 -3
  372. package/dist/propagator/index.js +3 -3
  373. package/dist/propagator/index.js.map +1 -1
  374. package/dist/sgp4/index.d.ts +2 -2
  375. package/dist/sgp4/index.js +2 -2
  376. package/dist/sgp4/index.js.map +1 -1
  377. package/dist/sgp4/sgp4.d.ts +3 -3
  378. package/dist/sgp4/sgp4.js +11 -5
  379. package/dist/sgp4/sgp4.js.map +1 -1
  380. package/dist/smoothing/ExponentialSmoothing.d.ts +2 -2
  381. package/dist/smoothing/ExponentialSmoothing.js +1 -1
  382. package/dist/time/Epoch.d.ts +2 -2
  383. package/dist/time/Epoch.js +2 -2
  384. package/dist/time/Epoch.js.map +1 -1
  385. package/dist/time/EpochGPS.d.ts +3 -3
  386. package/dist/time/EpochGPS.js +3 -3
  387. package/dist/time/EpochGPS.js.map +1 -1
  388. package/dist/time/EpochTAI.d.ts +2 -2
  389. package/dist/time/EpochTAI.js +2 -2
  390. package/dist/time/EpochTAI.js.map +1 -1
  391. package/dist/time/EpochTDB.d.ts +2 -2
  392. package/dist/time/EpochTDB.js +2 -2
  393. package/dist/time/EpochTDB.js.map +1 -1
  394. package/dist/time/EpochTT.d.ts +2 -2
  395. package/dist/time/EpochTT.js +2 -2
  396. package/dist/time/EpochTT.js.map +1 -1
  397. package/dist/time/EpochUTC.d.ts +7 -7
  398. package/dist/time/EpochUTC.js +9 -9
  399. package/dist/time/EpochUTC.js.map +1 -1
  400. package/dist/time/EpochWindow.d.ts +2 -2
  401. package/dist/time/EpochWindow.js +1 -1
  402. package/dist/time/TimeStamped.d.ts +2 -2
  403. package/dist/time/TimeStamped.js +1 -1
  404. package/dist/time/index.d.ts +8 -8
  405. package/dist/time/index.js +8 -8
  406. package/dist/time/index.js.map +1 -1
  407. package/dist/transforms/TransformCache.d.ts +1 -1
  408. package/dist/transforms/TransformCache.js +1 -1
  409. package/dist/transforms/conversions.d.ts +2 -2
  410. package/dist/transforms/conversions.js +2 -2
  411. package/dist/transforms/conversions.js.map +1 -1
  412. package/dist/transforms/index.d.ts +2 -2
  413. package/dist/transforms/index.js +2 -2
  414. package/dist/transforms/index.js.map +1 -1
  415. package/dist/transforms/transforms.d.ts +1 -1
  416. package/dist/transforms/transforms.js +1 -1
  417. package/dist/transforms/transforms.js.map +1 -1
  418. package/dist/types/types.d.ts +8 -3
  419. package/dist/types/types.js +6 -1
  420. package/dist/types/types.js.map +1 -1
  421. package/dist/utils/constants.d.ts +2 -2
  422. package/dist/utils/constants.js +1 -1
  423. package/dist/utils/constants.js.map +1 -1
  424. package/dist/utils/create-covariance-from-tle.d.ts +1 -1
  425. package/dist/utils/create-covariance-from-tle.js +1 -1
  426. package/dist/utils/create-covariance-from-tle.js.map +1 -1
  427. package/dist/utils/functions.d.ts +4 -4
  428. package/dist/utils/functions.js +9 -4
  429. package/dist/utils/functions.js.map +1 -1
  430. package/dist/utils/index.d.ts +5 -5
  431. package/dist/utils/index.js +5 -5
  432. package/dist/utils/index.js.map +1 -1
  433. package/dist/utils/jacobian.d.ts +2 -2
  434. package/dist/utils/jacobian.js +1 -1
  435. package/dist/utils/jacobian.js.map +1 -1
  436. package/dist/utils/linearDistance.d.ts +1 -1
  437. package/docs/README.md +132 -0
  438. package/docs/getting-started.md +792 -0
  439. package/docs/lambert-satellite-integration-guide.md +766 -0
  440. package/docs/user-guide.md +1935 -0
  441. package/jest.config.mjs +28 -0
  442. package/package.json +3 -4
  443. package/src/body/Celestial.ts +2 -2
  444. package/src/body/Earth.ts +4 -4
  445. package/src/body/Moon.ts +7 -7
  446. package/src/body/NutationAngles.ts +2 -2
  447. package/src/body/PrecessionAngles.ts +2 -2
  448. package/src/body/Sun.ts +4 -4
  449. package/src/body/index.ts +6 -5
  450. package/src/conjunction/ConjunctionAssessment.ts +417 -0
  451. package/src/conjunction/ConjunctionEvent.ts +149 -0
  452. package/src/conjunction/ProbabilityOfCollision.ts +300 -0
  453. package/src/conjunction/index.ts +24 -0
  454. package/src/coordinate/ClassicalElements.ts +16 -11
  455. package/src/coordinate/EquinoctialElements.ts +7 -7
  456. package/src/coordinate/FormatTle.ts +2 -2
  457. package/src/coordinate/Geodetic.ts +8 -8
  458. package/src/coordinate/Hill.ts +4 -4
  459. package/src/coordinate/ITRF.ts +6 -6
  460. package/src/coordinate/J2000.ts +7 -7
  461. package/src/coordinate/RIC.ts +4 -4
  462. package/src/coordinate/RelativeState.ts +5 -5
  463. package/src/coordinate/StateVector.ts +8 -3
  464. package/src/coordinate/TEME.ts +6 -6
  465. package/src/coordinate/Tle.ts +9 -9
  466. package/src/coordinate/index.ts +13 -12
  467. package/src/coordinate/tle-format-data.ts +1 -1
  468. package/src/covariance/CovarianceSample.ts +13 -13
  469. package/src/covariance/StateCovariance.ts +2 -2
  470. package/src/covariance/index.ts +3 -2
  471. package/src/data/DataHandler.ts +6 -6
  472. package/src/data/values/Egm96Data.ts +3 -3
  473. package/src/data/values/HpAtmosphereData.ts +3 -3
  474. package/src/data/values/HpAtmosphereResult.ts +2 -2
  475. package/src/data/values/Iau1980Data.ts +2 -2
  476. package/src/data/values/LeapSecond.ts +1 -1
  477. package/src/data/values/LeapSecondData.ts +2 -2
  478. package/src/data/values/egm96.ts +2 -2
  479. package/src/data/values/hpAtmosphere.ts +2 -2
  480. package/src/data/values/iau1980.ts +2 -2
  481. package/src/enums/AngularDiameterMethod.ts +1 -1
  482. package/src/enums/AngularDistanceMethod.ts +1 -1
  483. package/src/enums/OrbitRegime.ts +1 -1
  484. package/src/enums/PassType.ts +1 -1
  485. package/src/enums/Sgp4OpsMode.ts +1 -1
  486. package/src/enums/index.ts +8 -7
  487. package/src/fetch/horizons-constants.ts +53 -0
  488. package/src/fetch/horizons-interfaces.ts +38 -0
  489. package/src/fetch/horizons.ts +300 -0
  490. package/src/force/AtmosphericDrag.ts +3 -3
  491. package/src/force/EarthGravity.ts +3 -3
  492. package/src/force/Force.ts +3 -5
  493. package/src/force/ForceModel.ts +9 -9
  494. package/src/force/Gravity.ts +3 -3
  495. package/src/force/SolarRadiationPressure.ts +4 -4
  496. package/src/force/ThirdBodyGravity.ts +3 -3
  497. package/src/force/Thrust.ts +3 -3
  498. package/src/force/index.ts +2 -1
  499. package/src/interfaces/BaseObjectParams.ts +2 -2
  500. package/src/interfaces/ClassicalElementsParams.ts +2 -2
  501. package/src/interfaces/EquinoctialElementsParams.ts +2 -2
  502. package/src/interfaces/GroundPositionParams.ts +2 -2
  503. package/src/interfaces/RfSensorParams.ts +2 -2
  504. package/src/interfaces/SatelliteParams.ts +2 -2
  505. package/src/interfaces/SensorParams.ts +3 -3
  506. package/src/interfaces/StarObjectParams.ts +1 -1
  507. package/src/interfaces/TimeVariables.ts +1 -1
  508. package/src/interfaces/index.ts +10 -9
  509. package/src/interpolator/ChebyshevCoefficients.ts +2 -2
  510. package/src/interpolator/ChebyshevInterpolator.ts +4 -4
  511. package/src/interpolator/CubicSpline.ts +2 -2
  512. package/src/interpolator/CubicSplineInterpolator.ts +4 -4
  513. package/src/interpolator/FieldInterpolator.ts +3 -5
  514. package/src/interpolator/Interpolator.ts +2 -2
  515. package/src/interpolator/LagrangeInterpolator.ts +3 -3
  516. package/src/interpolator/StateInterpolator.ts +4 -6
  517. package/src/interpolator/VerletBlendInterpolator.ts +5 -5
  518. package/src/main.ts +41 -20
  519. package/src/maneuver/TwoBurnOrbitTransfer.ts +3 -3
  520. package/src/maneuver/Waypoint.ts +8 -8
  521. package/src/objects/BaseObject.ts +3 -3
  522. package/src/objects/DetailedSatellite.ts +9 -9
  523. package/src/objects/DetailedSensor.ts +5 -5
  524. package/src/objects/GroundObject.ts +9 -9
  525. package/src/objects/LandObject.ts +3 -3
  526. package/src/objects/Marker.ts +2 -2
  527. package/src/objects/RfSensor.ts +2 -2
  528. package/src/objects/Satellite.ts +21 -21
  529. package/src/objects/Sensor.ts +7 -7
  530. package/src/objects/Star.ts +3 -3
  531. package/src/objects/index.ts +11 -10
  532. package/src/observation/Observation.ts +11 -23
  533. package/src/observation/ObservationOptical.ts +7 -7
  534. package/src/observation/ObservationRadar.ts +7 -7
  535. package/src/observation/ObservationUtils.ts +2 -2
  536. package/src/observation/PropagatorPairs.ts +2 -2
  537. package/src/observation/RAE.ts +9 -9
  538. package/src/observation/RadecGeocentric.ts +9 -9
  539. package/src/observation/RadecTopocentric.ts +13 -10
  540. package/src/observation/index.ts +6 -5
  541. package/src/operations/BoxMuller.ts +2 -2
  542. package/src/operations/EulerAngles.ts +2 -2
  543. package/src/operations/Matrix.ts +2 -2
  544. package/src/operations/Quaternion.ts +2 -2
  545. package/src/operations/Random.ts +1 -1
  546. package/src/operations/RandomGaussianSource.ts +3 -3
  547. package/src/operations/Vector.ts +2 -2
  548. package/src/operations/Vector3D.ts +6 -4
  549. package/src/operations/index.ts +5 -4
  550. package/src/operations/operations.ts +6 -5
  551. package/src/optimize/ChebyshevCompressor.ts +5 -5
  552. package/src/optimize/DownhillSimplex.ts +2 -2
  553. package/src/optimize/GoldenSection.ts +2 -2
  554. package/src/optimize/PolynomialRegression.ts +4 -4
  555. package/src/optimize/PolynomicalRegressionResult.ts +1 -1
  556. package/src/optimize/SimpleLinearRegression.ts +1 -1
  557. package/src/optimize/SimplexEntry.ts +2 -2
  558. package/src/orbit_determination/BatchLeastSquaresOD.ts +10 -10
  559. package/src/orbit_determination/BatchLeastSquaresResult.ts +3 -3
  560. package/src/orbit_determination/GaussIOD.ts +393 -0
  561. package/src/orbit_determination/GibbsIOD.ts +4 -4
  562. package/src/orbit_determination/GoodingIOD.ts +458 -160
  563. package/src/orbit_determination/HerrickGibbsIOD.ts +2 -2
  564. package/src/orbit_determination/LambertIOD.ts +2 -2
  565. package/src/orbit_determination/ModifiedGoodingIOD.ts +33 -22
  566. package/src/orbit_determination/index.ts +8 -7
  567. package/src/propagator/DormandPrince54Propagator.ts +2 -2
  568. package/src/propagator/KeplerPropagator.ts +7 -8
  569. package/src/propagator/Propagator.ts +6 -6
  570. package/src/propagator/RkCheckpoint.ts +2 -2
  571. package/src/propagator/RkResult.ts +2 -2
  572. package/src/propagator/RungeKutta4Propagator.ts +6 -6
  573. package/src/propagator/RungeKutta89Propagator.ts +2 -2
  574. package/src/propagator/RungeKuttaAdaptive.ts +62 -12
  575. package/src/propagator/Sgp4Propagator.ts +7 -7
  576. package/src/propagator/index.ts +4 -3
  577. package/src/sgp4/index.ts +3 -2
  578. package/src/sgp4/sgp4.ts +6 -6
  579. package/src/smoothing/ExponentialSmoothing.ts +2 -2
  580. package/src/time/Epoch.ts +3 -3
  581. package/src/time/EpochGPS.ts +5 -5
  582. package/src/time/EpochTAI.ts +2 -2
  583. package/src/time/EpochTDB.ts +2 -2
  584. package/src/time/EpochTT.ts +2 -2
  585. package/src/time/EpochUTC.ts +10 -10
  586. package/src/time/EpochWindow.ts +2 -2
  587. package/src/time/TimeStamped.ts +2 -2
  588. package/src/time/index.ts +9 -8
  589. package/src/transforms/TransformCache.ts +1 -1
  590. package/src/transforms/conversions.ts +2 -2
  591. package/src/transforms/index.ts +3 -2
  592. package/src/transforms/transforms.ts +4 -4
  593. package/src/types/types.ts +8 -3
  594. package/src/utils/constants.ts +2 -2
  595. package/src/utils/create-covariance-from-tle.ts +1 -1
  596. package/src/utils/functions.ts +10 -5
  597. package/src/utils/index.ts +6 -5
  598. package/src/utils/jacobian.ts +2 -2
  599. package/src/utils/linearDistance.ts +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @author @thkruz Theodore Kruczek
2
+ * @author Theodore Kruczek
3
3
  * @license AGPL-3.0-or-later
4
4
  * @copyright (c) 2025 Kruczek Labs LLC
5
5
  *
@@ -15,19 +15,20 @@
15
15
  * Orbital Object ToolKit. If not, see <http://www.gnu.org/licenses/>.
16
16
  */
17
17
 
18
- import { Earth, J2000, Kilometers, KilometersPerSecond, Seconds, TAU, Vector3D } from '../main.js';
19
- import { ForceModel } from '../force/ForceModel.js';
20
- import { RungeKutta89Propagator } from '../propagator/RungeKutta89Propagator.js';
21
- import { ObservationOptical } from './../observation/ObservationOptical.js';
22
- import { GibbsIOD } from './GibbsIOD.js';
23
- import { LambertIOD } from './LambertIOD.js';
18
+ import { ForceModel } from '../force/ForceModel';
19
+ import { Earth, J2000, Kilometers, KilometersPerSecond, Seconds, TAU, Vector3D } from '../main';
20
+ import { RungeKutta89Propagator } from '../propagator/RungeKutta89Propagator';
21
+ import { ObservationOptical } from './../observation/ObservationOptical';
22
+ import { GaussIOD } from './GaussIOD';
23
+ import { GibbsIOD } from './GibbsIOD';
24
+ import { LambertIOD } from './LambertIOD';
24
25
 
25
26
  type SolveRangeProblemParams = {
26
27
  rho1init: Kilometers;
27
28
  rho3init: Kilometers;
28
29
  t13: Seconds;
29
30
  t12: Seconds;
30
- nrev: number;
31
+ nRev: number;
31
32
  direction: boolean;
32
33
  lineOfSight1: Vector3D<Kilometers>;
33
34
  lineOfSight2: Vector3D<Kilometers>;
@@ -42,8 +43,11 @@ type ComputeDerivativesParams = {
42
43
  lineOfSight3: Vector3D<Kilometers>;
43
44
  pin: Vector3D<Kilometers>;
44
45
  ein: Vector3D<Kilometers>;
46
+ fc: number;
47
+ gc: number;
45
48
  t13: Seconds
46
49
  t12: Seconds;
50
+ withHalley: boolean;
47
51
  nrev: number;
48
52
  direction: boolean;
49
53
  fd: Float64Array;
@@ -67,86 +71,325 @@ type GetPositionOnLoS2Params = {
67
71
  * Used for orbit determination from three optical observations.
68
72
  */
69
73
  export class GoodingIOD {
74
+ /** Finite difference factor for numerical derivatives */
75
+ private static readonly FINITE_DIFF_FACTOR = 1e-6;
76
+ /** Convergence tolerance for iterative solver */
77
+ private static readonly CONVERGENCE_TOLERANCE = 1e-14;
78
+ /** Maximum iterations for range problem solver */
79
+ private static readonly MAX_ITERATIONS = 100;
80
+ /** Minimum determinant value to avoid numerical issues */
81
+ private static readonly MIN_DETERMINANT = 1e-16;
82
+ /** Gravitational constant. */
70
83
  private readonly _mu: number;
71
- private readonly o1_: ObservationOptical;
72
- private readonly o2_: ObservationOptical;
73
- private readonly o3_: ObservationOptical;
84
+ /** observation 1 */
85
+ private o1_!: ObservationOptical;
86
+ /** observation 2 */
87
+ private o2_!: ObservationOptical;
88
+ /** observation 3 */
89
+ private o3_!: ObservationOptical;
90
+ /** observer position 1 */
74
91
  private vObserverPosition1_ = Vector3D.origin as Vector3D<Kilometers>;
92
+ /** observer position 2 */
75
93
  private vObserverPosition2_ = Vector3D.origin as Vector3D<Kilometers>;
94
+ /** observer position 3 */
76
95
  private vObserverPosition3_ = Vector3D.origin as Vector3D<Kilometers>;
77
- private r_ = 0.0 as Kilometers;
96
+ /** Normalizing constant for distances. */
97
+ private r_ = 0.0;
98
+ /** Normalizing constant for velocities. */
78
99
  private v_ = 0.0;
100
+ /** Normalizing constant for duration. */
79
101
  private t_ = 0.0;
102
+ /** Radius of point 1 (X-R1). */
80
103
  private r1_ = 0.0;
104
+ /** Radius of point 2 (X-R2). */
81
105
  private r2_ = 0.0;
106
+ /** Radius of point 3 (X-R3). */
82
107
  private r3_ = 0.0;
108
+ /** Range of point 1 (O1-R1). */
83
109
  private rho1_ = 0.0 as Kilometers;
110
+ /** Range of point 2 (O1-R1). */
84
111
  private rho2_ = 0.0 as Kilometers;
112
+ /** Range of point 3 (O1-R1). */
85
113
  private rho3_ = 0.0 as Kilometers;
114
+ /** working variable */
86
115
  private d1_ = 0.0 as Kilometers;
116
+ /** working variable */
87
117
  private d3_ = 0.0 as Kilometers;
118
+ /** factor for FD. */
88
119
  private facFiniteDiff_ = 0.0;
89
120
  private readonly _forceModel: ForceModel = new ForceModel().setGravity(1.0);
90
121
 
91
- constructor(o1: ObservationOptical, o2: ObservationOptical, o3: ObservationOptical, mu: number = Earth.mu) {
122
+ constructor(mu: number = Earth.mu) {
92
123
  this._mu = mu;
124
+ }
125
+
126
+ getRange1(): Kilometers {
127
+ return this.rho1_ * this.r_ as Kilometers;
128
+ }
129
+
130
+ getRange2(): Kilometers {
131
+ return this.rho2_ * this.r_ as Kilometers;
132
+ }
133
+
134
+ getRange3(): Kilometers {
135
+ return this.rho3_ * this.r_ as Kilometers;
136
+ }
137
+
138
+ /**
139
+ * Estimate an orbit from three angular observations (azimuth/elevation).
140
+ * Uses Gauss IOD to derive initial range estimates, so no external range
141
+ * guesses are required.
142
+ *
143
+ * @param o1 - first angular observation
144
+ * @param o2 - second angular observation
145
+ * @param o3 - third angular observation
146
+ * @param nRev - number of full revolutions between observation 1 and 3
147
+ * @param direction - true for prograde (short-way), false for retrograde
148
+ * @returns Orbit estimate referenced to the epoch of the second observation
149
+ */
150
+ estimate(o1: ObservationOptical, o2: ObservationOptical, o3: ObservationOptical,
151
+ rho1init: Kilometers| null = null, rho3init: Kilometers | null = null,
152
+ nRev = 0, direction = true,
153
+ ): J2000 {
154
+ let orbit: J2000 | null = null;
155
+
156
+
157
+ if (rho1init === null || rho3init === null) {
158
+ const gaussIod = new GaussIOD(this._mu);
159
+
160
+ orbit = gaussIod.estimate(o1, o2, o3);
161
+
162
+ if (orbit === null) {
163
+ throw new Error('Gauss IOD failed to provide initial estimate for Gooding IOD.');
164
+ }
165
+
166
+ /*
167
+ * Compute slant ranges (observer-to-satellite distance) from Gauss IOD solution
168
+ * The Gauss solution is at t2 (middle observation), so we use it as approximation
169
+ * Slant range = |satellite position - observer position|
170
+ */
171
+ const rho1Gauss = orbit.position.subtract(o1.site.position).magnitude();
172
+ const rho3Gauss = orbit.position.subtract(o3.site.position).magnitude();
173
+
174
+ rho1init = rho1init ?? rho1Gauss;
175
+ rho3init = rho3init ?? rho3Gauss;
176
+ }
177
+
178
+ return this.solve(
179
+ o1,
180
+ o2,
181
+ o3,
182
+ rho1init,
183
+ rho3init,
184
+ nRev,
185
+ direction,
186
+ );
187
+ }
188
+
189
+ /**
190
+ * @param r1Init - Initial guess for range at first observation
191
+ * @param r3Init - Initial guess for range at third observation
192
+ * @param nRev - Number of revolutions
193
+ * @param direction - Direction of orbit (true for prograde, false for retrograde)
194
+ * @returns
195
+ */
196
+ solve(o1: ObservationOptical, o2: ObservationOptical, o3: ObservationOptical,
197
+ r1Init: Kilometers, r3Init: Kilometers, nRev = 0, direction = true,
198
+ ): J2000 {
93
199
  this.o1_ = o1;
94
200
  this.o2_ = o2;
95
201
  this.o3_ = o3;
202
+
203
+ const lineOfSight1 = this.o1_.observation.lineOfSight() as Vector3D<Kilometers>;
204
+ const lineOfSight2 = this.o2_.observation.lineOfSight() as Vector3D<Kilometers>;
205
+ const lineOfSight3 = this.o3_.observation.lineOfSight() as Vector3D<Kilometers>;
206
+
207
+ this.r_ = Math.max(r1Init, r3Init) as Kilometers;
208
+ this.v_ = Math.sqrt(this._mu / this.r_);
209
+ this.t_ = this.r_ / this.v_;
210
+
211
+ // Normalize observer positions (dimensionless)
212
+ const invR = 1.0 / this.r_;
213
+
214
+ this.vObserverPosition1_ = this.o1_.site.position.scale(invR) as Vector3D<Kilometers>;
215
+ this.vObserverPosition2_ = this.o2_.site.position.scale(invR) as Vector3D<Kilometers>;
216
+ this.vObserverPosition3_ = this.o3_.site.position.scale(invR) as Vector3D<Kilometers>;
217
+
218
+ const converged = this.solveRangeProblem_({
219
+ rho1init: r1Init / this.r_ as Kilometers,
220
+ rho3init: r3Init / this.r_ as Kilometers,
221
+ t13: this.o3_.epoch.difference(this.o1_.epoch) / this.t_ as Seconds,
222
+ t12: this.o2_.epoch.difference(this.o1_.epoch) / this.t_ as Seconds,
223
+ nRev,
224
+ direction,
225
+ lineOfSight1,
226
+ lineOfSight2,
227
+ lineOfSight3,
228
+ maxIterations: GoodingIOD.MAX_ITERATIONS,
229
+ });
230
+
231
+ if (!converged) {
232
+ throw new Error(
233
+ `Gooding IOD failed to converge after ${GoodingIOD.MAX_ITERATIONS} iterations. ` +
234
+ 'Try different initial range estimates or check observation quality.',
235
+ );
236
+ }
237
+
238
+ const gibbs = new GibbsIOD(this._mu);
239
+ const p1 = this.vObserverPosition1_.add(lineOfSight1.scale(this.rho1_)).scale(this.r_) as Vector3D<Kilometers>;
240
+ const p2 = this.vObserverPosition2_.add(lineOfSight2.scale(this.rho2_)).scale(this.r_) as Vector3D<Kilometers>;
241
+ const p3 = this.vObserverPosition3_.add(lineOfSight3.scale(this.rho3_)).scale(this.r_) as Vector3D<Kilometers>;
242
+
243
+ return gibbs.solve(p1, p2, p3, this.o2_.epoch, this.o3_.epoch);
96
244
  }
97
245
 
98
- private _getPositionOnLoS2({
99
- e1,
100
- r01,
101
- e3,
102
- r03,
246
+ /**
247
+ * Solve the range problem when three line of sight are given.
248
+ * @param frame frame to be used (orbit frame)
249
+ * @param rho1init initial value for range R1, in meters
250
+ * @param rho3init initial value for range R3, in meters
251
+ * @param T13 time of flight 1->3, in seconds
252
+ * @param T12 time of flight 1->2, in seconds
253
+ * @param nRev number of revolutions
254
+ * @param direction posigrade (true) or retrograde
255
+ * @param lineOfSight1 line of sight 1
256
+ * @param lineOfSight2 line of sight 2
257
+ * @param lineOfSight3 line of sight 3
258
+ */
259
+ private solveRangeProblem_({
260
+ rho1init,
261
+ rho3init,
103
262
  t13,
104
263
  t12,
105
264
  nRev,
106
- posigrade,
107
- }: GetPositionOnLoS2Params): Vector3D<Kilometers> | null {
108
- const p1 = this.vObserverPosition1_.add(e1.scale(r01));
265
+ direction,
266
+ lineOfSight1,
267
+ lineOfSight2,
268
+ lineOfSight3,
269
+ maxIterations,
270
+ }: SolveRangeProblemParams): boolean {
271
+ this.rho1_ = rho1init;
272
+ this.rho3_ = rho3init;
109
273
 
110
- this.r1_ = p1.magnitude();
274
+ let iter = 0;
275
+ let withHalley = false; // Start with Newton-Raphson, switch to Halley's method later
276
+ let stoppingCriterion = 10.0 * GoodingIOD.CONVERGENCE_TOLERANCE;
111
277
 
112
- const p3 = this.vObserverPosition3_.add(e3.scale(r03));
278
+ while (iter < maxIterations && Math.abs(stoppingCriterion) > GoodingIOD.CONVERGENCE_TOLERANCE) {
279
+ this.facFiniteDiff_ = GoodingIOD.FINITE_DIFF_FACTOR;
113
280
 
114
- this.r3_ = p3.magnitude();
281
+ // Switch to Halley's method after half the iterations for better convergence
282
+ if (iter >= maxIterations / 2) {
283
+ withHalley = true;
284
+ }
115
285
 
116
- const p13 = p1.cross(p3);
286
+ const p2 = this.getPositionOnLoS2_({
287
+ e1: lineOfSight1,
288
+ r01: this.rho1_,
289
+ e3: lineOfSight3,
290
+ r03: this.rho3_,
291
+ t13,
292
+ t12,
293
+ nRev,
294
+ posigrade: direction,
295
+ });
117
296
 
118
- let th = Math.atan2(p13.magnitude(), p1.dot(p3));
297
+ if (p2 === null) {
298
+ this.modifyIterate_(lineOfSight1, lineOfSight3);
299
+ } else {
300
+ this.r2_ = p2.magnitude();
301
+ const c = p2.subtract(this.vObserverPosition2_);
119
302
 
120
- if (!posigrade) {
121
- th = TAU - th;
122
- }
303
+ this.rho2_ = c.magnitude();
304
+ const cr = lineOfSight2.dot(c);
123
305
 
124
- const v1 = new Float64Array(2);
125
- const exitflag = LambertIOD.solve(this.r1_, this.r3_, th, t13, nRev, v1);
306
+ const u = lineOfSight2.cross(c);
307
+ const p = u.cross(lineOfSight2).normalize();
308
+ const ent = lineOfSight2.cross(p);
126
309
 
127
- if (exitflag) {
128
- const pn = p1.cross(p3);
129
- const pt = pn.cross(p1);
310
+ const enr = ent.magnitude();
130
311
 
131
- let rt = pt.magnitude();
312
+ if (enr === 0.0) {
313
+ break; // Solution found - line of sight and position are aligned
314
+ }
132
315
 
133
- if (!posigrade) {
134
- rt = -rt as Kilometers;
135
- }
316
+ const en = ent.normalize();
136
317
 
137
- const vel1 = p1.scale(v1[0] / this.r1_).add(pt.scale(v1[1] / rt)) as Vector3D<KilometersPerSecond>;
318
+ const fc = p.dot(c);
319
+ const gc = en.dot(c);
138
320
 
139
- const p2 = new RungeKutta89Propagator(new J2000(this.o1_.epoch, p1, vel1), this._forceModel).propagate(
140
- this.o1_.epoch.roll(t12),
141
- ).position;
321
+ const fd = new Float64Array(2);
322
+ const gd = new Float64Array(2);
142
323
 
143
- return p2;
324
+ this.computeDerivatives_({
325
+ x: this.rho1_,
326
+ y: this.rho3_,
327
+ lineOfSight1,
328
+ lineOfSight3,
329
+ pin: p,
330
+ ein: en,
331
+ fc,
332
+ gc,
333
+ t13,
334
+ t12,
335
+ withHalley,
336
+ nrev: nRev,
337
+ direction,
338
+ fd,
339
+ gd,
340
+ });
341
+
342
+ const fr1 = fd[0];
343
+ const fr3 = fd[1];
344
+ const gr1 = gd[0];
345
+ const gr3 = gd[1];
346
+ const detj = fr1 * gr3 - fr3 * gr1;
347
+
348
+ // Check for singular Jacobian matrix
349
+ if (Math.abs(detj) < GoodingIOD.MIN_DETERMINANT) {
350
+ throw new Error('Jacobian determinant is near zero - system is ill-conditioned.');
351
+ }
352
+
353
+ /**
354
+ * Compute Newton-Raphson corrections
355
+ * Per Gooding's algorithm:
356
+ * D3 is the correction for rho1 (range at obs 1)
357
+ * D1 is the correction for rho3 (range at obs 3)
358
+ */
359
+ this.d3_ = (-gr3 * fc) / detj as Kilometers;
360
+ this.d1_ = (gr1 * fc) / detj as Kilometers;
361
+
362
+ // Update range estimates - note the swap per Gooding's algorithm
363
+ this.rho1_ = (this.rho1_ + this.d3_) as Kilometers;
364
+ this.rho3_ = (this.rho3_ + this.d1_) as Kilometers;
365
+
366
+ const den = Math.max(cr, this.r2_);
367
+
368
+ stoppingCriterion = fc / den;
369
+ }
370
+
371
+ ++iter;
144
372
  }
145
373
 
146
- return null;
374
+ // Store final convergence state for diagnostics
375
+ const converged = Math.abs(stoppingCriterion) <= GoodingIOD.CONVERGENCE_TOLERANCE;
376
+
377
+ if (!converged) {
378
+ /* eslint-disable no-console */
379
+ console.warn('Gooding IOD convergence diagnostics:');
380
+ console.warn(` Iterations: ${iter}/${maxIterations}`);
381
+ console.warn(` Final residual: ${Math.abs(stoppingCriterion).toExponential(3)}`);
382
+ console.warn(` Target tolerance: ${GoodingIOD.CONVERGENCE_TOLERANCE.toExponential(3)}`);
383
+ console.warn(` rho1: ${(this.rho1_ * this.r_).toFixed(2)} km`);
384
+ console.warn(` rho2: ${(this.rho2_ * this.r_).toFixed(2)} km`);
385
+ console.warn(` rho3: ${(this.rho3_ * this.r_).toFixed(2)} km`);
386
+ /* eslint-enable no-console */
387
+ }
388
+
389
+ return converged;
147
390
  }
148
391
 
149
- private _modifyIterate(lineOfSight1: Vector3D, lineOfSight3: Vector3D): void {
392
+ private modifyIterate_(lineOfSight1: Vector3D, lineOfSight3: Vector3D): void {
150
393
  const r13 = this.vObserverPosition3_.subtract(this.vObserverPosition1_);
151
394
 
152
395
  this.d1_ = r13.dot(lineOfSight1) as Kilometers;
@@ -158,15 +401,47 @@ export class GoodingIOD {
158
401
  this.rho3_ = Math.max((this.d1_ * d2 - this.d3_) / d4, 0.0) as Kilometers;
159
402
  }
160
403
 
161
- private _computeDerivatives({
404
+ /**
405
+ * Compute the derivatives by finite-differences for the range problem.
406
+ * Specifically, we are trying to solve the problem:
407
+ * f(x, y) = 0
408
+ * g(x, y) = 0
409
+ * So, in a Newton-Raphson process, we would need the derivatives:
410
+ * fx, fy, gx, gy
411
+ * Enventually,
412
+ * dx =-f*gy / D
413
+ * dy = f*gx / D
414
+ * where D is the determinant of the Jacobian matrix.
415
+ *
416
+ * @param frame frame to be used (orbit frame)
417
+ * @param x current range 1
418
+ * @param y current range 3
419
+ * @param lineOfSight1 line of sight
420
+ * @param lineOfSight3 line of sight
421
+ * @param Pin basis vector
422
+ * @param Ein basis vector
423
+ * @param F value of the f-function
424
+ * @param T13 time of flight 1->3, in seconds
425
+ * @param T12 time of flight 1->2, in seconds
426
+ * @param withHalley use Halley iterative method
427
+ * @param nRev number of revolutions
428
+ * @param direction direction of motion
429
+ * @param FD derivatives of f wrt (rho1, rho3) by finite differences
430
+ * @param GD derivatives of g wrt (rho1, rho3) by finite differences
431
+ */
432
+
433
+ private computeDerivatives_({
162
434
  x,
163
435
  y,
164
436
  lineOfSight1,
165
437
  lineOfSight3,
166
438
  pin,
167
439
  ein,
440
+ fc,
441
+ gc,
168
442
  t13,
169
443
  t12,
444
+ withHalley,
170
445
  nrev,
171
446
  direction,
172
447
  fd,
@@ -178,203 +453,226 @@ export class GoodingIOD {
178
453
  const dx = this.facFiniteDiff_ * x as Kilometers;
179
454
  const dy = this.facFiniteDiff_ * y as Kilometers;
180
455
 
181
- const cm1 = this._getPositionOnLoS2({
456
+ const pm1 = this.getPositionOnLoS2_({
182
457
  e1: lineOfSight1,
183
- r01: x - dx as Kilometers,
458
+ r01: (x - dx) as Kilometers,
184
459
  e3: lineOfSight3,
185
460
  r03: y,
186
461
  t13,
187
462
  t12,
188
463
  nRev: nrev,
189
464
  posigrade: direction,
190
- })!.subtract(this.vObserverPosition2_);
465
+ });
191
466
 
467
+ if (pm1 === null) {
468
+ throw new Error('Lambert solver failed during derivative computation (x-dx).');
469
+ }
470
+ const cm1 = pm1.subtract(this.vObserverPosition2_);
192
471
  const fm1 = p.dot(cm1);
193
472
  const gm1 = en.dot(cm1);
194
473
 
195
- const cp1 = this._getPositionOnLoS2({
474
+ const pp1 = this.getPositionOnLoS2_({
196
475
  e1: lineOfSight1,
197
- r01: x + dx as Kilometers,
476
+ r01: (x + dx) as Kilometers,
198
477
  e3: lineOfSight3,
199
478
  r03: y,
200
479
  t13,
201
480
  t12,
202
481
  nRev: nrev,
203
482
  posigrade: direction,
204
- })!.subtract(this.vObserverPosition2_);
483
+ });
205
484
 
485
+ if (pp1 === null) {
486
+ throw new Error('Lambert solver failed during derivative computation (x+dx).');
487
+ }
488
+ const cp1 = pp1.subtract(this.vObserverPosition2_);
206
489
  const fp1 = p.dot(cp1);
207
490
  const gp1 = en.dot(cp1);
208
491
 
209
492
  const fx = (fp1 - fm1) / (2.0 * dx);
210
493
  const gx = (gp1 - gm1) / (2.0 * dx);
211
494
 
212
- const cm3 = this._getPositionOnLoS2({
495
+ const pm3 = this.getPositionOnLoS2_({
213
496
  e1: lineOfSight1,
214
497
  r01: x,
215
498
  e3: lineOfSight3,
216
- r03: y - dy as Kilometers,
499
+ r03: (y - dy) as Kilometers,
217
500
  t13,
218
501
  t12,
219
502
  nRev: nrev,
220
503
  posigrade: direction,
221
- })!.subtract(this.vObserverPosition2_);
504
+ });
222
505
 
506
+ if (pm3 === null) {
507
+ throw new Error('Lambert solver failed during derivative computation (y-dy).');
508
+ }
509
+ const cm3 = pm3.subtract(this.vObserverPosition2_);
223
510
  const fm3 = p.dot(cm3);
224
511
  const gm3 = en.dot(cm3);
225
512
 
226
- const cp3 = this._getPositionOnLoS2({
513
+ const pp3 = this.getPositionOnLoS2_({
227
514
  e1: lineOfSight1,
228
515
  r01: x,
229
516
  e3: lineOfSight3,
230
- r03: y + dy as Kilometers,
517
+ r03: (y + dy) as Kilometers,
231
518
  t13,
232
519
  t12,
233
520
  nRev: nrev,
234
521
  posigrade: direction,
235
- })!.subtract(this.vObserverPosition2_);
522
+ });
236
523
 
524
+ if (pp3 === null) {
525
+ throw new Error('Lambert solver failed during derivative computation (y+dy).');
526
+ }
527
+ const cp3 = pp3.subtract(this.vObserverPosition2_);
237
528
  const fp3 = p.dot(cp3);
238
529
  const gp3 = en.dot(cp3);
239
530
 
240
531
  const fy = (fp3 - fm3) / (2.0 * dy);
241
532
  const gy = (gp3 - gm3) / (2.0 * dy);
242
533
 
534
+ // Coefficients for the classical Newton-Raphson iterative method
243
535
  fd[0] = fx;
244
536
  fd[1] = fy;
245
537
  gd[0] = gx;
246
538
  gd[1] = gy;
247
- }
248
-
249
- solve(r1Init: Kilometers, r3Init: Kilometers, nRev = 0, direction = true): J2000 {
250
- const lineOfSight1 = this.o1_.observation.lineOfSight() as Vector3D<Kilometers>;
251
- const lineOfSight2 = this.o2_.observation.lineOfSight() as Vector3D<Kilometers>;
252
- const lineOfSight3 = this.o3_.observation.lineOfSight() as Vector3D<Kilometers>;
253
-
254
- this.r_ = Math.max(r1Init, r3Init) as Kilometers;
255
- this.v_ = Math.sqrt(this._mu / this.r_);
256
- this.t_ = this.r_ / this.v_;
257
-
258
- this.vObserverPosition1_ = this.o1_.site.position.scale(1.0 / this.r_ as Kilometers);
259
- this.vObserverPosition2_ = this.o2_.site.position.scale(1.0 / this.r_ as Kilometers);
260
- this.vObserverPosition3_ = this.o3_.site.position.scale(1.0 / this.r_ as Kilometers);
261
-
262
- const maxiter = 100;
263
539
 
264
- this._solveRangeProblem({
265
- rho1init: r1Init / this.r_ as Kilometers,
266
- rho3init: r3Init / this.r_ as Kilometers,
267
- t13: this.o3_.epoch.difference(this.o1_.epoch) / this.t_ as Seconds,
268
- t12: this.o2_.epoch.difference(this.o1_.epoch) / this.t_ as Seconds,
269
- nrev: nRev,
270
- direction,
271
- lineOfSight1,
272
- lineOfSight2,
273
- lineOfSight3,
274
- maxIterations: maxiter,
275
- });
276
- const gibbs = new GibbsIOD(this._mu);
277
- const p1 = this.vObserverPosition1_.add(lineOfSight1.scale(this.rho1_)).scale(this.r_);
278
- const p2 = this.vObserverPosition2_.add(lineOfSight2.scale(this.rho2_)).scale(this.r_);
279
- const p3 = this.vObserverPosition3_.add(lineOfSight3.scale(this.rho3_)).scale(this.r_);
280
-
281
- return gibbs.solve(p1, p2, p3, this.o2_.epoch, this.o3_.epoch);
282
- }
540
+ // Modified Newton-Raphson process with Halley's method for cubic convergence
541
+ if (withHalley) {
542
+ const hrho1Sq = dx * dx;
543
+ const hrho3Sq = dy * dy;
283
544
 
284
- private _solveRangeProblem({
285
- rho1init,
286
- rho3init,
287
- t13,
288
- t12,
289
- nrev,
290
- direction,
291
- lineOfSight1,
292
- lineOfSight2,
293
- lineOfSight3,
294
- maxIterations,
295
- }: SolveRangeProblemParams): void {
296
- const arbf = 1e-6;
297
- const cvtol = 1e-14;
545
+ // Second order derivatives: d^2f / drho1^2 and d^2g / drho1^2
546
+ const fxx = (fp1 + fm1 - 2.0 * fc) / hrho1Sq;
547
+ const gxx = (gp1 + gm1 - 2.0 * gc) / hrho1Sq;
548
+ const fyy = (fp3 + fm3 - 2.0 * fc) / hrho3Sq;
549
+ const gyy = (gp3 + gm3 - 2.0 * gc) / hrho3Sq;
298
550
 
299
- this.rho1_ = rho1init;
300
- this.rho3_ = rho3init;
551
+ const pp13 = this.getPositionOnLoS2_({
552
+ e1: lineOfSight1,
553
+ r01: (x + dx) as Kilometers,
554
+ e3: lineOfSight3,
555
+ r03: (y + dy) as Kilometers,
556
+ t13,
557
+ t12,
558
+ nRev: nrev,
559
+ posigrade: direction,
560
+ });
301
561
 
302
- let iter = 0;
303
- let stoppingCriterion = 10.0 * cvtol;
562
+ if (pp13 === null) {
563
+ throw new Error('Lambert solver failed during Halley derivative computation (x+dx, y+dy).');
564
+ }
304
565
 
305
- while (iter < maxIterations && Math.abs(stoppingCriterion) > cvtol) {
306
- this.facFiniteDiff_ = arbf;
566
+ const cp13 = pp13.subtract(this.vObserverPosition2_);
567
+ const fp13 = p.dot(cp13);
568
+ const gp13 = en.dot(cp13);
307
569
 
308
- const p2 = this._getPositionOnLoS2({
570
+ const pm13 = this.getPositionOnLoS2_({
309
571
  e1: lineOfSight1,
310
- r01: this.rho1_,
572
+ r01: (x - dx) as Kilometers,
311
573
  e3: lineOfSight3,
312
- r03: this.rho3_,
574
+ r03: (y - dy) as Kilometers,
313
575
  t13,
314
576
  t12,
315
577
  nRev: nrev,
316
578
  posigrade: direction,
317
579
  });
318
580
 
319
- if (p2 === null) {
320
- this._modifyIterate(lineOfSight1, lineOfSight3);
321
- } else {
322
- this.r2_ = p2.magnitude();
323
- const c = p2.subtract(this.vObserverPosition2_);
581
+ if (pm13 === null) {
582
+ throw new Error('Lambert solver failed during Halley derivative computation (x-dx, y-dy).');
583
+ }
324
584
 
325
- this.rho2_ = c.magnitude();
326
- const cr = lineOfSight2.dot(c);
585
+ const cm13 = pm13.subtract(this.vObserverPosition2_);
586
+ const fm13 = p.dot(cm13);
587
+ const gm13 = en.dot(cm13);
327
588
 
328
- const u = lineOfSight2.cross(c);
329
- const p = u.cross(lineOfSight2).normalize();
330
- const ent = lineOfSight2.cross(p);
589
+ // Second order cross derivatives
590
+ const fxy = (fp13 + fm13) / (2.0 * dx * dy) - 0.5 * (fxx * dx / dy + fyy * dy / dx) - fc / (dx * dy);
591
+ const gxy = (gp13 + gm13) / (2.0 * dx * dy) - 0.5 * (gxx * dx / dy + gyy * dy / dx) - gc / (dx * dy);
331
592
 
332
- const enr = ent.magnitude();
593
+ // Determinant of Jacobian
594
+ const detJac = fx * gy - fy * gx;
333
595
 
334
- if (enr === 0.0) {
335
- return;
336
- }
596
+ // Delta Newton-Raphson, 1st order step
597
+ const dx3NR = (-gy * fc) / detJac;
598
+ const dx1NR = (gx * fc) / detJac;
337
599
 
338
- const en = ent.normalize();
600
+ // Halley's method Jacobian with second-order corrections
601
+ const fxH = fx + 0.5 * (fxx * dx3NR + fxy * dx1NR);
602
+ const fyH = fy + 0.5 * (fxy * dx3NR + fyy * dx1NR);
603
+ const gxH = gx + 0.5 * (gxx * dx3NR + gxy * dx1NR);
604
+ const gyH = gy + 0.5 * (gxy * dx3NR + gyy * dx1NR);
339
605
 
340
- const fc = p.dot(c);
606
+ // Update with Halley's method coefficients
607
+ fd[0] = fxH;
608
+ fd[1] = fyH;
609
+ gd[0] = gxH;
610
+ gd[1] = gyH;
611
+ }
612
+ }
341
613
 
342
- const fd = new Float64Array(2);
343
- const gd = new Float64Array(2);
614
+ /**
615
+ * Calculate the position along sight-line (forced planar mock-up for debugging).
616
+ * @param frame frame to be used (orbit frame)
617
+ * @param E1 line of sight 1 (ignored in planar mock-up)
618
+ * @param RO1 distance along E1 (used for R1)
619
+ * @param E3 line of sight 3 (ignored in planar mock-up)
620
+ * @param RO3 distance along E3 (used for R3)
621
+ * @param T13 time of flight 1->3
622
+ * @param T12 time of flight 1->2
623
+ * @param nRev number of revolutions
624
+ * @param posigrade direction of motion
625
+ * @return (R2-O2) in normalized units
626
+ */
627
+ private getPositionOnLoS2_({
628
+ e1,
629
+ r01,
630
+ e3,
631
+ r03,
632
+ t13,
633
+ t12,
634
+ nRev,
635
+ posigrade,
636
+ }: GetPositionOnLoS2Params): Vector3D<Kilometers> | null {
637
+ const p1 = this.vObserverPosition1_.add(e1.scale(r01));
344
638
 
345
- this._computeDerivatives({
346
- x: this.rho1_,
347
- y: this.rho3_,
348
- lineOfSight1,
349
- lineOfSight3,
350
- pin: p,
351
- ein: en,
352
- t13,
353
- t12,
354
- nrev,
355
- direction,
356
- fd,
357
- gd,
358
- });
639
+ this.r1_ = p1.magnitude();
359
640
 
360
- const fr1 = fd[0];
361
- const fr3 = fd[1];
362
- const gr1 = gd[0];
363
- const gr3 = gd[1];
364
- const detj = fr1 * gr3 - fr3 * gr1;
641
+ const p3 = this.vObserverPosition3_.add(e3.scale(r03));
365
642
 
366
- this.d3_ = (-gr3 * fc) / detj as Kilometers;
367
- this.d1_ = (gr1 * fc) / detj as Kilometers;
643
+ this.r3_ = p3.magnitude();
368
644
 
369
- this.rho1_ = this.rho1_ + this.d3_ as Kilometers;
370
- this.rho3_ = this.rho3_ + this.d1_ as Kilometers;
645
+ const p13 = p1.cross(p3);
371
646
 
372
- const den = Math.max(cr, this.r2_);
647
+ let th = Math.atan2(p13.magnitude(), p1.dot(p3));
373
648
 
374
- stoppingCriterion = fc / den;
649
+ if (!posigrade) {
650
+ th = TAU - th;
651
+ }
652
+
653
+ const v1 = new Float64Array(2);
654
+ const exitflag = LambertIOD.solve(this.r1_, this.r3_, th, t13, nRev, v1);
655
+
656
+ if (exitflag) {
657
+ const pn = p1.cross(p3);
658
+ const pt = pn.cross(p1);
659
+
660
+ let rt = pt.magnitude();
661
+
662
+ if (!posigrade) {
663
+ rt = -rt as Kilometers;
375
664
  }
376
665
 
377
- ++iter;
666
+ const vel1 = p1.scale(v1[0] / this.r1_).add(pt.scale(v1[1] / rt)) as Vector3D<KilometersPerSecond>;
667
+
668
+ const p2 = new RungeKutta89Propagator(
669
+ new J2000(this.o1_.epoch, p1, vel1),
670
+ this._forceModel,
671
+ ).propagate(this.o1_.epoch.roll(t12)).position;
672
+
673
+ return p2;
378
674
  }
675
+
676
+ return null;
379
677
  }
380
678
  }