View Full Version : How to go about making tankDrive and ArcadeDrive methods
kinganu123
18-05-2011, 10:46
So I'm a new programmer for my team and we program in Java. I already know Java programming language and i get the basics of FRC robotics programming. However our main programmer wants me to be able to make the tank drive and arcade drive methods instead of just knowing how to call them. I'm not allowed to look at the methods FRC provides so I was wondering whats the best way to go about making those methods on my own
I'm not allowed to look at the methods FRC provides so I was wondering whats the best way to go about making those methods on my own
Before anyone answers, how much help are you "allowed" to solicit from contributors here on Chief Delphi ? We want to help, but we don't want to interfere with the assignment you've been given.
Right, see what you can figure out. Read the sticks and turn on motors indivdually. Start with tank drive.
Start by looking into the Jaguar or Victor classes respective to the speed controllers you have.
A hint, tank drive directly maps joysticks to speed controllers.
Arcade drive is a little trickier, but here's a hint. To turn the robot you send a positive value to one speed controller and a negative to the other. To go in a direction you send the same value to both controllers. Remember your max value is 1 too, so you may want to consider that if you really want to impress :).
Jared Russell
18-05-2011, 13:02
When doing these sorts of problems, I like to make a table. What are my inputs? (Joystick positions). What are my outputs? (Motor PWM values). What are the "points" for which I have well behavior (for example, when your sticks aren't being touched you probably want to set your motors to 0 speed)?
Once you have this data down in front of you, the relationship between inputs and outputs can be analyzed and you can derive mathematical functions relating them.
kinganu123
18-05-2011, 13:44
Before anyone answers, how much help are you "allowed" to solicit from contributors here on Chief Delphi ? We want to help, but we don't want to interfere with the assignment you've been given.
im pretty sure you can help me in any way other than actually giving me the code. The reason ive gotta do this is so I can mod the FRC classes should the need ever arise
kinganu123
18-05-2011, 13:46
Start by looking into the Jaguar or Victor classes respective to the speed controllers you have.
A hint, tank drive directly maps joysticks to speed controllers.
Arcade drive is a little trickier, but here's a hint. To turn the robot you send a positive value to one speed controller and a negative to the other. To go in a direction you send the same value to both controllers. Remember your max value is 1 too, so you may want to consider that if you really want to impress :).
We have four motors, would it still be the same for arcade drive and tank drive that way?
We have four motors, would it still be the same for arcade drive and tank drive that way?
Yes, what you will want to do is pair the right speed controllers and left speed controllers together. So anytime you send values to them they should be the same.
L1 left 1 (Jaguar)
R1 right 1
So S1 = speed 1 (variable)
S2 = Speed 2
L1 S1 R1 S2
L2 S1 R2 S2
im pretty sure you can help me in any way other than actually giving me the code. The reason ive gotta do this is so I can mod the FRC classes should the need ever arise
Tank drive is pretty straightforward. To go straight forward, drive the left and right wheels at the same (forward) speed. To turn right, add a little speed to the left wheel(s), and subtract the same amount from the right wheel(s). To turn left, add a little speed to the right wheel(s), and subtract the same amount from the left wheel(s)
The above is actually a generic description for a skid steer vehicle.
For a "tank drive" interface to a skid-steer vehicle (where you are using only the Y axis of each of two joysticks) it is even easier. Just control the left wheel(s) with the left joystick Y-axis, and the right wheel(s) with the right joystick Y-axis.
Tank drive is pretty straightforward. To go straight forward, drive the left and right wheels at the same (forward) speed. To turn right, add a little speed to the left wheel(s), and subtract the same amount from the right wheel(s).
Now the trick is to try to figure out how to make it scale correctly. When you add together 2 values the max # you can see is 2 but the max value you can set is 1. I will let you know though that dividing by 2 is not the answer because then full speed ahead is only a .5 :).
sorry this is in reference to an arcade drive.
are you driving this via joystick or via autonomous?
also you may want to create a drive class that contains 2 functions arcade drive and tank drive.
encapsulating the drive within its own class is good practice.
kinganu123
18-05-2011, 17:29
are you driving this via joystick or via autonomous?
also you may want to create a drive class that contains 2 functions arcade drive and tank drive.
encapsulating the drive within its own class is good practice.
I am driving via joystick but I dont have the robot or a driver station on my personal laptop to actually test it so thats kind of a problem, and ya my assignment is to pretty much make the drive class with those methods and when I know trig i gotta add mecanum to it, but thats next year.
I am driving via joystick but I dont have the robot or a driver station on my personal laptop to actually test it so thats kind of a problem, and ya my assignment is to pretty much make the drive class with those methods and when I know trig i gotta add mecanum to it, but thats next year.
Actually you can do mecanum without trig. Just like the arcade drive is figuring out how to sum up the motor in the right way based on the joystick input. It certainly isn't an overly efficient mecanum drive as scaling is an issue, but you can get the idea of it. I think its actually a good problem solving task to do the mecanum without trig :).
Actually doing an encoder based mecanum drive could be done without trig too. Its only when you start going field centric that you really need trig.
Also the trig isn't too bad either, you could find it online. Just treat the left joystick as a circle and find the angle and distance from center based on the 2 values.
x^2 + y^2 = magnitude^2
angle = arctan(y/x)
soh cah toa
sin = opposite over hypotenuse
cos = adjacent over hypotenuse
tan = opposite over adjacent
cos(angle)*mag = y mag
sin(angle)*mag = x mag
give all 4 motor the y mag
top right back left y mag + x mag
top left back right y mag - x mag
i may have the side flipped not sure :)
programming a mec via trig is a lot easier than doing it without it, that why i suggest you try doing it by taking all joystick values / 2 and setting the motors via that. its def possible. for scaling reasons i'd leave out rotation at first.
if your feeling really ambitious let a gyro set the rotation value and you just set the x and y.
kinganu123
18-05-2011, 18:09
Actually you can do mecanum without trig. Just like the arcade drive is figuring out how to sum up the motor in the right way based on the joystick input. It certainly isn't an overly efficient mecanum drive as scaling is an issue, but you can get the idea of it. I think its actually a good problem solving task to do the mecanum without trig :).
Actually doing an encoder based mecanum drive could be done without trig too. Its only when you start going field centric that you really need trig.
Also the trig isn't too bad either, you could find it online. Just treat the left joystick as a circle and find the angle and distance from center based on the 2 values.
x^2 + y^2 = magnitude^2
angle = arctan(y/x)
soh cah toa
sin = opposite over hypotenuse
cos = adjacent over hypotenuse
tan = opposite over adjacent
cos(angle)*mag = y mag
sin(angle)*mag = x mag
give all 4 motor the y mag
top right back left y mag + x mag
top left back right y mag - x mag
i may have the side flipped not sure :)
programming a mec via trig is a lot easier than doing it without it, that why i suggest you try doing it by taking all joystick values / 2 and setting the motors via that. its def possible. for scaling reasons i'd leave out rotation at first.
if your feeling really ambitious let a gyro set the rotation value and you just set the x and y.
Lol Ill save mecanum for later on though, so ya i kinda got the logic behind tank, what about arcade?
Lol Ill save mecanum for later on though, so ya i kinda got the logic behind tank, what about arcade?
Rotation is handled as plus or minus
Left is y. - x
Right is y+ x
They may be flipped
Once again remember scaling
programming a mec via trig is a lot easier than doing it without it,
FR = -Y - X -Z
FL = -Y +X +Z
RR = -Y +X -Z
RL = -Y -X +Z
How does trig make the above any easier ?
for scaling reasons i'd leave out rotation at first.
Scaling is straightforward. Find the max absolute value of the 4 wheel speed commands above. If that max value exceeds the max command you want to send, then divide all 4 wheelspeeds by it.
kinganu123
18-05-2011, 19:54
Rotation is handled as plus or minus
Left is y. - x
Right is y+ x
They may be flipped
Once again remember scaling
That doesnt work for moving the joystick to the corners or towards them. thats the hardest part of arcade and ive been trying a bunch of algorithims but none of them can be used for more than one specific coordinate
That doesnt work for moving the joystick to the corners or towards them. thats the hardest part of arcade and ive been trying a bunch of algorithims but none of them can be used for more than one specific coordinate
well you could do an if > 1 output 1
or a divide by 2
those should work somewhat.
the best case would be to use trig even for an arcade drive to ensure max values
That doesnt work for moving the joystick to the corners or towards them. thats the hardest part of arcade and ive been trying a bunch of algorithims but none of them can be used for more than one specific coordinate
Look at this diagram (http://web.goodrobot.com/blog/wp-content/uploads/2009/09/tankdrive.png), and see if you can figure out what the left and right motor speeds should be for the red, green, and blue dots. If you can do that, you should be able to design an algorithm to compute the wheel speeds for any joystick position.
Some drivers find this (http://www.chiefdelphi.com/forums/attachment.php?attachmentid=10706&stc=1&d=1305810391) behavior more intuitive.
That doesnt work for moving the joystick to the corners or towards them. thats the hardest part of arcade and ive been trying a bunch of algorithims but none of them can be used for more than one specific coordinate
What do you mean by "doesn't work" and "one specific coordinate" ? Please post a couple of example calculations to illustrate the problem you are encountering.
What do you mean by "doesn't work" and "one specific coordinate" ? Please post a couple of example calculations to illustrate the problem you are encountering.
I assume it has something to do with the math being done. If you pass a value >1 or <-1 i'm pretty sure the robot does nothing.
Also knowing whether or not iterative or simple robot are being used is helpful too. I prefer simple robot as I like to have control over initialization and my loops.
My interest has been peaked by approaching the arcade drive similar to a mecanum by using arc functions. however arc estimators will have to be coded up as only standard sin cos and tan are supported
kinganu123
19-05-2011, 23:43
I assume it has something to do with the math being done. If you pass a value >1 or <-1 i'm pretty sure the robot does nothing.
Also knowing whether or not iterative or simple robot are being used is helpful too. I prefer simple robot as I like to have control over initialization and my loops.
My interest has been peaked by approaching the arcade drive similar to a mecanum by using arc functions. however arc estimators will have to be coded up as only standard sin cos and tan are supported
I was thinking it would be easier in simpleRobot as well however since we use iterative for our robot code he wants me to make one that will work with iterative.
kinganu123
19-05-2011, 23:48
What do you mean by "doesn't work" and "one specific coordinate" ? Please post a couple of example calculations to illustrate the problem you are encountering.
For example, i was trying to figure out how i would get the left motors to stay off and the right motors to stay full on when the joystick is at teh top left corner(X,Y) = (-1,1), and see if that code works for all quadrants. I used y+X for the left wheels and Math.max(X,Y) for the right wheels. However that algorithim doesnt work for all four quadrants so Ive made a big branching if-else so I have a different algorithim for each quadrant of the cartesian plane and another if else for if the joystick is on the x or y axis.
It looks pretty inefficient but without trig i dont think theres another way to do it.
arc estimators will have to be coded up as only standard sin cos and tan are supported
Not sure what you mean by the above. Java, C++, and LabVIEW all support the atan2 function.
My interest has been peaked by approaching the arcade drive similar to a mecanum by using arc functions.
There's nothing wrong with exploring that, it's a great way to learn. But what is the basis for the following statements:
the best case would be to use trig even for an arcade drive to ensure max values (http://www.chiefdelphi.com/forums/showpost.php?p=1062357&postcount=17)
programming a mec via trig is a lot easier than doing it without it (http://www.chiefdelphi.com/forums/showpost.php?p=1062293&postcount=12)
For example, i was trying to figure out how i would get the left motors to stay off and the right motors to stay full on when the joystick is at teh top left corner(X,Y) = (-1,1), and see if that code works for all quadrants. I used y+X for the left wheels and Math.max(X,Y) for the right wheels. However that algorithim doesnt work for all four quadrants so Ive made a big branching if-else so I have a different algorithim for each quadrant of the cartesian plane and another if else for if the joystick is on the x or y axis
Try this: Use L=Y+X and R=Y-X.
Then limit L and R to the range -1..+1. Spoiler hint at bottom.
If you do this, you should get these values:
X Y L R
0 1 1 1
1 1 1 0
1 0 1 -1
1 -1 0 -1
0 -1 -1 -1
-1 -1 -1 0
-1 0 -1 1
-1 1 0 1
The above table matches this diagram (http://web.goodrobot.com/blog/wp-content/uploads/2009/09/tankdrive.png).
If the above table is not the result you are seeking, post a table showing the result you want.
Warning: spoiler follows:
Hint:
for limiting (clipping), do this:
if(L>1) L=1; else if(L<-1) L=-1;
if(R>1) R=1; else if(R<-1) R=-1;
instead of clipping, you could normalize instead. you'll still get the same table as above, but intermediate joystick results will be slightly different:
max=fabs(L); if(fabs(R)>max) max=fabs(R);
if(max>1){ L/=max; R/=max;}
if you want to get the exact same results as the WPI library functions for all intermediate joystick settings, a slightly different algorithm will be necessary... but still no trig required.
See attached chart.
The first column is for the simple L=Y+X, R=Y-X with normalization. The second column is the same as the first except it uses clipping instead of normalization. The third column is a slightly (very slightly) more complicated algorithm which I believe gives the same results as what you get from the WPI library (and may indeed even be mathematically identical... I haven't checked).
The first 8 rows of the chart are the values around the perimeter of the large square in this diagram (http://web.goodrobot.com/blog/wp-content/uploads/2009/09/tankdrive.png), starting at the top center and going around the square clockwise. Notice that all three algorithms give the same values for these points.
The remaining rows show the outputs for intermediate joystick values. The three algorithms differ somewhat for these inputs.
None of these algorithms uses any trigonometry.
Not sure what you mean by the above. Java, C++, and LabVIEW all support the atan2 function.
There's nothing wrong with exploring that, it's a great way to learn. But what is the basis for the following statements:
the best case would be to use trig even for an arcade drive to ensure max values (http://www.chiefdelphi.com/forums/showpost.php?p=1062357&postcount=17)
programming a mec via trig is a lot easier than doing it without it (http://www.chiefdelphi.com/forums/showpost.php?p=1062293&postcount=12)
How do you access atan2? Its not included in the stripped down Math util.
A perfect arcade drive would map every point within a circle to a set of motor outputs. Using trig you can program for every case using one formula.
Same is true for the mecanum drive. By knowing the resulting vector and magnitude you want, you can program a whole mec drive with a couple calculations.
The code would be a lot cleaner and more efficient, as every point on the circle formed by the joystick would map to a distinct ideal set of motor outputs. (as opposed to using a scaling algorithm.)
Joe Ross
20-05-2011, 15:45
How do you access atan2? Its not included in the stripped down Math util.
http://www.chiefdelphi.com/forums/showthread.php?t=87052&highlight=atan2+java
How do you access atan2? Its not included in the stripped down Math util.
See Joe's post (http://www.chiefdelphi.com/forums/showpost.php?p=1062760&postcount=27).
A perfect arcade drive would map every point within a circle to a set of motor outputs.
The joystick makes a square, not a circle. The algorithms mentioned here (http://www.chiefdelphi.com/forums/showpost.php?p=1062752&postcount=25) map every point in the square to a set of left/right motor outputs.
Using trig you can program for every case using one formula.
You don't need trig to do this.
Same is true for the mecanum drive. By knowing the resulting vector and magnitude you want, you can program a whole mec drive with a couple calculations.
FR = -Y -X -Z
FL = -Y +X +Z
RR = -Y +X -Z
RL = -Y -X +Z
How does trig make the above any easier ?
The code would be a lot cleaner and more efficient, as every point on the circle formed by the joystick would map to a distinct ideal set of motor outputs. (as opposed to using a scaling algorithm.)
How does using trigonometry make the above mec code any "cleaner", or "more efficient"? The above code is kinematically correct (http://www.chiefdelphi.com/media/papers/download/2722), even after normalization.
See Joe's post (http://www.chiefdelphi.com/forums/showpost.php?p=1062760&postcount=27).
The joystick makes a square, not a circle. The algorithms mentioned here (http://www.chiefdelphi.com/forums/showpost.php?p=1062752&postcount=25) map every point in the square to a set of left/right motor outputs.
You don't need trig to do this.
FR = -Y -X -Z
FL = -Y +X +Z
RR = -Y +X -Z
RL = -Y -X +Z
How does trig make the above any easier ?
How does using trigonometry make the above mec code any "cleaner", or "more efficient"? The above code is kinematically correct (http://www.chiefdelphi.com/media/papers/download/2722), even after normalization.
thanks for the feedback.
I guess if you approach the js as a square, you are def right. I personally always approach the joystick as a circle as the points you can get on a joystick can be easily mapped to either a circle or a square.
The way you solve the grid seems to be a case statement. Personally I would rather have one equation that gets the value based on heading and magnitude.
Again your algorithm certainly solves the problem well and I do not believe it would have any dead spots. But i guess we approach the joystick from 2 different views: a square vs a circle. I believe both approaches to be correct.
approaching it as a square requires normalization where as approaching it as a circle does not (unless we start looking at mecanum where factoring in rotation requires normalization )
The way you solve the grid seems to be a case statement
No, its not a case statement. It's simply this:
L = Y+X
R = Y-X
I can't imagine anything simpler. It works for all 4 quadrants. No case statement is necessary.
Personally I would rather have one equation that gets the value based on heading and magnitude.
If that's your personal choice I cannot argue. But what "one equation" are you referring to? To get heading and magnitude, you need two equations right there. Then you have to calculate the wheel speeds from those.
But i guess we approach the joystick from 2 different views: a square vs a circle. I believe both approaches to be correct.
I also believe both approaches are correct.
approaching it as a square requires normalization where as approaching it as a circle does not
If your X,Y values are (1,1) then your magnitude calculation will give 1.4 and you will need to clip or normalize... unless you aren't using the magnitude but converting it back to X and Y values... in which case I'm puzzled why you converted them to polar in the first place.
Would you be willing to post your code ? I'd like to understand better what you are saying.
vBulletin® v3.6.4, Copyright ©2000-2017, Jelsoft Enterprises Ltd.