Ejemplo n.º 1
0
            private void PrintStatus()
            {
                PrintLine("  VECTOR MODULE ACTIVE");
                PrintLine("  MODE: " + action?.name.ToUpper() + "\n");

                string output = "";

                if (action?.name == "brake")
                {
                    var    percent = Math.Abs(cockpit.GetShipSpeed() / startSpeed);
                    string progressBar;
                    progressBar = "|";
                    int width  = 24;
                    var height = 3;
                    output = " PROGRESS\n";
                    for (var i = 0; i < width; i++)
                    {
                        progressBar += (i < width * (1 - percent)) ? "#" : " ";
                    }
                    progressBar += "|\n";
                    for (var i = 0; i < height; i++)
                    {
                        output += progressBar;
                    }
                }
                else
                {
                    output = " Speed: " + Math.Abs(cockpit.GetShipSpeed()).ToString("000") + " m/s";
                }

                PrintLine(output);
            }
Ejemplo n.º 2
0
            void WheelsControl(float angle, int direction, float speed)
            {
                if (float.IsNaN(angle))
                {
                    return;
                }

                SuspensionParametersChangedEventArgs args = new SuspensionParametersChangedEventArgs();

                args.Speed = speed;

                float KmH = (float)_controller.GetShipSpeed() * 3.7f;

                _controller.HandBrake = KmH > args.Speed + 2.0f;// || _handBrake;

                float speedFactor = KmH / _maxForwardSpeed;

                args.Movement = -(1f - 0.7f * speedFactor) * direction;

                args.Friction = 50.0f - 25.0f * speedFactor;

                args.Steer = angle / MAX_STEER_ANGLE;
                if (float.IsNaN(args.Steer))
                {
                    args.Steer = 0;
                }

                ChangeTruckSuspensionParameters?.Invoke(this, args);
            }
        void SetDampenersOnline(bool dampOn)
        {
            if (shipControllers.Count <= 0)
            {
                return;
            }

            IMyShipController SHIP_CONTROLLER = null;

            foreach (IMyShipController controler in shipControllers)
            {
                if (controler.IsWorking)
                {
                    SHIP_CONTROLLER = controler; if (controler.IsMainCockpit)
                    {
                        break;
                    }
                }
            }

            if (SHIP_CONTROLLER != null)
            {
                if (dampOn)
                {
                    if (SHIP_CONTROLLER.GetShipSpeed() <= 0d)
                    {
                        SHIP_CONTROLLER.DampenersOverride = true;
                    }
                }
                else
                {
                    SHIP_CONTROLLER.DampenersOverride = false;
                }
            }
        }
Ejemplo n.º 4
0
        private void SpeedControl()
        {
            SetSpeed(_currentSpeed + acceleration * (-controller.MoveIndicator.Z));

            float currentSpeed         = Math.Abs(_currentSpeed);
            float movementDirection    = Math.Sign(_currentSpeed);
            float currentRightOverride = -movementDirection;
            float currentLeftOverride  = movementDirection;

            if (controller.GetShipSpeed() * 3.7f > currentSpeed + 5.0f)
            {
                controller.HandBrake = true;
            }
            else
            {
                controller.HandBrake = handBrake;
            }


            foreach (IMyMotorSuspension wheel in wheels)
            {
                wheel.SetValueFloat("Speed Limit", currentSpeed);
                if (wheel.CustomName.Contains("Right"))
                {
                    wheel.SetValueFloat("Propulsion override", currentRightOverride);
                }
                else
                {
                    wheel.SetValueFloat("Propulsion override", currentLeftOverride);
                }
            }
        }
Ejemplo n.º 5
0
            private IEnumerator <bool> TargetingRoutine()
            {
                if (control.GetNaturalGravity() == Vector3D.Zero && control.GetShipSpeed() < 2)         // Easy
                {
                    quartic = new QuarticTargeting(control.GetVelocityVector(), control.GetPosition(), maxProjectileVel);

                    Vector3D?result = quartic.CalculateTrajectory(target);
                    if (result.HasValue)
                    {
                        onRoutineFinish?.Invoke(result.Value);
                    }
                    else
                    {
                        onRoutineFail?.Invoke();
                    }

                    yield return(false);
                }
                else                                                                                  // This may take a while...
                {
                    double timescale      = 0.1;
                    var    projectileInfo = new AdvancedSimTargeting.ProjectileInfo(200, maxProjectileVel, timescale, control.GetPosition(), control.GetVelocityVector());
                    simTargeting = new AdvancedSimTargeting(projectileInfo, target, control, ingameTime, 25, true, maxProjectileVel, timescale);
                    simTargeting.onSimComplete += OnSimValid;
                    simTargeting.onSimFail     += OnSimFail;

                    yield return(true);

                    while (keepRunning)
                    {
                        simTargeting.Tick();
                        yield return(true);
                    }
                }
            }
Ejemplo n.º 6
0
            public void Main()
            {
                if (accelerateTarget == null || accelerateTarget == Vector3D.Zero || accelerateTarget == Vector3D.PositiveInfinity || PID_Controller == null || !accelerateTarget.IsValid())
                {
                    return;
                }

                Vector3D accelerateTargetNormalized = accelerateTarget;
                double   accelerateTargetLength     = accelerateTargetNormalized.Normalize();
                double   error      = Vector3D.Dot(control.WorldMatrix.Forward, accelerateTarget) + accelerateTargetLength;
                double   multiplier = Math.Abs(PID_Controller.NextValue(error, 0.016));

                if (accelerateTargetLength < negligible)
                {
                    accelerateTargetNormalized = Vector3D.Normalize(control.GetShipVelocities().LinearVelocity);
                }

                GyroUtils.PointInDirection(gyros, control, accelerateTargetNormalized, multiplier);
                //ThrustUtils.SetThrustBasedDot(thrusters, accelerateTargetNormalized, multiplier);
                autopilotModule.ThrustToVelocity(control.GetShipVelocities().LinearVelocity + accelerateTarget);


                if (accelerateInDirection && control.GetShipSpeed() >= (speedLimit - 0.01))
                {
                    accelerateTarget = Vector3D.Zero;
                    BoostForward(0);
                    accelerateInDirection = false;
                }
            }
            private void WheelRotationSpeedLimiter()
            {
                if (!WheelRotationLimiter)
                {
                    return;
                }

                float maxWheelSpeed = (float)rc.GetShipSpeed() + WheelRotationLimiterBuffer;

                maxWheelSpeed *= 3.6f;

                foreach (var wheel in wheels)
                {
                    wheel.SetValueFloat("Speed Limit", maxWheelSpeed);
                }
            }
            public void TravelToPosition(Vector3D position, bool enableAvoidance, double maximumVelocity = 100, double safetyMargin = 1.25, bool turnSelf = true)
            {
                double distanceFromTargetSQ = (position - ControlPosition).LengthSquared();

                if (distanceFromTargetSQ > 1 || controller.GetShipSpeed() > 0.0001)
                {
                    if (enableAvoidance)
                    {
                        if (avoidanceCheckCounter++ > 100)
                        {
                            double scanDistance = CalculateStoppingDistance() * safetyMargin;
                            avoidanceCheckCounter = 0;

                            collisionAvoidance.Scan(scanDistance);
                        }


                        if (collisionAvoidance.CheckForObjects())
                        {
                            Vector3D heading = Vector3D.Normalize(position - ControlPosition);
                            Vector3D nextDir = Vector3D.Zero;
                            collisionAvoidance.NextPosition(ref nextDir, heading);

                            ThrustToVelocity(nextDir * maximumVelocity);
                            gyroControl.StopRotation(gyros);
                            return;
                        }
                    }

                    TravelToPosition(position, maximumVelocity, safetyMargin, turnSelf);
                }
            }
Ejemplo n.º 9
0
            private bool Travel()
            {
                double distToTarget = GetDistanceToTarget();

                if (distToTarget < 2 * shipCenterToEdge)
                {
                    return(true);
                }

                bool isEnd       = false;
                bool shouldBrake = CheckBrake();

                if (shouldBrake)
                {
                    ManageBrake();
                    if (timeSpentStationary > SHUTDOWN_TIME)
                    {
                        Debug("timeSpentStationary", timeSpentStationary);
                        isEnd = true;
                    }
                }
                else
                {
                    float shipMass         = referenceBlock.CalculateShipMass().PhysicalMass;
                    float speed            = (float)referenceBlock.GetShipSpeed();
                    float secondsUntilVmax = 1;
                    float minLimitToZero   = 1 / 100;
                    float maxLimitPercent  = 98 / 100;
                    // F = m*a
                    // v_t = a_0*t + v_0 => a_0 = (v_t - v_0) / t
                    // F = m * (v_t - v_0) / t
                    float maxForceRequiered     = shipMass * (maxInitialSpeed - speed) / secondsUntilVmax;
                    float percentForceRequiered = maxForceRequiered / GetAcceleratingForce();
                    if (percentForceRequiered > maxLimitPercent)
                    {
                        percentForceRequiered = maxLimitPercent;
                    }
                    if (percentForceRequiered < minLimitToZero)
                    {
                        percentForceRequiered = 0F;
                    }

                    GetThrusters(ThrustersFlag.Accelerating).ForEach(t => t.ThrustOverridePercentage = percentForceRequiered);
                }

                return(isEnd);
            }
Ejemplo n.º 10
0
 public void Seperation()
 {
     Echo("Waiting for RC to reach target");
     velo = RController.GetShipSpeed();
     if (!AutoEnable && (velo < 0.5))
     {
         Main("Return");
     }
     return;
 }
