diff --git a/IO.Astrodynamics.Performance/IO.Astrodynamics.Performance.csproj b/IO.Astrodynamics.Performance/IO.Astrodynamics.Performance.csproj new file mode 100644 index 0000000..822d18a --- /dev/null +++ b/IO.Astrodynamics.Performance/IO.Astrodynamics.Performance.csproj @@ -0,0 +1,60 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + + + + diff --git a/IO.Astrodynamics.Performance/Program.cs b/IO.Astrodynamics.Performance/Program.cs new file mode 100644 index 0000000..f8d369e --- /dev/null +++ b/IO.Astrodynamics.Performance/Program.cs @@ -0,0 +1,11 @@ +using BenchmarkDotNet.Running; + +namespace IO.Astrodynamics.Performance; + +class Program +{ + static void Main(string[] args) + { + var summary = BenchmarkRunner.Run(typeof(Program).Assembly); + } +} \ No newline at end of file diff --git a/IO.Astrodynamics.Performance/Scenario.cs b/IO.Astrodynamics.Performance/Scenario.cs new file mode 100644 index 0000000..e87452f --- /dev/null +++ b/IO.Astrodynamics.Performance/Scenario.cs @@ -0,0 +1,21 @@ +// Copyright 2023. Sylvain Guillet (sylvain.guillet@tutamail.com) + +using BenchmarkDotNet.Attributes; + +namespace IO.Astrodynamics.Performance; + +[MarkdownExporterAttribute.GitHub] +[MemoryDiagnoser] +[SkewnessColumn] +[KurtosisColumn] +[StatisticalTestColumn] +[ShortRunJob] +public class Scenario +{ + [Benchmark(Description = "Spacecraft propagator")] + public void Propagate() + { + var scenario = new IO.Astrodynamics.Tests.Mission.ScenarioTests(); + scenario.Propagate(); + } +} \ No newline at end of file diff --git a/IO.Astrodynamics.Tests/APITest.cs b/IO.Astrodynamics.Tests/APITest.cs index 8c7ff53..ad5b01c 100644 --- a/IO.Astrodynamics.Tests/APITest.cs +++ b/IO.Astrodynamics.Tests/APITest.cs @@ -157,45 +157,45 @@ public void PropagateScenario() // Read maneuver results var maneuver = spacecraft.StandbyManeuver; - Assert.Equal("2021-03-04T00:32:49.8175394 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T00:32:58.2100803 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); - Assert.Equal("2021-03-04T00:32:49.8175394 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T00:32:58.2100803 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); - Assert.Equal(8.3925409000000002, maneuver.ThrustWindow.Length.TotalSeconds, 3); - Assert.Equal(new Vector3(-97.0714098295484, 107.8305292474044, -119.8974902969949), ((ImpulseManeuver)maneuver).DeltaV); + Assert.Equal("2021-03-04T00:32:53.8146003 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T00:33:02.2130194 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); + Assert.Equal("2021-03-04T00:32:53.8146003 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T00:33:02.2130194 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); + Assert.Equal(8.3984190999999999, maneuver.ThrustWindow.Length.TotalSeconds, 3); + Assert.Equal(new Vector3(-97.1412202651915, 107.90256552680627, -119.98761196522472), ((ImpulseManeuver)maneuver).DeltaV); - Assert.Equal(419.62704377403645, maneuver.FuelBurned); + Assert.Equal(419.92095543527711, maneuver.FuelBurned); maneuver = maneuver.NextManeuver; - Assert.Equal("2021-03-04T01:15:39.8402441 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T01:16:02.1873755 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); - Assert.Equal("2021-03-04T01:15:39.8402441 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T01:16:02.1873755 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); - Assert.Equal(22.347131399999999, maneuver.ThrustWindow.Length.TotalSeconds, 3); - Assert.Equal(new Vector3(-462.3769514474425, -165.79592575424203, 234.3310697732304), ((ImpulseManeuver)maneuver).DeltaV); - Assert.Equal(1117.3565715207112, maneuver.FuelBurned); + Assert.Equal("2021-03-04T01:15:39.8407123 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:16:02.1869075 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:15:39.8407123 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:16:02.1869075 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); + Assert.Equal(22.3461952, maneuver.ThrustWindow.Length.TotalSeconds, 3); + Assert.Equal(new Vector3(-462.1414550058744, -166.03947455552907, 234.6077171916677), ((ImpulseManeuver)maneuver).DeltaV); + Assert.Equal(1117.3097601570541, maneuver.FuelBurned); maneuver = maneuver.NextManeuver; - Assert.Equal("2021-03-04T01:16:13.2426029 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T04:59:20.7658396 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); - Assert.Equal("2021-03-04T01:16:13.2426029 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T01:16:22.7850168 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:16:13.2426462 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T04:59:20.8256783 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:16:13.2426462 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:16:22.7849736 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); Assert.Equal(9.5424138999999997, maneuver.ThrustWindow.Length.TotalSeconds, 3); - Assert.Equal(new Vector3(-139.4951793647351, 85.72332642451474, 194.88236993709975), ((ImpulseManeuver)maneuver).DeltaV); - Assert.Equal(477.12069491886507, maneuver.FuelBurned); + Assert.Equal(new Vector3(-139.49753871704854, 85.72527093628567, 194.88665767803553), ((ImpulseManeuver)maneuver).DeltaV); + Assert.Equal(477.11637079604111, maneuver.FuelBurned); maneuver = maneuver.NextManeuver; - Assert.Equal("2021-03-04T05:23:58.7294586 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T05:24:07.2981610 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); - Assert.Equal("2021-03-04T05:23:58.7294586 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T05:24:07.2981610 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); + Assert.Equal("2021-03-04T05:23:58.7294805 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T05:24:07.2981393 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); + Assert.Equal("2021-03-04T05:23:58.7294805 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T05:24:07.2981393 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); Assert.Equal(8.5687023999999994, maneuver.ThrustWindow.Length.TotalSeconds, 3); - Assert.Equal(new Vector3(134.22795291868337, -81.45016347177679, -183.86968653289438), ((ImpulseManeuver)maneuver).DeltaV); - Assert.Equal(428.43511797710403, maneuver.FuelBurned); + Assert.Equal(new Vector3(134.21948840073748, -81.46563131619929, -183.87722556440008), ((ImpulseManeuver)maneuver).DeltaV); + Assert.Equal(428.43294038256437, maneuver.FuelBurned); } [Fact] @@ -214,9 +214,6 @@ public void PropagateScenario2() //Define parking orbit KeplerianElements parkingOrbit = new KeplerianElements(10000000.0, 0.5, 1.0, 0.0, 0.0, 0.0, earth, DateTimeExtension.J2000, Frames.Frame.ICRF); - //Define target orbit - KeplerianElements targetOrbit = new KeplerianElements(10000000.0, 0.5, 1.0, 0.0, 0.0, 0.0, earth, DateTimeExtension.J2000, Frames.Frame.ICRF); - //Create and configure spacecraft Clock clock = new Clock("clk1", System.Math.Pow(2.0, 16.0)); Spacecraft spacecraft = @@ -243,25 +240,25 @@ public void PropagateScenario2() // Read maneuver results var maneuver = spacecraft.StandbyManeuver; - Assert.Equal("2021-03-04T01:33:26.9842661 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T01:33:29.0433537 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); - Assert.Equal("2021-03-04T01:33:26.9842661 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T01:33:29.0433537 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); - Assert.Equal(2.0590875999999998, maneuver.ThrustWindow.Length.TotalSeconds, 3); - Assert.Equal(new Vector3(6.06672064664599, 42.796832837817874, -14.017587297211776), ((ImpulseManeuver)maneuver).DeltaV); + Assert.Equal("2021-03-04T01:33:26.9902501 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:33:29.0373698 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:33:26.9902501 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:33:29.0373698 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); + Assert.Equal(2.0470000000000002, maneuver.ThrustWindow.Length.TotalSeconds, 3); + Assert.Equal(new Vector3(0.27283642892594173, 42.940862925320744, -14.02921217988478), ((ImpulseManeuver)maneuver).DeltaV); - Assert.Equal(102.95438080009254, maneuver.FuelBurned); + Assert.Equal(102.35598515078391, maneuver.FuelBurned, 6); maneuver = maneuver.NextManeuver; - Assert.Equal("2021-03-04T04:18:00.5620061 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T04:18:01.4656137 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); - Assert.Equal("2021-03-04T04:18:00.5620061 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T04:18:01.4656137 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); - Assert.Equal(0.90360759999999996, maneuver.ThrustWindow.Length.TotalSeconds, 3); - Assert.Equal(new Vector3(0.6113331463337078, 10.731242700644234, 16.97261190194155), ((ImpulseManeuver)maneuver).DeltaV); - Assert.Equal(45.180377988723926, maneuver.FuelBurned); + Assert.Equal("2021-03-04T04:18:07.5605585 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T04:18:08.4670611 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); + Assert.Equal("2021-03-04T04:18:07.5605585 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T04:18:08.4670611 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); + Assert.Equal(0.90650260000000005, maneuver.ThrustWindow.Length.TotalSeconds, 3); + Assert.Equal(new Vector3(0.5763904852327267, 10.765407583564869, 17.027153112523376), ((ImpulseManeuver)maneuver).DeltaV); + Assert.Equal(45.325132147428718, maneuver.FuelBurned); } [Fact] @@ -667,7 +664,7 @@ void GetCelestialBodyInformation() Assert.Equal(-2.5388099999999996E-06, res.J3); Assert.Equal(-1.6559699999999999E-06, res.J4); } - + [Fact] void GetCelestialBodyInformationWithoutJ() { diff --git a/IO.Astrodynamics.Tests/IO.Astrodynamics.Tests.csproj b/IO.Astrodynamics.Tests/IO.Astrodynamics.Tests.csproj index a187c6f..2303bd2 100644 --- a/IO.Astrodynamics.Tests/IO.Astrodynamics.Tests.csproj +++ b/IO.Astrodynamics.Tests/IO.Astrodynamics.Tests.csproj @@ -10,6 +10,7 @@ + diff --git a/IO.Astrodynamics.Tests/Math/Vector3Test.cs b/IO.Astrodynamics.Tests/Math/Vector3Test.cs index 4dcc3a1..aba5910 100644 --- a/IO.Astrodynamics.Tests/Math/Vector3Test.cs +++ b/IO.Astrodynamics.Tests/Math/Vector3Test.cs @@ -82,6 +82,51 @@ public void Angle() Assert.Equal(System.Math.PI / 2.0, angle); } + [Fact] + public void Angle2() + { + Vector3 m1 = new Vector3(1, 0, 0); + Vector3 m2 = new Vector3(0, 1, 0); + double angle = m2.Angle(m1, Plane.Z); + Assert.Equal(-System.Math.PI / 2.0, angle); + } + + [Fact] + public void Angle3() + { + Vector3 m1 = new Vector3(1, -1, 0); + Vector3 m2 = new Vector3(0, 1, 0); + double angle = m2.Angle(m1, new Plane(new Vector3(0.0,0.0,10.0),0.0)); + Assert.Equal(-2.3561944901923448, angle, 6); + } + + [Fact] + public void Angle4() + { + Vector3 m1 = new Vector3(0, -1, 0); + Vector3 m2 = new Vector3(0, 1, 0); + double angle = m2.Angle(m1, Plane.Z); + Assert.Equal(3.1415929999999999, angle, 6); + } + + [Fact] + public void Angle5() + { + Vector3 m1 = new Vector3(-1, -1, 0); + Vector3 m2 = new Vector3(0, 1, 0); + double angle = m2.Angle(m1, Plane.Z); + Assert.Equal(2.3561939999999999, angle, 6); + } + + [Fact] + public void Angle6() + { + Vector3 m1 = new Vector3(-1, 0, 0); + Vector3 m2 = new Vector3(0, 1, 0); + double angle = m2.Angle(m1); + Assert.Equal(1.5707960000000001, angle, 6); + } + [Fact] public void To() { @@ -93,7 +138,7 @@ public void To() Assert.Equal(0.0, q.VectorPart.Y); Assert.Equal(-0.7071067811865475, q.VectorPart.Z); } - + [Fact] public void To2() { diff --git a/IO.Astrodynamics.Tests/Mission/ScenarioTests.cs b/IO.Astrodynamics.Tests/Mission/ScenarioTests.cs index dba33c4..61dbcee 100644 --- a/IO.Astrodynamics.Tests/Mission/ScenarioTests.cs +++ b/IO.Astrodynamics.Tests/Mission/ScenarioTests.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Linq; +using BenchmarkDotNet.Attributes; using IO.Astrodynamics.Body; using IO.Astrodynamics.Body.Spacecraft; using IO.Astrodynamics.Maneuver; @@ -56,6 +57,7 @@ public void AddAdditionalCelestialBody() } [Fact] + [Benchmark] public void Propagate() { DateTime start = DateTimeExtension.CreateUTC(667915269.18539762).ToTDB(); @@ -110,56 +112,56 @@ public void Propagate() // Read maneuver results var maneuver = spacecraft.StandbyManeuver; - Assert.Equal("2021-03-04T00:32:49.8175394 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T00:32:58.2100803 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); - Assert.Equal("2021-03-04T00:32:49.8175394 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T00:32:58.2100803 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); - Assert.Equal(8.3925409000000002, maneuver.ThrustWindow.Length.TotalSeconds, 3); - Assert.Equal(new Vector3(-97.0714098295484, 107.8305292474044, -119.8974902969949), ((ImpulseManeuver)maneuver).DeltaV); + Assert.Equal("2021-03-04T00:32:53.8146003 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T00:33:02.2130194 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); + Assert.Equal("2021-03-04T00:32:53.8146003 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T00:33:02.2130194 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); + Assert.Equal(8.3984190999999999, maneuver.ThrustWindow.Length.TotalSeconds, 3); + Assert.Equal(new Vector3(-97.1412202651915, 107.90256552680627, -119.98761196522472), ((ImpulseManeuver)maneuver).DeltaV); - Assert.Equal(419.62704377403645, maneuver.FuelBurned); + Assert.Equal(419.92095543527711, maneuver.FuelBurned); maneuver = maneuver.NextManeuver; - Assert.Equal("2021-03-04T01:15:39.8402441 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T01:16:02.1873755 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); - Assert.Equal("2021-03-04T01:15:39.8402441 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T01:16:02.1873755 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); - Assert.Equal(22.347131399999999, maneuver.ThrustWindow.Length.TotalSeconds, 3); - Assert.Equal(new Vector3(-462.3769514474425, -165.79592575424203, 234.3310697732304), ((ImpulseManeuver)maneuver).DeltaV); - Assert.Equal(1117.3565715207112, maneuver.FuelBurned, 3); + Assert.Equal("2021-03-04T01:15:39.8407123 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:16:02.1869075 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:15:39.8407123 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:16:02.1869075 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); + Assert.Equal(22.3461952, maneuver.ThrustWindow.Length.TotalSeconds, 3); + Assert.Equal(new Vector3(-462.1414550058744, -166.03947455552907, 234.6077171916677), ((ImpulseManeuver)maneuver).DeltaV); + Assert.Equal(1117.3097601570541, maneuver.FuelBurned, 3); maneuver = maneuver.NextManeuver; - Assert.Equal("2021-03-04T01:16:13.2426029 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T04:59:20.7658396 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); - Assert.Equal("2021-03-04T01:16:13.2426029 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T01:16:22.7850168 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:16:13.2426462 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T04:59:20.8256783 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:16:13.2426462 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T01:16:22.7849736 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); Assert.Equal(9.5424138999999997, maneuver.ThrustWindow.Length.TotalSeconds, 3); - Assert.Equal(new Vector3(-139.4951793647351, 85.72332642451474, 194.88236993709975), ((ImpulseManeuver)maneuver).DeltaV); - Assert.Equal(477.12069491886507, maneuver.FuelBurned, 3); + Assert.Equal(new Vector3(-139.49753871704854, 85.72527093628567, 194.88665767803553), ((ImpulseManeuver)maneuver).DeltaV); + Assert.Equal(477.11637079604111, maneuver.FuelBurned, 3); maneuver = maneuver.NextManeuver; - Assert.Equal("2021-03-04T05:23:58.7294586 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T05:24:07.2981610 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); - Assert.Equal("2021-03-04T05:23:58.7294586 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); - Assert.Equal("2021-03-04T05:24:07.2981610 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); + Assert.Equal("2021-03-04T05:23:58.7294805 (TDB)", maneuver.ManeuverWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T05:24:07.2981393 (TDB)", maneuver.ManeuverWindow.EndDate.ToFormattedString()); + Assert.Equal("2021-03-04T05:23:58.7294805 (TDB)", maneuver.ThrustWindow.StartDate.ToFormattedString()); + Assert.Equal("2021-03-04T05:24:07.2981393 (TDB)", maneuver.ThrustWindow.EndDate.ToFormattedString()); Assert.Equal(8.5687023999999994, maneuver.ThrustWindow.Length.TotalSeconds, 3); - Assert.Equal(new Vector3(134.22795291868337, -81.45016347177679, -183.86968653289438), ((ImpulseManeuver)maneuver).DeltaV); - Assert.Equal(428.43511797710403, maneuver.FuelBurned, 3); + Assert.Equal(new Vector3(134.21948840073748, -81.46563131619929, -183.87722556440008), ((ImpulseManeuver)maneuver).DeltaV); + Assert.Equal(428.43294038256437, maneuver.FuelBurned, 3); Assert.Equal(scenario.Window, summary.Window); Assert.Single(summary.SpacecraftSummaries); var maneuverWindow = summary.SpacecraftSummaries.First().ManeuverWindow; if (maneuverWindow != null) { - Assert.Equal(new DateTime(2021, 3, 4, 0, 32, 49, 818, DateTimeKind.Unspecified), maneuverWindow.Value.StartDate, TimeSpan.FromMilliseconds(1)); + Assert.Equal(new DateTime(2021, 3, 4, 0, 32, 53, 814, DateTimeKind.Unspecified), maneuverWindow.Value.StartDate, TimeSpan.FromMilliseconds(1)); Assert.Equal(new DateTime(2021, 3, 4, 5, 27, 13, 014, DateTimeKind.Unspecified), maneuverWindow.Value.EndDate, TimeSpan.FromMilliseconds(1)); } - Assert.Equal(2442.5394281907165, summary.SpacecraftSummaries.First().FuelConsumption, 3); + Assert.Equal(2442.7800000000002, summary.SpacecraftSummaries.First().FuelConsumption, 3); } [Fact] diff --git a/IO.Astrodynamics.sln b/IO.Astrodynamics.sln index f4a1938..8956183 100644 --- a/IO.Astrodynamics.sln +++ b/IO.Astrodynamics.sln @@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IO.Astrodynamics", "IO.Astr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IO.Astrodynamics.Tests", "IO.Astrodynamics.Tests\IO.Astrodynamics.Tests.csproj", "{7D17CAA6-C53A-447D-B6EC-FD71654EB56F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IO.Astrodynamics.Performance", "IO.Astrodynamics.Performance\IO.Astrodynamics.Performance.csproj", "{7ADFCA3F-5B86-4149-B4C8-99195C4E677F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -18,5 +20,9 @@ Global {7D17CAA6-C53A-447D-B6EC-FD71654EB56F}.Debug|Any CPU.Build.0 = Debug|Any CPU {7D17CAA6-C53A-447D-B6EC-FD71654EB56F}.Release|Any CPU.ActiveCfg = Release|Any CPU {7D17CAA6-C53A-447D-B6EC-FD71654EB56F}.Release|Any CPU.Build.0 = Release|Any CPU + {7ADFCA3F-5B86-4149-B4C8-99195C4E677F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7ADFCA3F-5B86-4149-B4C8-99195C4E677F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7ADFCA3F-5B86-4149-B4C8-99195C4E677F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7ADFCA3F-5B86-4149-B4C8-99195C4E677F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/IO.Astrodynamics/IO.Astrodynamics.nuspec b/IO.Astrodynamics/IO.Astrodynamics.nuspec index 71e7f32..1f6d569 100644 --- a/IO.Astrodynamics/IO.Astrodynamics.nuspec +++ b/IO.Astrodynamics/IO.Astrodynamics.nuspec @@ -4,7 +4,7 @@ IO.Astrodynamics Sylvain Guillet Sylvain Guillet - 1.9.1 + 1.9.2 Astrodynamics framework images\dragonfly-dark-trans.png docs\README.md diff --git a/IO.Astrodynamics/Maneuver/ApogeeHeightManeuver.cs b/IO.Astrodynamics/Maneuver/ApogeeHeightManeuver.cs index 7dec4eb..7b361f9 100644 --- a/IO.Astrodynamics/Maneuver/ApogeeHeightManeuver.cs +++ b/IO.Astrodynamics/Maneuver/ApogeeHeightManeuver.cs @@ -1,5 +1,7 @@ using System; using IO.Astrodynamics.Body.Spacecraft; +using IO.Astrodynamics.Math; +using IO.Astrodynamics.OrbitalParameters; namespace IO.Astrodynamics.Maneuver { diff --git a/IO.Astrodynamics/Maneuver/ApsidalAlignmentManeuver.cs b/IO.Astrodynamics/Maneuver/ApsidalAlignmentManeuver.cs index f32b080..7730315 100644 --- a/IO.Astrodynamics/Maneuver/ApsidalAlignmentManeuver.cs +++ b/IO.Astrodynamics/Maneuver/ApsidalAlignmentManeuver.cs @@ -1,5 +1,7 @@ using System; using IO.Astrodynamics.Body.Spacecraft; +using IO.Astrodynamics.Math; +using IO.Astrodynamics.OrbitalParameters; namespace IO.Astrodynamics.Maneuver diff --git a/IO.Astrodynamics/Maneuver/CombinedManeuver.cs b/IO.Astrodynamics/Maneuver/CombinedManeuver.cs index e395b30..445af6e 100644 --- a/IO.Astrodynamics/Maneuver/CombinedManeuver.cs +++ b/IO.Astrodynamics/Maneuver/CombinedManeuver.cs @@ -1,5 +1,7 @@ using System; using IO.Astrodynamics.Body.Spacecraft; +using IO.Astrodynamics.Math; +using IO.Astrodynamics.OrbitalParameters; namespace IO.Astrodynamics.Maneuver { diff --git a/IO.Astrodynamics/Maneuver/ImpulseManeuver.cs b/IO.Astrodynamics/Maneuver/ImpulseManeuver.cs index 36073ef..3d6a8b9 100644 --- a/IO.Astrodynamics/Maneuver/ImpulseManeuver.cs +++ b/IO.Astrodynamics/Maneuver/ImpulseManeuver.cs @@ -1,6 +1,8 @@ using System; +using System.Threading.Tasks; using IO.Astrodynamics.Body.Spacecraft; using IO.Astrodynamics.Math; +using IO.Astrodynamics.OrbitalParameters; namespace IO.Astrodynamics.Maneuver { diff --git a/IO.Astrodynamics/Maneuver/InstrumentPointingToAttitude.cs b/IO.Astrodynamics/Maneuver/InstrumentPointingToAttitude.cs index bbaf55f..03cf0f6 100644 --- a/IO.Astrodynamics/Maneuver/InstrumentPointingToAttitude.cs +++ b/IO.Astrodynamics/Maneuver/InstrumentPointingToAttitude.cs @@ -3,6 +3,8 @@ using System; using IO.Astrodynamics.Body; using IO.Astrodynamics.Body.Spacecraft; +using IO.Astrodynamics.Math; +using IO.Astrodynamics.OrbitalParameters; namespace IO.Astrodynamics.Maneuver; diff --git a/IO.Astrodynamics/Maneuver/Maneuver.cs b/IO.Astrodynamics/Maneuver/Maneuver.cs index 5b003ba..657fb43 100644 --- a/IO.Astrodynamics/Maneuver/Maneuver.cs +++ b/IO.Astrodynamics/Maneuver/Maneuver.cs @@ -1,25 +1,82 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using IO.Astrodynamics.Body.Spacecraft; - +using IO.Astrodynamics.Math; +using IO.Astrodynamics.OrbitalParameters; using IO.Astrodynamics.Time; namespace IO.Astrodynamics.Maneuver { public abstract class Maneuver { + /// + /// Gets or sets the ThrustWindow instance. + /// + /// + /// The ThrustWindow instance. + /// public Window ThrustWindow { get; internal set; } + + /// + /// The AttitudeWindow property represents the window object used to display attitude-related information. + /// + /// + /// Gets or sets the AttitudeWindow property. + /// public Window AttitudeWindow { get; internal set; } + + /// + /// Gets or sets the ManeuverWindow object that represents the window for controlling maneuvering tasks. + /// + /// + /// The ManeuverWindow object for controlling maneuvering tasks. + /// public Window ManeuverWindow { get; internal set; } + + /// + /// Gets the minimum epoch value. + /// + /// + /// The minimum epoch value represents the earliest date and time when the maneuver can be executed + /// + /// + /// The minimum epoch value. + /// public DateTime MinimumEpoch { get; } + + /// + /// Gets the duration for which a maneuver should be held. + /// + /// + /// This property represents the duration as a TimeSpan object. + /// + /// The maneuver hold duration as a TimeSpan. public TimeSpan ManeuverHoldDuration { get; } + + /// + /// Represents a collection of engine objects. + /// + /// A read-only collection of objects. public IReadOnlyCollection Engines { get; } + + /// + /// Gets or sets the next maneuver. + /// public Maneuver NextManeuver { get; protected set; } + /// + /// Gets the target orbital parameters. + /// + /// The target orbital parameters. public OrbitalParameters.OrbitalParameters TargetOrbit { get; } + /// + /// Gets or sets the amount of fuel burned. + /// public double FuelBurned { get; internal set; } + protected Maneuver(DateTime minimumEpoch, TimeSpan maneuverHoldDuration, OrbitalParameters.OrbitalParameters targetOrbit, params Engine[] engines) { @@ -52,17 +109,17 @@ public Maneuver SetNextManeuver(Maneuver maneuver) public static double ComputeDeltaV(double isp, double initialMass, double finalMass) { - return isp *Constants.g0 * System.Math.Log(initialMass / finalMass) * 1E-03; + return isp * Constants.g0 * System.Math.Log(initialMass / finalMass) * 1E-03; } public static TimeSpan ComputeDeltaT(double isp, double initialMass, double fuelFlow, double deltaV) { - return TimeSpan.FromSeconds(initialMass / fuelFlow * (1 - System.Math.Exp(-deltaV * 1E03 / (isp *Constants.g0)))); + return TimeSpan.FromSeconds(initialMass / fuelFlow * (1 - System.Math.Exp(-deltaV * 1E03 / (isp * Constants.g0)))); } public static double ComputeDeltaM(double isp, double initialMass, double deltaV) { - return initialMass * (1 - System.Math.Exp(-deltaV * 1E03 / (isp *Constants.g0))); + return initialMass * (1 - System.Math.Exp(-deltaV * 1E03 / (isp * Constants.g0))); } } } \ No newline at end of file diff --git a/IO.Astrodynamics/Maneuver/NadirAttitude.cs b/IO.Astrodynamics/Maneuver/NadirAttitude.cs index c427502..70414d7 100644 --- a/IO.Astrodynamics/Maneuver/NadirAttitude.cs +++ b/IO.Astrodynamics/Maneuver/NadirAttitude.cs @@ -2,6 +2,8 @@ using System; using IO.Astrodynamics.Body.Spacecraft; +using IO.Astrodynamics.Math; +using IO.Astrodynamics.OrbitalParameters; namespace IO.Astrodynamics.Maneuver; diff --git a/IO.Astrodynamics/Maneuver/PerigeeHeightManeuver.cs b/IO.Astrodynamics/Maneuver/PerigeeHeightManeuver.cs index 1e2409c..9ff8729 100644 --- a/IO.Astrodynamics/Maneuver/PerigeeHeightManeuver.cs +++ b/IO.Astrodynamics/Maneuver/PerigeeHeightManeuver.cs @@ -1,5 +1,7 @@ using System; using IO.Astrodynamics.Body.Spacecraft; +using IO.Astrodynamics.Math; +using IO.Astrodynamics.OrbitalParameters; namespace IO.Astrodynamics.Maneuver { diff --git a/IO.Astrodynamics/Maneuver/PhasingManeuver.cs b/IO.Astrodynamics/Maneuver/PhasingManeuver.cs index fad02ac..dcab975 100644 --- a/IO.Astrodynamics/Maneuver/PhasingManeuver.cs +++ b/IO.Astrodynamics/Maneuver/PhasingManeuver.cs @@ -1,5 +1,7 @@ using System; using IO.Astrodynamics.Body.Spacecraft; +using IO.Astrodynamics.Math; +using IO.Astrodynamics.OrbitalParameters; namespace IO.Astrodynamics.Maneuver { diff --git a/IO.Astrodynamics/Maneuver/PlaneAlignmentManeuver.cs b/IO.Astrodynamics/Maneuver/PlaneAlignmentManeuver.cs index 76e1953..8b3b6b8 100644 --- a/IO.Astrodynamics/Maneuver/PlaneAlignmentManeuver.cs +++ b/IO.Astrodynamics/Maneuver/PlaneAlignmentManeuver.cs @@ -1,5 +1,7 @@ using System; using IO.Astrodynamics.Body.Spacecraft; +using IO.Astrodynamics.Math; +using IO.Astrodynamics.OrbitalParameters; namespace IO.Astrodynamics.Maneuver { diff --git a/IO.Astrodynamics/Maneuver/ProgradeAttitude.cs b/IO.Astrodynamics/Maneuver/ProgradeAttitude.cs index d2c093c..115b660 100644 --- a/IO.Astrodynamics/Maneuver/ProgradeAttitude.cs +++ b/IO.Astrodynamics/Maneuver/ProgradeAttitude.cs @@ -2,6 +2,8 @@ using System; using IO.Astrodynamics.Body.Spacecraft; +using IO.Astrodynamics.Math; +using IO.Astrodynamics.OrbitalParameters; namespace IO.Astrodynamics.Maneuver; diff --git a/IO.Astrodynamics/Maneuver/RetrogradeAttitude.cs b/IO.Astrodynamics/Maneuver/RetrogradeAttitude.cs index af0d61c..b5ad732 100644 --- a/IO.Astrodynamics/Maneuver/RetrogradeAttitude.cs +++ b/IO.Astrodynamics/Maneuver/RetrogradeAttitude.cs @@ -2,6 +2,8 @@ using System; using IO.Astrodynamics.Body.Spacecraft; +using IO.Astrodynamics.Math; +using IO.Astrodynamics.OrbitalParameters; namespace IO.Astrodynamics.Maneuver; diff --git a/IO.Astrodynamics/Maneuver/ZenithAttitude.cs b/IO.Astrodynamics/Maneuver/ZenithAttitude.cs index 1ba346b..c1286c5 100644 --- a/IO.Astrodynamics/Maneuver/ZenithAttitude.cs +++ b/IO.Astrodynamics/Maneuver/ZenithAttitude.cs @@ -2,6 +2,8 @@ using System; using IO.Astrodynamics.Body.Spacecraft; +using IO.Astrodynamics.Math; +using IO.Astrodynamics.OrbitalParameters; namespace IO.Astrodynamics.Maneuver; diff --git a/IO.Astrodynamics/Math/Plane.cs b/IO.Astrodynamics/Math/Plane.cs index 89bff80..247b726 100644 --- a/IO.Astrodynamics/Math/Plane.cs +++ b/IO.Astrodynamics/Math/Plane.cs @@ -5,6 +5,10 @@ public class Plane public Vector3 Normal { get; } public double Distance { get; } + public static Plane X { get; } = new Plane(Vector3.VectorX); + public static Plane Y { get; } = new Plane(Vector3.VectorY); + public static Plane Z { get; } = new Plane(Vector3.VectorZ); + public Plane(Vector3 normal) : this(normal, 0.0) { } diff --git a/IO.Astrodynamics/Math/Vector3.cs b/IO.Astrodynamics/Math/Vector3.cs index 74a79d3..b709d6a 100644 --- a/IO.Astrodynamics/Math/Vector3.cs +++ b/IO.Astrodynamics/Math/Vector3.cs @@ -1,4 +1,3 @@ - namespace IO.Astrodynamics.Math { public readonly record struct Vector3 @@ -39,6 +38,11 @@ public double Angle(Vector3 vector) return System.Math.Acos(this * vector / (Magnitude() * vector.Magnitude())); } + public double Angle(Vector3 vector, Plane plane) + { + return double.Atan2(this.Cross(vector) * plane.Normal.Normalize(), this * vector); + } + public Vector3 Inverse() { return this * -1.0; diff --git a/IO.Astrodynamics/Mission/Scenario.cs b/IO.Astrodynamics/Mission/Scenario.cs index f092467..b5a72f5 100644 --- a/IO.Astrodynamics/Mission/Scenario.cs +++ b/IO.Astrodynamics/Mission/Scenario.cs @@ -92,14 +92,10 @@ public ScenarioSummary Simulate(DirectoryInfo outputDirectory) { throw new InvalidOperationException("There is nothing to simulate"); } - - var rootDirectory = outputDirectory.CreateSubdirectory(this.Mission.Name).CreateSubdirectory(this.Name); var spacecraftDirectory = rootDirectory.CreateSubdirectory("Spacecrafts"); var siteDirectory = rootDirectory.CreateSubdirectory("Sites"); - - API.Instance.PropagateScenario(this, siteDirectory, spacecraftDirectory); diff --git a/IO.Astrodynamics/OrbitalParameters/EquinoctialElements.cs b/IO.Astrodynamics/OrbitalParameters/EquinoctialElements.cs index 4d60e14..7143538 100644 --- a/IO.Astrodynamics/OrbitalParameters/EquinoctialElements.cs +++ b/IO.Astrodynamics/OrbitalParameters/EquinoctialElements.cs @@ -6,7 +6,15 @@ namespace IO.Astrodynamics.OrbitalParameters { public class EquinoctialElements : OrbitalParameters, IEquatable { - + private double? _argumentOfPeriapsis; + private double? _ascendingNode; + private double? _eccentricAnomaly; + private double? _eccentricity; + private double? _inclination; + private double? _meanAnomaly; + private double? _semisMajorAxis; + private double? _trueAnomaly; + /// /// Constructor @@ -41,51 +49,64 @@ public EquinoctialElements(double p, double f, double g, double h, double k, dou public override double ArgumentOfPeriapsis() { - return System.Math.Atan2(G * H - F * K, F * H + G * K); + _argumentOfPeriapsis ??= System.Math.Atan2(G * H - F * K, F * H + G * K); + return _argumentOfPeriapsis.Value; } public override double AscendingNode() { - return System.Math.Atan(K / H); + _ascendingNode ??= System.Math.Atan(K / H); + return _ascendingNode.Value; } public override double EccentricAnomaly() { + if (_eccentricAnomaly.HasValue) + { + return _eccentricAnomaly.Value; + } + double v = TrueAnomaly(); double e = Eccentricity(); - return 2 * System.Math.Atan((System.Math.Tan(v / 2.0)) / System.Math.Sqrt((1 + e) / (1 - e))); + _eccentricAnomaly = 2 * System.Math.Atan((System.Math.Tan(v / 2.0)) / System.Math.Sqrt((1 + e) / (1 - e))); + return _eccentricAnomaly.Value; } public override double Eccentricity() { - return System.Math.Sqrt(F * F + G * G); + _eccentricity ??= System.Math.Sqrt(F * F + G * G); + return _eccentricity.Value; } public override double Inclination() { - return System.Math.Atan2(2 * System.Math.Sqrt(H * H + K * K), 1 - H * H - K * K); + _inclination ??= System.Math.Atan2(2 * System.Math.Sqrt(H * H + K * K), 1 - H * H - K * K); + return _inclination.Value; } public override double MeanAnomaly() { - return EccentricAnomaly() - Eccentricity() * System.Math.Sin(EccentricAnomaly()); + _meanAnomaly ??= EccentricAnomaly() - Eccentricity() * System.Math.Sin(EccentricAnomaly()); + return _meanAnomaly.Value; } public override double SemiMajorAxis() { - return P / (1 - F * F - G * G); + _semisMajorAxis ??= P / (1 - F * F - G * G); + return _semisMajorAxis.Value; } public override double TrueAnomaly() { - return L0 - (AscendingNode() + ArgumentOfPeriapsis()); + _trueAnomaly ??= L0 - (AscendingNode() + ArgumentOfPeriapsis()); + return _trueAnomaly.Value; } public override EquinoctialElements ToEquinoctial() { return this; } - + public bool Equals(EquinoctialElements other) { if (ReferenceEquals(null, other)) return false; diff --git a/IO.Astrodynamics/OrbitalParameters/KeplerianElements.cs b/IO.Astrodynamics/OrbitalParameters/KeplerianElements.cs index 5c3a6de..b4f52e2 100644 --- a/IO.Astrodynamics/OrbitalParameters/KeplerianElements.cs +++ b/IO.Astrodynamics/OrbitalParameters/KeplerianElements.cs @@ -7,7 +7,9 @@ namespace IO.Astrodynamics.OrbitalParameters { public class KeplerianElements : OrbitalParameters, IEquatable { - + private double? _eccentricAnomaly; + private double? _trueAnomaly; + /// /// Constructor @@ -82,16 +84,21 @@ public override double AscendingNode() public override double EccentricAnomaly() { + if (_eccentricAnomaly.HasValue) + { + return _eccentricAnomaly.Value; + } + double tmpEA = M; - double EA = 0.0; + _eccentricAnomaly = 0.0; - while (System.Math.Abs(tmpEA - EA) > 1E-09) + while (System.Math.Abs(tmpEA - _eccentricAnomaly.Value) > 1E-09) { - EA = tmpEA; - tmpEA = M + E * System.Math.Sin(EA); + _eccentricAnomaly = tmpEA; + tmpEA = M + E * System.Math.Sin(_eccentricAnomaly.Value); } - return EA; + return _eccentricAnomaly.Value; } public override double Eccentricity() @@ -111,14 +118,19 @@ public override double SemiMajorAxis() public override double TrueAnomaly() { + if (_trueAnomaly.HasValue) + { + return _trueAnomaly.Value; + } double EA = EccentricAnomaly(); - double v = System.Math.Atan2(System.Math.Sqrt(1 - E * E) * System.Math.Sin(EA), System.Math.Cos(EA) - E); - if (v < 0.0) + _trueAnomaly = System.Math.Atan2(System.Math.Sqrt(1 - E * E) * System.Math.Sin(EA), System.Math.Cos(EA) - E); + if (_trueAnomaly < 0.0) { - v += Constants._2PI; + _trueAnomaly += Constants._2PI; } - return v % Constants._2PI; + _trueAnomaly %= Constants._2PI; + return _trueAnomaly.Value; } public override double MeanAnomaly() @@ -130,7 +142,7 @@ public override KeplerianElements ToKeplerianElements() { return this; } - + public bool Equals(KeplerianElements other) { if (ReferenceEquals(null, other)) return false; diff --git a/IO.Astrodynamics/OrbitalParameters/OrbitalParameters.cs b/IO.Astrodynamics/OrbitalParameters/OrbitalParameters.cs index 27db536..d6c3672 100644 --- a/IO.Astrodynamics/OrbitalParameters/OrbitalParameters.cs +++ b/IO.Astrodynamics/OrbitalParameters/OrbitalParameters.cs @@ -15,6 +15,26 @@ public abstract class OrbitalParameters : IEquatable public DateTime Epoch { get; } public Frame Frame { get; } + protected Vector3? _eccentricVector; + protected Vector3? _specificAngularMomentum; + protected double? _specificOrbitalEnergy; + protected Vector3? _ascendingNodeVector; + protected Vector3? _decendingNodeVector; + protected TimeSpan? _period; + protected double? _meanMotion; + protected StateVector _stateVector; + protected EquinoctialElements _equinoctial; + protected Vector3? _perigeevector; + protected Vector3? _apogeeVector; + protected double? _trueLongitude; + protected double? _meanLongitude; + protected bool? _isCircular; + protected bool? _isParabolic; + protected bool? _isHyperbolic; + protected KeplerianElements _keplerianElements; + protected Equatorial? _equatorial; + protected double? _perigeeVelocity; + protected double? _apogeeVelocity; /// /// Constructor @@ -35,7 +55,9 @@ protected OrbitalParameters(ILocalizable observer, DateTime epoch, Frame frame) /// public virtual Vector3 EccentricityVector() { - return ToStateVector().EccentricityVector(); + _eccentricVector ??= ToStateVector().EccentricityVector(); + + return _eccentricVector.Value; } /// @@ -50,7 +72,8 @@ public virtual Vector3 EccentricityVector() /// public virtual Vector3 SpecificAngularMomentum() { - return ToStateVector().SpecificAngularMomentum(); + _specificAngularMomentum ??= ToStateVector().SpecificAngularMomentum(); + return _specificAngularMomentum.Value; } /// @@ -59,7 +82,8 @@ public virtual Vector3 SpecificAngularMomentum() /// public virtual double SpecificOrbitalEnergy() { - return ToStateVector().SpecificOrbitalEnergy(); + _specificOrbitalEnergy ??= ToStateVector().SpecificOrbitalEnergy(); + return _specificOrbitalEnergy.Value; } /// @@ -85,7 +109,8 @@ public virtual Vector3 AscendingNodeVector() return Vector3.VectorX; } - return ToStateVector().AscendingNodeVector(); + _ascendingNodeVector ??= ToStateVector().AscendingNodeVector(); + return _ascendingNodeVector.Value; } /// @@ -94,7 +119,8 @@ public virtual Vector3 AscendingNodeVector() /// public Vector3 DescendingNodeVector() { - return AscendingNodeVector().Inverse(); + _decendingNodeVector ??= AscendingNodeVector().Inverse(); + return _decendingNodeVector.Value; } /// @@ -163,9 +189,14 @@ public static double TrueAnomalyToMeanAnomaly(double trueAnomaly, double eccentr /// public TimeSpan Period() { - double a = SemiMajorAxis(); - double T = Constants._2PI * System.Math.Sqrt((a * a * a) / Observer.GM); - return TimeSpan.FromSeconds(T); + if (!_period.HasValue) + { + double a = SemiMajorAxis(); + double T = Constants._2PI * System.Math.Sqrt((a * a * a) / Observer.GM); + _period = TimeSpan.FromSeconds(T); + } + + return _period.Value; } /// @@ -174,7 +205,8 @@ public TimeSpan Period() /// public double MeanMotion() { - return Constants._2PI / Period().TotalSeconds; + _meanMotion ??= Constants._2PI / Period().TotalSeconds; + return _meanMotion.Value; } @@ -184,24 +216,29 @@ public double MeanMotion() /// public virtual StateVector ToStateVector() { - var e = Eccentricity(); - var p = SemiMajorAxis() * (1 - e * e); - var v = TrueAnomaly(); - var r0 = p / (1 + e * System.Math.Cos(v)); - var x = r0 * System.Math.Cos(v); - var y = r0 * System.Math.Sin(v); - var dotX = -System.Math.Sqrt(Observer.GM / p) * System.Math.Sin(v); - var dotY = System.Math.Sqrt(Observer.GM / p) * (e + System.Math.Cos(v)); - Matrix R3 = Matrix.CreateRotationMatrixZ(AscendingNode()); - Matrix R1 = Matrix.CreateRotationMatrixX(Inclination()); - Matrix R3w = Matrix.CreateRotationMatrixZ(ArgumentOfPeriapsis()); - Matrix R = R3 * R1 * R3w; - double[] pos = { x, y, 0.0 }; - double[] vel = { dotX, dotY, 0.0 }; - double[] finalPos = pos * R; - double[] finalV = vel * R; - - return new StateVector(new Vector3(finalPos[0], finalPos[1], finalPos[2]), new Vector3(finalV[0], finalV[1], finalV[2]), Observer, Epoch, Frame); + if (_stateVector is null) + { + var e = Eccentricity(); + var p = SemiMajorAxis() * (1 - e * e); + var v = TrueAnomaly(); + var r0 = p / (1 + e * System.Math.Cos(v)); + var x = r0 * System.Math.Cos(v); + var y = r0 * System.Math.Sin(v); + var dotX = -System.Math.Sqrt(Observer.GM / p) * System.Math.Sin(v); + var dotY = System.Math.Sqrt(Observer.GM / p) * (e + System.Math.Cos(v)); + Matrix R3 = Matrix.CreateRotationMatrixZ(AscendingNode()); + Matrix R1 = Matrix.CreateRotationMatrixX(Inclination()); + Matrix R3w = Matrix.CreateRotationMatrixZ(ArgumentOfPeriapsis()); + Matrix R = R3 * R1 * R3w; + double[] pos = { x, y, 0.0 }; + double[] vel = { dotX, dotY, 0.0 }; + double[] finalPos = pos * R; + double[] finalV = vel * R; + + _stateVector = new StateVector(new Vector3(finalPos[0], finalPos[1], finalPos[2]), new Vector3(finalV[0], finalV[1], finalV[2]), Observer, Epoch, Frame); + } + + return _stateVector; } public virtual StateVector ToStateVector(DateTime epoch) @@ -215,20 +252,25 @@ public virtual StateVector ToStateVector(DateTime epoch) /// public virtual EquinoctialElements ToEquinoctial() { - double e = Eccentricity(); - double o = AscendingNode(); - double w = ArgumentOfPeriapsis(); - double i = Inclination(); - double v = TrueAnomaly(); - - double p = SemiMajorAxis() * (1 - e * e); - double f = e * System.Math.Cos(o + w); - double g = e * System.Math.Sin(o + w); - double h = System.Math.Tan(i * 0.5) * System.Math.Cos(o); - double k = System.Math.Tan(i * 0.5) * System.Math.Sin(o); - double l0 = o + w + v; + if (_equinoctial is null) + { + double e = Eccentricity(); + double o = AscendingNode(); + double w = ArgumentOfPeriapsis(); + double i = Inclination(); + double v = TrueAnomaly(); + + double p = SemiMajorAxis() * (1 - e * e); + double f = e * System.Math.Cos(o + w); + double g = e * System.Math.Sin(o + w); + double h = System.Math.Tan(i * 0.5) * System.Math.Cos(o); + double k = System.Math.Tan(i * 0.5) * System.Math.Sin(o); + double l0 = o + w + v; + + _equinoctial = new EquinoctialElements(p, f, g, h, k, l0, Observer, Epoch, Frame); + } - return new EquinoctialElements(p, f, g, h, k, l0, Observer, Epoch, Frame); + return _equinoctial; } /// @@ -242,7 +284,8 @@ public Vector3 PerigeeVector() return Vector3.VectorX * SemiMajorAxis(); } - return EccentricityVector().Normalize() * SemiMajorAxis() * (1.0 - Eccentricity()); + _perigeevector ??= EccentricityVector().Normalize() * SemiMajorAxis() * (1.0 - Eccentricity()); + return _perigeevector.Value; } /// @@ -256,7 +299,8 @@ public Vector3 ApogeeVector() return Vector3.VectorX.Inverse() * SemiMajorAxis(); } - return EccentricityVector().Normalize().Inverse() * SemiMajorAxis() * (1.0 + Eccentricity()); + _apogeeVector ??= EccentricityVector().Normalize().Inverse() * SemiMajorAxis() * (1.0 + Eccentricity()); + return _apogeeVector.Value; } /// @@ -275,7 +319,8 @@ public virtual OrbitalParameters AtEpoch(DateTime epoch) /// public double TrueLongitude() { - return (AscendingNode() + ArgumentOfPeriapsis() + TrueAnomaly()) % Constants._2PI; + _trueLongitude ??= (AscendingNode() + ArgumentOfPeriapsis() + TrueAnomaly()) % Constants._2PI; + return _trueLongitude.Value; } /// @@ -284,22 +329,26 @@ public double TrueLongitude() /// public double MeanLongitude() { - return (AscendingNode() + ArgumentOfPeriapsis() + MeanAnomaly()) % Constants._2PI; + _meanLongitude ??= (AscendingNode() + ArgumentOfPeriapsis() + MeanAnomaly()) % Constants._2PI; + return _meanLongitude.Value; } public bool IsCircular() { - return Eccentricity() < 1E-03; + _isCircular ??= Eccentricity() < 1E-03; + return _isCircular.Value; } public bool IsParabolic() { - return System.Math.Abs(Eccentricity() - 1.0) < double.Epsilon; + _isParabolic ??= System.Math.Abs(Eccentricity() - 1.0) < double.Epsilon; + return _isParabolic.Value; } public bool IsHyperbolic() { - return Eccentricity() > 1.0; + _isHyperbolic ??= Eccentricity() > 1.0; + return _isHyperbolic.Value; } private KeplerianElements ToKeplerianElements(DateTime epoch) @@ -316,7 +365,8 @@ private KeplerianElements ToKeplerianElements(DateTime epoch) public virtual KeplerianElements ToKeplerianElements() { - return ToKeplerianElements(Epoch); + _keplerianElements ??= ToKeplerianElements(Epoch); + return _keplerianElements; } public OrbitalParameters ToFrame(Frame frame) @@ -335,17 +385,20 @@ public OrbitalParameters ToFrame(Frame frame) public Equatorial ToEquatorial() { - return new Equatorial(ToStateVector()); + _equatorial ??= new Equatorial(ToStateVector()); + return _equatorial.Value; } public double PerigeeVelocity() { - return System.Math.Sqrt(Observer.GM * (2 / PerigeeVector().Magnitude() - 1.0 / SemiMajorAxis())); + _perigeeVelocity ??= System.Math.Sqrt(Observer.GM * (2 / PerigeeVector().Magnitude() - 1.0 / SemiMajorAxis())); + return _perigeeVelocity.Value; } public double ApogeeVelocity() { - return System.Math.Sqrt(Observer.GM * (2 / ApogeeVector().Magnitude() - 1.0 / SemiMajorAxis())); + _apogeeVelocity ??= System.Math.Sqrt(Observer.GM * (2 / ApogeeVector().Magnitude() - 1.0 / SemiMajorAxis())); + return _apogeeVelocity.Value; } public override bool Equals(object obj) diff --git a/IO.Astrodynamics/OrbitalParameters/StateVector.cs b/IO.Astrodynamics/OrbitalParameters/StateVector.cs index eb65b12..2c0988f 100644 --- a/IO.Astrodynamics/OrbitalParameters/StateVector.cs +++ b/IO.Astrodynamics/OrbitalParameters/StateVector.cs @@ -7,6 +7,15 @@ namespace IO.Astrodynamics.OrbitalParameters { public class StateVector : OrbitalParameters, IEquatable { + private double? _eccentricity; + private double? _inclination; + private double? _semiMajorAxis; + private double? _ascendingNode; + private double? _argumentOfPeriapsis; + private double? _trueAnomaly; + private double? _eccentricAnomaly; + private double? _meanAnomaly; + private StateVector _inverse; public Vector3 Position { get; internal set; } public Vector3 Velocity { get; internal set; } @@ -26,48 +35,66 @@ public StateVector(Vector3 position, Vector3 velocity, ILocalizable observer, Da public override Vector3 SpecificAngularMomentum() { - return Position.Cross(Velocity); + _specificAngularMomentum ??= Position.Cross(Velocity); + return _specificAngularMomentum.Value; } public override double Eccentricity() { - return EccentricityVector().Magnitude(); + _eccentricity ??= EccentricityVector().Magnitude(); + return _eccentricity.Value; } public override Vector3 EccentricityVector() { - return (Velocity.Cross(SpecificAngularMomentum()) / Observer.GM) - (Position / Position.Magnitude()); + _eccentricVector ??= (Velocity.Cross(SpecificAngularMomentum()) / Observer.GM) - (Position / Position.Magnitude()); + return _eccentricVector.Value; } public override double Inclination() { - return SpecificAngularMomentum().Angle(Vector3.VectorZ); + _inclination ??= SpecificAngularMomentum().Angle(Vector3.VectorZ); + return _inclination.Value; } public override double SpecificOrbitalEnergy() { - return System.Math.Pow(Velocity.Magnitude(), 2.0) / 2.0 - (Observer.GM / Position.Magnitude()); + _specificOrbitalEnergy ??= System.Math.Pow(Velocity.Magnitude(), 2.0) / 2.0 - (Observer.GM / Position.Magnitude()); + return _specificOrbitalEnergy.Value; } public override double SemiMajorAxis() { - return -(Observer.GM / (2.0 * SpecificOrbitalEnergy())); + _semiMajorAxis ??= -(Observer.GM / (2.0 * SpecificOrbitalEnergy())); + return _semiMajorAxis.Value; } public override Vector3 AscendingNodeVector() { + if (_ascendingNodeVector.HasValue) + { + return _ascendingNodeVector.Value; + } + if (Inclination() == 0.0) { return Vector3.VectorX; } var h = SpecificAngularMomentum(); - return new Vector3(-h.Y, h.X, 0.0); + _ascendingNodeVector = new Vector3(-h.Y, h.X, 0.0); + + return _ascendingNodeVector.Value; } public override double AscendingNode() { + if (_ascendingNode.HasValue) + { + return _ascendingNode.Value; + } + Vector3 n = AscendingNodeVector(); var omega = System.Math.Acos(n.X / n.Magnitude()); @@ -76,41 +103,58 @@ public override double AscendingNode() omega = 2 * System.Math.PI - omega; } - return omega; + _ascendingNode = omega; + + + return _ascendingNode.Value; } public override double ArgumentOfPeriapsis() { + if (_argumentOfPeriapsis.HasValue) + { + return _argumentOfPeriapsis.Value; + } + var n = AscendingNodeVector(); var e = EccentricityVector(); - var w = System.Math.Acos((n * e) / (n.Magnitude() * e.Magnitude())); + _argumentOfPeriapsis = System.Math.Acos((n * e) / (n.Magnitude() * e.Magnitude())); if (e.Z < 0.0) { - w = System.Math.PI * 2.0 - w; + _argumentOfPeriapsis = System.Math.PI * 2.0 - _argumentOfPeriapsis; } - return w; + return _argumentOfPeriapsis.Value; } public override double TrueAnomaly() { + if (_trueAnomaly.HasValue) + { + return _trueAnomaly.Value; + } + + if (IsCircular()) { if (Inclination() < 1E-03) { - return CircularNoInclinationTrueAnomaly(); + _trueAnomaly = CircularNoInclinationTrueAnomaly(); + return _trueAnomaly.Value; } - return CircularTrueAnomaly(); + _trueAnomaly = CircularTrueAnomaly(); + return _trueAnomaly.Value; } + var e = EccentricityVector(); - var v = System.Math.Acos((e * Position) / (e.Magnitude() * Position.Magnitude())); + _trueAnomaly = System.Math.Acos((e * Position) / (e.Magnitude() * Position.Magnitude())); if (Position * Velocity < 0.0) { - v = System.Math.PI * 2.0 - v; + _trueAnomaly = System.Math.PI * 2.0 - _trueAnomaly; } - return v; + return _trueAnomaly.Value; } private double CircularTrueAnomaly() @@ -130,7 +174,7 @@ private double CircularTrueAnomaly() return v % Constants._2PI; } - + private double CircularNoInclinationTrueAnomaly() { var l = System.Math.Acos(Position.X / Position.Magnitude()); @@ -150,9 +194,15 @@ private double CircularNoInclinationTrueAnomaly() public override double EccentricAnomaly() { + if (_eccentricAnomaly.HasValue) + { + return _eccentricAnomaly.Value; + } + double v = TrueAnomaly(); double e = Eccentricity(); - return 2 * System.Math.Atan((System.Math.Tan(v / 2.0)) / System.Math.Sqrt((1 + e) / (1 - e))); + _eccentricAnomaly ??= 2 * System.Math.Atan((System.Math.Tan(v / 2.0)) / System.Math.Sqrt((1 + e) / (1 - e))); + return _eccentricAnomaly.Value; } public override StateVector ToStateVector() @@ -162,7 +212,13 @@ public override StateVector ToStateVector() public override double MeanAnomaly() { - return EccentricAnomaly() - Eccentricity() * System.Math.Sin(EccentricAnomaly()); + if (_meanAnomaly.HasValue) + { + return _meanAnomaly.Value; + } + + _meanAnomaly ??= EccentricAnomaly() - Eccentricity() * System.Math.Sin(EccentricAnomaly()); + return _meanAnomaly.Value; } public static StateVector operator +(StateVector sv1, StateVector sv2) @@ -193,7 +249,13 @@ public double[] ToArray() public StateVector Inverse() { - return new StateVector(Position.Inverse(), Velocity.Inverse(), Observer, Epoch, Frame); + if (_inverse is not null) + { + return _inverse; + } + + _inverse ??= new StateVector(Position.Inverse(), Velocity.Inverse(), Observer, Epoch, Frame); + return _inverse; } diff --git a/IO.Astrodynamics/resources/IO.Astrodynamics.dll b/IO.Astrodynamics/resources/IO.Astrodynamics.dll index ca952ff..6580bb1 100644 Binary files a/IO.Astrodynamics/resources/IO.Astrodynamics.dll and b/IO.Astrodynamics/resources/IO.Astrodynamics.dll differ diff --git a/IO.Astrodynamics/resources/IO.Astrodynamics.lib b/IO.Astrodynamics/resources/IO.Astrodynamics.lib index 6365687..265eb51 100644 Binary files a/IO.Astrodynamics/resources/IO.Astrodynamics.lib and b/IO.Astrodynamics/resources/IO.Astrodynamics.lib differ diff --git a/IO.Astrodynamics/resources/libIO.Astrodynamics.so b/IO.Astrodynamics/resources/libIO.Astrodynamics.so index d802f7f..2f85301 100755 Binary files a/IO.Astrodynamics/resources/libIO.Astrodynamics.so and b/IO.Astrodynamics/resources/libIO.Astrodynamics.so differ