Skip to content
This repository has been archived by the owner on Aug 5, 2024. It is now read-only.

Commit

Permalink
Feature/propagator into spc (#83)
Browse files Browse the repository at this point in the history
* Add AOT

* Remove automapper

* Kernel loading and performance optimization

* Propagate sites

* Embed star in scenario

* Update Nuspec and fix propagation window to fit exactly requested window
  • Loading branch information
sylvain-guillet authored Mar 15, 2024
1 parent c71d63f commit 2832e13
Show file tree
Hide file tree
Showing 21 changed files with 724 additions and 188 deletions.
2 changes: 0 additions & 2 deletions IO.Astrodynamics.Tests/APITest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,6 @@ public async Task ReadOrientation()
var root = Constants.OutputPath.CreateSubdirectory(scenario.Mission.Name).CreateSubdirectory(scenario.Name);
await scenario.SimulateAsync(root, false, false, TimeSpan.FromSeconds(1.0));

API.Instance.LoadKernels(scenario.SpacecraftDirectory);
API.Instance.LoadKernels(scenario.SiteDirectory);
//Read spacecraft orientation
var res = API.Instance.ReadOrientation(window, spacecraft, TimeSpan.FromSeconds(10.0), Frames.Frame.ICRF,
TimeSpan.FromSeconds(10.0)).ToArray();
Expand Down
3 changes: 1 addition & 2 deletions IO.Astrodynamics.Tests/Body/InstrumentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ public async Task FindWindowInFieldOfView()

//Execute scenario
await scenario.SimulateAsync(root, false, false, TimeSpan.FromSeconds(1.0));
API.Instance.LoadKernels(scenario.SpacecraftDirectory);
API.Instance.LoadKernels(scenario.SiteDirectory);

//Find windows when the earth is in field of view of camera 600
var res = spacecraft.Instruments.First().FindWindowsInFieldOfViewConstraint(
new Window(DateTimeExtension.CreateTDB(676555200.0), DateTimeExtension.CreateTDB(676561646.0)), spacecraft,
Expand Down
1 change: 0 additions & 1 deletion IO.Astrodynamics.Tests/Body/SpacecraftTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ public async Task GetOrientation()

//Execute scenario
await scenario.SimulateAsync(root, false, false, TimeSpan.FromSeconds(1.0));
API.Instance.LoadKernels(scenario.SpacecraftDirectory);

var orientation = spacecraft.GetOrientation(Frames.Frame.ICRF, start);
Vector3.VectorY.Rotate(orientation.Rotation);
Expand Down
5 changes: 3 additions & 2 deletions IO.Astrodynamics.Tests/Body/StarTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using IO.Astrodynamics.Body;
using IO.Astrodynamics.Coordinates;
using IO.Astrodynamics.Time;
Expand Down Expand Up @@ -73,12 +74,12 @@ public void GetRightAscensionSigma()
}

[Fact]
public void Propagate()
public async Task Propagate()
{
var epoch = new DateTime(2001, 1, 1);
var observer = new Barycenter(0);
var star = new Star(1, "star1", 1E+30, "spec", 2, 0.3792, new Equatorial(1, 1), 0.1, 0.1, 0, 0, 0, 0, epoch);
star.Propagate(new Window(epoch, epoch + TimeSpan.FromDays(365 * 4)), TimeSpan.FromDays(365));
await star.PropagateAsync(new Window(epoch, epoch + TimeSpan.FromDays(365 * 4)), TimeSpan.FromDays(365),Constants.OutputPath);
var eph0 = star.GetEphemeris(epoch, observer, Frames.Frame.ICRF, Aberration.None);
var eph1 = star.GetEphemeris(epoch.Add(TimeSpan.FromDays(365)), observer, Frames.Frame.ICRF, Aberration.None);
var eph2 = star.GetEphemeris(epoch.Add(TimeSpan.FromDays(365 + 365)), observer, Frames.Frame.ICRF, Aberration.None);
Expand Down
208 changes: 198 additions & 10 deletions IO.Astrodynamics.Tests/Mission/ScenarioTests.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ public void IntegrateWithPerturbations()
forces.Add(new AtmosphericDrag(spc));
forces.Add(new SolarRadiationPressure(spc));
VVIntegrator vvIntegrator = new VVIntegrator(forces, TimeSpan.FromSeconds(1.0), spc.InitialOrbitalParameters.ToStateVector());
TimeSpan deltaT = TimeSpan.FromSeconds(1.0);
StateVector[] data = new StateVector[2];
Array.Fill(data, spc.InitialOrbitalParameters.ToStateVector(), 0, 2);
vvIntegrator.Integrate(data, 1);
Expand Down
89 changes: 50 additions & 39 deletions IO.Astrodynamics/API.cs

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions IO.Astrodynamics/Body/Spacecraft/FuelTank.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,10 @@ public override int GetHashCode()
{
return !Equals(left, right);
}

internal void Refuel()
{
Quantity = InitialQuantity;
}
}
}
114 changes: 111 additions & 3 deletions IO.Astrodynamics/Body/Spacecraft/Spacecraft.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
using System.Threading.Tasks;
using IO.Astrodynamics.Frames;
using IO.Astrodynamics.Math;
using IO.Astrodynamics.OrbitalParameters;
using IO.Astrodynamics.Propagator;
using IO.Astrodynamics.Time;
using StateOrientation = IO.Astrodynamics.OrbitalParameters.StateOrientation;


namespace IO.Astrodynamics.Body.Spacecraft
{
public class Spacecraft : CelestialItem, IOrientable
public class Spacecraft : CelestialItem, IOrientable, IDisposable
{
public static readonly Vector3 Front = Vector3.VectorY;
public static readonly Vector3 Back = Front.Inverse();
Expand All @@ -22,6 +24,7 @@ public class Spacecraft : CelestialItem, IOrientable
private readonly HashSet<Maneuver.Maneuver> _executedManeuvers = new HashSet<Maneuver.Maneuver>();
public IReadOnlyCollection<Maneuver.Maneuver> ExecutedManeuvers => _executedManeuvers;
public Maneuver.Maneuver StandbyManeuver { get; private set; }
public Maneuver.Maneuver InitialManeuver { get; private set; }
public Spacecraft Parent { get; private set; }
public Spacecraft Child { get; private set; }
public Clock Clock { get; }
Expand All @@ -42,6 +45,8 @@ public class Spacecraft : CelestialItem, IOrientable
public Frame Frame { get; }
public double SectionalArea { get; }
public double DragCoefficient { get; }
public DirectoryInfo PropagationOutput { get; private set; }
public bool IsPropagated => PropagationOutput != null;

/// <summary>
/// Spacecraft constructor
Expand Down Expand Up @@ -265,9 +270,19 @@ public void SetStandbyManeuver(Maneuver.Maneuver maneuver, DateTime? minimumEpoc
_executedManeuvers.Add(StandbyManeuver);
}

if (StandbyManeuver == null)
{
InitialManeuver = maneuver;
}

StandbyManeuver = maneuver;
}

/// <summary>
/// Set the initial orbital parameter
/// </summary>
/// <param name="orbitalParameters"></param>
/// <exception cref="ArgumentNullException"></exception>
public void SetInitialOrbitalParameters(OrbitalParameters.OrbitalParameters orbitalParameters)
{
if (orbitalParameters == null) throw new ArgumentNullException(nameof(orbitalParameters));
Expand Down Expand Up @@ -298,9 +313,102 @@ internal SpacecraftSummary GetSummary()
return new SpacecraftSummary(this, _executedManeuvers);
}

internal async Task WriteFrameAsync(FileInfo outputFile)
/// <summary>
/// Write frame
/// </summary>
/// <param name="outputFile"></param>
private async Task WriteFrameAsync(FileInfo outputFile)
{
await (Frame as SpacecraftFrame)!.WriteAsync(outputFile);
}

/// <summary>
/// Propagate spacecraft
/// </summary>
/// <param name="window"></param>
/// <param name="additionalCelestialBodies">Celestial bodies involved as perturbation bodies</param>
/// <param name="includeAtmosphericDrag"></param>
/// <param name="includeSolarRadiationPressure"></param>
/// <param name="propagatorStepSize"></param>
/// <param name="outputDirectory"></param>
public async Task PropagateAsync(Window window, IEnumerable<CelestialBody> additionalCelestialBodies, bool includeAtmosphericDrag,
bool includeSolarRadiationPressure, TimeSpan propagatorStepSize, DirectoryInfo outputDirectory)
{
ResetPropagation();
var propagator = new SpacecraftPropagator(window, this, additionalCelestialBodies, includeAtmosphericDrag, includeSolarRadiationPressure, propagatorStepSize);
var res = propagator.Propagate();
PropagationOutput = outputDirectory.CreateSubdirectory(Name);

//Write frame
await WriteFrameAsync(new FileInfo(Path.Combine(PropagationOutput.CreateSubdirectory("Frames").FullName, Name + ".tf")));


//write instrument frame and kernel
var instrumentDirectory = PropagationOutput.CreateSubdirectory("Instruments");
foreach (var instrument in Instruments)
{
await instrument.WriteFrameAsync(new FileInfo(Path.Combine(instrumentDirectory.FullName, instrument.Name + ".tf")));
await instrument.WriteKernelAsync(new FileInfo(Path.Combine(instrumentDirectory.FullName, instrument.Name + ".ti")));
}

//Write clock
var clockFile = new FileInfo(Path.Combine(PropagationOutput.CreateSubdirectory("Clocks").FullName, Name + ".tsc"));
await Clock.WriteAsync(clockFile);

//Write Ephemeris
if (API.Instance.WriteEphemeris(new FileInfo(Path.Combine(PropagationOutput.CreateSubdirectory("Ephemeris").FullName, Name + ".spk")), this,
res.stateVectors))
{
//Clock is loaded because is needed by orientation writer
API.Instance.LoadKernels(clockFile);
//Write Orientation
if (API.Instance.WriteOrientation(new FileInfo(Path.Combine(PropagationOutput.CreateSubdirectory("Orientation").FullName, Name + ".ck")), this,
res.stateOrientations))
{
API.Instance.LoadKernels(PropagationOutput);
}
}
}

/// <summary>
/// Reset propagation elements
/// </summary>
private void ResetPropagation()
{
if (IsPropagated)
{
API.Instance.UnloadKernels(PropagationOutput);
PropagationOutput.Delete(true);
PropagationOutput = null;
}

_executedManeuvers.Clear();
foreach (var fuelTank in FuelTanks)
{
fuelTank.Refuel();
}

InitialManeuver?.Reset();
StandbyManeuver = InitialManeuver;
}

private void ReleaseUnmanagedResources()
{
if (IsPropagated)
{
API.Instance.UnloadKernels(PropagationOutput);
}
}

public void Dispose()
{
ReleaseUnmanagedResources();
GC.SuppressFinalize(this);
}

~Spacecraft()
{
ReleaseUnmanagedResources();
}
}
}
70 changes: 59 additions & 11 deletions IO.Astrodynamics/Body/Star.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using IO.Astrodynamics.Coordinates;
using IO.Astrodynamics.Frames;
using IO.Astrodynamics.Math;
Expand All @@ -9,7 +10,7 @@

