Beispiel #1
0
        void DriveAscent(FlightCtrlState s)
        {
            if (timedLaunch)
            {
                status = Localizer.Format("#MechJeb_Ascent_status6");//"Awaiting liftoff"
                Log.dbg("Awaiting Liftoff");
                // kill the optimizer if it is running.
                core.guidance.enabled = false;

                core.attitude.AxisControl(false, false, false);
                return;
            }

            DriveDeployableComponents(s);

            if (ascentPath.DriveAscent(s))
            {
                Log.detail("Remaining in Ascent");
                status = ascentPath.status;
            }
            else
            {
                Log.detail("Ascend -> Circularize");
                mode = AscentMode.CIRCULARIZE;
            }
        }
        private void handleStageEvent(int data)
        {
            if (!enabled || stages.Count == 0)
            {
                return;
            }

            while (stages[0].ksp_stage > (vessel.currentStage - 1))
            {
                // we did drop a relevant stage
                stageCount      += 1;
                stages[0].staged = true;
                stages.RemoveAt(0);
                Log.detail("[MechJebModuleLogicalStageTracking] dropping a stage");
            }
        }
        public void Update()
        {
            if (lastTime == Planetarium.GetUniversalTime())
            {
                return;
            }

            core.stageStats.RequestUpdate(this, true);

            int j = 0;

            for (int i = core.stageStats.vacStats.Length - 1; i >= 0; i--)
            {
                var stats = core.stageStats.vacStats[i];

                // FIXME: either tweakability or identify ullage + sep motors correctly
                if (stats.deltaV < 20)
                {
                    if (!(j == 0 && stages.Count > 0 && stages[0].ksp_stage == i))   // check if we're just burning down the current stage
                    {
                        continue;
                    }
                }

                if (j >= stages.Count)
                {
                    Log.detail("[MechJebModuleLogicalStageTracking] adding a new stage: " + j);
                    stages.Add(new Stage(this));
                }

                stages[j].ksp_stage    = i;
                stages[j].rocket_stage = j + stageCount;
                stages[j].Sync();

                j++;
            }

            while (stages.Count > core.stageStats.vacStats.Length)
            {
                Log.detail("[MechJebModuleLogicalStageTracking] upper stage disappeared (user reconfig most likely)");
                stages.RemoveAt(stages.Count - 1);
            }

            lastTime = Planetarium.GetUniversalTime();
        }
Beispiel #4
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;
                        Log.detail(" 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)
                {
                    Log.info("RCS auto-ullaging: found state below very stable: {0}", vesselState.lowestUllage);
                    if (vessel.hasEnabledRCSModules())
                    {
                        if (!vessel.ActionGroups[KSPActionGroup.RCS])
                        {
                            Log.info("RCS auto-ullaging: enabling RCS action group for automatic ullaging");
                            vessel.ActionGroups.SetGroup(KSPActionGroup.RCS, true);
                        }
                        Log.info("RCS auto-ullaging: firing RCS to stabilize ulllage");
                        setTempLimit(0.0F, LimitMode.UnstableIgnition);
                        s.Z = -1.0F;
                    }
                    else
                    {
                        Log.info("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);
                    Log.info("Unstable Ignitions: preventing ignition in state: {0}", 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);
            }
        }
Beispiel #5
0
        public void SetupToolBarButtons()
        {
            if (!ToolbarManager.ToolbarAvailable)
            {
                return;
            }

            SetupMainToolbarButton();

            foreach (DisplayModule module in core.GetDisplayModules(DisplayOrder.instance).Where(m => !m.hidden))
            {
                Button button;
                if (!toolbarButtons.ContainsKey(module))
                {
                    Log.detail("Create button for module {0}", module.GetName());

                    String name = GetCleanName(module.GetName());

                    String TexturePath       = "MechJeb2/Icons/" + name;
                    String TexturePathActive = TexturePath + "_active";

                    button        = new Button();
                    button.button = ToolbarManager.Instance.add("MechJeb2", name);

                    if (GameDatabase.Instance.GetTexture(TexturePath, false) == null)
                    {
                        button.texturePath = Qmark;
                        Log.info("No icon for {0}", name);
                    }
                    else
                    {
                        button.texturePath = TexturePath;
                    }

                    if (GameDatabase.Instance.GetTexture(TexturePathActive, false) == null)
                    {
                        button.texturePathActive = TexturePath;
                        Log.dbg("No icon for {0}_active", name);
                    }
                    else
                    {
                        button.texturePathActive = TexturePathActive;
                    }

                    toolbarButtons[module] = button;

                    button.button.ToolTip  = "MechJeb " + module.GetName();
                    button.button.OnClick += (b) =>
                    {
                        DisplayModule mod = FlightGlobals.ActiveVessel.GetMasterMechJeb().GetDisplayModules(DisplayOrder.instance).FirstOrDefault(m => m == module);
                        if (mod != null)
                        {
                            mod.enabled = !mod.enabled;
                        }
                    };
                }
                else
                {
                    button = toolbarButtons[module];
                }

                button.button.Visible     = module.showInCurrentScene;
                button.button.TexturePath = module.isActive() ? button.texturePathActive : button.texturePath;
            }

            // create toolbar buttons for features
            if (featureButtons.Count == 0)
            {
                var maneuverPlannerModule = core.GetComputerModule <MechJebModuleManeuverPlanner>();
                if (!HighLogic.LoadedSceneIsEditor && maneuverPlannerModule != null && !maneuverPlannerModule.hidden)
                {
                    CreateFeatureButton(maneuverPlannerModule, "Exec_Node", "MechJeb Execute Next Node", (b) =>
                    {
                        if (vessel.patchedConicSolver.maneuverNodes.Count > 0 && core.node != null)
                        {
                            if (core.node.enabled)
                            {
                                core.node.Abort();
                            }
                            else
                            {
                                if (vessel.patchedConicSolver.maneuverNodes[0].DeltaV.magnitude > 0.0001)
                                {
                                    core.node.ExecuteOneNode(maneuverPlannerModule);
                                }
                                else
                                {
                                    ScreenMessages.PostScreenMessage("Maneuver burn vector not set", 3f);
                                }
                            }
                        }
                        else
                        {
                            ScreenMessages.PostScreenMessage("No maneuver nodes", 2f);
                        }
                    }, () => vessel.patchedConicSolver.maneuverNodes.Count > 0 && core.node != null && core.node.enabled);

                    CreateFeatureButton(maneuverPlannerModule, "Autostage_Once", "MechJeb Autostage Once", (b) =>
                    {
                        var w = core.GetComputerModule <MechJebModuleThrustWindow>();

                        if (core.staging.enabled && core.staging.autostagingOnce)
                        {
                            if (core.staging.users.Contains(w))
                            {
                                core.staging.users.Remove(w);
                                w.autostageSavedState = false;
                            }
                        }
                        else
                        {
                            core.staging.AutostageOnce(w);
                        }
                    }, () => core.staging.enabled && core.staging.autostagingOnce);

                    CreateFeatureButton(maneuverPlannerModule, "Auto_Warp", "MechJeb Auto-warp", (b) =>
                    {
                        core.node.autowarp = !core.node.autowarp;
                    }, () => core.node.autowarp);
                }
            }
        }