예제 #1
0
        void InitializeOrbit()
        {
            if (!lastEnemy.HasValue)
            {
                return;
            }

            v1     = rc.GetPosition() - lastEnemy.Value.Position;
            radius = MathHelper.Clamp(v1.Length(), minRadius, maxRadius);
            v1.Normalize();

            if (!useGravity)
            {
                Vector3D temp = RandomVector();
                v2 = v1.Cross(temp);
            }
            else
            {
                Vector3D gravity = rc.GetNaturalGravity();
                gravity.Normalize();
                Vector3D temp = gravity.Dot(v1) * gravity;
                v1 -= temp;
                v2  = v1.Cross(gravity);
            }


            v2.Normalize();

            theta = 0;

            double angularVelocity = orbitVelocity / radius;

            orbitStep = angularVelocity * (1f / 60);
        }
예제 #2
0
파일: Test.cs 프로젝트: BlackFIlms/LearnCS
    public void Main()
    {
        //Получаем и нормализуем вектор гравитации. Это наше направление "вниз" на планете.
        Vector3D GravityVector = RemCon.GetNaturalGravity();
        Vector3D GravNorm      = Vector3D.Normalize(GravityVector);

        //Получаем проекции вектора прицеливания на все три оси блока ДУ.
        double gF = GravNorm.Dot(RemCon.WorldMatrix.Forward);
        double gL = GravNorm.Dot(RemCon.WorldMatrix.Left);
        double gU = GravNorm.Dot(RemCon.WorldMatrix.Up);

        //Получаем сигналы по тангажу и крены операцией atan2
        float RollInput  = (float)Math.Atan2(gL, -gU);
        float PitchInput = -(float)Math.Atan2(gF, -gU);

        //На рыскание просто отправляем сигнал рыскания с контроллера. Им мы будем управлять вручную.
        float YawInput = RemCon.RotationIndicator.Y;

        //для каждого гироскопа устанавливаем текущие значения по тангажу, крену, рысканию.
        foreach (IMyGyro gyro in gyroList)
        {
            gyro.GyroOverride = true;
            gyro.Yaw          = YawInput;
            gyro.Roll         = RollInput;
            gyro.Pitch        = PitchInput;
        }
    }
        ///
        /// обновляем вектор гравитации с учетом массы корабля
        ///
        private void updateWeightVector()
        {
            Vector3D gravityVector = remoteControl.GetNaturalGravity();
            float    shipMass      = remoteControl.CalculateShipMass().PhysicalMass;

            Vector3D.Multiply(ref gravityVector, shipMass, out weightVector);
        }
예제 #4
0
        //конструктор

        public Program()
        {
            RemCon = GridTerminalSystem.GetBlockWithName("RemCon") as IMyRemoteControl;
            Gyros  = new List <IMyGyro>();
            GridTerminalSystem.GetBlocksOfType <IMyGyro>(Gyros);
            Runtime.UpdateFrequency = UpdateFrequency.Update1;
            Forward = RemCon.WorldMatrix.Forward;
            Forward = Vector3D.Reject(Forward, Vector3D.Normalize(RemCon.GetNaturalGravity()));
        }
예제 #5
0
 public bool getGravity(out Vector3D gravity)
 {
     gravity = Vector3D.Zero;
     if (_init())
     {
         return(true);
     }
     gravity = rc.GetNaturalGravity();
     return(false);
 }
