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