简体   繁体   中英

Using atan2 to turn a range from - 1 to 1 into degrees

I'm trying to use atan2 to turn a range of - 1 to 1 into radians and then from radians into degrees.

However atan2(0,1) is equal to 0 when it should be equal 90.0 what am I doing wrong here?

float radians = atan2(0, 1);
float degrees = (radians * 180 / PI);
if(radians < 0)
{
    degrees += 360;
}

Edit: Okay so i've plugged in the values the right way round this time.

float xaxisval = controller->left_stick_x_axis();
float yaxisval = controller->left_stick_y_axis();

// plug values into atan2
float radians = atan2(yaxisval, xaxisval);
float degrees = (radians * 180 / PI);
if (radians < 0)
{
    degrees += 360;
}

For context xaxisval and yaxisval are grabbing a value from an analog stick with a max value of 1 to the right and a minimum value of -1 to the left. So when i press the analog stick to the right the yaxisval is equal to 0 and the xaxisval is equal to 1.

This should return 90 degrees, as if you imagine the analog stick as a full 360 degree circle. Up direction is 360/0 right is 90 down is 180 left is 270 etc.

I stuck these values into the debugger and this is what it returned.

xaxisval: 1.00000
yaxisval: 0.00000
degrees: 0.00000

However I want this direction to come up as 90 degrees it has seemed to jumped up by 90 degrees and i tested the down position and it was equal to 90. Any suggestions?

Debugging Output: Joystick Up position

xaxisval: 0.00000
yaxisval: -1.00000
degrees: 270.00000

Joystick Right position

xaxisval: 1.00000
yaxisval: 0.00000
degrees: 0.00000

Joystick Down position

xaxisval: 0.00000
yaxisval: 1.00000
degrees: 90.00000

Joystick Left position

xaxisval: -1.00000
yaxisval: 0.00000
degrees: 180.00000

Joystick North East position

xaxisval: 0.929412
yaxisval: 0.592157
degrees: 327.497528

You're passing in the arguments in the wrong order. std::atan2 expects the arguments in the order y,x , not x,y .

Yes, that is incredibly dumb, but it's related to how the tangent function is defined in the first place (which is defined as a ratio of the y-component to the x-component, not the other way around), and like many notational mistakes in mathematics, inertia set in thousands of years ago and you can't push back against it without being a crank.

So write your code like this:

float radians = atan2(1, 0);

Or, if you want everything as explicit as possible:

float x = 0, y = 1;
float radians = atan2(y, x); //Yes, that's the correct order, don't @ me

And you'll get the results you expect.


Your second problem is that the values that atan2 correspond to don't match up with the directions you want. What you want is a circle where the top is 0°, the right side is 90°, the bottom is 180°, and the left side is 270°. Punching the values into atan2 is instead going to produce values where the right side is 0°, up is 90°, left is 180°, and down is 270°.

Also, in comparing with my own hardware, my y-axis is flipped compared to yours. Mine is y+↑, whereas your setup appears to be y-↑

So if you want to transform the normal atan2 rotation into the rotation you want, you'll need to transform it like this:

float radians = atan2(yaxisval, xaxisval);
float degrees = (radians * 180 / PI);
degrees = 90 - degrees;
if(degrees < 0)
    degrees += 360;

Then, all you have to do from there is possibly transform the y-axis depending on whether you expect the joystick pushed up to return a positive or negative value. That's up to the domain of your program.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM