openscenegraphosgearth

OSG/OSGEarth How to move a Camera


I'm making a Drone simulator with OSGEarth. I never used OSG before so I have some troubles to understand cameras. I'm trying to move a Camera to a specific location (lat/lon) with a specific roll, pitch and yaw in OSG Earth.

I need to have multiple cameras, so I use a composite viewer. But I don't understand how to move the particular camera. Currently I have one with the EarthManipulator which works fine.

 class NovaManipulator : publicosgGA::CameraManipulator {
         osg::Matrixd NovaManipulator::getMatrix() const
            {
              //drone_ is only a struct which contains updated infomations
              float roll = drone_->roll(),
              pitch = drone_->pitch(),
              yaw = drone_->yaw();

          auto position = drone_->position();
          osg::Vec3d world_position;
          position.toWorld(world_position);

          cam_view_->setPosition(world_position);

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

           //if found this code : 
           // https://stackoverflow.com/questions/32595198/controling-openscenegraph-camera-with-cartesian-coordinates-and-euler-angles
           osg::Quat rotationQuat;
           rotationQuat.makeRotate(
               osg::DegreesToRadians(pitch + 90), pitchAxis,
               osg::DegreesToRadians(roll),          rollAxis,
               osg::DegreesToRadians(yaw),          yawAxis);

          cam_view_->setAttitude(rotationQuat);

          // I don't really understand this also
          auto nodePathList = cam_view_->getParentalNodePaths();
          return osg::computeLocalToWorld(nodePathList[0]);
        }

        osg::Matrixd NovaManipulator::getInverseMatrix() const
        {
          //Don't know why need to be inverted
          return osg::Matrix::inverse(getMatrix());
        } 
    };

Then I install the manupulator to a Viewer. And when I simulate the world, The camera is on the good place (Lat/Lon/Height). But the orientation in completely wrong and I cannot find where I need to "correct" the axis.

Actually my drone is in France but the "up" vector is bad, it still head to North instead of "vertical" relatively to the ground. See what I'm getting on the right camera

I need to have a yaw relative to North (0 ==> North), and when my roll and pitch are set to zero I need to be "parallel" to the ground.

Is my approach (by making a Manipulator) is the best to do that ? Can I put the camera object inside the Graph node (behind a osgEarth::GeoTransform (it works for my model)) ?

Thanks :)


Solution

  • In the past, I have done a cute trick involving using an ObjectLocator object (to get the world position and plane-tangent-to-surface orientation), combined with a matrix to apply the HPR. There's an invert in there to make it into a camera orientation matrix rather than an object placement matrix, but it works out ok.

    http://forum.osgearth.org/void-ObjectLocator-setOrientation-default-orientation-td7496768.html#a7496844

    It's a little tricky to see what's going on in your code snippet as the types of many of the variables aren't obvious.

    AlphaPixel does lots of telemetry / osgEarth type stuff, so shout if you need help.