Encoders in Auto Mode

Anyone know how to use encoders in auto mode?

Your question is pretty vague. Could you please provide more details as to what you are trying to accomplish, and what the problem currently is? Also, it would be helpful to know what language you are using to program the robot, so responses could be tailored to that language.

In theory, using encoders in autonomous would be just the same as using them in teleop. You first must open a reference to an encoder, indicating what DIO it is on and any other necessarry variables, and then use the supplied methods, functions, or nodes/SubVIs to start and count ticks to measure distance or rotations.

I’m using c++, all I need to know is what funcution do I call to make our robot go forward until the encoders turn x amount of times

Still, there are many variations of using encoders. For example, do you care uisng PID? How many encoders do you have? One for left wheel and one for right wheel? Do you have mecanum wheels? In the simplest, your code should look something like this:


In some periodic function or in a loop:
if ((leftEncoder->GetDistance() + rightEncoder->GetDistance()) /2 < targetDistance)
{
    ArcadeDrive(0.5, 0.0);
}
else
{
    ArcadeDrive(0.0, 0.0);
}

We will have 4 encoders and we are using mecanum wheels. Want to just post my code?

4 encoders on mecanum wheels are tricky to deal with for using in autonomous drive. Basically, you need to look at the source code RobotDrive.cpp in the WPI library. For example, look at the function MecanumDrive_Polar. Read all four encoder readings (encoder->GetDistance()) and combine them using a reverse algorithm from MecanumDrive_Polar to calculate the magnitude, direction and rotation. Our team used mecanum wheels for last year and use them again this year. So we want to develop a library module to deal with 4 encoders for autonomous drive. Unfortunately, our build head selected gearboxes that made mounting the KOP encoders impossible. So we never get a chance to develop that library module. But if we were really going ahead to implement it, that would be how I would do it.

i thought it would be simple cause all we want to do is drive forward (for starters) my thought was that you would say in telop encoder.getdistante() and then play that back in auto mode or is it harder than that?

Have you developed this algorithm?

**

No, if I had, I would have posted it. I probably would take some time to do this after the season. Too busy at the moment. I have an algorithm in mind, but I need to enter the algorithm into excel and make sure the numbers will go a round trip without problem. i.e. With a given set of magnitude, direction and rotation numbers, use the algorithm in MecanumDrive_Polar to calculate the four wheel speeds and then calculate a set of encoder distances with a given drive time, apply the reverse algorithm to the encoder distances that should give me a set of: magnitude of distance traveled, direction of distrance travel, rotation delta since start. If I divide it by drive time, I should get back a set of number corresponding to the original numbers. I probably got some aspects wrong. That’s why I need to simulate that in excel to figure out the details of the reverse algorithm.

so then what is the easiest way of doing it in auto mode?

Tomy, if you only care about going straight forward, the algorithm may be a lot simpler without considering all the corner cases. When going straight forward, all four wheels will turn in the same direction with the same strength. So you could do the following:


double distanceTraveled = (leftfrontEncoder->GetDistance() +
                                     rightFrontEncoder->GetDistance() +
                                     leftRearEncoder->GetDistance() +
                                     rightRearEncoder->GetDistance())/4.0;
if (distanceTraveled < targetDistance)
{
    MecaumDrive_Polar(forwardPower, 0.0, 0.0);
}
else
{
   MecaumDrive_Polar(0.0, 0.0, 0.0);
}

where do you set the target distance and why do you divide it by 4?

Add the four encoder values and divide by 4 is averaging them. targetDistance is the distance you want to travel. For example, if you want to travel 5 ft (60 inches), you first set the encoder unit by calling encoder->SetDistancePerPulse for inches. Then set your targetDistance to 60.0.

ok so correct my if im wrong but for 60 inches it would look something like this?