Ejemplo n.º 11
0
        IEnumerable <int> AccelerateCruise(int selfInstance)
        {
            yield return(1);

            engineMgr.tsPower(ThrustFlags.Back, 100);
            while (selfInstance == cruiseInstance && shipCtrl.GetShipSpeed() < maxTopSpeed)
            {
                yield return(20);
            }
            engineMgr.tsPower(ThrustFlags.Back, 0);
        }
Ejemplo n.º 12
0
        void UpdateOrientationParameters()
        {
            Vector3D linearVelocity = Vector3D.Normalize(cockpit_.GetShipVelocities().LinearVelocity);
            Vector3D gravity        = -Vector3D.Normalize(cockpit_.GetNaturalGravity());

            pitch_ = Math.Acos(Vector3D.Dot(cockpit_.WorldMatrix.Forward, gravity)) * RadToDeg;
            roll_  = Math.Acos(Vector3D.Dot(cockpit_.WorldMatrix.Right, gravity)) * RadToDeg;

            worldSpeedForward_ = Vector3D.Dot(linearVelocity, Vector3D.Cross(gravity, cockpit_.WorldMatrix.Right)) * cockpit_.GetShipSpeed();
            worldSpeedRight_   = Vector3D.Dot(linearVelocity, Vector3D.Cross(gravity, cockpit_.WorldMatrix.Forward)) * cockpit_.GetShipSpeed();
            worldSpeedUp_      = Vector3D.Dot(linearVelocity, gravity) * cockpit_.GetShipSpeed();
        }
Ejemplo n.º 13
0
            public void Main()
            {
                if (started)
                {
                    ticks++;

                    speed += rc.GetShipSpeed();

                    distanceTravelled += (long)Math.Round(Vector3D.Distance(prevLoc, rc.GetPosition()));
                    prevLoc            = rc.GetPosition();
                }
            }
Ejemplo n.º 14
0
 public bool Update()
 {
     if (Controller != null)
     {
         newValue = Controller.GetShipSpeed();
         if (newValue != Value)
         {
             Value = newValue;
             return(true);
         }
     }
     return(false);
 }
Ejemplo n.º 15
0
            void GetController()
            {
                if (!(Controller ?? (Controller = Controllers[0])).IsUnderControl || !Controller.CanControlShip)
                {
                    for (int i = 1; i < Controllers.Count; i++)
                    {
                        if (Controllers[i].IsUnderControl && Controllers[i].CanControlShip)
                        {
                            Controller = Controllers[i];
                            break;
                        }
                    }
                }

                if (Controller.GetShipSpeed() >= 12 && Controller.RollIndicator == 0)
                {
                    if (Controller.GetShipSpeed() >= 40)
                    {
                        whangle = .17f;
                    }
                    else
                    {
                        whangle = .26f;
                    }
                }
                else
                {
                    whangle = .38f;
                }
                if (Tangle != whangle)
                {
                    Tangle = whangle;
                    foreach (IMyMotorSuspension w in Wheels)
                    {
                        w.MaxSteerAngle = Tangle;
                    }
                }
            }
Ejemplo n.º 16
0
        private void doorCheck()
        {
            if (controller.GetShipSpeed() > ABORT_SPEED)
            {
                Echo("Autodoor disabled: ship is moving");
                return;
            }

            // For each door, calculate appropriate bounding box where player must stand
            foreach (var d in doors)
            {
                var bb         = d.WorldAABB;
                var forwardDir = bb.Matrix.Forward;
                var backDir    = bb.Matrix.Backward;
                var ptForward  = d.GetPosition() + doorSensorDistanceFrontRear * forwardDir;
                var ptBackward = d.GetPosition() + doorSensorDistanceFrontRear * backDir;

                var expandedBB = bb.Include(ptForward).Include(ptBackward);

                bool openDoor = false;

                // Check each door against all sensors
                foreach (var sensor in sensors)
                {
                    var objects = new List <MyDetectedEntityInfo>();
                    sensor.DetectedEntities(objects);

                    // Process each detected object, check against door list and make sure object is a human
                    foreach (var obj in objects)
                    {
                        if (obj.Type == MyDetectedEntityType.CharacterHuman && obj.Relationship != MyRelationsBetweenPlayerAndBlock.Enemies)
                        {
                            if (expandedBB.Contains(obj.Position) == ContainmentType.Contains)
                            {
                                openDoor = true;
                            }
                        }
                    }
                }

                if (openDoor)
                {
                    d.ApplyAction("Open_On");
                }
                else
                {
                    d.ApplyAction("Open_Off");
                }
            }
        }
Ejemplo n.º 17
0
            public VectorModule(CustomDataConfig config, GyroController gyroController, IMyShipController cockpit)
            {
                this.gyroController = gyroController;
                this.cockpit        = cockpit;

                thrustVector = GetThrustVector(config.Get <string>("spaceMainThrust"));

                AddAction("disabled", (args) => { gyroController.SetGyroOverride(false); }, null);
                AddAction("brake", (args) => {
                    startSpeed = cockpit.GetShipSpeed();
                    cockpit.DampenersOverride = false;
                }, SpaceBrake);
                AddAction("prograde", null, () => { TargetOrientation(-Vector3D.Normalize(cockpit.GetShipVelocities().LinearVelocity)); });
                AddAction("retrograde", null, () => { TargetOrientation(Vector3D.Normalize(cockpit.GetShipVelocities().LinearVelocity)); });
            }
Ejemplo n.º 18
0
            public Vector2 CalculatePitchRollToAchiveVelocity(Vector3 targetVelocity)
            {
                Vector3 diffrence            = Vector3.Normalize(controller.GetShipVelocities().LinearVelocity - targetVelocity);
                Vector3 gravity              = -Vector3.Normalize(controller.GetNaturalGravity());
                float   velocity             = (float)controller.GetShipSpeed();
                float   proportionalModifier = (float)Math.Pow(Math.Abs(diffrence.Length()), 2);

                float pitch = NotNaN(Vector3.Dot(diffrence, Vector3.Cross(gravity, controller.WorldMatrix.Right)) * velocity) * proportionalModifier / dampeningFactor;
                float roll  = NotNaN(Vector3.Dot(diffrence, Vector3.Cross(gravity, controller.WorldMatrix.Forward)) * velocity) * proportionalModifier / dampeningFactor;

                pitch = MinAbs(pitch, 90.0f * degToRad);
                roll  = MinAbs(roll, 90.0f * degToRad);

                return(new Vector2(roll, pitch));
            }
            void UpdateTelemetry()
            {
                prevSpeed = currSpeed;
                currAccl  = (currSpeed = sc.GetShipSpeed()) - prevSpeed;

                gravity = (gravityStrength = sc.GetNaturalGravity().Length()) / 9.81;

                if (shipMassUpdateTick < Pgm.totalTicks)
                {
                    shipMassUpdateTick = Pgm.totalTicks + TPS;
                    shipMass           = sc.CalculateShipMass();
                }
                shipWeight = gravityStrength * shipMass.PhysicalMass;                 // or -> shipMass.TotalMass

                prevAltitude = altitudeSurface;
                if (sc.TryGetPlanetElevation(MyPlanetElevation.Surface, out altitudeSurface))
                {
                    altitudeDiff = altitudeSurface - prevAltitude;
                }
                else
                {
                    altitudeSurface = altitudeDiff = double.NaN;
                }

                atmosphereDensity = parachute?.Atmosphere ?? float.NaN;

                if (null != downCamera)
                {
                    if (downCamera.CanScan(1000))
                    {
                        MyDetectedEntityInfo dei = downCamera.Raycast(1000);
                        double len = 0;
                        if (null != dei.HitPosition)
                        {
                            Vector3D hp = (Vector3D)dei.HitPosition;
                            len = (hp - downCamera.CubeGrid.GetPosition()).Length();
                        }
                        raycastName = dei.Name + "/" + len;                         //downCamera.CubeGrid.GetPosition(); //dei.HitPosition.ToString();
                    }
                    else
                    {
                        raycastName = downCamera.AvailableScanRange.ToString();
                    }
                }
            }
Ejemplo n.º 20
0
        public void OnEntityDetected(HaE_Entity entity)
        {
            if (Vector3D.DistanceSquared(entity.entityInfo.Position, control.GetPosition()) > 1000 * 1000)
            {
                return;
            }

            if (IgnoreEventAfterOnce)
            {
                return;
            }

            if (control.GetShipSpeed() < maxActiveRotorGunVel)
            {
                gridCannonTargeting.NewTarget(entity.entityInfo);
            }
            else
            {
                foreach (var cannon in rotorTurretGroups)
                {
                    cannon.TargetDirection(ref Vector3D.Zero);
                }
            }

            statusWriter.UpdateStatus(StatusWriter.TargetingStatus.Targeting);

            missileCannonTargeting.NewTarget(entity.entityInfo);
            basicTargeting.UpdateValues(control.GetVelocityVector(), control.GetPosition(), maxGatlingBulletVel);
            var result = basicTargeting.CalculateTrajectory(entity.entityInfo);

            if (result.HasValue)
            {
                TargetSolvedGatling(result.Value);
            }

            IgnoreEventAfterOnce = true;
        }
Ejemplo n.º 21
0
            private void CalculateStopDistance(IMyShipController controller, List <IMyThrust> thrusters)
            {
                float  mass = controller.CalculateShipMass().PhysicalMass;
                double stopThrustAvailable = 0;
                int    disabledThrusters   = 0;

                thrusters.ForEach(thruster =>
                {
                    if (!thruster.IsWorking)
                    {
                        disabledThrusters++;
                    }
                    if (thruster.IsFunctional)
                    {
                        stopThrustAvailable += thruster.MaxEffectiveThrust;
                    }
                });
                StopThrustersWarning = disabledThrusters > 0;
                double deacceleration = -stopThrustAvailable / mass;
                double currentSpeed   = controller.GetShipSpeed();

                StoppingTime     = (float)(-currentSpeed / deacceleration);
                StoppingDistance = (float)(currentSpeed * StoppingTime + (deacceleration * StoppingTime * StoppingTime) / 2.0f);
            }
