コード例 #1
0
        /// <summary>
        /// Main control function
        /// </summary>
        /// <param name="cntrl">Control state to change</param>
        public float ApplyControl(FlightCtrlState cntrl, float target_value, float target_acc = 0.0f)
        {
            vel = imodel.AngularVel(axis);                  // get angular velocity

            float user_input = ControlUtils.get_neutralized_user_input(cntrl, axis);

            if (user_input != 0.0f || user_controlled)
            {
                // user is interfering with control
                float clamp = (watch_precision_mode && FlightInputHandler.fetch.precisionMode) ?
                              precision_mode_factor * user_input_deriv_clamp * TimeWarp.fixedDeltaTime :
                              user_input_deriv_clamp * TimeWarp.fixedDeltaTime;
                if (watch_precision_mode && FlightInputHandler.fetch.precisionMode)
                {
                    user_input *= precision_mode_factor;
                }
                float delta_input = Common.Clampf(user_input - prev_input, clamp);
                user_input      = prev_input + delta_input;
                prev_input      = user_input;
                desired_v       = user_input * max_v_construction;
                user_controlled = true;
            }
            else
            {
                // control from above
                desired_v = Common.Clampf(target_value, max_v_construction);
            }

            desired_v = process_desired_v(desired_v, user_controlled);      // moderation stage

            output_acc = get_desired_acc(desired_v) + target_acc;           // produce output acceleration

            // check if we're stable on given input value
            if (ApplyTrim && vessel == AtmosphereAutopilot.Instance.ActiveVessel)
            {
                if (Math.Abs(vel) < 0.002f)
                {
                    time_in_regime += TimeWarp.fixedDeltaTime;
                }
                else
                {
                    time_in_regime = 0.0;
                }

                if (time_in_regime >= 5.0)
                {
                    ControlUtils.set_trim(axis, imodel.ControlSurfPosHistory(axis).Average());
                }
            }

            acc_controller.ApplyControl(cntrl, output_acc);

            return(output_acc);
        }
コード例 #2
0
        double get_roll_aoa_deriv()
        {
            Vector3 pitch_aoa = new Vector3(imodel.AoA(PITCH), 0.0f, 0.0f);
            Vector3 yaw_aoa   = new Vector3(0.0f, imodel.AoA(YAW), 0.0f);
            Vector3 ang_v     = new Vector3(0.0f, 0.0f, imodel.AngularVel(ROLL));
            Vector3 plane_vel = Vector3.Cross(ang_v, pitch_aoa + yaw_aoa);

            if (axis == PITCH)
            {
                return(Vector3.Dot(Vector3.right, plane_vel));
            }
            if (axis == YAW)
            {
                return(Vector3.Dot(Vector3.up, plane_vel));
            }
            return(0.0);
        }
コード例 #3
0
        /// <summary>
        /// Main control function
        /// </summary>
        /// <param name="cntrl">Control state to change</param>
        /// <param name="target_value">Desired angular acceleration</param>
        public override float ApplyControl(FlightCtrlState cntrl, float target_value)
        {
            acc = (float)imodel.AngularAcc(axis);
            //model_acc = (float)imodel.model_acc[axis];
            desired_acc = target_value;

            if (write_telemetry)
            {
                desire_acc_writer.Write(target_value.ToString("G8") + ',');
                acc_writer.Write(acc.ToString("G8") + ',');
                v_writer.Write(imodel.AngularVel(axis).ToString("G8") + ',');
                //prediction_writer.Write(target_value.ToString("G8") + ',');
                aoa_writer.Write(imodel.AoA(axis).ToString("G8") + ',');
                airspd_writer.Write((imodel.up_srf_v + imodel.fwd_srf_v).magnitude.ToString("G8") + ',');
                density_writer.Write(vessel.atmDensity.ToString("G8") + ',');
            }

            float cur_input_raw = get_required_input(cntrl, desired_acc);

            output = cur_input_raw;
            if (float.IsNaN(output) || float.IsInfinity(output))
            {
                output = 0.0f;
            }

            // fighting numerical precision issues
            //if (axis == ROLL && imodel.dyn_pressure > 1000.0 && Mathf.Abs(output) < 0.006f)
            //    output = 0.0f;

            ControlUtils.set_raw_output(cntrl, axis, output);

            if (write_telemetry)
            {
                controlWriter.Write(csurf_output.ToString("G8") + ',');
                outputWriter.Write(output.ToString("G8") + ',');
            }

            return(output);
        }
コード例 #4
0
        /// <summary>
        /// Main control function
        /// </summary>
        /// <param name="cntrl">Control state to change</param>
        public override void ApplyControl(FlightCtrlState cntrl)
        {
            if (vessel.LandedOrSplashed)
            {
                landed             = true;
                time_after_takeoff = 0.0f;
                return;
            }

            // disable pitch moderation for two seconds after take-off
            if (landed || need_restore)
            {
                if (landed && !need_restore)
                {
                    aoa_moder       = pc.moderate_aoa;
                    g_moder         = pc.moderate_g;
                    pc.moderate_aoa = false;
                    pc.moderate_g   = false;
                    landed          = false;
                    need_restore    = true;
                }
                if (time_after_takeoff > 1.5f)
                {
                    pc.moderate_aoa = aoa_moder;
                    pc.moderate_g   = g_moder;
                    need_restore    = false;
                }
                else
                {
                    time_after_takeoff += TimeWarp.fixedDeltaTime;
                }
            }

            if (tc.spd_control_enabled)
            {
                tc.ApplyControl(cntrl, tc.setpoint.mps());
            }

            pc.user_controlled = true;
            if (coord_turn)
            {
                // account for yaw velocity in pitch neutral offset to assist coordinated turn
                Vector3 up_level_dir = Vector3.ProjectOnPlane(vessel.ReferenceTransform.position - vessel.mainBody.position,
                                                              vessel.ReferenceTransform.up).normalized;
                float yaw_v_vert_project = Vector3.Dot(im.AngularVel(YAW) * vessel.ReferenceTransform.right, up_level_dir);
                float pitch_vert_project = Vector3.Dot(up_level_dir, -vessel.ReferenceTransform.forward);
                if (pitch_vert_project > 0.0f)
                {
                    float level_pitch_vel = -yaw_v_vert_project / pitch_vert_project;
                    pc.neutral_offset = level_pitch_vel;
                }
                else
                {
                    pc.neutral_offset = 0.0f;
                }
            }
            else
            {
                pc.neutral_offset = 0.0f;
            }
            pc.ApplyControl(cntrl, 0.0f);

            if (rocket_mode)
            {
                yvc.user_controlled = true;
                yvc.ApplyControl(cntrl, 0.0f);
            }
            else
            {
                yc.user_controlled = true;
                yc.ApplyControl(cntrl, 0.0f, 0.0f);
            }
            rc.user_controlled = true;
            rc.ApplyControl(cntrl, 0.0f);
        }