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

Commit

Permalink
Add TransformFrame feature (#15)
Browse files Browse the repository at this point in the history
* Add TransformFrame feature
  • Loading branch information
sylvain-guillet authored May 30, 2023
1 parent 7a64757 commit 1624338
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 43 deletions.
94 changes: 57 additions & 37 deletions IO.SDK.Net.Tests/APITest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ public void ExecuteLaunchScenario()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));

//Convert UTC time to TDB
double start = api.ConvertUTCToTDB(667915130.814600);
double end = api.ConvertUTCToTDB(668174330.814560);
Expand All @@ -56,10 +56,10 @@ public void ExecuteLaunchScenario()

//Create launch object
Launch launch = new Launch(launchSite, recoverySite, true, 1, parkingOrbit, new Window(start, end));

//Find launch windows
api.FindLaunchWindows(ref launch);

//Read results
Assert.Equal(2, launch.Windows.Count(x => x.Start != 0 && x.End != 0));
Assert.Equal(new Window(668084955.97088385, 668084955.97088385), launch.Windows[0]);
Expand All @@ -75,10 +75,10 @@ public void ExecuteReachOrbitScenario()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));

//Define some keys datetime
double start = api.ConvertUTCToTDB(667915269.18539762);
double startPropagator = api.ConvertUTCToTDB(668085555.829810);
Expand Down Expand Up @@ -152,7 +152,7 @@ public void ExecuteReachOrbitScenario()
};

api.ExecuteScenario(ref scenario);

//Read maneuver results
Assert.Equal("2021-03-04 00:32:42.854653 (TDB)",
api.TDBToString(scenario.Spacecraft.OrbitalPlaneChangingManeuvers[0].ManeuverWindow.Start));
Expand Down Expand Up @@ -234,10 +234,10 @@ public void TDBToString()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));

var res = api.TDBToString(0.0);
Assert.Equal("2000-01-01 12:00:00.000000 (TDB)", res);

Expand All @@ -250,10 +250,10 @@ public void UTCToString()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));

var res = api.UTCToString(0.0);
Assert.Equal("2000-01-01 12:00:00.000000 (UTC)", res);
}
Expand All @@ -263,10 +263,10 @@ public void FindWindowsOnDistanceConstraintProxy()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));

//Find time windows when the moon will be 400000 km away from the Earth
var res = api.FindWindowsOnDistanceConstraint(new Window(220881665.18391809, 228657665.18565452),
PlanetsAndMoons.EARTH.NaifId, PlanetsAndMoons.MOON.NaifId, RelationnalOperator.Greater,
Expand All @@ -283,10 +283,10 @@ public void FindWindowsOnOccultationConstraint()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));

//Find time windows when the Sun will be occulted by the moon
var res = api.FindWindowsOnOccultationConstraint(new Window(61473664.183390938, 61646464.183445148),
PlanetsAndMoons.EARTH.NaifId, Stars.Sun.NaifId,
Expand All @@ -303,10 +303,10 @@ public void FindWindowsOnCoordinateConstraint()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));

//Find time windows when the moon will be above the horizon relative to Deep Space Station 13
var res = api.FindWindowsOnCoordinateConstraint(new Window(730036800.0, 730123200), 399013,
PlanetsAndMoons.MOON.NaifId, GroundStations.DSS_13.Frame,
Expand All @@ -324,10 +324,10 @@ public void FindWindowsOnIlluminationConstraint()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));