예제 #6
0
        void Main(string argument)
        {
            if (rc == null)
            {
                setup();
            }

            //Get orientation from rc
            Matrix or;

            rc.Orientation.GetMatrix(out or);
            Vector3D down = or.Down;

            Vector3D grav = rc.GetNaturalGravity();

            grav.Normalize();

            for (int i = 0; i < gyros.Count; ++i)
            {
                var g = gyros[i];

                g.Orientation.GetMatrix(out or);
                var localDown = Vector3D.Transform(down, MatrixD.Transpose(or));

                var localGrav = Vector3D.Transform(grav, MatrixD.Transpose(g.WorldMatrix.GetOrientation()));

                //Since the gyro ui lies, we are not trying to control yaw,pitch,roll but rather we
                //need a rotation vector (axis around which to rotate)
                var    rot = Vector3D.Cross(localDown, localGrav);
                double ang = rot.Length();
                ang = Math.Atan2(ang, Math.Sqrt(Math.Max(0.0, 1.0 - ang * ang))); //More numerically stable than: ang=Math.Asin(ang)

                if (ang < 0.01)
                {   //Close enough
                    //Echo("Level");
                    g.SetValueBool("Override", false);
                    continue;
                }
                //Echo("Off level: "+(ang*180.0/3.14).ToString()+"deg");

                //Control speed to be proportional to distance (angle) we have left
                double ctrl_vel = g.GetMaximum <float>("Yaw") * (ang / Math.PI) * CTRL_COEFF;
                ctrl_vel = Math.Min(g.GetMaximum <float>("Yaw"), ctrl_vel);
                ctrl_vel = Math.Max(0.01, ctrl_vel); //Gyros don't work well at very low speeds
                rot.Normalize();
                rot *= ctrl_vel;
                g.SetValueFloat("Pitch", (float)rot.GetDim(0));
                g.SetValueFloat("Yaw", -(float)rot.GetDim(1));
                g.SetValueFloat("Roll", -(float)rot.GetDim(2));

                g.SetValueFloat("Power", 1.0f);
                g.SetValueBool("Override", true);
            }
        }
예제 #7
0
 Vector3D _gravity()
 {
     if (_initRc())
     {
         return(new Vector3D());
     }
     else
     {
         return(rc.GetNaturalGravity());
     }
 }
예제 #8
0
            public void OnFlightUpdateFrame()
            {
                if (is_enabled)
                {
                    desired   = Vector3D.Zero;
                    velocity  = control.GetShipVelocities().LinearVelocity;
                    gravity   = control.GetNaturalGravity();
                    ship_mass = control.CalculateShipMass();
                    effective_breaking_distance = Settings.ARRIVAL_DIST * (ship_mass.TotalMass / ship_mass.BaseMass);

                    tasks.OnUpdateFrame();

                    if ((flags & SpaceshipFlags.CAS) == SpaceshipFlags.CAS)
                    {
                        cas.OnUpdateFrame();
                    }
                    if ((flags & SpaceshipFlags.FD) == SpaceshipFlags.FD)
                    {
                        fd.OnUpdateFrame();
                    }

                    Vector3DLimit(ref desired, Settings.MAX_SPEED);

                    if ((flags & SpaceshipFlags.AP) == SpaceshipFlags.AP)
                    {
                        autopilot.OnUpdateFrame();
                    }

                    if ((flags & SpaceshipFlags.TM) == SpaceshipFlags.TM)
                    {
                        thrusters.OnUpdateFrame();
                    }
                    else
                    {
                        thrusters.Disable();
                    }

                    CheckConnector();
                    if (fd.prev == fd.next)
                    {
                        fd.SetFlightPlan(null);
                    }
                }
            }
예제 #9
0
        // методы

        public void Main()
        {
            // получим уклон по осям вперед/назад и влево-вправо
            Vector3D GravVector = Vector3D.Normalize(RemCon.GetNaturalGravity());

            GravVector = Vector3D.Reject(GravVector, RemCon.WorldMatrix.Down);
            float Pitch = (float)GravVector.Dot(RemCon.WorldMatrix.Backward);
            float Roll  = (float)GravVector.Dot(RemCon.WorldMatrix.Left);
            float Yaw   = (float)Forward.Dot(Vector3D.Reject(RemCon.WorldMatrix.Forward, Vector3D.Normalize(RemCon.GetNaturalGravity())));

            // For debug only
            // Echo("Pitch: " + Pitch + "\n Roll: " + Roll + "\n Yaw: " + Yaw);

            foreach (IMyGyro Gyro in Gyros)
            {
                Gyro.Pitch = Pitch * GyroMult;
                Gyro.Roll  = Roll * GyroMult;
                Gyro.Yaw   = Yaw * GyroMult;
            }
        }
