From 592650341836cadda073dd7ba621de6ec023759c Mon Sep 17 00:00:00 2001 From: Lamont Granquist Date: Sun, 29 May 2016 12:35:09 -0700 Subject: [PATCH 1/7] add orbit constructor and velocityat/positionat adds a constructor for Orbit (OrbitInfo internally) structures so that users can construct their own orbit objects. this lets a function that can build a hohmann transfer node to the mun's orbit also be reused to transfer to a keosynchronous orbit. because the orbit structure has no associated orbitable body it is not possible to use positionat(orbitable) and velocityat(orbitable) functions, so therefore added positionat and velocityat functions to the orbit object (APIs that do not take into account maneuver nodes and are documented as such). docs updates and kerboscript tests included. --- doc/source/commands/prediction.rst | 2 +- doc/source/structures/orbits/orbit.rst | 54 +++++++++++++++- kerboscript_tests/structures/orbit1.ks | 90 ++++++++++++++++++++++++++ src/kOS/Function/Suffixed.cs | 35 +++++++--- src/kOS/Suffixed/OrbitInfo.cs | 31 ++++++++- src/kOS/Suffixed/Vector.cs | 7 +- 6 files changed, 202 insertions(+), 17 deletions(-) create mode 100644 kerboscript_tests/structures/orbit1.ks diff --git a/doc/source/commands/prediction.rst b/doc/source/commands/prediction.rst index 217adf60a..1912fd9ab 100644 --- a/doc/source/commands/prediction.rst +++ b/doc/source/commands/prediction.rst @@ -55,7 +55,7 @@ These return predicted information about the future position and velocity of an :type orbitable: :struct:`Orbitable` :param time: Time of prediction :type time: :struct:`TimeSpan` - :return: An :ref:`ObitalVelocity ` structure. + :return: An :ref:`OrbitalVelocity ` structure. Returns a prediction of what the :ref:`Orbitable's ` velocity will be at some :ref:`universal Timestamp `. If the :struct:`Orbitable` is a :struct:`Vessel`, and the :struct:`Vessel` has planned :struct:`maneuver nodes `, the prediction assumes they will be executed exactly as planned. diff --git a/doc/source/structures/orbits/orbit.rst b/doc/source/structures/orbits/orbit.rst index 061793f00..e20f1dbcf 100644 --- a/doc/source/structures/orbits/orbit.rst +++ b/doc/source/structures/orbits/orbit.rst @@ -17,6 +17,24 @@ Whenever you get the :struct:`Orbit` of a :struct:`Vessel`, be aware that its ju Some of the parameters listed here come directly from KSP's API and there is a bit of inconsistency with whether it uses radians or degrees for angles. As much as possible we have tried to present everything in kOS as degrees for consistency, but some of these may have slipped through. If you see any of these being reported in radians, please make a bug report. + +Creation +-------- + +.. function:: ORBIT(x, v, body, t) + + :parameter x: (vector) position at time t + :parameter v: (vetor) velocity at time t + :parameter body: (String) central body of orbit + :parameter t: (scalar) universal time + :return: :struct:`Orbit` + + This creates a new orbit around a body given the position and velocity at a given time:: + + SET o TO ORBIT( x, v, "kerbin", TIME:SECONDS ). + + Here, a new :struct:`Orbit` called ``o`` is created. + Structure --------- @@ -78,9 +96,15 @@ Structure * - :attr:`POSITION` - :struct:`Vector` - The current position + * - :attr:`POSITIONAT(time)` + - :struct:`Vector` + - The position at the given time * - :attr:`VELOCITY` - :struct:`Vector` - The current velocity + * - :attr:`VELOCITYAT(time)` + - :struct:`Vector` + - The velocity at the given time * - :attr:`NEXTPATCH` - :struct:`Orbit` - Next :struct:`Orbit` @@ -214,16 +238,42 @@ Structure :type: :struct:`Vector` :access: Get only + :return: A position :struct:`Vector` expressed as the coordinates in the :ref:`ship-center-raw-rotation ` frame - The current position of whatever the object is that is in this orbit. + The current position of whatever the object is that is in this orbit. This vector is relative to the :ref:`ship-center-raw-rotation ` frame. It + may be more useful to subtract the orbit:body:position before using it to convert to a body-centric position. -.. attribute:: Orbit:VELOCITY +.. attribute:: Orbit:POSITIONAT :type: :struct:`Vector` + :param time: Time of prediction + :type time: :struct:`TimeSpan` :access: Get only + :return: A position :struct:`Vector` expressed as the coordinates in the :ref:`ship-center-raw-rotation ` frame + + Returns a prediction of where the object will be at some :ref:`universal Timestamp `. This vector is relative to the + :ref:`ship-center-raw-rotation ` frame (at the current time). It may be more useful to subtract the orbit:body:position before + using it to conver to a body-centric position. This prediction does not take into account future maneuver nodes. + +.. attribute:: Orbit:VELOCITY + + :type: :struct:`OrbitalVelocity` + :access: Get only + :return: An :ref:`OrbitalVelocity ` structure. The current velocity of whatever the object is that is in this orbit. +.. attribute:: Orbit:VELOCITYAT + + :type: :struct:`OrbitalVelocity` + :param time: Time of prediction + :type time: :struct:`TimeSpan` + :access: Get only + :return: An :ref:`OrbitalVelocity ` structure. + + Returns a prediction of what the velocity of the object will be at some :ref:`universal Timestamp `. This prediction does not take into account + future maneuver nodes. + .. attribute:: Orbit:NEXTPATCH :type: :struct:`Orbit` diff --git a/kerboscript_tests/structures/orbit1.ks b/kerboscript_tests/structures/orbit1.ks new file mode 100644 index 000000000..d3c19ee1b --- /dev/null +++ b/kerboscript_tests/structures/orbit1.ks @@ -0,0 +1,90 @@ +// useful to debug: +// +// set o to orbit(x, v, body, time:seconds). +// o:positionat(time:seconds + dt). +// o:velocityat(time:seconds + dt). +// +// creates a keosynchronous orbit of an object directly above the equatorial coordinates of +// KSC and checks the position at the current time and 1/4 way around the orbit. + +// x0, v0 are what we use to build the orbit +set x0 to latlng(0, -75.08333333333333333332):position - ship:body:position. +set x0:mag to 3463334.06. +set v0 to vcrs(kerbin:angularvel, x0). +set v0:mag to sqrt(kerbin:mu / x0:mag). + +set keosynch to orbit(x0, v0, "kerbin", TIME:SECONDS). + +print "sma : " + keosynch:semimajoraxis. +print "ecc : " + keosynch:eccentricity. +print "lan : " + keosynch:lan. +print "arg : " + keosynch:argumentofperiapsis. +print "period : " + keosynch:period. + +set sidereal_day to 5*3600 + 59*60 + 9.4. + +// x1, v1 should recover the same, while x2, v2 should be 1/4 around the orbit +set x1 to keosynch:positionat(time:seconds) - ship:body:position. +set v1 to keosynch:velocityat(time:seconds):orbit. +set x2 to keosynch:positionat(time:seconds + sidereal_day/4) - ship:body:position. +set v2 to keosynch:velocityat(time:seconds + sidereal_day/4):orbit. + +print "x1 : " + x1:mag. +print "v1 : " + v1:mag. +print "x2 : " + x2:mag. +print "v2 : " + v2:mag. + +// some handy vectors for debugging in case something goes wrong. +set xvec1 to vecdraw(ship:body:position, x1, rgb(1,0,0), "x1", 1.0, true, 0.2). +set vvec1 to vecdraw(ship:body:position + x1, 1000 * v1, rgb(1,0,0), "v1", 1.0, true, 0.2). +set xvec2 to vecdraw(ship:body:position, x2, rgb(0,1,0), "x2", 1.0, true, 0.2). +set vvec2 to vecdraw(ship:body:position + x2, 1000 * v2, rgb(0,1,0), "v2", 1.0, true, 0.2). + +// assertions + +if abs(keosynch:period - sidereal_day) > 1 + exit. + +if abs(keosynch:eccentricity) > 0.000001 + exit. + +if abs(keosynch:semimajoraxis - 3463334.06) > 0.1 + exit. + +if abs(x0:mag - 3463334.06) > 0.1 + exit. +if abs(x1:mag - 3463334.06) > 0.1 + exit. +if abs(x2:mag - 3463334.06) > 0.1 + exit. + +if abs(v0:mag - 1009.80) > 0.1 + exit. +if abs(v1:mag - 1009.80) > 0.1 + exit. +if abs(v2:mag - 1009.80) > 0.1 + exit. + +if (x1 - x0):mag > 1 + exit. + +if (v1 - v0):mag > 1 + exit. + +// x2 should point in the v1 direction +if abs(3463334.06 - vdot(x2, v1:normalized)) > 0.1 + exit. + +// v2 should point in the -x1 direction +if abs(1009.80 - vdot(v2, -x1:normalized)) > 0.1 + exit. + +// all vectors should be normal to the angular vel of kerbin's rotation +if vdot(x1:normalized, kerbin:angularvel:normalized) > 0.001 + exit. +if vdot(v1:normalized, kerbin:angularvel:normalized) > 0.001 + exit. +if vdot(x2:normalized, kerbin:angularvel:normalized) > 0.001 + exit. +if vdot(v2:normalized, kerbin:angularvel:normalized) > 0.001 + exit. diff --git a/src/kOS/Function/Suffixed.cs b/src/kOS/Function/Suffixed.cs index 84dd355fe..87e8ba7de 100644 --- a/src/kOS/Function/Suffixed.cs +++ b/src/kOS/Function/Suffixed.cs @@ -166,6 +166,21 @@ public override void Execute(SharedObjects shared) } } + [Function("orbit")] + public class FunctionOrbit : FunctionBase + { + public override void Execute(SharedObjects shared) + { + var when = GetTimeSpan(PopValueAssert(shared)); + string bodyName = PopValueAssert(shared).ToString(); + Vector vel = GetVector(PopValueAssert(shared)); + Vector pos = GetVector(PopValueAssert(shared)); + AssertArgBottomAndConsume(shared); + var result = new OrbitInfo(pos, vel, VesselUtils.GetBodyByName(bodyName), when.ToUnixStyleTime(), shared); + ReturnValue = result; + } + } + [Function("heading")] public class FunctionHeading : FunctionBase { @@ -356,7 +371,7 @@ public override void Execute(SharedObjects shared) AssertArgBottomAndConsume(shared); DoExecuteWork(shared, start, vec, rgba, str, scale, show, width); } - + public void DoExecuteWork(SharedObjects shared, Vector start, Vector vec, RgbaColor rgba, string str, double scale, bool show, double width) { var vRend = new VectorRenderer( shared.UpdateHandler, shared ) @@ -369,7 +384,7 @@ public void DoExecuteWork(SharedObjects shared, Vector start, Vector vec, RgbaCo }; vRend.SetLabel( str ); vRend.SetShow( show ); - + ReturnValue = vRend; } } @@ -383,7 +398,7 @@ public override void Execute(SharedObjects shared) VectorRenderer.ClearAll(shared.UpdateHandler); } } - + [Function("positionat")] public class FunctionPositionAt : FunctionBase { @@ -435,7 +450,7 @@ public override void Execute(SharedObjects shared) ReturnValue = new OrbitInfo( what.GetOrbitAtUT(when.ToUnixStyleTime()), shared ); } } - + [Function("career")] public class FunctionCareer : FunctionBase { @@ -445,7 +460,7 @@ public override void Execute(SharedObjects shared) ReturnValue = new Career(); } } - + [Function("constant")] public class FunctionConstant : FunctionBase { @@ -455,14 +470,14 @@ public override void Execute(SharedObjects shared) ReturnValue = new ConstantValue(); } } - + [Function("allwaypoints")] public class FunctionAllWaypoints : FunctionBase { public override void Execute(SharedObjects shared) { AssertArgBottomAndConsume(shared); // no args - + // ReSharper disable SuggestUseVarKeywordEvident ListValue returnList = new ListValue(); // ReSharper enable SuggestUseVarKeywordEvident @@ -485,7 +500,7 @@ public override void Execute(SharedObjects shared) ReturnValue = returnList; } } - + [Function("waypoint")] public class FunctionWaypoint : FunctionBase { @@ -502,7 +517,7 @@ public override void Execute(SharedObjects shared) // first time a contract with a waypoint is created). if (wpm == null) throw new KOSInvalidArgumentException("waypoint", "\""+pointName+"\"", "no waypoints exist"); - + string baseName; int index; bool hasGreek = WaypointValue.GreekToInteger(pointName, out index, out baseName); @@ -510,7 +525,7 @@ public override void Execute(SharedObjects shared) pointName = baseName; Waypoint point = wpm.Waypoints.FirstOrDefault( p => string.Equals(p.name, pointName,StringComparison.CurrentCultureIgnoreCase) && (!hasGreek || p.index == index)); - + // We can't communicate the concept of a lookup fail to the script in a way it can catch (can't do // nulls), so bomb out here: if (point ==null) diff --git a/src/kOS/Suffixed/OrbitInfo.cs b/src/kOS/Suffixed/OrbitInfo.cs index e4aacd316..2122bd56b 100644 --- a/src/kOS/Suffixed/OrbitInfo.cs +++ b/src/kOS/Suffixed/OrbitInfo.cs @@ -4,6 +4,7 @@ using kOS.Serialization; using kOS.Safe.Serialization; using kOS.Safe; +using UnityEngine; namespace kOS.Suffixed { @@ -13,7 +14,7 @@ public class OrbitInfo : Structure, IHasSharedObjects private Orbit orbit; public SharedObjects Shared { get; set; } private string name; - + public OrbitInfo() { InitializeSuffixes(); @@ -25,7 +26,7 @@ public OrbitInfo(Orbitable orb, SharedObjects sharedObj) : this() Shared = sharedObj; name = orb.GetName(); } - + public OrbitInfo( Orbit orb, SharedObjects sharedObj) : this() { Shared = sharedObj; @@ -33,6 +34,28 @@ public OrbitInfo( Orbit orb, SharedObjects sharedObj) : this() name = ""; } + public OrbitInfo(Vector pos, Vector vel, CelestialBody body, double when, SharedObjects sharedObj) : this() + { + Shared = sharedObj; + orbit = new Orbit(); + orbit.UpdateFromStateVectors(pos.SwapYZ(), vel.SwapYZ(), body, when); + // fix from MJ for perfectly circular orbits + if (double.IsNaN(orbit.argumentOfPeriapsis)) + { + Debug.Log("fixing NaN argumentOfPeriapsis for orbit from UpdateFromStateVectors"); + Vector3d vectorToAN = Quaternion.AngleAxis((float)orbit.LAN, Planetarium.up) * Planetarium.right; + double cosArgumentOfPeriapsis = Vector3d.Dot(vectorToAN, orbit.eccVec) / (vectorToAN.magnitude * orbit.eccVec.magnitude); + if(cosArgumentOfPeriapsis > 1) { + orbit.argumentOfPeriapsis = 0; + } else if (cosArgumentOfPeriapsis < -1) { + orbit.argumentOfPeriapsis = 180; + } else { + orbit.argumentOfPeriapsis = Math.Acos(cosArgumentOfPeriapsis); + } + } + name = ""; + } + private void InitializeSuffixes() { AddSuffix("NAME", new Suffix(() => name)); @@ -50,7 +73,9 @@ private void InitializeSuffixes() AddSuffix("MEANANOMALYATEPOCH", new Suffix(() => Utilities.Utils.DegreeFix(Utilities.Utils.RadiansToDegrees(orbit.meanAnomalyAtEpoch), 0.0))); AddSuffix("TRANSITION", new Suffix(() => orbit.patchEndTransition.ToString())); AddSuffix("POSITION", new Suffix(() => GetPositionAtUT( new TimeSpan(Planetarium.GetUniversalTime() ) ))); + AddSuffix("POSITIONAT", new OneArgsSuffix(ut => GetPositionAtUT( new TimeSpan(ut)))); AddSuffix("VELOCITY", new Suffix(() => GetVelocityAtUT( new TimeSpan(Planetarium.GetUniversalTime() ) ))); + AddSuffix("VELOCITYAT", new OneArgsSuffix(ut => GetVelocityAtUT( new TimeSpan(ut)))); AddSuffix("NEXTPATCH", new Suffix(GetNextPatch)); AddSuffix("HASNEXTPATCH", new Suffix(GetHasNextPatch)); AddSuffix("NEXTPATCHETA", new Suffix(GetNextPatchETA)); @@ -98,7 +123,7 @@ public OrbitableVelocity GetVelocityAtUT( TimeSpan timeStamp ) surfVel = new Vector( orbVel.X, orbVel.Y, orbVel.Z ); return new OrbitableVelocity( orbVel, surfVel ); } - + /// /// Return the next OrbitInfo after this one (i.e. transitional encounter) /// diff --git a/src/kOS/Suffixed/Vector.cs b/src/kOS/Suffixed/Vector.cs index fde22763b..5ede8016e 100644 --- a/src/kOS/Suffixed/Vector.cs +++ b/src/kOS/Suffixed/Vector.cs @@ -109,6 +109,11 @@ public Vector3 ToVector3() // Vector3 is the single-precision version of Vector3 return new Vector3((float)X, (float)Y, (float)Z); } + public Vector SwapYZ() // Used for KSP APIs that swap Y and Z + { + return new Vector(X, Z, Y); + } + public override string ToString() { return "V(" + X + ", " + Y + ", " + Z + ")"; @@ -233,4 +238,4 @@ public override void LoadDump(Dump dump) Z = Convert.ToDouble(dump[DumpZ]); } } -} \ No newline at end of file +} From 36880faef2da52069a39ed9928288f14867ca13f Mon Sep 17 00:00:00 2001 From: Lamont Granquist Date: Mon, 30 May 2016 10:26:38 -0700 Subject: [PATCH 2/7] fix body argument + NaN fix from MJ --- doc/source/structures/orbits/orbit.rst | 4 ++-- kerboscript_tests/structures/orbit1.ks | 28 ++++++++++++++------------ src/kOS/Function/Suffixed.cs | 6 ++++-- src/kOS/Suffixed/OrbitInfo.cs | 13 ++++++++---- src/kOS/Suffixed/Vector.cs | 5 ----- src/kOS/Utilities/Utils.cs | 17 +++++++++++++++- 6 files changed, 46 insertions(+), 27 deletions(-) diff --git a/doc/source/structures/orbits/orbit.rst b/doc/source/structures/orbits/orbit.rst index e20f1dbcf..9161155db 100644 --- a/doc/source/structures/orbits/orbit.rst +++ b/doc/source/structures/orbits/orbit.rst @@ -25,13 +25,13 @@ Creation :parameter x: (vector) position at time t :parameter v: (vetor) velocity at time t - :parameter body: (String) central body of orbit + :parameter body: (CelstialBody) central body of orbit :parameter t: (scalar) universal time :return: :struct:`Orbit` This creates a new orbit around a body given the position and velocity at a given time:: - SET o TO ORBIT( x, v, "kerbin", TIME:SECONDS ). + SET o TO ORBIT( x, v, kerbin, TIME:SECONDS ). Here, a new :struct:`Orbit` called ``o`` is created. diff --git a/kerboscript_tests/structures/orbit1.ks b/kerboscript_tests/structures/orbit1.ks index d3c19ee1b..7fa15bb01 100644 --- a/kerboscript_tests/structures/orbit1.ks +++ b/kerboscript_tests/structures/orbit1.ks @@ -7,13 +7,15 @@ // creates a keosynchronous orbit of an object directly above the equatorial coordinates of // KSC and checks the position at the current time and 1/4 way around the orbit. +set sidereal_day to 5*3600 + 59*60 + 9.4. + // x0, v0 are what we use to build the orbit set x0 to latlng(0, -75.08333333333333333332):position - ship:body:position. -set x0:mag to 3463334.06. +set x0:mag to (sqrt(kerbin:mu) * sidereal_day / (2 * constant:pi))^(2/3). // 3463331.36. set v0 to vcrs(kerbin:angularvel, x0). set v0:mag to sqrt(kerbin:mu / x0:mag). -set keosynch to orbit(x0, v0, "kerbin", TIME:SECONDS). +set keosynch to orbit(x0, v0, kerbin, time:seconds). print "sma : " + keosynch:semimajoraxis. print "ecc : " + keosynch:eccentricity. @@ -21,8 +23,6 @@ print "lan : " + keosynch:lan. print "arg : " + keosynch:argumentofperiapsis. print "period : " + keosynch:period. -set sidereal_day to 5*3600 + 59*60 + 9.4. - // x1, v1 should recover the same, while x2, v2 should be 1/4 around the orbit set x1 to keosynch:positionat(time:seconds) - ship:body:position. set v1 to keosynch:velocityat(time:seconds):orbit. @@ -35,6 +35,8 @@ print "x2 : " + x2:mag. print "v2 : " + v2:mag. // some handy vectors for debugging in case something goes wrong. +set xvec0 to vecdraw(ship:body:position, x0, rgb(0,0,1), "x0", 1.0, true, 0.2). +set vvec0 to vecdraw(ship:body:position + x0, 1000 * v0, rgb(0,0,1), "v0", 1.0, true, 0.2). set xvec1 to vecdraw(ship:body:position, x1, rgb(1,0,0), "x1", 1.0, true, 0.2). set vvec1 to vecdraw(ship:body:position + x1, 1000 * v1, rgb(1,0,0), "v1", 1.0, true, 0.2). set xvec2 to vecdraw(ship:body:position, x2, rgb(0,1,0), "x2", 1.0, true, 0.2). @@ -48,21 +50,21 @@ if abs(keosynch:period - sidereal_day) > 1 if abs(keosynch:eccentricity) > 0.000001 exit. -if abs(keosynch:semimajoraxis - 3463334.06) > 0.1 +if abs(keosynch:semimajoraxis - 3463331.36) > 0.1 exit. -if abs(x0:mag - 3463334.06) > 0.1 +if abs(x0:mag - 3463331.36) > 0.1 exit. -if abs(x1:mag - 3463334.06) > 0.1 +if abs(x1:mag - 3463331.36) > 0.1 exit. -if abs(x2:mag - 3463334.06) > 0.1 +if abs(x2:mag - 3463331.36) > 0.1 exit. -if abs(v0:mag - 1009.80) > 0.1 +if abs(v0:mag - 1009.81) > 0.1 exit. -if abs(v1:mag - 1009.80) > 0.1 +if abs(v1:mag - 1009.81) > 0.1 exit. -if abs(v2:mag - 1009.80) > 0.1 +if abs(v2:mag - 1009.81) > 0.1 exit. if (x1 - x0):mag > 1 @@ -72,11 +74,11 @@ if (v1 - v0):mag > 1 exit. // x2 should point in the v1 direction -if abs(3463334.06 - vdot(x2, v1:normalized)) > 0.1 +if abs(3463331.36 - vdot(x2, v1:normalized)) > 0.1 exit. // v2 should point in the -x1 direction -if abs(1009.80 - vdot(v2, -x1:normalized)) > 0.1 +if abs(1009.81 - vdot(v2, -x1:normalized)) > 0.1 exit. // all vectors should be normal to the angular vel of kerbin's rotation diff --git a/src/kOS/Function/Suffixed.cs b/src/kOS/Function/Suffixed.cs index 87e8ba7de..ae021264c 100644 --- a/src/kOS/Function/Suffixed.cs +++ b/src/kOS/Function/Suffixed.cs @@ -172,11 +172,13 @@ public class FunctionOrbit : FunctionBase public override void Execute(SharedObjects shared) { var when = GetTimeSpan(PopValueAssert(shared)); - string bodyName = PopValueAssert(shared).ToString(); + var body = (BodyTarget) PopValueAssert(shared); + if (body == null) + throw new KOSInvalidArgumentException("orbit", "body", "no body found"); Vector vel = GetVector(PopValueAssert(shared)); Vector pos = GetVector(PopValueAssert(shared)); AssertArgBottomAndConsume(shared); - var result = new OrbitInfo(pos, vel, VesselUtils.GetBodyByName(bodyName), when.ToUnixStyleTime(), shared); + var result = new OrbitInfo(pos, vel, body.Body, when.ToUnixStyleTime(), shared); ReturnValue = result; } } diff --git a/src/kOS/Suffixed/OrbitInfo.cs b/src/kOS/Suffixed/OrbitInfo.cs index 2122bd56b..586eb47fe 100644 --- a/src/kOS/Suffixed/OrbitInfo.cs +++ b/src/kOS/Suffixed/OrbitInfo.cs @@ -4,6 +4,7 @@ using kOS.Serialization; using kOS.Safe.Serialization; using kOS.Safe; +using kOS.Utilities; using UnityEngine; namespace kOS.Suffixed @@ -38,13 +39,17 @@ public OrbitInfo(Vector pos, Vector vel, CelestialBody body, double when, Shared { Shared = sharedObj; orbit = new Orbit(); - orbit.UpdateFromStateVectors(pos.SwapYZ(), vel.SwapYZ(), body, when); + orbit.UpdateFromStateVectors(Utils.SwapYZ(pos), Utils.SwapYZ(vel), body, when); + Debug.Log("UpdateFromStateVectors body: " + body); + Debug.Log("UpdateFromStateVectors when: " + when); // fix from MJ for perfectly circular orbits if (double.IsNaN(orbit.argumentOfPeriapsis)) { Debug.Log("fixing NaN argumentOfPeriapsis for orbit from UpdateFromStateVectors"); - Vector3d vectorToAN = Quaternion.AngleAxis((float)orbit.LAN, Planetarium.up) * Planetarium.right; - double cosArgumentOfPeriapsis = Vector3d.Dot(vectorToAN, orbit.eccVec) / (vectorToAN.magnitude * orbit.eccVec.magnitude); + Vector3d vectorToAN = Quaternion.AngleAxis(-(float)orbit.LAN, Planetarium.up) * Planetarium.right; + Vector3d vectorToPe = Utils.SwapYZ(orbit.eccVec); + + double cosArgumentOfPeriapsis = Vector3d.Dot(vectorToAN, vectorToPe) / (vectorToAN.magnitude * vectorToPe.magnitude); if(cosArgumentOfPeriapsis > 1) { orbit.argumentOfPeriapsis = 0; } else if (cosArgumentOfPeriapsis < -1) { @@ -53,7 +58,7 @@ public OrbitInfo(Vector pos, Vector vel, CelestialBody body, double when, Shared orbit.argumentOfPeriapsis = Math.Acos(cosArgumentOfPeriapsis); } } - name = ""; + name = ""; } private void InitializeSuffixes() diff --git a/src/kOS/Suffixed/Vector.cs b/src/kOS/Suffixed/Vector.cs index 5ede8016e..1d37f0623 100644 --- a/src/kOS/Suffixed/Vector.cs +++ b/src/kOS/Suffixed/Vector.cs @@ -109,11 +109,6 @@ public Vector3 ToVector3() // Vector3 is the single-precision version of Vector3 return new Vector3((float)X, (float)Y, (float)Z); } - public Vector SwapYZ() // Used for KSP APIs that swap Y and Z - { - return new Vector(X, Z, Y); - } - public override string ToString() { return "V(" + X + ", " + Y + ", " + Z + ")"; diff --git a/src/kOS/Utilities/Utils.cs b/src/kOS/Utilities/Utils.cs index d6cdaa1d7..cf1a13962 100644 --- a/src/kOS/Utilities/Utils.cs +++ b/src/kOS/Utilities/Utils.cs @@ -41,6 +41,21 @@ public static double RadiansToDegrees(double radians) return radians * 180 / Math.PI; } + public static Vector3d SwapYZ(Vector3d vector) + { + return new Vector3d(vector.x, vector.z, vector.y); + } + + public static Vector3 SwapYZ(Vector3 vector) + { + return new Vector3(vector.x, vector.z, vector.y); + } + + public static Vector SwapYZ(Vector vector) + { + return new Vector(vector.X, vector.Z, vector.Y); + } + public static bool IsValidVector(Vector3d vector) { return IsValidNumber(vector.x) && @@ -270,4 +285,4 @@ public static CelestialBody KOSExtensionGetParentBody(this CelestialBody body) return parent; } } -} \ No newline at end of file +} From 859c4050b80af16783c2dad5ec5553c757877c9f Mon Sep 17 00:00:00 2001 From: Lamont Granquist Date: Mon, 30 May 2016 10:29:13 -0700 Subject: [PATCH 3/7] remove Debug.Log statements --- src/kOS/Suffixed/OrbitInfo.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/kOS/Suffixed/OrbitInfo.cs b/src/kOS/Suffixed/OrbitInfo.cs index 586eb47fe..224e37e53 100644 --- a/src/kOS/Suffixed/OrbitInfo.cs +++ b/src/kOS/Suffixed/OrbitInfo.cs @@ -40,12 +40,9 @@ public OrbitInfo(Vector pos, Vector vel, CelestialBody body, double when, Shared Shared = sharedObj; orbit = new Orbit(); orbit.UpdateFromStateVectors(Utils.SwapYZ(pos), Utils.SwapYZ(vel), body, when); - Debug.Log("UpdateFromStateVectors body: " + body); - Debug.Log("UpdateFromStateVectors when: " + when); // fix from MJ for perfectly circular orbits if (double.IsNaN(orbit.argumentOfPeriapsis)) { - Debug.Log("fixing NaN argumentOfPeriapsis for orbit from UpdateFromStateVectors"); Vector3d vectorToAN = Quaternion.AngleAxis(-(float)orbit.LAN, Planetarium.up) * Planetarium.right; Vector3d vectorToPe = Utils.SwapYZ(orbit.eccVec); From 869393c84f9fad3851c9dfbf4253e494f784f2b3 Mon Sep 17 00:00:00 2001 From: Lamont Granquist Date: Tue, 31 May 2016 23:14:10 -0700 Subject: [PATCH 4/7] add LAN fixup and change frame of API changed to ship-local from body-centric, docs updated --- doc/source/structures/orbits/orbit.rst | 15 +++++++++++---- src/kOS/Function/Suffixed.cs | 2 +- src/kOS/Suffixed/OrbitInfo.cs | 13 +++++++++---- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/doc/source/structures/orbits/orbit.rst b/doc/source/structures/orbits/orbit.rst index 9161155db..9d655a293 100644 --- a/doc/source/structures/orbits/orbit.rst +++ b/doc/source/structures/orbits/orbit.rst @@ -23,17 +23,24 @@ Creation .. function:: ORBIT(x, v, body, t) - :parameter x: (vector) position at time t + :parameter x: (vector) position at time t in the :ref:`ship-center-raw-rotation ` frame :parameter v: (vetor) velocity at time t :parameter body: (CelstialBody) central body of orbit :parameter t: (scalar) universal time :return: :struct:`Orbit` - This creates a new orbit around a body given the position and velocity at a given time:: + This creates a new user defined orbit (for predictive/calculation purposes) around a body given the position and velocity + at a given time. The vectors are in the ref:`ship-center-raw-rotation ` frame. This makes it easy to + recover (or perturb) an orbit based on a given position and velocity: - SET o TO ORBIT( x, v, kerbin, TIME:SECONDS ). + SET t TO TIME:SECONDS + 100. + SET o TO ORBIT( obt:velocityat(t), obt:positionat(t), body, t ). - Here, a new :struct:`Orbit` called ``o`` is created. + Here, a new :struct:`Orbit` called ``o`` is created that should be very nearly equal to the current orbit. + + To create an orbit based on the position (r) and velocity (v) from the center of the body a translation is required: + + SET o TO ORBIT( r + body:position, v, body, TIME:SECONDS ). Structure --------- diff --git a/src/kOS/Function/Suffixed.cs b/src/kOS/Function/Suffixed.cs index ae021264c..057c6b9f9 100644 --- a/src/kOS/Function/Suffixed.cs +++ b/src/kOS/Function/Suffixed.cs @@ -178,7 +178,7 @@ public override void Execute(SharedObjects shared) Vector vel = GetVector(PopValueAssert(shared)); Vector pos = GetVector(PopValueAssert(shared)); AssertArgBottomAndConsume(shared); - var result = new OrbitInfo(pos, vel, body.Body, when.ToUnixStyleTime(), shared); + var result = new OrbitInfo(pos, vel, body, when.ToUnixStyleTime(), shared); ReturnValue = result; } } diff --git a/src/kOS/Suffixed/OrbitInfo.cs b/src/kOS/Suffixed/OrbitInfo.cs index 224e37e53..d6377ed12 100644 --- a/src/kOS/Suffixed/OrbitInfo.cs +++ b/src/kOS/Suffixed/OrbitInfo.cs @@ -35,12 +35,17 @@ public OrbitInfo( Orbit orb, SharedObjects sharedObj) : this() name = ""; } - public OrbitInfo(Vector pos, Vector vel, CelestialBody body, double when, SharedObjects sharedObj) : this() + public OrbitInfo(Vector pos, Vector vel, BodyTarget body, double when, SharedObjects sharedObj) : this() { Shared = sharedObj; orbit = new Orbit(); - orbit.UpdateFromStateVectors(Utils.SwapYZ(pos), Utils.SwapYZ(vel), body, when); - // fix from MJ for perfectly circular orbits + orbit.UpdateFromStateVectors(Utils.SwapYZ(pos - body.GetPosition()), Utils.SwapYZ(vel), body.Body, when); + if (double.IsNaN(orbit.LAN)) + { + // not sure if this matters, but avoids annoying NaN issues in KOS with perfectly equatorial orbits + orbit.LAN = 0; + } + // fix from MJ for perfectly circular orbits (not sure if any of the precision here matters) if (double.IsNaN(orbit.argumentOfPeriapsis)) { Vector3d vectorToAN = Quaternion.AngleAxis(-(float)orbit.LAN, Planetarium.up) * Planetarium.right; @@ -52,7 +57,7 @@ public OrbitInfo(Vector pos, Vector vel, CelestialBody body, double when, Shared } else if (cosArgumentOfPeriapsis < -1) { orbit.argumentOfPeriapsis = 180; } else { - orbit.argumentOfPeriapsis = Math.Acos(cosArgumentOfPeriapsis); + orbit.argumentOfPeriapsis = Math.Acos(cosArgumentOfPeriapsis) * 180 / Math.PI;; } } name = ""; From 0ec76d57c0015de21850a84a316108818d08ae80 Mon Sep 17 00:00:00 2001 From: Lamont Granquist Date: Wed, 1 Jun 2016 16:23:53 -0700 Subject: [PATCH 5/7] update tests plus minor doc fix --- doc/source/structures/orbits/orbit.rst | 2 +- kerboscript_tests/structures/orbit1.ks | 61 ++++++++++++++++++++------ 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/doc/source/structures/orbits/orbit.rst b/doc/source/structures/orbits/orbit.rst index 9d655a293..880de0f9b 100644 --- a/doc/source/structures/orbits/orbit.rst +++ b/doc/source/structures/orbits/orbit.rst @@ -34,7 +34,7 @@ Creation recover (or perturb) an orbit based on a given position and velocity: SET t TO TIME:SECONDS + 100. - SET o TO ORBIT( obt:velocityat(t), obt:positionat(t), body, t ). + SET o TO ORBIT( obt:velocityat(t):orbit, obt:positionat(t), body, t ). Here, a new :struct:`Orbit` called ``o`` is created that should be very nearly equal to the current orbit. diff --git a/kerboscript_tests/structures/orbit1.ks b/kerboscript_tests/structures/orbit1.ks index 7fa15bb01..82bab9e20 100644 --- a/kerboscript_tests/structures/orbit1.ks +++ b/kerboscript_tests/structures/orbit1.ks @@ -7,15 +7,19 @@ // creates a keosynchronous orbit of an object directly above the equatorial coordinates of // KSC and checks the position at the current time and 1/4 way around the orbit. -set sidereal_day to 5*3600 + 59*60 + 9.4. + +wait until ship:unpacked. +CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Open Terminal"). + +local sidereal_day to 5*3600 + 59*60 + 9.4. // x0, v0 are what we use to build the orbit -set x0 to latlng(0, -75.08333333333333333332):position - ship:body:position. +local x0 to latlng(0, -75.08333333333333333332):position - ship:body:position. set x0:mag to (sqrt(kerbin:mu) * sidereal_day / (2 * constant:pi))^(2/3). // 3463331.36. -set v0 to vcrs(kerbin:angularvel, x0). +local v0 to vcrs(kerbin:angularvel, x0). set v0:mag to sqrt(kerbin:mu / x0:mag). -set keosynch to orbit(x0, v0, kerbin, time:seconds). +local keosynch to orbit(x0 + ship:body:position, v0, ship:body, time:seconds). print "sma : " + keosynch:semimajoraxis. print "ecc : " + keosynch:eccentricity. @@ -24,10 +28,20 @@ print "arg : " + keosynch:argumentofperiapsis. print "period : " + keosynch:period. // x1, v1 should recover the same, while x2, v2 should be 1/4 around the orbit -set x1 to keosynch:positionat(time:seconds) - ship:body:position. -set v1 to keosynch:velocityat(time:seconds):orbit. -set x2 to keosynch:positionat(time:seconds + sidereal_day/4) - ship:body:position. -set v2 to keosynch:velocityat(time:seconds + sidereal_day/4):orbit. +local xnow to keosynch:position - ship:body:position. +local vnow to keosynch:velocity:orbit. +local x1 to keosynch:positionat(time:seconds) - ship:body:position. +local v1 to keosynch:velocityat(time:seconds):orbit. +local x2 to keosynch:positionat(time:seconds + sidereal_day/4) - ship:body:position. +local v2 to keosynch:velocityat(time:seconds + sidereal_day/4):orbit. + +// this should recover the same orbit +local keosynch2 to orbit(keosynch:positionat(time:seconds + 100), keosynch:velocityat(time:seconds + 100):orbit, ship:body, time:seconds + 100). + +// should be the same as xnow/x1 +local x3 to keosynch2:positionat(time:seconds) - ship:body:position. +local v3 to keosynch2:velocityat(time:seconds):orbit. + print "x1 : " + x1:mag. print "v1 : " + v1:mag. @@ -35,8 +49,8 @@ print "x2 : " + x2:mag. print "v2 : " + v2:mag. // some handy vectors for debugging in case something goes wrong. -set xvec0 to vecdraw(ship:body:position, x0, rgb(0,0,1), "x0", 1.0, true, 0.2). -set vvec0 to vecdraw(ship:body:position + x0, 1000 * v0, rgb(0,0,1), "v0", 1.0, true, 0.2). +set xvec0 to vecdraw(ship:body:position, x0, rgb(1,0,0), "x0", 1.0, true, 0.2). +set vvec0 to vecdraw(ship:body:position + x0, 1000 * v0, rgb(1,0,0), "v0", 1.0, true, 0.2). set xvec1 to vecdraw(ship:body:position, x1, rgb(1,0,0), "x1", 1.0, true, 0.2). set vvec1 to vecdraw(ship:body:position + x1, 1000 * v1, rgb(1,0,0), "v1", 1.0, true, 0.2). set xvec2 to vecdraw(ship:body:position, x2, rgb(0,1,0), "x2", 1.0, true, 0.2). @@ -46,19 +60,26 @@ set vvec2 to vecdraw(ship:body:position + x2, 1000 * v2, rgb(0,1,0), "v2", 1.0, if abs(keosynch:period - sidereal_day) > 1 exit. - if abs(keosynch:eccentricity) > 0.000001 exit. - if abs(keosynch:semimajoraxis - 3463331.36) > 0.1 exit. +if abs(keosynch2:period - sidereal_day) > 1 + exit. +if abs(keosynch2:eccentricity) > 0.000001 + exit. +if abs(keosynch2:semimajoraxis - 3463331.36) > 0.1 + exit. + if abs(x0:mag - 3463331.36) > 0.1 exit. if abs(x1:mag - 3463331.36) > 0.1 exit. if abs(x2:mag - 3463331.36) > 0.1 exit. +if abs(x3:mag - 3463331.36) > 0.1 + exit. if abs(v0:mag - 1009.81) > 0.1 exit. @@ -66,12 +87,22 @@ if abs(v1:mag - 1009.81) > 0.1 exit. if abs(v2:mag - 1009.81) > 0.1 exit. +if abs(v3:mag - 1009.81) > 0.1 + exit. +// these all recover the same vector at time:seconds ("now") +if (x1 - xnow):mag > 1 + exit. +if (v1 - vnow):mag > 1 + exit. if (x1 - x0):mag > 1 exit. - if (v1 - v0):mag > 1 exit. +if (x1 - x3):mag > 1 + exit. +if (v1 - v3):mag > 1 + exit. // x2 should point in the v1 direction if abs(3463331.36 - vdot(x2, v1:normalized)) > 0.1 @@ -90,3 +121,7 @@ if vdot(x2:normalized, kerbin:angularvel:normalized) > 0.001 exit. if vdot(v2:normalized, kerbin:angularvel:normalized) > 0.001 exit. +if vdot(x3:normalized, kerbin:angularvel:normalized) > 0.001 + exit. +if vdot(v3:normalized, kerbin:angularvel:normalized) > 0.001 + exit. From ded12b427ae979a06f456179ccddb10c3753ca50 Mon Sep 17 00:00:00 2001 From: Lamont Granquist Date: Wed, 1 Jun 2016 16:29:19 -0700 Subject: [PATCH 6/7] document known bug --- src/kOS/Suffixed/OrbitInfo.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/kOS/Suffixed/OrbitInfo.cs b/src/kOS/Suffixed/OrbitInfo.cs index d6377ed12..79db895e9 100644 --- a/src/kOS/Suffixed/OrbitInfo.cs +++ b/src/kOS/Suffixed/OrbitInfo.cs @@ -39,6 +39,11 @@ public OrbitInfo(Vector pos, Vector vel, BodyTarget body, double when, SharedObj { Shared = sharedObj; orbit = new Orbit(); + // FIXME: there is a bug here in translating betwee ship-local and body-centered coordinate systems, if you + // are below the body.inverseRotationAltitude when you try to compute an orbit. you may be off by a rotation. + // uncertain of the exact incantations to fix. workaround is to get yourself into orbit first before trying + // to compute orbits from this function. mechjeb also has this bug, but nobody has reported it or fixed it. + // it should mostly troll people who are doing orbital computation testing while on the launchpad (sometimes). orbit.UpdateFromStateVectors(Utils.SwapYZ(pos - body.GetPosition()), Utils.SwapYZ(vel), body.Body, when); if (double.IsNaN(orbit.LAN)) { From 8de1d2117c6eb958167a7b5471487f0a45db15c7 Mon Sep 17 00:00:00 2001 From: Lamont Granquist Date: Thu, 23 Jun 2016 18:30:20 -0700 Subject: [PATCH 7/7] remove all the hacks no longer necessary for 1.1.3 --- doc/make.bat | 484 +++++++++++++++++----------------- src/kOS/Suffixed/OrbitInfo.cs | 25 -- 2 files changed, 242 insertions(+), 267 deletions(-) diff --git a/doc/make.bat b/doc/make.bat index 6d70fb3ad..cffb7b2c0 100644 --- a/doc/make.bat +++ b/doc/make.bat @@ -1,242 +1,242 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set BUILDDIR=build -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source -set I18NSPHINXOPTS=%SPHINXOPTS% source -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% - set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^` where ^ is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. singlehtml to make a single large HTML file - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. devhelp to make HTML files and a Devhelp project - echo. epub to make an epub - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. text to make text files - echo. man to make manual pages - echo. texinfo to make Texinfo files - echo. gettext to make PO message catalogs - echo. changes to make an overview over all changed/added/deprecated items - echo. xml to make Docutils-native XML files - echo. pseudoxml to make pseudoxml-XML files for display purposes - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - - -%SPHINXBUILD% 2> nul -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% gh-pages - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in gh-pages. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\kOS.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\kOS.ghc - goto end -) - -if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. - goto end -) - -if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdf" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf - cd %BUILDDIR%/.. - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdfja" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf-ja - cd %BUILDDIR%/.. - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. - goto end -) - -if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. - goto end -) - -if "%1" == "texinfo" ( - %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. - goto end -) - -if "%1" == "gettext" ( - %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The message catalogs are in %BUILDDIR%/locale. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - if errorlevel 1 exit /b 1 - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - if errorlevel 1 exit /b 1 - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - if errorlevel 1 exit /b 1 - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -if "%1" == "xml" ( - %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The XML files are in %BUILDDIR%/xml. - goto end -) - -if "%1" == "pseudoxml" ( - %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. - goto end -) - -:end +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source +set I18NSPHINXOPTS=%SPHINXOPTS% source +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% gh-pages + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in gh-pages. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\kOS.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\kOS.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/src/kOS/Suffixed/OrbitInfo.cs b/src/kOS/Suffixed/OrbitInfo.cs index 79db895e9..881ecaa99 100644 --- a/src/kOS/Suffixed/OrbitInfo.cs +++ b/src/kOS/Suffixed/OrbitInfo.cs @@ -39,32 +39,7 @@ public OrbitInfo(Vector pos, Vector vel, BodyTarget body, double when, SharedObj { Shared = sharedObj; orbit = new Orbit(); - // FIXME: there is a bug here in translating betwee ship-local and body-centered coordinate systems, if you - // are below the body.inverseRotationAltitude when you try to compute an orbit. you may be off by a rotation. - // uncertain of the exact incantations to fix. workaround is to get yourself into orbit first before trying - // to compute orbits from this function. mechjeb also has this bug, but nobody has reported it or fixed it. - // it should mostly troll people who are doing orbital computation testing while on the launchpad (sometimes). orbit.UpdateFromStateVectors(Utils.SwapYZ(pos - body.GetPosition()), Utils.SwapYZ(vel), body.Body, when); - if (double.IsNaN(orbit.LAN)) - { - // not sure if this matters, but avoids annoying NaN issues in KOS with perfectly equatorial orbits - orbit.LAN = 0; - } - // fix from MJ for perfectly circular orbits (not sure if any of the precision here matters) - if (double.IsNaN(orbit.argumentOfPeriapsis)) - { - Vector3d vectorToAN = Quaternion.AngleAxis(-(float)orbit.LAN, Planetarium.up) * Planetarium.right; - Vector3d vectorToPe = Utils.SwapYZ(orbit.eccVec); - - double cosArgumentOfPeriapsis = Vector3d.Dot(vectorToAN, vectorToPe) / (vectorToAN.magnitude * vectorToPe.magnitude); - if(cosArgumentOfPeriapsis > 1) { - orbit.argumentOfPeriapsis = 0; - } else if (cosArgumentOfPeriapsis < -1) { - orbit.argumentOfPeriapsis = 180; - } else { - orbit.argumentOfPeriapsis = Math.Acos(cosArgumentOfPeriapsis) * 180 / Math.PI;; - } - } name = ""; }