Ejemplo n.º 22
0
        public void Main(string argument, UpdateType updateType)
        {
            time += Runtime.TimeSinceLastRun;

            if (!Initialized && time.Seconds % 5 == 0)
            {
                //Run Init every 5 seconds if not initialized.
                Initialized = Init();
            }

            if (Initialized)
            {
                if ((updateType & (UpdateType.Terminal | UpdateType.Trigger)) != 0)
                {
                    Input(argument);
                }

                if ((updateType & UpdateType.Update10) != 0)
                {
                    //screen.WriteText($"Align: {(Align != null && Align.Enabled ? "on" : "off")}, Cruise: {(Cruise != null && Cruise.Enabled ? "on" : "off")}");
                    if (Align != null && Align.Enabled)
                    {
                        Align.Update();
                    }

                    if (Cruise != null && Cruise.Enabled)
                    {
                        Cruise.Update(Runtime.TimeSinceLastRun.TotalSeconds);
                    }

                    if (LCDs != null)
                    {
                        ScreenData data = new ScreenData();

                        data.maxAlt   = targetAltAscending;
                        data.minAlt   = targetAltDescending;
                        data.maxSpeed = worldTopSpeed;
                        if (Cruise != null)
                        {
                            if (Cruise.Enabled)
                            {
                                data.speed       = Cruise.Speed;
                                data.targetSpeed = Cruise.AdaptiveTargetSpeed;
                            }
                            else if (MainController != null)
                            {
                                data.speed       = MainController.GetShipSpeed();
                                data.targetSpeed = targetSpeed;
                            }
                            data.thrustOverrideH2 = Cruise.ThrustOverrideHydrogen;
                            data.thrustOverridePW = Cruise.ThrustOverrideElectric;
                            data.cruiseEnabled    = Cruise.Enabled;
                        }
                        else
                        {
                            if (MainController != null)
                            {
                                data.speed = MainController.GetShipSpeed();
                            }
                            data.targetSpeed = targetSpeed;
                        }

                        if (Align != null)
                        {
                            data.alignEnabled = Align.Enabled;
                        }



                        LCDs.Update(data);
                    }
                }
            }

            DetailedInfo();
            BroadcastStatus();
            //DrawScreens();
        }
Ejemplo n.º 23
0
        void StabilizePod()
        {
            //---Get speed
            currentSpeed = referenceBlock.GetShipSpeed();

            //---Dir'n vectors of the reference block
            var referenceMatrix  = referenceBlock.WorldMatrix;
            var referenceForward = referenceMatrix.Forward;
            var referenceLeft    = referenceMatrix.Left;
            var referenceUp      = referenceMatrix.Up;
            var referenceOrigin  = referenceMatrix.Translation;

            //---Get gravity vector
            gravityVec          = referenceBlock.GetNaturalGravity();
            gravityVecMagnitude = gravityVec.Length();
            if (gravityVec.LengthSquared() == 0)
            {
                foreach (IMyGyro thisGyro in gyros)
                {
                    thisGyro.GyroOverride = false;
                }
                shouldStabilize = false;

                angleRoll = 0;
                angleRoll = 0;
                downSpeed = 0;
                return;
            }

            shipVelocityVec = referenceBlock.GetShipVelocities().LinearVelocity;
            if (shipVelocityVec.LengthSquared() > maxSpeed * maxSpeed)
            {
                maxSpeed = shipVelocityVec.Length();
            }

            downSpeed = VectorProjection(shipVelocityVec, gravityVec).Length() * Math.Sign(shipVelocityVec.Dot(gravityVec));

            //---Determine if we should manually override brake controls
            altitude = 0;
            referenceBlock.TryGetPlanetElevation(MyPlanetElevation.Surface, out altitude);
            altitude -= shipHeight; //adjusts for height of the ship

            brakeAltitudeThreshold     = GetBrakingAltitudeThreshold();
            stabilizeAltitudeThreshold = brakeAltitudeThreshold + 10 * currentSpeed; //this gives us a good safety cushion for stabilization procedures

            //Echo($"Braking distance: {Math.Round(brakeAltitudeThreshold).ToString()}");

            if (altitude < 100 && currentSpeed < 1)
            {
                timeSpentStationary += timeCurrentCycle;
            }
            else
            {
                timeSpentStationary = 0;

                if (altitude <= stabilizeAltitudeThreshold)
                {
                    shouldStabilize = true;
                }
                else
                {
                    shouldStabilize = false;
                }

                if (altitude <= brakeAltitudeThreshold)
                {
                    shouldBrake = true;

                    //kills dampeners to stop their interference with landing procedures
                    referenceBlock.DampenersOverride = false;
                }
                else
                {
                    shouldBrake = false;
                }
            }

            if (shouldBrake)
            {
                if (downSpeed > descentSpeed)
                {
                    BrakingOn();
                }
                else
                {
                    if (attemptToLand)
                    {
                        BrakingThrust();
                    }
                    else
                    {
                        ShutownSystems();
                    }
                }
            }
            else
            {
                BrakingOff();
            }

            Vector3D alignmentVec = new Vector3D(0, 0, 0);

            //--Check if drift compensation is on
            if (useDriftCompensation && downSpeed > descentSpeed)
            {
                alignmentVec = shipVelocityVec;
            }
            else
            {
                alignmentVec = gravityVec;
            }

            //---Get Roll and Pitch Angles
            anglePitch = Math.Acos(MathHelper.Clamp(alignmentVec.Dot(referenceForward) / alignmentVec.Length(), -1, 1)) - Math.PI / 2;

            ///////////////

            ///



            Vector3D planetRelativeLeftVec = referenceForward.Cross(alignmentVec);                                                                                                                   //w.H.i.p.L.A.s.h.1.4.1

            angleRoll  = Math.Acos(MathHelper.Clamp(referenceLeft.Dot(planetRelativeLeftVec) / planetRelativeLeftVec.Length(), -1, 1));
            angleRoll *= Math.Sign(VectorProjection(referenceLeft, alignmentVec).Dot(alignmentVec)); //ccw is positive

            anglePitch *= -1;
            angleRoll  *= -1;

            roll_deg  = Math.Round(angleRoll / Math.PI * 180);
            pitch_deg = Math.Round(anglePitch / Math.PI * 180);

            //---Angle controller
            double rollSpeed  = Math.Round(angleRoll, 2);
            double pitchSpeed = Math.Round(anglePitch, 2);

            //---Enforce rotation speed limit
            if (Math.Abs(rollSpeed) + Math.Abs(pitchSpeed) > 2 * Math.PI)
            {
                double scale = 2 * Math.PI / (Math.Abs(rollSpeed) + Math.Abs(pitchSpeed));
                rollSpeed  *= scale;
                pitchSpeed *= scale;
            }

            if (shouldStabilize)
            {
                ApplyGyroOverride(pitchSpeed, 0, -rollSpeed, gyros, referenceBlock);
            }
            else
            {
                foreach (IMyGyro thisGyro in gyros)
                {
                    thisGyro.GyroOverride = false;
                }
            }
        }
Ejemplo n.º 24
0
        public void Main(string input)
        {
            lcds = SearchBlocksWithName <IMyTextPanel>(lcdSearchName);
            ClearOutput();

            if (input == "start")
            {
                Runtime.UpdateFrequency = UpdateFrequency.Update10;
                Autopilot = true;
            }

            IMyShipController controlBlock = (IMyShipController)GridTerminalSystem.GetBlockWithName(ShipControllerName);

            double altitude             = 0;
            bool   InsideNaturalGravity = controlBlock.TryGetPlanetElevation(MyPlanetElevation.Surface, out altitude);

            Vector3D velocity3D = controlBlock.GetShipVelocities().LinearVelocity;

            if (!InsideNaturalGravity)
            {
                if (Autopilot)
                {
                    WriteLine("Waiting for entering natural gravity");
                    if (input == "stop")
                    {
                        Autopilot = false;
                        WriteLine("Autopilot deactivated (manually)");
                    }
                }
                return;
            }
            else
            {
                if (Autopilot && AutoFall)
                {
                    if (!AutoFallUsed)
                    {
                        input        = "fall";
                        AutoFallUsed = true;
                    }
                }
            }

            List <IMyThrust> thrusters        = GetBlocksInGroup <IMyThrust>(HydrogenThrustersGroupName);
            ThrustController thrustController = new ThrustController(thrusters);

            gyros          = GetBlocksOfType <IMyGyro>();
            gyroController = new GyroController(controlBlock, gyros, Base6Directions.Direction.Down, RotationSpeedLimit);

            Vector3D gravity         = controlBlock.GetNaturalGravity();
            Vector3D position        = controlBlock.GetPosition();                   // ship coords
            double   gravityStrength = gravity.Length();                             // gravity in m/s^2
            double   totalMass       = controlBlock.CalculateShipMass().TotalMass;   // ship total mass including cargo mass
            double   baseMass        = controlBlock.CalculateShipMass().BaseMass;    // mass of the ship without cargo
            double   cargoMass       = totalMass - baseMass;                         // mass of the cargo
            double   actualMass      = baseMass + (cargoMass / InventoryMultiplier); // the mass the game uses for physics calculation
            double   shipWeight      = actualMass * gravityStrength;                 // weight in newtons of the ship
            double   velocity        = controlBlock.GetShipSpeed();                  // ship velocity
            double   brakeDistance   = CalculateBrakeDistance(gravityStrength, actualMass, altitude, thrustController.availableThrust, velocity);
            double   brakeAltitude   = StopAltitude + brakeDistance;                 // at this altitude the ship will start slowing Down

            if (Autopilot)
            {
                gyroController.Align(gravity);

                if (input == "fall")
                {
                    // This is a workaround to a game bug (ship speed greater than speed limit when free falling in natural gravity)
                    // Pros: your ship will not crash. Cons: you will waste a tiny amount of hydrogen.
                    thrustController.ApplyThrust(1);
                }

                if (altitude <= (brakeAltitude + AltitudeMargin))
                {
                    // BRAKE!!!
                    thrustController.ApplyFullThrust(); // Maybe just enable dampeners
                }

                if (altitude <= (StopAltitude + DisableMargin + AltitudeMargin))
                {
                    if (velocity < StopSpeed)
                    {
                        gyroController.Stop();
                        WriteLine("Autopilot deactivated (automatically)");
                    }

                    if (SmartDeactivation)
                    {
                        if (OldVelocity3D.X * velocity3D.X < 0 || OldVelocity3D.Y * velocity3D.Y < 0 || OldVelocity3D.Z * velocity3D.Z < 0)
                        {
                            gyroController.Stop();
                            WriteLine("Autopilot deactivated (automatically)");
                        }
                    }
                }
            }

            OldVelocity3D = velocity3D;

            if (input == "stop")
            {
                Runtime.UpdateFrequency = UpdateFrequency.None;
                gyroController.Stop();
                thrustController.Stop();
                WriteLine("Autopilot deactivated (manually)");
            }
        }