//Find time windows when the geodetic point is illuminated by the sun (Official twilight 0.8° bellow horizon)
var res = api.FindWindowsOnIlluminationConstraint(new Window(674524800, 674611200), Stars.Sun.NaifId,
PlanetsAndMoons.EARTH.NaifId, PlanetsAndMoons.EARTH.Frame,
Expand All @@ -337,8 +337,8 @@ public void FindWindowsOnIlluminationConstraint()
TimeSpan.FromHours(4.5));
Assert.Equal(2, res.Length);
Assert.Equal("2021-05-17 12:00:00.000000 (TDB)", api.TDBToString(res[0].Start));
Assert.Equal("2021-05-17 19:35:42.885022 (TDB)", api.TDBToString(res[0].End));
Assert.Equal("2021-05-18 04:18:50.060742 (TDB)", api.TDBToString(res[1].Start));
Assert.Equal("2021-05-17 19:35:24.908834 (TDB)", api.TDBToString(res[0].End));
Assert.Equal("2021-05-18 04:18:32.443750 (TDB)", api.TDBToString(res[1].Start));
Assert.Equal("2021-05-18 12:00:00.000000 (TDB)", api.TDBToString(res[1].End));
}

Expand All @@ -347,7 +347,7 @@ public void FindWindowsInFieldOfViewConstraint()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));

Expand Down Expand Up @@ -375,21 +375,21 @@ public void FindWindowsInFieldOfViewConstraint()

//Execute scenario
api.ExecuteScenario(ref scenario);

//Load generated kernels
api.LoadKernels(new DirectoryInfo("Data/User/Spacecrafts/DRAGONFLY"));

//Find windows when the earth is in field of view of camera 600
var res = api.FindWindowsInFieldOfViewConstraint(new Window(676555200, 676561647), -178, 600,
PlanetsAndMoons.EARTH.NaifId,
PlanetsAndMoons.EARTH.Frame, ShapeType.Ellipsoid,
Aberration.LT, TimeSpan.FromHours(1.0));

//Read results
Assert.Equal(2, res.Length);
Assert.Equal("2021-06-10 00:00:00.000000 (TDB)", api.TDBToString(res[0].Start));
Assert.Equal("2021-06-10 00:30:12.445632 (TDB)", api.TDBToString(res[0].End));
Assert.Equal("2021-06-10 01:02:53.829736 (TDB)", api.TDBToString(res[1].Start));
Assert.Equal("2021-06-10 00:30:12.445511 (TDB)", api.TDBToString(res[0].End));
Assert.Equal("2021-06-10 01:02:53.829783 (TDB)", api.TDBToString(res[1].Start));
Assert.Equal("2021-06-10 01:47:27.000000 (TDB)", api.TDBToString(res[1].End));
}

Expand All @@ -398,10 +398,10 @@ public void ReadEphemeris()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));

Window searchWindow = new Window(0.0, 100.0);
var res = api.ReadEphemeris(searchWindow, PlanetsAndMoons.EARTH.NaifId, PlanetsAndMoons.MOON.NaifId,
InertialFrame.ICRF.GetDescription(), Aberration.LT, TimeSpan.FromSeconds(10.0));
Expand All @@ -423,7 +423,7 @@ public void ReadOrientation()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));
// Window utcSearchWindow = new Window(662777930.816060, 662777990.816060);
Expand Down Expand Up @@ -459,10 +459,10 @@ public void ReadOrientation()

//Execute scenario
api.ExecuteScenario(ref scenario);

//Load generated kernels
api.LoadKernels(new DirectoryInfo("Data/User/Spacecrafts/DRAGONFLY2"));

//Read spacecraft orientation
var res = api.ReadOrientation(tdbSearchWindow, -1782, Math.Pow(2, 16), InertialFrame.ICRF.GetDescription(),
TimeSpan.FromSeconds(10.0));
Expand All @@ -484,7 +484,7 @@ void ConvertTDBToUTC()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));
Assert.Equal(-64.18392726322381, api.ConvertTDBToUTC(0.0));
Expand All @@ -495,7 +495,7 @@ void ConverUTCToTDB()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));
Assert.Equal(64.18392728466942, api.ConvertUTCToTDB(0.0));
Expand All @@ -506,7 +506,7 @@ void WriteEphemeris()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));
const int size = 10;
Expand Down Expand Up @@ -554,10 +554,10 @@ void GetCelestialBodyInformation()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));