예제 #10
0
        void level()
        {
            Runtime.UpdateFrequency = UpdateFrequency.Update10;
            //Get orientation from remoteControl
            Matrix orientation;

            remoteControl.Orientation.GetMatrix(out orientation);
            Vector3D down = orientation.Down;
            Vector3D grav = remoteControl.GetNaturalGravity();

            grav.Normalize();
            running = true;

            for (int i = 0; i < gyroList.Count; ++i)
            {
                var g = gyroList[i];

                g.Orientation.GetMatrix(out orientation);
                var localDown = Vector3D.Transform(down, MatrixD.Transpose(orientation));

                var localGrav = Vector3D.Transform(grav, MatrixD.Transpose(g.WorldMatrix.GetOrientation()));

                var rot = Vector3D.Cross(localDown, localGrav);
                ang = rot.Length();
                ang = Math.Atan2(ang, Math.Sqrt(Math.Max(0.0, 1.0 - ang * ang)));
                double ctrl_vel = g.GetMaximum <float>("Yaw") * (ang / Math.PI) * CTRL_COEFF;

                ctrl_vel = Math.Min(g.GetMaximum <float>("Yaw"), ctrl_vel);
                ctrl_vel = Math.Max(0.01, ctrl_vel); //Gyros don't work well at very low speeds
                rot.Normalize();
                rot *= ctrl_vel;
                g.SetValueFloat("Pitch", (float)rot.GetDim(0));
                g.SetValueFloat("Yaw", -(float)rot.GetDim(1));
                g.SetValueFloat("Roll", -(float)rot.GetDim(2));

                g.SetValueFloat("Power", 1.0f);
                g.SetValueBool("Override", true);
            }
        }