encoder->Setdistanceperpulse (60.0)
double distanceTraveled = (leftfrontEncoder->GetDistance() +
                                     rightFrontEncoder->GetDistance() +
                                     leftRearEncoder->GetDistance() +
                                     rightRearEncoder->GetDistance())/4.0;
if (distanceTraveled < targetDistance)
{
    MecaumDrive_Polar(forwardPower, 0.0, 0.0);
}
else
{
   MecaumDrive_Polar(0.0, 0.0, 0.0);
}


thanks for the help in advance im new to c++

You might the discussion of forward kinematics on Pages 7,8,&9 of this paper of interest.

**

No, you must call SetDistancePerPulse for all four encoders after they are instantiated (as part of the encoder initialization). The parameter to SetDistancePerPulse must be calculated or experimented. Basically, one revolution of the encoder will give you x pulses (I forgot what the KOP encoder is, probably 1440 pulses per revolution), then you have to multiply with the gear ratio if the encoders are mounted on the motor side instead of the wheel side.


Do this in your encoder intiialization:
distancePerPulse = (wheel_diameter*PI/pulses_per_revolution)*gear_ratio;
leftfrontEncoder->SetDistancePerPulse(distancePerPulse);
leftrearEncoder->SetDistancePerPulse(distancePerPulse);
rightfrontEncoder->SetDistancePerPulse(distancePerPulse);
rightrearEncoder->SetDistancePerPulse(distnacePerPulse);
 
Then do this in your autonomous loop:
double distanceTraveled = (leftfrontEncoder->GetDistance() +
                                     rightFrontEncoder->GetDistance() +
                                     leftRearEncoder->GetDistance() +
                                     rightRearEncoder->GetDistance())/4.0;
if (distanceTraveled < 60.0)
{
    MecaumDrive_Polar(forwardPower, 0.0, 0.0);
}
else
{
   MecaumDrive_Polar(0.0, 0.0, 0.0);
}

Thanks Ether, I will read it.

so this funtion will make the robot drive until it goes 60 inches.

my question is isnt there any easier way of doing it because you can fine the distance traveled by using the .getdistance in telop mode. why cant you just say something like

myrobot.drive till encoder turn so many revolutions?

That’s basically what the code is doing: drive until the encoder->GetDistance() say it has traveled 60 inches.
You could put the code in a function like this:


void DriveDistance(float targetDistance)
{
    float distanceTraveled = (leftfrontEncoder->GetDistance() +
                                     rightFrontEncoder->GetDistance() +
                                     leftRearEncoder->GetDistance() +
                                     rightRearEncoder->GetDistance())/4.0;
 
    while (distanceTraveled < targetDistance)
    {
        MecanumDrive_Polar(forwardPower, 0.0, 0.0);
    }
    MecanumDrivePolar(0.0, 0.0, 0.0);
}

But this function is blocking. You cannot do anything else why the while loop is waiting. Not to mention this will starve your watchdog although by calling the MecanumDrive_Polar function, you probably will feed the per motor watchdog for this year’s WPI library. So it’s better to do what I suggested in the previous post of checking the target distance in your autonomous loop.

so the best and easiest way is the way you described in post 16

Do this in your encoder intiialization:
distancePerPulse = (wheel_diameter*PI/pulses_per_revolution)*gear_ratio;
leftfrontEncoder->SetDistancePerPulse(distancePerPulse);
leftrearEncoder->SetDistancePerPulse(distancePerPulse);
rightfrontEncoder->SetDistancePerPulse(distancePerPulse);
rightrearEncoder->SetDistancePerPulse(distnacePerPulse);

Then do this in your autonomous loop:
double distanceTraveled = (leftfrontEncoder->GetDistance() +
rightFrontEncoder->GetDistance() +
leftRearEncoder->GetDistance() +
rightRearEncoder->GetDistance())/4.0;
if (distanceTraveled < 60.0)
{
MecaumDrive_Polar(forwardPower, 0.0, 0.0);
}
else
{
MecaumDrive_Polar(0.0, 0.0, 0.0);
}