Exemple #1
0
        public VesselSensors(Vessel target)
        {
            foreach (var part in target.Parts)
            {
                if (part.State != PartStates.ACTIVE && part.State != PartStates.IDLE) continue;

                foreach (PartModule module in part.Modules)
                {
                    if (module is ModuleEnviroSensor)
                    {
                        switch (module.Fields.GetValue("sensorType").ToString())
                        {
                            case "ACC":
                                acceleration =
                                    new Vector(FlightGlobals.getGeeForceAtPosition(part.transform.position) - target.acceleration);
                                break;
                            case "PRES":
                                pressure = FlightGlobals.getStaticPressure();
                                break;
                            case "TEMP":
                                temperature = part.temperature;
                                break;
                            case "GRAV":
                                geeForce = new Vector(FlightGlobals.getGeeForceAtPosition(part.transform.position));
                                break;
                        }
                    }
                    foreach (var c in part.FindModulesImplementing<ModuleDeployableSolarPanel>())
                    {
                        kerbolExposure += c.sunAOA;
                    }
                }
            }
        }
Exemple #2
0
 /// <summary>
 /// Interpret the vector given as a 3D position, and return the geocoordinates directly underneath it on this body.
 /// </summary>
 /// <param name="position">Vector to use as the 3D position in ship-raw coords</param>
 /// <returns>The GeoCoordinates under the position.</returns>
 public GeoCoordinates GeoCoordinatesFromPosition(Vector position)
 {
     Vector3d unityWorldPosition = Shared.Vessel.findWorldCenterOfMass() + position.ToVector3D();
     double lat = Body.GetLatitude(unityWorldPosition);
     double lng = Body.GetLongitude(unityWorldPosition);
     return new GeoCoordinates(Body, Shared, lat, lng);
 }
Exemple #3
0
 public OrbitableVelocity(CelestialBody b, SharedObjects shared)
 {
     Orbital = new Vector(b.KOSExtensionGetObtVelocity(shared)); // KSP's b.GetObtVelocity() is broken - it causes stack overflow
     CelestialBody parent = b.KOSExtensionGetParentBody();
     Surface = (parent != null) ?
         new Vector(b.orbit.GetVel() - parent.getRFrmVel(b.position)) :
         new Vector(Vector3d.zero);
     InitializeSuffixes();
 }
Exemple #4
0
 public OrbitableVelocity(CelestialBody b, SharedObjects shared)
 {
     Orbital = new Vector(b.KOSExtensionGetObtVelocity(shared)); // KSP's b.GetObtVelocity() is broken - it causes stack overflow
     CelestialBody parent = b.KOSExtensionGetParentBody();
     Surface = (parent != null) ?
         new Vector(b.orbit.GetVel() - parent.getRFrmVel(b.position)) :
         new Vector(Orbital); // return same velocity as orbit when no parent body to compare against.
     InitializeSuffixes();
 }
Exemple #5
0
        public override void Execute(SharedObjects shared)
        {
            double z = GetDouble(PopValueAssert(shared));
            double y = GetDouble(PopValueAssert(shared));
            double x = GetDouble(PopValueAssert(shared));
            AssertArgBottomAndConsume(shared);

            var result = new Vector(x, y, z);
            ReturnValue = result;
        }
Exemple #6
0
 public FlightControl(Vessel vessel)
 {
     rotation = new Vector(0, 0, 0);
     translation = new Vector(0, 0, 0);
     neutral = new Flushable<bool>();
     killRotation = new Flushable<bool>();
     bound = true;
     this.vessel = vessel;
     Vessel.OnFlyByWire += OnFlyByWire;
 }
Exemple #7
0
        public FlightControl(Vessel vessel)
        {
            rotation = new Vector(0, 0, 0);
            translation = new Vector(0, 0, 0);
            neutral = new Flushable<bool>();
            killRotation = new Flushable<bool>();
            bound = false;
            this.vessel = vessel;

            doubleSuffixes = new List<string> { "YAW", "PITCH", "ROLL", "STARBOARD", "TOP", "FORE", "MAINTHROTTLE", "WHEELTHROTTLE", "WHEELSTEER" };
            vectorSuffixes = new List<string> { "ROTATION", "TRANSLATION" };
        }