예제 #11
0
        public void Main(string argument, UpdateType updateSource)//main is called once per pysics update, ideally 60Hz
        {
            if (argument.ToLower() == "reset")
            {
                stage = 0;
            }
            bool valid = controller.TryGetPlanetElevation(MyPlanetElevation.Surface, out currentAltitude);

            var parts = Storage.Split(';');

            stage = int.Parse(parts[0]);

            maxTotalEffectiveThrust = 0.0f;//have to recalculate every time because it increases with alt
            foreach (var thruster in thrusters)
            {
                maxTotalEffectiveThrust += thruster.MaxEffectiveThrust;
            }
            physicalMass          = controller.CalculateShipMass().PhysicalMass;
            currentNaturalGravity = controller.GetNaturalGravity();   //
            double gravityMagnitude = currentNaturalGravity.Length(); //what a weird thing to call magnitude of a vector

            Echo($"STAGE: {stage}\nSPEED: {controller.GetShipVelocities().LinearVelocity.Length()}\nALT: {currentAltitude}");
            antenna.HudText = stage.ToString();

            if (stage == 0)
            {
                if (Freefall()) //if we are in freefall. Freefall is defined as accelerating at a rate ~= gravity, this implies thrusters are not acive. Also should check if it's heading towards or away from the gravity well. Linear alg time yay
                {
                    foreach (var thruster in thrusters)
                    {
                        thruster.ThrustOverride = 0;
                    }
                    stage++;
                    Storage = stage + ";";
                }
            }

            else if (stage == 1)
            {
                if (!Freefall())
                {
                    stage = 0;
                }
                double a = maxTotalEffectiveThrust / physicalMass - currentNaturalGravity.Length(); //acceleration with full retro burn
                double b = -controller.GetShipVelocities().LinearVelocity.Length();                 //velocity
                double c = currentAltitude;
                double thrustStopTime = -b / (2 * a);                                               //y=ax^2+bx ->  dy = 2ax+b | 0 = 2*a*x+b -> -b/2a=x

                Func <double, double> altitudeFunc = delegate(double x) {                           //x=time, y=altitude assuming full retro thrust
                    return(a * x * x + b * x + c);
                };

                double minHeight = altitudeFunc(thrustStopTime);                  //the lowest point of the trajectory IF thrust is engaged instantly
                double calculatedStoppingDistance = currentAltitude - minHeight;
                double safetyBuffer           = Math.Abs(b) * 1.25 + craftHeight; //a coefficient in front of the safety buffer feels wrong
                double safetyStoppingDistance = calculatedStoppingDistance + safetyBuffer;

                if (!controller.DampenersOverride && currentAltitude <= safetyStoppingDistance)
                {
                    stage++;
                    Storage = stage + ";";
                    controller.DampenersOverride = true;
                }
            }

            else if (stage == 2)//descent burn has been initiated, goto stg 3 when a safe speed has been reached
            {
                antenna.HudText = stage.ToString();

                if (controller.GetShipVelocities().LinearVelocity.Length() < safeVelocity)
                {
                    stage++;
                    Storage = stage + ";";
                }
            }

            else if (stage == 3)//target safe descent speed has been reached, maintain low speed until touchdown to planet
            {
                float totalThrustNeededToHover = physicalMass * (float)currentNaturalGravity.Length();
                float idealThrustPerThruster   = (float)totalThrustNeededToHover / (float)numThrusters;
                float thrustRatio = thrusters[0].MaxThrust / thrusters[0].MaxEffectiveThrust;//actual output of thrust is similar to but different from the input set by code/user.
                float adjustedThrustPerThruster = idealThrustPerThruster * thrustRatio;

                foreach (var thruster in thrusters)
                {
                    thruster.ThrustOverride = adjustedThrustPerThruster;
                }

                if (currentAltitude < touchdownHeight)
                {
                    stage++;
                    Storage = stage + ";";

                    foreach (var thruster in thrusters)
                    {
                        controller.DampenersOverride = false;
                        thruster.ThrustOverride      = 0.0f;
                    }
                }
            }

            else if (stage == 4)//touchdown, turn stuff off pls
            {
                antenna.HudText = stage.ToString();
                Echo($"TOUCHDOWN");
                stage   = 0;
                Storage = stage + ";";
                Runtime.UpdateFrequency = UpdateFrequency.None;//stop running the script
            }
            lastVelocities = controller.GetShipVelocities();
        }
