2.1 m/s Line follower with pololu components


This is a good article written by my friend Jorge (and translated by my friend Raul), members of C.i.r.e (spanish robotics club), about a fast line follower which can run 2.1 meters/second (6.56 feet/second). He used a lot of Pololu components. The article has instructions, source code, pictures and video:


I hope you like it.


Awesome! Thanks for sharing. --David

Nice follower.
Is there some formula or guidelines on how far the sensors are ahead of the wheels/body? I suspect it is a function of sensor sample rate, speed, minimum radius for turns, and the software following code, and …

We have the next formula: The distance between wheels axis and the sensors is about 1.0 to 1.5 times the distance between wheels.


Great project! We put a link to your project on Pololu’s Community Projects page.

- Ryan

Thanks for the reply.
You say use length ratios of 1.0 to 1.5. The 3pi robot is approximately 0.5. Is there any criteria for this ratio or is it all sort of arbitrary?


You should not be surprised if some aspect of an optimized line follower (for some type of course) is not shared by the 3pi, which has other design constraints (for instance, it’s round). Optimums aren’t arbitrary, but they vary with the problems you’re trying to solve.

- Jan

Thank you very much. Our goal is to share as much as possible.

[quote=“albooth”]Thanks for the reply.
You say use length ratios of 1.0 to 1.5. The 3pi robot is approximately 0.5. Is there any criteria for this ratio or is it all sort of arbitrary?[/quote]
Well, it depends of track class. If track has closed angles, circles, impasses, etc. your robot should have the sensors next to wheels, if track have long rects and open curves, the robot should have the sensors more far from wheels.

A 3pi is optimal for the first class of tracks, even it can run on second class of tracks, but slowly, because it can’t response quickly to curves at high speeds.

@osropa and jan
Thanks for the replies. Sounds like I need more experience, lots of trial and error, and then fine tuning.
Too bad - a simple equation or table would have been a lot easier, but less challenging and less educational.

Wanted to thank you in particular for posting your source code. Your obtener_errord() method has more or less saved my bacon.

I had noticed previously that adding a nonzero Kd constant–even a large one–to my line follower had practically no effect on its behavior. I believe what’s been happening is that the output of ‘error’ from my line sensors is essentially step function; it tries to interpolate the position of the line between sensors, but it’s not very good at it. So when I was calculating (error-last_error), I was seeing a short spike followed by a lot of nothing, then another short spike. The short spikes weren’t enough to affect my bot.

Your method does a much better job of detecting the drift in error values and reporting a continuous delta. I plugged that method in while leaving the rest of my program alone, and suddenly it started behaving like a line follower should–and I can get on with the tuning.

BTW, I’ve rewritten the method for my own use so I could fit it into my project better. Here’s the revision for anyone interested. You’ll notice I pulled the ‘kd’ constant out; I multiply the result of this method by kd, rather than saving the premultiplied version in here. And I’m using doubles because I’m lazy. :slight_smile:

double errorVelocity (double currentError)
         static double lastError = 0;
         static double currentVelocity = 0;
         static double lastVelocity = 1;
         static uint32_t elapsed = 1;
         static uint32_t elapsedAtLastChange = 1;


         if (currentError == lastError) {
            if ((elapsed = min(elapsed,30000)) > elapsedAtLastChange) {
               currentVelocity = lastVelocity / elapsed;
         } else {
            currentVelocity = (currentError - lastError) / elapsed;
            lastVelocity = currentVelocity;
            elapsedAtLastChange = elapsed;
            elapsed = 0;

         lastError = currentError;
         return currentVelocity;

One video in competition (The robot is on the right side in the first race and on the left side in the second race). Finally It took the third place.

Nice job osropa! It looks like your opponent had a lot of trouble on that tight turn (his robot wobbles back and forth) but your robot handled it just fine. --David