Syncronous motor speed with encoders

Hello! We’re considering using building another robot with Mecanum wheels for an off-season project to apply what we know as far as programming, but there may be a problem… From what I’ve read, there can be a lot of problems when using holonomic steering if the motors aren’t spinning at exactly the correct speed. I’m fairly certain that the absolute value of the wheel speed always has to be the same. I know that the simplest code for holonomic drive is

public void mecanumDrive_Cartesian(double x, double y, double rotation, double gyroAngle)

but, as far as I know, that code wouldn’t allow us to control the motor speed independently. Do I have to modify the mecanumDrive_Cartesian.cpp file? I assume that I’ll need PID loops somewhere in the program (which I have no idea how to write) to interpret the data from the encoders. Thanks!

I don’t know if this is a live thread, but I will suggest two options anyway.

If you want to use the WPI code you linked, the most straight forward method would be to use CAN Jaguar speed controllers and hook up encoders on each wheel connected directly to the Jaguar. Then you setup the Jaguars to do the PID loop on each wheel. There are many posts on how to do this, but the most successful seems to be to adjust the I term first and then the P term.

The other option would be to write your own Holonomic code - it is not that difficult. Ether has a link to some pseudo code that works well. My team took this approach and the robot was driving in about an hour.

To address the wheel speed issue, the consensus is that you need gyro feedback. Keep in mind that even if the wheels are all spinning at exactly the correct speeds, the force vector they create is a function of the weight on the wheel. If the CG is off or one wheel is lifted off the ground the robot could spin violently. The gyro can help redirect power to the wheels to compensate.

Hey! This thread isn’t entirely dead :stuck_out_tongue: We did end up completing our mecanum chassis (3 days from start to finish). What we wound up doing was writing our own mecanum code (thanks Ether) and ten compensating for the speed differences by multiplying each value by a constant which we figured out by trial and error (probably the simplest and worst solution). It looked like this:

	//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)
	}

and when actually controlling the motors, we used

Motor->Set(speedval*(fix(speedval))

It’s not exactly elegant, and it doesn’t always work well. We’ve proposed two things to remedy the issues, but never tried: 1) when rotation is 0, reset the gyro and drive using the gyro, or 2) Run four consecutive PI(D?) loops to that take the desired RPM from the joystick (map +1/-1 values after the drive equations to +max_rpm/-max_rpm) and attempt to set the motors to that. I have no idea if there’s something in-between, or whether or not it would be fast/consistent enough to work in real time. Any ideas about that?

I would like to add a clarification to my post above. The amount of torque (and therefor force vector) that a wheel can impart is a function of the traction of the wheel, which is limited by the weight on that wheel. If the CG is such that the weight is unevenly distributed, one wheel may break traction before the others, changing it’s force vector contribution and cause the robot to spin. All this assumes the wheels are spinning at the correct speeds an therefor trying to impart the correct force vector.

As for your wheel velocity correction method, yes it will work (for some time) but will not adapt for changes in the environment or robot. Your range of gains is larger than I have seen in the past, and you might want to look for the root cause. The only time I have had one wheel off that much, we tracked it down to a CIM with a very slightly bent output shaft, which caused the spur gear to over engage the gearbox and load the motor more. Start by looking at your slowest wheel and check your weight distribution. Is the frame planar? With the robot on a flat surface, try sliding a piece of paper under each wheel.