Reputation: 15519
I'm working with a program in which I am simulating a aircraft on a 2D map. I'm having some difficulty finding the direction to turn in order to hit a target bearing.
double maxHeadingChange = 10; //Maximum heading change per 100 ms
double targetHeading = 0;
double differenceHeading = Math.Abs(targetHeading - heading);
//if we need to turn clockwise
if (targetHeading > 340 || targetHeading < 30)
{
if (heading < 180)
{
if (differenceHeading > maxHeadingChange)
heading -= maxHeadingChange;
else
heading -= differenceHeading;
}
else
{
if (differenceHeading > maxHeadingChange)
heading -= maxHeadingChange;
else
heading -= differenceHeading;
}
}
else if (targetHeading > heading)
{
if (targetHeading - heading < maxHeadingChange)
heading = targetHeading;
else
heading += maxHeadingChange;
}
else
{
if (heading - targetHeading < maxHeadingChange)
heading = targetHeading;
else
heading -= maxHeadingChange;
}
//MessageBox.Show(headingDifference + "");
//just for now
//heading = targetHeading;
if(heading > 359)
heading = 0;
if(heading < 0)
heading += 360;
You can see what what I'm attempting to do is get the direction to turn, and then if the turn amount is greater than the max turn amount, turn by the max turn amount.
The issue is, that when the object is at a heading of ~10 degrees and the target is, say, 354 degrees, it sees that it should turn clockwise to hit that target, as that would be subtracting heading to hit a smaller target heading. The problem is, it's reversing the turn to clockwise as soon as the target heading passes 0 and goes to the higher heading ranges. This is causing the object to turn towards its heading (which is rotating counterclockwise, or decreasing in degrees), and suddenly reverse turn direction as soon as it passes 0.
I need to find a more efficient way of getting the turn amount in degrees (I can't simply set heading
to targetHeading
as there is some simulation in the maximum turn amount) so that it detects that to hit a heading of 350* from a current heading of 10*, to continue to subtract heading.
Sorry for the long explanation.
[Edit]: POTENTIAL SOLUTION 1
double maxHeadingChange = 10; //Maximum heading change per 100 ms
double targetHeading = 0;
double differenceHeading = Math.Abs(targetHeading - heading);
//if we need to turn clockwise
if(getTurnDir(heading, targetHeading))
{
//Turn right
if(differenceHeading > maxHeadingChange)
heading -= maxHeadingChange;
else
heading -= differenceHeading;
}
else
{
if (differenceHeading > maxHeadingChange)
heading += maxHeadingChange;
else
heading += differenceHeading;
}
//MessageBox.Show(headingDifference + "");
//just for now
//heading = targetHeading;
if(heading > 359)
heading = 0;
if(heading < 0)
heading += 360;
double hdgDiff(double h1, double h2)
{ // angle between two headings
double diff = h1 - h2 + 3600 % 360;
return diff <= 180 ? diff : 360 - diff;
}
bool getTurnDir(double hdg, double newHdg)
{ // should a new heading turn left or right?
if (newHdg > hdg)
return newHdg - hdg > 180;
return hdg - newHdg > 180;
}
Upvotes: 1
Views: 2234
Reputation: 9962
double hdgDiff (double h1, double h2) { // angle between two headings
const double diff = fmod(h1 - h2 + 3600, 360);
return diff <= 180 ? diff : 360 - diff;
}
bool isTurnCCW(double hdg, double newHdg) { // should a new heading turn left ie. CCW?
const double diff = newHdg - hdg; // CCW = counter-clockwise ie. left
return diff > 0 ? diff > 180 : diff >= -180;
}
Upvotes: 5