Exemple #8
0
 /// <summary>
 ///   Get the velocity pairing of this thing in this orbit at the given
 ///   time.  Note that it does NOT take into account any
 ///   encounters or maneuver nodes - it assumes the current
 ///   orbit patch remains followed forever.
 /// </summary>
 /// <param name="timeStamp">The universal time to query for</param>
 /// <returns></returns>
 public OrbitableVelocity GetVelocityAtUT( TimeSpan timeStamp )
 {
     var orbVel = new Vector( orbit.getOrbitalVelocityAtUT( timeStamp.ToUnixStyleTime() ) );
     // For some weird reason orbit returns velocities with Y and Z swapped, so flip them back:
     orbVel = new Vector( orbVel.X, orbVel.Z, orbVel.Y );
     CelestialBody parent = orbit.referenceBody;
     Vector surfVel;
     if (parent != null)
     {
         Vector3d pos = GetPositionAtUT( timeStamp );
         surfVel = new Vector( orbVel - parent.getRFrmVel( pos + shared.Vessel.findWorldCenterOfMass()) );
     }
     else
         surfVel = new Vector( orbVel.X, orbVel.Y, orbVel.Z );
     return new OrbitableVelocity( orbVel, surfVel );
 }
Exemple #9
0
        override public OrbitableVelocity GetVelocitiesAtUT(TimeSpan timeStamp)
        {
            CelestialBody parent = Body.KOSExtensionGetParentBody();
            if (parent == null) // only if Body is Sun and therefore has no parent, then do more complex work instead because KSP didn't provide a way itself
            {
                Vector3d futureOrbitalVel;
                CelestialBody soiBody = Shared.Vessel.mainBody;
                if (soiBody.orbit != null)
                    futureOrbitalVel = soiBody.orbit.GetFrameVelAtUT(timeStamp.ToUnixStyleTime());
                else
                    futureOrbitalVel = (-1) * (new VesselTarget(Shared.Vessel, Shared).GetVelocitiesAtUT(timeStamp).Orbital.ToVector3D());
                return new OrbitableVelocity(new Vector(futureOrbitalVel), new Vector(0.0, 0.0, 0.0));
            }

            var orbVel = new Vector(Orbit.getOrbitalVelocityAtUT(timeStamp.ToUnixStyleTime()));
            orbVel = new Vector(orbVel.X, orbVel.Z, orbVel.Y); // swap Y and Z because KSP API is weird.

            var surfVel = new Vector(Body.orbit.GetVel() - parent.getRFrmVel(Body.position));

            return new OrbitableVelocity(orbVel, surfVel);
        }
Exemple #10
0
 /// <summary>
 /// Interpret the vector given as a 3D position, and return the altitude above sea level of this body.
 /// </summary>
 /// <param name="position">Vector to use as the 3D position in ship-raw coords</param>
 /// <returns>The altitude above 'sea level'.</returns>
 public double AltitudeFromPosition(Vector position)
 {
     Vector3d unityWorldPosition = Shared.Vessel.findWorldCenterOfMass() + position.ToVector3D();
     return Body.GetAltitude(unityWorldPosition);
 }
Exemple #11
0
        public override bool SetSuffix(string suffixName, object value)
        {
            UnityEngine.Debug.Log("FlightControl Set: " + suffixName + " Value: " + value);
            Bind();

            if (CheckNeutral(suffixName, value))
            {
                return true;
            }

            if (CheckKillRotation(suffixName, value))
            {
                return true;
            }

            switch (suffixName)
            {
                case "YAW":
                    rotation.X = Convert.ToSingle(value);
                    break;
                case "PITCH":
                    rotation.Y = Convert.ToSingle(value);
                    break;
                case "ROLL":
                    rotation.Z = Convert.ToSingle(value);
                    break;
                case "STARBOARD":
                    translation.X = Convert.ToSingle(value);
                    break;
                case "TOP":
                    translation.Y = Convert.ToSingle(value);
                    break;
                case "FORE":
                    translation.Z = Convert.ToSingle(value);
                    break;
                case "ROTATION":
                    rotation = (Vector) value;
                    break;
                case "TRANSLATION":
                    translation = (Vector) value;
                    break;
                case "MAINTHROTTLE":
                    mainThrottle = Convert.ToSingle(value);
                    break;
                case "WHEELTHROTTLE":
                    wheelThrottle = Convert.ToSingle(value);
                    break;
                case "WHEELSTEER":
                    wheelSteer = Convert.ToSingle(value);
                    break;
                default:
                    return false;
            }
            return true;
        }