Ejemplo n.º 25
0
        public void Main(string arg)
        {
            RController = GridTerminalSystem.GetBlockWithName(RC) as IMyShipController;
            if (RController == null)
            {
                Echo(RCFailedMSG);
                RCFailed = true;
                Status   = "Failed";
                return;
            }

            RControllers = GridTerminalSystem.GetBlockWithName(RC) as IMyRemoteControl;
            if (RControllers == null)
            {
                Echo(RCFailedMSG);
                RCFailed = true;
                Status   = "Failed";
                return;
            }

            var CCruise = GridTerminalSystem.GetBlockWithName(CC) as IMyProgrammableBlock;

            if (CCruise == null)
            {
                Echo(CCFailedMSG);
                CCFailed = true;
                Status   = "Failed";
                return;
            }

            RGyro = GridTerminalSystem.GetBlockWithName(Gyro) as IMyGyro;
            if (RGyro == null)
            {
                Echo(GyroFailedMSG);
                GyroFailed = true;
                Status     = "Failed";
                return;
            }

            RGyros = GridTerminalSystem.GetBlockWithName(Gyro) as IMyFunctionalBlock;
            if (RGyros == null)
            {
                Echo(GyroFailedMSG);
                GyroFailed = true;
                Status     = "Failed";
                return;
            }

            RCon = GridTerminalSystem.GetBlockWithName(Cargo) as IMyCargoContainer;
            if (RCon == null)
            {
                Echo(RConFailedMSG);
                RConFailed = true;
                Status     = "Failed";
                return;
            }

            LAntenna = GridTerminalSystem.GetBlockWithName(LA) as IMyLaserAntenna;
            if (LAntenna == null)
            {
                Echo(LAFailedMSG);
                LAFailed = true;
                Status   = "Failed";
                return;
            }

            LGear = GridTerminalSystem.GetBlockWithName(LG) as IMyTimerBlock;
            if (LGear == null)
            {
                Echo(LGFailedMSG);
                LGFailed = true;
                Status   = "Failed";
                return;
            }

            CCUp = GridTerminalSystem.GetBlockWithName(CCU) as IMyTimerBlock;
            if (CCUp == null)
            {
                Echo(CCTsFailedMSG);
                CCTsFailed = true;
                Status     = "Failed";
                return;
            }
            CCOff = GridTerminalSystem.GetBlockWithName(CCO) as IMyTimerBlock;
            if (CCOff == null)
            {
                Echo(CCTsFailedMSG);
                CCTsFailed = true;
                Status     = "Failed";
                return;
            }
            CCDown = GridTerminalSystem.GetBlockWithName(CCD) as IMyTimerBlock;
            if (CCDown == null)
            {
                Echo(CCTsFailedMSG);
                CCTsFailed = true;
                Status     = "Failed";
                return;
            }
            GridTerminalSystem.GetBlocksOfType(thrustersUP, x => x.WorldMatrix.Forward == RControllers.WorldMatrix.Up);
            if (thrustersUP.Count == 0)
            {
                Echo($"Error: No lift-off thrusters were found!");
            }
            GridTerminalSystem.GetBlocksOfType(thrustersDOWN, x => x.WorldMatrix.Forward == RControllers.WorldMatrix.Down);
            if (thrustersDOWN.Count == 0)
            {
                Echo($"Error: No lift-off thrusters were found!");
            }
            var shipMass = RController.CalculateShipMass();

            TotalMass  = shipMass.TotalMass;
            AutoEnable = RControllers.IsAutoPilotEnabled;
            RController.TryGetPlanetElevation(MyPlanetElevation.Sealevel, out Elev);
            velo          = RController.GetShipSpeed();
            Position      = RController.GetPosition();
            Gravity       = (RController.GetNaturalGravity().Length());
            GravityG      = (RController.GetNaturalGravity().Length() / 9.81);
            thrustSumUP   = 0;
            thrustSumDOWN = 0;
            foreach (var block in thrustersUP)
            {
                thrustSumUP += block.MaxEffectiveThrust;
            }
            foreach (var block in thrustersDOWN)
            {
                thrustSumDOWN += block.MaxEffectiveThrust;
            }
            if (Status == "Launched")
            {
                TargetGravity = (PlanetGravity * (Math.Pow((MaxR / (TargetAltitude + MinR)), 7)));
                Accel         = ((thrustSumUP / TotalMass) + TargetGravity); //Stopping force
                AccelTime     = ((0 - velo) / -Accel);                       //Seconds to stop
                stopDistance  = ((velo * AccelTime) + ((-Accel * (AccelTime * AccelTime)) / 2));
            }
            if (Status == "Return")
            {
                Accel        = ((thrustSumDOWN / TotalMass) - PlanetGravity); //Stopping force
                AccelTime    = ((0 - velo) / -Accel);                         //Seconds to stop
                stopDistance = ((velo * AccelTime) + ((-Accel * (AccelTime * AccelTime)) / 2));
            }
            Echo(Ship + " Control Pro");
            Echo("Status: " + Status);
            Echo("Altitude: " + Math.Round(Elev, 2) + "/" + TargetAltitude);
            Echo("Speed: " + Math.Round(velo, 2));
            Echo("Total Weight: " + TotalMass);
            Echo("Gravity: " + Math.Round(GravityG, 2) + "G");
            string msg = ("Ship" + ":" + Ship + "," + "Status" + ":" + Status + "," + "Elevation" + ":" + Elev + "," + "Position" + ":" + Position + "," + "Speed" + ":" + velo + "," + "Target" + ":" + TargetAltitude + ",");

            LAntenna.TransmitMessage(msg);
            var keyValuePairs = arg.Split(',').Select(x => x.Split(':')).Where(x => x.Length == 2).ToDictionary(x => x.First(), x => x.Last());

            //Echo(thrustSumDOWN.ToString());
            //Echo(thrustersDOWN.Count.ToString());
            //Echo(thrustSumUP.ToString());
            //Echo(thrustersUP.Count.ToString());

            if (Status == "Failed")
            {
                if (RCFailed == true)
                {
                    Echo(RCFailedMSG); return;
                }
                if (CCFailed == true)
                {
                    Echo(CCFailedMSG); return;
                }
                if (GyroFailed == true)
                {
                    Echo(GyroFailedMSG); return;
                }
                if (LAFailed == true)
                {
                    Echo(LAFailedMSG); return;
                }
                if (LGFailed == true)
                {
                    Echo(LGFailedMSG); return;
                }
                if (RConFailed == true)
                {
                    Echo(RConFailedMSG); return;
                }
                if (CCTsFailed == true)
                {
                    Echo(CCTsFailedMSG); return;
                }
                Status = "Failed";
                return;
            }

            if (arg.Contains("Target"))
            {
                TargetAltitudeSetter = keyValuePairs["Target"];
                TargetAltitude       = int.Parse(TargetAltitudeSetter);
                NotReady();
            }
            if (!Init)
            {
                Status = "Initalizing..."; NotReady();
            }
            if (arg == "Reset")
            {
                Status = "Not Ready"; NotReady();
            }
            if (arg == "Ready")
            {
                Status = "Ready"; Ready();
            }
            if (arg == "Launch")
            {
                Status = "Launching"; Launch();
            }
            if (arg == "Launched")
            {
                Status = "Launched"; Climb();
            }
            if (arg == "Seperate")
            {
                Status = "Seperation"; Seperation();
            }
            if (arg == "Return")
            {
                Status = "Return"; Return();
            }
            if (arg == "Approach")
            {
                Status = "Approaching"; Approach();
            }
            if (arg == "Land")
            {
                Status = "Landing"; Land();
            }
            if (arg == "Landed")
            {
                Status = "Landed";
            }

            if (Status == "Launching")
            {
                Launch();
            }
            if (Status == "Launched")
            {
                Climb();
            }
            if (Status == "Seperation")
            {
                Seperation();
            }
            if (Status == "Return")
            {
                Return();
            }
            if (Status == "Approaching")
            {
                Approach();
            }
            if (Status == "Landing")
            {
                Land();
            }
            if (Status == "Landed")
            {
                Status = "Landed";
            }
        }
Ejemplo n.º 26
0
            private void StabilizePod()
            {
                //---Get speed
                double currentSpeed = referenceBlock.GetShipSpeed();


                Vector3D vectDistanceToEnd = destination.ToVector3D() - referenceBlock.GetPosition();

                Vector3D shipVelocityVec = referenceBlock.GetShipVelocities().LinearVelocity;

                double brakingSpeed = VectorUtils.Projection(shipVelocityVec, vectDistanceToEnd).Length() * Math.Sign(shipVelocityVec.Dot(vectDistanceToEnd));

                //---Determine if we should manually override brake controls
                double distanceToEnd = vectDistanceToEnd.Length();

                //--- Manage gravity
                Vector3D gravityVec          = referenceBlock.GetNaturalGravity();
                double   gravityVecMagnitude = gravityVec.Length();

                if (gravityVecMagnitude > 0.0001)
                {
                    double distanceToSurface;
                    referenceBlock.TryGetPlanetElevation(MyPlanetElevation.Surface, out distanceToSurface);
                    // TODO take into account this distance if we fly near the surface
                }

                distanceToEnd -= shipCenterToEdge;

                double distanceToStartBraking = GetBrakingDistanceThreshold(gravityVecMagnitude, shipVelocityVec);
                //this gives us a good safety cushion for stabilization procedures
                double distanceToStartStabilize = distanceToStartBraking + 10 * currentSpeed;

                bool shouldBrake     = false;
                bool shouldStabilize = false;

                if (distanceToEnd < 100 && currentSpeed < 1)
                {
                    timeSpentStationary += timeCurrentCycle;
                }
                else
                {
                    timeSpentStationary = 0;
                    shouldStabilize     = distanceToEnd <= distanceToStartStabilize;
                    shouldBrake         = distanceToEnd <= distanceToStartBraking;
                    //kills dampeners to stop their interference with landing procedures
                    if (shouldBrake)
                    {
                        referenceBlock.DampenersOverride = false;
                    }
                }

                if (shouldBrake)
                {
                    bool isBraking = brakingSpeed > FROM_BRAKING_TO_END_SPEED;
                    if (isBraking)
                    {
                        BrakingOn();
                    }
                    else
                    {
                        if (attemptToLand)
                        {
                            BrakingThrust(brakingSpeed, gravityVecMagnitude);
                        }
                        else
                        {
                            StopSystem();                             // Fin
                        }
                    }
                }
                else
                {
                    BrakingOff();
                }


                if (shouldStabilize)
                {
                    //---Get Roll and Pitch Angles

                    Vector3D alignmentVec = brakingSpeed > FROM_BRAKING_TO_END_SPEED || gravityVecMagnitude <= 0 ? shipVelocityVec : gravityVec;

                    //---Dir'n vectors of the reference block
                    var referenceMatrix  = referenceBlock.WorldMatrix;
                    var referenceForward = referenceMatrix.Forward;
                    var referenceLeft    = referenceMatrix.Left;
                    var referenceUp      = referenceMatrix.Up;
                    var referenceOrigin  = referenceMatrix.Translation;

                    // Roll = rotation around forward/backward axis => to roll
                    // Pitch = rotation around left/right axis => to go up or down
                    // Yaw = rotation around up/down axis => to go left or right

                    double forAngleRadPitch = MathHelper.Clamp(alignmentVec.Dot(referenceForward) / alignmentVec.Length(), -1, 1);
                    double anglePitch       = Math.Acos(forAngleRadPitch);               // TODO test mais on freine vers l'avant pas le bas : - Math.PI / 2;

                    // ???
                    Vector3D relativeLeftVec = referenceForward.Cross(alignmentVec);

                    double forAngleRadRoll = MathHelper.Clamp(referenceLeft.Dot(relativeLeftVec) / relativeLeftVec.Length(), -1, 1);
                    double angleRoll       = Math.Acos(forAngleRadRoll);
                    angleRoll *= Math.Sign(VectorUtils.Projection(referenceLeft, alignmentVec).Dot(alignmentVec));                     //ccw is positive

                    anglePitch *= -1;
                    angleRoll  *= -1;

                    double roll_deg  = Math.Round(angleRoll / Math.PI * 180);
                    double pitch_deg = Math.Round(anglePitch / Math.PI * 180);

                    //---Angle controller
                    double rollSpeed  = Math.Round(angleRoll, 2);
                    double pitchSpeed = Math.Round(anglePitch, 2);

                    //---Enforce rotation speed limit
                    if (Math.Abs(rollSpeed) + Math.Abs(pitchSpeed) > 2 * Math.PI)
                    {
                        double scale = 2 * Math.PI / (Math.Abs(rollSpeed) + Math.Abs(pitchSpeed));
                        rollSpeed  *= scale;
                        pitchSpeed *= scale;
                    }

                    ApplyGyroOverride(pitchSpeed, 0, -rollSpeed);
                }
                else
                {
                    foreach (IMyGyro thisGyro in gyros)
                    {
                        thisGyro.GyroOverride = false;
                    }
                }
            }
Ejemplo n.º 27
0
            private void CalcWorldSpeed()
            {
                Vector3D linearVelocity = Vector3D.Normalize(cockpit.GetShipVelocities().LinearVelocity);
                Vector3D gravity        = -Vector3D.Normalize(cockpit.GetNaturalGravity());

                worldSpeedForward = Helpers.NotNan(Vector3D.Dot(linearVelocity, Vector3D.Cross(gravity, cockpit.WorldMatrix.Right)) * cockpit.GetShipSpeed());
                worldSpeedRight   = Helpers.NotNan(Vector3D.Dot(linearVelocity, Vector3D.Cross(gravity, cockpit.WorldMatrix.Forward)) * cockpit.GetShipSpeed());
                worldSpeedUp      = Helpers.NotNan(Vector3D.Dot(linearVelocity, gravity) * cockpit.GetShipSpeed());
            }
Ejemplo n.º 28
0
        public void Main(string args = "START")
        {
            Config config = new Config(Me.CustomData);

            config.Set(ref thrustersGroupName, "thrustersGroupName");
            config.Set(ref referenceBlockName, "referenceBlockName");
            config.Set(ref lcdSearchName, "lcdSearchName");
            config.Set <double>(ref marginOfErrorThrust, "marginOfErrorThrust");
            config.Set <double>(ref targetSpeed, "targetSpeed");
            config.Set <double>(ref targetSpeedVariation, "targetSpeedVariation");
            config.Set <double>(ref gravityTreshold, "gravityTreshold");

            controlBlock = GridTerminalSystem.GetBlockWithName(referenceBlockName) as IMyShipController;
            lcds         = SearchBlocksWithName <IMyTextPanel>(lcdSearchName);

            if (args == "START")
            {
                Runtime.UpdateFrequency = UpdateFrequency.Update10;
                reachedTopSpeedOnce     = false;
                turnAndBurn             = null;
            }

            lcds.ForEach(lcd => {
                lcd.WritePublicTitle("Launch control");
                lcd.WritePublicText(""); // Clear LCD
            });

            if (controlBlock == null)
            {
                WriteLine("No control block found on grid.");
                WriteLine("Terminating script.");
                return;
            }

            thrusters        = GetBlocksInGroup <IMyThrust>(thrustersGroupName);
            thrustController = new ThrustController(thrusters);
            gyros            = GetBlocksOfType <IMyGyro>();
            gyroController   = new GyroController(controlBlock, gyros, Base6Directions.Direction.Down, 0.8);

            gravity         = controlBlock.GetNaturalGravity();
            gravityStrength = gravity.Length();
            var escaped = gravityStrength <= gravityTreshold;

            gravity.Normalize();

            if (gravityStrength != 0)
            {
                lastObservedGravity = gravity;
            }

            if (thrusters == null || thrusters.Count == 0)
            {
                WriteLine($"No thrusters found in \"{thrustersGroupName}\" group.");
                WriteLine("Terminating script.");
                return;
            }

            speed = controlBlock.GetShipSpeed();
            if (speed > targetSpeed)
            {
                reachedTopSpeedOnce = true;
            }

            WriteLine($"Ship speed: {Math.Round(speed, 1)} m/s");
            WriteLine($"Target: {Math.Round(targetSpeed, 1)} m/s");

            if (!escaped)
            {
                ApplyThrust();
                gyroController.Align(gravity);
                angle = Math.Acos(
                    Vector3D.Dot(
                        Vector3D.Normalize(controlBlock.GetNaturalGravity()),
                        Vector3D.Normalize(-controlBlock.GetShipVelocities().LinearVelocity)
                        )
                    ) * 180 / Math.PI;

                WriteLine($"Angle deviation: {Math.Round(angle)}°");
            }

            if (escaped)
            {
                if (turnAndBurn == null)
                {
                    thrustController.Stop();
                    SetDampeners(false);
                }

                turnAndBurn = gyroController.Align(lastObservedGravity, Base6Directions.Direction.Up) ? "aligned" : "started";
                WriteLine($"Turn and burn: {turnAndBurn}");
            }

            if (args == "STOP" || (escaped && turnAndBurn == "aligned"))
            {
                thrustController.Stop();
                gyroController.Stop();
                SetDampeners(true);
                Runtime.UpdateFrequency = UpdateFrequency.None;
                ClearOutput();
                WriteLine("Launch control ended.");
            }
        }
