public static Approx ( Vector3 val, Vector3 about, float range ) : bool | ||
val | Vector3 | |
about | Vector3 | |
range | float | |
Résultat | bool |
public void PreUpdateState(FlightCtrlState s) { //update control info PreUpdateControls = s; IsActiveVessel = vessel != null && vessel == FlightGlobals.ActiveVessel; HasUserInput = !Mathfx.Approx(PreUpdateControls.pitch, PreUpdateControls.pitchTrim, 0.01f) || !Mathfx.Approx(PreUpdateControls.roll, PreUpdateControls.rollTrim, 0.01f) || !Mathfx.Approx(PreUpdateControls.yaw, PreUpdateControls.yawTrim, 0.01f); AutopilotDisabled = HasUserInput; //update onPlanet state var on_planet = vessel.OnPlanet(); var in_orbit = vessel.InOrbit(); if(on_planet != OnPlanet) { if(CFG.Enabled) CFG.EnginesProfiles.OnPlanetChanged(on_planet); if(!on_planet) { if(CFG.BlockThrottle) { var THR = TCA.GetModule<ThrottleControl>(); if(THR != null) THR.Throttle = 0f; } CFG.DisableVSC(); CFG.Nav.Off(); CFG.HF.Off(); if(IsActiveVessel && TCAGui.Instance.ORB != null) TCAGui.Instance.ActiveTab = TCAGui.Instance.ORB; } } OnPlanet = on_planet; InOrbit = in_orbit; }
private void SetFlightCtrlState(Vector3d act, Vector3d deltaEuler, FlightCtrlState s, double precision, float drive_limit) { bool userCommandingPitchYaw = (Mathfx.Approx(s.pitch, s.pitchTrim, 0.1F) ? false : true) || (Mathfx.Approx(s.yaw, s.yawTrim, 0.1F) ? false : true); bool userCommandingRoll = (Mathfx.Approx(s.roll, s.rollTrim, 0.1F) ? false : true); if (userCommandingPitchYaw || userCommandingRoll) { pid.Reset(); part.vessel.ActionGroups.SetGroup(KSPActionGroup.SAS, false); if (attitudeKILLROT) { attitudeTo(Quaternion.LookRotation(vessel.GetTransform().up, -vessel.GetTransform().forward), AttitudeReference.INERTIAL, null); } } else { double int_error = Math.Abs(Vector3d.Angle(attitudeGetReferenceRotation(attitudeReference) * attitudeTarget * Vector3d.forward, vesselState.forward)); part.vessel.ActionGroups.SetGroup(KSPActionGroup.SAS, false); } if (!attitudeRollMatters) { attitudeTo(Quaternion.LookRotation(attitudeTarget * Vector3d.forward, attitudeWorldToReference(-vessel.GetTransform().forward, attitudeReference)), attitudeReference, null); _attitudeRollMatters = false; } if (!userCommandingRoll) { if (!double.IsNaN(act.z)) { s.roll = Mathf.Clamp((float)(act.z), -drive_limit, drive_limit); } if (Math.Abs(s.roll) < 0.05) { s.roll = 0; } } if (!userCommandingPitchYaw) { if (!double.IsNaN(act.x)) { s.pitch = Mathf.Clamp((float)(act.x), -drive_limit, drive_limit); } if (!double.IsNaN(act.y)) { s.yaw = Mathf.Clamp((float)(act.y), -drive_limit, drive_limit); } if (Math.Abs(s.pitch) < 0.05) { s.pitch = 0; } if (Math.Abs(s.yaw) < 0.05) { s.yaw = 0; } } }
public void UpdateAutopilotInfo(FlightCtrlState s) { if (!CFG.Enabled) { return; } Controls.GimbalLimit = 100; HasUserInput = !Mathfx.Approx(s.pitch, s.pitchTrim, 0.01f) || !Mathfx.Approx(s.roll, s.rollTrim, 0.01f) || !Mathfx.Approx(s.yaw, s.yawTrim, 0.01f); AutopilotDisabled = HasUserInput; }
private void calculateSteering(FlightCtrlState s) { if (!isActive) { return; } HasUserInput = !Mathfx.Approx(s.pitch, s.pitchTrim, GLB.USER_INPUT_TOL) || !Mathfx.Approx(s.roll, s.rollTrim, GLB.USER_INPUT_TOL) || !Mathfx.Approx(s.yaw, s.yawTrim, GLB.USER_INPUT_TOL); if (HasUserInput) { return; } steering.Zero(); var AV = vessel.angularVelocity * Mathf.Rad2Deg; if (launchParams != null && launchParams.Valid && !launchParams.maneuverStarted) { UpdateAttitudeError(); var torque = getTorque(out var nonRcsTorque); var maxAA = Utils.AngularAcceleration(torque, vessel.MOI) * Mathf.Rad2Deg; // x is direct error, y is pitch; see AttitudeError description steering.x = pitchController.Update(AttitudeError.y, -AV.x, maxAA.x); steering.z = yawController.Update(AttitudeError.z, -AV.z, maxAA.z); // disable RCS to fine-tune attitude host.vessel.ActionGroups.SetGroup(KSPActionGroup.RCS, AttitudeError.x > GLB.MAX_ATTITUDE_ERROR || nonRcsTorque.IsZero()); } else { pitchPID.Update(AV.x); steering.x = pitchPID.Action; yawPID.Update(AV.z); steering.z = yawPID.Action; } rollPID.Update(AV.y); steering.y = rollPID.Action; }
private void FixedUpdate() { if (FocusedObject) { CameraTarget = FocusedObject.position; } //Actual Camera Rig Transformations Quaternion QT = Quaternion.Euler(m_localRotation.y, m_localRotation.x, 0); m_pivotPosition.rotation = Quaternion.Lerp(m_pivotPosition.rotation, QT, Time.deltaTime * orbitDampening); //Handle zooming. if (m_cameraPosition.localPosition.z != ZoomLevel * -1f) { m_cameraPosition.localPosition = new Vector3(0f, 0f, Mathf.Lerp(m_cameraPosition.localPosition.z, ZoomLevel * -1f, .1f));//Time.deltaTime * scrollDampening)); } //Handle camera offset. if (!Mathfx.Approx(m_cameraPosition.parent.localPosition, CameraOffset, 0.05f)) { m_cameraPosition.parent.localPosition = Mathfx.Hermite(m_cameraPosition.parent.localPosition, CameraOffset, .2f); } else { m_cameraPosition.parent.localPosition = CameraOffset; } //Handle camera movement. if (!Mathfx.Approx(m_pivotPosition.position, CameraTarget, 0.05f)) { m_pivotPosition.position = Mathfx.Hermite(m_pivotPosition.position, CameraTarget, .2f); } else { m_pivotPosition.position = CameraTarget; } }
private void SetFlightCtrlState(Vector3d act, Vector3d deltaEuler, FlightCtrlState s, float drive_limit) { bool userCommandingPitchYaw = (Mathfx.Approx(s.pitch, s.pitchTrim, 0.1F) ? false : true) || (Mathfx.Approx(s.yaw, s.yawTrim, 0.1F) ? false : true); bool userCommandingRoll = (Mathfx.Approx(s.roll, s.rollTrim, 0.1F) ? false : true); // Disable the new SAS so it won't interfere. But enable it while in timewarp for compatibility with PersistentRotation if (TimeWarp.WarpMode != TimeWarp.Modes.HIGH || TimeWarp.CurrentRateIndex == 0) { part.vessel.ActionGroups.SetGroup(KSPActionGroup.SAS, false); } if (attitudeKILLROT) { if (lastReferencePart != vessel.GetReferenceTransformPart() || userCommandingPitchYaw || userCommandingRoll) { attitudeTo(Quaternion.LookRotation(vessel.GetTransform().up, -vessel.GetTransform().forward), AttitudeReference.INERTIAL, null); lastReferencePart = vessel.GetReferenceTransformPart(); } } if (userCommandingPitchYaw || userCommandingRoll) { pid.Reset(); } if (!userCommandingRoll) { if (!double.IsNaN(act.z)) { s.roll = Mathf.Clamp((float)(act.z), -drive_limit, drive_limit); } } if (!userCommandingPitchYaw) { if (!double.IsNaN(act.x)) { s.pitch = Mathf.Clamp((float)(act.x), -drive_limit, drive_limit); } if (!double.IsNaN(act.y)) { s.yaw = Mathf.Clamp((float)(act.y), -drive_limit, drive_limit); } } // RCS and SAS control: Vector3d absErr; // Absolute error (exag º) absErr.x = Math.Abs(deltaEuler.x); absErr.y = Math.Abs(deltaEuler.y); absErr.z = Math.Abs(deltaEuler.z); if ((absErr.x < 0.4) && (absErr.y < 0.4) && (absErr.z < 0.4)) { if (timeCount < 50) { timeCount++; } else { if (RCS_auto) { if (attitudeRCScontrol && core.rcs.users.Count == 0) { part.vessel.ActionGroups.SetGroup(KSPActionGroup.RCS, false); } } } } else if ((absErr.x > 1.0) || (absErr.y > 1.0) || (absErr.z > 1.0)) { timeCount = 0; if (RCS_auto && ((absErr.x > 3.0) || (absErr.y > 3.0) || (absErr.z > 3.0))) { if (attitudeRCScontrol) { part.vessel.ActionGroups.SetGroup(KSPActionGroup.RCS, true); } } } } // end of SetFlightCtrlState
public override void Drive(FlightCtrlState s) { float threshold = 0.1F; bool _userCommandingRotation = !(Mathfx.Approx(s.pitch, s.pitchTrim, threshold) && Mathfx.Approx(s.yaw, s.yawTrim, threshold) && Mathfx.Approx(s.roll, s.rollTrim, threshold)); bool _userCommandingTranslation = !(Math.Abs(s.X) < threshold && Math.Abs(s.Y) < threshold && Math.Abs(s.Z) < threshold); if (_userCommandingRotation && !_userCommandingTranslation) { userCommandingRotationSmoothed = 2; } else if (userCommandingRotationSmoothed > 0) { userCommandingRotationSmoothed--; } if (core.GetComputerModule <MechJebModuleThrustWindow>().hidden&& core.GetComputerModule <MechJebModuleAscentGuidance>().hidden) { return; } if ((tmode != TMode.OFF) && (vesselState.thrustAvailable > 0)) { double spd = 0; switch (tmode) { case TMode.KEEP_ORBITAL: spd = vesselState.speedOrbital; break; case TMode.KEEP_SURFACE: spd = vesselState.speedSurface; break; case TMode.KEEP_VERTICAL: spd = vesselState.speedVertical; Vector3d rot = Vector3d.up; if (trans_kill_h) { Vector3 hsdir = Vector3.ProjectOnPlane(vesselState.surfaceVelocity, vesselState.up); Vector3 dir = -hsdir + vesselState.up * Math.Max(Math.Abs(spd), 20 * mainBody.GeeASL); if ((Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue) > 5000) && (hsdir.magnitude > Math.Max(Math.Abs(spd), 100 * mainBody.GeeASL) * 2)) { tmode = TMode.DIRECT; trans_spd_act = 100; rot = -hsdir; } else { rot = dir.normalized; } core.attitude.attitudeTo(rot, AttitudeReference.INERTIAL, null); } break; } double t_err = (trans_spd_act - spd) / vesselState.maxThrustAccel; if ((tmode == TMode.KEEP_ORBITAL && Vector3d.Dot(vesselState.forward, vesselState.orbitalVelocity) < 0) || (tmode == TMode.KEEP_SURFACE && Vector3d.Dot(vesselState.forward, vesselState.surfaceVelocity) < 0)) { //allow thrust to declerate t_err *= -1; } double t_act = pid.Compute(t_err); if ((tmode != TMode.KEEP_VERTICAL) || !trans_kill_h || (core.attitude.attitudeError < 2) || ((Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue) < 1000) && (core.attitude.attitudeError < 90))) { if (tmode == TMode.DIRECT) { trans_prev_thrust = targetThrottle = trans_spd_act / 100.0F; } else { trans_prev_thrust = targetThrottle = Mathf.Clamp01(trans_prev_thrust + (float)t_act); } } else { bool useGimbal = (vesselState.torqueFromEngine.x / vessel.ctrlState.mainThrottle > vesselState.torqueAvailable.x * 10) || (vesselState.torqueFromEngine.z / vessel.ctrlState.mainThrottle > vesselState.torqueAvailable.z * 10); bool useDiffThrottle = (vesselState.torqueFromDiffThrottle.x > vesselState.torqueAvailable.x * 10) || (vesselState.torqueFromDiffThrottle.z > vesselState.torqueAvailable.z * 10); if ((core.attitude.attitudeError >= 2) && (useGimbal || (useDiffThrottle && core.thrust.differentialThrottle))) { trans_prev_thrust = targetThrottle = 0.1F; } else { trans_prev_thrust = targetThrottle = 0; } } } // Only set throttle if a module need it. Othewise let the user or other mods set it // There is always at least 1 user : the module itself (why ?) if (users.Count() > 1) { s.mainThrottle = targetThrottle; } float throttleLimit = 1; limiter = LimitMode.None; if (limitThrottle) { if (maxThrottle < throttleLimit) { limiter = LimitMode.Throttle; } throttleLimit = Mathf.Min(throttleLimit, (float)maxThrottle); } if (limitToTerminalVelocity) { float limit = TerminalVelocityThrottle(); if (limit < throttleLimit) { limiter = LimitMode.TerminalVelocity; } throttleLimit = Mathf.Min(throttleLimit, limit); } if (limitDynamicPressure) { float limit = MaximumDynamicPressureThrottle(); if (limit < throttleLimit) { limiter = LimitMode.DynamicPressure; } throttleLimit = Mathf.Min(throttleLimit, limit); } if (limitToPreventOverheats) { float limit = (float)TemperatureSafetyThrottle(); if (limit < throttleLimit) { limiter = LimitMode.Temperature; } throttleLimit = Mathf.Min(throttleLimit, limit); } if (limitAcceleration) { float limit = AccelerationLimitedThrottle(); if (limit < throttleLimit) { limiter = LimitMode.Acceleration; } throttleLimit = Mathf.Min(throttleLimit, limit); } if (electricThrottle && ElectricEngineRunning()) { float limit = ElectricThrottle(); if (limit < throttleLimit) { limiter = LimitMode.Electric; } throttleLimit = Mathf.Min(throttleLimit, limit); } if (limitToPreventFlameout) { // This clause benefits being last: if we don't need much air // due to prior limits, we can close some intakes. float limit = FlameoutSafetyThrottle(); if (limit < throttleLimit) { limiter = LimitMode.Flameout; } throttleLimit = Mathf.Min(throttleLimit, limit); } if (limiterMinThrottle && limiter != LimitMode.None && throttleLimit < minThrottle) { limiter = LimitMode.MinThrottle; throttleLimit = (float)minThrottle; } if (double.IsNaN(throttleLimit)) { throttleLimit = 0; } throttleLimit = Mathf.Clamp01(throttleLimit); vesselState.throttleLimit = throttleLimit; if (s.mainThrottle < throttleLimit) { limiter = LimitMode.None; } s.mainThrottle = Mathf.Min(s.mainThrottle, throttleLimit); if (smoothThrottle) { s.mainThrottle = SmoothThrottle(s.mainThrottle); } if (double.IsNaN(s.mainThrottle)) { s.mainThrottle = 0; } s.mainThrottle = Mathf.Clamp01(s.mainThrottle); if (s.Z == 0 && core.rcs.rcsThrottle && vesselState.rcsThrust) { s.Z = -s.mainThrottle; } lastThrottle = s.mainThrottle; if (!core.attitude.enabled) { Vector3d act = new Vector3d(s.pitch, s.yaw, s.roll); differentialThrottleDemandedTorque = -Vector3d.Scale(act.xzy, vesselState.torqueFromDiffThrottle * s.mainThrottle * 0.5f); } }
private void SetFlightCtrlState(Vector3d act, Vector3d deltaEuler, FlightCtrlState s, float drive_limit) { bool userCommandingPitchYaw = (Mathfx.Approx(s.pitch, s.pitchTrim, 0.1F) ? false : true) || (Mathfx.Approx(s.yaw, s.yawTrim, 0.1F) ? false : true); bool userCommandingRoll = (Mathfx.Approx(s.roll, s.rollTrim, 0.1F) ? false : true); // Disable the new SAS so it won't interfere. // Todo : enable it when it's a good idea or the user had it enabled before part.vessel.ActionGroups.SetGroup(KSPActionGroup.SAS, false); if (attitudeKILLROT) { if (lastReferencePart != vessel.GetReferenceTransformPart() || userCommandingPitchYaw || userCommandingRoll) { attitudeTo(Quaternion.LookRotation(vessel.GetTransform().up, -vessel.GetTransform().forward), AttitudeReference.INERTIAL, null); lastReferencePart = vessel.GetReferenceTransformPart(); } } if (userCommandingPitchYaw || userCommandingRoll) { pid.Reset(); } if (!attitudeRollMatters) { attitudeTo(Quaternion.LookRotation(attitudeTarget * Vector3d.forward, attitudeWorldToReference(-vessel.GetTransform().forward, attitudeReference)), attitudeReference, null); _attitudeRollMatters = false; } if (!userCommandingRoll) { if (!double.IsNaN(act.z)) { s.roll = Mathf.Clamp((float)(act.z), -drive_limit, drive_limit); } } if (!userCommandingPitchYaw) { if (!double.IsNaN(act.x)) { s.pitch = Mathf.Clamp((float)(act.x), -drive_limit, drive_limit); } if (!double.IsNaN(act.y)) { s.yaw = Mathf.Clamp((float)(act.y), -drive_limit, drive_limit); } } // RCS and SAS control: Vector3d absErr; // Absolute error (exag º) absErr.x = Math.Abs(deltaEuler.x); absErr.y = Math.Abs(deltaEuler.y); absErr.z = Math.Abs(deltaEuler.z); if ((absErr.x < 0.4) && (absErr.y < 0.4) && (absErr.z < 0.4)) { if (timeCount < 50) { timeCount++; } else { if (RCS_auto) { if (attitudeRCScontrol && core.rcs.users.Count == 0) { part.vessel.ActionGroups.SetGroup(KSPActionGroup.RCS, false); } } } } else if ((absErr.x > 1.0) || (absErr.y > 1.0) || (absErr.z > 1.0)) { timeCount = 0; if (RCS_auto && ((absErr.x > 3.0) || (absErr.y > 3.0) || (absErr.z > 3.0))) { if (attitudeRCScontrol) { part.vessel.ActionGroups.SetGroup(KSPActionGroup.RCS, true); } } } } // end of SetFlightCtrlState
public override void Drive(FlightCtrlState s) { float threshold = 0.1F; bool _userCommandingRotation = !(Mathfx.Approx(s.pitch, s.pitchTrim, threshold) && Mathfx.Approx(s.yaw, s.yawTrim, threshold) && Mathfx.Approx(s.roll, s.rollTrim, threshold)); bool _userCommandingTranslation = !(Math.Abs(s.X) < threshold && Math.Abs(s.Y) < threshold && Math.Abs(s.Z) < threshold); if (_userCommandingRotation && !_userCommandingTranslation) { userCommandingRotationSmoothed = 2; } else if (userCommandingRotationSmoothed > 0) { userCommandingRotationSmoothed--; } if (core.GetComputerModule <MechJebModuleThrustWindow>().hidden&& core.GetComputerModule <MechJebModuleAscentGuidance>().hidden) { return; } if ((tmode != TMode.OFF) && (vesselState.thrustAvailable > 0)) { double spd = 0; switch (tmode) { case TMode.KEEP_ORBITAL: spd = vesselState.speedOrbital; break; case TMode.KEEP_SURFACE: spd = vesselState.speedSurface; break; case TMode.KEEP_VERTICAL: spd = vesselState.speedVertical; Vector3d rot = Vector3d.up; if (trans_kill_h) { Vector3 hsdir = Vector3.ProjectOnPlane(vesselState.surfaceVelocity, vesselState.up); Vector3 dir = -hsdir + vesselState.up * Math.Max(Math.Abs(spd), 20 * mainBody.GeeASL); if ((Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue) > 5000) && (hsdir.magnitude > Math.Max(Math.Abs(spd), 100 * mainBody.GeeASL) * 2)) { tmode = TMode.DIRECT; trans_spd_act = 100; rot = -hsdir; } else { rot = dir.normalized; } core.attitude.attitudeTo(rot, AttitudeReference.INERTIAL, null); } break; } double t_err = (trans_spd_act - spd) / vesselState.maxThrustAccel; if ((tmode == TMode.KEEP_ORBITAL && Vector3d.Dot(vesselState.forward, vesselState.orbitalVelocity) < 0) || (tmode == TMode.KEEP_SURFACE && Vector3d.Dot(vesselState.forward, vesselState.surfaceVelocity) < 0)) { //allow thrust to declerate t_err *= -1; } double t_act = pid.Compute(t_err); if ((tmode != TMode.KEEP_VERTICAL) || !trans_kill_h || (core.attitude.attitudeError < 2) || ((Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue) < 1000) && (core.attitude.attitudeError < 90))) { if (tmode == TMode.DIRECT) { trans_prev_thrust = targetThrottle = trans_spd_act / 100.0F; } else { trans_prev_thrust = targetThrottle = Mathf.Clamp01(trans_prev_thrust + (float)t_act); } } else { bool useGimbal = (vesselState.torqueGimbal.positive.x > vesselState.torqueAvailable.x * 10) || (vesselState.torqueGimbal.positive.z > vesselState.torqueAvailable.z * 10); bool useDiffThrottle = (vesselState.torqueDiffThrottle.x > vesselState.torqueAvailable.x * 10) || (vesselState.torqueDiffThrottle.z > vesselState.torqueAvailable.z * 10); if ((core.attitude.attitudeError >= 2) && (useGimbal || (useDiffThrottle && core.thrust.differentialThrottle))) { trans_prev_thrust = targetThrottle = 0.1F; print(" targetThrottle = 0.1F"); } else { trans_prev_thrust = targetThrottle = 0; } } } // Only set throttle if a module need it. Otherwise let the user or other mods set it // There is always at least 1 user : the module itself (why ?) if (users.Count > 1) { s.mainThrottle = targetThrottle; } throttleLimit = 1; throttleFixedLimit = 1; limiter = LimitMode.None; if (limitThrottle) { if (maxThrottle < throttleLimit) { setFixedLimit((float)maxThrottle, LimitMode.Throttle); } } if (limitToTerminalVelocity) { float limit = TerminalVelocityThrottle(); if (limit < throttleLimit) { setFixedLimit(limit, LimitMode.TerminalVelocity); } } if (limitDynamicPressure) { float limit = MaximumDynamicPressureThrottle(); if (limit < throttleLimit) { setFixedLimit(limit, LimitMode.DynamicPressure); } } if (limitToPreventOverheats) { float limit = (float)TemperatureSafetyThrottle(); if (limit < throttleLimit) { setFixedLimit(limit, LimitMode.Temperature); } } if (limitAcceleration) { float limit = AccelerationLimitedThrottle(); if (limit < throttleLimit) { setFixedLimit(limit, LimitMode.Acceleration); } } if (electricThrottle && ElectricEngineRunning()) { float limit = ElectricThrottle(); if (limit < throttleLimit) { setFixedLimit(limit, LimitMode.Electric); } } if (limitToPreventFlameout) { // This clause benefits being last: if we don't need much air // due to prior limits, we can close some intakes. float limit = FlameoutSafetyThrottle(); if (limit < throttleLimit) { setFixedLimit(limit, LimitMode.Flameout); } } // Any limiters which can limit to non-zero values must come before this, any // limiters (like ullage) which enforce zero throttle should come after. The // minThrottle setting has authority over any other limiter that sets non-zero throttle. if (limiterMinThrottle && limiter != LimitMode.None) { if (minThrottle > throttleFixedLimit) { setFixedLimit((float)minThrottle, LimitMode.MinThrottle); } if (minThrottle > throttleLimit) { setTempLimit((float)minThrottle, LimitMode.MinThrottle); } } /* auto-RCS ullaging up to very stable */ if (autoRCSUllaging && s.mainThrottle > 0.0F && throttleLimit > 0.0F) { if (vesselState.lowestUllage < VesselState.UllageState.VeryStable) { Debug.Log("MechJeb RCS auto-ullaging: found state below very stable: " + vesselState.lowestUllage); if (vessel.hasEnabledRCSModules()) { if (!vessel.ActionGroups[KSPActionGroup.RCS]) { Debug.Log("MechJeb RCS auto-ullaging: enabling RCS action group for automatic ullaging"); vessel.ActionGroups.SetGroup(KSPActionGroup.RCS, true); } Debug.Log("MechJeb RCS auto-ullaging: firing RCS to stabilize ulllage"); setTempLimit(0.0F, LimitMode.UnstableIgnition); s.Z = -1.0F; } else { Debug.Log("MechJeb RCS auto-ullaging: vessel has no enabled/staged RCS modules"); } } } /* prevent unstable ignitions */ if (limitToPreventUnstableIgnition && s.mainThrottle > 0.0F && throttleLimit > 0.0F) { if (vesselState.lowestUllage < VesselState.UllageState.Stable) { ScreenMessages.PostScreenMessage(preventingUnstableIgnitionsMessage); Debug.Log("MechJeb Unstable Ignitions: preventing ignition in state: " + vesselState.lowestUllage); setTempLimit(0.0F, LimitMode.UnstableIgnition); } } // we have to force the throttle here so that rssMode can work, otherwise we don't get our last throttle command // back on the next tick after disabling. we save this before applying the throttle limits so that we preserve // the requested throttle, and not the limited throttle. if (core.rssMode) { SetFlightGlobals(s.mainThrottle); } if (double.IsNaN(throttleLimit)) { throttleLimit = 1.0F; } throttleLimit = Mathf.Clamp01(throttleLimit); /* we do not _apply_ the "fixed" limit, the actual throttleLimit should always be the more limited and lower one */ /* the purpose of the "fixed" limit is for external consumers like the node executor to consume */ if (double.IsNaN(throttleFixedLimit)) { throttleFixedLimit = 1.0F; } throttleFixedLimit = Mathf.Clamp01(throttleFixedLimit); vesselState.throttleLimit = throttleLimit; vesselState.throttleFixedLimit = throttleFixedLimit; if (s.mainThrottle < throttleLimit) { limiter = LimitMode.None; } s.mainThrottle = Mathf.Min(s.mainThrottle, throttleLimit); if (smoothThrottle) { s.mainThrottle = SmoothThrottle(s.mainThrottle); } if (double.IsNaN(s.mainThrottle)) { s.mainThrottle = 0; } s.mainThrottle = Mathf.Clamp01(s.mainThrottle); if (s.Z == 0 && core.rcs.rcsThrottle && vesselState.rcsThrust) { s.Z = -s.mainThrottle; } lastThrottle = s.mainThrottle; if (!core.attitude.enabled) { Vector3d act = new Vector3d(s.pitch, s.yaw, s.roll); differentialThrottleDemandedTorque = -Vector3d.Scale(act.xzy, vesselState.torqueDiffThrottle * s.mainThrottle * 0.5f); } }
public void Update() { if (afx == null) { GameObject fx = GameObject.Find("FXLogic"); if (fx != null) { afx = fx.GetComponent <AerodynamicsFX>(); } } Animation flapsAnim = part.FindModelAnimators("Flap_Top_Right")[0]; if (vessel != null && vessel.mainBody.atmosphere && vessel.altitude < vessel.mainBody.RealMaxAtmosphereAltitude()) { float direction = ((vessel.GetSrfVelocity().magnitude > 25) && (Vector3.Angle(vessel.transform.up, vessel.GetSrfVelocity()) > 90)) ? -1 : 1; lastFlaps[0] = AdvanceAnimationTo(flapsAnim, "Flap_Top_Right", Mathf.Clamp01(direction * (vessel.ctrlState.pitch - vessel.ctrlState.yaw) / 2), TimeWarp.deltaTime, lastFlaps[0]); lastFlaps[1] = AdvanceAnimationTo(flapsAnim, "Flap_Top_Left", Mathf.Clamp01(direction * (vessel.ctrlState.pitch + vessel.ctrlState.yaw) / 2), TimeWarp.deltaTime, lastFlaps[1]); lastFlaps[2] = AdvanceAnimationTo(flapsAnim, "Flap_Bottom_Right", Mathf.Clamp01(direction * (-vessel.ctrlState.pitch - vessel.ctrlState.yaw) / 2), TimeWarp.deltaTime, lastFlaps[2]); lastFlaps[3] = AdvanceAnimationTo(flapsAnim, "Flap_Bottom_Left", Mathf.Clamp01(direction * (-vessel.ctrlState.pitch + vessel.ctrlState.yaw) / 2), TimeWarp.deltaTime, lastFlaps[3]); } else { lastFlaps[0] = AdvanceAnimationTo(flapsAnim, "Flap_Top_Right", 0, TimeWarp.deltaTime, lastFlaps[0]); lastFlaps[1] = AdvanceAnimationTo(flapsAnim, "Flap_Top_Left", 0, TimeWarp.deltaTime, lastFlaps[1]); lastFlaps[2] = AdvanceAnimationTo(flapsAnim, "Flap_Bottom_Right", 0, TimeWarp.deltaTime, lastFlaps[2]); lastFlaps[3] = AdvanceAnimationTo(flapsAnim, "Flap_Bottom_Left", 0, TimeWarp.deltaTime, lastFlaps[3]); } switch (state) { case State.OFF: if (HighLogic.LoadedSceneIsEditor || (HighLogic.LoadedSceneIsFlight && FlightGlobals.ready && vessel != null && core.attitude.enabled)) { state = State.AWAKENING; part.FindModelAnimators("Waking")[0].Play("Waking"); } break; case State.AWAKENING: if (!part.FindModelAnimators("Waking")[0].isPlaying) { AdvanceAnimationTo(part.FindModelAnimators("Waking")[0], "Waking", 1, 100); state = State.AWAKE; lastBlink = lastAction = Time.time; } break; case State.AWAKE: if (!part.FindModelAnimators("Blink")[0].isPlaying) { if ((UnityEngine.Random.Range(0, 10.0F / (HighLogic.LoadedSceneIsEditor ? Time.deltaTime : TimeWarp.deltaTime)) < (Time.time - lastBlink))) { part.FindModelAnimators("Blink")[0].Play("Blink"); lastBlink = Time.time; } GameObject cam = HighLogic.LoadedSceneIsEditor ? EditorLogic.fetch.editorCamera.gameObject : FlightCamera.fetch.gameObject; Vector3 target = (cam.transform.position - part.transform.position).normalized; if (core.attitude.enabled) { target = core.attitude.attitudeGetReferenceRotation(core.attitude.attitudeReference) * core.attitude.attitudeTarget * Quaternion.Euler(90, 0, 0) * Vector3.up; lastAction = Time.time; } Vector3 localTarget = part.transform.InverseTransformDirection(target); Vector2 polarTarget = CartesianToPolar(localTarget); if (Mathfx.Approx(polarTarget.x, -90, 1) || Mathfx.Approx(polarTarget.x, 90, 1)) { polarTarget.y = eye_base.localEulerAngles.z + 90; } if ((!HighLogic.LoadedSceneIsEditor && (Time.time - lastAction > 30))) { if (Mathfx.Approx(eye_base.localEulerAngles.z, 0, 1) && Mathfx.Approx(eye_ball.localEulerAngles.x, 0, 1)) { state = State.SLEEPING; part.FindModelAnimators("Sleeping")[0].Play("Sleeping"); } else { polarTarget = new Vector2(-90, 90); } } if (afx != null && afx.FxScalar > 0) { polarTarget = new Vector2(90, 90); } eye_base.localEulerAngles = new Vector3(0, 0, Mathf.MoveTowardsAngle(eye_base.localEulerAngles.z, polarTarget.y - 90, 360 * Time.deltaTime)); eye_ball.localRotation = Quaternion.RotateTowards(eye_ball.localRotation, Quaternion.Euler(polarTarget.x + 90, 0, 0), 360 * Time.deltaTime); } break; case State.SLEEPING: if (!part.FindModelAnimators("Sleeping")[0].isPlaying) { AdvanceAnimationTo(part.FindModelAnimators("Sleeping")[0], "Sleeping", 1, 100); state = State.OFF; } break; default: break; } }