public static NavHeading WorldVecToNavHeading(Vector3d up, Vector3d north, Vector3d east, Vector3d v) { NavHeading ret = new NavHeading(); ret.Pitch = (float)-(Vector3d.Angle(up, v) - 90.0f); Vector3d progradeFlat = Vector3d.Exclude(up, v); float NAngle = (float)Vector3d.Angle(north, progradeFlat); float EAngle = (float)Vector3d.Angle(east, progradeFlat); if (EAngle < 90) { ret.Heading = NAngle; } else { ret.Heading = -NAngle + 360; } return(ret); }
/// <summary> /// Runs a timer. If the refresh time is exceed updates all vessel data and /// triggers a VesselDataInvalidated event. /// </summary> public void UpdateVesselData() { if (FlightGlobals.ActiveVessel != null) { bool vesselChanged = false; if (_activeVessel == null || _activeVessel.id != FlightGlobals.ActiveVessel.id) { vesselChanged = true; } if (vesselChanged) { _activeVessel = FlightGlobals.ActiveVessel; _vData.vesselSync++; if (_vData.vesselSync == 0) { _vData.vesselSync++; } _vesselSync = _vData.vesselSync; } _theTime = Time.unscaledTime; if ((_theTime - _lastUpdate) * 1000 > _refreshrate) { IOResource TempR = new IOResource(); Vessel ActiveVessel = FlightGlobals.ActiveVessel; _lastUpdate = _theTime; List <Part> ActiveEngines = new List <Part>(); ActiveEngines = GetListOfActivatedEngines(ActiveVessel); _vData.AP = (float)ActiveVessel.orbit.ApA; _vData.PE = (float)ActiveVessel.orbit.PeA; _vData.SemiMajorAxis = (float)ActiveVessel.orbit.semiMajorAxis; _vData.SemiMinorAxis = (float)ActiveVessel.orbit.semiMinorAxis; _vData.e = (float)ActiveVessel.orbit.eccentricity; _vData.inc = (float)ActiveVessel.orbit.inclination; _vData.VVI = (float)ActiveVessel.verticalSpeed; _vData.G = (float)ActiveVessel.geeForce; _vData.TAp = (int)Math.Round(ActiveVessel.orbit.timeToAp); _vData.TPe = (int)Math.Round(ActiveVessel.orbit.timeToPe); _vData.Density = (float)ActiveVessel.atmDensity; _vData.TrueAnomaly = (float)ActiveVessel.orbit.trueAnomaly; _vData.period = (int)Math.Round(ActiveVessel.orbit.period); double ASL = ActiveVessel.mainBody.GetAltitude(ActiveVessel.CoM); double AGL = (ASL - ActiveVessel.terrainAltitude); if (AGL < ASL) { _vData.RAlt = (float)AGL; } else { _vData.RAlt = (float)ASL; } _vData.Alt = (float)ASL; _vData.Vsurf = (float)ActiveVessel.srfSpeed; _vData.Lat = (float)ActiveVessel.latitude; _vData.Lon = (float)ActiveVessel.longitude; TempR = GetResourceTotal(ActiveVessel, "LiquidFuel"); _vData.LiquidFuelTot = TempR.Max; _vData.LiquidFuel = TempR.Current; _vData.LiquidFuelTotS = (float)ProspectForResourceMax("LiquidFuel", ActiveEngines); _vData.LiquidFuelS = (float)ProspectForResource("LiquidFuel", ActiveEngines); TempR = GetResourceTotal(ActiveVessel, "Oxidizer"); _vData.OxidizerTot = TempR.Max; _vData.Oxidizer = TempR.Current; _vData.OxidizerTotS = (float)ProspectForResourceMax("Oxidizer", ActiveEngines); _vData.OxidizerS = (float)ProspectForResource("Oxidizer", ActiveEngines); TempR = GetResourceTotal(ActiveVessel, "ElectricCharge"); _vData.EChargeTot = TempR.Max; _vData.ECharge = TempR.Current; TempR = GetResourceTotal(ActiveVessel, "MonoPropellant"); _vData.MonoPropTot = TempR.Max; _vData.MonoProp = TempR.Current; TempR = GetResourceTotal(ActiveVessel, "IntakeAir"); _vData.IntakeAirTot = TempR.Max; _vData.IntakeAir = TempR.Current; TempR = GetResourceTotal(ActiveVessel, "SolidFuel"); _vData.SolidFuelTot = TempR.Max; _vData.SolidFuel = TempR.Current; TempR = GetResourceTotal(ActiveVessel, "XenonGas"); _vData.XenonGasTot = TempR.Max; _vData.XenonGas = TempR.Current; _missionTime = ActiveVessel.missionTime; _deltaT = _missionTime - _missionTimeOld; _missionTimeOld = _missionTime; _vData.MissionTime = (UInt32)Math.Round(_missionTime); _vData.deltaTime = (float)_deltaT; _vData.VOrbit = (float)ActiveVessel.orbit.GetVel().magnitude; Vector3d CoM, north, up, east; Quaternion rotationSurface; CoM = ActiveVessel.CoM; up = (CoM - ActiveVessel.mainBody.position).normalized; north = Vector3d.Exclude(up, (ActiveVessel.mainBody.position + ActiveVessel.mainBody.transform.up * (float)ActiveVessel.mainBody.Radius) - CoM).normalized; east = Vector3d.Cross(up, north); rotationSurface = Quaternion.LookRotation(north, up); Vector3d attitude = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(ActiveVessel.GetTransform().rotation) * rotationSurface).eulerAngles; _vData.Roll = ToScaledUInt((attitude.z > 180) ? (attitude.z - 360.0) : attitude.z); _vData.Pitch = ToScaledUInt((attitude.x > 180) ? (attitude.x - 360.0) : attitude.x); _vData.Heading = ToScaledUInt((attitude.y > 180) ? (attitude.y - 360.0) : attitude.y); Vector3d prograde = new Vector3d(0, 0, 0); switch (FlightGlobals.speedDisplayMode) { case FlightGlobals.SpeedDisplayModes.Surface: prograde = ActiveVessel.srf_velocity.normalized; break; case FlightGlobals.SpeedDisplayModes.Orbit: prograde = ActiveVessel.obt_velocity.normalized; break; case FlightGlobals.SpeedDisplayModes.Target: prograde = FlightGlobals.ship_tgtVelocity; break; } NavHeading zeroHeading; zeroHeading.Pitch = zeroHeading.Heading = 0; NavHeading Prograde = WorldVecToNavHeading(up, north, east, prograde), Target = zeroHeading, Maneuver = zeroHeading; _vData.ProgradeHeading = ToScaledUInt(Prograde.Heading); _vData.ProgradePitch = ToScaledUInt(Prograde.Pitch); if (TargetExists()) { _vData.TargetDist = (float)Vector3.Distance(FlightGlobals.fetch.VesselTarget.GetVessel().transform.position, ActiveVessel.transform.position); _vData.TargetV = (float)FlightGlobals.ship_tgtVelocity.magnitude; Target = WorldVecToNavHeading(up, north, east, ActiveVessel.targetObject.GetTransform().position - ActiveVessel.transform.position); } _vData.TargetHeading = ToScaledUInt(Target.Heading); _vData.TargetPitch = ToScaledUInt(Target.Pitch); _vData.NormalHeading = ToScaledUInt(WorldVecToNavHeading(up, north, east, Vector3d.Cross(ActiveVessel.obt_velocity.normalized, up)).Heading); _vData.MNTime = 0; _vData.MNDeltaV = 0; if (ActiveVessel.patchedConicSolver != null) { if (ActiveVessel.patchedConicSolver.maneuverNodes != null) { if (ActiveVessel.patchedConicSolver.maneuverNodes.Count > 0) { _vData.MNTime = (UInt32)Math.Round(ActiveVessel.patchedConicSolver.maneuverNodes[0].UT - Planetarium.GetUniversalTime()); _vData.MNDeltaV = (float)ActiveVessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(ActiveVessel.patchedConicSolver.maneuverNodes[0].patch).magnitude; //Added JS Maneuver = WorldVecToNavHeading(up, north, east, ActiveVessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(ActiveVessel.patchedConicSolver.maneuverNodes[0].patch)); } } } _vData.ManeuverHeading = ToScaledUInt(Maneuver.Heading); _vData.ManeuverPitch = ToScaledUInt(Maneuver.Pitch); ControlStatus((int)EnumAG.SAS, ActiveVessel.ActionGroups[KSPActionGroup.SAS]); ControlStatus((int)EnumAG.RCS, ActiveVessel.ActionGroups[KSPActionGroup.RCS]); ControlStatus((int)EnumAG.Light, ActiveVessel.ActionGroups[KSPActionGroup.Light]); ControlStatus((int)EnumAG.Gear, ActiveVessel.ActionGroups[KSPActionGroup.Gear]); ControlStatus((int)EnumAG.Brakes, ActiveVessel.ActionGroups[KSPActionGroup.Brakes]); ControlStatus((int)EnumAG.Abort, ActiveVessel.ActionGroups[KSPActionGroup.Abort]); ControlStatus((int)EnumAG.Custom01, ActiveVessel.ActionGroups[KSPActionGroup.Custom01]); ControlStatus((int)EnumAG.Custom02, ActiveVessel.ActionGroups[KSPActionGroup.Custom02]); ControlStatus((int)EnumAG.Custom03, ActiveVessel.ActionGroups[KSPActionGroup.Custom03]); ControlStatus((int)EnumAG.Custom04, ActiveVessel.ActionGroups[KSPActionGroup.Custom04]); ControlStatus((int)EnumAG.Custom05, ActiveVessel.ActionGroups[KSPActionGroup.Custom05]); ControlStatus((int)EnumAG.Custom06, ActiveVessel.ActionGroups[KSPActionGroup.Custom06]); ControlStatus((int)EnumAG.Custom07, ActiveVessel.ActionGroups[KSPActionGroup.Custom07]); ControlStatus((int)EnumAG.Custom08, ActiveVessel.ActionGroups[KSPActionGroup.Custom08]); ControlStatus((int)EnumAG.Custom09, ActiveVessel.ActionGroups[KSPActionGroup.Custom09]); ControlStatus((int)EnumAG.Custom10, ActiveVessel.ActionGroups[KSPActionGroup.Custom10]); if (ActiveVessel.orbit.referenceBody != null) { _vData.SOINumber = GetSOINumber(ActiveVessel.orbit.referenceBody.name); } _vData.MaxOverHeat = GetMaxOverHeat(ActiveVessel); _vData.MachNumber = (float)ActiveVessel.mach; _vData.IAS = (float)ActiveVessel.indicatedAirSpeed; _vData.CurrentStage = (byte)StageManager.CurrentStage; _vData.TotalStage = (byte)StageManager.StageCount; _vData.NavballSASMode = (byte)(((int)FlightGlobals.speedDisplayMode + 1) << 4); //get navball speed display mode if (ActiveVessel.ActionGroups[KSPActionGroup.SAS]) { _vData.NavballSASMode = (byte)(((int)FlightGlobals.ActiveVessel.Autopilot.Mode + 1) | _vData.NavballSASMode); } //target distance and velocity stuff _vData.TargetDist = 0; _vData.TargetV = 0; if (TargetExists()) { _vData.TargetDist = (float)Vector3.Distance(FlightGlobals.fetch.VesselTarget.GetVessel().transform.position, ActiveVessel.transform.position); _vData.TargetV = (float)FlightGlobals.ship_tgtVelocity.magnitude; } _vData.NavballSASMode = (byte)(((int)FlightGlobals.speedDisplayMode + 1) << 4); //get navball speed display mode if (ActiveVessel.ActionGroups[KSPActionGroup.SAS]) { _vData.NavballSASMode = (byte)(((int)FlightGlobals.ActiveVessel.Autopilot.Mode + 1) | _vData.NavballSASMode); } //Notify listeners NotifyInvalidate(_vData); } } }