Exemple #12
0
 public VesselVelocity(Vessel v)
 {
     orbitVelocity = new Vector(v.obt_velocity);
     surfaceVelocity = new Vector(v.srf_velocity);
     velocityHeading = VesselUtils.GetVelocityHeading(v);
 }
Exemple #13
0
        private bool ValueToVector(object value, ref Vector vectorValue)
        {
            var valueStr = value.ToString();

            var vector = value as Vector;

            if (vector != null)
            {
                if (!Utils.IsValidVector(vector))
                    return false;
                vectorValue = vector;
            }
            else
            {
                return false;
            }
            return true;
        }
Exemple #14
0
 private void SetTranslation(Vector vectorValue)
 {
     if (vectorValue == null)
     {
         fore = 0.0f;
         top = 0.0f;
         starboard = 0.0f;
     }
     else
     {
         starboard = (float)vectorValue.X;
         top = (float)vectorValue.Y;
         fore = (float)vectorValue.Z;
     }
 }
Exemple #15
0
 private void SetRotation(Vector vectorValue)
 {
     if (vectorValue == null)
     {
         yaw = 0.0f;
         pitch = 0.0f;
         roll = 0.0f;
     }
     else
     {
         yaw = (float)vectorValue.X;
         pitch = (float)vectorValue.Y;
         roll = (float)vectorValue.Z;
     }
 }
Exemple #16
0
 /// <summary>
 ///   Create a OrbitableVelocity object out of a raw pair of hardcoded orbital and surface velocity:
 ///   This leaves it up to the caller to be responsible for making sure the orbital and
 ///   surface velocities match each other.
 /// </summary>
 /// <param name="orbVel">orbital velocity in raw reference frame</param>
 /// <param name="surfVel">surface velocity in raw reference frame</param>
 public OrbitableVelocity(Vector orbVel, Vector surfVel)
 {
     Orbital = orbVel;
     Surface = surfVel;
     InitializeSuffixes();
 }
Exemple #17
0
        public override OrbitableVelocity GetVelocitiesAtUT( TimeSpan timeStamp )
        {
            Vector orbVel = new Vector( Orbit.getOrbitalVelocityAtUT( timeStamp.ToUnixStyleTime() ) );
            orbVel = new Vector(orbVel.X,orbVel.Z,orbVel.Y); // swap Y and Z because KSP API is weird.

            CelestialBody parent = Body.referenceBody;
            if (parent==null) // only if Body is Sun and therefore has no parent.
                return new OrbitableVelocity( new Vector(0.0,0.0,0.0), new Vector(0.0,0.0,0.0) );
            var surfVel = new Vector( Body.orbit.GetVel() - parent.getRFrmVel( Body.position ) );

            return new OrbitableVelocity( orbVel, surfVel );
        }
Exemple #18
0
        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 )
                {
                    Vector = vec,
                    Start = start,
                    Color = rgba,
                    Scale = scale,
                    Width = width
                };
            vRend.SetLabel( str );
            vRend.SetShow( show );

            ReturnValue = vRend;
        }
