Maintaining perfect control of mecanums using encoders?

Hey! My team and I built a robot with mecanum wheels over the course of three days a few weeks ago, and right off the bat we had issues driving, because the motor controllers were extremely biased to move faster in one direction than the other. We solved this by running all of our motor outpute through these methods

	//motor speed control method
	public static float fix (float fixme) {
		return fixme < 0.00f ? 1.00f : 0.95f;
		//manipulates motor values based on direction only
	//overload motor speed control method
	public static float fix (int motorID, float fixme) {
		if      (motorID == 1){ return (fixme < 0f)? 1:0.95f; }  //frontLeft
		else if (motorID == 2){ return (fixme < 0f)? 1:0.85f; }  //frontRight
		else if (motorID == 3){ return (fixme < 0f)? 1:0.75f; }  //backLeft
		else if (motorID == 4){ return (fixme < 0f)? 1:0.65f; }  //backRight
		else return 0;
		//manipulates motor values based on direction and ID (slower, more precise)

At the competition last year, there were two or three teams using mecanum wheels, two of which said that they were using encoders to maintain perfect movement (probably also using PID loops…). I would like to learn how to do this. I have no idea where to begin, though, because mecanum wheels tend to spin in any direction at any speed depending on the actions being performed. Any ideas on how to do this would be greatly appreciated! Thanks!

Conceptually, the first thing to realize is that, without encoders, you are just setting a ‘speed’ value. You don’t actually KNOW what speed the wheels are turning. The teams that you talked to really just used PID to control the actual speed (in rev/min) of the wheels. The first step is to figure out what speed you actually want the wheels to be going, then implement PID to get the wheel to that speed.

Start by learning about PID… there’s a good paper you can google, “PID without a PhD”. Once you understand how it all works, implement it using the PIDController class. Basically, you set the various values, give it the input and output, and tell it how fast you want the motor to turn. If set up properly, it does the rest and “figures out” how fast to tell the controller to go in order to get the desired final speed, per the encoder feedback.

Also a small note… the bias you saw wasn’t due to the controllers. It was caused by forward bias in the motors themselves. Every motor has a direction it “prefers” to travel in (based on the design of the motor). As a result, when you set up a robot so that driving forwards involves sending some motors in a clockwise fashion and some in a counter-clockwise fashion, even if you apply the exact same power to every motor you won’t go perfectly straight.

For this reason, PID can be helpful with driving for all sorts of drive trains, not just Mecanum (although I think it’s most noticeable with Mecanum).

I think, more precisely, you are setting a ‘power’ value, less directly linked to speed than you need, which is the root of the problem. a motor will operate differently if it is trying to oppose your forward movement than add to it.

If you measured an unloaded CIM running at “50%” PWM, you will find it attains a RPM far greater than 1/2 of its RPM at 100% PWM, but with a loaded shaft, you can make a motor stall at 50% while it can still run at 100%.
Consequently, a robot moving forward and suddenly sliding left, will operate funny as several motors try to reverse direction and cant keep up (because of the opposing force [mainly inertia/momentum]) with motors continuing to spin forward (with far less opposing force)
This has a large effect, in addition to the above stated “motor preference”
Unfortunately I know next to nothing about software (a certain teammate of mine will attest to that), but I hope this makes sense as far as the problem is concerned.

Not really. More precisely, you are setting a PWM duty cycle value, which most closely correlates with applied voltage, not power.

less directly linked to speed than you need, which is the root of the problem


If you measured an unloaded CIM running at “50%” PWM, you will find it attains a RPM far greater than 1/2 of its RPM at 100% PWM

In the above, are you referring to the duty cycle of the motor controller’s output PWM, or the duty cycle of the PWM servo command signal coming into the motor controller?

If the former, what is your source for that claim?

So from what I’ve read… you would need to write a some sort of control loop that takes the motor controller value (motor->Get() or the PWM signal somehow) and encoder reading as inputs (pidsource)? And then run them through… something. I read through “PID without a PhD” a couple of times…

I concur. You said what I guess I should have said, and what I meant. Power is indeed another property altogether

In the above, are you referring to the duty cycle of the motor controller’s output PWM, or the duty cycle of the PWM servo command signal coming into the motor controller?

I was referring to the PWM signal exiting the sidecar (or what the code SAID was exiting the sidecar). We did some testing last year involving a CIM in a KOP CIMple box, (yeah it isn’t free speed I know, but was otherwise unloaded) Victor 884, a Talon, some incremental software (push a button to add .1 to the PWM value), and a 120fps GoPro (encoders are too mainstream :D).

We didn’t test it while loaded but it is a fairly obvious observation that you need more “juice” when it is harder to move.

We have run mecanum for the last two years including using the wheels to Auto Aim the frisbee bot. Running completely open loop we have had no control issues to make us want to pursue PID. We are using the jaguars in the absolute voltage mode. But we didn’t have issues before.

My point being you likely have other issues to fix before going the feedback route. Mechanically all for wheel need to have firm contact with the ground and as equally weighted as practical. Without your bot will not go straight with all 4 wheels turning the same speed.

Although you might get a little from manufacturing tolerances, CIMs don’t have a bias for one direction or the other & should turn the same spreed given the same load & voltage.

Not to beat a dead horse, but are you saying that you observed ^this^ with a Talon as well as with the 884?

Team 1718 test, unloaded output voltage vs PWM command for 884 and Talon.

If you still have the actual data, would you please post it?

BTW, how did you use the GoPro to measure speed? At 5000/4.67 RPM, 1/120 of a second is 1/7 of a rev. Did you put a circular protractor on the output shaft?


Check all your rollers. Make sure they spin freely, even when axially loaded.

Alternatively, Calibrate your motor controllers.

I’ve built mecanum powered robots before and never had any driveability issues with open loop. I could see wanting to close the loop in order to acheive accuracy in autonomous mode, maybe, but you shouldn’t need it to be able to drive at all.

We’ve also used open loop mecanum in 2011 and 2012, and had no issues worth addressing regarding wonky control.

Four wheels touching the floor with comparable force and correctly spinning rollers are important of course. We took care in design and construction to make that a non-issue. A suspension can help here. (We designed one with suspension, but due to issues removed the suspension)— our well engineered wooden bot frame may have provided enough ‘give’ to allow more even weight distribution than a more rigid metal frame would have provided.

If things are noticeably misbehaving, I have my doubts that changing from open loop to PID will resolve everything.

Get four bathroom scales on a level floor so that the scale platforms are level with each other and see how much weight is on each wheel. Of course, if the scales are different models, their heights will be different, so you might have to shim some under the scale feet. If the scales aren’t calibrated the same, you should be able to compensate by weighing 4 times, rotating the bot 90 degrees between weighings, Add up the 4 weighings for each wheel. We never actually did this with our bots, but that’s because we didn’t have issues with driving them as built.

*The weight distribution matters only if:

  1. one or more wheels loses traction because it has far less weight than the others


  1. one or more of the wheels has significantly more rolling friction because of the extra weight

Once, when we wanted to determine RPM from a video, we counted frames per revolution and divided that into frames per second. (Doing it over several revolutions gives a much more precise number.)

So to create a balanced mecanum bot, we don’t need a suspension? Because we definitely determined at the end of the year that this was the root of our problems…

Then again, we did have a few nasty hits, and I believe right now in our classroom we can rock the robot on the front left and rear right corners a wee bit…

If a somewhat flexible frame doesn’t count as a “suspension”, then you don’t need a suspension.

I believe right now in our classroom we can rock the robot on the front left and rear right corners a wee bit…

That spells death for mecanum.

If it’s only a teeny-tiny bit, it might not end up being a problem on carpet.

If it’s a lot more, you can get creative with a car jack and some straps, and bend the frame into shape again.

In order for mecanum to work properly, you need equal force pushing down on each wheel.

You need sufficient force on each wheel. The forces do not necessarily all have to be equal. Post 13.

Over the years our drivers have had allot of fun having their way with Mecanum drive robots. BoB was the last fun. However back in 2012 I noticed a Mecanum drive that had some pushing power and more swerve like movement. I did notice a KOP gyro on the bot. I suspect they had a very tightly controlled closed loop system. First time I saw a Mecanum that I had some respect for.

I know that in 2012 lots of MAR teams saw 1370 use Mecanum wheels to push other bots about the field. However, we didn’t have a working gyro or closed loop system. Most of our pushing came from the bot being 119.8 pounds!