Some math help
Jonathan
Posts: 1,023
Hi All,
I am, as I often am, stumped on a little piece of math. I'm hoping that someone can help me out here, what I need to do is pretty simple, but I juts can't get it to work.
I am working on getting my robot to follow a compass heading. Heading is a integer from 0 to 359 obtained from the compass. Bearing is the desired direction to follow. What I want to do is compare bearing Vs heading and come up wit two pieces of data.
a) How many degrees do we need to turn to face the bearing? This allows us to turn quickly if the bearing is 15 degrees or greater than heading, then turn slowly when we approach the correct heading.
Which direction is is fastest (closest) to turn. THe formula below is supposed to return a 0 for CCW and a 1 for CW.
What I have been trying is here:
numDegrees:= || (bearing - heading + (540//360)-180)
whichDir := (bearing - heading+ 360) / 360
What I can't do is get it to cross the 0 degree point properly. If not crossing 0 it works fine.
Any math whizzes out there?
Thanks!
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
I am, as I often am, stumped on a little piece of math. I'm hoping that someone can help me out here, what I need to do is pretty simple, but I juts can't get it to work.
I am working on getting my robot to follow a compass heading. Heading is a integer from 0 to 359 obtained from the compass. Bearing is the desired direction to follow. What I want to do is compare bearing Vs heading and come up wit two pieces of data.
a) How many degrees do we need to turn to face the bearing? This allows us to turn quickly if the bearing is 15 degrees or greater than heading, then turn slowly when we approach the correct heading.
Which direction is is fastest (closest) to turn. THe formula below is supposed to return a 0 for CCW and a 1 for CW.
What I have been trying is here:
numDegrees:= || (bearing - heading + (540//360)-180)
whichDir := (bearing - heading+ 360) / 360
What I can't do is get it to cross the 0 degree point properly. If not crossing 0 it works fine.
Any math whizzes out there?
Thanks!
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
Comments
cb = current bearing
ds = shortest distance
diff = abs(b-cb)
if diff < 180 ds = diff else ds = 360 - diff
if diff < 180 and b > cb turn right
if diff < 180 and b < cb turn left
if diff > 180 and b > cb turn left
if diff > 180 and b < cb turn right
return trip if B < 180 opposite = b + 180 else oppostie = b - 180
Thanks!
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
Rokicki I think there's a typo in the above code.
It should probably be
Rokicki's code restricts 'diff' to the range of -180 to 180 degrees. Conveniently, this range is perfect to feed into a servo loop. (basically what the last two 'If' statements do)
Try this method in your code, it should:
A single line formula, and a small case statement
Please give this code a try, i'd like to know if it works well/works at all. It'd come in handy for a R/C project of mine involving a small·r/c airplane, possibly a small r/c helicopter.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Definetly a E3 (Electronics Engineer Extrodinare!)
"I laugh in the face of imposible,... not because i know it all, ... but because I don't know well enough!"
is the same as
fsrl := des_brg - cur_brg
And does not deal with the zero crossing.
I finally setup a simple test program. I found that the whichDir statement *is* working properly. The following code *seems* to work under all conditions, but I would like if someone else tried it.
See anything obvious I am missing?
Thanks!
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
Here is my suggestion:
rotation := ((bearing - heading + 540) // 360) - 180
where the desired bearing and the current heading are in degrees from 0 to 359, and the rotation is degrees from -180 to +179. The direction is the sign bit.
Let me explain why it works (assuming it does work--I'm open to counterexamples!)? It depends on a particular shift of the coordinate system.
The first graph below shows in red the rotation required when the current heading has a particular value near 100 degrees, as a function of the desired bearing on the x axis from 0 to 360. Note that the rotation required is zero when the desired heading equals the current bearing. If the desired bearing is for example 170 degrees, then it takes a positive rotation of +70 degrees. Very simple graph, slope 1. Should be easy, right? The hard part comes with the discontinuity, which in this graph occurs at 280 degrees, and where the rotation required suddenly jumps from +180 to -180. The gymnastics required in the formulae suggested here have been wrapped up in how to account for the discontinuity. Note the extension of the red line on the lower left.
The second graph shows the same red line, but with the coordinate system shifted to the left. Now it is really easy, because there is no discontinuity! The coordinates are shifted by the amount that puts the current bearing precisely at 180 degrees, and the shift is
(Yj' = 180 - Yj).
The same coordinate shift is applied to the desired bearing,
Yk' = Yk + (180 - Yj)
That could have negative values, so to put it within the interval 0 to 360 we write:
Yk' = (Yk + (180 - Yj) + 360) mod 360
... = (Yk - Yj + 540) mod 360
Then to find the rotation, we have to subtract the shifted value of Yj', which is precisely and by choice 180 degrees.
Yk' = (Yk + (180 - Yj) + 360) mod 360 - 180
In spin:
rotation := ((Yk - Yj + 540) // 360) - 180
Note that 540// 360=180, so you are really back to rotation = Yk-Yj. But the weird thing is that the legerdemain moves it to the only frame of reference that zaps the discontinuity.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
Now that i think about it, your right about the formula, i ran it through my test calculations and it worked the same when the result was passed through the case statement.
Johnathan,
I appologize that my block 'o code didn't work, as i would have had to develope a simulation object to test this code.
It was just a bit of brainstorming i did in about 15 minutes.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Definetly a E3 (Electronics Engineer Extrodinare!)
"I laugh in the face of imposible,... not because i know it all, ... but because I don't know well enough!"
CMPSUB is good for doing this kind of stuff stuff in ASM.
You were right in your PM, I HAD misplaced the brackets on the numDegrees formula. One thing about your statement above is that it can return a negative number, so I changed it to:
numDegrees := || (((heading-bearing+540)//360)-180)
And it seems to work perfectly. Thanks so much, I was going crazy because I was sure I had it working before in Spin, and it was working on a calculator.
As to the direction to turn, I am still trying to understand your post. I still have a feeling that the original should work, or at least be able to made to work. I can't make it go on the calculator though, so it is more than just a bracket issue. However I just need to get something working and get past this issue, so I'm going to continue to try making your example work.
Rinks,
Hey, no worries! thanks for taking a stab at it, and I by no means expect a warranty along with any suggestions that you are kind enough to offer!
Thanks for all the help, folks! These things always stump me. As soon as I crack whichDir I can·get back to the meat of the matter.
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
Re-reading your post I realized that you had intentionally left out the ABS because the sign bit is the direction neede to turn. Duh! Anyway, I just did this, and it seems to work!!
numDegrees := (((heading - bearing + 540)//360)-180)
whichDir := numdegrees >> 31
numDegrees := || numdegrees
Whoo hoo! Thanks!
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
Thanks again
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
steerAngle= ( ( 540+Bearing) - Heading)) // 360
which yields a number between ) and 360, where 0 was steering hard right, 360 was steering hard left. and 180 was straight ahead.
I was Ackerman steering with a servo, so I wanted a number that was continous, not one with a positive and negative term.
A pulseout value for a servo could be as simple as (570+SteerAngle) but will probably need a little scaling. (180 gives a value of 750, which was straight ahead)
You'll Probably have to do some PID P term at least, to adjust to your robot's geometry.
If you are skid steering, steer right for numbers under 180 whith something like (180-SteerAngle) and for numbers over 180, steer left with (Steerangle-180)
In both these cases the left and right might be reversed in the formulas, depending on your robot's geometry.
Hope this helps
whoops, can't copy my own formulas. I think it's right now.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Post Edited (Larry) : 6/30/2007 8:54:53 PM GMT
Graham
rose = %1010000000000000000000000000111
The subsequent calculation has to determine the spread of values, which in in the above case would be 6, because the circle wraps around from msb to lsb and the hole counts as part of the spread. Actually, any number of holes count as part of the spread, and the object is to compute the minimum over the circle. Here is the snippet I came up to do that. I still wonder if it could be done without the repeat. Can anyone think of a way? The repeat rotates the current value of rose into all 32 positions and tracks the minimum value returned by the encode operator |<.
There is a class of problems on a circle like this. In robotics it might be to find the widest open gap detected by a rotating turrent.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
I can already see some applications for the formula in your last post. So too with Larry's. Of course, I can't think of any way to do it without the repeat. But do let us know if it comes to you in a stroke of brilliance.
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot