effort_display.h
Go to the documentation of this file.
1 #ifndef EFFORT_DISPLAY_H
2 #define EFFORT_DISPLAY_H
3 
4 #ifndef Q_MOC_RUN
5 #include <boost/circular_buffer.hpp>
6 #endif
7 
8 #include <sensor_msgs/JointState.h>
10 
11 namespace Ogre
12 {
13 class SceneNode;
14 }
15 
16 namespace rviz
17 {
18 class FloatProperty;
19 class IntProperty;
20 class StringProperty;
21 class CategoryProperty;
22 class BoolProperty;
23 class RosTopicProperty;
24 } // namespace rviz
25 
26 namespace urdf
27 {
28 class Model;
29 }
30 
31 // MessageFilter to support message with out frame_id
32 // https://code.ros.org/trac/ros-pkg/ticket/5467
33 namespace tf
34 {
35 #ifdef TF_MESSAGEFILTER_DEBUG
36 #undef TF_MESSAGEFILTER_DEBUG
37 #endif
38 #define TF_MESSAGEFILTER_DEBUG(fmt, ...) \
39  ROS_DEBUG_NAMED("message_filter", "MessageFilter [target=%s]: " fmt, getTargetFramesString().c_str(), \
40  __VA_ARGS__)
41 
42 #ifdef TF_MESSAGEFILTER_WARN
43 #undef TF_MESSAGEFILTER_WARN
44 #endif
45 #define TF_MESSAGEFILTER_WARN(fmt, ...) \
46  ROS_WARN_NAMED("message_filter", "MessageFilter [target=%s]: " fmt, getTargetFramesString().c_str(), \
47  __VA_ARGS__)
48 
49 class MessageFilterJointState : public MessageFilter<sensor_msgs::JointState>
50 {
51  typedef sensor_msgs::JointState M;
52 
53 public:
56  typedef boost::function<void(const MConstPtr&, FilterFailureReason)> FailureCallback;
57  typedef boost::signals2::signal<void(const MConstPtr&, FilterFailureReason)> FailureSignal;
58 
59  // If you hit this assert your message does not have a header, or does not have the HasHeader trait
60  // defined for it
62 
75  const std::string& target_frame,
76  uint32_t queue_size,
78  ros::Duration max_rate = ros::Duration(0.01))
79  : MessageFilter<sensor_msgs::JointState>(tf, target_frame, queue_size, nh, max_rate)
80  , tf_(tf)
81  , nh_(nh)
82  , max_rate_(max_rate)
83  , queue_size_(queue_size)
84  {
85  init();
86 
87  setTargetFrame(target_frame);
88  }
89 
102  template <class F>
104  Transformer& tf,
105  const std::string& target_frame,
106  uint32_t queue_size,
108  ros::Duration max_rate = ros::Duration(0.01))
109  : MessageFilter<sensor_msgs::JointState>(f, tf, target_frame, queue_size, nh, max_rate)
110  , tf_(tf)
111  , nh_(nh)
112  , max_rate_(max_rate)
113  , queue_size_(queue_size)
114  {
115  init();
116 
117  setTargetFrame(target_frame);
118 
119  connectInput(f);
120  }
121 
126  template <class F>
127  void connectInput(F& f)
128  {
129  message_connection_.disconnect();
130  message_connection_ = f.registerCallback(&MessageFilterJointState::incomingMessage, this);
131  }
132 
137  {
138  message_connection_.disconnect();
139  tf_.removeTransformsChangedListener(tf_connection_);
140 
141  clear();
142 
144  "Successful Transforms: %llu, Failed Transforms: %llu, Discarded due to age: %llu, Transform "
145  "messages received: %llu, Messages received: %llu, Total dropped: %llu",
146  (long long unsigned int)successful_transform_count_,
147  (long long unsigned int)failed_transform_count_,
148  (long long unsigned int)failed_out_the_back_count_,
149  (long long unsigned int)transform_message_count_,
150  (long long unsigned int)incoming_message_count_, (long long unsigned int)dropped_message_count_);
151  }
152 
156  void setTargetFrame(const std::string& target_frame) override
157  {
158  std::vector<std::string> frames;
159  frames.push_back(target_frame);
160  setTargetFrames(frames);
161  }
162 
166  void setTargetFrames(const std::vector<std::string>& target_frames) override
167  {
168  boost::mutex::scoped_lock list_lock(messages_mutex_);
169  boost::mutex::scoped_lock string_lock(target_frames_string_mutex_);
170 
171  target_frames_ = target_frames;
172 
173  std::stringstream ss;
174  for (std::vector<std::string>::iterator it = target_frames_.begin(); it != target_frames_.end(); ++it)
175  {
176  *it = tf::resolve(tf_.getTFPrefix(), *it);
177  ss << *it << " ";
178  }
179  target_frames_string_ = ss.str();
180  }
184  std::string getTargetFramesString()
185  {
186  boost::mutex::scoped_lock lock(target_frames_string_mutex_);
187  return target_frames_string_;
188  };
189 
193  void setTolerance(const ros::Duration& tolerance) override
194  {
195  time_tolerance_ = tolerance;
196  }
197 
201  void clear() override
202  {
203  boost::mutex::scoped_lock lock(messages_mutex_);
204 
205  TF_MESSAGEFILTER_DEBUG("%s", "Cleared");
206 
207  messages_.clear();
208  message_count_ = 0;
209 
210  warned_about_unresolved_name_ = false;
211  warned_about_empty_frame_id_ = false;
212  }
213 
214  void add(const MEvent& evt)
215  {
216  boost::mutex::scoped_lock lock(messages_mutex_);
217 
218  testMessages();
219 
220  if (!testMessage(evt))
221  {
222  // If this message is about to push us past our queue size, erase the oldest message
223  if (queue_size_ != 0 && message_count_ + 1 > queue_size_)
224  {
225  ++dropped_message_count_;
226  const MEvent& front = messages_.front();
228  "Removed oldest message because buffer is full, count now %d (frame_id=%s, stamp=%f)",
229  message_count_, front.getMessage()->header.frame_id.c_str(),
230  front.getMessage()->header.stamp.toSec());
231  signalFailure(messages_.front(), filter_failure_reasons::Unknown);
232 
233  messages_.pop_front();
234  --message_count_;
235  }
236 
237  // Add the message to our list
238  messages_.push_back(evt);
239  ++message_count_;
240  }
241 
242  TF_MESSAGEFILTER_DEBUG("Added message in frame %s at time %.3f, count now %d",
243  evt.getMessage()->header.frame_id.c_str(),
244  evt.getMessage()->header.stamp.toSec(), message_count_);
245 
246  ++incoming_message_count_;
247  }
248 
255  void add(const MConstPtr& message)
256  {
257  boost::shared_ptr<std::map<std::string, std::string> > header(new std::map<std::string, std::string>);
258  (*header)["callerid"] = "unknown";
259  add(MEvent(message, header, ros::Time::now()));
260  }
261 
266  message_filters::Connection registerFailureCallback(const FailureCallback& callback)
267  {
268  boost::mutex::scoped_lock lock(failure_signal_mutex_);
269  return message_filters::Connection(boost::bind(&MessageFilterJointState::disconnectFailure, this, _1),
270  failure_signal_.connect(callback));
271  }
272 
273  void setQueueSize(uint32_t new_queue_size) override
274  {
275  queue_size_ = new_queue_size;
276  }
277 
278  uint32_t getQueueSize() override
279  {
280  return queue_size_;
281  }
282 
283 private:
284  void init()
285  {
286  message_count_ = 0;
287  new_transforms_ = false;
288  successful_transform_count_ = 0;
289  failed_transform_count_ = 0;
290  failed_out_the_back_count_ = 0;
291  transform_message_count_ = 0;
292  incoming_message_count_ = 0;
293  dropped_message_count_ = 0;
294  time_tolerance_ = ros::Duration(0.0);
295  warned_about_unresolved_name_ = false;
296  warned_about_empty_frame_id_ = false;
297 
298  tf_connection_ =
299  tf_.addTransformsChangedListener(boost::bind(&MessageFilterJointState::transformsChanged, this));
300 
301  max_rate_timer_ = nh_.createTimer(max_rate_, &MessageFilterJointState::maxRateTimerCallback, this);
302  }
303 
304  typedef std::list<MEvent> L_Event;
305 
306  bool testMessage(const MEvent& evt)
307  {
308  const MConstPtr& message = evt.getMessage();
309  std::string callerid = evt.getPublisherName();
310  std::string frame_id = ros::message_traits::FrameId<M>::value(*message);
312 
313  // FIXED
314  if (frame_id.empty())
315  frame_id = *(target_frames_.begin());
316  // Throw out messages which have an empty frame_id
317  if (frame_id.empty())
318  {
319  if (!warned_about_empty_frame_id_)
320  {
321  warned_about_empty_frame_id_ = true;
323  "Discarding message from [%s] due to empty frame_id. This message will only print once.",
324  callerid.c_str());
325  }
326  signalFailure(evt, filter_failure_reasons::EmptyFrameID);
327  return true;
328  }
329 
330  if (frame_id[0] != '/')
331  {
332  std::string unresolved = frame_id;
333  frame_id = tf::resolve(tf_.getTFPrefix(), frame_id);
334 
335  if (!warned_about_unresolved_name_)
336  {
337  warned_about_unresolved_name_ = true;
338  ROS_WARN("Message from [%s] has a non-fully-qualified frame_id [%s]. Resolved locally to [%s]. "
339  "This is will likely not work in multi-robot systems. This message will only print "
340  "once.",
341  callerid.c_str(), unresolved.c_str(), frame_id.c_str());
342  }
343  }
344 
345  // Throw out messages which are too old
347  for (std::vector<std::string>::iterator target_it = target_frames_.begin();
348  target_it != target_frames_.end(); ++target_it)
349  {
350  const std::string& target_frame = *target_it;
351 
352  if (target_frame != frame_id && stamp != ros::Time(0))
353  {
354  ros::Time latest_transform_time;
355 
356  tf_.getLatestCommonTime(frame_id, target_frame, latest_transform_time, nullptr);
357  if (stamp + tf_.getCacheLength() < latest_transform_time)
358  {
359  ++failed_out_the_back_count_;
360  ++dropped_message_count_;
362  "Discarding Message, in frame %s, Out of the back of Cache Time(stamp: %.3f + "
363  "cache_length: %.3f < latest_transform_time %.3f. Message Count now: %d",
364  message->header.frame_id.c_str(), message->header.stamp.toSec(),
365  tf_.getCacheLength().toSec(), latest_transform_time.toSec(), message_count_);
366 
367  last_out_the_back_stamp_ = stamp;
368  last_out_the_back_frame_ = frame_id;
369 
370  signalFailure(evt, filter_failure_reasons::OutTheBack);
371  return true;
372  }
373  }
374  }
375 
376  bool ready = !target_frames_.empty();
377  for (std::vector<std::string>::iterator target_it = target_frames_.begin();
378  ready && target_it != target_frames_.end(); ++target_it)
379  {
380  std::string& target_frame = *target_it;
381  if (time_tolerance_ != ros::Duration(0.0))
382  {
383  ready = ready && (tf_.canTransform(target_frame, frame_id, stamp) &&
384  tf_.canTransform(target_frame, frame_id, stamp + time_tolerance_));
385  }
386  else
387  {
388  ready = ready && tf_.canTransform(target_frame, frame_id, stamp);
389  }
390  }
391 
392  if (ready)
393  {
394  TF_MESSAGEFILTER_DEBUG("Message ready in frame %s at time %.3f, count now %d", frame_id.c_str(),
395  stamp.toSec(), message_count_);
396 
397  ++successful_transform_count_;
398 
399  signalMessage(evt);
400  }
401  else
402  {
403  ++failed_transform_count_;
404  }
405 
406  return ready;
407  }
408 
410  {
411  if (!messages_.empty() && getTargetFramesString() == " ")
412  {
413  ROS_WARN_NAMED("message_notifier", "MessageFilter [target=%s]: empty target frame",
414  getTargetFramesString().c_str());
415  }
416 
417  int i = 0;
418 
419  L_Event::iterator it = messages_.begin();
420  for (; it != messages_.end(); ++i)
421  {
422  MEvent& evt = *it;
423 
424  if (testMessage(evt))
425  {
426  --message_count_;
427  it = messages_.erase(it);
428  }
429  else
430  {
431  ++it;
432  }
433  }
434  }
435 
436  void maxRateTimerCallback(const ros::TimerEvent& /*unused*/)
437  {
438  boost::mutex::scoped_lock list_lock(messages_mutex_);
439  if (new_transforms_)
440  {
441  testMessages();
442  new_transforms_ = false;
443  }
444 
445  checkFailures();
446  }
447 
452  {
453  add(evt);
454  }
455 
457  {
458  new_transforms_ = true;
459 
460  ++transform_message_count_;
461  }
462 
464  {
465  if (next_failure_warning_.isZero())
466  {
467  next_failure_warning_ = ros::Time::now() + ros::Duration(15);
468  }
469 
470  if (ros::Time::now() >= next_failure_warning_)
471  {
472  if (incoming_message_count_ - message_count_ == 0)
473  {
474  return;
475  }
476 
477  double dropped_pct =
478  (double)dropped_message_count_ / (double)(incoming_message_count_ - message_count_);
479  if (dropped_pct > 0.95)
480  {
481  TF_MESSAGEFILTER_WARN("Dropped %.2f%% of messages so far. Please turn the [%s.message_notifier] "
482  "rosconsole logger to DEBUG for more information.",
483  dropped_pct * 100, ROSCONSOLE_DEFAULT_NAME);
484  next_failure_warning_ = ros::Time::now() + ros::Duration(60);
485 
486  if ((double)failed_out_the_back_count_ / (double)dropped_message_count_ > 0.5)
487  {
488  TF_MESSAGEFILTER_WARN(" The majority of dropped messages were due to messages growing older "
489  "than the TF cache time. The last message's timestamp was: %f, and the "
490  "last frame_id was: %s",
491  last_out_the_back_stamp_.toSec(), last_out_the_back_frame_.c_str());
492  }
493  }
494  }
495  }
496 
498  {
499  boost::mutex::scoped_lock lock(failure_signal_mutex_);
500  c.getBoostConnection().disconnect();
501  }
502 
503  void signalFailure(const MEvent& evt, FilterFailureReason reason)
504  {
505  boost::mutex::scoped_lock lock(failure_signal_mutex_);
506  failure_signal_(evt.getMessage(), reason);
507  }
508 
513  std::vector<std::string>
517  uint32_t queue_size_;
518 
519  L_Event messages_;
520  uint32_t message_count_;
521  boost::mutex messages_mutex_;
522 
524  volatile bool new_transforms_;
525 
529 
536 
539 
541 
543 
545  boost::signals2::connection tf_connection_;
547 
548  FailureSignal failure_signal_;
549  boost::mutex failure_signal_mutex_;
550 };
551 } // namespace tf
552 
553 #ifndef Q_MOC_RUN
555 #include <tf/message_filter.h>
556 #endif
557 
558 #include "rviz/display_context.h"
559 #include "rviz/frame_manager.h"
561 
562 namespace rviz
563 {
571 {
572  // No Q_OBJECT macro here, moc does not support Q_OBJECT in a templated class.
573 public:
577 
578  MessageFilterJointStateDisplay() : tf_filter_(nullptr), messages_received_(0)
579  {
580  QString message_type =
581  QString::fromStdString(ros::message_traits::datatype<sensor_msgs::JointState>());
582  topic_property_->setMessageType(message_type);
583  topic_property_->setDescription(message_type + " topic to subscribe to.");
584  }
585 
586  void onInitialize() override
587  {
588 // TODO(wjwwood): remove this and use tf2 interface instead
589 #ifndef _WIN32
590 #pragma GCC diagnostic push
591 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
592 #endif
593 
594  auto tf_client = context_->getTFClient();
595 
596 #ifndef _WIN32
597 #pragma GCC diagnostic pop
598 #endif
599  tf_filter_ = new tf::MessageFilterJointState(*tf_client, fixed_frame_.toStdString(), 10, update_nh_);
600 
601  tf_filter_->connectInput(sub_);
602  tf_filter_->registerCallback(boost::bind(&MessageFilterJointStateDisplay::incomingMessage, this, _1));
603 // TODO(wjwwood): remove this and use tf2 interface instead
604 #ifndef _WIN32
605 #pragma GCC diagnostic push
606 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
607 #endif
608 
609  context_->getFrameManager()->registerFilterForTransformStatusCheck(tf_filter_, this);
610 
611 #ifndef _WIN32
612 #pragma GCC diagnostic pop
613 #endif
614  }
615 
617  {
618  unsubscribe();
619  delete tf_filter_;
620  }
621 
622  void reset() override
623  {
624  Display::reset();
625  tf_filter_->clear();
626  messages_received_ = 0;
627  }
628 
629 protected:
630  void updateTopic() override
631  {
632  unsubscribe();
633  reset();
634  subscribe();
635  context_->queueRender();
636  }
637 
638  virtual void subscribe()
639  {
640  if (!isEnabled())
641  {
642  return;
643  }
644 
645  try
646  {
647  sub_.subscribe(update_nh_, topic_property_->getTopicStd(), 10);
648  setStatus(StatusProperty::Ok, "Topic", "OK");
649  }
650  catch (ros::Exception& e)
651  {
652  setStatus(StatusProperty::Error, "Topic", QString("Error subscribing: ") + e.what());
653  }
654  }
655 
656  virtual void unsubscribe()
657  {
658  sub_.unsubscribe();
659  }
660 
661  void onEnable() override
662  {
663  subscribe();
664  }
665 
666  void onDisable() override
667  {
668  unsubscribe();
669  reset();
670  }
671 
672  void fixedFrameChanged() override
673  {
674  tf_filter_->setTargetFrame(fixed_frame_.toStdString());
675  reset();
676  }
677 
681  void incomingMessage(const sensor_msgs::JointState::ConstPtr& msg)
682  {
683  if (!msg)
684  {
685  return;
686  }
687 
688  ++messages_received_;
689  setStatus(StatusProperty::Ok, "Topic", QString::number(messages_received_) + " messages received");
690 
691  processMessage(msg);
692  }
693 
697  virtual void processMessage(const sensor_msgs::JointState::ConstPtr& msg) = 0;
698 
702 };
703 } // namespace rviz
704 
705 namespace rviz
706 {
707 class JointInfo : public QObject
708 {
709  Q_OBJECT
710 public:
711  JointInfo(const std::string name, rviz::Property* parent_category);
712  ~JointInfo() override;
713 
714  void setEffort(double e);
715  double getEffort();
716  void setMaxEffort(double m);
717  double getMaxEffort();
718  bool getEnabled() const;
719 
721 
722 public Q_SLOTS:
723  void updateVisibility();
724 
725 private:
726  std::string name_;
727  double effort_, max_effort_;
728 
732 };
733 
734 typedef std::set<JointInfo*> S_JointInfo;
735 typedef std::vector<std::string> V_string;
736 
737 class EffortVisual;
738 
740 {
741  Q_OBJECT
742 public:
743  // Constructor. pluginlib::ClassLoader creates instances by calling
744  // the default constructor, so make sure you have one.
745  EffortDisplay();
746  ~EffortDisplay() override;
747 
748  // Overrides of public virtual functions from the Display class.
749  void onInitialize() override;
750  void reset() override;
751 
752 private Q_SLOTS:
753  // Helper function to apply color and alpha to all visuals.
754  void updateColorAndAlpha();
755  void updateHistoryLength();
756  void updateRobotDescription();
757  void updateTfPrefix();
758 
759  JointInfo* getJointInfo(const std::string& joint);
760  JointInfo* createJoint(const std::string& joint);
761 
762 protected:
763  // overrides from Display
764  void onEnable() override;
765  void onDisable() override;
766 
767  // load
768  using MessageFilterJointStateDisplay::load;
769  void load();
770  void clear();
771 
772  // The object for urdf model
774 
775  //
776  std::string robot_description_;
777 
778 private:
779  void processMessage(const sensor_msgs::JointState::ConstPtr& msg) override;
780 
781  // Storage for the list of visuals. It is a circular buffer where
782  // data gets popped from the front (oldest) and pushed to the back (newest)
783  boost::circular_buffer<boost::shared_ptr<EffortVisual> > visuals_;
784 
785  typedef std::map<std::string, JointInfo*> M_JointInfo;
786  M_JointInfo joints_;
787 
788  // Property objects for user-editable properties.
789  rviz::FloatProperty *alpha_property_, *width_property_, *scale_property_;
791 
796 };
797 } // namespace rviz
798 
799 #endif // EFFORT_DISPLAY_H
uint32_t message_count_
The number of messages in the list. (messages_.size() has linear cost)
message_filters::Subscriber< sensor_msgs::JointState > sub_
void add(const MConstPtr &message)
Manually add a message into this filter.
rviz::BoolProperty * all_enabled_property_
std::list< MEvent > L_Event
rviz::IntProperty * history_length_property_
void clear() override
Clear any messages currently in the queue.
boost::shared_ptr< M const > MConstPtr
bool testMessage(const MEvent &evt)
void setQueueSize(uint32_t new_queue_size) override
rviz::StringProperty * robot_description_property_
#define ROS_WARN_NAMED(name,...)
void onEnable() override
Derived classes override this to do the actual work of enabling themselves.
tf::MessageFilterJointState * tf_filter_
message_filters::Connection message_connection_
void init(const M_string &remappings)
Display subclass using a tf::MessageFilter, templated on the ROS message type.
boost::shared_ptr< M > getMessage() const
rviz::Property * joints_category_
Transformer & tf_
The Transformer used to determine if transformation data is available.
A single element of a property tree, with a name, value, description, and possibly children...
Definition: property.h:100
std::string name_
ros::Time last_update_
#define TF_MESSAGEFILTER_WARN(fmt,...)
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))
Constructor.
uint32_t queue_size_
The maximum number of messages we queue up.
std::map< std::string, JointInfo * > M_JointInfo
bool add(const actionlib::TwoIntsGoal &req, actionlib::TwoIntsResult &res)
Property specialized to enforce floating point max/min.
#define ROS_WARN(...)
void reset() override
Called to tell the display to clear its state.
Property specialized to provide max/min enforcement for integers.
Definition: int_property.h:37
void disconnectFailure(const message_filters::Connection &c)
boost::signals2::signal< void(const MConstPtr &, FilterFailureReason)> FailureSignal
boost::shared_ptr< urdf::Model > robot_model_
void connectInput(F &f)
Connect this filter&#39;s input to another filter&#39;s output. If this filter is already connected...
void incomingMessage(const sensor_msgs::JointState::ConstPtr &msg)
Incoming message callback. Checks if the message pointer is valid, increments messages_received_, then calls processMessage().
boost::function< void(const MConstPtr &, FilterFailureReason)> FailureCallback
void onInitialize() override
Override this function to do subclass-specific initialization.
void setTargetFrame(const std::string &target_frame) override
Set the frame you need to be able to transform to before getting a message callback.
std::string resolve(const std::string &prefix, const std::string &frame_name)
ros::NodeHandle nh_
The node used to subscribe to the topic.
boost::mutex target_frames_string_mutex_
void subscribe()
#define ROS_STATIC_ASSERT(cond)
rviz::FloatProperty * width_property_
std::string getTargetFramesString()
Get the target frames as a string for debugging.
~MessageFilterJointState() override
Destructor.
MessageFilterJointStateDisplay MFDClass
Convenience typedef so subclasses don&#39;t have to use the long templated class name to refer to their s...
message_filters::Connection registerFailureCallback(const FailureCallback &callback)
Register a callback to be called when a message is about to be dropped.
void incomingMessage(const ros::MessageEvent< M const > &evt)
Callback that happens when we receive a message on the message topic.
boost::signals2::connection getBoostConnection() const
uint32_t getQueueSize() override
rviz::FloatProperty * max_effort_property_
bool new_messages_
Used to skip waiting on new_data_.
void setTolerance(const ros::Duration &tolerance) override
Set the required tolerance for the notifier to return true.
std::vector< std::string > V_string
boost::signals2::connection tf_connection_
void signalFailure(const MEvent &evt, FilterFailureReason reason)
#define TF_MESSAGEFILTER_DEBUG(fmt,...)
void fixedFrameChanged() override
Called by setFixedFrame(). Override to respond to changes to fixed_frame_.
boost::circular_buffer< boost::shared_ptr< EffortVisual > > visuals_
Property specialized for string values.
rviz::StringProperty * tf_prefix_property_
Property specialized to provide getter for booleans.
Definition: bool_property.h:38
sensor_msgs::JointState M
rviz::FloatProperty * effort_property_
rviz::Property * category_
void onDisable() override
Derived classes override this to do the actual work of disabling themselves.
std::string robot_description_
static Time now()
void setTargetFrames(const std::vector< std::string > &target_frames) override
Set the frames you need to be able to transform to before getting a message callback.
const std::string header
boost::mutex messages_mutex_
The mutex used for locking message list operations.
void unsubscribe()
ros::MessageEvent< M const > MEvent
std::set< JointInfo * > S_JointInfo
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))
Constructor.
#define ROSCONSOLE_DEFAULT_NAME
std::vector< std::string > target_frames_
The frames we need to be able to transform to before a message is ready.
const std::string & getPublisherName() const
void add(const MEvent &evt)
void maxRateTimerCallback(const ros::TimerEvent &)
L_Event messages_
The message list.
Helper superclass for MessageFilterDisplay, needed because Qt&#39;s moc and c++ templates don&#39;t work nice...


rviz
Author(s): Dave Hershberger, David Gossow, Josh Faust
autogenerated on Fri Feb 3 2023 03:06:42