From 7736a988348155c45295b163e1b43674468752ae Mon Sep 17 00:00:00 2001 From: Paul Hebble Date: Wed, 9 Nov 2022 17:48:39 -0600 Subject: [PATCH] Add orbit extensions to public API (fixes #32) --- GameData/Astrogator/Astrogator-Changelog.cfg | 5 + Source/PhysicsTools.cs | 102 +++++++++++-------- 2 files changed, 65 insertions(+), 42 deletions(-) diff --git a/GameData/Astrogator/Astrogator-Changelog.cfg b/GameData/Astrogator/Astrogator-Changelog.cfg index c820e75..8c1d5b4 100644 --- a/GameData/Astrogator/Astrogator-Changelog.cfg +++ b/GameData/Astrogator/Astrogator-Changelog.cfg @@ -10,6 +10,11 @@ KERBALCHANGELOG version = 1.0.0 versionName = Quite a show versionKSP = 1.12 + CHANGE + { + change = Add orbit extensions to public API + type = Add + } } VERSION { diff --git a/Source/PhysicsTools.cs b/Source/PhysicsTools.cs index c2fe9f4..ff17db8 100644 --- a/Source/PhysicsTools.cs +++ b/Source/PhysicsTools.cs @@ -441,10 +441,8 @@ public static double BurnToEscape(CelestialBody parent, Orbit fromOrbit, double /// Speed change in m/s needed /// public static double BurnToEscape(CelestialBody parent, double periapsis, double speedAtInfinity) - { - double preBurnSpeed = SpeedAtPeriapsis(parent, periapsis, periapsis); - return SpeedToExitSOI(parent, periapsis, speedAtInfinity) - preBurnSpeed; - } + => SpeedToExitSOI(parent, periapsis, speedAtInfinity) + - SpeedAtPeriapsis(parent, periapsis, periapsis); /// /// Calculate the absolute time when a satellite will be a given angle away from @@ -647,7 +645,7 @@ public static Vector3d DeltaVToMatchPlanes(Orbit currentOrbit, Orbit target, dou internal static class MuUtils { // acosh(x) = log(x + sqrt(x^2 - 1)) - internal static double Acosh(double x) + public static double Acosh(double x) => Math.Log(x + Math.Sqrt(x * x - 1)); } @@ -665,7 +663,11 @@ public static Vector3d SwapYZ(this Vector3d v) => new Vector3d(v.x, v.z, v.y); } - internal static class MuMech_OrbitExtensions + /// + /// Extensions to calculate the AN and DN. + /// Borrowed from KAC's borrowing from r4m0n's MJ plugin. + /// + public static class MuMech_OrbitExtensions { /// @@ -708,19 +710,53 @@ public static Vector3d SwappedRelativePositionAtUT(this Orbit o, double UT) // These "Swapped" functions translate preexisting Orbit class functions into world space. // The Orbit class uses a coordinate system in which the Y and Z coordinates are swapped. - // Normalized vector perpendicular to the orbital plane - // convention: as you look down along the orbit normal, the satellite revolves counterclockwise - internal static Vector3d SwappedOrbitNormal(this Orbit o) + /// + /// Normalized vector perpendicular to the orbital plane + /// convention: as you look down along the orbit normal, the satellite revolves counterclockwise + /// + /// An orbit + /// Normal vector of the orbit in world space + public static Vector3d SwappedOrbitNormal(this Orbit o) => -o.GetOrbitNormal().SwapYZ().normalized; + /// + /// Returns the next time at which a will cross its ascending node with b. + /// For elliptical orbits this is a time between UT and UT + a.period. + /// For hyperbolic orbits this can be any time, including a time in the past if + /// the ascending node is in the past. + /// NOTE: this function will throw an ArgumentException if a is a hyperbolic orbit and the "ascending node" + /// occurs at a true anomaly that a does not actually ever attain + /// + /// Our orbit + /// The other orbit + /// Minimum time of AN + /// Time of AN + public static double TimeOfAscendingNode(this Orbit a, Orbit b, double UT) + => a.TimeOfTrueAnomaly(a.AscendingNodeTrueAnomaly(b), UT); + + /// + /// Returns the next time at which a will cross its descending node with b. + /// For elliptical orbits this is a time between UT and UT + a.period. + /// For hyperbolic orbits this can be any time, including a time in the past if + /// the descending node is in the past. + /// NOTE: this function will throw an ArgumentException if a is a hyperbolic orbit and the "descending node" + /// occurs at a true anomaly that a does not actually ever attain + /// + /// Our orbit + /// The other orbit + /// Minimum time of DN + /// Time of DN + public static double TimeOfDescendingNode(this Orbit a, Orbit b, double UT) + => a.TimeOfTrueAnomaly(a.DescendingNodeTrueAnomaly(b), UT); + // Mean motion is rate of increase of the mean anomaly - internal static double MeanMotion(this Orbit o) + private static double MeanMotion(this Orbit o) => Math.Sqrt(o.referenceBody.gravParameter / Math.Abs(Math.Pow(o.semiMajorAxis, 3))); // The mean anomaly of the orbit. // For elliptical orbits, the value return is always between 0 and Tau // For hyperbolic orbits, the value can be any number. - internal static double MeanAnomalyAtUT(this Orbit o, double UT) + private static double MeanAnomalyAtUT(this Orbit o, double UT) => o.eccentricity < 1 ? clamp(o.meanAnomalyAtEpoch + o.MeanMotion() * (UT - o.epoch)) : o.meanAnomalyAtEpoch + o.MeanMotion() * (UT - o.epoch); @@ -729,7 +765,7 @@ internal static double MeanAnomalyAtUT(this Orbit o, double UT) // For elliptical orbits, this will be a time between UT and UT + o.period // For hyperbolic orbits, this can be any time, including a time in the past, if // the given mean anomaly occurred in the past - internal static double UTAtMeanAnomaly(this Orbit o, double meanAnomaly, double UT) + private static double UTAtMeanAnomaly(this Orbit o, double meanAnomaly, double UT) { double currentMeanAnomaly = o.MeanAnomalyAtUT(UT); double meanDifference = meanAnomaly - currentMeanAnomaly; @@ -740,18 +776,18 @@ internal static double UTAtMeanAnomaly(this Orbit o, double meanAnomaly, double // True anomaly (in a's orbit) at which a crosses its ascending node // with b's orbit. - internal static double AscendingNodeTrueAnomaly(this Orbit a, Orbit b) + private static double AscendingNodeTrueAnomaly(this Orbit a, Orbit b) => a.TrueAnomalyFromVector(Vector3d.Cross(b.SwappedOrbitNormal(), a.SwappedOrbitNormal())); // True anomaly (in a's orbit) at which a crosses its descending node // with b's orbit. - internal static double DescendingNodeTrueAnomaly(this Orbit a, Orbit b) + private static double DescendingNodeTrueAnomaly(this Orbit a, Orbit b) => a.TrueAnomalyFromVector(Vector3d.Cross(a.SwappedOrbitNormal(), b.SwappedOrbitNormal())); // Converts a direction, specified by a Vector3d, into a true anomaly. // The vector is projected into the orbital plane and then the true anomaly is // computed as the angle this vector makes with the vector pointing to the periapsis. - internal static double TrueAnomalyFromVector(this Orbit o, Vector3d vec) + private static double TrueAnomalyFromVector(this Orbit o, Vector3d vec) => clamp(o.GetTrueAnomalyOfZupVector(vec)); // Originally by Zool, revised by The_Duck @@ -760,7 +796,7 @@ internal static double TrueAnomalyFromVector(this Orbit o, Vector3d vec) // For hyperbolic orbits the returned value can be any number. // NOTE: For a hyperbolic orbit, if a true anomaly is requested that does not exist (a true anomaly // past the true anomaly of the asymptote) then an ArgumentException is thrown - internal static double GetEccentricAnomalyAtTrueAnomaly(this Orbit o, double trueAnomaly) + private static double GetEccentricAnomalyAtTrueAnomaly(this Orbit o, double trueAnomaly) { double e = o.eccentricity; double cosTA = Math.Cos(trueAnomaly); @@ -789,43 +825,25 @@ internal static double GetEccentricAnomalyAtTrueAnomaly(this Orbit o, double tru } } - ///Originally by Zool, revised by The_Duck - ///Converts an eccentric anomaly into a mean anomaly. - ///For an elliptical orbit, the returned value is between 0 and Tau - ///For a hyperbolic orbit, the returned value is any number - internal static double GetMeanAnomalyAtEccentricAnomaly(this Orbit o, double E) + // Originally by Zool, revised by The_Duck + // Converts an eccentric anomaly into a mean anomaly. + // For an elliptical orbit, the returned value is between 0 and Tau + // For a hyperbolic orbit, the returned value is any number + private static double GetMeanAnomalyAtEccentricAnomaly(this Orbit o, double E) => o.eccentricity < 1 // Elliptical orbits ? clamp(E - (o.eccentricity * Math.Sin(E))) // Hyperbolic orbits : (o.eccentricity * Math.Sinh(E)) - E; - ///NOTE: this function can throw an ArgumentException, if o is a hyperbolic orbit with an eccentricity - ///large enough that it never attains the given true anomaly - internal static double TimeOfTrueAnomaly(this Orbit o, double trueAnomaly, double UT) + // NOTE: this function can throw an ArgumentException, if o is a hyperbolic orbit with an eccentricity + // large enough that it never attains the given true anomaly + private static double TimeOfTrueAnomaly(this Orbit o, double trueAnomaly, double UT) => o.UTAtMeanAnomaly( o.GetMeanAnomalyAtEccentricAnomaly( o.GetEccentricAnomalyAtTrueAnomaly(trueAnomaly)), UT); - ///Returns the next time at which a will cross its ascending node with b. - ///For elliptical orbits this is a time between UT and UT + a.period. - ///For hyperbolic orbits this can be any time, including a time in the past if - ///the ascending node is in the past. - ///NOTE: this function will throw an ArgumentException if a is a hyperbolic orbit and the "ascending node" - ///occurs at a true anomaly that a does not actually ever attain - public static double TimeOfAscendingNode(this Orbit a, Orbit b, double UT) - => a.TimeOfTrueAnomaly(a.AscendingNodeTrueAnomaly(b), UT); - - ///Returns the next time at which a will cross its descending node with b. - ///For elliptical orbits this is a time between UT and UT + a.period. - ///For hyperbolic orbits this can be any time, including a time in the past if - ///the descending node is in the past. - ///NOTE: this function will throw an ArgumentException if a is a hyperbolic orbit and the "descending node" - ///occurs at a true anomaly that a does not actually ever attain - public static double TimeOfDescendingNode(this Orbit a, Orbit b, double UT) - => a.TimeOfTrueAnomaly(a.DescendingNodeTrueAnomaly(b), UT); - // End code copied from Kerbal Alarm Clock }