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 )
00025 , torque_color_( .8, .8, .2 )
00026 , alpha_( 1.0 )
00027 , scale_( 2.0 )
00028 , width_( 0.5 )
00029 {
00030 }
00031
00032 void WrenchStampedDisplay::onInitialize()
00033 {
00034
00035 scene_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
00036
00037
00038 setHistoryLength( 1 );
00039
00040
00041
00042
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
00051
00052
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
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
00087 propertyChanged( topic_property_ );
00088
00089
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
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
00153 void WrenchStampedDisplay::setHistoryLength( int length )
00154 {
00155
00156 if( length < 1 )
00157 {
00158 length = 1;
00159 }
00160
00161 if( history_length_ == length )
00162 {
00163 return;
00164 }
00165
00166
00167 history_length_ = length;
00168 propertyChanged( history_length_property_ );
00169
00170
00171 std::vector<WrenchStampedVisual*> new_visuals( history_length_, (WrenchStampedVisual*)0 );
00172
00173
00174
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
00187 for( size_t i = 0; i < visuals_.size(); i++ ) {
00188 delete visuals_[ i ];
00189 }
00190
00191
00192
00193
00194
00195
00196 visuals_.swap( new_visuals );
00197 }
00198
00199 void WrenchStampedDisplay::subscribe()
00200 {
00201
00202 if ( !isEnabled() )
00203 {
00204 return;
00205 }
00206
00207
00208
00209
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
00239
00240 void WrenchStampedDisplay::fixedFrameChanged()
00241 {
00242 tf_filter_->setTargetFrame( fixed_frame_ );
00243 clear();
00244 }
00245
00246
00247 void WrenchStampedDisplay::incomingMessage( const geometry_msgs::WrenchStamped::ConstPtr& msg )
00248 {
00249 ++messages_received_;
00250
00251
00252
00253 std::stringstream ss;
00254 ss << messages_received_ << " messages received";
00255 setStatus( rviz::status_levels::Ok, "Topic", ss.str() );
00256
00257
00258
00259
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
00272
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
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
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 }
00367
00368
00369
00370 #include <pluginlib/class_list_macros.h>
00371 PLUGINLIB_DECLARE_CLASS( jsk_rviz_plugin, WrenchStamped, jsk_rviz_plugin::WrenchStampedDisplay, rviz::Display )
00372
00373