Рассчитать повороты, чтобы посмотреть на 3D-точку? - PullRequest
12 голосов
/ 09 августа 2009

Мне нужно рассчитать 2 угла (рыскание и тангаж) для трехмерного объекта, чтобы он столкнулся с произвольной трехмерной точкой. Эти вращения известны как вращения Эйлера просто потому, что после первого вращения (скажем, Z, на основе рисунка ниже) ось Y также вращается вместе с объектом.

Это код, который я использую, но он не работает полностью. Находясь на плоскости земли (Y = 0), объект правильно вращается, чтобы повернуться лицом к точке, но как только я переместил точку вверх по Y, вращения не будут выглядеть правильно.

// x, y, z represent a fractional value between -[1] and [1]
// a "unit vector" of the point I need to rotate towards

yaw = Math.atan2( y, x )
pitch = Math.atan2( z, Math.sqrt( x * x + y * y ) )

Знаете ли вы, как рассчитать 2 угла Эйлера для данной точки?


На рисунке ниже показано, как я вращаюсь. Это углы, которые мне нужно рассчитать. (Разница лишь в том, что я вращаю объект в порядке X, Y, Z, а не Z, Y, X)

pic

enter image description here


Это моя система.

  • Система координат: x = вправо, y = вниз, z = дальше назад
  • объект по умолчанию (0,0,1) обращен назад
  • Вращения имеют порядок X, Y, Z, где вращение по X - это шаг, Y - по рысканию, а Z - по крену

my system

Ответы [ 4 ]

13 голосов
/ 26 октября 2010

Вот мои рабочие предположения:

  • Система координат (x, y, z) такова, что положительное значение x направо, положительное значение y направлено вниз, а z - оставшееся направление. В частности, y = 0 является земной плоскостью.
  • Объект в точке (0,0,0), обращенный в настоящее время к (0,0,1), поворачивается лицом к (x, y, z).
  • Для этого будет вращение вокруг оси x, за которым следует вращение вокруг оси y. Наконец, вокруг оси z есть поворот, чтобы все было в вертикальном положении.

(Терминология «рыскание», «тангаж» и «крен» может вводить в заблуждение, поэтому я хотел бы избегать его использования, но, грубо говоря, соответствие «x = pitch, y = yaw, z = roll».)

Вот моя попытка решить вашу проблему с этой настройкой:

rotx = Math.atan2( y, z )
roty = Math.atan2( x * Math.cos(rotx), z )
rotz = Math.atan2( Math.cos(rotx), Math.sin(rotx) * Math.sin(roty) )

Надеюсь, это правильно, вплоть до знаков. Я думаю, что самый простой способ исправить знаки - это методом проб и ошибок. Действительно, вы, кажется, правильно поняли знаки rotx и roty - включая небольшую проблему с z - поэтому вам нужно только исправить знак на rotz.

Я ожидаю, что это будет нетривиально (возможно, в зависимости от того, в каком октанте вы находитесь), но, пожалуйста, попробуйте несколько вариантов, прежде чем сказать, что это неправильно. Удачи!


Вот код, который наконец-то сработал для меня.

Я заметил эффект «переворота», который произошел, когда объект переместился из любого переднего квадранта (положительный Z) в любой задний квадрант. В передних квадрантах передний объекта всегда будет направлен к точке. В задних квадрантах назад объекта всегда обращен к точке.

Этот код исправляет эффект отражения, поэтому передняя часть объекта всегда обращена к точке. Я столкнулся с этим методом проб и ошибок, поэтому я действительно не знаю, что происходит!

 rotx = Math.atan2( y, z );
 if (z >= 0) {
    roty = -Math.atan2( x * Math.cos(rotx), z );
 }else{
    roty = Math.atan2( x * Math.cos(rotx), -z );
 }
6 голосов
/ 10 августа 2009

Богатый ответ продавца показывает, как повернуть точку из одной трехмерной системы координат в другую систему, учитывая набор углов Эйлера, описывающих вращение между двумя системами координат.

Но звучит так, будто вы просите что-то другое:

У вас есть: трехмерные координаты одной точки

Вы хотите: набор эйлеровых углов

Если это то, что вы просите, у вас недостаточно информации. Чтобы найти углы Эйлера, вам понадобятся координаты не менее двух точек в обеих системах координат, чтобы определить поворот из одной системы координат в другую.

Вы также должны знать, что углы Эйлера могут быть неоднозначными: ответ Рича предполагает повороты применяются к Z, затем X ', затем Z', но это не стандартизировано. Если вам нужно взаимодействовать с другим кодом, используя углы Эйлера, вам нужно убедиться, что вы используете то же соглашение.

Возможно, вы захотите использовать матрицы вращения или кватернионы вместо углов Эйлера.

3 голосов
/ 27 октября 2010

Эта серия вращений даст вам то, что вы просите:

  1. О X: 0
  2. О Y: atan2 (z, x)
  3. О Z: atan2 (y, sqrt (x * x + z * z))

Я не могу сказать вам, что это такое с точки зрения "крена", "высоты тона" и "рыскания", если вы сначала не определите, как вы используете эти термины. Вы не используете их стандартным способом.

EDIT:
Хорошо, тогда попробуйте это:

  1. О X: -atan2 (y, z)
  2. О Y: atan2 (x, sqrt (y * y + z * z))
  3. О Z: 0
0 голосов
/ 02 сентября 2009

Говоря о вращении осей, я думаю, что шагом 3 должно было стать вращение осей X ', Y' '- и Z' относительно оси Y ''.

...