Cambiar una matriz de sistema de coordenadas diestro a zurdo

Me gustaría cambiar una matriz 4×4 de un sistema diestro donde:
x es de izquierda a derecha, y es de frente y atrás y z es de arriba y abajo

a un sistema zurdo donde:
x es de izquierda a derecha, z es de frente y atrás, y y está arriba y abajo.

Para un vector es fácil, simplemente cambie los valores de yy z, pero ¿cómo lo hace para una matriz?

Déjame tratar de explicarlo un poco mejor. Necesito exportar un modelo de Blender, en el que el eje z mira hacia arriba, a OpenGL, donde el eje y mira hacia arriba.

Para cada coordenada (x, y, z) es simple; simplemente intercambie los valores de y y z: (x, z, y).
Como cambié todos los valores de yy z, cualquier matriz que use también debe voltearse para que tenga el mismo efecto.

Después de mucha búsqueda, finalmente encontré una solución en gamedev :

Si su matriz se ve así:

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

Para cambiarlo de izquierda a derecha o de derecha a izquierda, dele la vuelta de esta manera:

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

Creo que entiendo su problema porque actualmente estoy enfrentando uno similar.

  • Comienzas con una matriz mundial que transforma un vector en un espacio donde Z está arriba (por ejemplo, una matriz mundial).

  • Ahora tienes un espacio donde Y está arriba y quieres saber qué hacer con tu matriz anterior.

Prueba esto:

Hay una matriz mundial dada

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

Esta Matriz cambia los componentes Y y Z de un Vector

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

Usted está buscando esto:

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

El resultado es la misma matriz cmann publicada a continuación. Pero creo que esto es más comprensible ya que combina el siguiente cálculo:

1) Cambiar Y y Z

2) Haz la vieja transformación

3) Cambiar de vuelta Z e Y

He estado trabajando para convertir el Unity SteamVR_Utils.RigidTransform a ROS geometry_msgs / Pose y necesito convertir el sistema de coordenadas Unid de la mano izquierda al sistema de coordenadas ROS del lado derecho.

Este fue el código que terminé escribiendo para convertir sistemas de coordenadas.

 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); 

Originalmente traté de usar el ejemplo de la matriz de @bleater, pero parecía que no podía hacerlo funcionar. Me encantaría saber si cometí un error en alguna parte.

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

A menudo es el caso que desea cambiar una matriz de un conjunto de convenciones adelante / derecha / arriba a otro conjunto de convenciones adelante / derecha / arriba. Por ejemplo, ROS usa z-up, y Unreal usa y-up. El proceso funciona ya sea que necesites o no hacer un giro de la mano.

Tenga en cuenta que la frase “cambiar de diestro a zurdo” es ambigua. Hay muchas convenciones de avance / avance / avance hacia la izquierda. Por ejemplo: forward = z, right = x, up = y; y forward = x, right = y, up = z. Deberías considerarlo realmente como ” cómo convierto la noción de ROS de adelante / derecha / arriba a la noción de avance / derecha / arriba ” de Unreal .

Por lo tanto, es un trabajo sencillo crear una matriz que convierta convenciones. Supongamos que lo hemos hecho y ahora tenemos

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

Digamos que OP tiene una matriz que proviene de ROS y quiere usarla en Unreal. Su matriz original toma un vector estilo ROS, le hace algunas cosas y emite un vector estilo ROS. Ella necesita una matriz que tome un vector de estilo irreal, haga lo mismo y emite un vector de estilo irreal. Eso se ve así:

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

Debería estar bastante claro por qué esto funciona. Tomas un vector Unreal, lo conviertes al estilo ROS, y ahora puedes usar la matriz estilo ROS en él. Eso le da un vector ROS, que convierte de nuevo a estilo Unreal.

La respuesta de Gerrit no es completamente general, porque en el caso general, rosFromUnreal! = UnrealFromRos. Es cierto si solo está invirtiendo un solo eje, pero no es cierto si está haciendo algo así como convertir X-> Y, Y-> Z, Z-> X. He descubierto que es menos propenso a errores usar siempre una matriz y su inversa para hacer estos cambios de convención, en lugar de intentar escribir funciones especiales que invierten solo los miembros correctos.

Este tipo de operación de matriz inverse(M) * X * M aparece mucho. Puede pensarlo como una operación de “cambio de base”; Para obtener más información al respecto, consulte https://en.wikipedia.org/wiki/Matrix_similarity .

Depende si transforma sus puntos al multiplicar la matriz desde la izquierda o desde la derecha.

Si multiplicas desde la izquierda (por ejemplo: Ax = x ‘, donde A es una matriz yx’ el punto transformado), solo necesitas cambiar la segunda y la tercera columna. Si multiplicas desde la derecha (p. Ej .: xA = x ‘), debes cambiar la segunda y la tercera fila.

Si tus puntos son vectores de columna, entonces estás en el primer escenario.

Cambie el factor de siniestro a -sin para cambiar espacios de coordenadas entre diestros y zurdos

Dado que esto parece una respuesta a la tarea; Te daré un comienzo con una pista: ¿qué puedes hacer para que el determinante de la matriz sea negativo?

Además (mejor pista): como ya sabes cómo hacer esa transformación con vectores individuales, ¿no crees que serías capaz de hacerlo con los vectores de base que abarcan la transformación que representa la matriz? (Recuerde que una matriz se puede ver como una transormación lineal realizada en una tupla de vectores unitarios)