//Read celestial body information from spice kernels
var res = api.GetCelestialBodyInfo(PlanetsAndMoons.EARTH.NaifId);
Assert.Equal(PlanetsAndMoons.EARTH.NaifId, res.Id);
Expand All @@ -571,4 +571,24 @@ void GetCelestialBodyInformation()
Assert.Equal(6378.1365999999998, res.Radii.Y);
Assert.Equal(6356.7519000000002, res.Radii.Z);
}

[Fact]
void TransformFrame()
{
//Initialize API
API api = new API();

//Load solar system kernels
api.LoadKernels(new DirectoryInfo(SolarSystemKernelPath));

//Get the quaternion to transform
var res = api.TransformFrame(InertialFrame.ICRF.GetDescription(), PlanetsAndMoons.EARTH.Frame, 0.0);
Assert.Equal(0.76713121189662548, res.Rotation.W);
Assert.Equal(-1.8618846012434252e-05, res.Rotation.X);
Assert.Equal(8.468919252183845e-07, res.Rotation.Y);
Assert.Equal(0.64149022080358797, res.Rotation.Z);
Assert.Equal(-1.9637714059853662e-09, res.AngularVelocity.X);
Assert.Equal(-2.0389340573814659e-09, res.AngularVelocity.Y);
Assert.Equal(7.2921150642488516e-05, res.AngularVelocity.Z);
}
}
30 changes: 26 additions & 4 deletions IO.SDK.Net/API.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,14 @@ private static extern void ReadEphemerisProxy(Window searchWindow, int observerI

[DllImport(@"IO.SDK", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern bool
WriteEphemerisProxy(string filePath, int objectId, StateVector[] stateVectors, int size);
WriteEphemerisProxy(string filePath, int objectId, StateVector[] stateVectors, uint size);

[DllImport(@"IO.SDK", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern CelestialBody GetCelestialBodyInfoProxy(int celestialBodyId);

[DllImport(@"IO.SDK", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern FrameTransformation TransformFrameProxy(string fromFrame, string toFrame, double epoch);

/// <summary>
/// Instantiate API
/// </summary>
Expand Down Expand Up @@ -181,7 +184,7 @@ public void FindLaunchWindows(ref Launch launchDto)
/// <param name="searchWindow"></param>
/// <param name="observerId"></param>
/// <param name="targetId"></param>
/// <param name="constraint"></param>
/// <param name="relationnalOperator"></param>
/// <param name="value"></param>
/// <param name="aberration"></param>
/// <param name="stepSize"></param>
Expand Down Expand Up @@ -223,6 +226,8 @@ public Window[] FindWindowsOnOccultationConstraint(Window searchWindow, int obse
ShapeType frontShape,
OccultationType occultationType, Aberration aberration, TimeSpan stepSize)
{
if (targetFrame == null) throw new ArgumentNullException(nameof(targetFrame));
if (frontFrame == null) throw new ArgumentNullException(nameof(frontFrame));
Window[] windows = new Window[1000];
for (int i = 0; i < 1000; i++)
{
Expand Down Expand Up @@ -293,6 +298,9 @@ public Window[] FindWindowsOnIlluminationConstraint(Window searchWindow, int obs
RelationnalOperator relationalOperator, double value, double adjustValue,
Aberration aberration, TimeSpan stepSize, string illuminationSource = "SUN", string method = "Ellipsoid")
{
if (fixedFrame == null) throw new ArgumentNullException(nameof(fixedFrame));
if (illuminationSource == null) throw new ArgumentNullException(nameof(illuminationSource));
if (method == null) throw new ArgumentNullException(nameof(method));
Window[] windows = new Window[1000];
for (int i = 0; i < 1000; i++)
{
Expand Down Expand Up @@ -323,6 +331,7 @@ public Window[] FindWindowsInFieldOfViewConstraint(Window searchWindow, int obse
int instrumentId, int targetId, string targetFrame, ShapeType targetShape, Aberration aberration,
TimeSpan stepSize)
{
if (targetFrame == null) throw new ArgumentNullException(nameof(targetFrame));
Window[] windows = new Window[1000];
for (int i = 0; i < 1000; i++)
{
Expand All @@ -348,6 +357,7 @@ public Window[] FindWindowsInFieldOfViewConstraint(Window searchWindow, int obse
public StateVector[] ReadEphemeris(Window searchWindow, int observerId, int targetId, string frame,
Aberration aberration, TimeSpan stepSize)
{
if (frame == null) throw new ArgumentNullException(nameof(frame));
StateVector[] stateVectors = new StateVector[5000];
ReadEphemerisProxy(searchWindow, observerId, targetId, frame, aberration.GetDescription(),
stepSize.TotalSeconds,
Expand All @@ -361,12 +371,13 @@ public StateVector[] ReadEphemeris(Window searchWindow, int observerId, int targ
/// <param name="searchWindow"></param>
/// <param name="spacecraftId"></param>
/// <param name="tolerance"></param>
/// <param name="refrenceFrame"></param>
/// <param name="referenceFrame"></param>
/// <param name="stepSize"></param>
/// <returns></returns>
public StateOrientation[] ReadOrientation(Window searchWindow, int spacecraftId, double tolerance,
string referenceFrame, TimeSpan stepSize)
{
if (referenceFrame == null) throw new ArgumentNullException(nameof(referenceFrame));
StateOrientation[] stateOrientations = new StateOrientation[10000];
ReadOrientationProxy(searchWindow, spacecraftId, tolerance, referenceFrame, stepSize.TotalSeconds,
stateOrientations);
Expand Down Expand Up @@ -401,8 +412,12 @@ public double ConvertTDBToUTC(double tdb)
/// <param name="stateVectors"></param>
/// <param name="size"></param>
/// <returns></returns>
public bool WriteEphemeris(FileInfo filePath, int objectId, StateVector[] stateVectors, int size)
public bool WriteEphemeris(FileInfo filePath, int objectId, StateVector[] stateVectors, uint size)
{
if (filePath == null) throw new ArgumentNullException(nameof(filePath));
if (stateVectors == null) throw new ArgumentNullException(nameof(stateVectors));
if (stateVectors.Length == 0)
throw new ArgumentException("Value cannot be an empty collection.", nameof(stateVectors));
return WriteEphemerisProxy(filePath.FullName, objectId, stateVectors, size);
}

Expand All @@ -415,4 +430,11 @@ public CelestialBody GetCelestialBodyInfo(int celestialBodyId)
{
return GetCelestialBodyInfoProxy(celestialBodyId);
}

public FrameTransformation TransformFrame(string fromFrame, string toFrame, double epoch)
{
if (fromFrame == null) throw new ArgumentNullException(nameof(fromFrame));
if (toFrame == null) throw new ArgumentNullException(nameof(toFrame));
return TransformFrameProxy(fromFrame, toFrame, epoch);
}
}
10 changes: 10 additions & 0 deletions IO.SDK.Net/DTO/FrameTransformation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Runtime.InteropServices;

namespace IO.SDK.Net.DTO;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct FrameTransformation
{
public Quaternion Rotation;
public Vector3D AngularVelocity;
}
2 changes: 1 addition & 1 deletion IO.SDK.Net/IO.SDK.Net.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<id>IO.SDK.Net</id>
<authors>Sylvain Guillet</authors>
<copyright>Sylvain Guillet</copyright>
<version>0.7.0-alpha</version>
<version>0.8.0-alpha</version>
<title>.Net proxy to IO SDK</title>
<icon>images\dragonfly-dark-trans.png</icon>
<readme>docs\README.md</readme>
Expand Down
Loading

0 comments on commit 1624338

Please sign in to comment.