wrench_display.cpp
Go to the documentation of this file.
00001 #include <OGRE/OgreSceneNode.h>
00002 #include <OGRE/OgreSceneManager.h>
00003 
00004 #include <tf/transform_listener.h>
00005 
00006 #include <rviz/visualization_manager.h>
00007 #include <rviz/properties/property.h>
00008 #include <rviz/properties/property_manager.h>
00009 #include <rviz/frame_manager.h>
00010 
00011 #include <boost/foreach.hpp>
00012 
00013 #include "wrench_visual.h"
00014 
00015 #include "wrench_display.h"
00016 
00017 namespace jsk_rviz_plugin
00018 {
00019 
00020     WrenchStampedDisplay::WrenchStampedDisplay()
00021         : Display()
00022         , scene_node_( NULL )
00023         , messages_received_( 0 )
00024         , force_color_( .8, .2, .2 )       // Default force color is red
00025         , torque_color_( .8, .8, .2 )      // Default torque color is yellow
00026         , alpha_( 1.0 )              // Default alpha is completely opaque.
00027         , scale_( 2.0 )              // Default scale
00028         , width_( 0.5 )              // Default width 
00029     {
00030     }
00031 
00032     void WrenchStampedDisplay::onInitialize()
00033     {
00034         // Make an Ogre::SceneNode to contain all our visuals.
00035         scene_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
00036 
00037         // Set the default history length and resize the ``visuals_`` array.
00038         setHistoryLength( 1 );
00039 
00040         // A tf::MessageFilter listens to ROS messages and calls our
00041         // callback with them when they can be matched up with valid tf
00042         // transform data.
00043         tf_filter_ =
00044             new tf::MessageFilter<geometry_msgs::WrenchStamped>( *vis_manager_->getTFClient(),
00045                                              "", 100, update_nh_ );
00046         tf_filter_->connectInput( sub_ );
00047         tf_filter_->registerCallback( boost::bind( &WrenchStampedDisplay::incomingMessage,
00048                                                    this, _1 ));
00049 
00050         // FrameManager has some built-in functions to set the status of a
00051         // Display based on callbacks from a tf::MessageFilter.  These work
00052         // fine for this simple display.
00053         vis_manager_->getFrameManager()
00054             ->registerFilterForTransformStatusCheck( tf_filter_, this );
00055 
00056     }
00057 
00058     WrenchStampedDisplay::~WrenchStampedDisplay()
00059     {
00060         unsubscribe();
00061         clear();
00062         visuals_.clear();
00063 
00064         delete tf_filter_;
00065     }
00066 
00067     // Clear the visuals by deleting their objects.
00068     void WrenchStampedDisplay::clear()
00069     {
00070         for( size_t i = 0; i < visuals_.size(); i++ ) {
00071             delete visuals_[ i ];
00072             visuals_[ i ] = NULL;
00073         }
00074         tf_filter_->clear();
00075         messages_received_ = 0;
00076         setStatus( rviz::status_levels::Warn, "Topic", "No messages received" );
00077     }
00078 
00079     void WrenchStampedDisplay::setTopic( const std::string& topic )
00080     {
00081         unsubscribe();
00082         clear();
00083         topic_ = topic;
00084         subscribe();
00085 
00086         // Broadcast the fact that the variable has changed.
00087         propertyChanged( topic_property_ );
00088 
00089         // Make sure rviz renders the next time it gets a chance.
00090         causeRender();
00091     }
00092 
00093     void WrenchStampedDisplay::setForceColor( const rviz::Color& color )
00094     {
00095         force_color_ = color;
00096 
00097         propertyChanged( force_color_property_ );
00098         updateVisual();
00099         causeRender();
00100     }
00101 
00102     void WrenchStampedDisplay::setTorqueColor( const rviz::Color& color )
00103     {
00104         torque_color_ = color;
00105 
00106         propertyChanged( torque_color_property_ );
00107         updateVisual();
00108         causeRender();
00109     }
00110 
00111     void WrenchStampedDisplay::setAlpha( float alpha )
00112     {
00113         alpha_ = alpha;
00114 
00115         propertyChanged( alpha_property_ );
00116         updateVisual();
00117         causeRender();
00118     }
00119 
00120     void WrenchStampedDisplay::setScale( float scale )
00121     {
00122         scale_ = scale;
00123 
00124         propertyChanged( width_property_ );
00125         updateVisual();
00126         causeRender();
00127     }
00128 
00129     void WrenchStampedDisplay::setWidth( float width )
00130     {
00131         width_ = width;
00132 
00133         propertyChanged( width_property_ );
00134         updateVisual();
00135         causeRender();
00136     }
00137 
00138     // Set the current color and alpha values for each visual.
00139     void WrenchStampedDisplay::updateVisual()
00140     {
00141         BOOST_FOREACH(MapWrenchStampedVisual::value_type visual, visuals_)
00142         {
00143             if ( visual ) {
00144                 visual->setForceColor( force_color_.r_, force_color_.g_, force_color_.b_, alpha_ );
00145                 visual->setTorqueColor( torque_color_.r_, torque_color_.g_, torque_color_.b_, alpha_ );            
00146                 visual->setScale( scale_ );
00147                 visual->setWidth( width_ );
00148             }
00149         }
00150     }
00151 
00152     // Set the number of past visuals to show.
00153     void WrenchStampedDisplay::setHistoryLength( int length )
00154     {
00155         // Don't let people enter invalid values.
00156         if( length < 1 )
00157         {
00158             length = 1;
00159         }
00160         // If the length is not changing, we don't need to do anything.
00161         if( history_length_ == length )
00162         {
00163             return;
00164         }
00165 
00166         // Set the actual variable.
00167         history_length_ = length;
00168         propertyChanged( history_length_property_ );
00169 
00170         // Create a new array of visual pointers, all NULL.
00171         std::vector<WrenchStampedVisual*> new_visuals( history_length_, (WrenchStampedVisual*)0 );
00172 
00173         // Copy the contents from the old array to the new.
00174         // (Number to copy is the minimum of the 2 vector lengths).
00175         size_t copy_len =
00176             (new_visuals.size() > visuals_.size()) ?
00177             visuals_.size() : new_visuals.size();
00178         for( size_t i = 0; i < copy_len; i++ )
00179         {
00180             int new_index = (messages_received_ - i) % new_visuals.size();
00181             int old_index = (messages_received_ - i) % visuals_.size();
00182             new_visuals[ new_index ] = visuals_[ old_index ];
00183             visuals_[ old_index ] = NULL;
00184         }
00185 
00186         // Delete any remaining old visuals
00187         for( size_t i = 0; i < visuals_.size(); i++ ) {
00188             delete visuals_[ i ];
00189         }
00190 
00191         // We don't need to create any new visuals here, they are created as
00192         // needed when messages are received.
00193 
00194         // Put the new vector into the member variable version and let the
00195         // old one go out of scope.
00196         visuals_.swap( new_visuals );
00197     }
00198 
00199     void WrenchStampedDisplay::subscribe()
00200     {
00201         // If we are not actually enabled, don't do it.
00202         if ( !isEnabled() )
00203         {
00204             return;
00205         }
00206 
00207         // Try to subscribe to the current topic name (in ``topic_``).  Make
00208         // sure to catch exceptions and set the status to a descriptive
00209         // error message.
00210         try
00211         {
00212             sub_.subscribe( update_nh_, topic_, 10 );
00213             setStatus( rviz::status_levels::Ok, "Topic", "OK" );
00214         }
00215         catch( ros::Exception& e )
00216         {
00217             setStatus( rviz::status_levels::Error, "Topic",
00218                        std::string( "Error subscribing: " ) + e.what() );
00219         }
00220     }
00221 
00222     void WrenchStampedDisplay::unsubscribe()
00223     {
00224         sub_.unsubscribe();
00225     }
00226 
00227     void WrenchStampedDisplay::onEnable()
00228     {
00229         subscribe();
00230     }
00231 
00232     void WrenchStampedDisplay::onDisable()
00233     {
00234         unsubscribe();
00235         clear();
00236     }
00237 
00238     // When the "Fixed Frame" changes, we need to update our
00239     // tf::MessageFilter and erase existing visuals.
00240     void WrenchStampedDisplay::fixedFrameChanged()
00241     {
00242         tf_filter_->setTargetFrame( fixed_frame_ );
00243         clear();
00244     }
00245 
00246     // This is our callback to handle an incoming message.
00247     void WrenchStampedDisplay::incomingMessage( const geometry_msgs::WrenchStamped::ConstPtr& msg )
00248     {
00249         ++messages_received_;
00250 
00251         // Each display can have multiple status lines.  This one is called
00252         // "Topic" and says how many messages have been received in this case.
00253         std::stringstream ss;
00254         ss << messages_received_ << " messages received";
00255         setStatus( rviz::status_levels::Ok, "Topic", ss.str() );
00256 
00257         // Here we call the rviz::FrameManager to get the transform from the
00258         // fixed frame to the frame in the header of this Imu message.  If
00259         // it fails, we can't do anything else so we return.
00260         Ogre::Quaternion orientation;
00261         Ogre::Vector3 position;
00262         if( !vis_manager_->getFrameManager()->getTransform( msg->header.frame_id,
00263                                                             msg->header.stamp,
00264                                                             position, orientation ))
00265           {
00266             ROS_DEBUG( "Error transforming from frame '%s' to frame '%s'",
00267                        msg->header.frame_id.c_str(), fixed_frame_.c_str() );
00268             return;
00269           }
00270 
00271         // We are keeping a circular buffer of visual pointers.  This gets
00272         // the next one, or creates and stores it if it was missing.
00273         WrenchStampedVisual* visual = visuals_[ messages_received_ % history_length_ ];
00274         if( visual == NULL )
00275           {
00276             visual = new WrenchStampedVisual( vis_manager_->getSceneManager(), scene_node_ );
00277             visuals_[ messages_received_ % history_length_ ] = visual;
00278           }
00279 
00280         // Now set or update the contents of the chosen visual.
00281         visual->setMessage( msg );
00282         visual->setFramePosition( position );
00283         visual->setFrameOrientation( orientation );
00284         visual->setForceColor( force_color_.r_, force_color_.g_, force_color_.b_, alpha_ );
00285         visual->setTorqueColor( torque_color_.r_, torque_color_.g_, torque_color_.b_, alpha_ );
00286         visual->setScale( scale_ );
00287         visual->setWidth( width_ );
00288     }
00289 
00290     // Override rviz::Display's reset() function to add a call to clear().
00291     void WrenchStampedDisplay::reset()
00292     {
00293         Display::reset();
00294         clear();
00295     }
00296 
00297     void WrenchStampedDisplay::createProperties()
00298     {
00299         topic_property_ =
00300             property_manager_->createProperty<rviz::ROSTopicStringProperty>( "Topic",
00301                                                                              property_prefix_,
00302                                                                              boost::bind( &WrenchStampedDisplay::getTopic, this ),
00303                                                                              boost::bind( &WrenchStampedDisplay::setTopic, this, _1 ),
00304                                                                              parent_category_,
00305                                                                              this );
00306         setPropertyHelpText( topic_property_, "sensor_msgs::WrenchStamped topic to subscribe to." );
00307         rviz::ROSTopicStringPropertyPtr topic_prop = topic_property_.lock();
00308         topic_prop->setMessageType( ros::message_traits::datatype<geometry_msgs::WrenchStamped>() );
00309 
00310         force_color_property_ =
00311             property_manager_->createProperty<rviz::ColorProperty>( "Force Color",
00312                                                                     property_prefix_,
00313                                                                     boost::bind( &WrenchStampedDisplay::getForceColor, this ),
00314                                                                     boost::bind( &WrenchStampedDisplay::setForceColor, this, _1 ),
00315                                                                     parent_category_,
00316                                                                     this );
00317         setPropertyHelpText( force_color_property_, "Color to draw the force arrows." );
00318 
00319         torque_color_property_ =
00320             property_manager_->createProperty<rviz::ColorProperty>( "Torque Color",
00321                                                                     property_prefix_,
00322                                                                     boost::bind( &WrenchStampedDisplay::getTorqueColor, this ),
00323                                                                     boost::bind( &WrenchStampedDisplay::setTorqueColor, this, _1 ),
00324                                                                     parent_category_,
00325                                                                     this );
00326         setPropertyHelpText( torque_color_property_, "Color to draw the torque arrows." );
00327 
00328         alpha_property_ =
00329             property_manager_->createProperty<rviz::FloatProperty>( "Alpha",
00330                                                                     property_prefix_,
00331                                                                     boost::bind( &WrenchStampedDisplay::getAlpha, this ),
00332                                                                     boost::bind( &WrenchStampedDisplay::setAlpha, this, _1 ),
00333                                                                     parent_category_,
00334                                                                     this );
00335         setPropertyHelpText( alpha_property_, "0 is fully transparent, 1.0 is fully opaque." );
00336 
00337         scale_property_ =
00338             property_manager_->createProperty<rviz::FloatProperty>( "Arrow Scale",
00339                                                                     property_prefix_,
00340                                                                     boost::bind( &WrenchStampedDisplay::getScale, this ),
00341                                                                     boost::bind( &WrenchStampedDisplay::setScale, this, _1 ),
00342                                                                     parent_category_,
00343                                                                     this );
00344         setPropertyHelpText( alpha_property_, "arrow scale" );
00345 
00346 
00347         width_property_ =
00348             property_manager_->createProperty<rviz::FloatProperty>( "Arrow Width",
00349                                                                     property_prefix_,
00350                                                                     boost::bind( &WrenchStampedDisplay::getWidth, this ),
00351                                                                     boost::bind( &WrenchStampedDisplay::setWidth, this, _1 ),
00352                                                                     parent_category_,
00353                                                                     this );
00354         setPropertyHelpText( alpha_property_, "arrow width" );
00355 
00356 
00357         history_length_property_ =
00358             property_manager_->createProperty<rviz::IntProperty>( "History Length",
00359                                                                   property_prefix_,
00360                                                                   boost::bind( &WrenchStampedDisplay::getHistoryLength, this ),
00361                                                                   boost::bind( &WrenchStampedDisplay::setHistoryLength, this, _1 ),
00362                                                                   parent_category_,
00363                                                             this );
00364         setPropertyHelpText( history_length_property_, "Number of prior measurements to display." );
00365     }
00366 } // end namespace jsk_rviz_plugin
00367 
00368 // Tell pluginlib about this class.  It is important to do this in
00369 // global scope, outside our package's namespace.
00370 #include <pluginlib/class_list_macros.h>
00371 PLUGINLIB_DECLARE_CLASS( jsk_rviz_plugin, WrenchStamped, jsk_rviz_plugin::WrenchStampedDisplay, rviz::Display )
00372 
00373 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends Defines


jsk_rviz_plugins
Author(s): Kei Okada
autogenerated on Sat Mar 23 2013 20:30:29