Programming a Crab Drive System

My team is trying to prototype a crab drive over the summer so we have it in our arsenal. We’ve looked extensive at ways of setting it up, and ways of programming it, and have some questions to teams that have done this long-term.

We’re looking at doing either a single chain rotates all 4 modules, or 2 chains rotate two modules.

I’ve been doing pro/con on both, but I need to clarify something regarding the programming.

When a crab-bot is translating sideways, can it also rotate 360 degrees? If you run a single chain on all 4 modules, the answer appears to be an obvious no unless you stop to do the rotation.

With two chains running two modules each, it appears with some clever programming that it would be possible to rotate the robot 360 degrees while translating.

However, after watching a ton of match video of teams who have done crab, I’ve seen almost none of this. Most teams can tank-steer, but once they go into translational motion they do not rotate without going back into tank-steer configuration.

Is this correct? Is this due to the difficulty of the programming to rotate while translating, or this something else I’m missing? It would seem that having to go to tank mode to rotate the bot would be losing part of the beauty of crab drive.

So clarify it for me, if you can. What is your crab robot programmed to do when driving?

If you steer in pairs, you can rotate while translating near two poles (obviously where it’s setup like a 4wd tank), but the other pair of poles is incapable of rotating as you when you reverse motor direction on one side, you are just driving into the other side.

The other half is it’s a nasty control problem to do both at once, not impossible, but it’s certainly easier to strafe and turn separate.

We never got this far on our proto, but I wanted to allign the base based on our manipulator and game so that when we were accomplishing the game task, the wheels were aligned near the poles that allowed rotation, so we could make minor adjustments easily.

I can’t say our team has been doing anything long-term, but our lunacy robot was able to do what you described. With the trailer, it was probably the most difficult part to program. It didn’t work very well on the game surface, but on a rug and without a big object attached to the back of our robot obstructing our movement, our system would have probably worked out great.

Our crab drive had 4 independent crab modules. It might be more difficult to do this with chains, but I think it should. Our control system was field oriented. One joystick controlled the direction the robot moved, the other the direction the robot pointed. We used a gyro so that we always knew what direction our robot faced, and servos (might have been encoders, or hall-effect sensors, I forget) so that we knew what direction each of our wheels faced.

To rotate our robot while we were moving sideways, we simply made both wheels on one side of the robot spin faster than the other two, just like a crab drive. While our robot was turning, we constantly updated the facing of each wheel so that while was turning, our wheels were turning in the other direction and thus still moving in the desired direction.

(sorry for spelling/grammar errors I had to type this very quickly)

Team 1640 did swerve this year and as a off season project the math for 4 wheel independent steering and drive was worked out. There are several resources on our web site on this subject. On this page at the bottom are links to the math models.
http://wiki.team1640.com/index.php?title=4-Wheel_Pivot_Drive
On this page there are more info on our pivots.
http://wiki.team1640.com/index.php?title=DEWBOT_VI_Drive_Train
The website is a WIKI so the info is there, it does take a little searching to find everything we have on crab. This is the crab with a twist white paper.
http://wiki.team1640.com/images/3/3a/Pivot_-_Crab_with_a_Twist_edit.pdf

In software there are two main things to consider:
How many seperate steering motors are there (each module independent or are some together?)
Is it infinite of fixed-range?

If you have a single steering motor with a fixed range, there isn’t much to it. You can run a P or PID control to angle, and if the angle is -90 and it is suddenly set to 90 you can invert the motor instead of rotating the pod. You also have to check, and if the front has changed, then change which motors are “right” and “left” to the tank drive. That’s about all you can do.

If you have two pairs of steering motors, you can do a little more with steering. If you want to curve while driving, you can partially rotate the front and rear pods (with the rear pods inverse of the front ones). This can help augment tank steering, but is not as perfect as independent steering.

If you have a system with independent control of four wheel pods, then you can adjust each one separately to turn. You would take a point in space, of which the angle is 90 degrees off the desired translation angle, and which the distance from the center of the robot is the desired rotation. If the rotation axis is within a deadband, just set the wheels to the translation angle. If it gets out of the deadband, scale it so that a little rotation is very far from the robot but max is in the center of the robot. Then, add or subtract from this point to get the offset from each pod, and take do some math to find the angle for each wheel (take the arctangent of the X and Y, swapping X and Y). I have not seen many FIRST robots operate this way.

If you have an infinite system, you need to look at which path is the simplest: Check to see if the error between the current angle and desired angle is greater than the error between the current angle and the inverse of the desired angle. Whichever one is shortest is the path to take. If you go for the inverse of desired angle, set the motor negative to compensate.

Our lunacy bot had four wheel independent steer, and the operator controls were too difficult for the operator, so we have a “tank-hybrid” system where the average of the X axis determines the translation and the Y axis is a tank drive (rotating more than 45 degrees swaps some motors so the front is right and the rear is left, or vice-versa).

EDIT: I will post pictures to help explain the independent steering math later.

Idealy, you would want all four wheels independently rotated, otherwise you can’t turn very fast when you’re travelling diagonally (due to the sideways coeffecient of friction of the wheels).
If you care to do some soldering to wire up the keyangs, they are a possibility.
By the way, I would reccomend using a continuous-turn potentiometer to determine the wheel rotation. (Try to find one without a 1/8 turn blind spot).

Or, if you want to go fancy on the mechanical side, you could actually use a single motor for direction and a single motor for turn (using a differential on each wheel bracket to sum the two values).