namespace IO.Astrodynamics.Body;

public class Star : CelestialBody
public class Star : CelestialBody, IDisposable
{
public Star(int catalogNumber, string name, double mass, string spectralType, double visualMagnitude, double parallax, Equatorial equatorialCoordinatesAtEpoch,
double declinationProperMotion, double rightAscensionProperMotion, double declinationSigma, double rightAscensionSigma, double declinationSigmaProperMotion,
Expand All @@ -35,7 +36,7 @@ public Star(int catalogNumber, string name, double mass, string spectralType, do
public double VisualMagnitude { get; }

/// <summary>
/// ArcSec
/// Parallax in ArcSec
/// </summary>
public double Parallax { get; }

Expand All @@ -53,6 +54,9 @@ public Star(int catalogNumber, string name, double mass, string spectralType, do
public double RightAscensionSigmaProperMotion { get; }
public double DeclinationSigmaProperMotion { get; }

public DirectoryInfo PropagationOutput { get; private set; }
public bool IsPropagated => PropagationOutput != null;

public Equatorial GetEquatorialCoordinates(DateTime epoch)
{
var dt = (epoch.ToJulianDate() - Epoch.ToJulianDate()) / DateTimeExtension.JULIAN_YEAR;
Expand All @@ -79,19 +83,63 @@ public double GetDeclinationSigma(DateTime epoch)
return System.Math.Sqrt(System.Math.Pow(DeclinationSigma, 2) + System.Math.Pow(dt * DeclinationSigmaProperMotion, 2)) % Constants.PI2;
}

public void Propagate(Window timeWindow, TimeSpan stepSize)
/// <summary>
/// Propagate the star
/// </summary>
/// <param name="timeWindow"></param>
/// <param name="stepSize"></param>
/// <param name="starsOutputDirectory"></param>
public Task PropagateAsync(Window timeWindow, TimeSpan stepSize, DirectoryInfo starsOutputDirectory)
{
var path = new FileInfo($"Data/Stars/star{NaifId}.spk");
List<StateVector> svs = new List<StateVector>();
for (DateTime epoch = timeWindow.StartDate; epoch <= timeWindow.EndDate; epoch += stepSize)
return Task.Run(() =>
{
var position = GetEquatorialCoordinates(epoch).ToCartesian();
svs.Add(new StateVector(position, Vector3.Zero, new Barycenter(0), epoch, Frame.ICRF));
}
ResetPropagation();

List<StateVector> svs = new List<StateVector>();
for (DateTime epoch = timeWindow.StartDate; epoch <= timeWindow.EndDate; epoch += stepSize)
{
var position = GetEquatorialCoordinates(epoch).ToCartesian();
svs.Add(new StateVector(position, Vector3.Zero, new Barycenter(0), epoch, Frame.ICRF));
}

PropagationOutput = starsOutputDirectory.CreateSubdirectory(Name);
var path = new FileInfo(Path.Combine(PropagationOutput.FullName, $"star_{NaifId}.spk"));
if (API.Instance.WriteEphemeris(path, this, svs))
{
API.Instance.LoadKernels(path);
}
});
}

if (API.Instance.WriteEphemeris(path, this, svs))
/// <summary>
/// Reset propagation elements
/// </summary>
private void ResetPropagation()
{
if (IsPropagated)
{
API.Instance.UnloadKernels(PropagationOutput);
PropagationOutput.Delete(true);
PropagationOutput = null;
}
}

private void ReleaseUnmanagedResources()
{
if (IsPropagated)
{
API.Instance.LoadKernels(path);
API.Instance.UnloadKernels(PropagationOutput);
}
}

public void Dispose()
{
ReleaseUnmanagedResources();
GC.SuppressFinalize(this);
}

~Star()
{
ReleaseUnmanagedResources();
}
}
Loading

0 comments on commit 2832e13

Please sign in to comment.