Ejemplo n.º 29
0
            void doModeGoTarget()
            {
                int iMode  = thisProgram.wicoControl.IMode;
                int iState = thisProgram.wicoControl.IState;

                //                StatusLog("clear", textPanelReport);

                //                StatusLog(moduleName + ":Going Target!", textPanelReport);
                //            StatusLog(moduleName + ":GT: iState=" + iState.ToString(), textPanelReport);
                //            bWantFast = true;
                thisProgram.Echo("Going Target: state=" + iState.ToString());
                if (NAVTargetName != "")
                {
                    thisProgram.Echo(NAVTargetName);
                }

                string sNavDebug = "";

                sNavDebug += "GT:S=" + iState;
                //            sNavDebug += " MinE=" + NAVGravityMinElevation;
                //            ResetMotion();
                IMyShipController shipController = thisProgram.wicoBlockMaster.GetMainController();
                Vector3D          vNG            = shipController.GetNaturalGravity();
                double            dGravity       = vNG.Length();

                if (iState == 0)
                {
                    thisProgram.wicoTravelMovement.ResetTravelMovement();
                    //                sStartupError+="\nStart movemenet: ArrivalMode="+NAVArrivalMode+" State="+NAVArrivalState;
                    //                    if ((craft_operation & CRAFT_MODE_SLED) > 0)
                    if (thisProgram.wicoWheels.HasSledWheels())
                    {
                        bSled = true;
                        if (shipSpeedMax > 45)
                        {
                            shipSpeedMax = 45;
                        }
                    }
                    else
                    {
                        bSled = false;
                    }

                    //                    if ((craft_operation & CRAFT_MODE_ROTOR) > 0)
                    if (thisProgram.wicoNavRotors.NavRotorCount() > 0)
                    {
                        bRotor = true;
                        if (shipSpeedMax > 15)
                        {
                            shipSpeedMax = 15;
                        }
                    }
                    else
                    {
                        bRotor = false;
                    }
                    //                    if ((craft_operation & CRAFT_MODE_WHEEL) > 0)
                    if (thisProgram.wicoWheels.HasWheels())
                    {
                        bWheels = true;
                        //                   if (shipSpeedMax > 15) shipSpeedMax = 15;
                    }
                    else
                    {
                        bWheels = false;
                    }

//                    GyroControl.SetRefBlock(shipOrientationBlock);

                    // TODO: Put a timer on this so it's not done Update1
                    double elevation = 0;
                    shipController.TryGetPlanetElevation(MyPlanetElevation.Surface, out elevation);

                    if (!bSled && !bRotor)
                    { // if flying ship
                      // make sure set to default
                        if (thisProgram.wicoBlockMaster.DesiredMinTravelElevation < 0)
                        {
                            thisProgram.wicoBlockMaster.DesiredMinTravelElevation = 75; // for EFM getting to target 'arrived' radius
                        }
                    }

                    if (bValidNavTarget)
                    {
                        if (elevation > thisProgram.wicoBlockMaster.HeightInMeters())
                        {
                            iState = 150;
                        }
                        else
                        {
                            iState = 160;
                        }
                    }
                    else
                    {
                        thisProgram.wicoControl.SetMode(WicoControl.MODE_ATTENTION); //else setMode(MODE_ATTENTION);
                    }
                    thisProgram.wicoControl.WantFast();                              // bWantFast = true;
                }
                else if (iState == 150)
                {
                    thisProgram.wicoControl.WantFast();// bWantFast = true;
                    if (dGravity > 0)
                    {
                        double elevation = 0;

                        shipController.TryGetPlanetElevation(MyPlanetElevation.Surface, out elevation);
                        sNavDebug += " E=" + elevation.ToString("0.0");

                        float fSaveAngle = thisProgram.wicoGyros.GetMinAngle(); // minAngleRad;
                        thisProgram.wicoGyros.SetMinAngle(0.1f);                // minAngleRad = 0.1f;

                        bool bAligned = GyroMain("", vNG, shipController);
                        sNavDebug += " Aligned=" + bAligned.ToString();

                        thisProgram.Echo("bAligned=" + bAligned.ToString());
                        thisProgram.wicoGyros.SetMinAngle(fSaveAngle); //minAngleRad = fSaveAngle;
                        if (bAligned || elevation < thisProgram.wicoBlockMaster.HeightInMeters() * 2)
                        {
                            thisProgram.wicoGyros.gyrosOff();
                            if (thisProgram.wicoBlockMaster.DesiredMinTravelElevation > 0)
                            {
                                iState = 155;
                            }
                            else
                            {
                                iState = 160;
                            }
                        }
                    }
                    else
                    {
                        iState = 160;
                    }
                }
                else if (iState == 151)
                {
                    thisProgram.wicoControl.WantFast();// bWantFast = true;
                    if (dGravity > 0 || btmWheels)
                    {
                        double elevation = 0;

                        shipController.TryGetPlanetElevation(MyPlanetElevation.Surface, out elevation);
                        sNavDebug += " E=" + elevation.ToString("0.0");

                        float fSaveAngle = thisProgram.wicoGyros.GetMinAngle(); // minAngleRad;
                        thisProgram.wicoGyros.SetMinAngle(0.1f);                // minAngleRad = 0.1f;

                        bool bAligned = GyroMain("", vNG, shipOrientationBlock);
                        sNavDebug += " Aligned=" + bAligned.ToString();

                        thisProgram.Echo("bAligned=" + bAligned.ToString());
                        thisProgram.wicoGyros.SetMinAngle(fSaveAngle); //minAngleRad = fSaveAngle;
                        if (bAligned || elevation < thisProgram.wicoBlockMaster.HeightInMeters() * 2)
                        {
                            thisProgram.wicoGyros.gyrosOff();
                            if (thisProgram.wicoBlockMaster.DesiredMinTravelElevation > 0)
                            {
                                iState = 155;
                            }
                            else
                            {
                                iState = 160;
                            }
                        }
                        else
                        {
                            iState = 150; // try again to be aligned.
                        }
                    }
                    else
                    {
                        iState = 160;
                    }
                }
                else if (iState == 155)
                {                                       // for use in gravity: aim at location using yaw only
                    thisProgram.wicoControl.WantFast(); // bWantFast = true;
                    if (bWheels)
                    {
                        iState = 160;
                        return;
                    }

                    if (dGravity > 0)
                    {
                        bool bAligned = GyroMain("", vNG, shipController);
                        sNavDebug += " Aligned=" + bAligned.ToString();

                        double yawangle = -999;
                        yawangle = thisProgram.CalculateYaw(vNavTarget, shipController);
                        bool bAimed = Math.Abs(yawangle) < 0.1; // NOTE: 2x allowance
                        thisProgram.Echo("yawangle=" + yawangle.ToString());
                        sNavDebug += " Yaw=" + yawangle.ToString("0.00");

                        if (!bAimed)
                        {
                            if (btmRotor)
                            {
                                thisProgram.Echo("Rotor");
                                thisProgram.wicoNavRotors.DoRotorRotate(yawangle);
                            }
                            else // use for both sled and flight
                            {
                                thisProgram.wicoGyros.DoRotate(yawangle, "Yaw");
                            }
                        }
                        if (bAligned && bAimed)
                        {
                            thisProgram.wicoGyros.gyrosOff();
                            iState = 160;
                        }
                        else if (bAligned && Math.Abs(yawangle) < 0.5)
                        {
                            float atmo;
                            float hydro;
                            float ion;

                            thisProgram.wicoThrusters.CalculateHoverThrust(shipController, thrustForwardList, out atmo, out hydro, out ion);
                            atmo  += 1;
                            hydro += 1;
                            ion   += 1;

                            thisProgram.wicoThrusters.powerUpThrusters(thrustForwardList, atmo, WicoThrusters.thrustatmo);
                            thisProgram.wicoThrusters.powerUpThrusters(thrustForwardList, hydro, WicoThrusters.thrusthydro);
                            thisProgram.wicoThrusters.powerUpThrusters(thrustForwardList, ion, WicoThrusters.thrustion);
                        }
                        else
                        {
                            thisProgram.wicoThrusters.powerDownThrusters(thrustForwardList);
                        }
                    }
                    else
                    {
                        iState = 160;
                    }
                }
                else if (iState == 156)
                {
                    // realign gravity
                    thisProgram.wicoControl.WantFast();// bWantFast = true;
                    bool bAimed = GyroMain("", grav, shipOrientationBlock);
                    if (bAimed)
                    {
                        thisProgram.wicoGyros.gyrosOff();
                        iState = 160;
                    }
                }
                else if (iState == 160)
                { //	160 move to Target
                    thisProgram.Echo("Moving to Target");
                    Vector3D vTargetLocation = vNavTarget;
                    double   velocityShip    = shipController.GetShipSpeed();

                    Vector3D vVec     = vTargetLocation - shipController.GetPosition();
                    double   distance = vVec.Length();
                    thisProgram.Echo("distance=" + niceDoubleMeters(distance));
                    thisProgram.Echo("velocity=" + velocityShip.ToString("0.00"));

//                    StatusLog("clear", sledReport);
                    string sTarget = "Moving to Target";
                    if (NAVTargetName != "")
                    {
                        sTarget = "Moving to " + NAVTargetName;
                    }
//                    StatusLog(sTarget + "\nD:" + niceDoubleMeters(distance) + " V:" + velocityShip.ToString(velocityFormat), sledReport);
//                    StatusLog(sTarget + "\nDistance: " + niceDoubleMeters(distance) + "\nVelocity: " + niceDoubleMeters(velocityShip) + "/s", textPanelReport);


                    if (bGoOption && (distance < arrivalDistanceMin))
                    {
                        iState = 500;

                        thisProgram.Echo("we have arrived");
                        thisProgram.wicoControl.WantFast();// bWantFast = true;
                        return;
                    }

                    //                debugGPSOutput("TargetLocation", vTargetLocation);
                    bool bDoTravel = true;

                    if (thisProgram.wicoBlockMaster.DesiredMinTravelElevation > 0 && dGravity > 0)
                    {
                        double elevation = 0;

                        MyShipVelocities mysSV = shipController.GetShipVelocities();
                        Vector3D         lv    = mysSV.LinearVelocity;

                        // ASSUMES: -up = gravity down  Assuming ship orientation
                        var upVec   = shipController.WorldMatrix.Up;
                        var vertVel = Vector3D.Dot(lv, upVec);

                        //                    thisProgram.Echo("LV=" + Vector3DToString(lv));
                        //                    sNavDebug += " LV=" + Vector3DToString(lv);
                        //                    sNavDebug += " vertVel=" + vertVel.ToString("0.0");
                        //                    sNavDebug += " Hvel=" + lv.Y.ToString("0.0");

                        // NOTE: Elevation is only updated by game every 30? ticks. so it can be WAY out of date based on movement
                        shipController.TryGetPlanetElevation(MyPlanetElevation.Surface, out elevation);
                        sNavDebug += " E=" + elevation.ToString("0.0");
                        sNavDebug += " V=" + velocityShip.ToString("0.00");

                        thisProgram.Echo("Elevation=" + elevation.ToString("0.0"));
                        thisProgram.Echo("MinEle=" + thisProgram.wicoBlockMaster.DesiredMinTravelElevation.ToString("0.0"));

                        //                    double stopD = calculateStoppingDistance(thrustUpList, velocityShip, dGravity);
                        double stopD = 0;
                        if (vertVel < 0)
                        {
                            stopD = thisProgram.wicoThrusters.calculateStoppingDistance(thrustUpList, Math.Abs(vertVel), dGravity);
                        }
                        double maxStopD = thisProgram.wicoThrusters.calculateStoppingDistance(thrustUpList, thisProgram.wicoControl.fMaxWorldMps, dGravity);

                        float atmo;
                        float hydro;
                        float ion;
                        thisProgram.wicoThrusters.CalculateHoverThrust(thrustUpList, out atmo, out hydro, out ion);

                        //                    sNavDebug += " SD=" + stopD.ToString("0");

                        if (
                            //                        !bSled && !bRotor &&
                            thisProgram.wicoBlockMaster.DesiredMinTravelElevation > 0)
                        {
                            if (
                                vertVel < -0.5 && // we are going downwards
                                (elevation - stopD * 2) < thisProgram.wicoBlockMaster.DesiredMinTravelElevation)
                            { // too low. go higher
                              // Emergency thrust
                                sNavDebug += " EM UP!";

                                bool bAligned = GyroMain("", grav, shipOrientationBlock);

                                thisProgram.wicoThrusters.powerUpThrusters(thrustUpList, 100);
                                bDoTravel = false;
                                thisProgram.wicoControl.WantFast();// bWantFast = true;
                            }
                            else if (elevation < thisProgram.wicoBlockMaster.DesiredMinTravelElevation)
                            {
                                // push upwards
                                atmo      += Math.Min(5f, (float)shipSpeedMax);
                                hydro     += Math.Min(5f, (float)shipSpeedMax);
                                ion       += Math.Min(5f, (float)shipSpeedMax);
                                sNavDebug += " UP! A" + atmo.ToString("0.00"); // + " H"+hydro.ToString("0.00") + " I"+ion.ToString("0.00");
                                                                               //powerUpThrusters(thrustUpList, 100);
                                thisProgram.wicoThrusters.powerUpThrusters(thrustUpList, atmo, thrustatmo);
                                thisProgram.wicoThrusters.powerUpThrusters(thrustUpList, hydro, thrusthydro);
                                thisProgram.wicoThrusters.powerUpThrusters(thrustUpList, ion, thrustion);
                            }
                            else if (elevation > (maxStopD + thisProgram.wicoBlockMaster.DesiredMinTravelElevation * 1.25))
                            {
                                // if we are higher than maximum possible stopping distance, go down fast.
                                sNavDebug += " SUPERHIGH";

                                //                           Vector3D grav = (shipOrientationBlock as IMyShipController).GetNaturalGravity();
                                //                            bool bAligned = GyroMain("", grav, shipOrientationBlock);

                                thisProgram.wicoThrusters.powerDownThrusters(thrustUpList, thrustAll, true);
                                bool bAligned = GyroMain("", grav, shipOrientationBlock);
                                if (!bAligned)
                                {
                                    thisProgram.wicoControl.WantFast();// bWantFast = true;
                                    bDoTravel = false;
                                }
                                //                            powerUpThrusters(thrustUpList, 1f);
                            }
                            else if (
                                elevation > thisProgram.wicoBlockMaster.DesiredMinTravelElevation * 2  // too high
                                //                            && ((elevation-stopD)>NAVGravityMinElevation) // we can stop in time.
                                //                        && velocityShip < shipSpeedMax * 1.1 // to fast in any direction
                                //                           && Math.Abs(lv.X) < Math.Min(25, shipSpeedMax) // not too fast
                                //                            && Math.Abs(lv.Y) < Math.Min(25, shipSpeedMax) // not too fast downwards (or upwards)
                                )
                            { // too high
                                sNavDebug += " HIGH";
                                //DOWN! A" + atmo.ToString("0.00");// + " H" + hydro.ToString("0.00") + " I" + ion.ToString("0.00");

                                if (vertVel > 2) // going up
                                {                // turn off thrusters.
                                    sNavDebug += " ^";
                                    thisProgram.wicoThrusters.powerDownThrusters(thrustUpList, thrustAll, true);
                                }
                                else if (vertVel < -0.5) // going down
                                {
                                    sNavDebug += " v";
                                    if (vertVel > (-Math.Min(15, shipSpeedMax)))
                                    {
                                        // currently descending at less than desired
                                        atmo      -= Math.Max(25f, Math.Min(5f, (float)velocityShip / 2));
                                        hydro     -= Math.Max(25f, Math.Min(5f, (float)velocityShip / 2));
                                        ion       -= Math.Max(25f, Math.Min(5f, (float)velocityShip / 2));
                                        sNavDebug += " DOWN! A" + atmo.ToString("0.00"); // + " H" + hydro.ToString("0.00") + " I" + ion.ToString("0.00");
                                                                                         //                                   bDoTravel = false;
                                    }
                                    else
                                    {
                                        // we are descending too fast.
                                        atmo      += Math.Max(100f, Math.Min(5f, (float)velocityShip / 2));
                                        hydro     += Math.Max(100f, Math.Min(5f, (float)velocityShip / 2));
                                        ion       += Math.Max(100f, Math.Min(5f, (float)velocityShip / 2));
                                        sNavDebug += " 2FAST! A" + atmo.ToString("0.00");// + " H" + hydro.ToString("0.00") + " I" + ion.ToString("0.00");
                                        bool bAligned = GyroMain("", grav, shipOrientationBlock);
                                        if (!bAligned)
                                        {
                                            thisProgram.wicoControl.WantFast();// bWantFast = true;
                                            bDoTravel = false;
                                        }
                                        //                                    bDoTravel = false;
                                    }
                                }
                                else
                                {
                                    sNavDebug += " -";
                                    atmo      -= 5;
                                    hydro     -= 5;
                                    ion       -= 5;
                                }

                                thisProgram.wicoThrusters.powerUpThrusters(thrustUpList, atmo, thrustatmo);
                                thisProgram.wicoThrusters.powerUpThrusters(thrustUpList, hydro, thrusthydro);
                                thisProgram.wicoThrusters.powerUpThrusters(thrustUpList, ion, thrustion);
                            }
                            else
                            {
                                // normal hover
                                thisProgram.wicoThrusters.powerDownThrusters(thrustUpList);
                            }
                        }
                    }
                    if (bDoTravel)
                    {
                        thisProgram.Echo("Do Travel");
                        thisProgram.wicoTravelMovement.doTravelMovement(vTargetLocation, (float)arrivalDistanceMin, 500, 300);
                    }
                    else
                    {
                        thisProgram.wicoThrusters.powerDownThrusters(thrustForwardList);
                    }
                }

                else if (iState == 300)
                {                                       // collision detection
                    thisProgram.wicoControl.WantFast(); // bWantFast = true;
                    Vector3D vTargetLocation = vNavTarget;
                    thisProgram.wicoTravelMovement.ResetTravelMovement();
                    thisProgram.wicoTravelMovement.calcCollisionAvoid(vTargetLocation, lastDetectedInfo, out vAvoid);

                    //                iState = 301; // testing
                    iState = 320;
                }
                else if (iState == 301)
                {
                    // just hold this state
                    thisProgram.wicoControl.WantFast();// bWantFast = true;
                }

                else if (iState == 320)
                {
                    //                 Vector3D vVec = vAvoid - shipOrientationBlock.GetPosition();
                    //                double distanceSQ = vVec.LengthSquared();
                    thisProgram.Echo("Primary Collision Avoid");
//                    StatusLog("clear", sledReport);
//                    StatusLog("Collision Avoid", sledReport);
//                    StatusLog("Collision Avoid", textPanelReport);
                    thisProgram.wicoTravelMovement.doTravelMovement(vAvoid, 5.0f, 160, 340);
                }
                else if (iState == 340)
                {       // secondary collision
                    if (
                        lastDetectedInfo.Type == MyDetectedEntityType.LargeGrid ||
                        lastDetectedInfo.Type == MyDetectedEntityType.SmallGrid
                        )
                    {
                        iState = 345;
                    }
                    else if (lastDetectedInfo.Type == MyDetectedEntityType.Asteroid
                             )
                    {
                        iState = 350;
                    }
                    else
                    {
                        iState = 300;                   // setMode(MODE_ATTENTION);
                    }
                    thisProgram.wicoControl.WantFast(); // bWantFast = true;
                }
                else if (iState == 345)
                {
                    // we hit a grid.  align to it
                    Vector3D[] corners = new Vector3D[BoundingBoxD.CornerCount];

                    BoundingBoxD bbd = lastDetectedInfo.BoundingBox;
                    bbd.GetCorners(corners);

                    GridUpVector    = thisProgram.wicoSensors.PlanarNormal(corners[3], corners[4], corners[7]);
                    GridRightVector = thisProgram.wicoSensors.PlanarNormal(corners[0], corners[1], corners[4]);
                    thisProgram.wicoControl.WantFast();// bWantFast = true;
                    iState = 348;
                }
                else if (iState == 348)
                {
                    thisProgram.wicoControl.WantFast();// bWantFast = true;
                    if (GyroMain("up", GridUpVector, shipOrientationBlock))
                    {
                        iState = 349;
                    }
                }
                else if (iState == 349)
                {
                    thisProgram.wicoControl.WantFast();// bWantFast = true;
                    if (GyroMain("right", GridRightVector, shipOrientationBlock))
                    {
                        iState = 350;
                    }
                }
                else if (iState == 350)
                {
                    //                initEscapeScan(bCollisionWasSensor, !bCollisionWasSensor);
                    initEscapeScan(bCollisionWasSensor);
                    thisProgram.wicoTravelMovement.ResetTravelMovement();
                    dtNavStartShip = DateTime.Now;
                    iState         = 360;
                    thisProgram.wicoControl.WantFast();// bWantFast = true;
                }
                else if (iState == 360)
                {
//                    StatusLog("Collision Avoid\nScan for escape route", textPanelReport);
                    DateTime dtMaxWait = dtNavStartShip.AddSeconds(5.0f);
                    DateTime dtNow     = DateTime.Now;
                    if (DateTime.Compare(dtNow, dtMaxWait) > 0)
                    {
                        thisProgram.wicoControl.SetMode(WicoControl.MODE_ATTENTION);// setMode(MODE_ATTENTION);
                        //                        doTriggerMain();
                        return;
                    }
                    if (scanEscape())
                    {
                        thisProgram.Echo("ESCAPE!");
                        iState = 380;
                    }
                    thisProgram.wicoControl.WantMedium(); // bWantMedium = true;
                    //                bWantFast = true;
                }
                else if (iState == 380)
                {
//                    StatusLog("Collision Avoid Travel", textPanelReport);
                    thisProgram.Echo("Escape Collision Avoid");
                    thisProgram.wicoTravelMovement.doTravelMovement(vAvoid, 1f, 160, 340);
                }
                else if (iState == 500)
                { // we have arrived at target
                    /*
                     * // check for more nav commands
                     * if(wicoNavCommands.Count>0)
                     * {
                     *  wicoNavCommands.RemoveAt(0);
                     * }
                     * if(wicoNavCommands.Count>0)
                     * {
                     *  // another command
                     *  wicoNavCommandProcessNext();
                     * }
                     * else
                     */
                    {
//                        StatusLog("clear", sledReport);
//                        StatusLog("Arrived at Target", sledReport);
//                        StatusLog("Arrived at Target", textPanelReport);
                        sNavDebug += " ARRIVED!";

                        ResetMotion();
                        bValidNavTarget = false; // we used this one up.
                                                 //                float range = RangeToNearestBase() + 100f + (float)velocityShip * 5f;
                        thisProgram.wicoAntennas.SetMaxPower(false);
                        thisProgram.wicoSensors.SensorsSleepAll();
                        //                    sStartupError += "Finish WP:" + wicoNavCommands.Count.ToString()+":"+NAVArrivalMode.ToString();
                        // set to desired mode and state
                        thisProgram.wicoControl.SetMode(NAVArrivalMode);// setMode(NAVArrivalMode);
                        iState = NAVArrivalState;

                        // set up defaults for next run (in case they had been changed)
                        NAVArrivalMode  = WicoControl.MODE_ARRIVEDTARGET;
                        NAVArrivalState = 0;
                        NAVTargetName   = "";
                        bGoOption       = true;

                        //                setMode(MODE_ARRIVEDTARGET);
                        if (NAVEmulateOld)
                        {
                            var tList = GetBlocksContains <IMyTerminalBlock>("NAV:");
                            for (int i1 = 0; i1 < tList.Count(); i1++)
                            {
                                // don't want to get blocks that have "NAV:" in customdata..
                                if (tList[i1].CustomName.StartsWith("NAV:"))
                                {
                                    thisProgram.Echo("Found NAV: command:");
                                    tList[i1].CustomName = "NAV: C Arrived Target";
                                }
                            }
                        }
                    }
                    thisProgram.wicoControl.WantFast();// bWantFast = true;
//                    doTriggerMain();
                }
//                NavDebug(sNavDebug);
            }
