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 "ambient_sound_visual.h"
00012 
00013 #include "ambient_sound_display.h"
00014 
00015 namespace jsk_rviz_plugins
00016 {
00017 
00018     
00019     
00020     
00021     AmbientSoundDisplay::AmbientSoundDisplay()
00022         : Display()
00023           , scene_node_( NULL )
00024           , messages_received_( 0 )
00025           , color_( .8, .2, .8 )       
00026           , alpha_( 1.0 )              
00027           , width_(0.1)
00028           , scale_(0.1)
00029     {
00030     }
00031 
00032     
00033     
00034     
00035     void AmbientSoundDisplay::onInitialize()
00036     {
00037         
00038         scene_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
00039 
00040         
00041         setHistoryLength( 1 );
00042 
00043         
00044         
00045         
00046         tf_filter_ =
00047             new tf::MessageFilter<jsk_hark_msgs::HarkPower>( *vis_manager_->getTFClient(),
00048                     "", 100, update_nh_ );
00049         tf_filter_->connectInput( sub_ );
00050         tf_filter_->registerCallback( boost::bind( &AmbientSoundDisplay::incomingMessage,
00051                     this, _1 ));
00052 
00053         
00054         
00055         
00056         vis_manager_->getFrameManager()
00057             ->registerFilterForTransformStatusCheck( tf_filter_, this );
00058     }
00059 
00060     AmbientSoundDisplay::~AmbientSoundDisplay()
00061     {
00062         unsubscribe();
00063         clear();
00064         for( size_t i = 0; i < visuals_.size(); i++ )
00065         {
00066             delete visuals_[ i ];
00067         }
00068 
00069         delete tf_filter_;
00070     }
00071 
00072     
00073     void AmbientSoundDisplay::clear()
00074     {
00075         for( size_t i = 0; i < visuals_.size(); i++ )
00076         {
00077             delete visuals_[ i ];
00078             visuals_[ i ] = NULL;
00079         }
00080         tf_filter_->clear();
00081         messages_received_ = 0;
00082         setStatus( rviz::status_levels::Warn, "Topic", "No messages received" );
00083     }
00084 
00085     void AmbientSoundDisplay::setTopic( const std::string& topic )
00086     {
00087         unsubscribe();
00088         clear();
00089         topic_ = topic;
00090         subscribe();
00091 
00092         
00093         propertyChanged( topic_property_ );
00094 
00095         
00096         causeRender();
00097     }
00098 
00099     void AmbientSoundDisplay::setColor( const rviz::Color& color )
00100     {
00101         color_ = color;
00102 
00103         propertyChanged( color_property_ );
00104         updateColorAndAlpha();
00105         causeRender();
00106     }
00107 
00108     void AmbientSoundDisplay::setAlpha( float alpha )
00109     {
00110         alpha_ = alpha;
00111 
00112         propertyChanged( alpha_property_ );
00113         updateColorAndAlpha();
00114         causeRender();
00115     }
00116 
00117     void AmbientSoundDisplay::setWidth( float width )
00118     {
00119         width_ = width;
00120         
00121         propertyChanged( width_property_ );
00122         updateColorAndAlpha();
00123         causeRender();
00124     }
00125 
00126     void AmbientSoundDisplay::setScale( float scale )
00127     {
00128         scale_ = scale;
00129         
00130         propertyChanged( scale_property_ );
00131         updateColorAndAlpha();
00132         causeRender();
00133     }
00134     
00135     
00136     void AmbientSoundDisplay::setBias( float bias )
00137     {
00138         bias_ = bias;
00139         
00140         propertyChanged( bias_property_ );
00141         updateColorAndAlpha();
00142         causeRender();
00143     }
00144 
00145     void AmbientSoundDisplay::setGrad( float grad )
00146     {
00147         grad_ = grad;
00148         
00149         propertyChanged( grad_property_ );
00150         updateColorAndAlpha();
00151         causeRender();
00152     }
00153 
00154     
00155     void AmbientSoundDisplay::updateColorAndAlpha()
00156     {
00157         for( size_t i = 0; i < visuals_.size(); i++ )
00158         {
00159             if( visuals_[ i ] )
00160             {
00161                 visuals_[ i ]->setColor( color_.r_, color_.g_, color_.b_, alpha_ );
00162             }
00163         }
00164     }
00165 
00166     
00167     void AmbientSoundDisplay::setHistoryLength( int length )
00168     {
00169         
00170         if( length < 1 )
00171         {
00172             length = 1;
00173         }
00174         
00175         if( history_length_ == length )
00176         {
00177             return;
00178         }
00179 
00180         
00181         history_length_ = length;
00182         propertyChanged( history_length_property_ );
00183 
00184         
00185         std::vector<AmbientSoundVisual*> new_visuals( history_length_, (AmbientSoundVisual*)0 );
00186 
00187         
00188         
00189         size_t copy_len =
00190             (new_visuals.size() > visuals_.size()) ?
00191             visuals_.size() : new_visuals.size();
00192         for( size_t i = 0; i < copy_len; i++ )
00193         {
00194             int new_index = (messages_received_ - i) % new_visuals.size();
00195             int old_index = (messages_received_ - i) % visuals_.size();
00196             new_visuals[ new_index ] = visuals_[ old_index ];
00197             visuals_[ old_index ] = NULL;
00198         }
00199 
00200         
00201         for( size_t i = 0; i < visuals_.size(); i++ ) {
00202             delete visuals_[ i ];
00203         }
00204 
00205         
00206         
00207 
00208         
00209         
00210         visuals_.swap( new_visuals );
00211     }
00212 
00213     void AmbientSoundDisplay::subscribe()
00214     {
00215         
00216         if ( !isEnabled() )
00217         {
00218             return;
00219         }
00220 
00221         
00222         
00223         
00224         try
00225         {
00226             sub_.subscribe( update_nh_, topic_, 10 );
00227             setStatus( rviz::status_levels::Ok, "Topic", "OK" );
00228         }
00229         catch( ros::Exception& e )
00230         {
00231             setStatus( rviz::status_levels::Error, "Topic",
00232                     std::string( "Error subscribing: " ) + e.what() );
00233         }
00234     }
00235 
00236     void AmbientSoundDisplay::unsubscribe()
00237     {
00238         sub_.unsubscribe();
00239     }
00240 
00241     void AmbientSoundDisplay::onEnable()
00242     {
00243         subscribe();
00244     }
00245 
00246     void AmbientSoundDisplay::onDisable()
00247     {
00248         unsubscribe();
00249         clear();
00250     }
00251 
00252     
00253     
00254     void AmbientSoundDisplay::fixedFrameChanged()
00255     {
00256         tf_filter_->setTargetFrame( fixed_frame_ );
00257         clear();
00258     }
00259 
00260     
00261     void AmbientSoundDisplay::incomingMessage( const jsk_hark_msgs::HarkPower::ConstPtr& msg )
00262     {
00263         ++messages_received_;
00264 
00265         
00266         
00267         std::stringstream ss;
00268         ss << messages_received_ << " messages received";
00269         setStatus( rviz::status_levels::Ok, "Topic", ss.str() );
00270 
00271         
00272         
00273         
00274         Ogre::Quaternion orientation;
00275         Ogre::Vector3 position;
00276         if( !vis_manager_->getFrameManager()->getTransform( msg->header.frame_id,
00277                     msg->header.stamp,
00278                     position, orientation ))
00279         {
00280             ROS_DEBUG( "Error transforming from frame '%s' to frame '%s'",
00281                     msg->header.frame_id.c_str(), fixed_frame_.c_str() );
00282             return;
00283         }
00284 
00285         
00286         
00287         AmbientSoundVisual* visual = visuals_[ messages_received_ % history_length_ ];
00288         if( visual == NULL )
00289         {
00290             visual = new AmbientSoundVisual( vis_manager_->getSceneManager(), scene_node_ );
00291             visuals_[ messages_received_ % history_length_ ] = visual;
00292         }
00293 
00294         
00295         visual->setFramePosition( position );
00296         visual->setFrameOrientation( orientation );
00297         visual->setColor( color_.r_, color_.g_, color_.b_, alpha_ );
00298         visual->setWidth( width_ );
00299         visual->setScale( scale_ );
00300         visual->setBias ( bias_ );
00301         visual->setGrad ( grad_ );
00302         visual->setMessage( msg );
00303     }
00304 
00305     
00306     void AmbientSoundDisplay::reset()
00307     {
00308         Display::reset();
00309         clear();
00310     }
00311 
00312     
00313     
00314     
00315     
00316     void AmbientSoundDisplay::createProperties()
00317     {
00318         topic_property_ =
00319             property_manager_->createProperty<rviz::ROSTopicStringProperty>( "Topic",
00320                     property_prefix_,
00321                     boost::bind( &AmbientSoundDisplay::getTopic, this ),
00322                     boost::bind( &AmbientSoundDisplay::setTopic, this, _1 ),
00323                     parent_category_,
00324                     this );
00325         setPropertyHelpText( topic_property_, "jsk_hark_msgs::HarkPower topic to subscribe to." );
00326         rviz::ROSTopicStringPropertyPtr topic_prop = topic_property_.lock();
00327         topic_prop->setMessageType( ros::message_traits::datatype<jsk_hark_msgs::HarkPower>() );
00328 
00329         color_property_ =
00330             property_manager_->createProperty<rviz::ColorProperty>( "Color",
00331                     property_prefix_,
00332                     boost::bind( &AmbientSoundDisplay::getColor, this ),
00333                     boost::bind( &AmbientSoundDisplay::setColor, this, _1 ),
00334                     parent_category_,
00335                     this );
00336         setPropertyHelpText( color_property_, "Color to draw the acceleration arrows." );
00337 
00338         alpha_property_ =
00339             property_manager_->createProperty<rviz::FloatProperty>( "Alpha",
00340                     property_prefix_,
00341                     boost::bind( &AmbientSoundDisplay::getAlpha, this ),
00342                     boost::bind( &AmbientSoundDisplay::setAlpha, this, _1 ),
00343                     parent_category_,
00344                     this );
00345         setPropertyHelpText( alpha_property_, "0 is fully transparent, 1.0 is fully opaque." );
00346 
00347         history_length_property_ =
00348             property_manager_->createProperty<rviz::IntProperty>( "History Length",
00349                     property_prefix_,
00350                     boost::bind( &AmbientSoundDisplay::getHistoryLength, this ),
00351                     boost::bind( &AmbientSoundDisplay::setHistoryLength, this, _1 ),
00352                     parent_category_,
00353                     this );
00354         setPropertyHelpText( history_length_property_, "Number of prior measurements to display." );
00355         
00356         width_property_ = 
00357             property_manager_->createProperty<rviz::FloatProperty>( "Width",
00358                     property_prefix_,
00359                     boost::bind( &AmbientSoundDisplay::getWidth, this ),
00360                     boost::bind( &AmbientSoundDisplay::setWidth, this, _1 ),
00361                     parent_category_,
00362                     this );
00363         setPropertyHelpText( width_property_, "Width of line" );
00364 
00365         scale_property_ = 
00366             property_manager_->createProperty<rviz::FloatProperty>( "Scale",
00367                     property_prefix_,
00368                     boost::bind( &AmbientSoundDisplay::getScale, this ),
00369                     boost::bind( &AmbientSoundDisplay::setScale, this, _1 ),
00370                     parent_category_,
00371                     this );
00372         setPropertyHelpText( scale_property_, "Scale of line" );
00373         
00374         grad_property_ = 
00375             property_manager_->createProperty<rviz::FloatProperty>( "Grad",
00376                     property_prefix_,
00377                     boost::bind( &AmbientSoundDisplay::getGrad, this ),
00378                     boost::bind( &AmbientSoundDisplay::setGrad, this, _1 ),
00379                     parent_category_,
00380                     this );
00381         setPropertyHelpText( grad_property_, "Graduation" );
00382 
00383         bias_property_ = 
00384             property_manager_->createProperty<rviz::FloatProperty>( "Bias",
00385                     property_prefix_,
00386                     boost::bind( &AmbientSoundDisplay::getBias, this ),
00387                     boost::bind( &AmbientSoundDisplay::setBias, this, _1 ),
00388                     parent_category_,
00389                     this );
00390         setPropertyHelpText( bias_property_, "Bias to subtract" );
00391     }
00392 
00393 } 
00394 
00395 
00396 
00397 #include <pluginlib/class_list_macros.h>
00398 PLUGINLIB_EXPORT_CLASS( jsk_rviz_plugins::AmbientSoundDisplay, rviz::Display )
00399