Skip to content

Commit 2d81ded

Browse files
Features/gauss method (#229)
* Add Gauss method * Add tests * Add Raphson newton * Add bissection * Fix gauss * Use expectedCenter of motion for Rn values * Adapt tests and revert gauss method to seconds * Fix gauss implementation * Logs * Add tests and validate method * Reduce coeff for gauss's method * Use GM AU3/D2 * Find COBE * Geo and cobe work * add logs * fix tests * Add threshold for coplanar and global arc * Evaluate reliability * Improve reliability * Clean code * Upgrade version
1 parent 359c9ba commit 2d81ded

File tree

12 files changed

+561
-4
lines changed

12 files changed

+561
-4
lines changed

IO.Astrodynamics.Net/IO.Astrodynamics.CLI/IO.Astrodynamics.CLI.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<FileVersion>0.0.1</FileVersion>
1010
<PackAsTool>true</PackAsTool>
1111
<ToolCommandName>astro</ToolCommandName>
12-
<Version>0.6.2.1</Version>
12+
<Version>0.6.3.1</Version>
1313
<Title>Astrodynamics command line interface</Title>
1414
<Authors>Sylvain Guillet</Authors>
1515
<Description>This CLI allows end user to exploit IO.Astrodynamics framework </Description>
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
using System;
2+
using IO.Astrodynamics.Body;
3+
using IO.Astrodynamics.Coordinates;
4+
using IO.Astrodynamics.Math;
5+
using IO.Astrodynamics.OrbitalParameters;
6+
using IO.Astrodynamics.SolarSystemObjects;
7+
using IO.Astrodynamics.Surface;
8+
using Xunit;
9+
10+
namespace IO.Astrodynamics.Tests.OrbitalParameters;
11+
12+
public class InitialOrbitDeterminationTests
13+
{
14+
public InitialOrbitDeterminationTests()
15+
{
16+
API.Instance.LoadKernels(Constants.SolarSystemKernelPath);
17+
}
18+
19+
[Fact]
20+
public void GeosynchronousObject()
21+
{
22+
for (int i = 1; i <= 5; i++)
23+
{
24+
var timespan = TimeSpan.FromMinutes(i * 2);
25+
Site site = new Site(80, "MyStation", TestHelpers.EarthAtJ2000, new Planetodetic(0.0, 45.0 * Constants.DEG_RAD, 0.0));
26+
27+
var e2 = new TimeSystem.Time(2024, 1, 2);
28+
29+
var e1 = e2 - timespan;
30+
var e3 = e2 + timespan;
31+
var referenceOrbit = new KeplerianElements(
32+
semiMajorAxis: 42164000.0, // m
33+
eccentricity: 0.0,
34+
inclination: 15.0 * Constants.DEG_RAD,
35+
rigthAscendingNode: 45.0 * Constants.DEG_RAD,
36+
argumentOfPeriapsis: 0.0,
37+
meanAnomaly: 45.0 * Constants.DEG_RAD, // Décalage de 45 degrés
38+
observer: TestHelpers.EarthAtJ2000,
39+
frame: Frames.Frame.ICRF,
40+
epoch: e2
41+
);
42+
var obs1 = referenceOrbit.AtEpoch(e1).RelativeTo(site, Aberration.LT);
43+
var obs2 = referenceOrbit.AtEpoch(e2).RelativeTo(site, Aberration.LT);
44+
var obs3 = referenceOrbit.AtEpoch(e3).RelativeTo(site, Aberration.LT);
45+
var orbitalParams =
46+
InitialOrbitDetermination.CreateFromObservation_Gauss(obs1.ToEquatorial(), obs2.ToEquatorial(), obs3.ToEquatorial(), site,
47+
PlanetsAndMoons.EARTH_BODY, 42000000.0);
48+
var deltaRange = 100.0 * (orbitalParams.OrbitalParameters.ToStateVector().Position - referenceOrbit.ToStateVector().Position).Magnitude() /
49+
referenceOrbit.ToStateVector().Position.Magnitude();
50+
var deltaVelocity = 100.0 * (orbitalParams.OrbitalParameters.ToStateVector().Velocity - referenceOrbit.ToStateVector().Velocity).Magnitude() /
51+
referenceOrbit.ToStateVector().Velocity.Magnitude();
52+
Assert.True(deltaRange < 0.02);
53+
Assert.True(deltaVelocity < 0.02);
54+
}
55+
}
56+
57+
[Fact]
58+
public void PlanetObject()
59+
{
60+
var timespan = TimeSpan.FromDays(10);
61+
Site site = new Site(13, "DSS-13", TestHelpers.EarthAtJ2000);
62+
63+
var e2 = new TimeSystem.Time(2023, 3, 1);
64+
var e1 = e2 - timespan;
65+
var e3 = e2 + timespan;
66+
var target = new Barycenter(4);
67+
var obs1 = target.GetEphemeris(e1, site, Frames.Frame.ICRF, Aberration.LT);
68+
var obs2 = target.GetEphemeris(e2, site, Frames.Frame.ICRF, Aberration.LT);
69+
var obs3 = target.GetEphemeris(e3, site, Frames.Frame.ICRF, Aberration.LT);
70+
var referenceOrbit = target.GetEphemeris(e2, TestHelpers.Sun, Frames.Frame.ICRF, Aberration.LT);
71+
var orbitalParams =
72+
InitialOrbitDetermination.CreateFromObservation_Gauss(obs1.ToEquatorial(), obs2.ToEquatorial(), obs3.ToEquatorial(), site,
73+
Stars.SUN_BODY, 350000000000.58063);
74+
75+
var deltaRange = 100.0 * (orbitalParams.OrbitalParameters.ToStateVector().Position - referenceOrbit.ToStateVector().Position).Magnitude() /
76+
referenceOrbit.ToStateVector().Position.Magnitude();
77+
var deltaVelocity = 100.0 * (orbitalParams.OrbitalParameters.ToStateVector().Velocity - referenceOrbit.ToStateVector().Velocity).Magnitude() /
78+
referenceOrbit.ToStateVector().Velocity.Magnitude();
79+
80+
Assert.True(deltaRange < 0.06);
81+
Assert.True(deltaVelocity < 0.15);
82+
}
83+
84+
[Fact]
85+
public void COBE()
86+
{
87+
var ut1 = new TimeSystem.Time(2000, 11, 6, 22, 31, 29, 0, 0, TimeSystem.TimeFrame.UTCFrame);
88+
var ut2 = new TimeSystem.Time(2000, 11, 6, 22, 34, 30, 0, 0, TimeSystem.TimeFrame.UTCFrame);
89+
var ut3 = new TimeSystem.Time(2000, 11, 6, 22, 37, 30, 0, 0, TimeSystem.TimeFrame.UTCFrame);
90+
var site = new Site(99, "Maryland university", TestHelpers.EarthAtJ2000, new Planetodetic(-76.95667 * Constants.DEG_RAD, 39.00167 * Constants.DEG_RAD, 53.0));
91+
var obs1 = new Equatorial(-16.3 * Astrodynamics.Constants.Deg2Rad, 327.0 * Astrodynamics.Constants.Deg2Rad, 7250000.0, ut1);
92+
var obs2 = new Equatorial(46.9 * Astrodynamics.Constants.Deg2Rad, 318.5 * Astrodynamics.Constants.Deg2Rad, 7250000.0, ut2);
93+
var obs3 = new Equatorial(76.1 * Astrodynamics.Constants.Deg2Rad, 165.75 * Astrodynamics.Constants.Deg2Rad, 7250000.0, ut3);
94+
var orbitalParams =
95+
InitialOrbitDetermination.CreateFromObservation_Gauss(obs1, obs2, obs3, site, PlanetsAndMoons.EARTH_BODY, 7_250_000.0);
96+
StateVector referenceOrbit = new(new Vector3(3520477.0118993367, -4310404.2221997585, 4645118.5764311915),
97+
new Vector3(-4026.2486947722973, 2615.67401249017, 5468.113004203227),
98+
TestHelpers.EarthAtJ2000, ut2, Frames.Frame.ICRF);
99+
Assert.Equal(referenceOrbit, orbitalParams.OrbitalParameters.ToStateVector(), TestHelpers.StateVectorComparer);
100+
}
101+
}

IO.Astrodynamics.Net/IO.Astrodynamics/Coordinates/Equatorial.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,13 @@ public Vector3 ToCartesian()
4747
double z = Distance * System.Math.Sin(Declination);
4848
return new Vector3(x, y, z);
4949
}
50+
51+
public Vector3 ToDirection()
52+
{
53+
double x = System.Math.Cos(Declination) * System.Math.Cos(RightAscension);
54+
double y = System.Math.Cos(Declination) * System.Math.Sin(RightAscension);
55+
double z = System.Math.Sin(Declination);
56+
return new Vector3(x, y, z);
57+
}
5058
}
5159
}

IO.Astrodynamics.Net/IO.Astrodynamics/IO.Astrodynamics.nuspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<id>IO.Astrodynamics</id>
55
<authors>Sylvain Guillet</authors>
66
<copyright>Sylvain Guillet</copyright>
7-
<version>6.2.0</version>
7+
<version>6.3.0</version>
88
<title>Astrodynamics framework</title>
99
<icon>images\dragonfly-dark-trans.png</icon>
1010
<readme>docs\README.md</readme>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System;
2+
3+
public class BisectionMethod
4+
{
5+
public static double Solve(
6+
Func<double, double> f, // Your polynomial function
7+
double a, // Left endpoint
8+
double b, // Right endpoint
9+
double tolerance = 1E-12, // Matching your tolerance
10+
int maxIterations = 1000) // Matching your max iterations
11+
{
12+
if (f(a) * f(b) >= 0)
13+
{
14+
throw new ArgumentException("Function must have different signs at endpoints a and b");
15+
}
16+
17+
double c = a;
18+
int iterations = 0;
19+
20+
while ((b - a) > tolerance && iterations < maxIterations)
21+
{
22+
c = (a + b) / 2;
23+
double fc = f(c);
24+
25+
if (Math.Abs(fc) < tolerance)
26+
break;
27+
28+
if (f(a) * fc < 0)
29+
{
30+
b = c;
31+
}
32+
else
33+
{
34+
a = c;
35+
}
36+
37+
iterations++;
38+
}
39+
40+
if (iterations >= maxIterations)
41+
{
42+
throw new ArgumentException($"Failed to converge after {maxIterations} iterations");
43+
}
44+
45+
return c;
46+
}
47+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using System;
2+
3+
namespace IO.Astrodynamics.Math;
4+
5+
/// <summary>
6+
/// Newton-Raphson method for finding the root of a function.
7+
/// </summary>
8+
public class NewtonRaphson
9+
{
10+
/// <summary>
11+
/// Solve the equation f(x) = 0 using the Newton-Raphson method.
12+
/// </summary>
13+
/// <param name="function"></param>
14+
/// <param name="derivative"></param>
15+
/// <param name="initialGuess"></param>
16+
/// <param name="tolerance"></param>
17+
/// <param name="maxIterations"></param>
18+
/// <returns></returns>
19+
/// <exception cref="Exception"></exception>
20+
public static double Solve(
21+
Func<double, double> function,
22+
Func<double, double> derivative,
23+
double initialGuess,
24+
double tolerance = 1e-6,
25+
int maxIterations = 100)
26+
{
27+
double x = initialGuess;
28+
29+
for (int i = 0; i < maxIterations; i++)
30+
{
31+
double fValue = function(x);
32+
double fDerivative = derivative(x);
33+
34+
if (System.Math.Abs(fDerivative) < 1e-12) // Avoid division by zero or near-zero derivatives
35+
throw new Exception($"Derivative too small (f'(x) = {fDerivative}) at iteration {i}. Adjust initial guess or problem scaling.");
36+
37+
// Update the root estimate using Newton-Raphson formula
38+
double xNew = x - fValue / fDerivative;
39+
40+
// Check for convergence (absolute and relative tolerance)
41+
if (System.Math.Abs(xNew - x) < tolerance || System.Math.Abs(xNew - x) < tolerance * System.Math.Abs(xNew))
42+
return xNew;
43+
44+
if (double.IsNaN(xNew) || double.IsInfinity(xNew))
45+
throw new Exception("Newton-Raphson method diverged.");
46+
47+
x = xNew;
48+
}
49+
50+
51+
throw new Exception("Newton-Raphson method did not converge within the maximum number of iterations.");
52+
}
53+
54+
public static double BoundedNewtonRaphson(Func<double, double> f, Func<double, double> df,
55+
double x0, double min, double max, double tolerance, int maxIterations)
56+
{
57+
double x = x0;
58+
for (int i = 0; i < maxIterations; i++)
59+
{
60+
double fx = f(x);
61+
if (System.Math.Abs(fx) < tolerance)
62+
return x;
63+
64+
double dfx = df(x);
65+
if (System.Math.Abs(dfx) < 1e-10)
66+
break;
67+
68+
double step = fx / dfx;
69+
double newX = x - step;
70+
71+
// Bound the solution
72+
if (newX < min)
73+
newX = min;
74+
else if (newX > max)
75+
newX = max;
76+
77+
if (System.Math.Abs(newX - x) < tolerance)
78+
return newX;
79+
80+
x = newX;
81+
}
82+
83+
throw new Exception("Failed to converge within maximum iterations");
84+
}
85+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
3+
namespace IO.Astrodynamics.Math;
4+
5+
public class Solver
6+
{
7+
/// <summary>
8+
/// Solve the quadratic equation ax^2 + bx + c = 0.
9+
/// </summary>
10+
/// <param name="a"></param>
11+
/// <param name="b"></param>
12+
/// <param name="c"></param>
13+
/// <returns></returns>
14+
/// <exception cref="InvalidOperationException"></exception>
15+
public static double SolveQuadratic(double a, double b, double c)
16+
{
17+
double discriminant = b * b - 4 * a * c;
18+
if (discriminant < 0)
19+
throw new InvalidOperationException("No real roots for the polynomial.");
20+
21+
double root1 = (-b + System.Math.Sqrt(discriminant)) / (2 * a);
22+
double root2 = (-b - System.Math.Sqrt(discriminant)) / (2 * a);
23+
24+
// Select the positive root (physically meaningful solution)
25+
return System.Math.Max(root1, root2);
26+
}
27+
}

IO.Astrodynamics.Net/IO.Astrodynamics/Math/Vector3.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ public Vector3(double x, double y, double z)
2020

2121
public double Magnitude()
2222
{
23-
return System.Math.Sqrt(X * X + Y * Y + Z * Z);
23+
return System.Math.Sqrt(MagnitudeSquared());
24+
}
25+
26+
public double MagnitudeSquared()
27+
{
28+
return X * X + Y * Y + Z * Z;
2429
}
2530

2631
public Vector3 Normalize()

0 commit comments

Comments
 (0)