2009-08-11 22 views
22

Vorrei cambiare una matrice 4x4 da un sistema destrorso dove:
x è sinistra e destra, y è anteriore e posteriore e z è su e giùModifica di una matrice da sistema destrorso a destrorso

ad un sistema mancini dove:
x è bilaterale, z è anteriore e posteriore e y è su e giù.

Per un vettore è facile, basta scambiare i valori y e z, ma come si fa per una matrice?

+0

I può essere confuso qui, perché non si può semplicemente scambiare i valori Y e Z? Suppongo tu intenda una matrice 4x4x4, dal momento che un 4x4 non avrebbe z. – derobert

+0

Solo una matrice 4x4. Basta ruotando i valori di traslazione yez non sembra funzionare e una matrice contiene anche un'operazione di rotazione così sto asuming il problema è lì. – cmann

+0

Penso che avrai bisogno di chiarire esattamente quello che vuoi prima che qualcuno possa rispondere alla tua domanda. Per un vettore '(x, y, z, w)', hai spiegato che per "passare da destrorso a mancino" significa che lo si cambia nel vettore '(x, z, y, w) ', ma non è del tutto chiaro cosa significhi questa frase per una matrice. Ad esempio, supponiamo che una matrice prenda il vettore '(1,2,3,4)' al vettore '(5,6,7,8)', quindi quando si "passa da destrorso a mancino", dovrebbe prendere '(1,2,3,4)' a '(5,7,6,8)', o dovrebbe prendere '(1,3,2,4)' a '(5,7,6 , 8) ', o intendevi che facesse qualcos'altro? –

risposta

21

Lasciami provare a spiegarlo un po 'meglio. Ho bisogno di esportare un modello da Blender, in cui l'asse z è rivolto verso l'alto, in OpenGL, dove l'asse y è rivolto verso l'alto.

Per ogni coordinata (x, y, z) è semplice; basta scambiare i valori y e z: (x, z, y).
Poiché ho scambiato tutti i valori di y e z, anche qualsiasi matrice che uso deve essere ruotata in modo che abbia lo stesso effetto.

Dopo un sacco di ricerca che ho finalmente trovato una soluzione al gamedev:

Se la matrice è simile al seguente:

{ rx, ry, rz, 0 } 
{ ux, uy, uz, 0 } 
{ lx, ly, lz, 0 } 
{ px, py, pz, 1 } 

Per passare da sinistra a destra o da destra a sinistra, a fogli mobili in questo modo:

{ rx, rz, ry, 0 } 
{ lx, lz, ly, 0 } 
{ ux, uz, uy, 0 } 
{ px, pz, py, 1 } 
+2

La tua risposta sembra essere il cambiamento dal sistema di coordinate a sinistra a destra -hand sistema di coordinate, ma la descrizione del problema è di cambiare la direzione del vettore. – zionpi

+1

opengl è un sistema di mano destra. se si sceglie l'asse y in alto e si scambiano solo l'asse ye l'asse z, si ottiene un sistema di coordinate non soggetto a nessuno dei sistemi coordinati di sinistra/destra. Non penso che questa sia una risposta giusta. – flankechen

-7

Poiché questa sembra una risposta a casa; ti darò un primo sguardo a un suggerimento: cosa puoi fare per rendere negativo il determinante della matrice?

Inoltre (suggerimento migliore): poiché sai già come eseguire quella trasformazione con i singoli vettori, non credi di riuscire a farlo con i vettori di base che coprono la trasformazione rappresentata dalla matrice? (Ricorda che una matrice può essere vista come una transormazione lineare eseguita su una tupla di vettori unitari)

+2

Grazie, ma in realtà non sono compiti a casa e in realtà non conosco nessuno dei calcoli matematici dietro le matrici, quindi in realtà non ne capisco nulla. – cmann

+0

Ok, per essere più pragmatico e meno matematico, inizia con il fatto che puoi trattare la rotazione e la traduzione separatamente .. –

+0

(sto assumendo una trasformazione affine) –

0

Dipende se si trasformano i punti moltiplicando la matrice da sinistra o da destra.

Se si moltiplica da sinistra (ad esempio Ax = x ', dove A è una matrice e x' il punto trasformato), è sufficiente scambiare la seconda e la terza colonna. Se si moltiplica da destra (ad esempio xA = x '), è necessario scambiare la seconda e la terza riga.

Se i punti sono vettori di colonne, si è nel primo scenario.

11

credo di capire il vostro problema, perché attualmente sto affrontando uno simile.

  • Si inizia con una matrice mondo che trasforma un vettore in uno spazio dove Z è alto (per esempio una matrice mondo).

  • Ora hai uno spazio in cui Y è attivo e vuoi sapere cosa fare con la tua vecchia matrice.

Prova questo:

C'è una data matrice mondo

Matrix world = ... //space where Z is up 

questa matrice cambia i componenti Y e Z di un vettore

Matrix mToggle_YZ = new Matrix(
{1, 0, 0, 0} 
{0, 0, 1, 0} 
{0, 1, 0, 0} 
{0, 0, 0, 1}) 

stai cercando per questo :

//same world transformation in a space where Y is up 
Matrix world2 = mToggle_YZ * world * mToggle_YZ; 

Il risultato è la stessa matrice cmann pubblicata di seguito. Ma penso che questo sia più comprensibile in quanto combina il seguente calcolo:

1) Accendere Y e Z

2) Fare il vecchio trasformazione

3) Passare Z e Y

+3

Se c'è bisogno di rispecchiare un asse, si può fare questo con l'aggiunta di questa matrice nella moltiplicazione di matrici mondo: Matrix mMirror_X = new Matrix ( {-1, 0, 0, 0} {0, 1, 0 , 0} {0, 0, 1, 0} {0, 0, 0, 1}) – Gerrit

+0

grazie Gerrit ha funzionato benissimo. – VivekParamasivam

0

Change fattore peccato -sin per swaping coordinare gli spazi tra destra e sinistra consegnato

4

ho lavorato sulla conversione l'Unità SteamVR_Utils.RigidTransform a geometry_msgs ROS/Pose e necessario per convertire l'unità mancini sistema di coordinate il sistema di coordinate della mano destra del ROS.

Questo era il codice che ho finito per scrivere per convertire i sistemi di coordinate.

var device = SteamVR_Controller.Input(index); 
// Modify the unity controller to be in the same coordinate system as ROS. 
Vector3 ros_position = new Vector3(
    device.transform.pos.z, 
    -1 * device.transform.pos.x, 
    device.transform.pos.y); 
Quaternion ros_orientation = new Quaternion(
    -1 * device.transform.rot.z, 
    device.transform.rot.x, 
    -1 * device.transform.rot.y, 
    device.transform.rot.w); 

Inizialmente ho provato a utilizzare l'esempio di matrice da @bleater, ma non riuscivo a farlo funzionare. Mi piacerebbe sapere se ho fatto un errore da qualche parte.

HmdMatrix44_t m = device.transform.ToHmdMatrix44(); 
HmdMatrix44_t m2 = new HmdMatrix44_t(); 
m2.m = new float[16]; 
// left -> right 
m2.m[0] = m.m[0]; m2.m[1] = m.m[2]; m2.m[2] = m.m[1]; m2.m[3] = m.m[3]; 
m2.m[4] = m.m[8]; m2.m[5] = m.m[10]; m2.m[6] = m.m[9]; m2.m[7] = m.m[7]; 
m2.m[8] = m.m[4]; m2.m[9] = m.m[6]; m2.m[10] = m.m[5]; m2.m[11] = m.m[11]; 
m2.m[12] = m.m[12]; m2.m[13] = m.m[14]; m2.m[14] = m.m[13]; m2.m[15] = m.m[15]; 

SteamVR_Utils.RigidTransform rt = new SteamVR_Utils.RigidTransform(m2); 

Vector3 ros_position = new Vector3(
    rt.pos.x, 
    rt.pos.y, 
    rt.pos.z); 
Quaternion ros_orientation = new Quaternion(
    rt.rot.x, 
    rt.rot.y, 
    rt.rot.z, 
    rt.rot.w); 
+0

Grazie, questo ha aiutato così tanto! – davetcoleman

+0

Vedo che la conversione di Steam_Utils.RigidTransform è diversa da qui. Vorresti completare la tua risposta qui? – NTj

2

Spesso è il caso che si desidera modificare una matrice da un insieme di avanti/destra/su convenzioni a un'altra serie di avanti/destra/su convenzioni. Ad esempio, ROS usa z-up, e Unreal usa y-up. Il processo funziona indipendentemente dal fatto che sia necessario o meno fare un lancio.

Si noti che la frase "passare da destrorso a mancino" è ambigua. Ci sono molte convenzioni di sinistra/destra/su mancino. Ad esempio: forward = z, right = x, up = y; e avanti = x, destra = y, su = z. Dovresti davvero pensare a "come converto la nozione di ROS di forward/right/up alla nozione di Unreal di forward/right/up".

Quindi, è un lavoro semplice creare una matrice che converta tra convenzioni. Supponiamo che abbiamo fatto e ora abbiamo

mat4x4 unrealFromRos = /* construct this by hand */; 
mat4x4 rosFromUnreal = unrealFromRos.inverse(); 

Diciamo che l'OP ha una matrice che viene da ROS, e vuole usarlo in Unreal. La sua matrice originale prende un vettore in stile ROS, fa alcune cose e emette un vettore in stile ROS. Ha bisogno di una matrice che prende un vettore in stile Unreal, fa le stesse cose ed emette un vettore stile Unreal. Sembra:

mat4x4 turnLeft10Degrees_ROS = ...; 
mat4x4 turnLeft10Degrees_Unreal = unrealFromRos * turnLeft10Degrees_ROS * rosFromUnreal; 

Dovrebbe essere abbastanza chiaro il motivo per cui funziona. Prendi un vettore Unreal, lo converti in stile ROS, e ora puoi usare la matrice in stile ROS su di esso. Questo ti dà un vettore ROS, che converti in stile Unreal.

risposta di Gerrit non è abbastanza completamente generale, perché nel caso generale, rosFromUnreal! = UnrealFromRos. È vero se stai invertendo un solo asse, ma non è vero se stai facendo qualcosa come convertire X-> Y, Y-> Z, Z-> X. Ho scoperto che è meno incline agli errori usare sempre una matrice e il suo contrario per fare queste convenzioni, piuttosto che provare a scrivere funzioni speciali che capovolgono solo i membri giusti.

Questo tipo di funzionamento della matrice inverse(M) * X * M arriva un sacco. Si può pensare ad un'operazione di "cambio di base"; per saperne di più, vedi https://en.wikipedia.org/wiki/Matrix_similarity.

Problemi correlati