Hi everyone, I wanted to open this topic in order to get your opinion on the fixes I made to the IodGooding implementation (to fix the bug in the Halley convergence method). Basically, I followed the typical method and compared it with what was already implemented. I noticed several issues in the original code and made the following changes:
final double Fc = P.dotProduct(C);
final double Gc = EN.dotProduct(C);
I uncommented the G function and added it to the compute derivative function
private void computeDerivatives(final Frame frame,
final double x, final double y,
final Vector3D lineOfSight1, final Vector3D lineOfSight3,
final Vector3D Pin,
final Vector3D Ein,
final double F,
final double G,
final double T13, final double T12,
final boolean withHalley,
final int nRev,
final boolean direction,
final double[] FD, final double[] GD)
In the Halley method section, I found errors in the second-order derivative definitions.
final double Fxx = (Fp1 + Fm1 - 2 * F) / hrho1Sq;
final double Gxx = (Gp1 + Gm1 - 2 * F) / hrho1Sq;
final double Fyy = (Fp3 + Fp3 - 2 * F) / hrho3Sq;
final double Gyy = (Gm3 + Gm3 - 2 * F) / hrho3Sq;
After changes, it looks like this (replace F by G when computing Gxx and Gyy; in Fyy, change the second Fp3 to Fm3, and same for Gyy).
final double Fxx = (Fp1 + Fm1 - 2 * F) / hrho1Sq;
final double Gxx = (Gp1 + Gm1 - 2 * G) / hrho1Sq;
final double Fyy = (Fp3 + Fm3 - 2 * F) / hrho3Sq;
final double Gyy = (Gp3 + Gm3 - 2 * G) / hrho3Sq;
In the Fxy, and Gxy definitions we have :
final double Fxy = (Fp13 + Fm13) / (2 * dx * dy) - 0.5 * (Fxx * dx / dy + Fyy * dy / dx) - F / (dx * dy);
final double Gxy = (Gp13 + Gm13) / (2 * dx * dy) - 0.5 * (Gxx * dx / dy + Gyy * dy / dx) - F / (dx * dy);
I replaced the F function by G in Gxy :
final double Gxy = (Gp13 + Gm13) / (2 * dx * dy) - 0.5 * (Gxx * dx / dy + Gyy * dy / dx) - G / (dx * dy);
Finally in the terms of the jacobian we originally have :
final double FxH = Fx + 0.5 * (Fxx * dx3NR + Fxy * dx1NR);
final double FyH = Fy + 0.5 * (Fxy * dx3NR + Fxx * dx1NR);
final double GxH = Gx + 0.5 * (Gxx * dx3NR + Gxy * dx1NR);
final double GyH = Gy + 0.5 * (Gxy * dx3NR + Gyy * dx1NR);
But in the FyH definition we should have :
final double FyH = Fy + 0.5 * (Fxy * dx3NR + Fyy * dx1NR); (Change the Fxx for a Fyy)
After making those changes, I changed the boolean of the Halley method to be true at any iteration in order to only use Halley for convergence.
I also introduced an error in rho_init to have more than one or two iterations.
// rho1 = rho1init;
// rho3 = rho3init;
rho1 = rho1init*6.0 ;
rho3 = rho3init*6.0 ;
I gave three pre-computed RaDec (generated with an initial position of the target and the observer). The true position of the considered target is : x = -26649.115, y = 41027.775,z = -5294.460, x_dot = -2.993, y_dot = -1.943, z_dot = 0.267 (GCRF)
With only halley convergence and without any changes I obtained :
iter=0 rho1=4.6110494091158705 rho3=4.968694812279726 Fc=0.08130464752872525 stop=1.0E-13 detj=-1.8412824579164062E10 [H]
iter=1 rho1=4.609833976420186 rho3=4.970016431157314 Fc=0.08275745857588751 stop=0.016709747968573017 detj=4.5117283069085156E11 [H]
[...]
iter=99 rho1=4.638688189311865 rho3=4.938169143471605 Fc=0.08419265237286516 stop=0.017319291348148164 detj=9.270718313762109E11 [H]
=== 100 iter | crit=0.017312895545320228 | converge=false ===
SpacecraftState{orbit=Cartesian parameters: {P(-1.3157182332905114E8, 1.7937535613075933E8, -4.742736253553751E7), V(-108.16833248624134, 48.41570984076883, -188.23927712334591)}, attitude=org.orekit.attitudes.Attitude@78aab498, mass=1000.0, additional={}, additionalDot={}}
Basically the algorithm reaches 100 iterations (max iteration , so it does not converge) , after that i tested with only newton convergence (setting halley booleans to false):
iter=0 rho1=0.9199352246773724 rho3=1.0032745735207915 Fc=0.08130464752872525 stop=1.0E-13 detj=5.0865838066984505E-5 [N]
iter=1 rho1=0.9164790066979406 rho3=1.000035273457973 Fc=8.289453314661068E-5 stop=0.016709747968573017 detj=5.057591176035089E-5 [N]
iter=2 rho1=0.9164788018969453 rho3=1.0000350705179064 Fc=4.766519784284826E-9 stop=7.917761787949509E-5 detj=5.057217296105787E-5 [N]
iter=3 rho1=0.9164788018969446 rho3=1.0000350705179106 Fc=8.235447725389051E-17 stop=4.567270813927941E-9 detj=5.057217205322497E-5 [N]
=== 4 iter | crit=7.89119295009951E-17 | converge=true ===
SpacecraftState{orbit=Cartesian parameters: {P(-2.654762526549285E7, 4.088969679165287E7, -5266101.981770694), V(-2818.604309042942, -2176.784785455636, 361.48403445103736)}, attitude=org.orekit.attitudes.Attitude@78aab498, mass=1000.0, additional={}, additionalDot={}}
Four iteration and the algorithm converged to a solution which is not too far from the real position of the target, so the algorithm can converge.
And finally , I used only halley convergence with the fixes described above and obtained :
iter=0 rho1=0.9182210087747658 rho3=1.0806785155741272 Fc=0.08130464752872525 stop=1.0E-13 detj=5.19574749174509E-5 [H]
iter=1 rho1=0.9171477122553526 rho3=1.0018455500424541 Fc=0.0010129347671791087 stop=0.016709747968573017 detj=5.134398033016589E-5 [H]
iter=2 rho1=0.9164787920945492 rho3=1.0000350412456398 Fc=2.533557768076061E-6 stop=9.342238476293698E-4 detj=5.0571682332857805E-5 [H]
iter=3 rho1=0.9164788018969866 rho3=1.0000350705180212 Fc=5.1772430911083636E-11 stop=2.4248037492153602E-6 detj=5.0572175791752496E-5 [H]
iter=4 rho1=0.916478801896857 rho3=1.0000350705176695 Fc=4.906942494961125E-16 stop=4.960826211236196E-11 detj=5.057217540277937E-5 [H]
=== 5 iter | crit=4.701824516887309E-16 | converge=true ===
SpacecraftState{orbit=Cartesian parameters: {P(-2.654762526580604E7, 4.088969679140569E7, -5266101.981731054), V(-2818.6043085247147, -2176.784785039024, 361.4840343835512)}, attitude=org.orekit.attitudes.Attitude@78aab498, mass=1000.0, additional={}, additionalDot={}}
In this case, the algorithm converged around the same solution as Newton using only Halley. From what I saw, the code should be good, but I am not sure, and I would appreciate your opinions/tests on the question. I put the full modified Java code.
Hugo B
IodGooding.java (35.0 KB)