Question

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;
}
Was it helpful?

Solution

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;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top