//This code draws the target distance and closest approach private void rightGauge() { ITargetable itarget = FlightGlobals.fetch.VesselTarget; if (itarget != null && itarget.GetOrbit() != null) { Vessel target = itarget.GetVessel(); //Calculate and draw the distance between active vessal and target Vector3d aPos = FlightGlobals.ActiveVessel.orbit.pos; Vector3d tPos = itarget.GetOrbit().pos; //double distance = Vector3d.Distance(tPos, aPos); double distance = SteamShip.TargetDist; drawDigits(981, 131, distance); //Draw closure light if (distance < closestRed) //red light { GUI.DrawTextureWithTexCoords(new Rect(1014f * Scale, 101f * Scale, 17f * Scale, 17f * Scale), texture, new Rect(0.5058f, 0.2625f, 0.0142f, 0.0142f)); } else if (distance < closestYellow) //yellow light { GUI.DrawTextureWithTexCoords(new Rect(1014f * Scale, 101f * Scale, 17f * Scale, 17f * Scale), texture, new Rect(0.5225f, 0.2625f, 0.0142f, 0.0142f)); } else if (distance < closestGreen) //green light { GUI.DrawTextureWithTexCoords(new Rect(1014f * Scale, 101f * Scale, 17f * Scale, 17f * Scale), texture, new Rect(0.4875f, 0.2625f, 0.0142f, 0.0142f)); } //Crunch closest distance, and display //res Result = getClosestApproach(); drawDigits(982, 197, SteamShip.ClosestApproach); drawTime(1019, 260, SteamShip.ClosestTime); //Maybe surround this gauge with a AN/DN offset? } }
/// <summary> /// Return the body to search for destinations next after the parameter. /// Essentially a wrapper around CelestialBody.referenceBody to make it /// return null for the sun instead of itself. /// </summary> /// <param name="target">Previous target we searched</param> public static CelestialBody ParentBody(ITargetable target) { if (target.GetOrbit() == null || target.GetOrbit().referenceBody == target as CelestialBody) { return(null); } else { return(target.GetOrbit().referenceBody); } }
public string findNameForOrbit(Orbit orbit, ITargetable start) { if (start.GetOrbit() == orbit || start.GetOrbit() == null) { return(start.GetName()); } else { return(findNameForOrbit(orbit, start.GetOrbit().referenceBody)); } }
private void relAsc() { if (_patch == null || _patch.referenceBody == null) { return; } //ManeuverController.maneuverLog("Rel Asc: {0}", logLevels.log, 1); ITargetable tgt = FlightGlobals.fetch.VesselTarget; if (tgt == null || tgt.GetOrbit() == null || tgt.GetOrbit().referenceBody == null) { return; } //ManeuverController.maneuverLog("Rel Asc: {0}", logLevels.log, 2); if (_patch.referenceBody != tgt.GetOrbit().referenceBody) { return; } //ManeuverController.maneuverLog("Rel Asc: {0}", logLevels.log, 3); double relAsc = ManeuverUtilities.RelAscTime(_patch, tgt); if (_patch.UTsoi > 0 && relAsc > _patch.UTsoi) { return; } else if (relAsc < Planetarium.GetUniversalTime()) { return; } else { //ManeuverController.maneuverLog("Rel Asc: {0}", logLevels.log, 4); double periods = 0; if (!double.IsNaN(_patch.period) && !double.IsInfinity(_patch.period)) { periods = (_orbitsAdded * _patch.period); } setNodeTime(relAsc + periods); } }
internal static Orbit getTargetOrbit(CelestialBody refbody) { ITargetable tgt = FlightGlobals.fetch.VesselTarget; if (tgt == null || FlightGlobals.ActiveVessel == tgt.GetVessel()) { return(null); } Orbit o = tgt.GetOrbit(); if (o.referenceBody == refbody) { return(o); } while (o.nextPatch != null) { if (o.isClosed()) { return(null); } o = o.nextPatch; if (o.referenceBody == refbody) { return(o); } } return(null); }
/// <summary> /// Update the current target. /// </summary> /// <param name="vessel"></param> private void RefreshTarget(Vessel vessel) { // Do we have a target? ITargetable target = vessel.targetObject; if (target == null) { targetOrbitalPeriod = double.NaN; return; } // We have a target. If it's a vessel, is it non-orbiting? Vessel targetVessel = target.GetVessel(); if ((targetVessel != null) && (targetVessel.situation != Vessel.Situations.ORBITING)) { targetOrbitalPeriod = double.NaN; return; } // It's something else. Could be an orbiting vessel, could be a celestial body, // could be some other ITargetable (which I believe doesn't exist in the stock // game, but mods could introduce other types). Does it have an orbit? Orbit orbit = target.GetOrbit(); targetOrbitalPeriod = (orbit == null) ? double.NaN : orbit.period; }
/// <summary> /// Make the map view focus move to the given body. /// Borrowed and modified from Precise Node. /// </summary> /// <param name="center">The body or vessel to put at the middle of the screen</param> /// <param name="edge">A body or vessel to keep barely visible when we zoom</param> public static void FocusMap(ITargetable center, ITargetable edge = null) { MapView.MapCamera.SetTarget( PlanetariumCamera.fetch.targets.Find( mapObj => mapObj.celestialBody != null && mapObj.celestialBody.Equals(center) ) ); // Zoom the camera to facilitate the next step. if (edge != null) { // Without an encounter, the next step is establishing the encounter within the transfer SOI. SetMapZoom((float)edge.GetOrbit().semiMajorAxis); } else { // With an encounter, the next step is fine tuning within the destination SOI. CelestialBody b = center as CelestialBody; if (b != null) { SetMapZoom((float)b.sphereOfInfluence); } } }
private void UpdateTarget() { activeTarget = FlightGlobals.fetch.VesselTarget; if (activeTarget != null) { targetDisplacement = activeTarget.GetTransform().position - vessel.GetTransform().position; targetDirection = targetDisplacement.normalized; targetRelativeVelocity = vessel.obt_velocity - activeTarget.GetObtVelocity(); targetCmpSpeed = -1.0; targetDockingTransform = null; if (activeTarget is Vessel) { targetType = ((activeTarget as Vessel).vesselType == VesselType.SpaceObject) ? TargetType.Asteroid : TargetType.Vessel; } else if (activeTarget is CelestialBody) { targetType = TargetType.CelestialBody; } else if (activeTarget is ModuleDockingNode) { targetType = TargetType.DockingPort; targetDockingTransform = (activeTarget as ModuleDockingNode).GetTransform(); } else if (activeTarget is PositionTarget) { targetType = TargetType.PositionTarget; } else { Utility.LogError(this, "UpdateTarget() - unable to classify target {0}", activeTarget.GetType().Name); targetType = TargetType.None; } if (targetType == TargetType.Vessel || targetType == TargetType.DockingPort) { UpdateTargetDockingPorts(); } targetName = activeTarget.GetName(); targetOrbit = activeTarget.GetOrbit(); } else { targetCmpSpeed = 0.0; targetType = TargetType.None; targetDisplacement = Vector3.zero; targetRelativeVelocity = Vector3d.zero; targetDirection = forward; targetDockingTransform = null; targetName = string.Empty; targetOrbit = null; if (targetDockingPorts.Length > 0) { targetDockingPorts = new ModuleDockingNode[0]; } } approachSolver.ResetComputation(); }
/// <summary> /// Check whether a burn from one target to another constitutes a same-SOI transfer /// </summary> /// <param name="start">The body from which we start</param> /// <param name="end">The body where we end up</param> /// <returns> /// True if same SOI transfer, false if an ejection angle is involved /// </returns> public static bool SameSOITransfer(ITargetable start, ITargetable end) { CelestialBody b1 = start as CelestialBody; if (b1 != null) { // 1. start is body, end is body: end's referenceBody must be start // 2. start is body, end is vessel: N/A - bodies can't have targets return(b1 == end.GetOrbit().referenceBody); } else { // 3. start is vessel, end is vessel: Orbits must have same referenceBody // 4. start is vessel, end is body: Orbits must have same referenceBody // This needs to treat solar orbit -> Laythe as same SOI! return(AncestorsInclude(end.GetOrbit().referenceBody, start.GetOrbit().referenceBody)); } }
//Code fully by me //Come to within 150m of the target void RenezvousWithTarget(ITargetable target, Vessel attackVessel) { var oDriver = attackVessel.orbitDriver; var tOrbit = target.GetOrbit(); HardsetOrbit(oDriver, tOrbit); attackVessel.GoOffRails(); target.GetVessel().GoOffRails(); }
public static bool TargetValid() { if (FlightGlobals.ActiveVessel == null || FlightGlobals.ActiveVessel.targetObject == null || FlightGlobals.ActiveVessel.targetObject.GetOrbit() == null || FlightGlobals.ActiveVessel.targetObject.GetOrbit().referenceBody == null || FlightGlobals.ActiveVessel.orbit == null || FlightGlobals.ActiveVessel.orbit.referenceBody == null) { _targetBody = null; _vesselIntersect = false; _bodyIntersect = false; _updated = false; _activeVessel = null; _activeBody = null; _targetObject = null; _targetTransform = null; return(false); } _activeVessel = FlightGlobals.ActiveVessel; _activeBody = FlightGlobals.currentMainBody; _targetObject = _activeVessel.targetObject; if (_targetObject.GetVessel() == null) { if (_targetObject.GetOrbit() == null) { _targetBody = null; _isCelestial = false; _isVessel = false; } else if (_targetObject.GetOrbitDriver().celestialBody != null) { _targetBody = _targetObject.GetOrbitDriver().celestialBody; _isCelestial = true; _isVessel = false; } else { _targetBody = null; _isCelestial = false; _isVessel = false; } } else { _targetBody = null; _isCelestial = false; _isVessel = true; _targetTransform = FlightGlobals.fetch.vesselTargetTransform; _vesselTargetDelta = FlightGlobals.fetch.vesselTargetDelta; } return(true); }
/// <summary> /// Returns the orbit of the currently targeted item or null if there is none. /// </summary> /// <returns>The orbit or null.</returns> public static Orbit getTargetOrbit() { ITargetable tgt = FlightGlobals.fetch.VesselTarget; if (tgt != null) { // if we have a null vessel it's a celestial body if (tgt.GetVessel() == null) { return(tgt.GetOrbit()); } // otherwise make sure we're not targeting ourselves. if (!FlightGlobals.fetch.activeVessel.Equals(tgt.GetVessel())) { return(tgt.GetOrbit()); } } return(null); }
private void relDesc() { if (_patch == null || _patch.referenceBody == null) { return; } ITargetable tgt = FlightGlobals.fetch.VesselTarget; if (tgt == null || tgt.GetOrbit() == null || tgt.GetOrbit().referenceBody == null) { return; } if (_patch.referenceBody != tgt.GetOrbit().referenceBody) { return; } double relDesc = ManeuverUtilities.RelDescTime(_patch, tgt); if (_patch.UTsoi > 0 && relDesc > _patch.UTsoi) { return; } else if (relDesc < Planetarium.GetUniversalTime()) { return; } else { double periods = 0; if (!double.IsNaN(_patch.period) && !double.IsInfinity(_patch.period)) { periods = (_orbitsAdded * _patch.period); } setNodeTime(relDesc + periods); } }
private void clApp() { if (_patch == null) { return; } ITargetable tgt = FlightGlobals.fetch.VesselTarget; if (tgt == null) { return; } double clApp = 0; if (tgt.GetVessel() == null) { clApp = _patch.closestTgtApprUT; } else { clApp = ManeuverUtilities.closestVessel(0, _patch, tgt.GetOrbit(), true, 0, 0); } if (clApp <= 0) { return; } if (_patch.UTsoi > 0 && clApp > _patch.UTsoi) { return; } else if (clApp < Planetarium.GetUniversalTime()) { return; } else { setNodeTime(clApp); } }
public static double RelDescTime(Orbit o, ITargetable tgt) { Vector3d node = Vector3d.Cross(o.GetOrbitNormal(), tgt.GetOrbit().GetOrbitNormal()); double anomaly = o.GetTrueAnomalyOfZupVector(node); double period = 0; if (!double.IsNaN(o.period) && !double.IsInfinity(o.period)) { period = o.period; } double relDesc = o.GetDTforTrueAnomaly(anomaly, period); if (relDesc < 0) { relDesc += period; } return(relDesc + o.StartUT); }
private void WindowLayout_AddPane_TargetDistance() { intAddDistanceHeight = 262;// 272; GUILayout.BeginVertical(); GUILayout.Label(strAlarmEventName + " Details...", KACResources.styleAddSectionHeading); //What are the possible targets?? List <ITargetable> iTargets = new List <ITargetable>(); if (!(KACWorkerGameState.CurrentVesselTarget == null)) { iTargets.Add(KACWorkerGameState.CurrentVesselTarget); //VesselTarget } iTargets.Add(KACWorkerGameState.CurrentVessel.mainBody); //Body we are orbiting if (KACWorkerGameState.SOIPointExists) { iTargets.Add(KACWorkerGameState.CurrentVessel.orbit.nextPatch.referenceBody); //Body we will orbit next } if (intSelectediTarget > iTargets.Count - 1) { intSelectediTarget = 0; } intAddDistanceHeight += (iTargets.Count * 30); //Now give the user the choice GUILayout.BeginHorizontal(); GUILayout.Label("Select Target:", KACResources.styleAddXferName); if (DrawRadioListVertical(ref intSelectediTarget, iTargets.Select(x => x.GetName()).ToArray())) { Log.info("Distance Target is:{0}", iTargets[intSelectediTarget].GetName()); } GUILayout.EndHorizontal(); //Set the tgt Object tgtSelectedDistance = iTargets[intSelectediTarget]; string strDistanceName = "Distance"; if (tgtSelectedDistance is CelestialBody) { strDistanceName = "Altitude"; } //Ask for the target distance/altitude GUILayout.BeginHorizontal(); GUILayout.Label(string.Format("Target {0} (m):", strDistanceName), KACResources.styleAddXferName); dblTargetDistance = Convert.ToDouble(GUILayout.TextField(dblTargetDistance.ToString(), KACResources.styleAddField)); GUILayout.EndHorizontal(); //If the body has an atmosphere then add an option to set the Altitude straight to that if (tgtSelectedDistance is CelestialBody) { if ((tgtSelectedDistance as CelestialBody).atmosphere) { GUILayout.BeginHorizontal(); GUILayout.Label(string.Format("Atmosphere: {0}", (tgtSelectedDistance as CelestialBody).atmosphereDepth)); if (GUILayout.Button("Set to Edge")) { dblTargetDistance = (tgtSelectedDistance as CelestialBody).atmosphereDepth; } GUILayout.EndHorizontal(); intAddDistanceHeight += 26; } } //For a vessel give some options for orbits to look forwards GUILayout.BeginVertical(KACResources.styleAddFieldAreas); if (!(tgtSelectedDistance is CelestialBody)) { GUILayout.BeginHorizontal(); GUILayout.Label("Orbits to Search:", KACResources.styleAddHeading, GUILayout.Width(110)); GUILayout.Label(((int)Math.Round((Decimal)fltOrbits_Distance, 0)).ToString(), KACResources.styleAddXferName, GUILayout.Width(25)); fltOrbits_Distance = GUILayout.HorizontalSlider(fltOrbits_Distance, 1, 20); fltOrbits_Distance = (float)Math.Floor((Decimal)fltOrbits_Distance); GUILayout.EndHorizontal(); intAddDistanceHeight += 18; } //What VesselOrbit do we care about Orbit VesselOrbitToCompare = KACWorkerGameState.CurrentVessel.GetOrbit(); if ((KACWorkerGameState.SOIPointExists) && ((tgtSelectedDistance as CelestialBody) == KACWorkerGameState.CurrentVessel.orbit.nextPatch.referenceBody)) { VesselOrbitToCompare = KACWorkerGameState.CurrentVessel.orbit.nextPatch; } //Get the startUT of the orbit Double VesselOrbitStartUT = KACWorkerGameState.CurrentVessel.GetOrbit().StartUT; //Set up some variables intOrbits_Distance = (int)fltOrbits_Distance; int intDistanceOrbitPass = 0; double dblClosestDistance = Double.MaxValue; double dblDistanceUT = 0; double dblOrbitTestDistance = Double.MaxValue; double dblOrbitTestDistanceUT = 0; //If its an Altitude alarm then do this if (tgtSelectedDistance is CelestialBody) { dblOrbitTestDistanceUT = KACUtils.timeOfTargetAltitude(VesselOrbitToCompare, VesselOrbitStartUT, out dblOrbitTestDistance, dblTargetDistance ); dblClosestDistance = dblOrbitTestDistance; dblDistanceUT = dblOrbitTestDistanceUT; } else { //Else Iterate through the orbits to find the target separation for (int intOrbitToTest = 1; intOrbitToTest <= intOrbits_Distance; intOrbitToTest++) { dblOrbitTestDistanceUT = KACUtils.timeOfTargetDistance(VesselOrbitToCompare, tgtSelectedDistance.GetOrbit(), KACWorkerGameState.CurrentTime.UT, intOrbitToTest, out dblOrbitTestDistance, dblTargetDistance ); if (dblOrbitTestDistance < dblClosestDistance) { dblClosestDistance = dblOrbitTestDistance; dblDistanceUT = dblOrbitTestDistanceUT; intDistanceOrbitPass = intOrbitToTest; } } } //Now display what we got GUILayout.BeginHorizontal(); GUILayout.Label(String.Format("{0}:", strDistanceName), KACResources.styleAddHeading, GUILayout.Width(70)); String strDistance = string.Format("{0:#}m", dblClosestDistance); if (dblClosestDistance > 999) { strDistance = string.Format("{0:#.0}km", dblClosestDistance / 1000); } GUILayout.Label(strDistance, KACResources.styleAddXferName, GUILayout.Width(90)); if (!(tgtSelectedDistance is CelestialBody)) { GUILayout.Label("On Orbit:", KACResources.styleAddHeading); GUILayout.Label(intDistanceOrbitPass.ToString(), KACResources.styleAddXferName); } GUILayout.EndHorizontal(); GUILayout.EndVertical(); //Now do the stuff to draw the alarm button String strMarginConversion = ""; KSPDateTime eventTime = new KSPDateTime(dblDistanceUT); KSPTimeSpan eventInterval = new KSPTimeSpan(dblDistanceUT - KACWorkerGameState.CurrentTime.UT); KSPDateTime eventAlarm; KSPTimeSpan eventAlarmInterval; try { eventAlarm = new KSPDateTime(eventTime.UT - timeMargin.UT); eventAlarmInterval = new KSPTimeSpan(eventTime.UT - KACWorkerGameState.CurrentTime.UT - timeMargin.UT); } catch (Exception) { eventAlarm = null; eventAlarmInterval = null; strMarginConversion = "Unable to Add the Margin Minutes"; } if ((eventTime.UT > KACWorkerGameState.CurrentTime.UT) && strMarginConversion == "") { if (DrawAddAlarm(eventTime, eventInterval, eventAlarmInterval)) { KACAlarm newAlarm = new KACAlarm(KACWorkerGameState.CurrentVessel.id.ToString(), strAlarmName, strAlarmNotes, eventAlarm.UT, timeMargin.UT, AddType, AddActions); newAlarm.TargetObject = KACWorkerGameState.CurrentVesselTarget; newAlarm.ManNodes = KACWorkerGameState.CurrentVessel.patchedConicSolver.maneuverNodes; alarms.Add(newAlarm); //settings.Save(); _ShowAddPane = false; } } else { strMarginConversion = "No Target Distance Approach found"; } if (strMarginConversion != "") { GUILayout.Label(strMarginConversion, GUILayout.ExpandWidth(true)); } GUILayout.EndVertical(); }
//This code draws the Apoapis, Periapsis, and Period digits onto the gauge private void drawAPPEP(Orbit o) { double ap = o.ApA; if (o.eccentricity > 1.0) { ap = 0; //Escape trajectory } drawDigits(181f, 132f, ap); //Draw the Apoapsis value double pe = o.PeA; if (!showNegativePe && pe < 0) { pe = 0; //Don't draw negative values unless requested } drawDigits(181f, 199f, pe); //Draw the Periapsis value //Time to next of: Ap, Pe, An, Dn, SoI double apt = Math.Abs(o.timeToAp); double pet = Math.Abs(o.timeToPe); double ant = double.MaxValue; double dnt = double.MaxValue; ITargetable tar = FlightGlobals.fetch.VesselTarget; if (tar != null && tar.GetOrbit() != null) { //This should prevent a few errors try { ant = TimeOfAscendingNode(o, tar.GetOrbit(), Planetarium.fetch.time) - Planetarium.fetch.time; dnt = TimeOfDescendingNode(o, tar.GetOrbit(), Planetarium.fetch.time) - Planetarium.fetch.time; } catch { } } //Parabolic or hyperbolic orbits don't have an apoapsis if (o.eccentricity > 1.0) { apt = pet; } //Also draw label on gauge double seconds = double.MaxValue; if (pet < seconds) { seconds = pet; next = "pe"; } if (apt < seconds) { seconds = apt; next = "ap"; } if (ant >= 0 && ant < seconds) { seconds = ant; next = "an"; } if (dnt >= 0 && dnt < seconds) { seconds = dnt; next = "dn"; } double sec_fraction = seconds; int s = (int)Math.Round(sec_fraction); sec_fraction -= s; int minutes = s / 60; s -= minutes * 60; int hours = minutes / 60; minutes -= hours * 60; float width = Resources.digits.width; float height = Resources.digits.height / 11; int x = minutes % 10; GUI.DrawTextureWithTexCoords(new Rect(150f * Scale, 261f * Scale, width * Scale, height * Scale), Resources.digits, new Rect(0f, (float)(x * 0.091), 1f, 0.091f)); x = minutes / 10; GUI.DrawTextureWithTexCoords(new Rect(130f * Scale, 261f * Scale, width * Scale, height * Scale), Resources.digits6, new Rect(0f, (float)(x * 0.143), 1f, 0.143f)); x = hours % 10; GUI.DrawTextureWithTexCoords(new Rect(100f * Scale, 261f * Scale, width * Scale, height * Scale), Resources.digits, new Rect(0f, (float)(x * 0.091), 1f, 0.091f)); x = hours / 10; x = x % 10; GUI.DrawTextureWithTexCoords(new Rect(80f * Scale, 261f * Scale, width * Scale, height * Scale), Resources.digits, new Rect(0f, (float)(x * 0.091), 1f, 0.091f)); x = hours / 100; x = x % 10; GUI.DrawTextureWithTexCoords(new Rect(60f * Scale, 261f * Scale, width * Scale, height * Scale), Resources.digits, new Rect(0f, (float)(x * 0.091), 1f, 0.091f)); //Seconds //109, 132 double fx = s % 10 + sec_fraction; GUI.DrawTextureWithTexCoords(new Rect(198f * Scale, 261f * Scale, width * Scale, height * Scale), Resources.digits, new Rect(0f, (float)(fx * 0.091), 1f, 0.091f)); x = s / 10; GUI.DrawTextureWithTexCoords(new Rect(178f * Scale, 261f * Scale, width * Scale, height * Scale), Resources.digits6, new Rect(0f, (float)(x * 0.143), 1f, 0.143f)); }
/// <summary> /// Updates the details by recalculating if requested. /// </summary> public void Update() { ITargetable target = null; global::Vessel vessel = null; if (HighLogic.LoadedSceneIsFlight) { if (FlightGlobals.fetch == null || FlightGlobals.fetch.VesselTarget == null || FlightGlobals.ActiveVessel == null || FlightGlobals.ActiveVessel.targetObject == null || FlightGlobals.ActiveVessel.targetObject.GetOrbit() == null || FlightGlobals.ship_orbit == null || FlightGlobals.ship_orbit.referenceBody == null) { ShowDetails = false; return; } else { target = FlightGlobals.ActiveVessel.targetObject; vessel = FlightGlobals.ActiveVessel; } } else if (HighLogic.LoadedScene == GameScenes.TRACKSTATION) { if (PlanetariumCamera.fetch.target.type == MapObject.ObjectType.CelestialBody) { target = PlanetariumCamera.fetch.target.celestialBody; } else if (PlanetariumCamera.fetch.target.type == MapObject.ObjectType.Vessel) { target = PlanetariumCamera.fetch.target.vessel; } if (TrackingStationSource != null) { vessel = TrackingStationSource.GetVessel(); } else { TrackingStationSource = target; } } activeTarget = target; if (target == null) { ShowDetails = false; return; } ShowDetails = true; var actualSourceOrbit = vessel != null ? vessel.orbit : TrackingStationSource.GetOrbit(); var actualTargetOrbit = target.GetOrbit(); if (target is global::Vessel) { targetVessel = (global::Vessel)target; } else { targetVessel = null; } activeVessel = vessel; if (actualSourceOrbit == null) { // Debug.Log("Source orbit is null!"); TrackingStationSource = null; ShowDetails = false; return; } if (actualTargetOrbit == null) { // Debug.Log("Target orbit is null!"); ShowDetails = false; return; } isLanded = vessel != null && vessel.LandedOrSplashed; bool targetLanded = (target is global::Vessel && ((global::Vessel)target).LandedOrSplashed); landedSamePlanet = isLanded && targetLanded && actualSourceOrbit.referenceBody == actualTargetOrbit.referenceBody; var originOrbit = isLanded ? actualSourceOrbit.referenceBody.orbit : actualSourceOrbit; var targetOrbit = targetLanded ? actualTargetOrbit.referenceBody.orbit : actualTargetOrbit; if ((!isLanded && !targetLanded) || (actualSourceOrbit.referenceBody != actualTargetOrbit.referenceBody)) { findConcentricParents(ref originOrbit, ref targetOrbit); } if (originOrbit == targetOrbit && !landedSamePlanet) { targetOrbit = actualTargetOrbit; originOrbit = null; } AltitudeSeaLevel = targetOrbit.altitude; ApoapsisHeight = targetOrbit.ApA; PeriapsisHeight = targetOrbit.PeA; TimeToApoapsis = targetOrbit.timeToAp; TimeToPeriapsis = targetOrbit.timeToPe; SemiMajorAxis = targetOrbit.semiMajorAxis; SemiMinorAxis = targetOrbit.semiMinorAxis; OrbitalPeriod = targetOrbit.period; RelativeInclination = targetOrbit.inclination; TimeToAscendingNode = 0; TimeToDescendingNode = 0; AngleToAscendingNode = 0; AngleToDescendingNode = 0; RelativeVelocity = 0; RelativeSpeed = 0; PhaseAngle = 0; InterceptAngle = 0; TimeToTransferAngle = 0; AngleToPlane[0] = 0; TimeToPlane[0] = 0; AngleToPlane[1] = 0; TimeToPlane[1] = 0; Distance = 0; if (originOrbit != null) { overrideANDN = isLanded && actualSourceOrbit.referenceBody == targetOrbit.referenceBody; overrideANDNRev = targetLanded && !isLanded && actualTargetOrbit.referenceBody == actualSourceOrbit.referenceBody && target.GetVessel() != null; if (landedSamePlanet) //this should only occur when landed targeting something else landed on same body. { AltitudeSeaLevel = target.GetVessel().altitude; ApoapsisHeight = 0; PeriapsisHeight = 0; TimeToApoapsis = 0; TimeToPeriapsis = 0; SemiMajorAxis = 0; SemiMinorAxis = 0; bodyRotationPeriod = actualSourceOrbit.referenceBody.rotationPeriod; Distance = Vector3d.Distance(target.GetVessel().GetWorldPos3D(), vessel.GetWorldPos3D()); OrbitalPeriod = bodyRotationPeriod; TimeToRendezvous = 0; RelativeRadialVelocity = 0; } else { RelativeInclination = originOrbit.GetRelativeInclination(targetOrbit); RelativeSpeed = originOrbit.orbitalSpeed - targetOrbit.orbitalSpeed; RelativeVelocity = RelativeSpeed; PhaseAngle = originOrbit.GetPhaseAngle(targetOrbit); InterceptAngle = CalcInterceptAngle(targetOrbit, originOrbit); double tspd = 360 / targetOrbit.period; double sspd = 360 / originOrbit.period; if (PhaseAngle < 0) { double diff = InterceptAngle - PhaseAngle; if (diff < 0) { diff += 360; } if (diff > 340) { diff -= 360; } TimeToTransferAngle = sspd == tspd ? 0 : diff / (tspd - sspd); } else { double diff = PhaseAngle - InterceptAngle; if (diff < 0) { diff += 360; } if (diff > 340) { diff -= 360; } TimeToTransferAngle = sspd == tspd ? 0 : diff / (sspd - tspd); } TimeToAscendingNode = originOrbit.GetTimeToVector(GetAscendingNode(targetOrbit, originOrbit)); TimeToDescendingNode = originOrbit.GetTimeToVector(GetDescendingNode(targetOrbit, originOrbit)); AngleToAscendingNode = originOrbit.GetAngleToVector(GetAscendingNode(targetOrbit, originOrbit)); AngleToDescendingNode = originOrbit.GetAngleToVector(GetDescendingNode(targetOrbit, originOrbit)); Distance = Vector3d.Distance(targetOrbit.pos, originOrbit.pos); bodyRotationPeriod = actualSourceOrbit.referenceBody.rotationPeriod; // beware that the order/sign of coordinates is inconsistent across different exposed variables // in particular, v below does not equal to FlightGlobals.ship_tgtVelocity Vector3d x = targetOrbit.pos - originOrbit.pos; Vector3d v = targetOrbit.vel - originOrbit.vel; double xv = Vector3d.Dot(x, v); TimeToRendezvous = -xv / Vector3d.SqrMagnitude(v); RelativeRadialVelocity = xv / Vector3d.Magnitude(x); if (overrideANDN) //calc launch time { if (vessel != null) { AngleToPlane = CalcAngleToPlane(vessel.GetOrbit().referenceBody, vessel.latitude, vessel.longitude, targetOrbit); TimeToPlane[0] = (AngleToPlane[0] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod; TimeToPlane[1] = (AngleToPlane[1] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod; } RelativeInclination = targetOrbit.inclination; RelativeRadialVelocity = 0; TimeToRendezvous = 0; PhaseAngle = 0; InterceptAngle = 0; TimeToTransferAngle = 0; } else if (overrideANDNRev) //calc land time. { global::Vessel tgt = target.GetVessel(); if (vessel != null) { AngleToPlane = CalcAngleToPlane(vessel.GetOrbit().referenceBody, tgt.latitude, tgt.longitude, originOrbit); TimeToPlane[0] = (AngleToPlane[0] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod; TimeToPlane[1] = (AngleToPlane[1] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod; } RelativeInclination = originOrbit.inclination; Distance = Vector3d.Distance(target.GetVessel().GetWorldPos3D(), vessel.GetWorldPos3D()); AltitudeSeaLevel = tgt.altitude; PhaseAngle = 0; InterceptAngle = 0; TimeToTransferAngle = 0; ApoapsisHeight = 0; PeriapsisHeight = 0; TimeToApoapsis = 0; TimeToPeriapsis = 0; SemiMajorAxis = 0; SemiMinorAxis = 0; OrbitalPeriod = 0; RelativeRadialVelocity = 0; TimeToRendezvous = 0; } } } if (actualTargetOrbit != targetOrbit) { targetDisplay = findNameForOrbit(targetOrbit, target); } else { targetDisplay = null; } if (originOrbit == null) { sourceDisplay = "N/A"; } else if (actualSourceOrbit != originOrbit || HighLogic.LoadedScene == GameScenes.TRACKSTATION) { sourceDisplay = findNameForOrbit(originOrbit, vessel != null ? vessel : TrackingStationSource); } else { sourceDisplay = null; } }
public static void Update() { _update = false; if (FlightGlobals.ActiveVessel == null || FlightGlobals.ActiveVessel.targetObject == null || FlightGlobals.ActiveVessel.targetObject.GetOrbit() == null || FlightGlobals.ActiveVessel.targetObject.GetOrbit().referenceBody == null || FlightGlobals.ActiveVessel.orbit == null || FlightGlobals.ActiveVessel.orbit.referenceBody == null) { _updated = false; return; } _updated = true; Orbit active = _activeVessel.orbit; Orbit target = _targetObject.GetOrbit(); _trueShipOrbit = active; _showAngle = false; _showPhasing = false; _shipOrbit = null; _targetOrbit = null; if (active.referenceBody == target.referenceBody) { _shipOrbit = active; _targetOrbit = target; } else { if (active.referenceBody == Planetarium.fetch.Sun) { _shipOrbit = active; _targetOrbit = target; } else { _showAngle = true; } _showPhasing = true; DrillDownOrbits(active, target); } Vessel.Situations sit = _activeVessel.situation; if ((sit |= Vessel.Situations.LANDED | Vessel.Situations.SPLASHED | Vessel.Situations.PRELAUNCH) == 0) { _vesselIntersect = false; _bodyIntersect = false; } else { if (!_isVessel && !_isCelestial) { _vesselIntersect = false; _bodyIntersect = false; } else { OrbitTargeter oTargeter = _activeVessel.orbitTargeter; PatchedConicSolver solver = _activeVessel.patchedConicSolver; if (oTargeter == null || solver == null) { _vesselIntersect = false; _bodyIntersect = false; } else if (!MapView.MapIsEnabled) { if (_isVessel) { _bodyIntersect = false; Vessel tgt = _targetObject.GetVessel(); if (tgt == null || tgt.LandedOrSplashed) { _vesselIntersect = false; return; } Orbit _refPatch = null; if (solver.maneuverNodes.Count > 0) { _refPatch = GetReferencePatch(oTargeter, solver, target.referenceBody, null, true); } else { _refPatch = BasicOrbitReflection.GetRefPatch(oTargeter); } Orbit _tgtRefPatch = BasicOrbitReflection.GetTargetRefPatch(oTargeter); _vesselIntersect = GetClosestVessel(_refPatch, _tgtRefPatch); } else { _vesselIntersect = false; double Pe = GetLowestPeA(solver); if (Pe < BasicExtensions.AlmostMaxValue) { _closestDist = Pe; _bodyIntersect = true; } else { Orbit _refPatch = null; if (solver.maneuverNodes.Count > 0) { _refPatch = GetReferencePatch(oTargeter, solver, _targetBody, target.referenceBody, false); } else { _refPatch = BasicOrbitReflection.GetRefPatch(oTargeter); } if (_refPatch != null && _refPatch.closestTgtApprUT <= 0) { _bodyIntersect = false; return; } Orbit _tgtRefPatch = BasicOrbitReflection.GetTargetRefPatch(oTargeter); _bodyIntersect = GetClosestCelestial(_refPatch, _tgtRefPatch); } } } else { if (_markers == null || _markers.Count <= 0) { _markers = BasicOrbitReflection.GetOrbitMarkers(oTargeter); } if (_markers == null || _markers.Count <= 0) { _vesselIntersect = false; _bodyIntersect = false; } else if (_isVessel) { _bodyIntersect = false; if (solver.maneuverNodes.Count > 0) { Orbit _refPatch = GetReferencePatch(oTargeter, solver, target.referenceBody, null, true); Orbit _tgtRefPatch = BasicOrbitReflection.GetTargetRefPatch(oTargeter); _vesselIntersect = GetClosestVessel(_refPatch, _tgtRefPatch); } else { OrbitTargeter.ISectMarker _intersectOne = null; OrbitTargeter.ISectMarker _intersectTwo = null; for (int i = _markers.Count - 1; i >= 0; i--) { OrbitTargeter.Marker m = _markers[i]; if (m == null) { continue; } if (!(m is OrbitTargeter.ISectMarker)) { continue; } int num = ((OrbitTargeter.ISectMarker)m).num; if (num == 1) { _intersectOne = m as OrbitTargeter.ISectMarker; } else if (num == 2) { _intersectTwo = m as OrbitTargeter.ISectMarker; } } OrbitTargeter.ISectMarker _closestIntersect = null; if (_intersectOne != null && _intersectTwo != null) { _closestIntersect = _intersectOne.separation > _intersectTwo.separation ? _intersectTwo : _intersectOne; } else if (_intersectOne != null) { _closestIntersect = _intersectOne; } else if (_intersectTwo != null) { _closestIntersect = _intersectTwo; } else { _closestIntersect = null; } if (_closestIntersect == null) { _vesselIntersect = false; } else { _vesselIntersect = true; _closestDist = _closestIntersect.separation * 1000; _closestRelVel = _closestIntersect.relSpeed; _closestTime = _closestIntersect.UT; } } } else { _vesselIntersect = false; double Pe = GetLowestPeA(solver); if (Pe < BasicExtensions.AlmostMaxValue) { _closestDist = Pe; _bodyIntersect = true; } else { if (solver.maneuverNodes.Count > 0) { Orbit _refPatch = GetReferencePatch(oTargeter, solver, _targetBody, target.referenceBody, false); Orbit _tgtRefPatch = BasicOrbitReflection.GetTargetRefPatch(oTargeter); _bodyIntersect = GetClosestCelestial(_refPatch, _tgtRefPatch); } else { OrbitTargeter.ClApprMarker _approach = null; for (int i = _markers.Count - 1; i >= 0; i--) { OrbitTargeter.Marker m = _markers[i]; if (m == null) { continue; } if (!(m is OrbitTargeter.ClApprMarker)) { continue; } _approach = m as OrbitTargeter.ClApprMarker; } if (_approach == null) { _bodyIntersect = false; } else { _bodyIntersect = true; _closestDist = _approach.separation * 1000; _closestTime = (_approach.dT * -1) + Planetarium.GetUniversalTime(); } } } } } } } }
private void checkOrbit() { if (_manager.SelectedManeuverNode == null || _snapTab == null) { return; } if (_patch == null) { SetFields(); } double UT = Planetarium.GetUniversalTime(); //_snapTab.CurrentTime.OnTextUpdate.Invoke(string.Format("Maneuver Node #{0}: T {1}", _index + 1, KSPUtil.PrintTime(UT - _manager.SelectedManeuverNode.UT, 3, true))); _snapTab.ResetTime.OnTextUpdate.Invoke(string.Format("{0}", KSPUtil.PrintTime(_startUT - UT, 3, false))); if (_patch.eccentricity >= 1) { if (_manager.SelectedManeuverNode.attachedGizmo != null) { _manager.SelectedManeuverNode.attachedGizmo.orbitsAdded = 0; } _orbitsAdded = 0; _snapTab.NextOrbitButton.gameObject.SetActive(false); _snapTab.PreviousOrbitButton.gameObject.SetActive(false); _snapTab.ApoButton.gameObject.SetActive(false); if (_patch.timeToPe < 0) { _snapTab.PeriButton.gameObject.SetActive(false); } else if (_patch.PeR < 0) { _snapTab.PeriButton.gameObject.SetActive(false); } else if (_patch.UTsoi > 0 && _patch.timeToPe + _patch.StartUT > _patch.UTsoi) { _snapTab.PeriButton.gameObject.SetActive(false); } else { _snapTab.PeriButton.gameObject.SetActive(true); periUT = _patch.StartUT + _patch.timeToPe; } if ((_patch.patchEndTransition == Orbit.PatchTransitionType.ENCOUNTER || _patch.patchEndTransition == Orbit.PatchTransitionType.ESCAPE || _patch.patchEndTransition == Orbit.PatchTransitionType.MANEUVER) && (_patch.nextPatch.patchEndTransition == Orbit.PatchTransitionType.ENCOUNTER || _patch.nextPatch.patchEndTransition == Orbit.PatchTransitionType.ESCAPE)) { _snapTab.NextPatchButton.gameObject.SetActive(true); if (_patch.nextPatch.nextPatch.UTsoi > 0) { nextPUT = _patch.nextPatch.nextPatch.StartUT + ((_patch.nextPatch.nextPatch.UTsoi - _patch.nextPatch.nextPatch.StartUT) / 2); } else if (_patch.nextPatch.nextPatch.eccentricity < 1 && !double.IsNaN(_patch.nextPatch.nextPatch.period) && !double.IsInfinity(_patch.nextPatch.nextPatch.period)) { nextPUT = _patch.nextPatch.nextPatch.StartUT + (_patch.nextPatch.nextPatch.period / 2); } else { nextPUT = _patch.nextPatch.nextPatch.StartUT + ((_patch.nextPatch.nextPatch.EndUT - _patch.nextPatch.nextPatch.StartUT) / 2); } } else { _snapTab.NextPatchButton.gameObject.SetActive(false); } if (_patch.patchStartTransition == Orbit.PatchTransitionType.INITIAL || _patch.patchStartTransition == Orbit.PatchTransitionType.MANEUVER) { _snapTab.PreviousPatchButton.gameObject.SetActive(false); } else { _snapTab.PreviousPatchButton.gameObject.SetActive(true); if (_patch.previousPatch.UTsoi > 0) { prevPUT = _patch.previousPatch.StartUT + ((_patch.previousPatch.UTsoi - _patch.previousPatch.StartUT) / 2); } else if (_patch.previousPatch.eccentricity < 1 && !double.IsNaN(_patch.previousPatch.period) && !double.IsInfinity(_patch.previousPatch.period)) { prevPUT = _patch.previousPatch.StartUT + (_patch.previousPatch.period / 2); } else { prevPUT = _patch.previousPatch.StartUT + ((_patch.previousPatch.EndUT - _patch.previousPatch.StartUT) / 2); } } eqAscUT = ManeuverUtilities.EqAscTime(_patch); if (_patch.UTsoi > 0 && eqAscUT > _patch.UTsoi) { _snapTab.EqAscButton.gameObject.SetActive(false); } else if (eqAscUT < UT) { _snapTab.EqAscButton.gameObject.SetActive(false); } else { _snapTab.EqAscButton.gameObject.SetActive(true); } eqDescUT = ManeuverUtilities.EqDescTime(_patch); if (_patch.UTsoi > 0 && eqDescUT > _patch.UTsoi) { _snapTab.EqDescButton.gameObject.SetActive(false); } else if (eqDescUT < UT) { _snapTab.EqDescButton.gameObject.SetActive(false); } else { _snapTab.EqDescButton.gameObject.SetActive(true); } ITargetable target = FlightGlobals.fetch.VesselTarget; if (target == null) { _snapTab.RelAscButton.gameObject.SetActive(false); _snapTab.RelDescButton.gameObject.SetActive(false); _snapTab.ClAppButton.gameObject.SetActive(false); } else { Orbit tgtPatch = target.GetOrbit(); if (tgtPatch.referenceBody != _patch.referenceBody) { _snapTab.RelAscButton.gameObject.SetActive(false); _snapTab.RelDescButton.gameObject.SetActive(false); _snapTab.ClAppButton.gameObject.SetActive(false); } else { relAscUT = ManeuverUtilities.RelAscTime(_patch, target); if (_patch.UTsoi > 0 && relAscUT > _patch.UTsoi) { _snapTab.RelAscButton.gameObject.SetActive(false); } else if (relAscUT < UT) { _snapTab.RelAscButton.gameObject.SetActive(false); } else { _snapTab.RelAscButton.gameObject.SetActive(true); } relDescUT = ManeuverUtilities.RelDescTime(_patch, target); if (_patch.UTsoi > 0 && relDescUT > _patch.UTsoi) { _snapTab.RelDescButton.gameObject.SetActive(false); } else if (relDescUT < UT) { _snapTab.RelDescButton.gameObject.SetActive(false); } else { _snapTab.RelDescButton.gameObject.SetActive(true); } if (target.GetVessel() == null) { clAppUT = _patch.closestTgtApprUT; } else { clAppUT = ManeuverUtilities.closestVessel(0, _patch, tgtPatch, true, 0, 0); } if (clAppUT <= 0) { _snapTab.ClAppButton.gameObject.SetActive(false); } else if (_patch.UTsoi > 0 && clAppUT > _patch.UTsoi) { _snapTab.ClAppButton.gameObject.SetActive(false); } else if (clAppUT < UT) { _snapTab.ClAppButton.gameObject.SetActive(false); } else { _snapTab.ClAppButton.gameObject.SetActive(true); } } } } else { if (_patch.patchEndTransition == Orbit.PatchTransitionType.FINAL) { if (!double.IsNaN(_patch.period) && !double.IsInfinity(_patch.period)) { _snapTab.NextOrbitButton.gameObject.SetActive(true); nextOUT = _manager.SelectedManeuverNode.UT + _patch.period; } else { _snapTab.NextOrbitButton.gameObject.SetActive(false); } if (double.IsNaN(_patch.period) || double.IsInfinity(_patch.period) || _manager.SelectedManeuverNode.UT - _patch.period < UT) { _snapTab.PreviousOrbitButton.gameObject.SetActive(false); } else { _snapTab.PreviousOrbitButton.gameObject.SetActive(true); prevOUT = _manager.SelectedManeuverNode.UT - _patch.period; } _snapTab.ApoButton.gameObject.SetActive(true); apoUT = _patch.StartUT + _patch.timeToAp; _snapTab.PeriButton.gameObject.SetActive(true); periUT = _patch.StartUT + _patch.timeToPe; _snapTab.NextPatchButton.gameObject.SetActive(false); if (_patch.patchStartTransition == Orbit.PatchTransitionType.INITIAL || _patch.patchStartTransition == Orbit.PatchTransitionType.MANEUVER) { _snapTab.PreviousPatchButton.gameObject.SetActive(false); } else { _snapTab.PreviousPatchButton.gameObject.SetActive(true); if (_patch.previousPatch.UTsoi > 0) { prevPUT = _patch.previousPatch.StartUT + ((_patch.previousPatch.UTsoi - _patch.previousPatch.StartUT) / 2); } else if (_patch.previousPatch.eccentricity < 1 && !double.IsNaN(_patch.previousPatch.period) && !double.IsInfinity(_patch.previousPatch.period)) { prevPUT = _patch.previousPatch.StartUT + (_patch.previousPatch.period / 2); } else { prevPUT = _patch.previousPatch.StartUT + ((_patch.previousPatch.EndUT - _patch.previousPatch.StartUT) / 2); } } _snapTab.EqAscButton.gameObject.SetActive(true); eqAscUT = ManeuverUtilities.EqAscTime(_patch); _snapTab.EqDescButton.gameObject.SetActive(true); eqDescUT = ManeuverUtilities.EqDescTime(_patch); ITargetable target = FlightGlobals.fetch.VesselTarget; if (target == null) { _snapTab.RelAscButton.gameObject.SetActive(false); _snapTab.RelDescButton.gameObject.SetActive(false); _snapTab.ClAppButton.gameObject.SetActive(false); } else { Orbit tgtPatch = target.GetOrbit(); if (tgtPatch.referenceBody != _patch.referenceBody) { _snapTab.RelAscButton.gameObject.SetActive(false); _snapTab.RelDescButton.gameObject.SetActive(false); _snapTab.ClAppButton.gameObject.SetActive(false); } else { _snapTab.RelAscButton.gameObject.SetActive(true); relAscUT = ManeuverUtilities.RelAscTime(_patch, target); _snapTab.RelDescButton.gameObject.SetActive(true); relDescUT = ManeuverUtilities.RelDescTime(_patch, target); if (target.GetVessel() == null) { clAppUT = _patch.closestTgtApprUT; } else { clAppUT = ManeuverUtilities.closestVessel(0, _patch, tgtPatch, true, 0, 0); } if (clAppUT <= 0) { _snapTab.ClAppButton.gameObject.SetActive(false); } else { _snapTab.ClAppButton.gameObject.SetActive(true); } } } } else { if (_manager.SelectedManeuverNode.attachedGizmo != null) { _manager.SelectedManeuverNode.attachedGizmo.orbitsAdded = 0; } _orbitsAdded = 0; _snapTab.NextOrbitButton.gameObject.SetActive(false); _snapTab.PreviousOrbitButton.gameObject.SetActive(false); if (_patch.timeToAp < 0) { _snapTab.ApoButton.gameObject.SetActive(false); } if (_patch.UTsoi > 0 && _patch.timeToAp + _patch.StartUT > _patch.UTsoi) { _snapTab.ApoButton.gameObject.SetActive(false); } if (_patch.ApA > _patch.referenceBody.sphereOfInfluence) { _snapTab.ApoButton.gameObject.SetActive(false); } else { _snapTab.ApoButton.gameObject.SetActive(true); apoUT = _patch.StartUT + _patch.timeToAp; } if (_patch.timeToPe < 0) { _snapTab.PeriButton.gameObject.SetActive(false); } else if (_patch.PeR < 0) { _snapTab.PeriButton.gameObject.SetActive(false); } else if (_patch.UTsoi > 0 && _patch.timeToPe + _patch.StartUT > _patch.UTsoi) { _snapTab.PeriButton.gameObject.SetActive(false); } else { _snapTab.PeriButton.gameObject.SetActive(true); periUT = _patch.StartUT + _patch.timeToPe; } if ((_patch.patchEndTransition == Orbit.PatchTransitionType.ENCOUNTER || _patch.patchEndTransition == Orbit.PatchTransitionType.ESCAPE || _patch.patchEndTransition == Orbit.PatchTransitionType.MANEUVER) && (_patch.nextPatch.patchEndTransition == Orbit.PatchTransitionType.ENCOUNTER || _patch.nextPatch.patchEndTransition == Orbit.PatchTransitionType.ESCAPE)) { _snapTab.NextPatchButton.gameObject.SetActive(true); if (_patch.nextPatch.nextPatch.UTsoi > 0) { nextPUT = _patch.nextPatch.nextPatch.StartUT + ((_patch.nextPatch.nextPatch.UTsoi - _patch.nextPatch.nextPatch.StartUT) / 2); } else if (_patch.nextPatch.nextPatch.eccentricity < 1 && !double.IsNaN(_patch.nextPatch.nextPatch.period) && !double.IsInfinity(_patch.nextPatch.nextPatch.period)) { nextPUT = _patch.nextPatch.nextPatch.StartUT + (_patch.nextPatch.nextPatch.period / 2); } else { nextPUT = _patch.nextPatch.nextPatch.StartUT + ((_patch.nextPatch.nextPatch.EndUT - _patch.nextPatch.nextPatch.StartUT) / 2); } } else { _snapTab.NextPatchButton.gameObject.SetActive(false); } if (_patch.patchStartTransition == Orbit.PatchTransitionType.INITIAL || _patch.patchStartTransition == Orbit.PatchTransitionType.MANEUVER) { _snapTab.PreviousPatchButton.gameObject.SetActive(false); } else { _snapTab.PreviousPatchButton.gameObject.SetActive(true); if (_patch.previousPatch.UTsoi > 0) { prevPUT = _patch.previousPatch.StartUT + ((_patch.previousPatch.UTsoi - _patch.previousPatch.StartUT) / 2); } else if (_patch.previousPatch.eccentricity < 1 && !double.IsNaN(_patch.previousPatch.period) && !double.IsInfinity(_patch.previousPatch.period)) { prevPUT = _patch.previousPatch.StartUT + (_patch.previousPatch.period / 2); } else { prevPUT = _patch.previousPatch.StartUT + ((_patch.previousPatch.EndUT - _patch.previousPatch.StartUT) / 2); } } eqAscUT = ManeuverUtilities.EqAscTime(_patch); if (_patch.UTsoi > 0 && eqAscUT > _patch.UTsoi) { _snapTab.EqAscButton.gameObject.SetActive(false); } else if (eqAscUT < UT) { _snapTab.EqAscButton.gameObject.SetActive(false); } else { _snapTab.EqAscButton.gameObject.SetActive(true); } eqDescUT = ManeuverUtilities.EqDescTime(_patch); if (_patch.UTsoi > 0 && eqDescUT > _patch.UTsoi) { _snapTab.EqDescButton.gameObject.SetActive(false); } else if (eqDescUT < UT) { _snapTab.EqDescButton.gameObject.SetActive(false); } else { _snapTab.EqDescButton.gameObject.SetActive(true); } ITargetable target = FlightGlobals.fetch.VesselTarget; if (target == null) { _snapTab.RelAscButton.gameObject.SetActive(false); _snapTab.RelDescButton.gameObject.SetActive(false); _snapTab.ClAppButton.gameObject.SetActive(false); } else { Orbit tgtPatch = target.GetOrbit(); if (tgtPatch.referenceBody != _patch.referenceBody) { _snapTab.RelAscButton.gameObject.SetActive(false); _snapTab.RelDescButton.gameObject.SetActive(false); _snapTab.ClAppButton.gameObject.SetActive(false); } else { relAscUT = ManeuverUtilities.RelAscTime(_patch, target); if (_patch.UTsoi > 0 && relAscUT > _patch.UTsoi) { _snapTab.RelAscButton.gameObject.SetActive(false); } else if (relAscUT < UT) { _snapTab.RelAscButton.gameObject.SetActive(false); } else { _snapTab.RelAscButton.gameObject.SetActive(true); } relDescUT = ManeuverUtilities.RelDescTime(_patch, target); if (_patch.UTsoi > 0 && relDescUT > _patch.UTsoi) { _snapTab.RelDescButton.gameObject.SetActive(false); } else if (relDescUT < UT) { _snapTab.RelDescButton.gameObject.SetActive(false); } else { _snapTab.RelDescButton.gameObject.SetActive(true); } if (target.GetVessel() == null) { clAppUT = _patch.closestTgtApprUT; } else { clAppUT = ManeuverUtilities.closestVessel(0, _patch, tgtPatch, true, 0, 0); } if (clAppUT <= 0) { _snapTab.ClAppButton.gameObject.SetActive(false); } else if (_patch.UTsoi > 0 && clAppUT > _patch.UTsoi) { _snapTab.ClAppButton.gameObject.SetActive(false); } else if (clAppUT < UT) { _snapTab.ClAppButton.gameObject.SetActive(false); } else { _snapTab.ClAppButton.gameObject.SetActive(true); } } } } } }
private void WindowLayout_AddPane_TargetDistance() { intAddDistanceHeight = 272; GUILayout.BeginVertical(); GUILayout.Label(strAlarmEventName + " Details...", KACResources.styleAddSectionHeading); //What are the possible targets?? List<ITargetable> iTargets = new List<ITargetable>(); if (!(KACWorkerGameState.CurrentVesselTarget == null)) { iTargets.Add(KACWorkerGameState.CurrentVesselTarget); //VesselTarget } iTargets.Add(KACWorkerGameState.CurrentVessel.mainBody); //Body we are orbiting if (KACWorkerGameState.SOIPointExists) { iTargets.Add(KACWorkerGameState.CurrentVessel.orbit.nextPatch.referenceBody); //Body we will orbit next } if (intSelectediTarget > iTargets.Count - 1) intSelectediTarget = 0; intAddDistanceHeight += (iTargets.Count*30); //Now give the user the choice GUILayout.BeginHorizontal(); GUILayout.Label("Select Target:",KACResources.styleAddXferName); if (DrawRadioListVertical(ref intSelectediTarget, iTargets.Select(x => x.GetName()).ToArray())) { DebugLogFormatted("Distance Target is:{0}", iTargets[intSelectediTarget].GetName()); } GUILayout.EndHorizontal(); //Set the tgt Object tgtSelectedDistance=iTargets[intSelectediTarget]; string strDistanceName = "Distance"; if (tgtSelectedDistance is CelestialBody) strDistanceName = "Altitude"; //Ask for the target distance/altitude GUILayout.BeginHorizontal(); GUILayout.Label(string.Format("Target {0} (m):",strDistanceName), KACResources.styleAddXferName); dblTargetDistance= Convert.ToInt32(GUILayout.TextField(dblTargetDistance.ToString(),KACResources.styleAddField)); GUILayout.EndHorizontal(); //If the body has an atmosphere then add an option to set the Altitude straight to that if (tgtSelectedDistance is CelestialBody) { if ((tgtSelectedDistance as CelestialBody).atmosphere) { GUILayout.BeginHorizontal(); GUILayout.Label(string.Format("Atmosphere: {0}", (tgtSelectedDistance as CelestialBody).maxAtmosphereAltitude)); if (GUILayout.Button("Set to Edge")) { dblTargetDistance = (tgtSelectedDistance as CelestialBody).maxAtmosphereAltitude; } GUILayout.EndHorizontal(); intAddDistanceHeight += 26; } } //For a vessel give some options for orbits to look forwards GUILayout.BeginVertical(KACResources.styleAddFieldAreas); if (!(tgtSelectedDistance is CelestialBody)) { GUILayout.BeginHorizontal(); GUILayout.Label("Orbits to Search:", KACResources.styleAddHeading, GUILayout.Width(110)); GUILayout.Label(((int)Math.Round((Decimal)fltOrbits_Distance, 0)).ToString(), KACResources.styleAddXferName, GUILayout.Width(25)); fltOrbits_Distance = GUILayout.HorizontalSlider(fltOrbits_Distance, 1, 20); fltOrbits_Distance = (float)Math.Floor((Decimal)fltOrbits_Distance); GUILayout.EndHorizontal(); intAddDistanceHeight += 18; } //What VesselOrbit do we care about Orbit VesselOrbitToCompare=KACWorkerGameState.CurrentVessel.GetOrbit(); if ((KACWorkerGameState.SOIPointExists) && ((tgtSelectedDistance as CelestialBody) == KACWorkerGameState.CurrentVessel.orbit.nextPatch.referenceBody)) { VesselOrbitToCompare = KACWorkerGameState.CurrentVessel.orbit.nextPatch; } //Get the startUT of the orbit Double VesselOrbitStartUT = KACWorkerGameState.CurrentVessel.GetOrbit().StartUT; //Set up some variables intOrbits_Distance = (int)fltOrbits_Distance; int intDistanceOrbitPass = 0; double dblClosestDistance = Double.MaxValue; double dblDistanceUT = 0; double dblOrbitTestDistance = Double.MaxValue; double dblOrbitTestDistanceUT = 0; //If its an Altitude alarm then do this if (tgtSelectedDistance is CelestialBody) { dblOrbitTestDistanceUT = KACUtils.timeOfTargetAltitude(VesselOrbitToCompare, VesselOrbitStartUT, out dblOrbitTestDistance, dblTargetDistance ); dblClosestDistance = dblOrbitTestDistance; dblDistanceUT = dblOrbitTestDistanceUT; } else { //Else Iterate through the orbits to find the target separation for (int intOrbitToTest = 1; intOrbitToTest <= intOrbits_Distance; intOrbitToTest++) { dblOrbitTestDistanceUT = KACUtils.timeOfTargetDistance(VesselOrbitToCompare, tgtSelectedDistance.GetOrbit(), KACWorkerGameState.CurrentTime.UT, intOrbitToTest, out dblOrbitTestDistance, dblTargetDistance ); if (dblOrbitTestDistance < dblClosestDistance) { dblClosestDistance = dblOrbitTestDistance; dblDistanceUT = dblOrbitTestDistanceUT; intDistanceOrbitPass = intOrbitToTest; } } } //Now display what we got GUILayout.BeginHorizontal(); GUILayout.Label(String.Format("{0}:",strDistanceName), KACResources.styleAddHeading, GUILayout.Width(70)); String strDistance = string.Format("{0:#}m", dblClosestDistance); if (dblClosestDistance > 999) strDistance = string.Format("{0:#.0}km", dblClosestDistance / 1000); GUILayout.Label(strDistance, KACResources.styleAddXferName, GUILayout.Width(90)); if (!(tgtSelectedDistance is CelestialBody)) { GUILayout.Label("On Orbit:", KACResources.styleAddHeading); GUILayout.Label(intDistanceOrbitPass.ToString(), KACResources.styleAddXferName); } GUILayout.EndHorizontal(); GUILayout.EndVertical(); //Now do the stuff to draw the alarm button String strMarginConversion = ""; KACTime eventTime = new KACTime(dblDistanceUT); KACTime eventInterval = new KACTime(dblDistanceUT - KACWorkerGameState.CurrentTime.UT); KACTime eventAlarm; KACTime eventAlarmInterval; try { eventAlarm = new KACTime(eventTime.UT - timeMargin.UT); eventAlarmInterval = new KACTime(eventTime.UT - KACWorkerGameState.CurrentTime.UT - timeMargin.UT); } catch (Exception) { eventAlarm = null; eventAlarmInterval = null; strMarginConversion = "Unable to Add the Margin Minutes"; } if ((eventTime.UT > KACWorkerGameState.CurrentTime.UT) && strMarginConversion == "") { if (DrawAddAlarm(eventTime, eventInterval, eventAlarmInterval)) { KACAlarm newAlarm = new KACAlarm(KACWorkerGameState.CurrentVessel.id.ToString(), strAlarmName, strAlarmNotes, eventAlarm.UT, timeMargin.UT, AddType, (AddAction == KACAlarm.AlarmAction.KillWarp), (AddAction == KACAlarm.AlarmAction.PauseGame)); newAlarm.TargetObject = KACWorkerGameState.CurrentVesselTarget; newAlarm.ManNodes = KACWorkerGameState.CurrentVessel.patchedConicSolver.maneuverNodes; Settings.Alarms.Add(newAlarm); Settings.Save(); _ShowAddPane = false; } } else { strMarginConversion = "No Target Distance Approach found"; } if (strMarginConversion != "") GUILayout.Label(strMarginConversion, GUILayout.ExpandWidth(true)); GUILayout.EndVertical(); }
private void FetchCommonData() { localGeeASL = vessel.orbit.referenceBody.GeeASL * gee; coM = vessel.findWorldCenterOfMass(); localGeeDirect = FlightGlobals.getGeeForceAtPosition(coM).magnitude; up = (coM - vessel.mainBody.position).normalized; forward = vessel.GetTransform().up; right = vessel.GetTransform().right; north = Vector3d.Exclude(up, (vessel.mainBody.position + vessel.mainBody.transform.up * (float)vessel.mainBody.Radius) - coM).normalized; rotationSurface = Quaternion.LookRotation(north, up); rotationVesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(vessel.GetTransform().rotation) * rotationSurface); velocityVesselOrbit = vessel.orbit.GetVel(); velocityVesselSurface = velocityVesselOrbit - vessel.mainBody.getRFrmVel(coM); speedVertical = Vector3d.Dot(velocityVesselSurface, up); speedVerticalRounded = Math.Ceiling(speedVertical * 20) / 20; target = FlightGlobals.fetch.VesselTarget; node = vessel.patchedConicSolver.maneuverNodes.Count > 0 ? vessel.patchedConicSolver.maneuverNodes[0] : null; time = Planetarium.GetUniversalTime(); FetchAltitudes(); terrainHeight = altitudeASL - altitudeTrue; if (time >= lastTimePerSecond + 1) { terrainDelta = terrainHeight - lastTerrainHeight; lastTerrainHeight = terrainHeight; lastTimePerSecond = time; } horzVelocity = (velocityVesselSurface - (speedVertical * up)).magnitude; horzVelocityForward = Vector3d.Dot(velocityVesselSurface, forward); horzVelocityRight = Vector3d.Dot(velocityVesselSurface, right); atmPressure = FlightGlobals.getStaticPressure(altitudeASL, vessel.mainBody); dynamicPressure = 0.5 * velocityVesselSurface.sqrMagnitude * vessel.atmDensity; if (target != null) { targetSeparation = vessel.GetTransform().position - target.GetTransform().position; targetOrientation = target.GetTransform().rotation; targetVessel = target as Vessel; targetBody = target as CelestialBody; targetDockingNode = target as ModuleDockingNode; targetDistance = Vector3.Distance(target.GetTransform().position, vessel.GetTransform().position); // This is kind of messy. targetOrbitSensibility = false; // All celestial bodies except the sun have orbits that make sense. targetOrbitSensibility |= targetBody != null && targetBody != Planetarium.fetch.Sun; if (targetVessel != null) targetOrbitSensibility = JUtil.OrbitMakesSense(targetVessel); if (targetDockingNode != null) targetOrbitSensibility = JUtil.OrbitMakesSense(target.GetVessel()); if (targetOrbitSensibility) targetOrbit = target.GetOrbit(); // TODO: Actually, there's a lot of nonsensical cases here that need more reasonable handling. // Like what if we're targeting a vessel landed on a moon of another planet?... if (targetOrbit != null) { velocityRelativeTarget = vessel.orbit.GetVel() - target.GetOrbit().GetVel(); } else { velocityRelativeTarget = vessel.orbit.GetVel(); } // If our target is somehow our own celestial body, approach speed is equal to vertical speed. if (targetBody == vessel.mainBody) approachSpeed = speedVertical; // In all other cases, that should work. I think. approachSpeed = Vector3d.Dot(velocityRelativeTarget, (target.GetTransform().position - vessel.GetTransform().position).normalized); } else { velocityRelativeTarget = targetSeparation = Vector3d.zero; targetOrbit = null; targetDistance = 0; approachSpeed = 0; targetBody = null; targetVessel = null; targetDockingNode = null; targetOrientation = vessel.GetTransform().rotation; targetOrbitSensibility = false; } orbitSensibility = JUtil.OrbitMakesSense(vessel); if (vessel.situation == Vessel.Situations.SUB_ORBITAL || vessel.situation == Vessel.Situations.FLYING) { // Mental note: the local g taken from vessel.mainBody.GeeASL will suffice. // t = (v+sqrt(v²+2gd))/g or something. // What is the vertical component of current acceleration? double accelUp = Vector3d.Dot(vessel.acceleration, up); double altitude = altitudeTrue; if (vessel.mainBody.ocean && altitudeASL > 0.0) { // AltitudeTrue shows distance above the floor of the ocean, // so use ASL if it's closer in this case, and we're not // already below SL. altitude = Math.Min(altitudeASL, altitudeTrue); } if (accelUp < 0.0 || speedVertical >= 0.0 || Planetarium.TimeScale > 1.0) { // If accelUp is negative, we can't use it in the general // equation for finding time to impact, since it could // make the term inside the sqrt go negative. // If we're going up, we can use this as well, since // the precision is not critical. // If we are warping, accelUp is always zero, so if we // do not use this case, we would fall to the simple // formula, which is wrong. secondsToImpact = (speedVertical + Math.Sqrt(speedVertical * speedVertical + 2 * localGeeASL * altitude)) / localGeeASL; } else if (accelUp > 0.005) { // This general case takes into account vessel acceleration, // so estimates on craft that include parachutes or do // powered descents are more accurate. secondsToImpact = (speedVertical + Math.Sqrt(speedVertical * speedVertical + 2 * accelUp * altitude)) / accelUp; } else { // If accelUp is small, we get floating point precision // errors that tend to make secondsToImpact get really big. secondsToImpact = altitude / -speedVertical; } // MOARdV: I think this gets the computation right. High thrust will // result in NaN, which is already handled. /* double accelerationAtMaxThrust = localG - (totalMaximumThrust / totalShipWetMass); double timeToImpactAtMaxThrust = (speedVertical + Math.Sqrt(speedVertical * speedVertical + 2 * accelerationAtMaxThrust * altitude)) / accelerationAtMaxThrust; bestPossibleSpeedAtImpact = speedVertical - accelerationAtMaxThrust * timeToImpactAtMaxThrust; if (double.IsNaN(bestPossibleSpeedAtImpact)) bestPossibleSpeedAtImpact = 0; */ bestPossibleSpeedAtImpact = SpeedAtImpact(totalMaximumThrust, totalShipWetMass, localGeeASL, speedVertical, altitude); expectedSpeedAtImpact = SpeedAtImpact(totalCurrentThrust, totalShipWetMass, localGeeASL, speedVertical, altitude); } else { secondsToImpact = Double.NaN; bestPossibleSpeedAtImpact = 0; expectedSpeedAtImpact = 0; } }
public static void Add(Kerbulator kalc) { // Planets foreach (CelestialBody b in FlightGlobals.Bodies) { if (b.name == "Sun") { AddCelestialBody(kalc, b, "Kerbol"); } else { AddCelestialBody(kalc, b, b.name); } } Vessel v = FlightGlobals.ActiveVessel; Orbit orbit1 = v.orbit; if (v != null) { // Current orbit AddOrbit(kalc, orbit1, "Craft"); // Current position in carthesian coordinates AddVector3d(kalc, "Craft.Pos", v.GetWorldPos3D()); // Navball (thank you MechJeb source) Vector3d CoM = v.findWorldCenterOfMass(); Vector3d up = (CoM - v.mainBody.position).normalized; Vector3d north = Vector3d.Exclude(up, (v.mainBody.position + v.mainBody.transform.up * (float)v.mainBody.Radius) - CoM).normalized; Quaternion rotationSurface = Quaternion.LookRotation(north, up); Quaternion rotationVesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(v.GetTransform().rotation) * rotationSurface); Vector3d velocityVesselOrbit = v.orbit.GetVel(); Vector3d velocityVesselSurface = velocityVesselOrbit - v.mainBody.getRFrmVel(CoM); AddDouble(kalc, "Navball.Heading", rotationVesselSurface.eulerAngles.y); AddDouble(kalc, "Navball.Pitch", (rotationVesselSurface.eulerAngles.x > 180) ? (360.0 - rotationVesselSurface.eulerAngles.x) : -rotationVesselSurface.eulerAngles.x); AddDouble(kalc, "Navball.Roll", (rotationVesselSurface.eulerAngles.z > 180) ? (rotationVesselSurface.eulerAngles.z - 360.0) : rotationVesselSurface.eulerAngles.z); AddDouble(kalc, "Navball.OrbitalVelocity", velocityVesselOrbit.magnitude); AddDouble(kalc, "Navball.SurfaceVelocity", velocityVesselSurface.magnitude); AddDouble(kalc, "Navball.VerticalVelocity", Vector3d.Dot(velocityVesselSurface, up)); // Current time double UT = (double)Planetarium.GetUniversalTime(); AddDouble(kalc, "UT", UT); // Reference body AddCelestialBody(kalc, v.orbit.referenceBody, "Parent"); // Target if (FlightGlobals.fetch.VesselTarget != null) { ITargetable target = FlightGlobals.fetch.VesselTarget; Orbit orbit2 = target.GetOrbit(); // Target Orbit AddOrbit(kalc, orbit2, "Target"); // Intersection with target orbit double CD = 0.0; double CCD = 0.0; double FFp = 0.0; double FFs = 0.0; double SFp = 0.0; double SFs = 0.0; int iterationCount = 0; Orbit.FindClosestPoints(orbit1, orbit2, ref CD, ref CCD, ref FFp, ref FFs, ref SFp, ref SFs, 0.0, 100, ref iterationCount); double T1 = orbit1.GetDTforTrueAnomaly(FFp, 0.0); double T2 = orbit1.GetDTforTrueAnomaly(SFp, 0.0); AddDouble(kalc, "Craft.Inter1.dt", T1); AddDouble(kalc, "Craft.Inter1.Δt", T1); AddDouble(kalc, "Craft.Inter1.Sep", (orbit1.getPositionAtUT(T1 + UT) - orbit2.getPositionAtUT(T1 + UT)).magnitude); AddDouble(kalc, "Craft.Inter1.TrueAnomaly", orbit1.TrueAnomalyAtUT(T1 + UT)); AddDouble(kalc, "Craft.Inter1.θ", orbit1.TrueAnomalyAtUT(T1 + UT)); AddDouble(kalc, "Craft.Inter2.dt", T2); AddDouble(kalc, "Craft.Inter2.Δt", T2); AddDouble(kalc, "Craft.Inter2.Sep", (orbit1.getPositionAtUT(T2 + UT) - orbit2.getPositionAtUT(T2 + UT)).magnitude); AddDouble(kalc, "Craft.Inter2.TrueAnomaly", orbit2.TrueAnomalyAtUT(T2 + UT)); AddDouble(kalc, "Craft.Inter2.θ", orbit2.TrueAnomalyAtUT(T2 + UT)); } } }
public Orbit GetOrbit() { return(target == null? null : target.GetOrbit()); }
private void CreateTransfers(ITargetable start) { DbgFmt("Fabricating transfers around {0}", TheName(start)); if (hyperbolicOrbit && inbound) { // Just try to calculate a capture burn DbgFmt("Orbit is hyperbolic, creating transfer for capture"); transfers.Add(new TransferModel(origin, origin.GetOrbit().referenceBody)); } else { // Normal orbit, load up everything bool foundTarget = false; CelestialBody targetBody = FlightGlobals.fetch.VesselTarget as CelestialBody, first = start as CelestialBody; // If the starting point is a vessel or has no solid surface, then we can't // launch from it. if (first == null || !first.hasSolidSurface) { first = start.GetOrbit()?.referenceBody; } for (CelestialBody b = first, toSkip = start as CelestialBody; b != null; toSkip = b, b = ParentBody(b)) { DbgFmt("Checking transfers around {0}", TheName(b)); // It's worth calculating return-from-satellite burns for Eve, Kerbin, and Duna, // but not for Jool or the Sun. if (b.hasSolidSurface && b != first) { DbgFmt("Adding return-to-parent transfer to {0}", TheName(b)); transfers.Add(new TransferModel(origin, b)); } int numBodies = b.orbitingBodies.Count; for (int i = 0; i < numBodies; ++i) { CelestialBody satellite = b.orbitingBodies[i]; if (satellite != toSkip) { DbgFmt("Allocating transfer to {0}", TheName(satellite)); transfers.Add(new TransferModel(origin, satellite)); if (satellite == targetBody) { DbgFmt("Found target as satellite"); foundTarget = true; } } } if (Settings.Instance.ShowTrackedAsteroids) { // Add any tracked asteroids in this SOI. // Insertion sort into bodies according to semiMajorAxis. for (int i = 0; i < FlightGlobals.Vessels.Count; ++i) { Vessel v = FlightGlobals.Vessels[i]; if (v != start as Vessel && IsTrackedAsteroid(v) && v.GetOrbit()?.referenceBody == b) { // Loop past the end of the array to provide a chance to // append after the last entry. for (int t = 0; t < transfers.Count + 1; ++t) { if (t >= transfers.Count) { transfers.Add(new TransferModel(origin, v)); if (v == targetBody) { foundTarget = true; } break; } else if (transfers[t].destination.GetOrbit().referenceBody == b && (v.GetOrbit()?.semiMajorAxis ?? 0) < transfers[t].destination.GetOrbit().semiMajorAxis) { transfers.Insert(t, new TransferModel(origin, v)); if (v == targetBody) { foundTarget = true; } break; } } } } } if (toSkip == targetBody && targetBody != null) { DbgFmt("Found target as ancestor"); foundTarget = true; } } if (!foundTarget && FlightGlobals.ActiveVessel != null && FlightGlobals.fetch.VesselTarget != null) { DbgFmt("Allocating transfer to {0}", FlightGlobals.fetch.VesselTarget.GetName()); transfers.Insert(0, new TransferModel(origin, FlightGlobals.fetch.VesselTarget)); } } }
/// <summary> /// Updates the details by recalculating if requested. /// </summary> public void Update() { ITargetable target = null; global::Vessel vessel = null; landedSamePlanet = false; isLanded = false; overrideANDN = false; overrideANDNRev = false; if (HighLogic.LoadedSceneIsFlight) { if (FlightGlobals.fetch == null || FlightGlobals.fetch.VesselTarget == null || FlightGlobals.ActiveVessel == null || FlightGlobals.ActiveVessel.targetObject == null || FlightGlobals.ActiveVessel.targetObject.GetOrbit() == null || FlightGlobals.ship_orbit == null || FlightGlobals.ship_orbit.referenceBody == null) { ShowDetails = false; return; } else { target = FlightGlobals.ActiveVessel.targetObject; vessel = FlightGlobals.ActiveVessel; } TrackingStationSource = null; } else if (HighLogic.LoadedScene == GameScenes.TRACKSTATION) { if (PlanetariumCamera.fetch.target.type == MapObject.ObjectType.CelestialBody) { target = PlanetariumCamera.fetch.target.celestialBody; } else if (PlanetariumCamera.fetch.target.type == MapObject.ObjectType.Vessel) { target = PlanetariumCamera.fetch.target.vessel; } if (TrackingStationSource != null) { vessel = TrackingStationSource.GetVessel(); } else { TrackingStationSource = target; } } activeTarget = target; if (target == null) { ShowDetails = false; return; } ShowDetails = true; var actualSourceOrbit = vessel != null ? vessel.orbit : TrackingStationSource.GetOrbit(); var actualTargetOrbit = target.GetOrbit(); if (target is global::Vessel) { targetVessel = (global::Vessel)target; } else { targetVessel = null; } activeVessel = vessel; if (actualSourceOrbit == null) { // Debug.Log("Source orbit is null!"); TrackingStationSource = null; ShowDetails = false; return; } if (actualTargetOrbit == null) { // Debug.Log("Target orbit is null!"); ShowDetails = false; return; } isLanded = vessel != null && vessel.LandedOrSplashed; bool targetLanded = (target is global::Vessel && ((global::Vessel)target).LandedOrSplashed); landedSamePlanet = isLanded && targetLanded && actualSourceOrbit.referenceBody == actualTargetOrbit.referenceBody; var originOrbit = isLanded ? actualSourceOrbit.referenceBody.orbit : actualSourceOrbit; var targetOrbit = targetLanded ? actualTargetOrbit.referenceBody.orbit : actualTargetOrbit; if ((!isLanded && !targetLanded) || (actualSourceOrbit.referenceBody != actualTargetOrbit.referenceBody)) { findConcentricParents(ref originOrbit, ref targetOrbit); } if (originOrbit == targetOrbit && !landedSamePlanet) { targetOrbit = actualTargetOrbit; originOrbit = null; } { //These are not 'rendezvous' calculations, just raw data about the target object. AltitudeSeaLevel = targetOrbit.altitude; ApoapsisHeight = targetOrbit.ApA; PeriapsisHeight = targetOrbit.PeA; TimeToApoapsis = targetOrbit.timeToAp; TimeToPeriapsis = targetOrbit.timeToPe; SemiMajorAxis = targetOrbit.semiMajorAxis; SemiMinorAxis = targetOrbit.semiMinorAxis; OrbitalPeriod = targetOrbit.period; RelativeInclination = targetOrbit.inclination; } { //Set everything else 0 incase some are not valid. TimeToAscendingNode = 0; TimeToDescendingNode = 0; AngleToAscendingNode = 0; AngleToDescendingNode = 0; RelativeVelocity = 0; RelativeSpeed = 0; PhaseAngle = 0; InterceptAngle = 0; TimeToTransferAngle = 0; AngleToPlane[0] = 0; TimeToPlane[0] = 0; AngleToPlane[1] = 0; TimeToPlane[1] = 0; Distance = 0; TimeTilEncounter = double.NaN; SeparationAtEncounter = double.NaN; SpeedAtEncounter = double.NaN; Orbital.ManoeuvreNode.ManoeuvreProcessor.PostBurnRelativeInclination = 0; } if (originOrbit != null) //Actually calculating an encounter with 2 different things. { overrideANDN = isLanded && actualSourceOrbit.referenceBody == targetOrbit.referenceBody; overrideANDNRev = targetLanded && !isLanded && actualTargetOrbit.referenceBody == actualSourceOrbit.referenceBody && target.GetVessel() != null; bodyRotationPeriod = actualSourceOrbit.referenceBody.rotationPeriod; if (landedSamePlanet) //this should only occur when landed targeting something else landed on same body. { AltitudeSeaLevel = target.GetVessel().altitude; ApoapsisHeight = 0; PeriapsisHeight = 0; TimeToApoapsis = 0; TimeToPeriapsis = 0; SemiMajorAxis = 0; SemiMinorAxis = 0; Distance = Vector3d.Distance(target.GetVessel().GetWorldPos3D(), vessel.GetWorldPos3D()); OrbitalPeriod = bodyRotationPeriod; } else if (overrideANDN) //launching { if (vessel != null) { AngleToPlane = CalcAngleToPlane(vessel.GetOrbit().referenceBody, vessel.latitude, vessel.longitude, targetOrbit); TimeToPlane[0] = (AngleToPlane[0] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod; TimeToPlane[1] = (AngleToPlane[1] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod; } RelativeInclination = targetOrbit.inclination; PhaseAngle = OrbitExtensions.GetPhaseAngle(actualSourceOrbit, actualTargetOrbit); //this works for some reason. } else if (overrideANDNRev) //landing { global::Vessel tgt = target.GetVessel(); if (vessel != null) { AngleToPlane = CalcAngleToPlane(vessel.GetOrbit().referenceBody, tgt.latitude, tgt.longitude, originOrbit); TimeToPlane[0] = (AngleToPlane[0] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod; TimeToPlane[1] = (AngleToPlane[1] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod; } RelativeInclination = originOrbit.inclination; Distance = Vector3d.Distance(target.GetVessel().GetWorldPos3D(), vessel.GetWorldPos3D()); AltitudeSeaLevel = tgt.altitude; PhaseAngle = OrbitExtensions.GetPhaseAngle(actualSourceOrbit, actualTargetOrbit); //this works for some reason. } else //standard 2 orbits { RelativeInclination = OrbitExtensions.GetRelativeInclination(originOrbit, targetOrbit); if (FlightGlobals.ActiveVessel == null || FlightGlobals.ActiveVessel.patchedConicSolver == null || FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes == null || FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes.Count == 0) { } else { var node = FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes[0]; if (node != null && node.nextPatch != null) { Orbital.ManoeuvreNode.ManoeuvreProcessor.PostBurnRelativeInclination = OrbitExtensions.GetRelativeInclination(node.nextPatch, FlightGlobals.ActiveVessel.targetObject.GetOrbit()); } } RelativeSpeed = originOrbit.GetRelativeVel().magnitude - target.GetObtVelocity().magnitude; RelativeVelocity = (originOrbit.GetRelativeVel() - target.GetObtVelocity()).magnitude; // FlightGlobals.ship_tgtVelocity = FlightGlobals.ship_obtVelocity - this.VesselTarget.GetObtVelocity(); // FlightGlobals.ship_tgtSpeed = FlightGlobals.ship_tgtVelocity.magnitude; PhaseAngle = OrbitExtensions.GetPhaseAngle(originOrbit, targetOrbit); InterceptAngle = CalcInterceptAngle(targetOrbit, originOrbit); double tspd = 360 / targetOrbit.period; double sspd = 360 / originOrbit.period; if (PhaseAngle < 0) { double diff = InterceptAngle - PhaseAngle; if (diff < 0) { diff += 360; } if (diff > 340) { diff -= 360; } TimeToTransferAngle = sspd == tspd ? 0 : diff / (tspd - sspd); } else { double diff = PhaseAngle - InterceptAngle; if (diff < 0) { diff += 360; } if (diff > 340) { diff -= 360; } TimeToTransferAngle = sspd == tspd ? 0 : diff / (sspd - tspd); } TimeToAscendingNode = OrbitExtensions.GetTimeToVector(originOrbit, GetAscendingNode(targetOrbit, originOrbit)); TimeToDescendingNode = OrbitExtensions.GetTimeToVector(originOrbit, GetDescendingNode(targetOrbit, originOrbit)); AngleToAscendingNode = OrbitExtensions.GetAngleToVector(originOrbit, GetAscendingNode(targetOrbit, originOrbit)); AngleToDescendingNode = OrbitExtensions.GetAngleToVector(originOrbit, GetDescendingNode(targetOrbit, originOrbit)); Distance = Vector3d.Distance(targetOrbit.pos, originOrbit.pos); //From OrbitTargeter double tOne = 0; if (target is CelestialBody) { Vector3d relativePositionAtUT = originOrbit.getRelativePositionAtUT(originOrbit.closestTgtApprUT); Vector3d relativePositionAtUT2 = targetOrbit.getRelativePositionAtUT(originOrbit.closestTgtApprUT); double separation = (relativePositionAtUT - relativePositionAtUT2).magnitude; tOne = originOrbit.closestTgtApprUT; } else { double num3 = 0.0; double num4 = 0.0; double num5 = 0.0; double eVs = 0.0; double num6 = 0.0; double eVs2 = 0.0; int iterations = 0; int num7 = Orbit.FindClosestPoints(originOrbit, targetOrbit, ref num3, ref num4, ref num5, ref eVs, ref num6, ref eVs2, 0.0001, 20, ref iterations); tOne = originOrbit.StartUT + originOrbit.GetDTforTrueAnomaly(num5, 0.0); double tTwo = originOrbit.StartUT + originOrbit.GetDTforTrueAnomaly(num6, 0.0); if (tOne > tTwo) { UtilMath.SwapValues(ref tOne, ref tTwo); UtilMath.SwapValues(ref num5, ref num6); UtilMath.SwapValues(ref eVs, ref eVs2); } } if (tOne > originOrbit.StartUT) { TimeTilEncounter = tOne - originOrbit.StartUT; SeparationAtEncounter = (originOrbit.getPositionAtUT(tOne) - targetOrbit.getPositionAtUT(tOne)).magnitude; SpeedAtEncounter = Math.Abs(originOrbit.getOrbitalSpeedAt(tOne) - targetOrbit.getOrbitalSpeedAt(tOne)); } } } if (actualTargetOrbit != targetOrbit) { targetDisplay = findNameForOrbit(targetOrbit, target); } else { targetDisplay = null; } if (originOrbit == null) { sourceDisplay = "N/A"; } else if (actualSourceOrbit != originOrbit || HighLogic.LoadedScene == GameScenes.TRACKSTATION) { sourceDisplay = findNameForOrbit(originOrbit, vessel != null ? vessel : TrackingStationSource); } else { sourceDisplay = null; } }
/// <summary> /// Draws the target information when selected. /// </summary> private void DrawTarget(Unity.Flight.ISectionModule section) { ITargetable target = Flight.Readouts.Rendezvous.RendezvousProcessor.activeTarget; this.ResizeRequested = true; if (target != null) { if (HighLogic.LoadedSceneIsFlight) { if (GUILayout.Button("Go Back to Target Selection", this.ButtonStyle, GUILayout.Width(this.ContentWidth))) { FlightGlobals.fetch.SetVesselTarget(null); } } else { if (RendezvousProcessor.TrackingStationSource != target) { if (GUILayout.Button("Use " + RendezvousProcessor.nameForTargetable(target) + " As Reference", this.ButtonStyle, GUILayout.Width(this.ContentWidth))) { RendezvousProcessor.TrackingStationSource = target; } } } if (HighLogic.LoadedSceneIsFlight) { var act = FlightGlobals.ActiveVessel; if (!(target is CelestialBody) && GUILayout.Button("Switch to Target", this.ButtonStyle, GUILayout.Width(this.ContentWidth))) { FlightEngineerCore.SwitchToVessel(target.GetVessel(), act); } bool focusable = (target is CelestialBody || target is global::Vessel); if (focusable) { MapObject targMo = null; if (target is global::Vessel) { targMo = ((global::Vessel)(target)).mapObject; } else { targMo = ((CelestialBody)(target)).MapObject; } bool shouldFocus = targMo != null && (targMo != PlanetariumCamera.fetch.target || !MapView.MapIsEnabled); if (shouldFocus && GUILayout.Button("Focus Target", this.ButtonStyle, GUILayout.Width(this.ContentWidth))) { wasMapview = MapView.MapIsEnabled; MapView.EnterMapView(); PlanetariumCamera.fetch.SetTarget(targMo); } } bool switchBack = PlanetariumCamera.fetch.target != act.mapObject; if (switchBack && MapView.MapIsEnabled && GUILayout.Button("Focus Vessel", this.ButtonStyle, GUILayout.Width(this.ContentWidth))) { if (!wasMapview) { MapView.ExitMapView(); } PlanetariumCamera.fetch.SetTarget(act.mapObject); } if (FlightCamera.fetch.mode != FlightCamera.Modes.LOCKED && !MapView.MapIsEnabled && GUILayout.Button("Look at Target", this.ButtonStyle, GUILayout.Width(this.ContentWidth))) { var pcam = PlanetariumCamera.fetch; var fcam = FlightCamera.fetch; Vector3 from = new Vector3(); if (target is global::Vessel && ((global::Vessel)target).LandedOrSplashed) { from = ((global::Vessel)target).GetWorldPos3D(); } else { //I don't think it's possible to target the sun so this should always work but who knows. if (target.GetOrbit() != null) { from = target.GetOrbit().getTruePositionAtUT(Planetarium.GetUniversalTime()); } } Vector3 to = FlightGlobals.fetch.activeVessel.GetWorldPos3D(); // float pdist = pcam.Distance; float fdist = fcam.Distance; Vector3 n = (from - to).normalized; if (!n.IsInvalid()) { // pcam.SetCamCoordsFromPosition(n * -pdist); //this does weird stuff fcam.SetCamCoordsFromPosition(n * -fdist); } } } GUILayout.Space(3f); this.DrawLine("Selected Target", RendezvousProcessor.nameForTargetable(target), section.IsHud); if (RendezvousProcessor.sourceDisplay != null) { if (RendezvousProcessor.landedSamePlanet || RendezvousProcessor.overrideANDN) { this.DrawLine("Ref Orbit", "Landed on " + RendezvousProcessor.activeVessel.GetOrbit().referenceBody.GetName(), section.IsHud); } else { this.DrawLine("Ref Orbit", RendezvousProcessor.sourceDisplay, section.IsHud); } } if (RendezvousProcessor.targetDisplay != null) { if (RendezvousProcessor.landedSamePlanet || RendezvousProcessor.overrideANDNRev) { this.DrawLine("Target Orbit", "Landed on " + target.GetOrbit().referenceBody.GetName(), section.IsHud); } else { this.DrawLine("Target Orbit", RendezvousProcessor.targetDisplay, section.IsHud); } } } }
public static void Add(Kerbulator kalc) { // Planets foreach (CelestialBody b in FlightGlobals.Bodies) { if (b.name == "Sun") { AddCelestialBody(kalc, b, "Sun"); AddCelestialBody(kalc, b, "Kerbol"); } else { AddCelestialBody(kalc, b, b.name); } } // Current time double UT = (double)Planetarium.GetUniversalTime(); AddDouble(kalc, "UT", UT); Vessel v = FlightGlobals.ActiveVessel; if (v != null) { // Mission time AddDouble(kalc, "MissionTime", v.missionTime); // Current orbit Orbit orbit1 = v.orbit; AddOrbit(kalc, orbit1, "Craft"); // Navball (thank you MechJeb source) Vector3 CoM = v.CoM; Vector3 up = v.up; Vector3 north = v.north; Quaternion rotationSurface = Quaternion.LookRotation(north, up); Quaternion rotationVesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(v.GetTransform().rotation) * rotationSurface); Vector3 velocityVesselOrbit = v.orbit.GetVel(); Vector3 velocityVesselSurface = velocityVesselOrbit - v.mainBody.getRFrmVel(CoM); AddDouble(kalc, "Navball.Heading", rotationVesselSurface.eulerAngles.y); AddDouble(kalc, "Navball.Pitch", (rotationVesselSurface.eulerAngles.x > 180) ? (360.0 - rotationVesselSurface.eulerAngles.x) : -rotationVesselSurface.eulerAngles.x); AddDouble(kalc, "Navball.Roll", (rotationVesselSurface.eulerAngles.z > 180) ? (rotationVesselSurface.eulerAngles.z - 360.0) : rotationVesselSurface.eulerAngles.z); AddDouble(kalc, "Navball.OrbitalVelocity", velocityVesselOrbit.magnitude); AddDouble(kalc, "Navball.SurfaceVelocity", v.srfSpeed); AddDouble(kalc, "Navball.VerticalVelocity", v.verticalSpeed); // Reference body AddCelestialBody(kalc, v.orbit.referenceBody, "Parent"); // Target if (FlightGlobals.fetch.VesselTarget != null) { ITargetable target = FlightGlobals.fetch.VesselTarget; Orbit orbit2 = target.GetOrbit(); // Target Orbit AddOrbit(kalc, orbit2, "Target"); // Intersection with target orbit double CD = 0.0; double CCD = 0.0; double FFp = 0.0; double FFs = 0.0; double SFp = 0.0; double SFs = 0.0; int iterationCount = 0; Orbit.FindClosestPoints(orbit1, orbit2, ref CD, ref CCD, ref FFp, ref FFs, ref SFp, ref SFs, 0.0, 100, ref iterationCount); double t1 = orbit1.GetDTforTrueAnomaly(FFp, 0.0); double t2 = orbit1.GetDTforTrueAnomaly(SFp, 0.0); double T1 = Math.Min(t1, t2); double T2 = Math.Max(t1, t2); AddDouble(kalc, "Craft.Inter1.dt", T1); AddDouble(kalc, "Craft.Inter1.Δt", T1); AddDouble(kalc, "Craft.Inter1.Sep", (orbit1.getPositionAtUT(T1 + UT) - orbit2.getPositionAtUT(T1 + UT)).magnitude); AddDouble(kalc, "Craft.Inter1.TrueAnomaly", orbit1.TrueAnomalyAtUT(T1 + UT) * (180 / Math.PI)); AddDouble(kalc, "Craft.Inter1.θ", orbit1.TrueAnomalyAtUT(T1 + UT) * (180 / Math.PI)); AddDouble(kalc, "Craft.Inter2.dt", T2); AddDouble(kalc, "Craft.Inter2.Δt", T2); AddDouble(kalc, "Craft.Inter2.Sep", (orbit1.getPositionAtUT(T2 + UT) - orbit2.getPositionAtUT(T2 + UT)).magnitude); AddDouble(kalc, "Craft.Inter2.TrueAnomaly", orbit2.TrueAnomalyAtUT(T2 + UT) * (180 / Math.PI)); AddDouble(kalc, "Craft.Inter2.θ", orbit2.TrueAnomalyAtUT(T2 + UT) * (180 / Math.PI)); // Relative Ascending and Descending Nodes, Inclination AddDouble(kalc, "Craft.Rel.AN", orbit1.GetTrueAnomalyOfZupVector(Vector3.Cross(orbit2.GetOrbitNormal(), orbit1.GetOrbitNormal())) * (180 / Math.PI)); AddDouble(kalc, "Craft.Rel.DN", orbit1.GetTrueAnomalyOfZupVector(Vector3.Cross(orbit1.GetOrbitNormal(), orbit2.GetOrbitNormal())) * (180 / Math.PI)); AddDouble(kalc, "Craft.Rel.Inc", Vector3.Angle(orbit1.GetOrbitNormal(), orbit2.GetOrbitNormal())); } } }