Смещение углов Эйлера с использованием матрицы вращения

Я ищу правильный способ применения смещения к набору вращений Эйлера. Я хотел бы иметь преобразование, где задан конкретный набор углов Эйлера (x1,y1,z1), если бы я преобразовал их, я бы получил последовательность Эйлера (0,0,0). Все другие преобразованные эйлеровы последовательности (xi,yi,zi) затем будут действовать так, как (x1, y1, z1) (0,0,0).

Фон:

Я использую Oculus DK2 HMD для отображения виртуальной среды (Vizard 5, Python 2.7.5) при использовании системы захвата движения Vicon (Nexus 2) для обновления положения и ориентации. Я могу получить углы Эйлера HMD (из кластера маркеров, а не гироскопа DK2) из ​​системы Vicon, но когда я обращаюсь к моей желаемой (0,0,0) ориентации, HMD имеет ненулевую последовательность вращения.

Проблема:

Мне трудно думать о том, что преобразование (матрица вращения?) Я мог бы найти, что может принять последовательность вроде (-105, 110, -30) и сделать ее (0,0,0), не будучи бесполезной матрицей нули. Если бы в матрице вращения были все нули, любая последовательность была бы преобразована в (0,0,0)). Формула, которую я имею в виду (пожалуйста, игнорируйте синтаксис):

[0,0,0] = (3x3) R * (3x1) [- 105,110, -30] что такое R? R не может быть нулевой матрицей 3х3.

Попытка:

Я тупо пытался просто вычесть самые неприятные углы Эйлера вот так:

import viz
viz.go()
navigationNode = viz.addGroup() #create node
viewLink = viz.link(navigationNode, viz.MainView) #link it to the main view

#I am not showing how I get variables HMDX HMDY HMDZ but it's not important for this question
navigationNode.setEuler(HMDRZ-90,HMDRX+180,-1*(HMDRY)+30) #update the view orientation

Увы,

введите описание изображения здесь

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

1 ответ

Решение

Правильный способ сделать это - определить трансформацию между ориентацией hmd и желаемой ориентацией вида в нужной точке. Я называю это время нолем, хотя время мало с этим связано, на самом деле это "домашняя" ориентация. Как только преобразование известно, его можно использовать для определения ориентации вида с использованием данных из hmd, поскольку координатные рамки hmd и view можно рассматривать как смонтированные на одном и том же твердом теле (то есть их относительное преобразование не изменится). с течением времени).

Вот математика: введите описание изображения здесь

Вот как я это закодировал (это работает!):

import numpy as np
import math

#setup the desired calibration transformation (hmd orientation that will result in looking straight ahead

#Euler angles for the hmd at desired "zero" orientation
a0 = -177.9*math.pi/180
b0 = 31.2*math.pi/180
g0 = 90.4*math.pi/180

#make the matrices
Ra0 = np.matrix([[1,0,0],[0, float(math.cos(a0)),float(-1*math.sin(a0))],[0,float(math.sin(a0)),float(math.cos(a0))]],dtype=np.float)
Rb0 = np.matrix([[math.cos(b0),0,math.sin(b0)],[0,1,0],[-1*math.sin(b0),0,math.cos(b0)]],dtype=np.float)
Rg0 = np.matrix([[math.cos(g0),-1*math.sin(g0),0],[math.sin(g0),math.cos(g0),0],[0,0,1]],dtype=np.float)

#the hmd rotation matrix in the "zero" orientation
global RhmdU0 
RhmdU0 = Ra0*Rb0*Rg0
#the view orientation when the hmd is in the "zero" orientation (basically a zero degree turn about the Z axis)
global RdU0
RdU0 = np.matrix([[1,0,0],[0,1,0],[0,0,1]],dtype=np.float)

#this can be called in a loop, inputs are Euler angles of the hmd
def InverseK(at,bt,gt):
    global RdU0
    global RhmdU0

    #given 3 Euler sequence of the hmd in universal space, determine the viewpoint
    Rat = np.matrix([[1,0,0],[0, float(math.cos(at)), float(-1*math.sin(at))],[0,float(math.sin(at)),float(math.cos(at))]],dtype=np.float)
    Rbt = np.matrix([[math.cos(bt),0,math.sin(bt)],[0,1,0],[-1*math.sin(bt),0,math.cos(bt)]],dtype=np.float)
    Rgt = np.matrix([[math.cos(gt),-1*math.sin(gt),0],[math.sin(gt),math.cos(gt),0],[0,0,1]],dtype=np.float)

    RhmdUt = Rat*Rbt*Rgt

    RdUt = RhmdUt*RhmdU0.transpose()*RdU0

    #do inverse K to get euler sequence out:
    beta = math.atan2(RdUt[0,2],math.sqrt(RdUt[1,2]**2+RdUt[2,2]**2))
    alpha = math.atan2(-1*RdUt[1,2]/math.cos(beta),RdUt[2,2]/math.cos(beta))
    gamma = math.atan2(-1*RdUt[0,1]/math.cos(beta),RdUt[0,0]/math.cos(beta))

    return(alpha,beta,gamma)
Другие вопросы по тегам