Преобразование данных G Force в ротацию? - PullRequest
1 голос
/ 24 марта 2011


Я играл с акселерометром с 3 осями: X, Y и Z. На сайте поставщика говорится, что он измеряет гравитационную силу.

IЯ посылаю эти данные в движок игр Blender, где я вращаю куб в режиме реального времени, в зависимости от значений данных, поступающих от акселерометра.Однако полученные значения не совпадают.

По каждой оси акселерометр выплевывает значения от -700 до 700 по каждой оси, и мне нужно преобразовать эти значения во что-то, что я могу использовать в Blender.Мои знания по математике не на пустом месте, поэтому я не знаю, с чего начать.

Если бы кто-нибудь мог пролить свет на это, это было бы здорово.1012 * Will

EDIT В настоящее время я использую немного кода Python для преобразования значений вращения в матрицу:

def reorient(alpha, beta, gamma):
  a = math.cos(alpha) 
  b = math.sin(alpha) 
  c = math.cos(beta) 
  d = math.sin(beta) 
  e = math.cos(gamma) 
  f = math.sin(gamma)    
  ad = a*d 
  bd = b*d 
  matrix = [[c*e, -a*f+b*d*e, b*f+a*d*e], [c*f, a*e+b*d*f, -b*e+a*d*f], [-d, b*c, a*c]]
  return matrix 

Затем я использую setOrientation (матрица), чтобы повлиять на вращение куба.Однако в настоящее время я выкидываю неверные значения в функцию reorient () матрицы

Ответы [ 2 ]

1 голос
/ 24 марта 2011

Давайте предположим, что вы можете использовать акселерометры, чтобы правильно определить, какой путь «вверх». Мы можем назвать этот вектор N . Мне кажется, что вы хотите, чтобы направление «вверх» вашего куба совпадало с N . Как уже упоминалось, это позволяет кубу свободно вращаться, но вы все равно можете найти матрицу вращения, которая может выполнить то, что вы хотите, но вам нужно учесть два отдельных случая, иначе у вас будет особенность в решении , Я предполагаю, что «Z» на кубе «вверх».

Если вы обрабатываете три значения акселерометра как вектор и нормализуете его (чтобы получить N ), вы получите новую часть оси Z вашей матрицы вращения, чтобы вектор указывал на Направление z теперь будет совпадать с вектором «вверх».

| a d N.x |   |0|   |N.x|
| b e N.y | * |0| = |N.y|
| c f N.z |   |1|   |N.z|

Итак, нам нужно решить, что делать с a-f. Одна общая вещь, которую нужно сделать, это: если N указывает в основном вдоль исходной оси 'Z', тогда задайте для новой части оси 'Y' матрицы значение M = * 1016. * N крест X :

d =  0
e =  N.z
f = -N.y

Нормализуйте M , а затем найдите часть оси 'X' матрицы: L = M cross N . Нормализовать L .

Если N не указывает в основном вдоль оси 'Z' (Nz <.707), то вы найдете новую часть оси 'Y' как <strong>M = N крест Z . Нормализуйте M и найдите L = M cross N и, наконец, нормализуйте L .


Edit:

Итак, у нас есть три значения акселерометра: A.x, A.y, A.z. Первый шаг - их нормализация:

a = sqrt(A.x*A.x + A.y*Ay + A.z*A.z);      and then 
N.x = A.x/a;  N.y = A.y/a;  N.z = A.z/a;

Мы предполагаем, что если N == [0, 0, 1], то правильной матрицей вращения является единичная матрица. Если N не указывает прямо вдоль оси z , то мы хотим сформировать матрицу, которая будет вращать ось Z куба так, чтобы он совпадал с N .

1 голос
/ 24 марта 2011

Я полагаю, вы используете измеренное ускорение, чтобы найти направление гравитационного притяжения (то есть вниз). Если вы двигаете акселерометр, кроме его поворота, будет дополнительная сила; Подумайте о акселерометре, имеющем маятниковую массу, которая движется от него, когда вы перемещаете его, маятник качается (хотя в этом случае это будет очень короткий, быстро реагирующий маятник?). Вы можете попытаться выполнить какую-то компенсацию движения, но может быть проще просто держать датчик в фиксированном месте.

Редактировать: хорошо, похоже, я полностью неправильно понял вопрос - вы хотите знать как сделать поворот в скрипте?

Похоже, что каждый объект Blender имеет три свойства (.RotX, .RotY, .RotZ), которые содержат текущие значения (в радианах), и метод (.rot (new_rotx, new_roty, new_rotz)), который выполняет вращение ( см. документацию по http://www.blender.org/documentation/249PythonDoc/Object.Object-class.html). В настоящее время я смотрю, как применяются повороты, более коротко.

Edit2: похоже, что углы заданы как углы Эйлера (http://en.wikipedia.org/wiki/Euler_angles); они дают некоторые матрицы преобразования. Также похоже, что ваши данные акселерометра недооценены (вам нужно еще одно ограничение, задающее поворот вокруг направление «вниз» - может быть, какой-то инерционный расчет «наименьшего расстояния от предыдущей позиции»?)

Edit3: есть пример сценария, который может быть полезен; на моей машине это C: \ Users \ Me \ AppData \ Roaming \ Blender Foundation \ Blender.blender \ scripts \ object_random_loc_sz_rot.py Показывает, как получить текущий выбранный объект и настроить его вращение. Надеюсь, это поможет!

Edit4: ради обсуждения, вот пример кода; это может быть немного избыточно (я раньше не работал в Blender), и это не решает проблему, но по крайней мере даст нам общую основу для дальнейшего обсуждения; -)

#!BPY

"""
Name: 'Set rotation by accelerometer'
Blender: 249
Group: 'Object'
Tooltip: 'Set the selected objects rotation by accelerometer'
"""

__bpydoc__=\
'''
This script sets the selected objects rotation by accelerometer.
'''

from Blender import Draw, Scene
import math

def reorient(alpha, beta, gamma):
    a = math.cos(alpha)
    b = math.sin(alpha)
    c = math.cos(beta)
    d = math.sin(beta)
    e = math.cos(gamma)
    f = math.sin(gamma)

    ad = a*d
    bd = b*d

    return = [
        [c*e, -a*f+b*d*e, b*f+a*d*e],
        [c*f, a*e+b*d*f, -b*e+a*d*f],
        [-d,  b*c,        a*c      ]
    ]

def getAccel():
    # test stub -
    # need to get actual values from accelerometer here
    dx = -700
    dy = 100
    dz = 250
    return (dx,dy,dz)

def normalize(vec):
    "Return scaled unit vector"
    x,y,z = vec
    mag = (x*x + y*y + z*z)**0.5
    return (x/mag, y/mag, z/mag)

def main():
    scn = Scene.GetCurrent()
    try:
        obj = scn.objects.context
        euler = (obj.RotX, obj.RotY, obj.RotZ)
    except AttributeError:
        return

    down = normalize(getAccel())
    matrix = None
    # do something here to find new rotation-matrix
    #   based on euler and down
    # then

    if matrix:
        obj.setOrientation(matrix)
    else:
        # test value:
        # if reorient() is working properly, the
        # object's rotation should not change!
        obj.setOrientation(reorient(*euler))

if __name__=="__main__":
    main()
...