Exemple #19
0
        /// <summary>
        ///   Calculates the velocities of this vessel at some future universal timestamp,
        ///   taking into account all currently predicted SOI transition patches, and also
        ///   assuming that all the planned maneuver nodes will actually be executed precisely
        ///   as planned.  Note that this cannot "see" into the future any farther than the
        ///   KSP orbit patches setting allows for.
        /// </summary>
        /// <param name="timeStamp">The time to predict for.  Although the intention is to
        ///   predict for a future time, it could be used to predict for a past time.</param>
        /// <returns>The orbit/surface velocity pair as a user-readable Vector in raw rotation coordinates.</returns>
        override public OrbitableVelocity GetVelocitiesAtUT(TimeSpan timeStamp)
        {
            string blockingTech;
            if (!Career.CanMakeNodes(out blockingTech))
                throw new KOSLowTechException("use VELOCITYAT on a vessel", blockingTech);

            double desiredUT = timeStamp.ToUnixStyleTime();

            Orbit patch = GetOrbitAtUT(desiredUT);

            Vector3d orbVel = patch.getOrbitalVelocityAtUT(desiredUT);

            // This is an ugly workaround to fix what is probably a bug in KSP's API:
            // If looking at a future orbit patch around a child body of the current body, then
            // the various get{Thingy}AtUT() methods return numbers calculated incorrectly as
            // if the child body was going to remain stationary where it is now, rather than
            // taking into account where it will be later when the intercept happens.
            // This corrects for that case:
            if (Utils.BodyOrbitsBody(patch.referenceBody, Vessel.orbit.referenceBody))
            {
                Vector3d futureBodyVel = patch.referenceBody.orbit.getOrbitalVelocityAtUT(desiredUT);
                orbVel = orbVel + futureBodyVel;
            }

            // For some weird reason orbital velocities are returned by the KSP API
            // with Y and Z swapped, so swap them back:
            orbVel = new Vector3d(orbVel.x, orbVel.z, orbVel.y);

            CelestialBody parent = patch.referenceBody;
            Vector surfVel;
            if (parent != null)
            {
                Vector3d pos = GetPositionAtUT(timeStamp);
                surfVel = new Vector(orbVel - parent.getRFrmVel(pos + Shared.Vessel.findWorldCenterOfMass()));
            }
            else
                surfVel = new Vector(orbVel.x, orbVel.y, orbVel.z);

            return new OrbitableVelocity(new Vector(orbVel), surfVel);
        }
Exemple #20
0
 public double PositionToLongitude( Vector pos )
 {
     CelestialBody parent = GetParentBody();
     if (parent == null) //happens when this Orbitable is the Sun
         return 0.0;
     Vector3d unityWorldPos = GetPosition() + (Vector3d)Shared.Vessel.CoMD;
     return Utils.DegreeFix( parent.GetLongitude(unityWorldPos), -180.0 );
 }
Exemple #21
0
        private void InitializeMockObjects()
        {
            _mocks.GetOrAdd(typeof(VesselTarget), (type) =>
            {
                var constructor = type.GetConstructor(
                    BindingFlags.NonPublic | BindingFlags.Instance,
                    null,
                    new Type[] { typeof(Vessel), typeof(SharedObjects) },
                    null);
                Structure obj = (Structure)constructor.Invoke(new object[] { null, new SharedObjects() });
                if (obj == null)
                {
                    Console.Error.WriteLine("Failed to create mock object for " + type.ToString());
                }
                else
                {
                    obj.HasSuffix("TYPENAME");
                }
                return(obj);
            });

            _mocks.GetOrAdd(typeof(BodyTarget), (type) =>
            {
                var constructor = type.GetConstructor(
                    BindingFlags.NonPublic | BindingFlags.Instance,
                    null,
                    new Type[] { typeof(CelestialBody), typeof(SharedObjects) },
                    null);
                Structure obj = (Structure)constructor.Invoke(new object[] { null, new SharedObjects() });
                if (obj == null)
                {
                    Console.Error.WriteLine("Failed to create mock for " + type.ToString());
                }
                return(obj);
            });

            _mocks.GetOrAdd(typeof(kOS.Suffixed.Vector), (type) =>
            {
                var obj = new kOS.Suffixed.Vector();
                obj.HasSuffix("TYPENAME"); // force suffix initialization
                return(obj);
            });

            _mocks.GetOrAdd(typeof(OrbitableVelocity), (type) =>
            {
                return(new OrbitableVelocity((Vector)null, (Vector)null));
            });

            _mocks.GetOrAdd(typeof(KUniverseValue), (type) =>
            {
                return(new KUniverseValue(new SharedObjects()));
            });

            _mocks.GetOrAdd(typeof(OrbitInfo), (type) =>
            {
                return(new OrbitInfo());
            });

            _mocks.GetOrAdd(typeof(StringValue), (type) =>
            {
                var obj = new StringValue("");
                obj.HasSuffix("TYPENAME"); // force suffix initialization
                return(obj);
            });

            _mocks.GetOrAdd(typeof(VesselAlt), (type) =>
            {
                return(new VesselAlt(new SharedObjects()));
            });

            _mocks.GetOrAdd(typeof(Node), (type) =>
            {
                return(new Node(0.0, 0.0, 0.0, 0.0, new SharedObjects()));
            });

            _mocks.GetOrAdd(typeof(Suffixed.TimeSpan), (type) =>
            {
                return(new Suffixed.TimeSpan(0.0));
            });

            _mocks.GetOrAdd(typeof(VesselEta), (type) =>
            {
                return(new VesselEta(new SharedObjects()));
            });

            _mocks.GetOrAdd(typeof(kOS.Core), (type) =>
            {
                return(new Core(null, new SharedObjects()));
            });

            _mocks.GetOrAdd(typeof(HomeConnection), (type) =>
            {
                return(new HomeConnection(new SharedObjects()));
            });

            _mocks.GetOrAdd(typeof(ControlConnection), (type) =>
            {
                return(new ControlConnection(new SharedObjects()));
            });

            _mocks.GetOrAdd(typeof(Direction), (type) =>
            {
                return(new Direction());
            });

            _mocks.GetOrAdd(typeof(PIDLoop), (type) =>
            {
                return(new PIDLoop());
            });

            _mocks.GetOrAdd(typeof(SteeringManager), (type) =>
            {
                return(new SteeringManager((Vessel)null));
            });

            _mocks.GetOrAdd(typeof(GeoCoordinates), (type) =>
            {
                var constructor = type.GetConstructor(
                    BindingFlags.NonPublic | BindingFlags.Instance,
                    null,
                    new Type[] {},
                    null);
                Structure obj = (Structure)constructor.Invoke(new object[] {});
                if (obj == null)
                {
                    Console.Error.WriteLine("Failed to create mock for " + type.ToString());
                }
                return(obj);
            });

            _mocks.GetOrAdd(typeof(FlightControl), (type) =>
            {
                return(new FlightControl((Vessel)null));
            });

            _mocks.GetOrAdd(typeof(ListValue), (type) =>
            {
                var obj = new ListValue();
                obj.HasSuffix("TYPENAME");
                return(obj);
            });

            _mocks.GetOrAdd(typeof(ListValue <Structure>), (type) =>
            {
                var obj = new ListValue <Structure>();
                obj.HasSuffix("TYPENAME");
                return(obj);
            });

            _mocks.GetOrAdd(typeof(PartValue), (type) =>
            {
                var constructor = type.GetConstructor(
                    BindingFlags.NonPublic | BindingFlags.Instance,
                    null,
                    new Type[] { typeof(SharedObjects), typeof(global::Part), typeof(PartValue), typeof(DecouplerValue) },
                    null);
                Structure obj = (Structure)constructor.Invoke(new object[] { new SharedObjects(), null, null, null });
                if (obj == null)
                {
                    Console.Error.WriteLine("Failed to create mock for " + type.ToString());
                }
                else
                {
                    obj.HasSuffix("TYPENAME");
                }
                return(obj);
            });

            _mocks.GetOrAdd(typeof(kOS.Safe.Persistence.Volume), (type) =>
            {
                return(new Persistence.MockVolume());
            });

            _mocks.GetOrAdd(typeof(kOS.Safe.Encapsulation.Lexicon), (type) =>
            {
                return(new kOS.Safe.Encapsulation.Lexicon());
            });

            _mocks.GetOrAdd(typeof(ConstantValue), (type) =>
            {
                return(new ConstantValue());
            });

            _mocks.GetOrAdd(typeof(VesselAlt), (type) =>
            {
                return(new VesselAlt((SharedObjects)null));
            });

            _mocks.GetOrAdd(typeof(VesselEta), (type) =>
            {
                return(new VesselEta((SharedObjects)null));
            });
        }
Exemple #22
0
 public OrbitableVelocity(Vessel v)
 {
     Orbital = new Vector(v.obt_velocity);
     Surface = new Vector(v.srf_velocity);
     InitializeSuffixes();
 }
Exemple #23
0
 /// <summary>
 /// Interpret the vector given as a 3D position, and return the altitude above sea level of this body.
 /// </summary>
 /// <param name="position">Vector to use as the 3D position in ship-raw coords</param>
 /// <returns>The altitude above 'sea level'.</returns>
 public ScalarValue AltitudeFromPosition(Vector position)
 {
     Vector3d unityWorldPosition = Shared.Vessel.CoMD + position.ToVector3D();
     return Body.GetAltitude(unityWorldPosition);
 }
