Ejemplo n.º 1
0
        private void GoStraight(float Y, float targetHeading)
        {
            if (_enableCompensating == false)
            {
                /* calling app has turned this off */
                _isCompensating = false;
            }
            else if (_pidgey.GetState() != PigeonImu.PigeonState.Ready)
            {
                /* pigeon is not present on bus */
                _isCompensating = false;
            }
            else
            {
                /* feature enabled and pigeon is present, we are good to go */
                _isCompensating = true;
            }

            /* if we can compensate do it, otherwise just apply same output on both sides */
            float x_correction;

            if (_isCompensating == false)
            {
                /* apply same to both sides */
                x_correction = 0;
            }
            else
            {
                /* let user know if they have more work to do */
                if (_servoParams.P == 0 && _servoParams.I == 0 && _servoParams.D == 0)
                {
                    Debug.Print("CTR: Servo Go Straight With Imu has no PID values, cannot go straight");
                }

                /* Grab current heading */
                float currentHeading = GetImuHeading();

                /* Grab angular rate from the pigeon */
                _pidgey.GetRawGyro(XYZ_Dps);
                float currentAngularRate = XYZ_Dps[2];

                /* Heading PID */
                float headingError = targetHeading - currentHeading;
                float X            = (headingError) * _servoParams.P - (currentAngularRate) * _servoParams.D;
                X            = Util.Cap(X, _maxOutput);
                x_correction = -X;
            }

            /* Select control mode based on selected style */
            _driveTrain.Set(_selectedStyle, Y, x_correction);
        }
        /** Singleton instance and entry into while loop that runs the desired program*/
        public static void Main()
        {
            /* Tracking gamepad buttons states for single press captures*/
            bool LastBtn1 = false;
            bool LastBtn2 = false;
            bool LastBtn3 = false;
            bool LastBtn5 = false;
            bool LastBtn6 = false;

            /* Forword/Backward Scalor */
            const float kScalarX = 0.50f;
            /* Left/Right Scalor */
            const float kScalarY = 0.50f;
            /* Turning Scalor */
            const float kScalarTwist = 0.30f;
            /* Ramp Rate */
            const float kVoltageRampSec = 0.2f;

            /* Gains for PixyDrive (May have to play with this for a better PixyDrive experience)*/
            float KpGain = 0.002f;                  /*P-Gain for Turning*/
            float KdGain = 0.001f;                  /*D-Gain for Turning*/
            float kTurnCorrectionRatio = 0.3f;      /*Ratio for turning speed*/
            float KpGain1 = 0.0003f;                /*P-Gain for driving*/
            float KdGain1 = 0.0f;                   /*D-Gain for driving*/
            float kForwardCorrectionRatio = 0.6f;   /*Ratio for driving speed*/

            /* Configure Talons to operate in percentage VBus mode, and Ramp Up Voltage*/
            foreach (CTRE.TalonSrx temp in Talons)
            {
                temp.SetControlMode(TalonSrx.ControlMode.kPercentVbus);
                temp.SetVoltageRampRate(12.0f / kVoltageRampSec);
            }

            /* Initiate the program by starting off in Manaul Drive mode */
            CurrentState = States.ManualDrive;

            /* Variables to hold target position and distance of object, set when PixyDrive is initialized */
            int TargetX    = 160;
            int TargetArea = 0;

            /* Number of values to use when averaging data from Block, Set to 1 to remove average */
            int AvgCount = 3;
            /* Tracks the Distance between the PixyCamera and the Object using the pervious Area used in PD Loop */
            int LastErrorArea = 0;
            /* Value used to cycle between 3 colors of the LED on the PixyCamera */
            byte RGB = 0;

            while (true)
            {
                /* Keep robot enabled if gamepad is connected and in 'D' mode */
                if (GamePad.GetConnectionStatus() == CTRE.UsbDeviceConnection.Connected)
                {
                    CTRE.Watchdog.Feed();
                }

                /* Clear the average of X, Y, and Area */
                int AverageX    = 0;
                int AverageY    = 0;
                int AverageArea = 0;
                /* Adds up the pervious values of X, Y, and Area */
                for (int i = 0; i < AvgCount; i++)
                {
                    /* Run Pixy process to check for Data, pull Block if there is data */
                    Thread.Sleep(5);
                    Pixy.Process();
                    if (Pixy.GetBlock(blockToFill))
                    {
                        /* Store block from Pixy into Local Block */
                        CurrentBlock = blockToFill;
                        /* Uncomment for block data */
                        Debug.Print("===================================");
                        Debug.Print(blockToFill.ToString());
                    }
                    ///* Pull Block data into variables */
                    AverageX    += CurrentBlock.X;      /* Pull X from CurrentBlock */
                    AverageY    += CurrentBlock.Y;      /* Pull Y from CurrentBlock */
                    AverageArea += CurrentBlock.Area;   /* Pull Area from CurrentBlock */
                }
                /* Finishes the average process by dividing the sum by the number of values */
                AverageX    /= AvgCount;
                AverageY    /= AvgCount;
                AverageArea /= AvgCount;

                /* Sync Status of Pixy */
                bool Synced = Pixy.Status.Synced;
                /* Duration since last time Pixy had a good data in ms */
                long TimeSinceLastBlock = Pixy.Status.TimeSinceLastBlock;
                /* Uncomment for Pixy status information */
                //Debug.Print("===================================");
                //Debug.Print(Pixy.Status.ToString());

                /* Get angular rate of the robot from Pigeon IMU */
                float[] XYZ_Dps = new float[3];
                Pidgeot.GetRawGyro(XYZ_Dps);
                float CurrentAngularRate = XYZ_Dps[2];

                /* Allows for increasing or decreasing the distance between PixyCamera and the target object
                 * Button 5 (Left-bumper) decreases the range
                 * Button 6 (Right-bumper) increases the range */
                bool Btn5 = GamePad.GetButton(5);
                bool Btn6 = GamePad.GetButton(6);
                if (Btn5 && !LastBtn5)
                {
                    if (TargetArea < (TargetArea + 350))    /* Minimum Distance found through play */
                    {
                        TargetArea += 50;                   /* Step closer to object */
                    }
                    /* Else, the object is too close to PixyCam */
                }
                if (Btn6 & !LastBtn6)
                {
                    if (TargetArea > (TargetArea - 350))    /* Maximum Distance found through play */
                    {
                        TargetArea -= 50;                   /* Step further from object */
                    }
                    /* Else, the object is too far from PixyCam */
                }

                /* Control the LED on the Pixy Camera
                 * Button 2 (A) Cycles the color of the LED between Red, Green, and Blue */
                bool Btn2 = GamePad.GetButton(2);
                if (Btn2 && !LastBtn2)
                {
                    /* Cycle between 3 values by incrementing and wrapping around */
                    if (RGB == 2)
                    {
                        RGB = 0;
                    }
                    else
                    {
                        RGB++;
                    }

                    /* Set the states of the color based on RGB value
                     * Colors can be modified by doing different combinations of 0 and 255 */
                    if (RGB == 0)
                    {
                        Pixy.SetLED(true, false, false);
                    }
                    else if (RGB == 1)
                    {
                        Pixy.SetLED(false, true, false);
                    }
                    else if (RGB == 2)
                    {
                        Pixy.SetLED(false, false, true);
                    }
                }
                LastBtn2 = Btn2;

                /* Always give user the ability to enter Manaul Drive mode
                 * Button 1 (X) changes the PixyDrive State to Manual Drive State */
                bool Btn1 = GamePad.GetButton(1);
                if (Btn1 && !LastBtn1)
                {
                    CurrentState = States.ManualDrive;
                }
                LastBtn1 = Btn1;

                /* State machine that determines if Pixy Target needs to be initiated, Pixy object is in target of Pixy Camera parameters, or
                 * robot is in Manual Drive mode */
                switch (CurrentState)
                {
                case States.Init:
                    /* Grab Inital area and X-position, and set as target values */
                    TargetX      = AverageX;
                    TargetArea   = AverageArea;
                    CurrentState = States.PixyDrive;
                    break;

                case States.PixyDrive:
                    /* Bulk of the PixyDrive, where it uses the current Pixy data to allign with the TargetArea and TargetX */
                    if (Synced == true && TimeSinceLastBlock < 50)      /* Time since last block should be around 50 ms */
                    {
                        /* Object is in View of camera and we getting good data */

                        /* Find the Error between the desired values between the the current values of Area and X */
                        int ErrorX    = TargetX - AverageX;
                        int ErrorArea = TargetArea - AverageArea;
                        /* Variable used later on to smooth out PD of Drive */
                        int ErrorArea_Kd1 = ErrorArea - LastErrorArea;
                        /* Track the last error value and compared to next error value */
                        LastErrorArea = ErrorArea;

                        /* Checks to see if the error is within an allowable margin,
                         * ErrorX is good in the sense that there is minimal noise on X and Y
                         * Error Area can be tweeked according to application as larger objects will have more noise and smallear objects have
                         * less noise and will require more preciseness for better response */
                        if ((ErrorX < 3 && ErrorX > -3) && (ErrorArea < 20 && ErrorArea > -20))
                        {
                            /* Consisered centerd and a good distance away so stop */
                            TankDrive(0, 0);
                        }
                        else
                        {
                            /* There is error with either X or Area, so fix that */
                            bool xOutOfBounds = OutOfBoundsX(AverageX, CurrentBlock.Width);
                            /* If object is out bounds, kill the forward and backward drive, turn right or left to still follow */
                            if (xOutOfBounds)
                            {
                                /* Set ErrorArea to 0 to prevent forward/backward drive in PixyDrive */
                                ErrorArea     = 0;
                                ErrorArea_Kd1 = 0;
                            }

                            /* PD Loop for PixyDrive until centered
                             * Turning uses ErrorX for P and CurrentAngularRate for D
                             * Forward/Backward uses ErrorArea for P and ErrorArea_Kd1 (ErrorArea - LastErrorArea) for D */
                            float Turn    = (ErrorX) * KpGain - (CurrentAngularRate) * KdGain;
                            float Forward = (ErrorArea) * KpGain1 + (ErrorArea_Kd1) * KdGain1;
                            /* Cap the return values to turn down the output of the motors */
                            Turn    = Cap(Turn, kTurnCorrectionRatio);
                            Forward = Cap(Forward, kForwardCorrectionRatio);

                            /* With the turn and forward values found, feed that to the TankDrive accordingly */
                            float LeftAuto  = ((-Turn + Forward));
                            float RightAuto = ((Turn + Forward));
                            TankDrive(LeftAuto, RightAuto);
                        }
                    }
                    else
                    {
                        /* We are in PixyDrive Mode, but there is no object found, so stop */
                        TankDrive(0, 0);
                    }
                    break;

                case States.ManualDrive:
                    /* Allow the user to enter PixyDrive mode
                     * Button 3 (B) Changes Manual Drive Stat to PixyDrive State */
                    bool Btn3 = GamePad.GetButton(3);
                    if (Btn3 && !LastBtn3)
                    {
                        CurrentState = States.Init;
                    }
                    LastBtn3 = Btn3;

                    /* Regular mecanum drive that is scaled and Gamepad joysticks have been adjusted */
                    float X = GamePad.GetAxis(0);
                    /* Invert gamepad so forward is truly forward */
                    float Y     = -1 * GamePad.GetAxis(1);
                    float Twist = GamePad.GetAxis(2);
                    MecanumDrive(Y * kScalarY, X * kScalarX, Twist * kScalarTwist);
                    break;
                }
            }
        }