Loading...
Pages: [1]   Go Down
Author Topic: Help me break this mental block--degrees to heading  (Read 302 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For some reason I simply can't get past this simple problem. I'm using a compass to maintain  heading hold. When I press a button it reads the current value in degrees (int holdHeading) and then steers to maintain that heading. Since the compass output is degrees I need to convert each new reading (int currentHeading) into a servo position (int headingError) to steer back to the heading. Simple enough, but when you get in the vicinity of 360 degrees things get messy.

If holdHeading is 359 and currentHeading is 10 then headingError should be 11
if holdHeading is 10 and currentHeading is 359 then headingError should be -11

more simply:
is holdHeading is 180 and currentHeading is 170 then headingError should be -10
if holdHeading is 170 and currentHeading is 180 then headingError should be 10

I'm going to restrict the servo movement to some value like 60 to 120 with 90 being the centered position, but I know how to do that. It's this silly degrees thing that driving me nuts. I seem to have a mental block preventing me from solving something that seems pretty simple.
Logged

Offline Offline
God Member
*****
Karma: 3
Posts: 992
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If holdHeading is 359 and currentHeading is 10 then headingError should be 11
if holdHeading is 10 and currentHeading is 359 then headingError should be -11
The calculations are easier to deal with if you convert heading into the +/- 180 degree range. 359 (from your example) then becomes -1 and so headingError is a simple difference:

headingError = holdHeading - currentHeading
headingError = -1 - 10 = -11
headingError = 10 - (-1) = 11

For display and input however you may want to keep the 0-360 range and convert accordingly, but stick to -180 to 180 internally.
Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 129
Posts: 10383
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


headingError = currentHeading - holdHeading

Negative headingError means go right.

Positive headingError means go left.

Quote
If holdHeading is 359 and currentHeading is 10 then headingError should be 11

headingError = currentHeading - holdHeading
headingError = 10 - 359
headingError = -349

From 10 degrees go right 349 degrees to get to 359.  This is correct.  Obviously, you'd prefer to take the shorter route.

Code:
if ( headingError < -180 )
{
  headingError = 360 + headingError;
}

headingError = currentHeading - holdHeading
headingError = 359 - 10
headingError = +349

From 359 degrees go left 349 degrees to get to 10.  This is correct.  Obviously, you'd prefer to take the shorter route.

Code:
if ( headingError > +180 )
{
  headingError = 360 - headingError;
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you, thank you. I was literally banging my head against the wall.
Logged

UK
Offline Offline
Tesla Member
***
Karma: 100
Posts: 6784
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
if ( headingError > +180 )
{
  headingError = 360 - headingError;
}

Don't you mean headingError = headingError - 360?
Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 129
Posts: 10383
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Yup...

Code:
if ( headingError < -180 )
{
  headingError = headingError + 360;
}

if ( headingError > +180 )
{
  headingError = headingError - 360;
}
Logged

UK
Offline Offline
Tesla Member
***
Karma: 100
Posts: 6784
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This feels like the sort of situation where expressions like this come in handy:

heading = ((heading + 360 + 180) % 360) -180;
Logged

Offline Offline
God Member
*****
Karma: 3
Posts: 992
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Yup...

Code:
if ( headingError < -180 )
{
  headingError = headingError + 360;
}

if ( headingError > +180 )
{
  headingError = headingError - 360;
}

Why insist on making this a lot more difficult than it is. Convert to -180 +180 and you're good to go.

degrees-to-turn = desiredHeading - currentHeading

+ > turn right
- > turn left

Always shortest turn, no if's - done.
Logged

Pages: [1]   Go Up
Print
 
Jump to: