Spoiler Alert: It works! Dizzy bat, anyone?
This post is basically a context rich requirements document for the next evolutionary stage of our software. That means it contains some rambling thoughts on what we need to do -- and these notes might turn out not to be very accurate. The disclosure is now out of the way, and we can move on.
The last post discussed a "botMotors" class. This class allows us to create methods and "variables" of type botMotors and move commands for 4 motors plus a status in one variable or return statement.
That becomes important when we want to use mecanum wheels (the link goes to the Wikipedia page) because while forward and backward are just the same, these wheels provide the ability to slew or crab left and right. You'll see this as "strafe" in other print, but that term seems both too violent insufficiently accurate for our needs.
There are three areas we'll need to address:
1) Control of the crabbing.
2) Human interface - what control movements result in what robot movements
3) Some more sophisticated possibilities
Control of Crabbing:
With the mecanum wheels, if you drive the left wheels the same way as the right wheels, then you can turn or go straight just like today. BUT, if you make one set of wheels turn "inward" or toward each other, and the other set of wheels turn "outward" or away from each other, then the robot will move side to side.
If we think of the robot as pointing north, what we've described so far accounts for moving it North, South, East, and West. It stands to reason that we can make it move other directions, like North -East, by varying the power to one or more wheels.That is, instead of thinking of them in sets of two (left/right, turning inward/turning outward), we figure out what combinations are necessary for movement in any arbitrary direction between 0 and 90 degrees. The other quadrants should be reflections of this so there's no need to figure it out for the whole circle.
We can do this a couple of different ways. We can either use trigonometry in our java code to make the calculations on the fly or calculate a basic set of vectors and add them together to get the result we need. For example, we can generate a table like this by using cosine and sine to calculate the x & y motion needed for any given crab angle then summing the vectors to figure out the left-front through right-rear relative power settings:
Notes |
fwd: all 100% |
each step is pi/16 radians |
crab straight |
going back - all at -100% |
crab left |
... and fwd again at 100% |
We'll have to normalize the power so all wheels are between -1.0 and 1.0, of course.
Each x = COS('Heading (in radians)' ) and each y is the corresponding SIN. Each front motor is either (x+y) or (x-y), I think. I haven't really hammered this out yet. Either way the actual setup will depend on how the wheels are installed on the robot.
I've run this through 360 degrees just to sanity check, and through one full cycle, our front and rear power commands seem like they may look like this (heading is on the right axis ... and these power settings are NOT yet normalized to +/- 1):
Or I might have badly miscalculated things and that's all wrong. It looks right at 0, 90, 180, 270, and 360 degrees, but we'll give it a little more thought. The good news is that it isn't as complicated as it looks.
Sophisticated combinations
At this point, I expect we'll end up with an array like the table above, and do a little interpolation if we land between values. Due to the expected slop in our mecanum system (friction on the rollers, friction on the playing field, and some variability in motors keep this from being super precise), we can probably get away with 16 or 32 rows on our lookup table and won't need 360. That will be part of the voyage of discovery :-). Here's a simpler view of what I expect after things have been normalized[1] to +/-1. Will think about it some more, then code it up this evening or tomorrow AM.
To summarize: the numbers as presented should be a good starting point for using the mecanum wheels on their own. When we want to add a turn or other rotational motion to them, we're going to start adding numbers together to make that happen. But by thinking about it first as a set of vectors, we should be able to integrate that capability into this without a lot of anger management sessions.
That leaves us with the human interface. For both driver and autonomous modes, we need to think of what data needs to be moved from one place to another. For example, what stick inputs translate to what motor values, and how do we make this more or less intuitive to the driver. The immediately obvious idea is to use the Y axis of the drive joysticks to run fore/aft in tank mode just like before, then use the X axis as "crab vectors" ... the sum of the vectors of the two sticks ought to map reasonably well to the vectors as sent to the individual motor controls. Figuring out what this mapping is probably ought to be really early on our to do list, because we won't know if it works if we don't know what we expect it to do. I want to allow the drivers all kinds of freedom, but I think they should expect to bang the sticks to the left and see the 'bot crab off that direction, same for the right. It gets much more interesting when you start combining that with normal y-axis inputs ... which takes us back to the vectors from the "Sophisticated Combinations" paragraph.
I expect we'll see some left/right, front/back mixups, and other things like that, but on the whole, this promises to be a lot of fun.
H
[1] by normalized, I'm meaning something like this: https://en.wikipedia.org/wiki/Unit_vector
basically just restricting the min and max to -1 and +1, and keeping all the other things to the same proportions they had originally. Again, I *think* this will suit our needs.
Been thinking about this a bit more.... What if we considered using the left stick to give most of the 'tank' like behavior. Then used the right stick to give the '360' crab behavior. Initially these could be an either or thing. If the controller sees input on the left stick ignore right stick. Long term the students could add weighting and average out the vectors for each stick.
ReplyDeleteAnother thought for the long term. (Or later this morning if I can motivate Katherine.) On a single stick the arc tangent of the X and Y should be the angle of the desired direction of the robot. You could either calculate this on the fly or use a table like you mentioned above. But if you calculate the length of the hypotenuse you could use that to scale the power to the wheels. Full power is stick fully extended, which should always return a hypotenuse of 1. Anything less just scale the power values by that number.