3d акселерометр рассчитать ориентацию - PullRequest
27 голосов
/ 21 сентября 2010

У меня есть значения акселерометра для оси 3 (обычно, когда есть только гравитация, содержит данные между -1,0 и 1,0):

  float Rx;
  float Ry;
  float Rz;

Я делаю расчеты сомы, затем получаю углы для каждой оси.

  float R =  sqrt(pow(Rx,2)+pow(Ry,2)+pow(Rz,2));
  float Arx = acos(Rx/R)*180/M_PI;
  float Ary = acos(Ry/R)*180/M_PI;
  float Arz = acos(Rz/R)*180/M_PI;

Затем я устанавливаю значения для углов окна в opengl

rquad = Arx;
yquad = Ary;

Который вращает мою коробку:

glRotatef(yquad,1.0f,0.0f,0.0f);
glRotatef(rquad,0.0f,1.0f,0.0f);

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

Обновление: Окончательный ответ в моем случае:

  rquad = -atan2(Rx/R, Rz/R)*180/M_PI;
  yquad = -atan2(Ry/R, Rz/R)*180/M_PI;

Ответы [ 5 ]

41 голосов
/ 25 апреля 2012

Правильный ответ:

Roll = atan2(Y, Z) * 180/M_PI;
Pitch = atan2(-X, sqrt(Y*Y + Z*Z)) * 180/M_PI;

Источник: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf (стр. 10, уравнения 25 и 26)

ответ Уэсп неправильный. Это выглядит как приемлемое приближение, пока оба шага и крена не поднимутся выше 45 градусов.

Возможно, я предполагаю другое соглашение об ориентации, но даже если вы меняете оси и инвертируете значения любым последовательным способом, вычисления uesp никогда не будут эквивалентны.

18 голосов
/ 12 мая 2015

Хотя ответ matteo верен, он не дает полного, полного решения: Формулы верны:

Roll = atan2(Y, Z) * 180/M_PI;
Pitch = atan2(-X, sqrt(Y*Y + Z*Z)) * 180/M_PI;

Однако, когда угол наклона равен + 90 / -90 градусов, а ось X направлена ​​вертикально вверх / вниз, идеальный нормированный выходной сигнал акселерометра должен составлять:

accX = -1  / accX = 1 
accY = 0
accZ = 0

Что означает roll angle of 0 degrees; правильный. Но на практике выходной сигнал акселерометра зашумлен, и вы получите что-то ближе к:

accX = -1  / accX = 1 
accY = 0.003
accZ = 0.004

Это может показаться небольшим, но из-за этого угол крена составит ~ 30 градусов, что не правильно.

Очевидным инстинктом было бы отфильтровывать последние цифры, но это влияло бы на точность, что не всегда приемлемо.

Компромисс, который очень хорошо объяснен в примечании к справочному приложению, состоит в том, чтобы включить в формулу для крена очень маленький процент показаний оси X акселерометра:

Roll  = atan2( Y,   sign* sqrt(Z*Z+ miu*X*X));
sign  = 1 if accZ>0, -1 otherwise 
miu = 0.001

Ошибка, вносимая таким образом, значительно меньше, чем в предыдущем случае: 2-3 градуса при измерении крена при тех же условиях, которые описаны выше.

3 голосов
/ 14 апреля 2017

Я попробовал рекомендованное решение (matteo's), и, хотя на первый взгляд оно показалось отличным, я заметил, что когда угол наклона приближается к 90 градусам (начиная примерно с 70 градусов, но не обязательно одинаковым для разных телефонов), поворотвнезапно горятКогда шаг равен 90, крен, который должен быть около 0, теперь превышает 100 и продолжает увеличиваться до 180. Я пытаюсь придумать способ математически предотвратить это, если я ограничу крен на + 90 / -90.ведет себя нормально, но я не получаю нужный диапазон (+ 180 / -180): Math.atan2 (y, Math.sqrt ((x x) + (z z))) * (180/Math.PI))

0 голосов
/ 22 марта 2018

Для roll, я обнаружил, что вы можете использовать arctan(y/sqrt(X*X)+(z*z)), это даст бросок -90/90, который является авиационным стандартом без указания высоты тона

0 голосов
/ 21 сентября 2010

Я использую следующие расчеты для преобразования наших показаний акселерометра в значения крена и шага:

Roll = atan2( sqrt(Y*Y + X*X), Z) * 180/M_PI;
Pitch = atan2( sqrt(X*X + Z*Z), Y) * 180/M_PI;

Возможно, вам придется поменять значения X / Y / Z или перевести крен / шаг в зависимости от того, какакселерометры определены.Чтобы использовать их в отображении их, это просто вопрос:

glRotatef (Pitch, 0.0f, 0.0f, 1.0f);
glRotatef (Roll,  1.0f, 0.0f, 0.0f);
...