Tracking wheels or Inertial for turn pid?

I have a decision to make in my programming process. I’m trying to decide if I should use the difference in position of my tracking wheels, OR my inertial heading to define my current position. Now, I know how to do it with the tracking wheels, and i’m trying to learn how to do it using the inertial sensor.

(help learning how to use the inertial in my turn pid would be greatly appreciated)

so, should I continue learning how to make a turn pid using the inertial sensor, or should I just use my tracking wheels, or, could I use a combiniation of both somehow??

It’s not hard to use the inertial sensor. All you do is get the heading or any other info you want from it. It is so much easier than using tracking wheels to determine heading. I would say the best idea is to probably take an average of both.

1 Like

So youre saying do something like this?

Int currentPosition(LeftTrackPos + RightTrackPos + Inertial.heading(degrees))/3;

I don’t think that calculating position is as easy as that. You first need to get the angle from the difference in the 2 odom wheel and then take the average of that angle and the inertial angle.
Here is a link explaining how to get the angle from 2 Odom wheels: Odometry - BLRS Wiki

1 Like

Ill take a look, thanks!

So, I spent some time reading and I’m thinking this isn’t the route I want to go (unless im already doing it without realizing).

What I’m trying to do is make a PID loop to more accurately move my robot. Ive already developed four PID loops: forward, reverse, strafe left, and strafe right. Those are all basically the same, you just have to change the motor direction.

Note: I’m going off the top of my head and I dont have my code with me

Where I’m stuck is on turning. The first rendition I created took the difference in position of the left and right tracking wheels and I called that “TurnDifference”. I then defined my turn error like this

TurnError = TurnDifference - finalTurnValue

My main question is this- can I replace the turn difference (Left-right) with the inertial heading?

Yes and it will be more accurate because on your current version you use final turn value where as if you use the inertial sensor you can get and use the angle in degrees. The code would be something like error=target angle- current angle

1 Like

I’ll go ahead and code something up tomorrow. Thanks for all of the help.

Alright, I’m getting the hang of it and I’m just about done, but I’m noticing that you can calibrate the inertial and you can set the position to 0 degrees. What does calibrating it do, and does setting the position to 0 degrees effectively reset its position? or would it cause problems when programming an auton?

Calibration of the inertial sensor is necessary for accuracy. It can be done in pre-auton using a loop like

gyro.calibrate()
gyro.setRotation(0, degrees)
While(gyro.isCalibrating){
wait(10,msec)
}

Setting the position to zero basically resets it’s position so I would avoid touching it. Instead the easiest thing to do is when you want the robot to turn an angle you add or subtract the amount you want to turn from your current angle.

1 Like

What would happen if I turn right too many times and the value exceeds 360 degrees?

also i’ve decided I want to use two inertial sensors. One for left turns, and one for right. the one for right turns would be placed in the normal mounting direction, and the one for left turns would be directly to the left of the right one, flipped 180 degrees so the front of the sensor faces the back of the robot.

Im doing this because as far as I understand, you cant turn left if you use one inertial sensor because the angle cannot be negative.

When you turn left the angle is negative

I thought the inertial heading could only be 0-359.99?

To the best of my memory it goes -180 to 180

Oh… I guess Im mistaken.

oh well, Ill try everything we discussed. thanks for the help.

I always set the inertial sensor to calibrate and set to 0 at the beginning, and then tell the robot to turn until it is facing a certain degree relative to where the robot was facing when it started and it can go up to 360 degrees, with 90 being 90 degrees right and 270 being 90 degrees left.
Edit: here is an example if you want to face right 90 degrees

Front_Left.spin(fwd);
Back_Left.spin(fwd);
Front_Right.spin(rev);
Back_Right.spin(rev);

//this waits until the inertial is in between two values so it has some time to read the inertial values if it is going too fast
waitUntil(Inertial.Heading(degrees) > 88 && Inertial.Heading(degrees) < 92);