1717 did diagonal modules rotated by a single motor, with each diagonal rotated independently. This allowed them to translate independent of turn without worrying about the skiding nature of 4 wheels at the corners.

Another thing I’d like to point out from a controls perspective is that any sort of complex translate + spin move needs to be field-centric and not robot-centric. The drivers would have a very difficult time performing it under pressure otherwise.

Field centric is something I want to work toward, but first I want to firmly define in my mind what our end objectives for maneuvering should be.

We are going to go 4 modules, in 2 pairs. My thought is similar to a post from wild stangs: when the wheels are within 30 degrees of making the robot a wide configuration robot, the rotational joystick will simply modify the wheel speed and the robot will tank turn.

Once the robot is diagonal to the direction of translation, you can no longer rotate. This is because wheels at the left and right corners will oppose eachother. Again: I’m looking at the situation where you have left and right side coupled modules.

See attached picture and tell me if my thinking is correct or there is some shortcut to work around the directions that you cannot rotate.





Actually, on the right, the robot could still theoretically turn a little, the sidescrub of the wheels may sway otherwise. If both sets were powered opposite, a moment would be created around center.

The nice thing about the control software in this scenario is, if you tell it to turn 5 degrees, it’ll turn 5 degrees no matter how difficult it may be for a human to do so (I know I don’t have to tell you that, but figured it was worth mentioning).

I’m going to throw this solution out there, and let you figure out how to apply it to a Crab. It shouldn’t be that hard, except that I have hw to do…

What you want to do is minimize the slip velocity squared of your wheels. If you set up a set of equations that describe the slip velocity of your wheels given the wheel angles, velocities, the goal velocity vector and the goal angular velocity, you can optimize the wheel angles and speeds.

I ran through this math for a swerve drive with paired wheels like you drew, but individual motors for each wheel, and when we downloaded and ran it, we were able to translate and rotate with ease. I was able to get out a closed form solution for the correct wheel angles.

Once you do that math, the bot will discover that if you want to turn while going sideways, you want to steer by turning the modules in opposite directions. It’ll also figure out that you just skid steer when going forwards. It’ll also figure out how to mix the two modes when going at an angle. It’s a beauty to watch in action, and has no special cases. In other words, once you do the math, it just works.

I created a spreadsheet to do the math for this problem (it even has a little graph to show you what direction each wheel is turning). As the other poster said, with independent steering for each wheel, once you get the math done correctly there are no special cases and it just works.

http://www.virtualroadside.com/blog/index.php/2009/03/09/swerve-drive-model-spreadsheet/

In playing with the numbers on your spreadsheet, I ran into a couple items I had questions about.

If I put the speed to 1 (full) and the rotation to 1 (full) I get a wheel speed of 2+. I was assuming the full-scale wheel speed was from -1 to 1. Is that not the case?

In addition, when I put in Speed 1, Angle 0, Rotation 1, I get a picture where the two left wheels are 90 degrees from the supposed angle of travel shown in the overall motion. That would seem to me to be physically impossible, as it appears you are trying to literally drag those two wheels sideways.

Let me know if I’m making some incorrect assumptions.

Does a no-blind-spot limitless pot exist? We sure couldn’t find one. Our first attempt at solution was to gang together two pots so that their deadspots didn’t overlap, but they weren’t linear enough for that to work perfectly. We ended up using the absolute encoders that came in the kit, and that worked really well.

MA3 absolute encoders from us digital.

Yes, the wheel speed is -1 to 1. However, the spreadsheet/equations do not account for this at all in that implementation. Our code had a thing like this in it:


	// only need to scale if speed > 1
	if (highest_speed > 1.0 )
	{
		// scale each speed by the highest speed
		for (int i = 0; i < 4; i++)
			speeds* /= highest_speed;
	}

It would just have made the spreadsheet more complicated to implement it that way, so I left it out.

Yes, I think that is how it ends up working, and it is a bit counterintuitive. Generally speaking, I don’t think we used high values of rotation and high values of speed particularly often.

Keep in mind that you cannot travel in a straight line AND rotate at the same time without some external thing helping you compensate (for instance, a gyro), because you will always be having to adjust things relative to the robot. This is probably where part of the confusion comes from. However, with a gyro and a PID controller, you can make it go in a straight line and rotate at the same time without too much effort.

On the same website, we have our 2009 code posted which has a SwerveDrive.cpp with an implementation of this stuff there. We ended up finding an annoying bug in our implementation though (it had to do with the way that we calculated the shortest path for our servos)… but, I never updated the site with the code. Or maybe I did, I don’t recall. But its a useful starting point in any case.*

Be careful of the ma3’s. I prefer the Cherry AN8 sensors with a .5" x .125" magnet. Next year there should be more low cost absolute non contact magnetic sensors on the market.

We also very much like the MA3 or MAE3 absolute encoders from US Digital. Other than the fact that the connectors for these are encoders are difficult to connect, they have been wonderful. We used them in 2008 to measure wheel rotation on both our “Speed Racer” lapbot and our hurdling robot. On the “Speed Racer” they ran continuously at high RPMs for the rear wheels, and also at very low RPMs with precision control for the steering feedback and we had no trouble with them at all other than when our abuse of the wiring (without sufficient strain relief) led to a wire coming out of the connector. In 2009, we used the MA3 for precision control of our turret, again with no problems.

We didn’t have an MA3 on the robot this year (for the first time in 3 years), but we had great success with the US Digital encoders for our drivetrain transmissions and kicker gearbox.