Использование atan2 для поворота диапазона от - 1 до 1 в градусах

Я пытаюсь использовать atan2, чтобы превратить диапазон от 1 до 1 в радианы, а затем из радианов в градусы.

Однако atan2(0,1) равен 0, когда он должен быть равен 90.0, что я тут делаю?

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

Изменить: Хорошо, поэтому я подключил значения правильно в этот раз.

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;
}

Для контекста xaxisval и yaxisval получают значение с аналогового джойстика с максимальным значением 1 справа и минимальным значением - 1 слева. Поэтому, когда я нажимаю аналоговый джойстик вправо, yaxisval равен 0, а xaxisval равен 1.

Это должно вернуть 90 градусов, как будто вы представляете аналоговый джойстик как полный круг на 360 градусов. Направление вверх - 360/0, вправо - 90, вниз - 180, слева - 270 и т. Д.

Я вставил эти значения в отладчик, и это то, что он вернул.

xaxisval: 1.00000
yaxisval: 0.00000
degrees: 0.00000

Однако я хочу, чтобы это направление поднялось до 90 градусов, оно, кажется, подпрыгнуло на 90 градусов, и я проверил позицию вниз, и она была равна 90. Есть предложения?

Вывод отладки: положение джойстика вверх

xaxisval: 0.00000
yaxisval: -1.00000
degrees: 270.00000

Джойстик Правое положение

xaxisval: 1.00000
yaxisval: 0.00000
degrees: 0.00000

Положение джойстика вниз

xaxisval: 0.00000
yaxisval: 1.00000
degrees: 90.00000

Джойстик в левом положении

xaxisval: -1.00000
yaxisval: 0.00000
degrees: 180.00000

Джойстик на северо-восток

xaxisval: 0.929412
yaxisval: 0.592157
degrees: 327.497528

1 ответ

Решение

Вы передаете аргументы в неправильном порядке. std::atan2 ожидает аргументы в порядке y,x не x,y,

Да, это невероятно глупо, но это связано с тем, как касательная функция определяется в первую очередь (которая определяется как отношение компонента y к компоненту x, а не наоборот), и, как и многие другие обозначения ошибки в математике, инерция возникли тысячи лет назад, и вы не можете противостоять ей, не будучи чудаком.

Поэтому напишите свой код так:

float radians = atan2(1, 0);

Или, если вы хотите, чтобы все было как можно более явным:

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

И вы получите ожидаемые результаты.


Ваша вторая проблема заключается в том, что ценности, которые atan2 соответствовать не совпадают с направлениями, которые вы хотите. То, что вы хотите, это круг, где верхняя часть равна 0°, правая сторона - 90°, нижняя - 180°, а левая сторона - 270°. Пробивая значения в atan2 вместо этого он будет производить значения, где правая сторона равна 0°, верхняя сторона равна 90°, левая равна 180°, а нижняя равна 270°.

Кроме того, по сравнению с моим собственным оборудованием, моя ось Y перевернута по сравнению с вашей. У меня есть y+↑, тогда как ваша установка выглядит как y-↑

Так что если вы хотите преобразовать нормальный atan2 вращение в нужное вам вращение, вам нужно преобразовать его так:

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

Затем все, что вам нужно сделать, - это, возможно, преобразовать ось Y в зависимости от того, ожидаете ли вы, что нажатый джойстик вернет положительное или отрицательное значение. Это зависит от области вашей программы.

Другие вопросы по тегам