/// <summary> /// This is called at destroy /// </summary> public void OnDisable() { // Tear down the window (saves the position as a side effect) HideMainWindow(false); // Save the persistent attributes to our settings file Settings.Instance.Save(); // The "dead" copy of our object will re-add itself if we don't unsubscribe to this! GameEvents.onGUIApplicationLauncherReady.Remove(AddLauncher); // This event fires when KSP wants mods to remove their toolbar buttons GameEvents.onGUIApplicationLauncherDestroyed.Remove(RemoveLauncher); // This event fires when switching focus in the tracking station GameEvents.onPlanetariumTargetChanged.Remove(TrackingStationTargetChanged); // Reset the view when we take off or land, etc. GameEvents.onVesselSituationChange.Remove(OnSituationChanged); // The launcher destroyed event doesn't always fire when we need it (?) RemoveLauncher(); // This event fires on SOI change if (VesselMode) { OrbitDriver orbDrv = FlightGlobals.ActiveVessel.GetOrbitDriver(); orbDrv.OnReferenceBodyChange -= SOIChanged; } }
public static void Complex(OrbitDriver currentlyEditing, double inclination, double eccentricity, double semiMajorAxis, double longitudeAscendingNode, double argumentOfPeriapsis, double meanAnomalyAtEpoch, double epoch, CelestialBody body) { SetOrbit(currentlyEditing, CreateOrbit(inclination, eccentricity, semiMajorAxis, longitudeAscendingNode, argumentOfPeriapsis, meanAnomalyAtEpoch, epoch, body)); }
public static void ForceStart(this OrbitDriver driver) { if (!driver.Ready()) { OrbitDriverStart.Invoke(driver, null); } }
public static void Graphical(OrbitDriver currentlyEditing, double inclination, double eccentricity, double periapsis, double longitudeAscendingNode, double argumentOfPeriapsis, double meanAnomaly, double epoch) { var body = currentlyEditing.orbit.referenceBody; var soi = body.Soi(); var ratio = soi / (body.Radius + body.atmosphereDepth + 1000); periapsis = Math.Pow(ratio, periapsis) / ratio; periapsis *= soi; eccentricity *= Math.PI / 2 - 0.001; eccentricity = Math.Tan(eccentricity); var semimajor = periapsis / (1 - eccentricity); if (semimajor < 0) { meanAnomaly -= 0.5; meanAnomaly *= eccentricity * 4; // 4 is arbitrary constant } inclination *= 360; longitudeAscendingNode *= 360; argumentOfPeriapsis *= 360; meanAnomaly *= 2 * Math.PI; SetOrbit(currentlyEditing, CreateOrbit(inclination, eccentricity, semimajor, longitudeAscendingNode, argumentOfPeriapsis, meanAnomaly, epoch, body)); }
public static void GetSimple(OrbitDriver currentlyEditing, out double altitude, out CelestialBody body) { const int min = 1000; const int defaultAlt = 100000; body = currentlyEditing.orbit.referenceBody; altitude = currentlyEditing.orbit.semiMajorAxis - body.Radius; if (altitude > min) { return; } if (currentlyEditing.vessel.Landed) { altitude = currentlyEditing.vessel.radarAltitude; return; } else { altitude = currentlyEditing.orbit.ApA; } if (altitude > min) { return; } altitude = defaultAlt; }
/// <summary> /// This is called at creation /// </summary> public void Start() { Instance = this; // This event fires when KSP is ready for mods to add toolbar buttons GameEvents.onGUIApplicationLauncherReady.Add(AddLauncher); // This event fires when KSP wants mods to remove their toolbar buttons GameEvents.onGUIApplicationLauncherDestroyed.Add(RemoveLauncher); // This event fires when switching focus in the tracking station GameEvents.onPlanetariumTargetChanged.Add(TrackingStationTargetChanged); // Reset the view when we take off or land, etc. GameEvents.onVesselSituationChange.Add(OnSituationChanged); // This event fires on SOI change if (FlightGlobals.ActiveVessel != null) { VesselMode = true; OrbitDriver orbDrv = FlightGlobals.ActiveVessel.GetOrbitDriver(); orbDrv.OnReferenceBodyChange += SOIChanged; } }
private static void TrackRigidbody(OrbitDriver driver, CelestialBody refBody, double fdtOffset, ref double updateUT) { updateUT = Planetarium.GetUniversalTime(); if (driver.vessel != null) { driver.pos = (driver.vessel.CoMD - driver.referenceBody.position).xzy; } if (driver.vessel != null && driver.vessel.rootPart != null && driver.vessel.rootPart.rb != null) // && !driver.vessel.rootPart.rb.isKinematic { updateUT += fdtOffset; driver.vel = driver.vessel.velocityD.xzy + driver.orbit.GetRotFrameVelAtPos(driver.referenceBody, driver.pos); } else if (driver.updateMode == OrbitDriver.UpdateMode.IDLE) { driver.vel = driver.orbit.GetRotFrameVel(driver.referenceBody); } if (refBody != driver.referenceBody) { if (driver.vessel != null) { driver.pos = (driver.vessel.CoMD - refBody.position).xzy; } driver.vel = driver.vel + (driver.referenceBody.GetFrameVel() - refBody.GetFrameVel()); } driver.lastTrackUT = updateUT; //Do not call UpdateFromStateVectors as that would update the orbit data BASED on the current vessel position //driver.orbit.UpdateFromStateVectors(driver.pos, driver.vel, refBody, updateUT); //driver.pos.Swizzle(); //driver.vel.Swizzle(); }
public static void GetGraphical(OrbitDriver currentlyEditing, out double inclination, out double eccentricity, out double periapsis, out double longitudeAscendingNode, out double argumentOfPeriapsis, out double meanAnomaly, out double epoch) { inclination = currentlyEditing.orbit.inclination / 360; inclination = inclination.Mod(1); longitudeAscendingNode = currentlyEditing.orbit.LAN / 360; longitudeAscendingNode = longitudeAscendingNode.Mod(1); argumentOfPeriapsis = currentlyEditing.orbit.argumentOfPeriapsis / 360; argumentOfPeriapsis = argumentOfPeriapsis.Mod(1); var eTemp = Math.Atan(currentlyEditing.orbit.eccentricity); eccentricity = eTemp / (Math.PI / 2 - 0.001); var soi = currentlyEditing.orbit.referenceBody.Soi(); var ratio = soi / (currentlyEditing.orbit.referenceBody.Radius + currentlyEditing.orbit.referenceBody.atmosphereDepth + 1000); var semimajor = currentlyEditing.orbit.semiMajorAxis * (1 - currentlyEditing.orbit.eccentricity); semimajor /= soi; semimajor *= ratio; semimajor = Math.Log(semimajor, ratio); periapsis = semimajor; meanAnomaly = currentlyEditing.orbit.meanAnomalyAtEpoch; meanAnomaly /= (2 * Math.PI); if (currentlyEditing.orbit.semiMajorAxis < 0) { meanAnomaly /= currentlyEditing.orbit.eccentricity * 4; meanAnomaly += 0.5; } epoch = currentlyEditing.orbit.epoch; }
private static void HardsetOrbit(OrbitDriver orbitDriver, Orbit newOrbit) { Log.Info("HardsetOrbit"); var orbit = orbitDriver.orbit; orbit.inclination = newOrbit.inclination; orbit.eccentricity = newOrbit.eccentricity; orbit.semiMajorAxis = newOrbit.semiMajorAxis; orbit.LAN = newOrbit.LAN; orbit.argumentOfPeriapsis = newOrbit.argumentOfPeriapsis; orbit.meanAnomalyAtEpoch = newOrbit.meanAnomalyAtEpoch; orbit.epoch = newOrbit.epoch; orbit.referenceBody = newOrbit.referenceBody; orbit.Init(); orbit.UpdateFromUT(Planetarium.GetUniversalTime()); if (orbit.referenceBody != newOrbit.referenceBody) { if (orbitDriver.OnReferenceBodyChange != null) { orbitDriver.OnReferenceBodyChange(newOrbit.referenceBody); } } RateLimitedLogger.Log(HardsetOrbitLogObject, string.Format("Orbit \"{0}\" changed to: inc={1} ecc={2} sma={3} lan={4} argpe={5} mep={6} epoch={7} refbody={8}", orbitDriver.OrbitDriverToString(), orbit.inclination, orbit.eccentricity, orbit.semiMajorAxis, orbit.LAN, orbit.argumentOfPeriapsis, orbit.meanAnomalyAtEpoch, orbit.epoch, orbit.referenceBody.CbToString())); }
/// <summary> /// This is called at creation /// </summary> public void Start() { // This event fires when KSP is ready for mods to add toolbar buttons GameEvents.onGUIApplicationLauncherReady.Add(AddLauncher); // This event fires when KSP wants mods to remove their toolbar buttons GameEvents.onGUIApplicationLauncherDestroyed.Add(RemoveLauncher); // This event fires when switching focus in the tracking station GameEvents.onPlanetariumTargetChanged.Add(TrackingStationTargetChanged); // Reset the view when we take off or land, etc. GameEvents.onVesselSituationChange.Add(OnSituationChanged); // Save window position before Unity pre-emptively destroys it GameEvents.onGameSceneSwitchRequested.Add(BeforeSceneChange); // Reset the view when craft changes GameEvents.onVesselStandardModification.Add(OnVesselStandardModification); // Recalculate model when delta V numbers are updated GameEvents.onDeltaVCalcsCompleted.Add(OnDeltaVCalcsCompleted); // This event fires on SOI change if (FlightGlobals.ActiveVessel != null) { VesselMode = true; OrbitDriver orbDrv = FlightGlobals.ActiveVessel.GetOrbitDriver(); orbDrv.OnReferenceBodyChange += SOIChanged; } }
/// <summary> /// Old school style override of PatchedConics.CheckEncounter, set up in Start and reset at destroy. /// We prevent any encounter with our starting body, and otherwise hand off to the default implementation. /// </summary> /// <param name="p">The patch currently being analyzed</param> /// <param name="nextPatch">The next patch to be analyzed</param> /// <param name="startEpoch">The time when the vessel reaches p</param> /// <param name="sec">The driver of the orbit to check for an encounter; this is the only parameter that we actually use here rather than passing along to the default implementation</param> /// <param name="targetBody">The user's currently selected target</param> /// <param name="pars">Stuff that controls how the solver works</param> /// <param name="logErrors">true to print things to the log, false otherwise</param> /// <returns> /// true if encounter found, false otherwise (or if one would have been found for our starting body) /// </returns> private bool MyCheckEncounter( Orbit p, Orbit nextPatch, double startEpoch, OrbitDriver sec, CelestialBody targetBody, PatchedConics.SolverParameters pars, bool logErrors = true) { // Suppress encounters with our starting body, because it makes the solver put NaN orbits in the flight plan return(sec?.celestialBody == editingNode?.origin ? false : originalCheckEncounter(p, nextPatch, startEpoch, sec, targetBody, pars, logErrors)); }
private static void HardsetOrbit(OrbitDriver orbitDriver, Orbit newOrbit) { var orbit = orbitDriver.orbit; HardsetOrbit(orbit, newOrbit); if (orbit.referenceBody != newOrbit.referenceBody) { orbitDriver.OnReferenceBodyChange?.Invoke(newOrbit.referenceBody); } }
public static void Rendezvous(OrbitDriver currentlyEditing, double leadTime, Vessel target) { SetOrbit(currentlyEditing, CreateOrbit( target.orbit.inclination, target.orbit.eccentricity, target.orbit.semiMajorAxis, target.orbit.LAN, target.orbit.argumentOfPeriapsis, target.orbit.meanAnomalyAtEpoch, target.orbit.epoch - leadTime, target.orbit.referenceBody)); }
private static void UpdateOrbit(OrbitDriver driver, bool offset, ref bool ready, ref double fdtLast, ref bool isHyperbolic) { if (!ready) { return; } driver.lastMode = driver.updateMode; //Always call updateFromParameters so the vessel is positioned based on the orbital data if ((VesselPositionSystem.Singleton.VesselHavePositionUpdatesQueued(driver.vessel.id) && driver.updateMode == OrbitDriver.UpdateMode.TRACK_Phys) || driver.updateMode == OrbitDriver.UpdateMode.UPDATE) { driver.updateFromParameters(); if (driver.vessel) { driver.CheckDominantBody(driver.referenceBody.position + driver.pos); } } if (driver.vessel && driver.vessel.rootPart && driver.vessel.rootPart.rb) { if (!offset) { fdtLast = 0; } if (!driver.CheckDominantBody(driver.vessel.CoMD)) { driver.TrackRigidbody(driver.referenceBody, -fdtLast); } } fdtLast = (double)TimeWarp.fixedDeltaTime; if (isHyperbolic && driver.orbit.eccentricity < 1) { isHyperbolic = false; if (driver.vessel != null) { GameEvents.onVesselOrbitClosed.Fire(driver.vessel); } } if (!isHyperbolic && driver.orbit.eccentricity > 1) { isHyperbolic = true; if (driver.vessel != null) { GameEvents.onVesselOrbitEscaped.Fire(driver.vessel); } } if (driver.drawOrbit) { driver.orbit.DrawOrbit(); } }
private static void PostfixTrackRigidbody(OrbitDriver __instance, bool __state) { if (MainSystem.NetworkState < ClientState.Connected) { return; } if (__instance.vessel && __instance.vessel.rootPart && __instance.vessel.rootPart.rb && !__instance.vessel.rootPart.rb.isKinematic && __state) { __instance.vessel.rootPart.rb.isKinematic = true; } }
public static void GetComplex(OrbitDriver currentlyEditing, out double inclination, out double eccentricity, out double semiMajorAxis, out double longitudeAscendingNode, out double argumentOfPeriapsis, out double meanAnomalyAtEpoch, out double epoch, out CelestialBody body) { inclination = currentlyEditing.orbit.inclination; eccentricity = currentlyEditing.orbit.eccentricity; semiMajorAxis = currentlyEditing.orbit.semiMajorAxis; longitudeAscendingNode = currentlyEditing.orbit.LAN; argumentOfPeriapsis = currentlyEditing.orbit.argumentOfPeriapsis; meanAnomalyAtEpoch = currentlyEditing.orbit.meanAnomalyAtEpoch; epoch = currentlyEditing.orbit.epoch; body = currentlyEditing.orbit.referenceBody; }
public static void DynamicSetOrbit(this OrbitDriver orbit, Orbit newOrbit) { Log.Info("DynamicSetOrbit"); var vessel = orbit.vessel; if (vessel != null) { vessel.SetOrbit(newOrbit); } else { HardsetOrbit(orbit, newOrbit); } }
private static bool PrefixUpdateOrbit(OrbitDriver __instance, bool offset) { if (MainSystem.NetworkState < ClientState.Connected) { return(true); } if (SettingsSystem.CurrentSettings.OverrideIntegrator && __instance?.vessel != null) { return(LockSystem.LockQuery.UpdateLockBelongsToPlayer(__instance.vessel.id, SettingsSystem.CurrentSettings.PlayerName)); } return(true); }
/// <summary> /// This is called at destroy /// </summary> public void OnDisable() { // Tear down the window (saves the position as a side effect) HideMainWindow(false); // Save the persistent attributes to our settings file Settings.Instance.Save(); if (loader != null) { // Tell the loader we don't need data anymore; // prevents new threads from starting loader.OnDisplayClosed(); // Clean up the timer and thread loader.Dispose(); } // The "dead" copy of our object will re-add itself if we don't unsubscribe to this! GameEvents.onGUIApplicationLauncherReady.Remove(AddLauncher); // This event fires when KSP wants mods to remove their toolbar buttons GameEvents.onGUIApplicationLauncherDestroyed.Remove(RemoveLauncher); // This event fires when switching focus in the tracking station GameEvents.onPlanetariumTargetChanged.Remove(TrackingStationTargetChanged); // Reset the view when we take off or land, etc. GameEvents.onVesselSituationChange.Remove(OnSituationChanged); // Save window position before Unity pre-emptively destroys it GameEvents.onGameSceneSwitchRequested.Remove(BeforeSceneChange); // Reset the view when craft changes GameEvents.onVesselStandardModification.Remove(OnVesselStandardModification); // Recalculate model when delta V numbers are updated GameEvents.onDeltaVCalcsCompleted.Remove(OnDeltaVCalcsCompleted); // The launcher destroyed event doesn't always fire when we need it (?) RemoveLauncher(); // This event fires on SOI change if (VesselMode) { OrbitDriver orbDrv = FlightGlobals.ActiveVessel.GetOrbitDriver(); orbDrv.OnReferenceBodyChange -= SOIChanged; } }
private static bool PrefixUpdateOrbit(OrbitDriver __instance, bool offset, ref bool ___ready, ref double ___fdtLast, ref bool ___isHyperbolic) { if (MainSystem.NetworkState < ClientState.Connected) { return(true); } if (__instance.vessel == null) { return(true); } UpdateOrbit(__instance, offset, ref ___ready, ref ___fdtLast, ref ___isHyperbolic); return(false); }
private static bool PrefixUpdateFromParameters(OrbitDriver __instance, ref double ___updateUT) { if (MainSystem.NetworkState < ClientState.Connected) { return(true); } if (__instance.vessel == null) { return(true); } UpdateFromParameters(__instance, ref ___updateUT); return(false); }
private static bool PrefixTrackRigidbody(OrbitDriver __instance, CelestialBody refBody, double fdtOffset, ref double ___updateUT) { if (MainSystem.NetworkState < ClientState.Connected) { return(true); } if (__instance.vessel == null) { return(true); } TrackRigidbody(__instance, refBody, fdtOffset, ref ___updateUT); return(false); }
private void MakeOrbit(OrbitDriver driver, CelestialBody reference) { Debug.Log("Jumping to " + partnerBody); CelestialBody oldBody = driver.referenceBody; FlightGlobals.overrideOrbit = true; FlightGlobals.fetch.Invoke("disableOverride", 2f); driver.vessel.Landed = false; driver.vessel.Splashed = false; driver.vessel.SetLandedAt(""); driver.vessel.KillPermanentGroundContact(); driver.vessel.ResetGroundContact(); FlightGlobals.currentMainBody = reference; OrbitPhysicsManager.SetDominantBody(reference); // Pack vessels foreach (Vessel vessel in FlightGlobals.Vessels) { if (!vessel.packed) { vessel.GoOnRails(); } } // Disable inverse rotation foreach (CelestialBody body in PSystemManager.Instance.localBodies) { body.inverseRotation = false; } driver.orbit.referenceBody = reference; driver.updateFromParameters(); // Finalize Vessel Movement CollisionEnhancer.bypass = true; FloatingOrigin.SetOffset(driver.vessel.transform.position); OrbitPhysicsManager.CheckReferenceFrame(); OrbitPhysicsManager.HoldVesselUnpack(10); if (reference != oldBody) { GameEvents.onVesselSOIChanged.Fire( new GameEvents.HostedFromToAction <Vessel, CelestialBody>(driver.vessel, oldBody, reference)); } driver.vessel.IgnoreGForces(20); }
private static void UpdateFromParameters(OrbitDriver driver, ref double updateUT) { updateUT = Planetarium.GetUniversalTime(); driver.orbit.UpdateFromUT(updateUT); driver.pos = driver.orbit.pos; driver.vel = driver.orbit.vel; driver.pos.Swizzle(); driver.vel.Swizzle(); if (double.IsNaN(driver.pos.x)) { MonoBehaviour.print(string.Concat(new object[] { "ObT : ", driver.orbit.ObT, "\nM : ", driver.orbit.meanAnomaly, "\nE : ", driver.orbit.eccentricAnomaly, "\nV : ", driver.orbit.trueAnomaly, "\nRadius: ", driver.orbit.radius, "\nvel: ", driver.vel.ToString(), "\nAN: ", driver.orbit.an.ToString(), "\nperiod: ", driver.orbit.period, "\n" })); if (driver.vessel) { Debug.LogWarning(string.Concat("[LMP - OrbitDriver Warning!]: ", driver.vessel.vesselName, " had a NaN Orbit and was removed.")); driver.vessel.Unload(); VesselRemoveSystem.Singleton.MessageSender.SendVesselRemove(driver.vessel.id, true); VesselRemoveSystem.Singleton.KillVessel(driver.vessel.id, true, "Corrupt vessel orbit"); return; } } if (driver.reverse) { driver.referenceBody.position = (!driver.celestialBody ? (Vector3d)driver.driverTransform.position : driver.celestialBody.position) - driver.pos; } else if (driver.vessel) { if (VesselPositionSystem.Singleton.VesselHavePositionUpdatesQueued(driver.vessel.id)) { //DO NOT update the vessel position here. The VesselPositioningSystem takes care of that return; } else { Vector3d vector3d = driver.driverTransform.rotation * driver.vessel.localCoM; driver.vessel.SetPosition((driver.referenceBody.position + driver.pos) - vector3d); } } else if (!driver.celestialBody) { driver.driverTransform.position = driver.referenceBody.position + driver.pos; } else { driver.celestialBody.position = driver.referenceBody.position + driver.pos; } }
private bool MouseOverTargetable(ITargetable targetable) { bool result = false; OrbitDriver targetDriver = targetable.GetOrbitDriver(); OrbitRenderer.OrbitCastHit rendererHit = default(OrbitRenderer.OrbitCastHit); if (targetDriver != null && targetDriver.Renderer.OrbitCast(Input.mousePosition, out rendererHit)) { result = true; _hitOrbit = rendererHit.or.driver.orbit; _hitScreenPoint = rendererHit.GetScreenSpacePoint(); _hitUT = rendererHit.UTatTA; } return(result); }
public static void DynamicSetOrbit(this OrbitDriver orbit, Orbit newOrbit) { var vessel = orbit.vessel; var body = orbit.celestialBody; if (vessel != null) { vessel.SetOrbit(newOrbit); } else if (body != null) { body.SetOrbit(newOrbit); } else { HardsetOrbit(orbit, newOrbit); } }
public override void Cache() { if (!IsSun()) { orbit = planet.GetOrbit(); orbitData = OrbitDataFromOrbit(orbit); orbitDriver = planet.orbitDriver; referenceBody = orbit.referenceBody; referenceBodyData = solarSystem.GetPlanetByCelestialBody(referenceBody); } else { referenceBody = solarSystem.sun; referenceBodyData = solarSystem.sunData; } gravity = planet.gravParameter; sphereOfInfluence = planet.sphereOfInfluence; }
private static void HardsetOrbit(OrbitDriver orbitDriver, Orbit newOrbit) { var orbit = orbitDriver.orbit; orbit.inclination = newOrbit.inclination; orbit.eccentricity = newOrbit.eccentricity; orbit.semiMajorAxis = newOrbit.semiMajorAxis; orbit.LAN = newOrbit.LAN; orbit.argumentOfPeriapsis = newOrbit.argumentOfPeriapsis; orbit.meanAnomalyAtEpoch = newOrbit.meanAnomalyAtEpoch; orbit.epoch = newOrbit.epoch; orbit.referenceBody = newOrbit.referenceBody; orbit.Init(); orbit.UpdateFromUT(Planetarium.GetUniversalTime()); if (orbit.referenceBody != newOrbit.referenceBody) { orbitDriver.OnReferenceBodyChange?.Invoke(newOrbit.referenceBody); } }
public static string OrbitDriverToString(this OrbitDriver driver) { if (driver == null) { return(null); } if (driver.celestialBody != null) { return(driver.celestialBody.bodyName); } if (driver.vessel != null) { return(driver.vessel.VesselToString()); } if (!string.IsNullOrEmpty(driver.name)) { return(driver.name); } return("Unknown"); }
private static void HardsetOrbit(OrbitDriver orbitDriver, Orbit newOrbit) { var orbit = orbitDriver.orbit; orbit.inclination = newOrbit.inclination; orbit.eccentricity = newOrbit.eccentricity; orbit.semiMajorAxis = newOrbit.semiMajorAxis; orbit.LAN = newOrbit.LAN; orbit.argumentOfPeriapsis = newOrbit.argumentOfPeriapsis; orbit.meanAnomalyAtEpoch = newOrbit.meanAnomalyAtEpoch; orbit.epoch = newOrbit.epoch; orbit.referenceBody = newOrbit.referenceBody; orbit.Init(); orbit.UpdateFromUT(Planetarium.GetUniversalTime()); if (orbit.referenceBody != newOrbit.referenceBody) { orbitDriver.OnReferenceBodyChange?.Invoke(newOrbit.referenceBody); } RateLimitedLogger.Log(HardsetOrbitLogObject, $"Orbit \"{orbitDriver.OrbitDriverToString()}\" changed to: inc={orbit.inclination} ecc={orbit.eccentricity} sma={orbit.semiMajorAxis} lan={orbit.LAN} argpe={orbit.argumentOfPeriapsis} mep={orbit.meanAnomalyAtEpoch} epoch={orbit.epoch} refbody={orbit.referenceBody.CbToString()}"); }
public static void Simple(OrbitDriver currentlyEditing, double altitude, CelestialBody body) { SetOrbit(currentlyEditing, CreateOrbit(0 , 0, altitude + body.Radius, 0, 0, 0, 0, body)); }
// Show exit orbital predictions private void showExitOrbit(Vessel near, Vessel far, string model) { // Recenter map, save previous state. wasInMapView = MapView.MapIsEnabled; if (!MapView.MapIsEnabled) MapView.EnterMapView(); print("Finding target."); MapObject farTarget = findVesselBody(far); if (farTarget != null) MapView.MapCamera.SetTarget(farTarget); // Initialize projection stuff. print("Beginning orbital projection."); Vector3d exitTraj = getJumpOffset(near, far, model); oPredictDriver = new OrbitDriver(); oPredictDriver.orbit = new Orbit(); oPredictDriver.orbit.referenceBody = far.mainBody; oPredictDriver.referenceBody = far.mainBody; oPredictDriver.upperCamVsSmaRatio = 999999; // Took forever to figure this out - this sets at what zoom level the orbit appears. Was causing it not to appear at small bodies. oPredictDriver.lowerCamVsSmaRatio = 0.0001f; oPredictDriver.orbit.UpdateFromStateVectors(far.orbit.pos, exitTraj, far.mainBody, Planetarium.GetUniversalTime()); oPredictDriver.orbit.Init(); Vector3d p = oPredictDriver.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); Vector3d v = oPredictDriver.orbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()); oPredictDriver.orbit.h = Vector3d.Cross(p, v); oPredict = MapView.MapCamera.gameObject.AddComponent<OrbitRenderer>(); oPredict.upperCamVsSmaRatio = 999999; oPredict.lowerCamVsSmaRatio = 0.0001f; oPredict.celestialBody = far.mainBody; oPredict.driver = oPredictDriver; oPredictDriver.Renderer = oPredict; // Splash some color on it. print("Displaying orbital projection."); oPredict.driver.drawOrbit = true; oPredict.driver.orbitColor = Color.red; oPredict.orbitColor = Color.red; oPredict.drawIcons = OrbitRenderer.DrawIcons.OBJ_PE_AP; oPredict.drawMode = OrbitRenderer.DrawMode.REDRAW_AND_RECALCULATE; // Directional indicator. oDirObj = new GameObject("Indicator"); oDirObj.layer = 10; // Map layer! oDirection = oDirObj.AddComponent<LineRenderer>(); oDirection.useWorldSpace = false; oOrigin = null; foreach (Transform sstr in ScaledSpace.Instance.scaledSpaceTransforms) { if (sstr.name == far.mainBody.name) { oOrigin = sstr; print("Found origin: " + sstr.name); break; } } oDirection.transform.parent = oOrigin; oDirection.transform.position = ScaledSpace.LocalToScaledSpace(far.transform.position); oDirection.material = new Material(Shader.Find("Particles/Additive")); oDirection.SetColors(Color.clear, Color.red); oDirection.SetWidth(20.0f, 0.01f); oDirection.SetVertexCount(2); oDirection.SetPosition(0, Vector3d.zero + exitTraj.xzy.normalized * 10); oDirection.SetPosition(1, exitTraj.xzy.normalized * 50); oDirection.enabled = true; // */ }
public static void SetNewOrbit(OrbitDriver driver, Orbit oldOrbit) { var orbit = driver.orbit; orbit.inclination = driver.orbit.inclination; orbit.eccentricity = driver.orbit.eccentricity; orbit.semiMajorAxis = (driver.orbit.semiMajorAxis - DecayValue); orbit.LAN = driver.orbit.LAN; orbit.argumentOfPeriapsis = driver.orbit.argumentOfPeriapsis; orbit.meanAnomalyAtEpoch = driver.orbit.meanAnomalyAtEpoch; orbit.epoch = driver.orbit.epoch; orbit.referenceBody = driver.orbit.referenceBody; orbit.Init(); orbit.UpdateFromUT(Planetarium.GetUniversalTime()); if (orbit.referenceBody != driver.orbit.referenceBody) { if (driver.OnReferenceBodyChange != null) driver.OnReferenceBodyChange(driver.orbit.referenceBody); } }
public static void StationKeeping(OrbitDriver driver, Vessel vessel) { // Background resource processing bool ResourceFound = true; double MaxDecayInfluence = vessel.orbitDriver.orbit.referenceBody.Radius * 10; double AtmosphereMultiplier; if (vessel.orbitDriver.orbit.referenceBody.atmosphere) { AtmosphereMultiplier = vessel.orbitDriver.orbit.referenceBody.atmospherePressureSeaLevel / 101.325; } else { AtmosphereMultiplier = 0.5; } if (vessel.orbitDriver.orbit.semiMajorAxis + 50 < MaxDecayInfluence) { double Lambda = 0.000000000133913 * UI.DifficultySetting; double Sigma = MaxDecayInfluence - vessel.orbitDriver.orbit.altitude; DecayValue = (double)TimeWarp.CurrentRate * Sigma * vessel.orbitDriver.orbit.referenceBody.GeeASL * AtmosphereMultiplier * Lambda; } else { DecayValue = 0; } foreach (Part part in vessel.Parts) { if (part.Resources.Count != 0) { foreach (PartResource resource in part.Resources) { if (resource.name == "ElectricCharge" && resource.amount > DecayValue) { ResourceFound = true; part.RequestResource("ElectricCharge", DecayValue); VesselData.CanStationKeep.Remove(vessel.id); VesselData.CanStationKeep.Add(vessel.id, true); break; } } } } if (ResourceFound == false) { ScreenMessages.PostScreenMessage("Warning: " + vessel.name + " has run out of Mono-Propellant, stationkeeping stopped"); VesselData.CanStationKeep.Remove(vessel.id); VesselData.CanStationKeep.Add(vessel.id, false); } }
public static void CalculateOrbit(Vessel vessel, Orbit oldOrbit, OrbitDriver driver) { VesselDied = false; if (!VesselData.Message.ContainsKey(vessel.id)) { VesselData.Message.Add(vessel.id, false); VesselData.DisplayedMessage = false; } else { VesselData.Message.TryGetValue(vessel.id, out VesselData.DisplayedMessage); } vessel.GoOnRails(); var oldBody = vessel.orbitDriver.orbit.referenceBody; // The ISS decays at about 2km/month = 2000/30*24*60*60 == 7.7x10^-4 m/s double BodyGravityConstant = vessel.orbitDriver.orbit.referenceBody.GeeASL; double AtmosphereMultiplier; double MaxDecayInfluence = vessel.orbitDriver.orbit.referenceBody.Radius * 10; if (vessel.orbitDriver.orbit.referenceBody.atmosphere) { AtmosphereMultiplier = vessel.orbitDriver.orbit.referenceBody.atmospherePressureSeaLevel / 101.325; } else { AtmosphereMultiplier = 0.5; } if (vessel.orbitDriver.orbit.semiMajorAxis + 50 < MaxDecayInfluence ) { double Lambda = 0.000000000133913 * UI.DifficultySetting; //0.000000000133913; double Sigma = MaxDecayInfluence - vessel.orbitDriver.orbit.altitude; DecayValue = (double)TimeWarp.CurrentRate * Sigma * BodyGravityConstant * AtmosphereMultiplier * Lambda; if (vessel.orbitDriver.orbit.referenceBody.atmosphere) { if (vessel.orbitDriver.orbit.PeA < vessel.orbitDriver.orbit.referenceBody.atmosphereDepth) { DecayValue = DecayValue * (Math.Pow(Math.E, vessel.orbitDriver.orbit.referenceBody.atmosphereDepth - vessel.orbitDriver.orbit.PeA)); // Have it increase alot more as we enter the hard atmosphere } //EstimatedTimeUntilDeorbit = (float)(vessel.orbitDriver.orbit.altitude - (float)vessel.orbitDriver.orbit.referenceBody.atmosphereDepth) / (float)DecayValue; MaxDecayValue = ((vessel.orbitDriver.orbit.referenceBody.Radius + vessel.orbitDriver.orbit.referenceBody.atmosphereDepth) * BodyGravityConstant * AtmosphereMultiplier * Lambda); EstimatedTimeUntilDeorbit = ((float)(vessel.orbitDriver.orbit.semiMajorAxis - (float)vessel.orbitDriver.orbit.referenceBody.atmosphereDepth)) / (float)MaxDecayValue; // EstimatedTimeUntilDeorbit = (float)(vessel.orbitDriver.orbit.PeA - (((vessel.orbitDriver.referenceBody.atmosphereDepth)/((MaxDecayValue+DecayValue)/2) - vessel.orbitDriver.orbit.PeA)) *((MaxDecayValue + DecayValue) / 2)); } else { //EstimatedTimeUntilDeorbit = (float)(vessel.orbitDriver.orbit.altitude - 100) / (float)DecayValue; MaxDecayValue = ((vessel.orbitDriver.orbit.referenceBody.Radius + 100) * BodyGravityConstant * AtmosphereMultiplier * Lambda); EstimatedTimeUntilDeorbit = ((float)(vessel.orbitDriver.orbit.semiMajorAxis - (float)vessel.orbitDriver.orbit.referenceBody.atmosphereDepth)) / (float)MaxDecayValue; } if (VesselData.DecayTimes.ContainsKey(vessel.id)) { VesselData.DecayTimes.Remove(vessel.id); VesselData.DecayTimes.Add(vessel.id, EstimatedTimeUntilDeorbit); } else { VesselData.DecayTimes.Add(vessel.id, EstimatedTimeUntilDeorbit); } // print(vessel.name + " Semi major axis reduced by: " + (DecayValue)); } else { DecayValue = 0; if (VesselData.DecayTimes.ContainsKey(vessel.id)) { VesselData.DecayTimes.Remove(vessel.id); VesselData.DecayTimes.Add(vessel.id, 0.5f); } else { VesselData.DecayTimes.Add(vessel.id, 0.5f); } } if (VesselDied == false) // Just Incase the vessel is destroyed part way though the check. { if (vessel.orbitDriver.orbit.referenceBody.GetInstanceID() != 0 || vessel.orbitDriver.orbit.semiMajorAxis > vessel.orbitDriver.orbit.referenceBody.Radius + 5) { SetNewOrbit(driver, oldOrbit); } } if (vessel.orbitDriver.orbit.referenceBody.atmosphere) // Big problem ( Jool, Eve, Duna, Kerbin, Laythe) { if (vessel.orbitDriver.orbit.semiMajorAxis < vessel.orbitDriver.orbit.referenceBody.Radius + vessel.orbitDriver.referenceBody.atmosphereDepth + 500) { FlightDriver.SetPause(true); TimeWarp.SetRate(1, true); FlightDriver.SetPause(false); print("Warning: " + vessel.name + " is approaching " + oldOrbit.referenceBody.name + "'s hard atmosphere"); ScreenMessages.PostScreenMessage("Warning: " + vessel.name + " is approaching " + oldOrbit.referenceBody.name + "'s hard atmosphere"); VesselData.Message.Remove(vessel.id); VesselData.Message.Add(vessel.id, true); } if (vessel.orbitDriver.orbit.semiMajorAxis < vessel.orbitDriver.orbit.referenceBody.Radius + vessel.orbitDriver.referenceBody.atmosphereDepth + 5) { VesselDied = true; } } else // Moon Smaller Problem { if (vessel.orbitDriver.orbit.semiMajorAxis < vessel.orbitDriver.orbit.referenceBody.Radius + 5000) { FlightDriver.SetPause(true); TimeWarp.SetRate(1, true); FlightDriver.SetPause(false); print("Warning: " + vessel.name + " is approaching " + oldOrbit.referenceBody.name + "'s surface"); ScreenMessages.PostScreenMessage("Warning: " + vessel.name + " is approaching " + oldOrbit.referenceBody.name + "'s surface"); VesselData.Message.Remove(vessel.id); VesselData.Message.Add(vessel.id, true); } if (vessel.orbitDriver.orbit.semiMajorAxis < vessel.orbitDriver.orbit.referenceBody.Radius + 100) { VesselDied = true; } } if (VesselDied == false) { vessel.orbitDriver.pos = vessel.orbit.pos.xzy; vessel.orbitDriver.vel = vessel.orbit.vel; var newBody = vessel.orbitDriver.orbit.referenceBody; if (newBody != oldBody) { var evnt = new GameEvents.HostedFromToAction<Vessel, CelestialBody>(vessel, oldBody, newBody); GameEvents.onVesselSOIChanged.Fire(evnt); } } if (VesselDied == true) { vessel.Die(); VesselData.CanStationKeep.Remove(vessel.id); VesselData.DecayTimes.Remove(vessel.id); VesselData.DisplayedDecayTimes.Remove(vessel); VesselData.StationKeeping.Remove(vessel.id); } }
private void setup() { generator = new System.Random(this.Root.MissionSeed); iconWaypoints = new List<Waypoint>(); for (int cardinals = 0; cardinals < 4; cardinals++) { bool addedWaypoint = false; switch (cardinals) { case 0: if (HighLogic.LoadedSceneIsFlight) { iconWaypoints.Add(new Waypoint()); iconWaypoints[iconWaypoints.Count - 1].waypointType = WaypointType.ASCENDINGNODE; addedWaypoint = true; } break; case 1: if (HighLogic.LoadedSceneIsFlight) { iconWaypoints.Add(new Waypoint()); iconWaypoints[iconWaypoints.Count - 1].waypointType = WaypointType.DESCENDINGNODE; addedWaypoint = true; } break; case 2: iconWaypoints.Add(new Waypoint()); iconWaypoints[iconWaypoints.Count - 1].waypointType = WaypointType.APOAPSIS; addedWaypoint = true; break; case 3: iconWaypoints.Add(new Waypoint()); iconWaypoints[iconWaypoints.Count - 1].waypointType = WaypointType.PERIAPSIS; addedWaypoint = true; break; } if (addedWaypoint) { iconWaypoints[iconWaypoints.Count - 1].celestialName = targetBody.GetName(); iconWaypoints[iconWaypoints.Count - 1].isOnSurface = false; iconWaypoints[iconWaypoints.Count - 1].isNavigatable = false; iconWaypoints[iconWaypoints.Count - 1].seed = Root.MissionSeed; WaypointManager.AddWaypoint(iconWaypoints[iconWaypoints.Count - 1]); } } for (int x = 0; x < numSpinners; x++) { iconWaypoints.Add(new Waypoint()); iconWaypoints[iconWaypoints.Count - 1].celestialName = targetBody.GetName(); iconWaypoints[iconWaypoints.Count - 1].waypointType = WaypointType.ORBITAL; iconWaypoints[iconWaypoints.Count - 1].isOnSurface = false; iconWaypoints[iconWaypoints.Count - 1].isNavigatable = false; iconWaypoints[iconWaypoints.Count - 1].seed = Root.MissionSeed; WaypointManager.AddWaypoint(iconWaypoints[iconWaypoints.Count - 1]); } orbitDriver = new OrbitDriver(); orbitDriver.orbit = new Orbit(); orbitDriver.orbit.referenceBody = targetBody; orbitDriver.orbit.semiMajorAxis = sma; orbitDriver.orbit.eccentricity = eccentricity; orbitDriver.orbit.argumentOfPeriapsis = argumentOfPeriapsis; orbitDriver.orbit.inclination = inclination; orbitDriver.orbit.LAN = lan; orbitDriver.orbit.meanAnomalyAtEpoch = meanAnomalyAtEpoch; orbitDriver.orbit.epoch = epoch; orbitDriver.orbit.Init(); //The orbit needs to be post processed in an appropriate scene, or it will be useless. Util.PostProcessOrbit(ref orbitDriver.orbit); orbitDriver.orbitColor = WaypointManager.RandomColor(Root.MissionSeed); orbitRenderer = MapView.MapCamera.gameObject.AddComponent<OrbitRenderer>(); orbitRenderer.driver = orbitDriver; orbitRenderer.drawIcons = OrbitRenderer.DrawIcons.NONE; orbitRenderer.drawNodes = false; orbitRenderer.orbitColor = WaypointManager.RandomColor(Root.MissionSeed); setVisible(true); orbitRenderer.celestialBody = targetBody; beenSetup = true; }
private static void SetOrbit(OrbitDriver currentlyEditing, Orbit orbit) { currentlyEditing.DynamicSetOrbit(orbit); }
public static void GetSimple(OrbitDriver currentlyEditing, out double altitude, out CelestialBody body) { const int min = 1000; const int defaultAlt = 100000; body = currentlyEditing.orbit.referenceBody; altitude = currentlyEditing.orbit.semiMajorAxis - body.Radius; if (altitude > min) return; altitude = currentlyEditing.orbit.ApA; if (altitude > min) return; altitude = defaultAlt; }
public static void Velocity(OrbitDriver currentlyEditing, VelocityChangeDirection direction, double speed) { Vector3d velocity; switch (direction) { case VelocityChangeDirection.Prograde: velocity = currentlyEditing.orbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()).normalized * speed; break; case VelocityChangeDirection.Normal: velocity = currentlyEditing.orbit.GetOrbitNormal().normalized * speed; break; case VelocityChangeDirection.Radial: velocity = Vector3d.Cross(currentlyEditing.orbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()), currentlyEditing.orbit.GetOrbitNormal()).normalized * speed; break; case VelocityChangeDirection.North: var upn = currentlyEditing.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()).normalized; velocity = Vector3d.Cross(Vector3d.Cross(upn, new Vector3d(0, 0, 1)), upn) * speed; break; case VelocityChangeDirection.East: var upe = currentlyEditing.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()).normalized; velocity = Vector3d.Cross(new Vector3d(0, 0, 1), upe) * speed; break; case VelocityChangeDirection.Up: velocity = currentlyEditing.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()).normalized * speed; break; default: throw new Exception("Unknown VelChangeDir"); } var tempOrbit = currentlyEditing.orbit.Clone(); tempOrbit.UpdateFromStateVectors(currentlyEditing.orbit.pos, currentlyEditing.orbit.vel + velocity, currentlyEditing.orbit.referenceBody, Planetarium.GetUniversalTime()); SetOrbit(currentlyEditing, tempOrbit); }
public static void GetVelocity(OrbitDriver currentlyEditing, out VelocityChangeDirection direction, out double speed) { direction = VelocityChangeDirection.Prograde; speed = 0; }
private ProtoVessel syncOrbit(KMPVessel kvessel, double fromTick, ProtoVessel protovessel, double LAN) { KMPClientMain.DebugLog("updating OrbitSnapshot"); double tick = Planetarium.GetUniversalTime(); //Update orbit Planetarium.SetUniversalTime(fromTick); Vector3 orbit_pos = kvessel.translationFromBody; Vector3 orbit_vel = kvessel.worldVelocity; //Swap the y and z values of the orbital position/velocities float temp = orbit_pos.y; orbit_pos.y = orbit_pos.z; orbit_pos.z = temp; temp = orbit_vel.y; orbit_vel.y = orbit_vel.z; orbit_vel.z = temp; OrbitDriver orbitDriver = new OrbitDriver(); orbitDriver.orbit.UpdateFromStateVectors(orbit_pos, orbit_vel, kvessel.mainBody, fromTick); Orbit newOrbit = orbitDriver.orbit; newOrbit.LAN = LAN; Vessel victim = FlightGlobals.ActiveVessel; OrbitDriver oldDriver = victim.orbitDriver; victim.orbitDriver = orbitDriver; victim.patchedConicSolver.obtDriver = orbitDriver; victim.orbitDriver.UpdateOrbit(); victim.patchedConicSolver.Update(); newOrbit = victim.patchedConicSolver.orbit; if (newOrbit.referenceBody == null) newOrbit.referenceBody = FlightGlobals.Bodies.Find(b => b.name == "Sun"); if (newOrbit.EndUT > 0) { double lastEndUT = newOrbit.EndUT; while (newOrbit.EndUT > 0 && newOrbit.EndUT < tick && newOrbit.EndUT > lastEndUT && newOrbit.nextPatch != null) { KMPClientMain.DebugLog("orbit EndUT < target: " + newOrbit.EndUT + " vs " + tick); lastEndUT = newOrbit.EndUT; newOrbit = newOrbit.nextPatch; if (newOrbit.referenceBody == null) newOrbit.referenceBody = FlightGlobals.Bodies.Find(b => b.name == "Sun"); KMPClientMain.DebugLog("updated to next patch"); } } victim.patchedConicSolver.obtDriver = oldDriver; victim.orbitDriver = oldDriver; Planetarium.SetUniversalTime(tick); protovessel.orbitSnapShot = new OrbitSnapshot(newOrbit); KMPClientMain.DebugLog("OrbitSnapshot updated"); return protovessel; }
private void setup() { generator = new System.Random(this.Root.MissionSeed); iconWaypoints = new List<Waypoint>(); for (int x = 0; x < 4; x++) { iconWaypoints.Add(new Waypoint()); iconWaypoints[iconWaypoints.Count - 1].celestialName = targetBody.GetName(); iconWaypoints[iconWaypoints.Count - 1].textureName = "orbit"; iconWaypoints[iconWaypoints.Count - 1].isOrbital = true; iconWaypoints[iconWaypoints.Count - 1].seed = Root.MissionSeed; WaypointManager.AddWaypoint(iconWaypoints[iconWaypoints.Count - 1]); } orbitDriver = new OrbitDriver(); //Start with periapsis at a safe distance and a random eccentricity, weighted towards the bottom. //Derive SMA from eccentricity and desired periapsis. orbitDriver.orbit = new Orbit(); switch (this.orbitType) { case OrbitType.POLAR: setRandomOrbit(difficultyFactor, false, true); break; case OrbitType.EQUATORIAL: setRandomOrbit(difficultyFactor, true, false); break; case OrbitType.STATIONARY: setSynchronousOrbit(difficultyFactor, true, 0.0); break; case OrbitType.SYNCHRONOUS: setSynchronousOrbit(difficultyFactor, false, generator.NextDouble()*(difficultyFactor/2)); break; case OrbitType.MOLNIYA: setMolniyaOrbit(); break; case OrbitType.TUNDRA: setTundraOrbit(); break; default: setRandomOrbit(difficultyFactor, false, false); break; } orbitDriver.orbitColor = WaypointManager.RandomColor(Root.MissionSeed); orbitRenderer = MapView.MapCamera.gameObject.AddComponent<OrbitRenderer>(); orbitRenderer.driver = orbitDriver; orbitRenderer.drawIcons = OrbitRenderer.DrawIcons.NONE; orbitRenderer.drawNodes = false; orbitRenderer.orbitColor = WaypointManager.RandomColor(Root.MissionSeed); setVisible(true); orbitRenderer.celestialBody = targetBody; beenSetup = true; }