2017-04-25 6 views
0

J'ai un quaternion représentant l'orientantion d'un objet (boîte jaune et sphère). Je voudrais savoir s'il est possible de diviser ce quaternion en autres quaternions qui nous donnent la rotation de chaque axe local (X, Y et Z).Diviser le quaternion en rotation d'axe

Due to I do not have enough reputation to post images directly, I have to put just the link of the image

Ce que je fais jusqu'à présent est d'obtenir la représentation d'Euler et de travailler avec elle, mais ce n'est pas la bonne solution pour mon cas particulier:

Étant donné deux points (boîtes bleues), Je veux limiter l'orientation de mon objet pour qu'il ne puisse pas pointer du plan gris, même si mon quaternion regarde de ce plan. Je veux diviser (décomposer) le quaternion, parce que quand mon objet atteint la limite du plan (par exemple, le droit), je veux le faire rester (dans ce composant), puis faire pivoter mon objet dans le composante verticale, en utilisant l'un des nouveaux quaternion divisé.

Je travaille avec Unity.

je l'espère, il est compréhensible mon problème :)

+0

serait 'rotation Quaternion = Quaternion.Euler (nouveau Vector3 (transform.eulerAngles.x, 0, 0)) 'être applicable? –

+0

Merci @Peh pour l'édition. Merci Ryan, mais je veux éviter les angles d'Euler car le quaternion originel vient d'un IMU externe, et en limitant l'orientantion avec des angles d'Euler j'ai eu quelques problèmes – javinair

+0

[Quaternion.eulerAngles] (https://docs.unity3d.com /ScriptReference/Quaternion-eulerAngles.html) est une chose, mais je pense que c'est ce que vous utilisez déjà. Je sais que les valeurs 'wxyz' n'aideront pas du tout car elles sont incomplètes. Le mieux que je puisse penser est de calculer un Euler 'AngleTo()' (vous devrez écrire cette méthode) sur les deux cases bleues et vérifier que les deux composantes X et Y sont supérieures à 0 (ou moins, selon le cas). – Draco18s

Répondre

0

J'ai travaillé avec IMU avant et à ma connaissance avec l'unité si l'objet est en train de lire dans les données IMU comme escouades, vous ne rencontrerez pas le problème de verrouillage de Gimbo . Ainsi, vous pouvez en effet créer une référence à la rotation de l'objet et la convertir en anges euler, puis la reconvertir en quaternions avant de l'appliquer à l'objet.

Cependant, si vous êtes simplement désireux de limiter la rotation que je ferais quelque chose comme ceci:

//the last rotation was pointed at the grey zone. 
private Quaternion prevAllowedRotation; 

void FixedUpdate(){ 
    if(!isValidRotation()){ 
     this.transform.rotation = prevAllowedRotation; 
    }else{ 
     this.transform.lookAt(lockToArea()); 
    } 
} 


private bool isValidRotation(){ 
    //I chose forward based on the image, find the direction that works for you 
    Ray ray = new Ray(this.transform.position, this.transform.forward); 
    RaycastHit hit; 
    if(Physics.Raycast(ray, out hit, 10f){ 
     if(hit.transform.tag == "wall"){ 
      return true; 
     } 
    } 
    return false; 
} 


private Vector3 lockToArea(Gameobject grey){ 
    Vector3 center = grey.transform.position; 
    //figure out how to get the position of the facing direction on the same plane as the grey area. 
    Vector3 pointerPosition = getPointerPosition(); 
    RaycastHit hit; 
    if(Physics.Linecast(pointerPosition, center, hit)){ 
     return hit.point; 
    } 
    return Vector3.zero; 

} 

private Vector3 getPointerOnPlane(){ 
    Ray ray = new Ray(this.transform.position, this.transform.forward); 
    // you need to figure out how to dyanmically get the distance so that the ray lands on the same plane as the vector 
    float distance = 0; 
    return ray.GetPoint(distance);  
} 

Cette fonction verrouille sa rotation à ne pointer le cube gris. Cela devrait vous aider beaucoup, vous avez juste besoin d'obtenir le point que les données de l'IMU lisent à et sont sur le même plan que le centre du cube gris.

+0

merci pour votre @ Dan répondre. C'est vraiment proche de ce à quoi je m'attends, mais je veux aller un peu plus loin. Ma rotation est limitée à la zone du plan gris, OK, mais le problème est maintenant quand mon cube pointe du plan (la rotation brute que je veux dire), il est bloqué d'un côté de l'avion.Par exemple, si j'obtiens mon cube du côté droit de l'avion et que je le déplace verticalement, il reste coincé dans la dernière position autorisée, au lieu de monter et descendre le long du bord droit. Est-ce facile à atteindre? Merci encore. – javinair

+0

@ javinair regarde les dernières modifications que j'ai faites, je n'ai pas eu assez de temps pour faire la dernière étape qui a fini le getPointerOnPlane mais si vous le comprenez, alors vous avez exactement ce que vous voulez. J'ai fait ces modifications après avoir relu votre question. Je suis également heureux que cela a fonctionné, car je ne pouvais pas le tester XD. –

0

Voici un moyen d'obtenir la rotation locale de l'axe Y uniquement. Cette fonction peut être modifiée pour obtenir l'axe x ou z.

/// <summary> isolate the y-Component of a rotation </summary> 
private Quaternion yRotation(Quaternion q) 
{ 
    float theta = Mathf.Atan2(q.y, q.w); 

    // quaternion representing rotation about the y axis 
    return new Quaternion(0, Mathf.Sin(theta), 0, Mathf.Cos(theta)); 
} 

Vous pouvez vérifier le résultat de l'inspecteur en convertissant l'unité d'Euler:

public float yLocal; 
void Update() 
{ 
    yLocal = yRotation(this.transform.rotation).eulerAngles.y; 
}