3d Accelerometer рассчитать ориентацию
У меня есть значения акселерометра для 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;
Ответы
Ответ 1
Правильный ответ:
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)
Ответ uesp неверен. Это похоже на приемлемое приближение, пока шаг и бросок не достигнут выше 45 градусов.
Я могу придерживаться другого соглашения об ориентации, но даже если вы меняете оси и инвертируете значения любым способом, вычисления uesp никогда не будут эквивалентными.
Ответ 2
В то время как ответ 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:
Roll = atan2( Y, sign* sqrt(Z*Z+ miu*X*X));
sign = 1 if accZ>0, -1 otherwise
miu = 0.001
Ошибка, введенная таким образом, значительно меньше, чем предыдущий случай: 2-3 градуса при измерении рулона при тех же условиях, которые были описаны выше.
Ответ 3
Я пробовал рекомендованное решение (matteo's), и, хотя сначала казалось, что он отлично работает, я заметил, что когда шаг приближается к 90 градусам (начиная примерно с 70 градусов, но не обязательно согласовываясь между разными телефонами), рулон внезапно вспыхивает. Когда шаг составляет 90, рулон, который должен быть около 0, теперь составляет более 100 и продолжает увеличиваться до 180. Я пытаюсь придумать способ математически предотвратить это, если я ограничу рулон до + 90/-90 ведет себя нормально, но я не получаю диапазон, который я хочу (+ 180/-180):
Math.atan2 (y, Math.sqrt((xx) + (zz))) * (180/Math.PI))
Ответ 4
Я использую следующие вычисления для преобразования наших показаний акселерометра в значения рулона и шага:
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 или перевести Roll/Pitch в зависимости от того, как определяются ваши акселерометры. Чтобы использовать их на дисплее, это просто:
glRotatef (Pitch, 0.0f, 0.0f, 1.0f);
glRotatef (Roll, 1.0f, 0.0f, 0.0f);