2015-09-15 2 views
1

Je tente de contrôler une caméra osg :: avec des coordonnées cartésiennes (X, Y, Z) et des angles d'Euler (lacet, tangage, roulis) que j'ai lues dans le fichier.Contrôle d'une caméra OpenSceneGraph avec des coordonnées cartésiennes et des angles d'Euler

Partie 1

Pour une raison quelconque je crée mon rouleau provoquera la caméra pour tourner autour de l'axe z et non l'axe y comme prévu.

Ce qui suit est le manipulateur de caméra précédemment écrit auquel je donne mes données de position.

class EulerManipulator : public osgGA::CameraManipulator 
{ 
    public: 
     EulerManipulator(osg::ref_ptr<osg::View> x) : 
      view(x), 
      camView(new osg::CameraView) 
     { 
     } 

     virtual ~EulerManipulator(){} 

     virtual osg::Matrixd getMatrix() const 
     { 
      // Note: (x, y, z) and (yaw, pitch, roll) are read in from file and saved in memory 

      // Position works fine 
      this->camView->setPosition(osg::Vec3d(x, y, z)); 

      // Possibly something wrong with rotation 
      osg::Quat rotationQuat; 

      const osg::Vec3d headingAxis(0.0, 0.0, 1.0); 
      const osg::Vec3d pitchAxis(1.0, 0.0, 0.0); 
      const osg::Vec3d rollAxis(0.0, 1.0, 0.0); 

      std::array<double, 3> rotation = {yaw, pitch, roll}; 

      rotationQuat.makeRotate(
       deg2rad(rotation[2]), rollAxis, 
       deg2rad(rotation[1] + 90.0f), pitchAxis, 
       -deg2rad(rotation[0]), headingAxis); 

      this->camView->setAttitude(rotationQuat); 

      // Not 100% sure what this does but assume it works as Heading and Pitch seem to work fine. 
      auto nodePathList = this->camView->getParentalNodePaths(); 
      return osg::computeLocalToWorld(nodePathList[0]); 
     } 

    private: 
     osg::ref_ptr<osg::View> view; 
     osg::ref_ptr<osg::CameraView> camView; 
}; 

Remarque: Le code ci-dessus n'est pas le mien, mais le code utilisé pour piloter la caméra. Mon but est de saisir la position cartésienne et les angles d'Euler depuis ma propre caméra et de les écrire dans un fichier. Mais avant que je puisse le faire, je dois comprendre pourquoi ce code ne se comporte pas comme prévu.

Y at-il quelque chose qui ne va pas avec le code ci-dessus?

Partie 2

Pour la deuxième partie de ce problème que je capture des données de position de la caméra et de l'écriture dans un fichier.

J'ai eu un peu de succès mais ça ne fonctionne toujours pas correctement. Voici la fonction de poignée surchargée que j'ai écrite pour un gestionnaire d'événements attaché à ma vue. Le but est de capturer les données de position de la caméra lorsque je déplace la caméra dans la scène.

Ici, j'exécute mon programme et je fais tourner la caméra horizontalement (lacet), mais pour une raison quelconque, l'angle de tangage diminue considérablement. Si je passe de 0 degré de lacet à 90 degrés de lacet. Mon angle de pas va diminuer de 0 à environ 90 degrés. Je m'attendais à ce que ma hauteur reste à peu près la même que lorsque je fais tourner la caméra horizontalement. La question à se poser est la suivante: y a-t-il quelque chose qui ne va manifestement pas dans la façon dont je saisis les données positionnelles de l'appareil photo? Y a-t-il une meilleure façon de le faire?

+0

partie 1: Je pense que ce que vous rencontrez est une condition similaire à Gimbal verrouillage https://en.wikipedia.org/wiki/Gimbal_lock Gimbal verrouillage se produit parce que vous concaténez des rotations, et en fonction de l'ordre dans lequel vous les exécutez, ils peuvent changer l'axe dans lequel la rotation suivante est exécutée. Quelle est la source de vos valeurs Titre, Pitch, roll que vous essayez d'utiliser? Ils auront été décomposés à partir d'une orientation 3D et vous devrez faire correspondre l'ordre d'application à l'ordre de décomposition, sinon tout sera vicieux. – XenonofArcticus

Répondre

1

Partie 1

La question est l'ordre dans lequel j'ai ajouté mes angles au quaternion.

rotationQuat.makeRotate(
    deg2rad(rotation[1] + 90.0f), pitchAxis, 
    deg2rad(rotation[2]), rollAxis, 
    -deg2rad(rotation[0]), headingAxis); 

Pas dû être ajouté en premier car il tourne autour de l'axe X

Partie 2

Quelques choses étaient mal ici.

D'abord, j'avais besoin de saisir la matrice de vue inverse. Je ne suis pas sûr à 100% pourquoi, peut-être que quelqu'un avec plus de connaissances peut laisser un commentaire, mais cela fonctionne. Deuxièmement, supposer que la fonction de conversion était correcte s'est révélée être mauvaise. J'ai écrit un test unitaire qui manquait pour cette fonction et il s'est avéré que c'était faux.

// Assuming this conversion is correct 
auto ypr = Quaternion2YawPitchRoll(quat);