rviz_animated_view_controller.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2009, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 
00031 #include "rviz_animated_view_controller/rviz_animated_view_controller.h"
00032 
00033 #include "rviz/load_resource.h"
00034 #include "rviz/uniform_string_stream.h"
00035 #include "rviz/display_context.h"
00036 #include "rviz/viewport_mouse_event.h"
00037 #include "rviz/frame_manager.h"
00038 #include "rviz/geometry.h"
00039 #include "rviz/ogre_helpers/shape.h"
00040 #include "rviz/properties/float_property.h"
00041 #include "rviz/properties/vector_property.h"
00042 #include "rviz/properties/bool_property.h"
00043 #include "rviz/properties/tf_frame_property.h"
00044 #include "rviz/properties/editable_enum_property.h"
00045 #include "rviz/properties/ros_topic_property.h"
00046 
00047 #include "view_controller_msgs/CameraPlacement.h"
00048 
00049 #include <OGRE/OgreViewport.h>
00050 #include <OGRE/OgreQuaternion.h>
00051 #include <OGRE/OgreVector3.h>
00052 #include <OGRE/OgreSceneNode.h>
00053 #include <OGRE/OgreSceneManager.h>
00054 #include <OGRE/OgreCamera.h>
00055 
00056 namespace rviz_animated_view_controller
00057 {
00058 using namespace view_controller_msgs;
00059 using namespace rviz;
00060 
00061 // Strings for selecting control mode styles
00062 static const std::string MODE_ORBIT = "Orbit";
00063 static const std::string MODE_FPS = "FPS";
00064 
00065 // Limits to prevent orbit controller singularity, but not currently used.
00066 //static const Ogre::Radian PITCH_LIMIT_LOW  = Ogre::Radian(-Ogre::Math::HALF_PI + 0.02);
00067 //static const Ogre::Radian PITCH_LIMIT_HIGH = Ogre::Radian( Ogre::Math::HALF_PI - 0.02);
00068 static const Ogre::Radian PITCH_LIMIT_LOW  = Ogre::Radian( 0.02 );
00069 static const Ogre::Radian PITCH_LIMIT_HIGH = Ogre::Radian( Ogre::Math::PI - 0.02);
00070 
00071 
00072 // Some convenience functions for Ogre / geometry_msgs conversions
00073 static inline Ogre::Vector3 vectorFromMsg(const geometry_msgs::Point &m) { return Ogre::Vector3(m.x, m.y, m.z); }
00074 static inline Ogre::Vector3 vectorFromMsg(const geometry_msgs::Vector3 &m) { return Ogre::Vector3(m.x, m.y, m.z); }
00075 static inline geometry_msgs::Point pointOgreToMsg(const Ogre::Vector3 &o)
00076 {
00077   geometry_msgs::Point m;
00078   m.x = o.x; m.y = o.y; m.z = o.z;
00079   return m;
00080 }
00081 static inline void pointOgreToMsg(const Ogre::Vector3 &o, geometry_msgs::Point &m)  { m.x = o.x; m.y = o.y; m.z = o.z; }
00082 
00083 static inline geometry_msgs::Vector3 vectorOgreToMsg(const Ogre::Vector3 &o)
00084 {
00085   geometry_msgs::Vector3 m;
00086   m.x = o.x; m.y = o.y; m.z = o.z;
00087   return m;
00088 }
00089 static inline void vectorOgreToMsg(const Ogre::Vector3 &o, geometry_msgs::Vector3 &m) { m.x = o.x; m.y = o.y; m.z = o.z; }
00090 
00091 // -----------------------------------------------------------------------------
00092 
00093 
00094 AnimatedViewController::AnimatedViewController()
00095   : nh_(""), animate_(false), dragging_( false )
00096 {
00097   interaction_disabled_cursor_ = makeIconCursor( "package://rviz/icons/forbidden.svg" );
00098 
00099   mouse_enabled_property_ = new BoolProperty("Mouse Enabled", true,
00100                                    "Enables mouse control of the camera.",
00101                                    this);
00102   interaction_mode_property_ = new EditableEnumProperty("Control Mode", QString::fromStdString(MODE_ORBIT),
00103                                    "Select the style of mouse interaction.",
00104                                    this);
00105   interaction_mode_property_->addOptionStd(MODE_ORBIT);
00106   interaction_mode_property_->addOptionStd(MODE_FPS);
00107   interaction_mode_property_->setStdString(MODE_ORBIT);
00108 
00109   fixed_up_property_ = new BoolProperty( "Maintain Vertical Axis", true,
00110                                          "If enabled, the camera is not allowed to roll side-to-side.",
00111                                           this);
00112   attached_frame_property_ = new TfFrameProperty("Target Frame",
00113                                                  TfFrameProperty::FIXED_FRAME_STRING,
00114                                                  "TF frame the camera is attached to.",
00115                                                  this, NULL, true );
00116   eye_point_property_    = new VectorProperty( "Eye", Ogre::Vector3( 5, 5, 10 ),
00117                                               "Position of the camera.", this );
00118   focus_point_property_ = new VectorProperty( "Focus", Ogre::Vector3::ZERO,
00119                                               "Position of the focus/orbit point.", this );
00120   up_vector_property_ = new VectorProperty( "Up", Ogre::Vector3::UNIT_Z,
00121                                             "The vector which maps to \"up\" in the camera image plane.", this );
00122   distance_property_    = new FloatProperty( "Distance", getDistanceFromCameraToFocalPoint(),
00123                                              "The distance between the camera position and the focus point.",
00124                                              this );
00125   distance_property_->setMin( 0.01 );
00126   default_transition_time_property_ = new FloatProperty( "Transition Time", 0.5,
00127                                                          "The default time to use for camera transitions.",
00128                                                          this );
00129   camera_placement_topic_property_ = new RosTopicProperty("Placement Topic", "/rviz/camera_placement",
00130                                                           QString::fromStdString(ros::message_traits::datatype<view_controller_msgs::CameraPlacement>() ),
00131                                                           "Topic for CameraPlacement messages", this, SLOT(updateTopics()));
00132 
00133 //  camera_placement_trajectory_topic_property_ = new RosTopicProperty("Trajectory Topic", "/rviz/camera_placement_trajectory",
00134 //                                                          QString::fromStdString(ros::message_traits::datatype<view_controller_msgs::CameraPlacementTrajectory>() ),
00135 //                                                          "Topic for CameraPlacementTrajectory messages", this, SLOT(updateTopics()));
00136 }
00137 
00138 AnimatedViewController::~AnimatedViewController()
00139 {
00140     delete focal_shape_;
00141     context_->getSceneManager()->destroySceneNode( attached_scene_node_ );
00142 }
00143 
00144 void AnimatedViewController::updateTopics()
00145 {
00146 //  trajectory_subscriber_ = nh_.subscribe<view_controller_msgs::CameraPlacementTrajectory>
00147 //                              (camera_placement_trajectory_topic_property_->getStdString(), 1,
00148 //                              boost::bind(&AnimatedViewController::cameraPlacementTrajectoryCallback, this, _1));
00149   placement_subscriber_  = nh_.subscribe<view_controller_msgs::CameraPlacement>
00150                               (camera_placement_topic_property_->getStdString(), 1,
00151                               boost::bind(&AnimatedViewController::cameraPlacementCallback, this, _1));
00152 }
00153 
00154 void AnimatedViewController::onInitialize()
00155 {
00156     attached_frame_property_->setFrameManager( context_->getFrameManager() );
00157     attached_scene_node_ = context_->getSceneManager()->getRootSceneNode()->createChildSceneNode();
00158     camera_->detachFromParent();
00159     attached_scene_node_->attachObject( camera_ );
00160 
00161     camera_->setProjectionType( Ogre::PT_PERSPECTIVE );
00162 
00163     focal_shape_ = new Shape(Shape::Sphere, context_->getSceneManager(), attached_scene_node_);
00164     focal_shape_->setScale(Ogre::Vector3(0.05f, 0.05f, 0.01f));
00165     focal_shape_->setColor(1.0f, 1.0f, 0.0f, 0.5f);
00166     focal_shape_->getRootNode()->setVisible(false);
00167 
00168 }
00169 
00170 void AnimatedViewController::onActivate()
00171 {
00172   updateAttachedSceneNode();
00173 
00174   // Before activation, changes to target frame property should have
00175   // no side-effects.  After activation, changing target frame
00176   // property has the side effect (typically) of changing an offset
00177   // property so that the view does not jump.  Therefore we make the
00178   // signal/slot connection from the property here in onActivate()
00179   // instead of in the constructor.
00180   connect( attached_frame_property_, SIGNAL( changed() ), this, SLOT( updateAttachedFrame() ));
00181   connect( fixed_up_property_,       SIGNAL( changed() ), this, SLOT( onUpPropertyChanged() ));
00182   connectPositionProperties();
00183 
00184   // Only do this once activated!
00185   updateTopics();
00186 
00187 }
00188 
00189 void AnimatedViewController::connectPositionProperties()
00190 {
00191   connect( distance_property_,    SIGNAL( changed() ), this, SLOT( onDistancePropertyChanged() ), Qt::UniqueConnection);
00192   connect( eye_point_property_,   SIGNAL( changed() ), this, SLOT( onEyePropertyChanged() ),      Qt::UniqueConnection);
00193   connect( focus_point_property_, SIGNAL( changed() ), this, SLOT( onFocusPropertyChanged() ),    Qt::UniqueConnection);
00194   connect( up_vector_property_,   SIGNAL( changed() ), this, SLOT( onUpPropertyChanged() ),       Qt::UniqueConnection);
00195 }
00196 
00197 void AnimatedViewController::disconnectPositionProperties()
00198 {
00199   disconnect( distance_property_,    SIGNAL( changed() ), this, SLOT( onDistancePropertyChanged() ));
00200   disconnect( eye_point_property_,   SIGNAL( changed() ), this, SLOT( onEyePropertyChanged() ));
00201   disconnect( focus_point_property_, SIGNAL( changed() ), this, SLOT( onFocusPropertyChanged() ));
00202   disconnect( up_vector_property_,   SIGNAL( changed() ), this, SLOT( onUpPropertyChanged() ));
00203 }
00204 
00205 void AnimatedViewController::onEyePropertyChanged()
00206 {
00207   distance_property_->setFloat(getDistanceFromCameraToFocalPoint());
00208 }
00209 
00210 void AnimatedViewController::onFocusPropertyChanged()
00211 {
00212   distance_property_->setFloat(getDistanceFromCameraToFocalPoint());
00213 }
00214 
00215 void AnimatedViewController::onDistancePropertyChanged()
00216 {
00217   disconnectPositionProperties();
00218   Ogre::Vector3 new_eye_position = focus_point_property_->getVector() + distance_property_->getFloat()* camera_->getOrientation().zAxis();
00219   eye_point_property_->setVector(new_eye_position);
00220   connectPositionProperties();
00221 }
00222 
00223 void AnimatedViewController::onUpPropertyChanged()
00224 {
00225   disconnect( up_vector_property_,   SIGNAL( changed() ), this, SLOT( onUpPropertyChanged() ));
00226   if(fixed_up_property_->getBool()){
00227     up_vector_property_->setVector(Ogre::Vector3::UNIT_Z);
00228     camera_->setFixedYawAxis(true, reference_orientation_ * Ogre::Vector3::UNIT_Z);
00229   }
00230   else {
00231     // force orientation to match up vector; first call doesn't actually change the quaternion
00232     camera_->setFixedYawAxis(true, reference_orientation_ * up_vector_property_->getVector());
00233     camera_->setDirection( reference_orientation_ * (focus_point_property_->getVector() - eye_point_property_->getVector()));
00234     // restore normal behavior
00235     camera_->setFixedYawAxis(false);
00236   }
00237   connect( up_vector_property_,   SIGNAL( changed() ), this, SLOT( onUpPropertyChanged() ),       Qt::UniqueConnection);
00238 }
00239 
00240 void AnimatedViewController::updateAttachedFrame()
00241 {
00242   Ogre::Vector3 old_position = attached_scene_node_->getPosition();
00243   Ogre::Quaternion old_orientation = attached_scene_node_->getOrientation();
00244 
00245   updateAttachedSceneNode();
00246 
00247   onAttachedFrameChanged( old_position, old_orientation );
00248 }
00249 
00250 void AnimatedViewController::updateAttachedSceneNode()
00251 {
00252   Ogre::Vector3 new_reference_position;
00253   Ogre::Quaternion new_reference_orientation;
00254 
00255   bool queue = false;
00256   if( context_->getFrameManager()->getTransform( attached_frame_property_->getFrameStd(), ros::Time(),
00257                                                  new_reference_position, new_reference_orientation ))
00258   {
00259     attached_scene_node_->setPosition( new_reference_position );
00260     attached_scene_node_->setOrientation( new_reference_orientation );
00261     reference_position_ = new_reference_position;
00262     reference_orientation_ = new_reference_orientation;
00263     queue = true;
00264   }
00265   if(queue) context_->queueRender();
00266 }
00267 
00268 void AnimatedViewController::onAttachedFrameChanged(const Ogre::Vector3& old_reference_position, const Ogre::Quaternion& old_reference_orientation)
00269 {
00270   Ogre::Vector3 fixed_frame_focus_position = old_reference_orientation*focus_point_property_->getVector() + old_reference_position;
00271   Ogre::Vector3 fixed_frame_eye_position = old_reference_orientation*eye_point_property_->getVector() + old_reference_position;
00272   Ogre::Vector3 new_focus_position = fixedFrameToAttachedLocal(fixed_frame_focus_position);
00273   Ogre::Vector3 new_eye_position = fixedFrameToAttachedLocal(fixed_frame_eye_position);
00274   Ogre::Vector3 new_up_vector = reference_orientation_.Inverse()*old_reference_orientation*up_vector_property_->getVector();
00275 
00276   //Ogre::Quaternion new_camera_orientation = reference_orientation_.Inverse()*old_reference_orientation*getOrientation();
00277 
00278   focus_point_property_->setVector(new_focus_position);
00279   eye_point_property_->setVector(new_eye_position);
00280   up_vector_property_->setVector(fixed_up_property_->getBool() ? Ogre::Vector3::UNIT_Z : new_up_vector);
00281   distance_property_->setFloat( getDistanceFromCameraToFocalPoint());
00282 
00283   // force orientation to match up vector; first call doesn't actually change the quaternion
00284   camera_->setFixedYawAxis(true, reference_orientation_ * up_vector_property_->getVector());
00285   camera_->setDirection( reference_orientation_ * (focus_point_property_->getVector() - eye_point_property_->getVector()));
00286 }
00287 
00288 float AnimatedViewController::getDistanceFromCameraToFocalPoint()
00289 {
00290     return (eye_point_property_->getVector() - focus_point_property_->getVector()).length();
00291 }
00292 
00293 void AnimatedViewController::reset()
00294 {
00295     eye_point_property_->setVector(Ogre::Vector3(5, 5, 10));
00296     focus_point_property_->setVector(Ogre::Vector3::ZERO);
00297     up_vector_property_->setVector(Ogre::Vector3::UNIT_Z);
00298     distance_property_->setFloat( getDistanceFromCameraToFocalPoint());
00299     mouse_enabled_property_->setBool(true);
00300     interaction_mode_property_->setStdString(MODE_ORBIT);
00301 
00302 
00303   // Hersh says: why is the following junk necessary?  I don't know.
00304   // However, without this you need to call reset() twice after
00305   // switching from TopDownOrtho to FPS.  After the first call the
00306   // camera is in the right position but pointing the wrong way.
00307   updateCamera();
00308   camera_->lookAt( 0, 0, 0 );
00309   setPropertiesFromCamera( camera_ );
00310 }
00311 
00312 void AnimatedViewController::handleMouseEvent(ViewportMouseEvent& event)
00313 {
00314   if( !mouse_enabled_property_->getBool() )
00315   {
00316     setCursor( interaction_disabled_cursor_ );
00317     setStatus( "<b>Mouse interaction is disabled. You can enable it by checking the \"Mouse Enabled\" check-box in the Views panel." );
00318     return;
00319   }
00320   else if ( event.shift() )
00321   {
00322     setStatus( "TODO: Fix me! <b>Left-Click:</b> Move X/Y.  <b>Right-Click:</b>: Move Z." );
00323   }
00324   else if ( event.control() )
00325   {
00326     setStatus( "TODO: Fix me! <b>Left-Click:</b> Move X/Y.  <b>Right-Click:</b>: Move Z." );
00327   }
00328   else
00329   {
00330     setStatus( "TODO: Fix me! <b>Left-Click:</b> Rotate.  <b>Middle-Click:</b> Move X/Y.  <b>Right-Click:</b>: Zoom.  <b>Shift</b>: More options." );
00331   }
00332 
00333   float distance = distance_property_->getFloat();
00334   int32_t diff_x = 0;
00335   int32_t diff_y = 0;
00336   bool moved = false;
00337 
00338   if( event.type == QEvent::MouseButtonPress )
00339   {
00340     focal_shape_->getRootNode()->setVisible(true);
00341     moved = true;
00342     dragging_ = true;
00343     cancelTransition();  // Stop any automated movement
00344   }
00345   else if( event.type == QEvent::MouseButtonRelease )
00346   {
00347     focal_shape_->getRootNode()->setVisible(false);
00348     moved = true;
00349     dragging_ = false;
00350   }
00351   else if( dragging_ && event.type == QEvent::MouseMove )
00352   {
00353     diff_x = event.x - event.last_x;
00354     diff_y = event.y - event.last_y;
00355     moved = true;
00356   }
00357 
00358   // regular left-button drag
00359   if( event.left() && !event.shift() )
00360   {
00361     setCursor( Rotate3D );
00362     yaw_pitch_roll( -diff_x*0.005, -diff_y*0.005, 0 );
00363   }
00364   // middle or shift-left drag
00365   else if( event.middle() || ( event.shift() && event.left() ))
00366   {
00367     setCursor( MoveXY );
00368     if(interaction_mode_property_->getStdString() == MODE_ORBIT)  // Orbit style
00369     {
00370         float fovY = camera_->getFOVy().valueRadians();
00371         float fovX = 2.0f * atan( tan( fovY / 2.0f ) * camera_->getAspectRatio() );
00372 
00373         int width = camera_->getViewport()->getActualWidth();
00374         int height = camera_->getViewport()->getActualHeight();
00375 
00376         move_focus_and_eye( -((float)diff_x / (float)width) * distance * tan( fovX / 2.0f ) * 2.0f,
00377               ((float)diff_y / (float)height) * distance * tan( fovY / 2.0f ) * 2.0f,
00378               0.0f );
00379     }
00380     else if(interaction_mode_property_->getStdString() == MODE_FPS)  // Orbit style
00381     {
00382       move_focus_and_eye( diff_x*0.01, -diff_y*0.01, 0.0f );
00383     }
00384   }
00385   else if( event.right() )
00386   {
00387     if( event.shift() ||  (interaction_mode_property_->getStdString() == MODE_FPS) )
00388     {
00389       setCursor( MoveZ );
00390       move_focus_and_eye(0.0f, 0.0f, diff_y * 0.01 * distance);
00391     }
00392     else
00393     {
00394       setCursor( Zoom );
00395       move_eye( 0, 0, diff_y * 0.01 * distance );
00396     }
00397   }
00398   else
00399   {
00400     setCursor( event.shift() ? MoveXY : Rotate3D );
00401   }
00402 
00403   if ( event.wheel_delta != 0 )
00404   {
00405     int diff = event.wheel_delta;
00406 
00407     if( event.shift() )
00408     {
00409       move_focus_and_eye(0, 0, -diff * 0.001 * distance );
00410     }
00411     else if(event.control())
00412     {
00413       yaw_pitch_roll(0, 0, diff*0.001 );
00414     }
00415     else
00416     {
00417       move_eye( 0, 0, -diff * 0.001 * distance );
00418     }
00419     moved = true;
00420   }
00421 
00422   if(event.type == QEvent::MouseButtonPress && event.left() && event.control() && event.shift())
00423   {
00424     bool was_orbit = (interaction_mode_property_->getStdString() == MODE_ORBIT);
00425     interaction_mode_property_->setStdString(was_orbit ? MODE_FPS : MODE_ORBIT );
00426   }
00427 
00428   if (moved)
00429   {
00430     context_->queueRender();
00431   }
00432 }
00433 
00434 //void AnimatedViewController::setUpVectorPropertyModeDependent( const Ogre::Vector3 &vector )
00435 //{
00436 //  if(fixed_up_property_->getBool())
00437 //  {
00438 //    //up_vector_property_->setVector(Ogre::Vector3::UNIT_Z);
00439 //  }
00440 //  else {
00441 //    up_vector_property_->setVector(vector);
00442 //  }
00443 //}
00444 
00445 
00446 void AnimatedViewController::setPropertiesFromCamera( Ogre::Camera* source_camera )
00447 {
00448   disconnectPositionProperties();
00449   Ogre::Vector3 direction = source_camera->getOrientation() * Ogre::Vector3::NEGATIVE_UNIT_Z;
00450   eye_point_property_->setVector( source_camera->getPosition() );
00451   focus_point_property_->setVector( source_camera->getPosition() + direction*distance_property_->getFloat());
00452   if(fixed_up_property_->getBool())
00453     up_vector_property_->setVector(Ogre::Vector3::UNIT_Z);
00454   else
00455     up_vector_property_->setVector(source_camera->getOrientation().yAxis());
00456 
00457   //setUpVectorPropertyModeDependent(source_camera->getOrientation().yAxis());
00458   connectPositionProperties();
00459 }
00460 
00461 void AnimatedViewController::mimic( ViewController* source_view )
00462 {
00463     QVariant target_frame = source_view->subProp( "Target Frame" )->getValue();
00464     if( target_frame.isValid() )
00465     {
00466       attached_frame_property_->setValue( target_frame );
00467     }
00468 
00469     Ogre::Camera* source_camera = source_view->getCamera();
00470     Ogre::Vector3 position = source_camera->getPosition();
00471     Ogre::Quaternion orientation = source_camera->getOrientation();
00472 
00473     if( source_view->getClassId() == "rviz/Orbit" )
00474     {
00475         distance_property_->setFloat( source_view->subProp( "Distance" )->getValue().toFloat() );
00476     }
00477     else
00478     {
00479         distance_property_->setFloat( position.length() );
00480     }
00481     interaction_mode_property_->setStdString( MODE_ORBIT );
00482 
00483     Ogre::Vector3 direction = orientation * (Ogre::Vector3::NEGATIVE_UNIT_Z * distance_property_->getFloat() );
00484     focus_point_property_->setVector( position + direction );
00485     eye_point_property_->setVector(position);
00486     updateCamera();
00487 }
00488 
00489 void AnimatedViewController::transitionFrom( ViewController* previous_view )
00490 {
00491   AnimatedViewController* fvc = dynamic_cast<AnimatedViewController*>(previous_view);
00492   if(fvc)
00493   {
00494     Ogre::Vector3 new_eye =   eye_point_property_->getVector();
00495     Ogre::Vector3 new_focus = focus_point_property_->getVector();
00496     Ogre::Vector3 new_up =    up_vector_property_->getVector();
00497 
00498     eye_point_property_->setVector(fvc->eye_point_property_->getVector());
00499     focus_point_property_->setVector(fvc->focus_point_property_->getVector());
00500     up_vector_property_->setVector(fvc->up_vector_property_->getVector());
00501 
00502     beginNewTransition(new_eye, new_focus, new_up, ros::Duration(default_transition_time_property_->getFloat()));
00503   }
00504 }
00505 
00506 void AnimatedViewController::beginNewTransition(const Ogre::Vector3 &eye, const Ogre::Vector3 &focus, const Ogre::Vector3 &up,
00507                                             const ros::Duration &transition_time)
00508 {
00509   if(ros::Duration(transition_time).isZero())
00510   {
00511     eye_point_property_->setVector(eye);
00512     focus_point_property_->setVector(focus);
00513     up_vector_property_->setVector(up);
00514     distance_property_->setFloat(getDistanceFromCameraToFocalPoint());
00515     return;
00516   }
00517 
00518   start_position_ = eye_point_property_->getVector();
00519   goal_position_ = eye;
00520 
00521   start_focus_ = focus_point_property_->getVector();
00522   goal_focus_ = focus;
00523 
00524 //  start_up_ = fixed_up_property_->getBool() ? (Ogre::Vector3::UNIT_Z) : getOrientation().yAxis();
00525 //  goal_up_ =  fixed_up_property_->getBool() ? (Ogre::Vector3::UNIT_Z) : up;
00526   start_up_ = up_vector_property_->getVector();
00527   goal_up_ =  up;
00528 
00529   current_transition_duration_ = ros::Duration(transition_time);
00530   transition_start_time_ = ros::Time::now();
00531 
00532   animate_ = true;
00533 }
00534 
00535 void AnimatedViewController::cancelTransition()
00536 {
00537   animate_ = false;
00538 }
00539 
00540 void AnimatedViewController::cameraPlacementCallback(const CameraPlacementConstPtr &cp_ptr)
00541 {
00542   CameraPlacement cp = *cp_ptr;
00543 
00544   // Handle control parameters
00545   mouse_enabled_property_->setBool( !cp.interaction_disabled );
00546   fixed_up_property_->setBool( !cp.allow_free_yaw_axis );
00547   if(cp.mouse_interaction_mode != cp.NO_CHANGE)
00548   {
00549     std::string name = "";
00550     if(cp.mouse_interaction_mode == cp.ORBIT) name = MODE_ORBIT;
00551     else if(cp.mouse_interaction_mode == cp.FPS) name = MODE_FPS;
00552     interaction_mode_property_->setStdString(name);
00553   }
00554 
00555   if(cp.target_frame != "")
00556   {
00557     attached_frame_property_->setStdString(cp.target_frame);
00558     updateAttachedFrame();
00559   }
00560 
00561   if(cp.time_from_start.toSec() >= 0)
00562   {
00563     ROS_DEBUG_STREAM("Received a camera placement request! \n" << cp);
00564     transformCameraPlacementToAttachedFrame(cp);
00565     ROS_DEBUG_STREAM("After transform, we have \n" << cp);
00566 
00567     Ogre::Vector3 eye = vectorFromMsg(cp.eye.point);
00568     Ogre::Vector3 focus = vectorFromMsg(cp.focus.point);
00569     Ogre::Vector3 up = vectorFromMsg(cp.up.vector);
00570 
00571     beginNewTransition(eye, focus, up, cp.time_from_start);
00572   }
00573 }
00574 
00575 //void AnimatedViewController::cameraPlacementTrajectoryCallback(const CameraPlacementTrajectoryConstPtr &cptptr)
00576 //{
00577 //  CameraPlacementTrajectory cpt = *cptptr;
00578 //  ROS_DEBUG_STREAM("Received a camera placement trajectory request! \n" << cpt);
00579   
00580 //  // Handle control parameters
00581 //  mouse_enabled_property_->setBool( cpt.interaction_enabled );
00582 //  fixed_up_property_->setBool( !cpt.allow_free_yaw_axis );
00583 //  if(cpt.mouse_interaction_mode != cpt.NO_CHANGE)
00584 //  {
00585 //    std::string name = "";
00586 //    if(cpt.mouse_interaction_mode == cpt.ORBIT) name = MODE_ORBIT;
00587 //    else if(cpt.mouse_interaction_mode == cpt.FPS) name = MODE_FPS;
00588 //    interaction_mode_property_->setStdString(name);
00589 //  }
00590 
00591 //  // TODO should transform the interpolated positions (later), or transform info will only reflect the TF tree state at the beginning...
00592 //  for(size_t i = 0; i<cpt.placements.size(); i++)
00593 //  {
00594 //    transformCameraPlacementToAttachedFrame(cpt.placements[i]);
00595 //  }
00596 
00597 //  // For now, just transition to the first placement until we put in the capacity for a trajectory
00598 //  CameraPlacement cp = cpt.placements[0];
00599 //  if(cp.target_frame != "")
00600 //  {
00601 //    attached_frame_property_->setStdString(cp.target_frame);
00602 //    updateAttachedFrame();
00603 //  }
00604 //  Ogre::Vector3 eye = vectorFromMsg(cp.eye.point);
00605 //  Ogre::Vector3 focus = vectorFromMsg(cp.focus.point);
00606 //  Ogre::Vector3 up = vectorFromMsg(cp.up.vector);
00607 
00608 //  beginNewTransition(eye, focus, up, cp.time_from_start);
00609 //}
00610 
00611 void AnimatedViewController::transformCameraPlacementToAttachedFrame(CameraPlacement &cp)
00612 {
00613   Ogre::Vector3 position_fixed_eye, position_fixed_focus, position_fixed_up; // position_fixed_attached;
00614   Ogre::Quaternion rotation_fixed_eye, rotation_fixed_focus, rotation_fixed_up; // rotation_fixed_attached;
00615 
00616   context_->getFrameManager()->getTransform(cp.eye.header.frame_id, ros::Time(0), position_fixed_eye, rotation_fixed_eye);
00617   context_->getFrameManager()->getTransform(cp.focus.header.frame_id,  ros::Time(0), position_fixed_focus, rotation_fixed_focus);
00618   context_->getFrameManager()->getTransform(cp.up.header.frame_id,  ros::Time(0), position_fixed_up, rotation_fixed_up);
00619   //context_->getFrameManager()->getTransform(attached_frame_property_->getStdString(),  ros::Time(0), position_fixed_attached, rotation_fixed_attached);
00620 
00621   Ogre::Vector3 eye = vectorFromMsg(cp.eye.point); 
00622   Ogre::Vector3 focus = vectorFromMsg(cp.focus.point); 
00623   Ogre::Vector3 up = vectorFromMsg(cp.up.vector); 
00624 
00625   eye = fixedFrameToAttachedLocal(position_fixed_eye + rotation_fixed_eye*eye);
00626   focus = fixedFrameToAttachedLocal(position_fixed_focus + rotation_fixed_focus*focus);
00627   up = reference_orientation_.Inverse()*rotation_fixed_up*up;
00628   //up = rotation_fixed_up*up;
00629 
00630   cp.eye.point = pointOgreToMsg(eye);
00631   cp.focus.point = pointOgreToMsg(focus);
00632   cp.up.vector = vectorOgreToMsg(up);
00633   cp.eye.header.frame_id = attached_frame_property_->getStdString();
00634   cp.focus.header.frame_id = attached_frame_property_->getStdString();
00635   cp.up.header.frame_id = attached_frame_property_->getStdString();
00636 }
00637 
00638 
00639 // We must assume that this point is in the Rviz Fixed frame since it came from Rviz...
00640 void AnimatedViewController::lookAt( const Ogre::Vector3& point )
00641 {
00642   if( !mouse_enabled_property_->getBool() ) return;
00643 
00644   Ogre::Vector3 new_point = fixedFrameToAttachedLocal(point);
00645 
00646   beginNewTransition(eye_point_property_->getVector(), new_point,
00647                      up_vector_property_->getVector(),
00648                      ros::Duration(default_transition_time_property_->getFloat()));
00649 
00650   //  // Just for easily testing the other movement styles:
00651   //  orbitCameraTo(point);
00652   //  moveCameraWithFocusTo(point);
00653 }
00654 
00655 void AnimatedViewController::orbitCameraTo( const Ogre::Vector3& point)
00656 {
00657   beginNewTransition(point, focus_point_property_->getVector(),
00658                      up_vector_property_->getVector(),
00659                      ros::Duration(default_transition_time_property_->getFloat()));
00660 }
00661 
00662 void AnimatedViewController::moveEyeWithFocusTo( const Ogre::Vector3& point)
00663 {
00664   beginNewTransition(point, focus_point_property_->getVector() + (point - eye_point_property_->getVector()),
00665                      up_vector_property_->getVector(),
00666                      ros::Duration(default_transition_time_property_->getFloat()));
00667 }
00668 
00669 
00670 void AnimatedViewController::update(float dt, float ros_dt)
00671 {
00672   updateAttachedSceneNode();
00673 
00674   if(animate_)
00675   {
00676     ros::Duration time_from_start = ros::Time::now() - transition_start_time_;
00677     float fraction = time_from_start.toSec()/current_transition_duration_.toSec();
00678     // make sure we get all the way there before turning off
00679     if(fraction > 1.0f)
00680     {
00681       fraction = 1.0f;
00682       animate_ = false;
00683     }
00684 
00685     // TODO remap progress to progress_out, which can give us a new interpolation profile.
00686     float progress = 0.5*(1-cos(fraction*M_PI));
00687 
00688     Ogre::Vector3 new_position = start_position_ + progress*(goal_position_ - start_position_);
00689     Ogre::Vector3 new_focus  = start_focus_ + progress*(goal_focus_ - start_focus_);
00690     Ogre::Vector3 new_up  = start_up_ + progress*(goal_up_ - start_up_);
00691 
00692     disconnectPositionProperties();
00693     eye_point_property_->setVector( new_position );
00694     focus_point_property_->setVector( new_focus );
00695     up_vector_property_->setVector(new_up);
00696     distance_property_->setFloat( getDistanceFromCameraToFocalPoint());
00697     connectPositionProperties();
00698 
00699     // This needs to happen so that the camera orientation will update properly when fixed_up_property == false
00700     camera_->setFixedYawAxis(true, reference_orientation_ * up_vector_property_->getVector());
00701     camera_->setDirection(reference_orientation_ * (focus_point_property_->getVector() - eye_point_property_->getVector()));
00702   }
00703   updateCamera();
00704 }
00705 
00706 void AnimatedViewController::updateCamera()
00707 {
00708   camera_->setPosition( eye_point_property_->getVector() );
00709   camera_->setFixedYawAxis(fixed_up_property_->getBool(), reference_orientation_ * up_vector_property_->getVector());
00710   camera_->setDirection( reference_orientation_ * (focus_point_property_->getVector() - eye_point_property_->getVector()));
00711   //camera_->setDirection( (focus_point_property_->getVector() - eye_point_property_->getVector()));
00712   focal_shape_->setPosition( focus_point_property_->getVector() );
00713 }
00714 
00715 void AnimatedViewController::yaw_pitch_roll( float yaw, float pitch, float roll )
00716 {
00717   Ogre::Quaternion old_camera_orientation = camera_->getOrientation();
00718   Ogre::Radian old_pitch = old_camera_orientation.getPitch(false);// - Ogre::Radian(Ogre::Math::HALF_PI);
00719 
00720   if(fixed_up_property_->getBool()) yaw = cos(old_pitch.valueRadians() - Ogre::Math::HALF_PI)*yaw; // helps to reduce crazy spinning!
00721 
00722   Ogre::Quaternion yaw_quat, pitch_quat, roll_quat;
00723   yaw_quat.FromAngleAxis( Ogre::Radian( yaw ), Ogre::Vector3::UNIT_Y );
00724   pitch_quat.FromAngleAxis( Ogre::Radian( pitch ), Ogre::Vector3::UNIT_X );
00725   roll_quat.FromAngleAxis( Ogre::Radian( roll ), Ogre::Vector3::UNIT_Z );
00726   Ogre::Quaternion orientation_change = yaw_quat * pitch_quat * roll_quat;
00727   Ogre::Quaternion new_camera_orientation = old_camera_orientation * orientation_change;
00728   Ogre::Radian new_pitch = new_camera_orientation.getPitch(false);// - Ogre::Radian(Ogre::Math::HALF_PI);
00729 
00730   if( fixed_up_property_->getBool() &&
00731       ((new_pitch > PITCH_LIMIT_HIGH && new_pitch > old_pitch) || (new_pitch < PITCH_LIMIT_LOW && new_pitch < old_pitch)) )
00732   {
00733     orientation_change = yaw_quat * roll_quat;
00734     new_camera_orientation = old_camera_orientation * orientation_change;
00735   }
00736 
00737 //  Ogre::Radian new_roll = new_camera_orientation.getRoll(false);
00738 //  Ogre::Radian new_yaw = new_camera_orientation.getYaw(false);
00739   //ROS_INFO("old_pitch: %.3f, new_pitch: %.3f", old_pitch.valueRadians(), new_pitch.valueRadians());
00740 
00741   camera_->setOrientation( new_camera_orientation );
00742   if( interaction_mode_property_->getStdString() == MODE_ORBIT )
00743   {
00744     // In orbit mode the focal point stays fixed, so we need to compute the new camera position.
00745     Ogre::Vector3 new_eye_position = focus_point_property_->getVector() + distance_property_->getFloat()* new_camera_orientation.zAxis();
00746     eye_point_property_->setVector(new_eye_position);
00747     camera_->setPosition(new_eye_position);
00748     setPropertiesFromCamera(camera_);
00749   }
00750   else
00751   {
00752     // In FPS mode the camera stays fixed, so we can just apply the rotations and then rely on the property update to set the new focal point.
00753     setPropertiesFromCamera(camera_);
00754   }
00755 }
00756 
00757 Ogre::Quaternion AnimatedViewController::getOrientation()  // Do we need this?
00758 {
00759   return camera_->getOrientation();
00760 }
00761 
00762 void AnimatedViewController::move_focus_and_eye( float x, float y, float z )
00763 {
00764   Ogre::Vector3 translate( x, y, z );
00765   eye_point_property_->add( getOrientation() * translate );
00766   focus_point_property_->add( getOrientation() * translate );
00767 }
00768 
00769 void AnimatedViewController::move_eye( float x, float y, float z )
00770 {
00771   Ogre::Vector3 translate( x, y, z );
00772   // Only update the camera position if it won't "pass through" the origin
00773   Ogre::Vector3 new_position = eye_point_property_->getVector() + getOrientation() * translate;
00774   if( (new_position - focus_point_property_->getVector()).length() > distance_property_->getMin() )
00775     eye_point_property_->setVector(new_position);
00776   distance_property_->setFloat(getDistanceFromCameraToFocalPoint());
00777 }
00778 
00779 
00780 
00781 } // end namespace rviz
00782 
00783 #include <pluginlib/class_list_macros.h>
00784 PLUGINLIB_EXPORT_CLASS( rviz_animated_view_controller::AnimatedViewController, rviz::ViewController )


rviz_animated_view_controller
Author(s): Adam Leeper
autogenerated on Fri Aug 28 2015 12:56:50