00001 #include <OGRE/OgreSceneNode.h>
00002 #include <OGRE/OgreSceneManager.h>
00003
00004 #include <tf/transform_listener.h>
00005 #include <tf/message_filter.h>
00006
00007 #include <rviz/visualization_manager.h>
00008 #include <rviz/properties/property.h>
00009 #include <rviz/properties/property_manager.h>
00010 #include <rviz/frame_manager.h>
00011
00012 #include <boost/foreach.hpp>
00013
00014 #include "effort_visual.h"
00015
00016 #include "effort_display.h"
00017
00018 #include <urdf/model.h>
00019
00020
00021
00022 namespace tf {
00023
00024 #define TF_MESSAGEFILTER_DEBUG(fmt, ...) \
00025 ROS_DEBUG_NAMED("message_filter", "MessageFilter [target=%s]: "fmt, getTargetFramesString().c_str(), __VA_ARGS__)
00026
00027 #define TF_MESSAGEFILTER_WARN(fmt, ...) \
00028 ROS_WARN_NAMED("message_filter", "MessageFilter [target=%s]: "fmt, getTargetFramesString().c_str(), __VA_ARGS__)
00029
00030 class MessageFilterJointState : public MessageFilter<sensor_msgs::JointState>
00031 {
00032 typedef sensor_msgs::JointState M;
00033 public:
00034 typedef boost::shared_ptr<M const> MConstPtr;
00035 typedef ros::MessageEvent<M const> MEvent;
00036 typedef boost::function<void(const MConstPtr&, FilterFailureReason)> FailureCallback;
00037 typedef boost::signal<void(const MConstPtr&, FilterFailureReason)> FailureSignal;
00038
00039
00040 ROS_STATIC_ASSERT(ros::message_traits::HasHeader<M>::value);
00041
00051 MessageFilterJointState(Transformer& tf, const std::string& target_frame, uint32_t queue_size, ros::NodeHandle nh = ros::NodeHandle(), ros::Duration max_rate = ros::Duration(0.01))
00052 : MessageFilter<sensor_msgs::JointState>(tf, target_frame, queue_size, nh, max_rate)
00053 , tf_(tf)
00054 , nh_(nh)
00055 , max_rate_(max_rate)
00056 , queue_size_(queue_size)
00057 {
00058 init();
00059
00060 setTargetFrame(target_frame);
00061 }
00062
00073 template<class F>
00074 MessageFilterJointState(F& f, Transformer& tf, const std::string& target_frame, uint32_t queue_size, ros::NodeHandle nh = ros::NodeHandle(), ros::Duration max_rate = ros::Duration(0.01))
00075 : tf_(tf)
00076 , nh_(nh)
00077 , max_rate_(max_rate)
00078 , queue_size_(queue_size)
00079 , MessageFilter<sensor_msgs::JointState>(f, tf, target_frame, queue_size, nh, max_rate)
00080 {
00081 init();
00082
00083 setTargetFrame(target_frame);
00084
00085 connectInput(f);
00086 }
00087
00091 template<class F>
00092 void connectInput(F& f)
00093 {
00094 message_connection_.disconnect();
00095 message_connection_ = f.registerCallback(&MessageFilterJointState::incomingMessage, this);
00096 }
00097
00101 ~MessageFilterJointState()
00102 {
00103 message_connection_.disconnect();
00104 tf_.removeTransformsChangedListener(tf_connection_);
00105
00106 clear();
00107
00108 TF_MESSAGEFILTER_DEBUG("Successful Transforms: %llu, Failed Transforms: %llu, Discarded due to age: %llu, Transform messages received: %llu, Messages received: %llu, Total dropped: %llu",
00109 (long long unsigned int)successful_transform_count_, (long long unsigned int)failed_transform_count_,
00110 (long long unsigned int)failed_out_the_back_count_, (long long unsigned int)transform_message_count_,
00111 (long long unsigned int)incoming_message_count_, (long long unsigned int)dropped_message_count_);
00112
00113 }
00114
00118 void setTargetFrame(const std::string& target_frame)
00119 {
00120 std::vector<std::string> frames;
00121 frames.push_back(target_frame);
00122 setTargetFrames(frames);
00123 }
00124
00128 void setTargetFrames(const std::vector<std::string>& target_frames)
00129 {
00130 boost::mutex::scoped_lock list_lock(messages_mutex_);
00131 boost::mutex::scoped_lock string_lock(target_frames_string_mutex_);
00132
00133 target_frames_ = target_frames;
00134
00135 std::stringstream ss;
00136 for (std::vector<std::string>::iterator it = target_frames_.begin(); it != target_frames_.end(); ++it)
00137 {
00138 *it = tf::resolve(tf_.getTFPrefix(), *it);
00139 ss << *it << " ";
00140 }
00141 target_frames_string_ = ss.str();
00142 }
00146 std::string getTargetFramesString()
00147 {
00148 boost::mutex::scoped_lock lock(target_frames_string_mutex_);
00149 return target_frames_string_;
00150 };
00151
00155 void setTolerance(const ros::Duration& tolerance)
00156 {
00157 time_tolerance_ = tolerance;
00158 }
00159
00163 void clear()
00164 {
00165 boost::mutex::scoped_lock lock(messages_mutex_);
00166
00167 TF_MESSAGEFILTER_DEBUG("%s", "Cleared");
00168
00169 messages_.clear();
00170 message_count_ = 0;
00171
00172 warned_about_unresolved_name_ = false;
00173 warned_about_empty_frame_id_ = false;
00174 }
00175
00176 void add(const MEvent& evt)
00177 {
00178 boost::mutex::scoped_lock lock(messages_mutex_);
00179
00180 testMessages();
00181
00182 if (!testMessage(evt))
00183 {
00184
00185 if (queue_size_ != 0 && message_count_ + 1 > queue_size_)
00186 {
00187 ++dropped_message_count_;
00188 const MEvent& front = messages_.front();
00189 TF_MESSAGEFILTER_DEBUG("Removed oldest message because buffer is full, count now %d (frame_id=%s, stamp=%f)", message_count_, front.getMessage()->header.frame_id.c_str(), front.getMessage()->header.stamp.toSec());
00190 signalFailure(messages_.front(), filter_failure_reasons::Unknown);
00191
00192 messages_.pop_front();
00193 --message_count_;
00194 }
00195
00196
00197 messages_.push_back(evt);
00198 ++message_count_;
00199 }
00200
00201 TF_MESSAGEFILTER_DEBUG("Added message in frame %s at time %.3f, count now %d", evt.getMessage()->header.frame_id.c_str(), evt.getMessage()->header.stamp.toSec(), message_count_);
00202
00203 ++incoming_message_count_;
00204 }
00205
00211 void add(const MConstPtr& message)
00212 {
00213 boost::shared_ptr<std::map<std::string, std::string> > header(new std::map<std::string, std::string>);
00214 (*header)["callerid"] = "unknown";
00215 add(MEvent(message, header, ros::Time::now()));
00216 }
00217
00222 message_filters::Connection registerFailureCallback(const FailureCallback& callback)
00223 {
00224 boost::mutex::scoped_lock lock(failure_signal_mutex_);
00225 return message_filters::Connection(boost::bind(&MessageFilterJointState::disconnectFailure, this, _1), failure_signal_.connect(callback));
00226 }
00227
00228 virtual void setQueueSize( uint32_t new_queue_size )
00229 {
00230 queue_size_ = new_queue_size;
00231 }
00232
00233 virtual uint32_t getQueueSize()
00234 {
00235 return queue_size_;
00236 }
00237
00238 private:
00239
00240 void init()
00241 {
00242 message_count_ = 0;
00243 new_transforms_ = false;
00244 successful_transform_count_ = 0;
00245 failed_transform_count_ = 0;
00246 failed_out_the_back_count_ = 0;
00247 transform_message_count_ = 0;
00248 incoming_message_count_ = 0;
00249 dropped_message_count_ = 0;
00250 time_tolerance_ = ros::Duration(0.0);
00251 warned_about_unresolved_name_ = false;
00252 warned_about_empty_frame_id_ = false;
00253
00254 tf_connection_ = tf_.addTransformsChangedListener(boost::bind(&MessageFilterJointState::transformsChanged, this));
00255
00256 max_rate_timer_ = nh_.createTimer(max_rate_, &MessageFilterJointState::maxRateTimerCallback, this);
00257 }
00258
00259 typedef std::list<MEvent> L_Event;
00260
00261 bool testMessage(const MEvent& evt)
00262 {
00263 const MConstPtr& message = evt.getMessage();
00264 std::string callerid = evt.getPublisherName();
00265 std::string frame_id = ros::message_traits::FrameId<M>::value(*message);
00266 ros::Time stamp = ros::message_traits::TimeStamp<M>::value(*message);
00267
00268
00269 if (frame_id.empty()) frame_id = * (target_frames_.begin());
00270
00271 if (frame_id.empty())
00272 {
00273 if (!warned_about_empty_frame_id_)
00274 {
00275 warned_about_empty_frame_id_ = true;
00276 TF_MESSAGEFILTER_WARN("Discarding message from [%s] due to empty frame_id. This message will only print once.", callerid.c_str());
00277 }
00278 signalFailure(evt, filter_failure_reasons::EmptyFrameID);
00279 return true;
00280 }
00281
00282 if (frame_id[0] != '/')
00283 {
00284 std::string unresolved = frame_id;
00285 frame_id = tf::resolve(tf_.getTFPrefix(), frame_id);
00286
00287 if (!warned_about_unresolved_name_)
00288 {
00289 warned_about_unresolved_name_ = true;
00290 ROS_WARN("Message from [%s] has a non-fully-qualified frame_id [%s]. Resolved locally to [%s]. This is will likely not work in multi-robot systems. This message will only print once.", callerid.c_str(), unresolved.c_str(), frame_id.c_str());
00291 }
00292 }
00293
00294
00296 for (std::vector<std::string>::iterator target_it = target_frames_.begin(); target_it != target_frames_.end(); ++target_it)
00297 {
00298 const std::string& target_frame = *target_it;
00299
00300 if (target_frame != frame_id && stamp != ros::Time(0))
00301 {
00302 ros::Time latest_transform_time ;
00303
00304 tf_.getLatestCommonTime(frame_id, target_frame, latest_transform_time, 0) ;
00305 if (stamp + tf_.getCacheLength() < latest_transform_time)
00306 {
00307 ++failed_out_the_back_count_;
00308 ++dropped_message_count_;
00309 TF_MESSAGEFILTER_DEBUG("Discarding Message, in frame %s, Out of the back of Cache Time(stamp: %.3f + cache_length: %.3f < latest_transform_time %.3f. Message Count now: %d", message->header.frame_id.c_str(), message->header.stamp.toSec(), tf_.getCacheLength().toSec(), latest_transform_time.toSec(), message_count_);
00310
00311 last_out_the_back_stamp_ = stamp;
00312 last_out_the_back_frame_ = frame_id;
00313
00314 signalFailure(evt, filter_failure_reasons::OutTheBack);
00315 return true;
00316 }
00317 }
00318
00319 }
00320
00321 bool ready = !target_frames_.empty();
00322 for (std::vector<std::string>::iterator target_it = target_frames_.begin(); ready && target_it != target_frames_.end(); ++target_it)
00323 {
00324 std::string& target_frame = *target_it;
00325 if (time_tolerance_ != ros::Duration(0.0))
00326 {
00327 ready = ready && (tf_.canTransform(target_frame, frame_id, stamp) &&
00328 tf_.canTransform(target_frame, frame_id, stamp + time_tolerance_) );
00329 }
00330 else
00331 {
00332 ready = ready && tf_.canTransform(target_frame, frame_id, stamp);
00333 }
00334 }
00335
00336 if (ready)
00337 {
00338 TF_MESSAGEFILTER_DEBUG("Message ready in frame %s at time %.3f, count now %d", frame_id.c_str(), stamp.toSec(), message_count_);
00339
00340 ++successful_transform_count_;
00341
00342 signalMessage(evt);
00343 }
00344 else
00345 {
00346 ++failed_transform_count_;
00347 }
00348
00349 return ready;
00350 }
00351
00352 void testMessages()
00353 {
00354 if (!messages_.empty() && getTargetFramesString() == " ")
00355 {
00356 ROS_WARN_NAMED("message_notifier", "MessageFilter [target=%s]: empty target frame", getTargetFramesString().c_str());
00357 }
00358
00359 int i = 0;
00360
00361 L_Event::iterator it = messages_.begin();
00362 for (; it != messages_.end(); ++i)
00363 {
00364 MEvent& evt = *it;
00365
00366 if (testMessage(evt))
00367 {
00368 --message_count_;
00369 it = messages_.erase(it);
00370 }
00371 else
00372 {
00373 ++it;
00374 }
00375 }
00376 }
00377
00378 void maxRateTimerCallback(const ros::TimerEvent&)
00379 {
00380 boost::mutex::scoped_lock list_lock(messages_mutex_);
00381 if (new_transforms_)
00382 {
00383 testMessages();
00384 new_transforms_ = false;
00385 }
00386
00387 checkFailures();
00388 }
00389
00393 void incomingMessage(const ros::MessageEvent<M const>& evt)
00394 {
00395 add(evt);
00396 }
00397
00398 void transformsChanged()
00399 {
00400 new_transforms_ = true;
00401
00402 ++transform_message_count_;
00403 }
00404
00405 void checkFailures()
00406 {
00407 if (next_failure_warning_.isZero())
00408 {
00409 next_failure_warning_ = ros::Time::now() + ros::Duration(15);
00410 }
00411
00412 if (ros::Time::now() >= next_failure_warning_)
00413 {
00414 if (incoming_message_count_ - message_count_ == 0)
00415 {
00416 return;
00417 }
00418
00419 double dropped_pct = (double)dropped_message_count_ / (double)(incoming_message_count_ - message_count_);
00420 if (dropped_pct > 0.95)
00421 {
00422 TF_MESSAGEFILTER_WARN("Dropped %.2f%% of messages so far. Please turn the [%s.message_notifier] rosconsole logger to DEBUG for more information.", dropped_pct*100, ROSCONSOLE_DEFAULT_NAME);
00423 next_failure_warning_ = ros::Time::now() + ros::Duration(60);
00424
00425 if ((double)failed_out_the_back_count_ / (double)dropped_message_count_ > 0.5)
00426 {
00427 TF_MESSAGEFILTER_WARN(" The majority of dropped messages were due to messages growing older than the TF cache time. The last message's timestamp was: %f, and the last frame_id was: %s", last_out_the_back_stamp_.toSec(), last_out_the_back_frame_.c_str());
00428 }
00429 }
00430 }
00431 }
00432
00433 void disconnectFailure(const message_filters::Connection& c)
00434 {
00435 boost::mutex::scoped_lock lock(failure_signal_mutex_);
00436 c.getBoostConnection().disconnect();
00437 }
00438
00439 void signalFailure(const MEvent& evt, FilterFailureReason reason)
00440 {
00441 boost::mutex::scoped_lock lock(failure_signal_mutex_);
00442 failure_signal_(evt.getMessage(), reason);
00443 }
00444
00445 Transformer& tf_;
00446 ros::NodeHandle nh_;
00447 ros::Duration max_rate_;
00448 ros::Timer max_rate_timer_;
00449 std::vector<std::string> target_frames_;
00450 std::string target_frames_string_;
00451 boost::mutex target_frames_string_mutex_;
00452 uint32_t queue_size_;
00453
00454 L_Event messages_;
00455 uint32_t message_count_;
00456 boost::mutex messages_mutex_;
00457
00458 bool new_messages_;
00459 volatile bool new_transforms_;
00460
00461 bool warned_about_unresolved_name_;
00462 bool warned_about_empty_frame_id_;
00463
00464 uint64_t successful_transform_count_;
00465 uint64_t failed_transform_count_;
00466 uint64_t failed_out_the_back_count_;
00467 uint64_t transform_message_count_;
00468 uint64_t incoming_message_count_;
00469 uint64_t dropped_message_count_;
00470
00471 ros::Time last_out_the_back_stamp_;
00472 std::string last_out_the_back_frame_;
00473
00474 ros::Time next_failure_warning_;
00475
00476 ros::Duration time_tolerance_;
00477
00478 boost::signals::connection tf_connection_;
00479 message_filters::Connection message_connection_;
00480
00481 FailureSignal failure_signal_;
00482 boost::mutex failure_signal_mutex_;
00483 };
00484 }
00485
00486 namespace jsk_rviz_plugin
00487 {
00488
00489 struct JointInfo {
00490 JointInfo();
00491
00492 bool isEnabled() { return enabled_; }
00493 void setEffort(double e) { effort_ = e; }
00494 double getEffort() { return effort_; }
00495 void setMaxEffort(double m) { max_effort_ = m; }
00496 double getMaxEffort() { return max_effort_; }
00497
00498 std::string name_;
00499 bool enabled_;
00500 double effort_, max_effort_;
00501
00502 ros::Time last_update_;
00503
00504 rviz::CategoryPropertyWPtr category_;
00505 rviz::BoolPropertyWPtr enabled_property_;
00506 rviz::FloatPropertyWPtr effort_property_;
00507 rviz::FloatPropertyWPtr max_effort_property_;
00508 };
00509
00510 JointInfo::JointInfo()
00511 : enabled_(true)
00512 {
00513 }
00514
00515 JointInfo* EffortDisplay::getJointInfo( const std::string& joint)
00516 {
00517 M_JointInfo::iterator it = joints_.find( joint );
00518 if ( it == joints_.end() )
00519 {
00520 return NULL;
00521 }
00522
00523 return it->second;
00524 }
00525
00526 void EffortDisplay::setJointEnabled(JointInfo* joint, bool enabled)
00527 {
00528 joint->enabled_ = enabled;
00529 propertyChanged(joint->enabled_property_);
00530 }
00531
00532 JointInfo* EffortDisplay::createJoint(const std::string &joint)
00533 {
00534 JointInfo *info = new JointInfo;
00535 joints_.insert( std::make_pair( joint, info ) );
00536
00537 info->name_ = joint;
00538 info->enabled_ = true;
00539 info->effort_ = 0;
00540 info->max_effort_ = 0;
00541 info->last_update_ = ros::Time::now();
00542
00543 std::string prefix = "Joints.";
00544 info->category_ = property_manager_->createCategory( info->name_, "", joints_category_, this);
00545
00546 prefix += info->name_ + ".";
00547
00548 info->enabled_property_ = property_manager_->createProperty<rviz::BoolProperty>( "Enabled", prefix, boost::bind( &JointInfo::isEnabled, info), boost::bind(&EffortDisplay::setJointEnabled, this, info, _1), info->category_, this);
00549 setPropertyHelpText(info->enabled_property_, "Enable or disable this individual joint.");
00550
00551 info->effort_property_ = property_manager_->createProperty<rviz::FloatProperty>( "Effort", prefix, boost::bind( &JointInfo::getEffort, info), boost::bind( &JointInfo::setEffort, info, _1), info->category_, this);
00552 setPropertyHelpText(info->effort_property_, "Effort value of this joint.");
00553
00554 info->max_effort_property_ = property_manager_->createProperty<rviz::FloatProperty>( "Max Effort", prefix, boost::bind( &JointInfo::getMaxEffort, info), boost::bind( &JointInfo::setMaxEffort, info, _1), info->category_, this);
00555 setPropertyHelpText(info->max_effort_property_, "Max Effort value of this joint.");
00556 updateJoint(info);
00557
00558 return info;
00559 }
00560
00561 void EffortDisplay::updateJoint(JointInfo* joint)
00562 {
00563 }
00564
00565 void EffortDisplay::deleteJoint(JointInfo* joint, bool delete_properties)
00566 {
00567 }
00568
00569 EffortDisplay::EffortDisplay()
00570 : Display()
00571 , scene_node_( NULL )
00572 , messages_received_( 0 )
00573 , alpha_( 1.0 )
00574 , width_( 0.02 )
00575 , scale_( 1.0 )
00576 , all_enabled_( true )
00577 {
00578 }
00579
00580 void EffortDisplay::onInitialize()
00581 {
00582
00583 scene_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
00584
00585
00586 setHistoryLength( 1 );
00587
00588
00589
00590
00591 tf_filter_ =
00592
00593 new tf::MessageFilterJointState( *vis_manager_->getTFClient(),
00594 "", 100, update_nh_, ros::Duration(0.1) );
00595 tf_filter_->connectInput( sub_ );
00596 tf_filter_->registerCallback( boost::bind( &EffortDisplay::incomingMessage,
00597 this, _1 ));
00598
00599
00600
00601
00602 vis_manager_->getFrameManager()
00603 ->registerFilterForTransformStatusCheck( tf_filter_, this );
00604
00605 }
00606
00607 EffortDisplay::~EffortDisplay()
00608 {
00609 unsubscribe();
00610 clear();
00611 visuals_.clear();
00612
00613 delete tf_filter_;
00614 }
00615
00616
00617 void EffortDisplay::clear()
00618 {
00619 for( size_t i = 0; i < visuals_.size(); i++ ) {
00620 delete visuals_[ i ];
00621 visuals_[ i ] = NULL;
00622 }
00623 tf_filter_->clear();
00624 messages_received_ = 0;
00625 setStatus( rviz::status_levels::Warn, "Topic", "No messages received" );
00626 }
00627
00628 void EffortDisplay::setTopic( const std::string& topic )
00629 {
00630 unsubscribe();
00631 clear();
00632 topic_ = topic;
00633 subscribe();
00634
00635
00636 propertyChanged( topic_property_ );
00637
00638
00639 causeRender();
00640 }
00641
00642 void EffortDisplay::setAlpha( float alpha )
00643 {
00644 alpha_ = alpha;
00645
00646 propertyChanged( alpha_property_ );
00647 updateColorAndAlpha();
00648 causeRender();
00649 }
00650
00651 void EffortDisplay::setWidth( float width )
00652 {
00653 width_ = width;
00654
00655 propertyChanged( width_property_ );
00656 updateColorAndAlpha();
00657 causeRender();
00658 }
00659
00660 void EffortDisplay::setScale( float scale )
00661 {
00662 scale_ = scale;
00663
00664 propertyChanged( scale_property_ );
00665 updateColorAndAlpha();
00666 causeRender();
00667 }
00668
00669
00670 void EffortDisplay::updateColorAndAlpha()
00671 {
00672 BOOST_FOREACH(MapEffortVisual::value_type visual, visuals_)
00673 {
00674 if ( visual ) {
00675 visual->setWidth( width_ );
00676 visual->setScale( scale_ );
00677 }
00678 }
00679 }
00680
00681
00682 void EffortDisplay::setHistoryLength( int length )
00683 {
00684
00685 if( length < 1 )
00686 {
00687 length = 1;
00688 }
00689
00690 if( history_length_ == length )
00691 {
00692 return;
00693 }
00694
00695
00696 history_length_ = length;
00697 propertyChanged( history_length_property_ );
00698
00699
00700 std::vector<EffortVisual*> new_visuals( history_length_, (EffortVisual*)0 );
00701
00702
00703
00704 size_t copy_len =
00705 (new_visuals.size() > visuals_.size()) ?
00706 visuals_.size() : new_visuals.size();
00707 for( size_t i = 0; i < copy_len; i++ )
00708 {
00709 int new_index = (messages_received_ - i) % new_visuals.size();
00710 int old_index = (messages_received_ - i) % visuals_.size();
00711 new_visuals[ new_index ] = visuals_[ old_index ];
00712 visuals_[ old_index ] = NULL;
00713 }
00714
00715
00716 for( size_t i = 0; i < visuals_.size(); i++ ) {
00717 delete visuals_[ i ];
00718 }
00719
00720
00721
00722
00723
00724
00725 visuals_.swap( new_visuals );
00726 }
00727
00728 void EffortDisplay::load()
00729 {
00730
00731 std::string urdf_string;
00732 update_nh_.getParam(description_param_, urdf_string);
00733 urdfModel = boost::shared_ptr<urdf::Model>(new urdf::Model());
00734 if (!urdfModel->initString(urdf_string))
00735 {
00736 ROS_ERROR("Unable to parse URDF description!");
00737 setStatus(rviz::status_levels::Error, "URDF", "Unable to parse robot model description!");
00738 return;
00739 }
00740 setStatus(rviz::status_levels::Ok, "URDF", "Ok");
00741
00742 for (std::map<std::string, boost::shared_ptr<urdf::Joint> >::iterator it = urdfModel->joints_.begin(); it != urdfModel->joints_.end(); it ++ ) {
00743 boost::shared_ptr<urdf::Joint> joint = it->second;
00744 if ( joint->type == urdf::Joint::REVOLUTE ) {
00745 std::string joint_name = it->first;
00746 boost::shared_ptr<urdf::JointLimits> limit = joint->limits;
00747 joints_[joint_name] = createJoint(joint_name);
00748 joints_[joint_name]->setMaxEffort(limit->effort);
00749 }
00750 }
00751 }
00752
00753 void EffortDisplay::setRobotDescription( const std::string& description_param )
00754 {
00755 description_param_ = description_param;
00756
00757 propertyChanged(robot_description_property_);
00758
00759 if ( isEnabled() )
00760 {
00761 load();
00762 unsubscribe();
00763 subscribe();
00764 causeRender();
00765 }
00766 }
00767
00768 void EffortDisplay::setAllEnabled(bool enabled)
00769 {
00770 all_enabled_ = enabled;
00771
00772 M_JointInfo::iterator it = joints_.begin();
00773 M_JointInfo::iterator end = joints_.end();
00774 for (; it != end; ++it)
00775 {
00776 JointInfo* joint = it->second;
00777
00778 setJointEnabled(joint, enabled);
00779 }
00780
00781 propertyChanged(all_enabled_property_);
00782 }
00783
00784
00785 void EffortDisplay::subscribe()
00786 {
00787
00788 if ( !isEnabled() )
00789 {
00790 return;
00791 }
00792
00793
00794 if ( ! urdfModel ) {
00795 setStatus( rviz::status_levels::Warn, "URDF", "Valid robot model is not loaded" );
00796 return;
00797 }
00798
00799
00800
00801
00802 try
00803 {
00804 sub_.subscribe( update_nh_, topic_, 10 );
00805 setStatus( rviz::status_levels::Ok, "Topic", "OK" );
00806 }
00807 catch( ros::Exception& e )
00808 {
00809 setStatus( rviz::status_levels::Error, "Topic",
00810 std::string( "Error subscribing: " ) + e.what() );
00811 }
00812 }
00813
00814 void EffortDisplay::unsubscribe()
00815 {
00816 sub_.unsubscribe();
00817 }
00818
00819 void EffortDisplay::onEnable()
00820 {
00821 subscribe();
00822 }
00823
00824 void EffortDisplay::onDisable()
00825 {
00826 unsubscribe();
00827 clear();
00828 }
00829
00830
00831
00832 void EffortDisplay::fixedFrameChanged()
00833 {
00834 tf_filter_->setTargetFrame( fixed_frame_ );
00835 clear();
00836 }
00837
00838
00839 void EffortDisplay::incomingMessage( const sensor_msgs::JointState::ConstPtr& msg )
00840 {
00841 ++messages_received_;
00842
00843
00844
00845 std::stringstream ss;
00846 ss << messages_received_ << " messages received";
00847 setStatus( rviz::status_levels::Ok, "Topic", ss.str() );
00848
00849
00850
00851 EffortVisual* visual = visuals_[ messages_received_ % history_length_ ];
00852 if( visual == NULL )
00853 {
00854 visual = new EffortVisual( vis_manager_->getSceneManager(), scene_node_ , urdfModel );
00855 visuals_[ messages_received_ % history_length_ ] = visual;
00856 }
00857
00858 V_string joints;
00859 int joint_num = msg->name.size();
00860 for (int i = 0; i < joint_num; i++ )
00861 {
00862 std::string joint_name = msg->name[i];
00863 JointInfo* joint_info = getJointInfo(joint_name);
00864 if ( !joint_info ) continue;
00865
00866
00867 joint_info->setEffort(msg->effort[i]);
00868
00869
00870 if ( ros::Time::now() - joint_info->last_update_ > ros::Duration(0.2) ) {
00871 propertyChanged(joint_info->effort_property_);
00872 joint_info->last_update_ = ros::Time::now();
00873 }
00874
00875 const urdf::Joint* joint = urdfModel->getJoint(joint_name).get();
00876 int joint_type = joint->type;
00877 if ( joint_type == urdf::Joint::REVOLUTE )
00878 {
00879
00880 std::string parent_link_name = joint->child_link_name;
00881 Ogre::Quaternion orientation;
00882 Ogre::Vector3 position;
00883
00884
00885
00886
00887 if( !vis_manager_->getFrameManager()->getTransform( parent_link_name,
00888 ros::Time(),
00889
00890 position, orientation ))
00891 {
00892 ROS_DEBUG( "Error transforming from frame '%s' to frame '%s'",
00893 parent_link_name.c_str(), fixed_frame_.c_str() );
00894 continue;
00895 }
00896 ;
00897 tf::Vector3 axis_joint(joint->axis.x, joint->axis.y, joint->axis.z);
00898 tf::Vector3 axis_z(0,0,1);
00899 tf::Quaternion axis_rotation(tf::tfCross(axis_joint, axis_z), tf::tfAngle(axis_joint, axis_z));
00900 if ( std::isnan(axis_rotation.x()) ||
00901 std::isnan(axis_rotation.y()) ||
00902 std::isnan(axis_rotation.z()) ) axis_rotation = tf::Quaternion::getIdentity();
00903
00904 tf::Quaternion axis_orientation(orientation.x, orientation.y, orientation.z, orientation.w);
00905 tf::Quaternion axis_rot = axis_orientation * axis_rotation;
00906 Ogre::Quaternion joint_orientation(Ogre::Real(axis_rot.w()), Ogre::Real(axis_rot.x()), Ogre::Real(axis_rot.y()), Ogre::Real(axis_rot.z()));
00907 visual->setFramePosition( joint_name, position );
00908 visual->setFrameOrientation( joint_name, joint_orientation );
00909 visual->setFrameEnabled( joint_name, joint_info->isEnabled() );
00910 }
00911 }
00912
00913
00914
00915 visual->setWidth( width_ );
00916 visual->setScale( scale_ );
00917 visual->setMessage( msg );
00918 }
00919
00920
00921 void EffortDisplay::reset()
00922 {
00923 Display::reset();
00924 clear();
00925 }
00926
00927 void EffortDisplay::createProperties()
00928 {
00929 topic_property_ =
00930 property_manager_->createProperty<rviz::ROSTopicStringProperty>( "Topic",
00931 property_prefix_,
00932 boost::bind( &EffortDisplay::getTopic, this ),
00933 boost::bind( &EffortDisplay::setTopic, this, _1 ),
00934 parent_category_,
00935 this );
00936 setPropertyHelpText( topic_property_, "sensor_msgs::Effort topic to subscribe to." );
00937 rviz::ROSTopicStringPropertyPtr topic_prop = topic_property_.lock();
00938 topic_prop->setMessageType( ros::message_traits::datatype<sensor_msgs::JointState>() );
00939
00940 alpha_property_ =
00941 property_manager_->createProperty<rviz::FloatProperty>( "Alpha",
00942 property_prefix_,
00943 boost::bind( &EffortDisplay::getAlpha, this ),
00944 boost::bind( &EffortDisplay::setAlpha, this, _1 ),
00945 parent_category_,
00946 this );
00947 setPropertyHelpText( alpha_property_, "0 is fully transparent, 1.0 is fully opaque." );
00948
00949 width_property_ =
00950 property_manager_->createProperty<rviz::FloatProperty>( "Width",
00951 property_prefix_,
00952 boost::bind( &EffortDisplay::getWidth, this ),
00953 boost::bind( &EffortDisplay::setWidth, this, _1 ),
00954 parent_category_,
00955 this );
00956 setPropertyHelpText( width_property_, "Width to drow effort circle" );
00957
00958 scale_property_ =
00959 property_manager_->createProperty<rviz::FloatProperty>( "Scale",
00960 property_prefix_,
00961 boost::bind( &EffortDisplay::getScale, this ),
00962 boost::bind( &EffortDisplay::setScale, this, _1 ),
00963 parent_category_,
00964 this );
00965 setPropertyHelpText( scale_property_, "Scale to drow effort circle" );
00966
00967 history_length_property_ =
00968 property_manager_->createProperty<rviz::IntProperty>( "History Length",
00969 property_prefix_,
00970 boost::bind( &EffortDisplay::getHistoryLength, this ),
00971 boost::bind( &EffortDisplay::setHistoryLength, this, _1 ),
00972 parent_category_,
00973 this );
00974 setPropertyHelpText( history_length_property_, "Number of prior measurements to display." );
00975
00976 robot_description_property_ = property_manager_->createProperty<rviz::StringProperty>( "Robot Description", property_prefix_, boost::bind( &EffortDisplay::getRobotDescription, this ), boost::bind( &EffortDisplay::setRobotDescription, this, _1 ), parent_category_, this );
00977 rviz::setPropertyHelpText(robot_description_property_, "Name of the parameter to search for to load the robot description.");
00978
00979
00980 joints_category_ =
00981 property_manager_->createCategory( "Joints",
00982 property_prefix_,
00983 parent_category_,
00984 this );
00985 setPropertyHelpText( joints_category_, "The list of all joints." );
00986 rviz::CategoryPropertyPtr cat_prop = joints_category_.lock();
00987 cat_prop->collapse();
00988 all_enabled_property_ = property_manager_->createProperty<rviz::BoolProperty>( "All Enabled", property_prefix_, boost::bind( &EffortDisplay::getAllEnabled, this ),
00989 boost::bind( &EffortDisplay::setAllEnabled, this, _1 ), joints_category_, this );
00990 setPropertyHelpText(all_enabled_property_, "Whether all the joints should be enabled or not.");
00991
00992 }
00993 }
00994
00995
00996
00997 #include <pluginlib/class_list_macros.h>
00998 PLUGINLIB_DECLARE_CLASS( jsk_rviz_plugin, Effort, jsk_rviz_plugin::EffortDisplay, rviz::Display )
00999
01000