Rotate to a specific angle?

So my question is more to do with logic/maths than programming. I m trying to rotate a robot to a certain degree. Basically I had been using quite a blunt method that has a glitch. The orientation of the robot is obtained from odometry readings. So the robot rotates 0-360 in the anti clockwise direction where any angle greater than 360 is clipped or wrapped around. eg 370 degrees is 10 degrees. So I m using the following method where theta_angle is the angle being made by the robot.

void leftBy(float left_By)
{
  prevAngle = theta_angle;
  targetAngle = prevAngle + left_By;
  boolean clip_L  = clipL();

while(motorsMovingLeft)
{
  odometryRecording();

    if(clip_L)
    {
      if((theta_angle > targetAngle) && (theta_angle < prevAngle - 180))
      {
        stop();
        break;
      } 
    }

    if(clip_L == false)
    {
      if(theta_angle >= targetAngle)
      {
        stop();
        break;
      }
    } 
}
}

boolean clipL()
{
  if(targetAngle >= 360)
  {
    targetAngle -= 360;
    return true;
  }
  return false;
}

This code works for most angles however if you specify 180 degrees it wont work. eg leftBy(180).
So it doesnt work for 180 because the following statement,

if((theta_angle > targetAngle) && (theta_angle < prevAngle - 180))

This wont run as both statements wont be true for a 180 degree turn. So most angles that are not 180 degrees will work. So i m wondering is there a better way of doing this. I d like to keep angles between 0-360 and not have negative angles as this complicates things. Basically angles that go beyound 360 that wrap around is what i m having trouble with. It seems like it should be an easy question, so sorry for my stupidity.

Could you post the whole code? Not sure what left_By is, and also why targetAngle is an argument of leftBy, but assigned a new value before being used.

Can you still post the whole code though?

I can only assume what variables are set to from their names, same for functions, and as my old man used to tell me "assumption is the first stage of a cock up".

So I m using the following method where theta_angle is the angle being made by the robot.

What does “being made” mean here?

Does theta_angle refer to the direction the robot is facing? Or is it how far the robot is supposed to rotate?

if((theta_angle > targetAngle) && (theta_angle < prevAngle - 180))

If you algorithm works for every angle except 180, I suggest you consider carefully what would happen if you changed one or both of the inequality signs in this conditional expression to “>=” or “<=”

theta_angle is the direction the robot is facing. This is generated by the encoder ticks from the motors.

michinyon: Yes, this is true if I change

if((theta_angle > targetAngle) && (theta_angle < prevAngle - 180))

to

if((theta_angle > targetAngle) && (theta_angle <= prevAngle - 180))

then it should work. But my angle resolution is every 4 degrees so this doesnt always occur.

Whats going on with the code is this. Take the following example, if the robot is moving from 350 degrees to 10 degrees, the short way, as its moving the statement (theta_angle > targetAngle) is true but the statement (theta_angle <= prevAngle - 180) is false. Once the robot has moved beyound the 360 degree mark. eg 5 degrees, the statement (theta_angle > targetAngle) is now false and (theta_angle < prevAngle - 180) is now true. Then of course when the robot passes the 10 degrees both statements will be true. This is probably not the best way of doing it so do people have alternatives to this.

If the zero crossing is giving you so much grief, why don’t you make your target angle bearing 0 (dead ahead), and have all angles relative to this. This will ensure all left turns provided they aren’t >360 (usually pointless) won’t pass the 0 threshold.

Failing that you’ll need logic to cater for the zero crossing.

*Edit: By removing your post between #1 and #2 you’ve made me look slightly deranged, there might be some truth to that, but generally its not good practice to remove your posts.

if((theta_angle > targetAngle) && (theta_angle < prevAngle - 180))

I would change that condition to:

if((theta_angle > targetAngle) && (theta_angle < prevAngle))

or something similar.
Try thinking in pictures, with the angles as pieces of a circle, and you will see why this works. (At least, I think it would work.)

Note that if the requested amount of rotation (you call it leftBy) is something like 359.99 degrees, the robot might overshoot its target and keep spinning in circles forever. I suggest that you limit leftBy to a maximum of, say, 350 degrees in order to prevent this.

ha sorry about making you look deranged tammytam. :slight_smile: .

Thank you odometer, this seemed to work. Hopefully it will hold up for now. I knew there was something obvious i wasnt seeing.