예제 #12
0
            public void Update(MyDetectedEntityInfo target, Vector3D T, Vector3D PointerPos, Vector3D PointerDir)
            {
                if (!Launched)
                {
                    foreach (IMyThrust thr in thrusters)
                    {
                        thr.Enabled = true;
                        thr.ThrustOverridePercentage = 1;
                    }
                    Launched = true;
                }
                else
                {
                    counter++;
                    if (remcon.IsFunctional && (counter > VerticalDelay))
                    {
                        double   currentVelocity = remcon.GetShipVelocities().LinearVelocity.Length();
                        Vector3D targetvector    = new Vector3D();
                        if (LASER_GUIDED)
                        {
                            targetvector = ((remcon.GetPosition() - PointerPos).Dot(PointerDir) + 700) * PointerDir + PointerPos - remcon.GetPosition();
                        }
                        else
                        {
                            targetvector = FindInterceptVector(remcon.GetPosition(),
                                                               currentVelocity * INTERCEPT_COURSE,
                                                               T,
                                                               target.Velocity);
                        }

                        Vector3D trgNorm = Vector3D.Normalize(targetvector);

                        if ((target.Position - remcon.GetPosition()).Length() < WH_ARM_DIST)
                        {
                            if (currentVelocity - MyVelocity < -ACCEL_DET)
                            {
                                foreach (IMyWarhead wh in warheads)
                                {
                                    wh.Detonate();
                                }
                            }

                            MyVelocity = currentVelocity;
                        }

                        Vector3D velNorm          = Vector3D.Normalize(remcon.GetShipVelocities().LinearVelocity);
                        Vector3D CorrectionVector = Math.Max(ReflectK * trgNorm.Dot(velNorm), 1) * trgNorm - velNorm;
                        Vector3D G = remcon.GetNaturalGravity();

                        if (G.LengthSquared() == 0)
                        {
                            CorrectionVector = Math.Max(ReflectK * trgNorm.Dot(velNorm), 1) * trgNorm - velNorm;
                        }
                        else
                        {
                            if (JAVELIN)
                            {
                                //trgNorm = Vector3D.Normalize(Vector3D.Reflect(-G, trgNorm));
                                trgNorm = Vector3D.Normalize(G.Dot(trgNorm) * trgNorm * JAVELIN_CURVE - G);
                            }
                            CorrectionVector = Math.Max(ReflectK * trgNorm.Dot(velNorm), 1) * trgNorm - velNorm;
                            double A = 0;
                            foreach (IMyThrust thr in thrusters)
                            {
                                A += thr.MaxEffectiveThrust;
                            }
                            A /= remcon.CalculateShipMass().PhysicalMass;

                            Vector3D CorrectionNorm = Vector3D.Normalize(CorrectionVector);
                            //CorrectionVector = CorrectionNorm * A - G;
                            Vector3D gr = Vector3D.Reject(remcon.GetNaturalGravity(), CorrectionNorm);
                            CorrectionVector = CorrectionNorm * Math.Sqrt(A * A + gr.LengthSquared()) - gr;
                        }


                        Vector3D Axis = Vector3D.Normalize(CorrectionVector).Cross(remcon.WorldMatrix.Forward);
                        if (Axis.LengthSquared() < 0.1)
                        {
                            Axis += remcon.WorldMatrix.Backward * ROLL;
                        }
                        Axis *= GyroMult;
                        foreach (IMyGyro gyro in gyros)
                        {
                            gyro.Pitch = (float)Axis.Dot(gyro.WorldMatrix.Right);
                            gyro.Yaw   = (float)Axis.Dot(gyro.WorldMatrix.Up);
                            gyro.Roll  = (float)Axis.Dot(gyro.WorldMatrix.Backward);
                        }
                    }
                    else
                    {
                        foreach (IMyGyro gyro in gyros)
                        {
                            gyro.Pitch = 0;
                            gyro.Yaw   = 0;
                            gyro.Roll  = 0;
                        }
                    }
                }
            }
