Approx() 공개 정적인 메소드

public static Approx ( Vector3 val, Vector3 about, float range ) : bool
val Vector3
about Vector3
range float
리턴 bool
예제 #1
0
 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;
 }
예제 #2
0
        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;
                }
            }
        }
예제 #3
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;
        }
예제 #5
0
    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;
        }
    }
예제 #6
0
        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);
            }
        }
예제 #8
0
        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
예제 #9
0
        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);
            }
        }
예제 #10
0
        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;
            }
        }