Exemple #24
0
 private void SetRotation(Vector vectorValue)
 {
     if (vectorValue == null)
     {
         yaw = 0.0f;
         pitch = 0.0f;
         roll = 0.0f;
     }
     else
     {
         yaw = (float)Safe.Utilities.KOSMath.Clamp(vectorValue.X, -1, 1);
         pitch = (float)Safe.Utilities.KOSMath.Clamp(vectorValue.Y, -1, 1);
         roll = (float)Safe.Utilities.KOSMath.Clamp(vectorValue.Z, -1, 1);
     }
 }
Exemple #25
0
        public override void Execute(SharedObjects shared)
        {
            Vector vector2 = shared.Cpu.PopValue() as Vector;
            Vector vector1 = shared.Cpu.PopValue() as Vector;

            if (vector1 != null && vector2 != null)
            {
                object result = new Vector(Vector3d.Exclude(vector1.ToVector3D(), vector2.ToVector3D()));
                shared.Cpu.PushStack(result);
            }
        }
Exemple #26
0
        public override void Execute(SharedObjects shared)
        {
            var vector2 = GetVector(PopValueAssert(shared));
            var vector1 = GetVector(PopValueAssert(shared));
            AssertArgBottomAndConsume(shared);

            if (vector1 != null && vector2 != null)
            {
                object result = new Vector(Vector3d.Exclude(vector1, vector2));
                ReturnValue = result;
            }
            else
                throw new KOSException("vector exclude attempted with a non-vector value");
        }
Exemple #27
0
 private void SetTranslation(Vector vectorValue)
 {
     if (vectorValue == null)
     {
         fore = 0.0f;
         top = 0.0f;
         starboard = 0.0f;
     }
     else
     {
         starboard = (float)Safe.Utilities.KOSMath.Clamp(vectorValue.X, -1, 1);
         top = (float)Safe.Utilities.KOSMath.Clamp(vectorValue.Y, -1, 1);
         fore = (float)Safe.Utilities.KOSMath.Clamp(vectorValue.Z, -1, 1);
     }
 }
Exemple #28
0
 public static bool IsValidVector(Vector vector)
 {
     return IsValidNumber(vector.X) &&
            IsValidNumber(vector.Y) &&
            IsValidNumber(vector.Z);
 }
Exemple #29
0
        public override void Execute(SharedObjects shared)
        {
            double z = GetDouble(shared.Cpu.PopValue());
            double y = GetDouble(shared.Cpu.PopValue());
            double x = GetDouble(shared.Cpu.PopValue());

            var result = new Vector(x, y, z);
            shared.Cpu.PushStack(result);
        }
Exemple #30
0
 public double PositionToAltitude( Vector pos )
 {
     CelestialBody parent = GetParentBody();
     if (parent == null) //happens when this Orbitable is the Sun
         return 0.0;
     Vector3d unityWorldPos = GetPosition() + (Vector3d)Shared.Vessel.findWorldCenterOfMass();
     return parent.GetAltitude(unityWorldPos);
 }
Exemple #31
0
        public override OrbitableVelocity GetVelocitiesAtUT(TimeSpan timeStamp)
        {
            CelestialBody parent = Body.KOSExtensionGetParentBody();
            if (parent == null) // only if Body is Sun and therefore has no parent, then do more complex work instead because KSP didn't provide a way itself
            {
                Vector3d futureOrbitalVel;
                CelestialBody soiBody = Shared.Vessel.mainBody;
                if (soiBody.orbit != null)
                    futureOrbitalVel = soiBody.orbit.GetFrameVelAtUT(timeStamp.ToUnixStyleTime());
                else
                    futureOrbitalVel = -1 * new VesselTarget(Shared.Vessel, Shared).GetVelocitiesAtUT(timeStamp).Orbital.ToVector3D();
                Vector swappedVel = new Vector(futureOrbitalVel.x, futureOrbitalVel.z, futureOrbitalVel.y); // swap Y and Z because KSP API is weird.
                 // Also invert directions because the above gives vel of my body rel to sun, and I want vel of sun rel to my body:
                return new OrbitableVelocity( -swappedVel, -swappedVel);
            }

            var orbVel = new Vector(Orbit.getOrbitalVelocityAtUT(timeStamp.ToUnixStyleTime()));
            orbVel = new Vector(orbVel.X, orbVel.Z, orbVel.Y); // swap Y and Z because KSP API is weird.

            var surfVel = new Vector(Body.orbit.GetVel() - parent.getRFrmVel(Body.position));

            return new OrbitableVelocity(orbVel, surfVel);
        }