예제 #13
0
        void GuideMissile()
        {
            missilePos = shipReference.GetPosition();

            //---Get orientation vectors of our missile
            Vector3D missileFrontVec = shipReference.WorldMatrix.Forward;
            Vector3D missileLeftVec  = shipReference.WorldMatrix.Left;
            Vector3D missileUpVec    = shipReference.WorldMatrix.Up;

            //---Check if we have gravity
            double rollAngle = 0; double rollSpeed = 0;

            var remote = remotes[0] as IMyRemoteControl;

            gravVec = shipReference.GetNaturalGravity();
            double gravMagSquared = gravVec.LengthSquared();

            if (gravMagSquared != 0)
            {
                if (gravVec.Dot(missileUpVec) < 0)
                {
                    //	rollAngle = Math.PI / 2 - Math.Acos(MathHelper.Clamp(gravVec.Dot(missileLeftVec) / gravVec.Length(), -1, 1));
                }
                else
                {
                    //	rollAngle = Math.PI + Math.Acos(MathHelper.Clamp(gravVec.Dot(missileLeftVec) / gravVec.Length(), -1, 1));
                }
            }
            else
            {
                rollSpeed = 0;
            }


            //---Get travel vector
            var    missileVelocityVec = shipReference.GetShipVelocities().LinearVelocity;
            double speed = shipReference.GetShipSpeed();

            //---Find vector from missile to destinationVec
            Vector3D missileToTargetVec;

            if (speed > 10 ||)
            {
                missileToTargetVec = Vector3D.Negate(missileVelocityVec);
            }
            else
            {
                shipReference.TryGetPlanetPosition(out targetPos);
                missileToTargetVec = Vector3D.Negate(targetPos - missilePos);                // targetPos - missilePos;
            }

            //---Calc our new heading based upon our travel vector

            var headingVec = CalculateHeadingVector(missileToTargetVec, missileVelocityVec, driftCompensation);

            //---Get pitch and yaw angles
            double yawAngle; double pitchAngle;

            GetRotationAngles(headingVec, missileFrontVec, missileLeftVec, missileUpVec, out yawAngle, out pitchAngle);

            logger.Info("mttv: " + missileToTargetVec);
            logger.Info("mvv: " + missileVelocityVec);
            logger.Info("hv: " + headingVec);
            if (firstGuidance)
            {
                lastPitchAngle = pitchAngle;
                lastYawAngle   = yawAngle;
                firstGuidance  = false;
            }

            //---Angle controller
            logger.Debug(yawAngle + "|" + lastYawAngle);
            double yawSpeed   = Math.Round(proportionalConstant * yawAngle + derivativeConstant * (yawAngle - lastYawAngle) * 60, 3);
            double pitchSpeed = Math.Round(proportionalConstant * pitchAngle + derivativeConstant * (pitchAngle - lastPitchAngle) * 60, 3);

            //---Set appropriate gyro override
            if (speed <= 1E-2)
            {
                logger.Info("Fin");
                ApplyGyroOverride(0, 0, 0, gyros, shipReference);
                Runtime.UpdateFrequency = UpdateFrequency.None;
            }
            else
            {
                logger.Info("V=" + missileVelocityVec.Length());
                ApplyGyroOverride(pitchSpeed, yawSpeed, rollSpeed, gyros, shipReference);
            }

            //---Store previous values
            lastYawAngle   = yawAngle;
            lastPitchAngle = pitchAngle;
            lastRollAngle  = rollAngle;
        }
예제 #14
0
            private bool EvaluateCondition()
            {
                switch (currentCondition)
                {
                case Conditions.NONE:
                    return(true);

                case Conditions.PGRA:
                    double currentPGravity = control.GetNaturalGravity().Length();
                    switch (currentOperator)
                    {
                    case Operators.EQUAL:
                        return(currentPGravity == value);

                    case Operators.LESS:
                        return(currentPGravity < value);

                    case Operators.MORE:
                        return(currentPGravity > value);
                    }
                    break;

                case Conditions.AGRA:
                    double currentAGravity = control.GetArtificialGravity().Length();
                    switch (currentOperator)
                    {
                    case Operators.EQUAL:
                        return(currentAGravity == value);

                    case Operators.LESS:
                        return(currentAGravity < value);

                    case Operators.MORE:
                        return(currentAGravity > value);
                    }
                    break;

                case Conditions.SPEED:
                    double currentSpeed = control.GetShipSpeed();
                    switch (currentOperator)
                    {
                    case Operators.EQUAL:
                        return(currentSpeed == value);

                    case Operators.LESS:
                        return(currentSpeed < value);

                    case Operators.MORE:
                        return(currentSpeed > value);
                    }
                    break;

                case Conditions.TIME:
                    if (time == -1)
                    {
                        time = DateTime.Now.Millisecond;
                    }
                    if (DateTime.Now.Millisecond - time > value * 1000)
                    {
                        time = -1;
                        return(true);
                    }
                    return(false);

                case Conditions.LOCATION:
                    BoundingSphereD boundaries = control.CubeGrid.WorldVolume;
                    return(boundaries.Contains(conditionGPS) != ContainmentType.Disjoint);
                }
                return(false);
            }