View Full Version : Drive Programming
EvilDeathCrab
13-02-2003, 18:45
We're trying to implement three things. I think I've got a handle on one of them, and the two others I'm going to ask for input on.
All of this code is considering tank drive on one joystick, with PBASIC 2.5.
1) We have the wheel controlling a speed multiplier that gets added in to the calculation for the motor outputs.
2) We want to implement a "Regular drive" mode where the robot does not turn on a dime. This would involve one of the motors moving more slowly than the other.
3) We want to implement a gradual slowdown in the motor so that the robot does not come to a dead halt whenever the joystick is moved to the neutral position.
This is our current code, with #1 above enabled.
leftdrive=((p1_wheel/255)*(2000 + p1_y - p1_x + 127) Min 2000 Max 2254)-2000
rightdrive=((p1_wheel)/255)*(2000 + p1_y + p1_x - 127) Min 2000 Max 2254)-2000
For #2 I'm thinking something like this:
Wait a minute. I just had a stroke of genius... I think. Wouldn't it just be
if p1_x < 127 then
leftdrive = p1_x
rightdrive = p1_y
else
leftdrive = p1_y
rightdrive = p1_x
endif
as for #3, I'm drawing a blank. I cannot think of an easy way to code this. It would involve getting the difference between the drive (left? right? both?) and the joystick position. Maybe just a lot of IF statements.
Any input on any of the above three would be much appreciated. Thanks again!
1. Have you tested the code you posted? From reading it quickly it looks as if it would always cause your robot to go full reverse. Thanks to the integer math (p1_wheel/255) will always be 0.
2. The ((2000 + p1_y + p1_x - 127) Min 2000 Max 2254)-2000 will do this for you. If you push the joystick straight to the left/right you will turn on a dime. If you push it to the corners, you will turn while still going forward. Stuff in between will give similar results. Try dropping it in RoboEmu and take a look at the motor outputs as you move the "joystick" around.
3. Take a look at InnovationFirst's digital filter whitepaper. I believe it accomplishes exacltly what you are looking for.
--Rob
#3 you could do something like this
old_Y VAR byte
old_X VAR byte
old_Y = p1_y
old_X = p1_x
...
...
...
MAINLOOP:
gosub INPU
IF p1_y > old_Y THEN
p1_y = ((p1_y - old_Y) / 2) + old_Y
ELSE
IF p1_y < old_Y THEN
p1_y = ((old_Y - p1_y) / 2) + p1_y
ENDIF
ENDIF
' do same for p1_x
...
...
...
goto MAINLOOP
This would make the input be scaled based on the previous value instead of just jumping.
This is our motor/acceleration code from last year. It limits the maximum change in the motor values to MAX_ACC per every loop.
SAFE_ZONE CON 1000
MAX_ACC CON 10
MAX_ACC_VAL CON SAFE_ZONE + MAX_ACC
MIN_ACC_VAL CON SAFE_ZONE - MAX_ACC
speed_l = speed_l + (((p1_y - speed_l + SAFE_ZONE) min MIN_ACC_VAL max MAX_ACC_VAL) - SAFE_ZONE)
Modify it as you wish. This will accomplish tasks 1 and 3. speed_l is the speed of the left motor. Replace p1_y with your desired left motor value.
jburstein
16-02-2003, 16:27
if you're using drill motors for drive then what you can do is remove the pins from the clutch. There are plenty papers out there on how to do this. The pins prevent the motors from being backdriven, so removing them allows your robot to coast to a stop.
EbonySeraphim
18-02-2003, 23:19
I'm gonna butt in with my overcomplication philosphy -
Why is number 3 neccessary? Does slowing your robot down in code help while playing the game? I would think adjusting the motors themselves to coasting would be good enough to not stop abruptly. Or just letting the driver do it manually. It's not that hard to ease up on the joystick a little bit. Also the effort required to put it in programming requires a few things considered:
-There was some suggested code in a previous post. That code seems to slow down the turning too. So if you were turning then wanted your robot to slow down, it would keep turning while slowing down(while reducing the turn rate). I would assume that most would want to to keep its heading(or turn position) while slowing down in the current foward direction. That would require setting both motors to the same speed, and then slowing down.
-Two, there is an issue of knowing what you should be doing while slowing down. Subtracting from both motors is the simple answer. What if the robot was going backwards? You would be adding. How do you know to slow down? When p1_y is set to 127 is the simple answer. But what if you want to turn the robot while being still? p1_y is still 127 but your robot should be moving not slowing down.
To address number 2:
Why do you need special code for this? The default code can do that pretty well. rblayer address that himself, He was referring to the default code - I think.
About number 1:
I have no clue what you mean, or what you need to accomplish. Please clarify. It seems you want the wheel to set a "sensitivity" value for the joystick. Or else you want to have a wheel be able to "cruise control" your robot. There are two other wheels for the x and y axis that do this for you already.
Originally posted by EbonySeraphim
Why is number 3 neccessary?
One of the fundamental axioms of computer science is "never trust the user"; the user can screw up, an untrained person can try to use it, or the input controls could get royally screwed up. Along these lines, you shouldn't trust your gearbox integrity to the driver remembering to gradually slow down in the heat of a match. If you do and they forget, you can easily destroy gearboxes by going from full forward to full reverse over a short period of time, thus rendering your robot inoperable until you find a replacement. This is even more true if you haven't removed the backdrive pins from the drill motors.
-Two, there is an issue of knowing what you should be doing while slowing down. Subtracting from both motors is the simple answer. What if the robot was going backwards? You would be adding. How do you know to slow down? When p1_y is set to 127 is the simple answer. But what if you want to turn the robot while being still? p1_y is still 127 but your robot should be moving not slowing down.
Here's the code we use:
p1_y=p1_y_filt+(softChangeCoeff*(2000+p1_y-p1_y_filt)/100) - (20*softChangeCoeff)
p1_x=p1_x_filt+(softChangeCoeff*(2000+p1_x-p1_x_filt)/100) - (20*softChangeCoeff)
it handles all cases and doesn't require any special condition testing
There are two other wheels for the x and y axis that do this for you already.
NO! Every veteran team I know of (mine included) has nearly killed someone over moving the trim wheels. If it wasn't technically illegal, I would highly recomend a heavy dose of epoxy to keep them from ever moving.
Brian_Lim
19-02-2003, 01:11
This might be a little off topic, but since this thread is about drive programming, I will risk it.
Our drivers complain about the turning being too sensitive. It is. If you're like our team and new (we're on second year) probably will be using tank steering.
Well my solution so far was to slow down the speed of the turning, and keep the forward and backward motions at full speed.
' Drive Sensitivity Control >>> ---------------------------
if NOT (drive_R > 135 and drive_L < 129) then skip001
drive_R = 127 + ((127-drive_R)/4)
drive_L = 127 - ((drive_L - 127)/4)
skip001
if NOT (drive_R < 129 and drive_L > 135) then skip002
drive_R = 127 + ((127-drive_R)/4)
drive_L = 127 - ((drive_L-127)/4)
skip002
' End Drive Sensitivity Control >>> ----------------------
Just makes it so when turning using 1-stick control, the turning is four times slower. A necessity I think when using tank steering -- turning can be very fast with one motor going full forward and another going full reverse. Also thinking of adding a "full-speed" button on the top of the joystick so the driver can turn full speed if he wants by holding down the button.
I've gotten used to the skewed if statements, haven't upgraded to 2.5 yet, should I?
What do you think, share your code too.
907 Toronto, East York Collegiate
Brian Lim
EbonySeraphim
19-02-2003, 01:21
I understand that axiom...but in this case. I would trust the user not to screw up the robot, and also, I know our robot can handle that kind of controlling. We have ran ours in full foward to reverse, and it works fine. I'm sure its a big strain, but it can take it a few times.
About your code for the next quote - I have no clue what that does. You'd need to tell me what all of those variables mean/are set to in this or that case. Looking at the names of certain variables, it seems that code limits how much change in the x or y axis of the joystick can occur per iteration. The intial post was asking for a slowdown to stop - not a limiter. Though a limiter would get rid of code for gradually slowing down the robot.
As for the trim wheels. My team has used it and has remained safe. There is an issue of once your going forward you need to stop(meaning return to center not go into reverse). But we can control it pretty well with that. There are no plans on using it in competition, but it's useful for testing to see if our robot drifts left or right because we can be assured that there is no X axis movement on the joystick.
Originally posted by EbonySeraphim
About your code for the next quote - I have no clue what that does. You'd need to tell me what all of those variables mean/are set to in this or that case. Looking at the names of certain variables, it seems that code limits how much change in the x or y axis of the joystick can occur per iteration. The intial post was asking for a slowdown to stop - not a limiter. Though a limiter would get rid of code for gradually slowing down the robot.
The code I posted will make it so the robot gradually changes speed, as set by softChangeCoeff. Each loop it will calculate the difference between where p1_y is and where it was last loop (p1_y_filt) and decrease that interval by some percentage of it. At the end of each loop, there is a p1_y_filt=p1_y to accomplish this. If you want more detail, check out InnovationFirst's whitepapers as it is taken almost directly from there.
I understand that axiom...but in this case. I would trust the user not to screw up the robot, and also, I know our robot can handle that kind of controlling. We have ran ours in full foward to reverse, and it works fine. I'm sure its a big strain, but it can take it a few times.
That's what we though two years ago. We then proceeded to destroy three gearboxes at a single regional. After adding the above two lines of code, we had no problems whatsoever.
Remember, this thread is not about your robot or mine. EvilDeathCrab asked for help implementing this feature not whether or not it was necessary. If you want to continue this discussion, please PM or email me.
Greg Ross
20-02-2003, 22:28
Originally posted by rbayer
Here's the code we use:
p1_y=p1_y_filt+(softChangeCoeff*(2000+p1_y-p1_y_filt)/100) - (20*softChangeCoeff)
p1_x=p1_x_filt+(softChangeCoeff*(2000+p1_x-p1_x_filt)/100) - (20*softChangeCoeff)
it handles all cases and doesn't require any special condition testing
For the last couple of years, we have used the following code to filter our joystick inputs.
GAIN con 30
DIVISOR con 100
newJoystick = ((prevJoystick*(DIVISOR-GAIN)) + (newJoystick*GAIN)) / DIVISOR
I derived my algorithm by rearranging and simplifying IFI's code (basically the same as Rob's code above). I believe that as long as GAIN is chosen to be less than DIVISOR, and DIVISOR is less than 129 (to be extremely safe) mine will work perfectly.
It seems so much more straightforward than IFI's. If anyone can point out why it wouldn't work... or is less than optimal, I would appreciate you pointing it out to me.
EbonySeraphim
20-02-2003, 22:33
Who or what is IFI?
And I don't know what's going on with either your or rbayer's algorithms. I need to know what those variables are/mean.
Greg Ross
21-02-2003, 01:56
Originally posted by EbonySeraphim
Who or what is IFI?
And I don't know what's going on with either your or rbayer's algorithms. I need to know what those variables are/mean.
IFI is Innovation First Inc. (That's the company that makes the control systems for FIRST.)
Both Rob's and my code "smooth out" the joystick input. I think Rob gave a fairly understandable explanation of what the code accomplishes, so I assume what you want to know is how it accomplishes it.
In my code, newJoystick is the joystick value just read in, and prevJoystick is the "filtered" joystick calculated the last time through the loop. DIVISOR is an arbitrary number. In this case, I chose 100 because people are used to thinking in percents. GAIN is a value that is chosen to produce the desired smoothing.
On each loop, a new filtered joystick value is calculated by summing 70% of the previous value with 30% of the new joystick. (Using the GAIN and DIVISOR from my code snippet.) Does this make sense how it will smooth out the response to rapid joystick changes?
Again, GAIN must be less than (or equal to) DIVISOR. If GAIN equals DIVISOR, then no smoothing will occur because 100% of the new value will be added to 0% of the previous value. If GAIN is zero, then the filtered value will never change.
Now, one thing I left out of my snippet, is that if the new filtered value is within 10 of 127, I set it to 127. This keeps rounding errors from preventing the filtered joystick from ever returning to neutral.
Any questions?:)
EbonySeraphim
21-02-2003, 10:25
Crystal clear. Thanks for the explanation. One more question about it. I assume your filter is applied to both axes right? Not just the Y?
I knew about Innovation First. I just haven't seen taht abbreviation of their name.
Greg Ross
21-02-2003, 11:18
Originally posted by EbonySeraphim
I assume your filter is applied to both axes right? Not just the Y?
When the driver chooses single joystick steering, I filter both axes of the one joystick. Otherwise, only the two Y axes.
Jared Russell
30-03-2003, 16:16
The aforementioned digital filters can accomplish 1 and 3. For 2, why not just constrict p1_x with MIN and MAX (say, MIN 50 MAX 204)?
Obviously this method will only work for one joystick drive, but that seems to be what you are using.
Lloyd Burns
30-03-2003, 22:33
With the code presented above in this thread, you probably won't need the wheel, but, as in all things you assume, there is a catch...
Check out your wheel pot's range (use a debug on the wheel variable). It may be that you won't find 0-254!
With p#_y and p#_x, if the trim wheel is not centred, you may not get the full range either.
And for what it may be worth, remember that whatever you output to the PWMs, the Victors 883's and 884's respond to values above 230 and below 25 (approximately) with full output (= no pulses). The no-pulse, no-voltage neutral range appeared not to be symmetric about 127 either, on two that were recailbrated to "factory specs" using the Victor manual's instructions ! Hook up a light and a scope to a victor, and send out discrete values, to check this out.
I believe the default code will do exactly what you want it to do.
Instead of pshing full left push to the corners of the joystick y and x-axis. You'll get the results you want
drive_FL = (((2000 + p1_y + p1_x - 127) Min 2000 Max 2254) - 2000)
drive_FR = (((2000 + p1_y - p1_x + 127) Min 2000 Max 2254) - 2000)
:D
vBulletin® v3.6.4, Copyright ©2000-2017, Jelsoft Enterprises Ltd.