View Full Version : Driving Straight With Encoders
microbuns
02-03-2015, 12:57
How do you drive straight with a tank style drivetrain using encoders (no gyro)? Our bot has 2 wheels which each have identical encoders on them, but unfortunately one side has more friction than the other side.
Our best solution we have right now (which isn't amazing) is to have a speed PID controller on both sides, which ensures they are both going the correct speed relative to the floor. However, this doesn't always guarantee the wheels get up to speed in time - meaning one side may get as much as 2-3 inches ahead of the other while they are speeding up - this difference will be maintained as they stay at speed.
I was thinking about somehow trying to minimize the difference between the two sides' encoders, but I'm not exactly sure what/how to go about that. Do you just have some speed factor you add to one side and subtract to the other that scales off the difference of the two sides?
notmattlythgoe
02-03-2015, 13:00
How do you drive straight with a tank style drivetrain using encoders (no gyro)? Our bot has 2 wheels which each have identical encoders on them, but unfortunately one side has more friction than the other side.
Our best solution we have right now (which isn't amazing) is to have a speed PID controller on both sides, which ensures they are both going the correct speed relative to the floor. However, this doesn't always guarantee the wheels get up to speed in time - meaning one side may get as much as 2-3 inches ahead of the other while they are speeding up - this difference will be maintained as they stay at speed.
I was thinking about somehow trying to minimize the difference between the two sides' encoders, but I'm not exactly sure what/how to go about that. Do you just have some speed factor you add to one side and subtract to the other that scales off the difference of the two sides?
What language are you using?
Last year we read the values of the encoder and then used a PID controller with a setpoint of 0 and did as you said, added to one side and subtracted from the other. This can also be done using arcade style driving just just putting your PID output into the turn value.
microbuns
02-03-2015, 13:19
We are using C++.
How straight did you end up driving with that? We are looking for a maxiumum error of roughly 1:100 (ie 100 units forward gets you at worst 1 unit to the left or right) or ~0.5 degrees. Is that kind of precision you guys were seeing?
notmattlythgoe
02-03-2015, 13:22
We are using C++.
How straight did you end up driving with that? We are looking for a maxiumum error of roughly 1:100 (ie 100 units forward gets you at worst 1 unit to the left or right) or ~0.5 degrees. Is that kind of precision you guys were seeing?
I don't know the exact numbers, but we were able to grab multiple balls in every match last year.
I was thinking about somehow trying to minimize the difference between the two sides' encoders, but I'm not exactly sure what/how to go about that. Do you just have some speed factor you add to one side and subtract to the other that scales off the difference of the two sides?
This is a good approach. I've seen the following work pretty well:
// Set up drivePID as a PIDController with a custom PIDSource that
// calculates the distance between the encoders and outputs the result
// in PIDGet(). The PIDOutput doesn't matter and should be a dummy.
// In AutonomousInit
drivePID.Enable();
// In AutonomousPeriodic
drivePID.SetSetpoint(0);
double movement = someConstant;
double rotation = drivePID.Get();
drive.ArcadeDrive(movement, rotation, /*SquaredInputs=*/ false);
This is where drivePID is an instance of the PIDController class. The PIDController class is pretty obnoxious in that its source and output have to be of the types PIDSource and PIDOutput, respectively. This means that you (the FRC team) have to create a class that inherits from PIDSource which calculates the difference between two encoders and returns that in the virtual function PIDGet().
Gotta say, sometimes the flow of information in C++ is really hard to follow.
Keep in mind that if both sides turn the exact same amount, the robot will go straight, in theory ONLY. In the real world, tiny inconsistencies will prevent this from ever happening. Tiny perturbances lead to vastly varying results. Things like: wheels being slightly different diameters; slightly wrinkled carpeting; driving over a wire tie with one side, one side of the robot being heavier and sinking into the carpet more etc. Counting on dead reckoning for less than a 1" drift over 100" of travel seems iffy, even with perfect software. The actual physical environment just isn't that theoretically perfect.
For example, you might expect repeatability of a 4" diameter cast rubber wheel to be about +/-.020". If one side has wheels 3.98" and the other side has wheels 4.02" in diameter, if you tell the robot to drive 100" (7.958 revolutions of a 4.000" wheel) one side will travel 99.5 inches, and the other side will travel 100.5", and that's just one factor out of many that will cause drift. If you are lucky, all those factors will cancel each other out, but it's likely they won't.
I'm not trying to discourage you from implementing a purely encoder based solution. But you need to realize that even if your software is perfect, the robot may still not drive straight. You may need to add some other sensors to your control algorithm. This could be computer vision, keeping you headed exactly at your target. It could be a sideways looking distance sensor, keeping you driving parallel to a wall. It could be a highly accurate gyro telling you if you are drifting off course. Hopefully, you have a practice bot with which to experiment. If not, next summer is a great time for experimentation, so you have a thoroughly tested solution ready for next season.
microbuns
02-03-2015, 14:47
Keep in mind that if both sides turn the exact same amount, the robot will go straight, in theory ONLY. In the real world, tiny inconsistencies will prevent this from ever happening. Tiny perturbances lead to vastly varying results. Things like: wheels being slightly different diameters; slightly wrinkled carpeting; driving over a wire tie with one side, one side of the robot being heavier and sinking into the carpet more etc. Counting on dead reckoning for less than a 1" drift over 100" of travel seems iffy, even with perfect software. The actual physical environment just isn't that theoretically perfect.
For example, you might expect repeatability of a 4" diameter cast rubber wheel to be about +/-.020". If one side has wheels 3.98" and the other side has wheels 4.02" in diameter, if you tell the robot to drive 100" (7.958 revolutions of a 4.000" wheel) one side will travel 99.5 inches, and the other side will travel 100.5", and that's just one factor out of many that will cause drift. If you are lucky, all those factors will cancel each other out, but it's likely they won't.
I'm not trying to discourage you from implementing a purely encoder based solution. But you need to realize that even if your software is perfect, the robot may still not drive straight. You may need to add some other sensors to your control algorithm. This could be computer vision, keeping you headed exactly at your target. It could be a sideways looking distance sensor, keeping you driving parallel to a wall. It could be a highly accurate gyro telling you if you are drifting off course. Hopefully, you have a practice bot with which to experiment. If not, next summer is a great time for experimentation, so you have a thoroughly tested solution ready for next season.
Thank you very much for this Todd. I do understand that it's almost impossible to drive straight with just encoders... However that's the situation the programmers on our team have been put on. Next year we're going to have to get this driving straight thing down earlier!
We do have a practice bot. I'm not sure how practical it is to try and implement something new completely to our bot, given time constraints. However I do think we will try the "keep encoder delta at 0" PID strategy.
Just out of curiosity - what is considered the "best" way to drive straight (assuming a tank drive bot and a moderate budget)? Would that be encoders + a gyro?
rich2202
02-03-2015, 14:52
Just out of curiosity - what is considered the "best" way to drive straight (assuming a tank drive bot and a moderate budget)? Would that be encoders + a gyro?
Driving straight has always been a problem. Even with a gyro. We just received the navX board, and have high hopes. It should be able to tell you orientation of the bot, heading, and where you are so mid-course corrections can be made.
http://www.andymark.com/product-p/am-3060.htm
Andymark is supposed to be getting in more any day now.
Chris Hibner
02-03-2015, 15:38
Providing your wheels don't slip, the change in heading of your robot is
heading_radians = (leftEncoderDistance - rightEncoderDistance)/TrackWidth
TrackWidth is the distance between the left and right wheels.
Wheel slip and other imperfections make the above heading calculation not perfect, but it's good enough to use in a PID loop to keep your robot driving straight.
Here's some info that may be of interest.
Drive straight with encoders:
http://www.chiefdelphi.com/forums/showthread.php?p=1446789#post1446789
Use motion planning for best results:
http://www.chiefdelphi.com/forums/showthread.php?t=98358
http://www.chiefdelphi.com/forums/showthread.php?t=134965
Do some simple system identification[1]. For example, take the wheel diameter problem Todd mentioned. Drive the vehicle in a straight line (by tweaking the left-right motor commands) and note the ratio of the left and right encoder values. Use that ratio to fudge your setpoints, or use it to fudge your encoder readings before using them as your process variable.
[1] http://en.wikipedia.org/wiki/System_identification
Just out of curiosity - what is considered the "best" way to drive straight ?
Any of these (gyroscope, encoders on wheels) or even a magnetic compass is a good first step, and is probably good enough to get you through most 15 second autonomous tasks.
The next step is to make mid-course corrections, based on sensing the environment. This could range from the highly complex (camera-based navigation) to the ridiculously simple (two "curb feelers" or other touch sensors that as limit switches for the drive on either side) and a number of points in between (down-looking sensor looking for the landmark; optical or ultrasonic rangefinders). In this game (unlike most), you could even set down a "trail of bread crumbs" to follow, provided that those bread crumbs are on a tether to your robot.
microbuns
02-03-2015, 16:07
Here's some info that may be of interest.
Drive straight with encoders:
http://www.chiefdelphi.com/forums/showthread.php?p=1446789#post1446789
Use motion planning for best results:
http://www.chiefdelphi.com/forums/showthread.php?t=98358
http://www.chiefdelphi.com/forums/showthread.php?t=134965
Do some simple system identification[1]. For example, take the wheel diameter problem Todd mentioned. Drive the vehicle in a straight line (by tweaking the left-right motor commands) and note the ratio of the left and right encoder values. Use that ratio to fudge your setpoints, or use it to fudge your encoder readings before using them as your process variable.
[1] http://en.wikipedia.org/wiki/System_identification
We may have done some of this "system identification" unintentionally. We did a test where we pushed the robot straight and looked at the encoder values after a certain distance - the two wheel systems seem to be more than within our error tolerance, as we saw a <0.1% error arise (little enough error to just be caused by how we conducted the experiment). We believe the difference is in friction on the two wheels, but we are unsure of a way to quantify that.
We believe the difference is in friction on the two wheels, but we are unsure of a way to quantify that.
If by "friction on the two wheels" you mean a difference between the left vs right drivetrain friction (due to gearbox, chains/belts, misalignment, lube, etc) then the closed-loop control can compensate for that.
Skyehawk
12-03-2015, 17:43
I have not have time to read this entire thread, my apologies it I am being redundant:
My team has a method for making a "perfectly" straight line while driving forward in auto.
The method:
1) Reset both the left and right encoders.
2) Running in a ~20ms while loop:
...A) some form of counter, timer, or interrupt to stop the loop
...B) some form of comparison between the two encoders
3) Start off the while loop by driving at a certain speed
4) Check if Right>Left, if so speed up Left
5) Check if Left>Right, if so speed up Right
6) Stop loop when the control condition is met.
We sped up the side that was going slower when we reached a tolerance of + or - 1/8 inch. This gave us a drift of 2 inch over a 500 inch forward run.
vBulletin® v3.6.4, Copyright ©2000-2017, Jelsoft Enterprises Ltd.