Correcting Mecanum Wheels with Encoders (Ether, We Summon You!)

We have the mecanum wheels set up to properly move in the Y (forwards and back) direction and to turn without any problems, but when attempting to strafe, the robot veers off to one side instead of going straight to the side. To fix this, we are using encoders, but we are running into some severe difficulties. Through a bit of troubleshooting, I found that this works…


public class TalonCan {

    CANTalon talon;

    public TalonCan(int canID){
	talon = new CANTalon(canID);
        talon.changeControlMode(ControlMode.PercentVbus);
    }
}

And this doesn’t…


public class TalonCan {
    
    CANTalon talon;
    
    public TalonCan(int canID){
        talon = new CANTalon(canID);
	talon.changeControlMode(ControlMode.Speed);
	talon.setPID(0.1, 0.001, 1, 0.0001, 100, 36, 0);
	talon.set(0);
	talon.setFeedbackDevice(FeedbackDevice.QuadEncoder);
    }
}

I believe it’s from not using the encoders, so my question is, what am I doing wrong in the second example? The robot does not move in autonomous, nor in teleop.

[EDIT]
We have already put the robot on blocks and the wheels are moving in the correct direction and correct speed. It’s only on the floor that we have problems, hence the need for encoders.

*I don’t do Java/C++ code debugging from afar so I invite Java/C++ gurus to jump in here.

In the meanwhile, it might help if you would post answers to the following questions:

What units are you using for speed commands when in Speed mode?

How did you determine the PID gains?

Have you looked at the encoder values you are getting?

Put the bot up on blocks and command pure strafe right. Observe the 4 wheels and tell us what direction each wheel is spinning, in both PercentVbus and Speed mode. Just saw your edit, so: What direction was each wheel spinning?

The top left and bottom right rotated counter-clockwise and the opposite for the other wheels.

<–] –>]
–>] <–]

Like this. It works well enough, except it veers to the right side.

We just used default values given by a manual. We messed around with them a bit, but no difference to before.

I’m sure the diagram makes perfect sense, but not without some explanation. What do the arrows mean? Which wheel is which?

I should have added a bit of detail. The arrows are the direction of the wheels from the top down. The movement should be upwards, where the top left is the top left wheel, the top right is the top right wheel, and so on and so forth. This is assuming sliding is up and down according to the diagram.

I have already checked the movement against your explanations, and they checked out. Any errors you see above are my personal errors.

I’m a bit uncertain what the above means. When strafing to the right, the bot should “slide” sideways to the right. How is “veers to the right side” different from that?

*In case you missed these questions:

I’m trying to make things simpler by changing the orientation, but I guess I’m doing the opposite. So to drive forward, the wheels all move in the same direction.

<---- (movement from top down)

Forward (<)
[top right] [bottom right]
[top left] [bottom left]

Sliding right (^)
<–] -->]
–>] <–]

Sliding left (v)
–>] <–]
<–] -->]

The problem we are running into is that when sliding, it veers up and down. The right top and bottom output velocity values lower than those on the right top and bottom

First off, your wheel spins look to be backwards for the strafes, unless your wheel rollers are configured in an X (worm’s eye view). However, you said you can turn normally, so you are likely configured correctly to be O and just have things backwards here??

Have you checked things mechanically before you go correcting things with sensors?
-can all rollers spin freely?

-what happens when you drive at 45 degree angle?

-I have seen both a bad motor and an incorrectly assembled gearbox cause problems that you can’t visually see when you put the robot up on blocks and look at wheel speeds. unplugging 2 PWMs at a time can sometimes help troubleshoot this: unplug front motors then rears and drive forward/back, then sides and strafe both ways. compare how far off course you get in each case.

for that matter, can you try to quantify how far off a perfect strafe you are in the normal configuration? Of course, a VIDEO WOULD GET YOU BETTER HELP!!!

*Have you gathered and analyzed the troubleshooting data in the status frames? What did you find?

20.1. General Status
The General Status frame has a default period of 10ms, and provides…
-Closed Loop Error: the closed-loop target minus actual position/velocity.
-Throttle: The current 10bit motor output duty cycle (-1023 full reverse to +1023 full forward).

20.3. Quadrature Encoder Status
The Quadrature Encoder Status frame has a default period of 100ms.
-Encoder Velocity: Velocity of the selected sensor

There appears to be some confusion interpreting your ASCII art.

Please confirm that your wheel speeds conform to the attached sketches.

*









For what it’s worth, I understood the pictures immediately, and I think they look correct.

How heavy is your robot, and how is the weight distributed? The symptom sounds like the back wheels are slipping a little on the carpet, which suggests that the robot is front-heavy.

The ultimate solution is going to be to recognize that controlling wheel speed precisely isn’t good enough to always prevent unwanted rotation of a mecanum drivebase. You’re going to have to add some way of measuring the actual robot motion, and in this case I think the appropriate sensor to do that is a gyro.

I’d have to agree with lcoreyl here. Your diagram appears to be saying that the right-side wheels are being driven away from each other, and the left-side wheels are being driven toward each other for strafe right. If that’s what you meant, it’s not correct: that would be the wheel directions for strafe left.

But that’s not what’s causing your problem. You said in the OP that the robot doesn’t move at all when it’s on the ground and using ControlMode.Speed. I would recommend checking the status frames to see what the encoders are doing.

If the weight is not distributed evenly, for a given voltage the angular acceleration of the heavier weight on wheels will will be lower relative to the lighter wheel, mecanum roller slippage or not. I think using the PID loop to even out the wheel RPMs is the right stategy.
Having said that, I rarely use the built-in PID controllers WPI provides, usually just write my own control loop. I’m not sure why OP selected values of P=0.1, I=.001, D=1 . Recommend reducing D down to near zero while testing, as this would just produce a damper which could null out your rates to near zero despite your offset.

Another thing to consider that strongly affects mecanum… is your frame square? Perhaps one of the wheels is off the ground or bears too little of the weight.

My #1 concern in your setup is this:
What is causing the odd strafing? If it’s wheel slippage (my main guess), encoders on the drive wheels won’t help you. Consider using a gyroscope to get your error. You’ll likely be happier anyways.

*The OP has stopped responding to his thread, so we don’t know the status is, or if he is still reading.

But so far, the responses have not addressed his original question:

I assume that since you are only showing the constructor that you are not changing anything else. That would be your problem I suspect. When you change modes, you change the units of “set();”. That means you need to select a velocity based on your joystick. If you are using it like you should for a typical open-loop robot, then the values you are sending to set() are -1 to 1. This means that when you switch to closed loop you are asking for a velocity of -1 to 1. Depending on your sensor (you indicated an encoder) that is incredibly slow. Depending on how your PID constants are tuned, it may give the results you described.

Just to add a little bit more to what Joe has said, the “velocity” in the Talon SRX when using speed (velocity) control mode is in counts per 1/10 of a second. See section 17.1 of the Talon SRX Software Reference Manual for a little more info. On our robot, our top speed as measured on the Talon SRX is around 600 units, so we use set() commands which range from -600 to +600.