Ejemplo n.º 30
0
        public void LcdWriter()
        {
            if (ticks % 31 == 0)
            {
                lcdCounter++;
            }
            if (lcdCounter > 6)
            {
                lcdCounter = 0;
            }

            /*===========|  LCD's  |===========*/
            if (sensor.Main())
            {
                lcd.SetDirection(LCD_CLOSESTPERSON, " " + sensor.DistanceToClosest.ToString(), sensor.GetVector2());

                if (MISCINFO)
                {
                    //misc entity info
                    MyDetectedEntityInfo temp = sensor.closest;
                    var sb = new StringBuilder();
                    if (SCROLLING)
                    {
                        sb.AppendLine("Closest info:");
                        sb.AppendLine("Name: " + temp.Name);
                        sb.AppendLine("Speed: " + Math.Round(temp.Velocity.Length() * 2.23693629, 2) + " mph");
                        sb.AppendLine("Size: " + Math.Round(temp.BoundingBox.Size.Length() * 3.2808399, 2) + "ft");
                    }
                    else if (NOSCROLL)
                    {
                        sb.AppendLine("Closest info:");
                        sb.AppendLine("Name: " + temp.Name);
                        sb.AppendLine("Speed: " + Math.Round(temp.Velocity.Length() * 3.6, 2) + " km/h");
                        sb.AppendLine("Size: " + Math.Round(temp.BoundingBox.Size.Length(), 2) + "m");
                    }
                    else
                    {
                        sb.AppendLine("Closest info:");
                        sb.AppendLine("Name: " + temp.Name);
                        sb.AppendLine("Speed: " + Math.Round(temp.Velocity.Length(), 2) + " m/s");
                        sb.AppendLine("Size: " + Math.Round(temp.BoundingBox.Size.Length(), 2) + "m");
                    }


                    lcd.WriteTo(LCD_MISCINFO, sb.ToString());
                }
            }

            if (!MISCINFO)
            {
                var sb = new StringBuilder();
                sb.AppendLine("Craft info:");
                if (SCROLLING)
                {
                    if (lcdCounter == 0)
                    {
                        sb.AppendLine("Friction: " + Math.Round(wheel.GetCurrentFriction()).ToString() + "%");
                    }
                    if (lcdCounter == 1)
                    {
                        sb.AppendLine("Downforce: " + Math.Round(downforce.GetDownForcePercent(), 2).ToString() + "%");
                    }
                    if (lcdCounter == 2)
                    {
                        sb.AppendLine("Stopwatch:");
                    }
                    if (lcdCounter == 3)
                    {
                        sb.AppendLine("Time: " + stopwatch.GetTime() + "s");
                    }
                    if (lcdCounter == 4)
                    {
                        sb.AppendLine("Avg speed: " + Math.Round(stopwatch.GetSpeedAvg() * 3.6, 1) + "km/h");
                    }
                    if (lcdCounter == 5)
                    {
                        sb.AppendLine("Travelled distance: " + Math.Round(stopwatch.GetDistance() / 1000.0, 3) + "km");
                    }
                }
                else if (NOSCROLL)
                {
                    sb.AppendLine("Craft info:");
                    sb.AppendLine("Friction: " + Math.Round(wheel.GetCurrentFriction()).ToString() + "%");
                    sb.AppendLine("Downforce: " + Math.Round(downforce.GetDownForcePercent(), 2).ToString() + "%");
                    sb.AppendLine("Stopwatch:");
                    sb.AppendLine("Time: " + stopwatch.GetTime() + "s");
                    sb.AppendLine("Avg speed: " + Math.Round(stopwatch.GetSpeedAvg() * 3.6, 1) + "km/h");
                    sb.AppendLine("Travelled distance: " + Math.Round(stopwatch.GetDistance() / 1000.0, 3) + "km");
                }
                else
                {
                    sb.AppendLine("Craft info:");
                    sb.AppendLine("Friction: " + Math.Round(wheel.GetCurrentFriction()).ToString() + "%");
                    sb.AppendLine("Downforce: " + Math.Round(downforce.GetDownForcePercent(), 2).ToString() + "%");
                    sb.AppendLine("Stopwatch");
                    sb.AppendLine("Time: " + stopwatch.GetTime() + "s");
                    sb.AppendLine("Avg speed: " + Math.Round(stopwatch.GetSpeedAvg(), 2) + "m/s");
                    sb.AppendLine("Travelled distance: " + stopwatch.GetDistance() + "m");
                }

                if (lcdCounter == 6 || NOSCROLL)
                {
                    sb.AppendLine("SnowMode: " + wheel.snowMode.ToString());
                }

                lcd.WriteTo(LCD_MISCINFO, sb.ToString());
            }


            lcd.WriteTo(LCD_SPEDOMETER, Math.Round(rc.GetShipSpeed() * 3.6, 2).ToString() + "\nkm/h");
        }