Compass module and how to make 355 + 10 = 5 (or 5-10 = 355)
SteveWoodrough
Posts: 190
I have a routine in my current project that aligns the BOT Heading (I've defined Heading as the direction the BOT is pointed) to a selected Azimuth (I've defined Azimuth as the users desired BOT Heading.· Heading is where its pointed, Azimuth is where I want it to go.· Once an Azimuth is input, the Bot looks at the compass, determines the Heading and pivots right or left to align the heading to the desired Azimuth.· If the Heading is 80 degrees and the desired Azimuth 90 the bot turns right.
The routine works fine for any selected Azimuth that is not close to 0/360.·
The trouble for Azimuths close 0 or 360 is my logic breaks down.· How does one do the math so that the 355 is recognized as being 10 degrees from 5 degrees the same as 15 degrees is 10 degrees from 5 degrees?
Certainly SOMEONE has solved the problem already....
Thanks...Steve
··· '---[noparse][[/noparse]AlignHeading]
Aligns BOT Heading to desired Azimuth
AlignHeading:
· Speed = speed / 10······························ ' Slows down servo movements while finding azimuth
·DO
· GOSUB Compass····································· ' Get current Heading from Compass module
· IF Heading > Azimuth+10 THEN: GOSUB LeftPivot····· ' If the Heading is greater than Azimuth· by 10 degrees turn Left
· ELSEIF Heading < Azimuth-10 THEN: GOSUB RightPivot ' If the Heading is less than Azimuth· by 10 degrees turn Right
· ENDIF
LOOP UNTIL Heading > Azimuth-10 AND Heading < Azimuth+10· ' Loop stops once BOT Heading is between +/- 10 Degrees of desired
· Speed = speed * 10···································· ' Returns BOT speed to normal
RETURN
·
The routine works fine for any selected Azimuth that is not close to 0/360.·
The trouble for Azimuths close 0 or 360 is my logic breaks down.· How does one do the math so that the 355 is recognized as being 10 degrees from 5 degrees the same as 15 degrees is 10 degrees from 5 degrees?
Certainly SOMEONE has solved the problem already....
Thanks...Steve
··· '---[noparse][[/noparse]AlignHeading]
Aligns BOT Heading to desired Azimuth
AlignHeading:
· Speed = speed / 10······························ ' Slows down servo movements while finding azimuth
·DO
· GOSUB Compass····································· ' Get current Heading from Compass module
· IF Heading > Azimuth+10 THEN: GOSUB LeftPivot····· ' If the Heading is greater than Azimuth· by 10 degrees turn Left
· ELSEIF Heading < Azimuth-10 THEN: GOSUB RightPivot ' If the Heading is less than Azimuth· by 10 degrees turn Right
· ENDIF
LOOP UNTIL Heading > Azimuth-10 AND Heading < Azimuth+10· ' Loop stops once BOT Heading is between +/- 10 Degrees of desired
· Speed = speed * 10···································· ' Returns BOT speed to normal
RETURN
·
Comments
http://forums.parallax.com/showthread.php?p=768034
Does this do what you need?
Walk me though this please.· I'm stuck at: ·
IF(theta1 > (180 + theta1)) THEN······
'how can theta 1 be greater than the same value plus 180?··Is theta 1 in brads (which could be the answer to the problem) Not likely since you are adding 180 which would logically be degrees....
··· theta1 = theta1 + 360
' likewise this gives a peculiar value unless the units are somewhere converted back to brads.
The more I think about this the more I am convinced that the most elegant solution is to·do all computation work in brads and save the conversion·from and to degrees for user interface only (since we, at least I, don't think in terms or radians but rollover math becomes automatic)
I would like to better understand your code.
Thanks...Steve
'
CalculateDesiredHeading
'This section recieves two variables in the form of
'degree values 0-360. One is the desired heading as given
'by _GetGPSHeading (above), the other is given by the compass
'Theta1 is compass heading, theta2 is GPS heading
_CalculateDesiredHeading:
· 'get the current heading
· GET 39, Word theta1
· 'theta2 is already given by previous method
· 'DEBUG "Enter the Current heading", CR
· 'DEBUGIN DEC3 theta1
· IF(theta1 > (180 + theta1)) THEN
··· theta1 = theta1 + 360
· ELSE
··· IF(theta1>(180 + theta2)) THEN
····· theta2 = theta2 + 360
··· ENDIF
· ENDIF
· IF(theta1 > theta2) THEN
··· LOOKDOWN theta1 - theta2, >=[noparse][[/noparse]55,40,20,0], headingGPS
··· headingGPS = headingGPS + 1
· ELSE
··· LOOKDOWN theta2 - theta1, >=[noparse][[/noparse]55, 40, 20, 0], headingGPS
··· headingGPS = 7 - headingGPS
· ENDIF
· DEBUG DEC1 ? headingGPS, CR, CR
· PUT 48, headingGPS
RETURN
if (heading - Azimuth // 360) > 10 then ......
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Smile ... It increases your face value!
If things were reversed, you'd have heading = 5 and Azimuth = 355. You have result = (5 - 355) // 360 = -350 and add 360 to get 10. You take the minimum of 10 and 360-10 = 350 to get the value 10.
Post Edited (SRLM) : 3/8/2009 5:45:55 AM GMT
Here is a way to scale the DEG so that it "wraps around" (i.e. 360 equals 0) to do what you want...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 3/8/2009 6:20:27 AM GMT
Thank You.· I'll try this out tonight.· One question:
You suggest a value of 46604, however, Page 101 of Smart Sensors and Applications suggests a value of 46733 for a similar conversion.· Am I splitting hairs or is there some detail I'm missing?
Best Regards
Steve
I knew you were going to ask that..
Using 46733 is equivalent to multiplying the Deg value by 182.5508 and was derived by taking 65536 and dividing it by 359 which works out to...
182.5515 ...· multiplying 182.5515 by 256 gives us 46733 .... Note: 182.5515 is the desired value·.... 182.5508 is the actual value due to rounding.
... I simply used 360 instead of 359 ...· 65536 divided by 360 works out to ...
182.0444 ... multiplying 182.0444 by 256 gives us 46603 ( <-- a little testing indicated that I needed to bump the value up by 1 ) ... rounding error since the 'desired' value of 182.0444 actually works out to 182.0430 when going the other way (46603 / 256 =·182.0430)·.· Bumping this value up to 46604 works out to 182.0469.
Using·46733 will cause a value of 360 to not·properly translate to 0 during the 16-bit roll-over.·
359 * 182.5508 = 65535
360 * 182.5508 = 65718 = 182 (<-after the 16-bit roll-over)
Instead, if you use 46604, a value of 360 will properly translate to 0
359 * 182.0469 = 65534
360 * 182.0469 = 65536 = 0 (<-after the 16-bit roll-over)
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
I understand scaling, and how to make the 16 bit values wrap around but I'm having trouble understanding how the suggested modulus operator solution·// is going to work.
The logic I'm unsuccesfully using is:
If Heading > Azimuth + 10 then Turn Left
·Else if Heading < Azimuth - 10 then Turn Right
LOOP UNTIL Heading > (Azimuth-10) and Heading < (Azimuth+10)
If my Azimuth (desired direction) is 90 degrees and the heading is 105 then the result is a left turn. Good
If my Azimuth (desired direction) is 90 degrees and the heading is 75 then the result is a right turn. Good
However, if my Azimuth (desired direction) is 0 degrees and the heading is 345 (the same 15 deg from desired)·then the result is a left turn ALL the way around.· And if the BOT overshoots to 359 degrees heading·the only recovery is again a long slow turn to the left.· Seems to me there ought to be a clever way to write the steering logic to accomodate the special case when the Azimuth is close to 0.
Thanks for your help and consideration.·
NumDegrees has the number of degrees needed to turn and whichDir tells you whether to turn clockwise or counter-clockwise.
HTH
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
Post Edited (FearTurtles) : 3/24/2009 3:18:22 PM GMT
What you can do is to test to see if the ten degree band lies on the 0 degree boundary, and make a special case for if it does. The (revised) code that I posted does that.
Modulus just returns the remainder (r) of an integer division.
@Turtles
You can format your code nicely with the [noparse][[/noparse] code ] tag. As for what would work, again, take a look at the code I posted. It sets a bit and an amount.
Post Edited (FearTurtles) : 3/24/2009 3:19:19 PM GMT