web-dev-qa-db-fra.com

Changer une matrice de la main droite au système de coordonnées gauchers

Je voudrais changer une matrice 4x4 d'un système droitier où:
x est laissé et à droite, y est avant et arrière et z est de haut en bas

à un système gaucher où:
[.____] x reste gauche et droite, z est avant et arrière et toi est de haut en bas.

Pour un vecteur, il est facile, il suffit d'échanger les valeurs Y et Z, mais comment le faites-vous pour une matrice?

26
cmann

Je pense que je comprends votre problème parce que je suis actuellement confronté à un similaire.

  • Vous commencez avec une matrice mondiale qui transforme un vecteur dans un espace où Z est en hausse (par exemple une matrice mondiale).

  • Maintenant, vous avez un espace où Y est en hausse et que vous voulez savoir quoi faire avec votre ancienne matrice.

Essaye ça:

Il y a une matrice mondiale donnée

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

Cette matrice change les composants Y et Z d'un vecteur

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

Vous recherchez ceci:

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

Le résultat est la même matrice CMANN posté ci-dessous. Mais je pense que cela est plus compréhensible car il combine le calcul suivant:

1) commutateur Y et Z

2) faire l'ancienne transformation

3) retourner z et y

13
Gerrit

Il est souvent le cas que vous souhaitez modifier une matrice d'un ensemble de conventions avant/droit/up vers un autre ensemble de conventions avant/droite/up. Par exemple, ROS utilise Z-up et irréelle utilise Y-UP. Le processus fonctionne si vous devez ou non une retournement.

Notez que la phrase "passion de la main droite à gaucher" est ambiguë. Il existe de nombreux conventions de gauche en avant/droite/up. Par exemple: avant = z, droite = x, up = y; et avant = x, droite = y, up = z. Vous devriez vraiment y penser comme " Comment convertir la notion de Ros" de la notion de transfert/droite/à la notion d'irréelle de l'avant/à droite/up ".

Donc, c'est un travail simple de créer une matrice qui convertit entre conventions. Supposons que nous avons fait cela et nous avons maintenant

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

Disons que l'OP a une matrice qui vient de ROS, et elle veut l'utiliser dans irréel. Sa matrice originale prend un vecteur de style ROS, fait quelques trucs et émet un vecteur de style ROS. Elle a besoin d'une matrice qui prend un vecteur de style irréel, fait la même chose et émet un vecteur de style irréel. Cela ressemble à ceci:

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

Il devrait être assez clair pourquoi cela fonctionne. Vous prenez un vecteur irréel, convertissez-le en style ROS et vous pouvez maintenant utiliser la matrice de style ROS. Cela vous donne un vecteur de ROS, que vous convertiez dans un style irréel.

La réponse de Gerrit n'est pas tout à fait pleinement générale, car dans le cas général, Rosfromunreal! = Irréelfromros. C'est vrai si vous invitez simplement un seul axe, mais pas vrai si vous faites quelque chose comme convertir x-> y, y-> z, z-> x. J'ai constaté que cela est moins sujet à une erreur d'erreur d'utiliser toujours une matrice et son inverse pour effectuer ces commutateurs de convention, plutôt que d'essayer d'écrire des fonctions spéciales qui basculent uniquement les bons membres.

Ce type de fonctionnement matriciel inverse(M) * X * M revient beaucoup. Vous pouvez y penser comme une opération "changement de base"; Pour en savoir plus à ce sujet, voir - https://fr.wikipedia.org/wiki/matrix_similarity .

5
Paul Du Bois

Je travaille sur la conversion de l'unité Steamvr_utils.rigidtransform en Ros Geometry_MSGS/pose et nécessaire pour convertir le système de coordonnées gauchers de l'unité au système de coordonnées droitiers ROS.

C'était le code que j'ai fini par écrire pour convertir des systèmes de coordonnées.

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

À l'origine, j'ai essayé d'utiliser l'exemple Matrix à partir de @Bablerater, mais je ne pouvais pas sembler le faire fonctionner. J'aimerais savoir si j'ai commis une erreur quelque part.

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

Cela dépend si vous transformez vos points en multipliant la matrice de la gauche ou de la droite.

Si vous multipliez à partir de gauche (E.G: AX = X ', où A est une matrice et X' le point transformé), vous devez simplement échanger la deuxième et la troisième colonne. Si vous multipliez de la droite (E.G: XA = X '), vous devez échanger les deuxième et troisième rangées.

Si vos points sont des vecteurs de colonne, vous êtes dans le premier scénario.

1
tugudum

Changer le facteur de péché sur -Sin pour échanger des espaces de coordonnées entre droitiers et gauchers

0
Yesman