Front_Left.stop();
Back_Left.stop();
Front_Right.stop();
Back_Right.stop();

If I need to turn an angle that is not exactly 90 degrees, I usually just look at a degree wheel like this and use it to see where I want the robot to face and use that number.
image_2022-08-03_095433867

I have an update. for the sake of keeping this as short as possible, Im only going to post what ive done for my turn left pid.

first, in pre auton, I reset the inertial

I’m using two inertial sensors at opposite mounting angles so that if I want to turn left 90 degrees, I say turn until left inertial reads 90, and vice versa for right.

This just makes it so that I dont have to add 180 degrees to every turn I make. (ex, to turn 90 deg left id have to tell my motors to spin until the inertial reads 270.)

void pre_auton(void){
    vexcodeInit();

    //calibrating left inertial
    LeftInertial.calibrate();
    LeftInertial.setRotation(0, degrees);
    while(LeftInertial.isCalibrating()){
      wait(10, msec);
    }
    
    //calibrating right inertial
    RightInertial.calibrate();
    RightInertial.setRotation(0, degrees);
    while(RightInertial.isCalibrating()){
      wait(10, msec);
    }
    

    }

next, I have my turn left pid loop

//Turn left pid
  //--------------------------------------------------------------------------------------------------------------------------------------------//

        //turn left constants
        double turnLeftkP = 0.1;
        double turnLeftkI = 0.0;
        double turnLeftkD = 0.0;

        //Desired value
        int desiredTurnLeftValue = 0;

        //defining errors
        int turnLeftError; //SensorValue - DesiredValue : Positional value
        int turnLeftPrevError = 0; //Position 20ms ago
        int turnLeftDerivative; // error - prevError : speed
        int turnLeftTotalError = 0; //totalError = totalError + error
        
        //variables for settings
        bool enableTurnLeftPID = true;
        bool resetTurnLeftSensors = false;

        //Drive pid
        int turnLeftPID(){

          if (resetTurnLeftSensors) {
            resetTurnLeftSensors = false;
            LeftTrack.resetPosition();
            RightTrack.resetPosition();
            RearTrack.resetPosition();
            LeftInertial.setRotation(0, degrees);
          }


        while(resetTurnLeftSensors){
        

          //Averaging position
          int TLCurrentPosition = LeftInertial.heading(degrees);
          

          //Potential
          turnLeftError = desiredTurnLeftValue - TLCurrentPosition;

          //Integral
          turnLeftTotalError += turnLeftError;

          //Derivative
          turnLeftDerivative = turnLeftError - turnLeftPrevError; 

          //Lateral PID equation
          double turnLeftSpeed = (turnLeftError * turnLeftkP + turnLeftTotalError * turnLeftkI + turnLeftDerivative * turnLeftkD);

      
          FrontLeftDrive.spin(reverse, turnLeftSpeed, voltageUnits::volt);
          FrontRightDrive.spin(forward, turnLeftSpeed, voltageUnits::volt);
          BackLeftDrive.spin(reverse, turnLeftSpeed, voltageUnits::volt);
          BackRightDrive.spin(forward, turnLeftSpeed, voltageUnits::volt);
          turnLeftPrevError = turnLeftError;


          vex::task::sleep(20);

          }

          return 1;
          }

next, I created a function that basically gives the pid task parameters to run on, and it makes it easier to code in auton.

in this section, I use both of my inertial sensors for more accurate turning. the perameters tell the motors to spin until the left inertial is between 90 and 92 degrees, and the right inertial is between 270 and 272 degrees.

void LTurnPID(int degrees){
        resetTurnLeftSensors = true;
        desiredTurnLeftValue = degrees;
        waitUntil(LInertialAngle > degrees && LInertialAngle < (degrees + 2) && RInertialAngle > (degrees + 180) && RInertialAngle < (degrees + 182)); 

      }

finally, I have the movement testing

vex::task tltest(turnLeftPID);
        LTurnPID(90);
        vex::task::stop(tltest);
        wait(0.5, seconds);