1 #ifndef EFFORT_DISPLAY_H 2 #define EFFORT_DISPLAY_H 5 #include <boost/circular_buffer.hpp> 8 #include <sensor_msgs/JointState.h> 21 class CategoryProperty;
23 class RosTopicProperty;
35 #ifdef TF_MESSAGEFILTER_DEBUG 36 #undef TF_MESSAGEFILTER_DEBUG 38 #define TF_MESSAGEFILTER_DEBUG(fmt, ...) \ 39 ROS_DEBUG_NAMED("message_filter", "MessageFilter [target=%s]: " fmt, getTargetFramesString().c_str(), \ 42 #ifdef TF_MESSAGEFILTER_WARN 43 #undef TF_MESSAGEFILTER_WARN 45 #define TF_MESSAGEFILTER_WARN(fmt, ...) \ 46 ROS_WARN_NAMED("message_filter", "MessageFilter [target=%s]: " fmt, getTargetFramesString().c_str(), \ 51 typedef sensor_msgs::JointState
M;
56 typedef boost::function<void(const MConstPtr&, FilterFailureReason)>
FailureCallback;
57 typedef boost::signals2::signal<void(const MConstPtr&, FilterFailureReason)>
FailureSignal;
75 const std::string& target_frame,
83 , queue_size_(queue_size)
87 setTargetFrame(target_frame);
105 const std::string& target_frame,
112 , max_rate_(max_rate)
113 , queue_size_(queue_size)
117 setTargetFrame(target_frame);
129 message_connection_.disconnect();
130 message_connection_ = f.registerCallback(&MessageFilterJointState::incomingMessage,
this);
138 message_connection_.disconnect();
139 tf_.removeTransformsChangedListener(tf_connection_);
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_);
158 std::vector<std::string> frames;
159 frames.push_back(target_frame);
160 setTargetFrames(frames);
168 boost::mutex::scoped_lock list_lock(messages_mutex_);
169 boost::mutex::scoped_lock string_lock(target_frames_string_mutex_);
171 target_frames_ = target_frames;
173 std::stringstream ss;
174 for (std::vector<std::string>::iterator it = target_frames_.begin(); it != target_frames_.end(); ++it)
179 target_frames_string_ = ss.str();
186 boost::mutex::scoped_lock lock(target_frames_string_mutex_);
187 return target_frames_string_;
195 time_tolerance_ = tolerance;
203 boost::mutex::scoped_lock lock(messages_mutex_);
210 warned_about_unresolved_name_ =
false;
211 warned_about_empty_frame_id_ =
false;
214 void add(
const MEvent& evt)
216 boost::mutex::scoped_lock lock(messages_mutex_);
220 if (!testMessage(evt))
223 if (queue_size_ != 0 && message_count_ + 1 > queue_size_)
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(),
231 signalFailure(messages_.front(), filter_failure_reasons::Unknown);
233 messages_.pop_front();
238 messages_.push_back(evt);
244 evt.
getMessage()->header.stamp.toSec(), message_count_);
246 ++incoming_message_count_;
255 void add(
const MConstPtr& message)
258 (*header)[
"callerid"] =
"unknown";
268 boost::mutex::scoped_lock lock(failure_signal_mutex_);
270 failure_signal_.connect(callback));
275 queue_size_ = new_queue_size;
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;
295 warned_about_unresolved_name_ =
false;
296 warned_about_empty_frame_id_ =
false;
299 tf_.addTransformsChangedListener(boost::bind(&MessageFilterJointState::transformsChanged,
this));
301 max_rate_timer_ = nh_.createTimer(max_rate_, &MessageFilterJointState::maxRateTimerCallback,
this);
314 if (frame_id.empty())
315 frame_id = *(target_frames_.begin());
317 if (frame_id.empty())
319 if (!warned_about_empty_frame_id_)
321 warned_about_empty_frame_id_ =
true;
323 "Discarding message from [%s] due to empty frame_id. This message will only print once.",
326 signalFailure(evt, filter_failure_reasons::EmptyFrameID);
330 if (frame_id[0] !=
'/')
332 std::string unresolved = frame_id;
333 frame_id =
tf::resolve(tf_.getTFPrefix(), frame_id);
335 if (!warned_about_unresolved_name_)
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 " 341 callerid.c_str(), unresolved.c_str(), frame_id.c_str());
347 for (std::vector<std::string>::iterator target_it = target_frames_.begin();
348 target_it != target_frames_.end(); ++target_it)
350 const std::string& target_frame = *target_it;
352 if (target_frame != frame_id && stamp !=
ros::Time(0))
356 tf_.getLatestCommonTime(frame_id, target_frame, latest_transform_time,
nullptr);
357 if (stamp + tf_.getCacheLength() < latest_transform_time)
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_);
367 last_out_the_back_stamp_ = stamp;
368 last_out_the_back_frame_ = frame_id;
370 signalFailure(evt, filter_failure_reasons::OutTheBack);
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)
380 std::string& target_frame = *target_it;
383 ready = ready && (tf_.canTransform(target_frame, frame_id, stamp) &&
384 tf_.canTransform(target_frame, frame_id, stamp + time_tolerance_));
388 ready = ready && tf_.canTransform(target_frame, frame_id, stamp);
395 stamp.
toSec(), message_count_);
397 ++successful_transform_count_;
403 ++failed_transform_count_;
411 if (!messages_.empty() && getTargetFramesString() ==
" ")
413 ROS_WARN_NAMED(
"message_notifier",
"MessageFilter [target=%s]: empty target frame",
414 getTargetFramesString().c_str());
419 L_Event::iterator it = messages_.begin();
420 for (; it != messages_.end(); ++i)
424 if (testMessage(evt))
427 it = messages_.erase(it);
438 boost::mutex::scoped_lock list_lock(messages_mutex_);
442 new_transforms_ =
false;
458 new_transforms_ =
true;
460 ++transform_message_count_;
465 if (next_failure_warning_.isZero())
472 if (incoming_message_count_ - message_count_ == 0)
478 (double)dropped_message_count_ / (
double)(incoming_message_count_ - message_count_);
479 if (dropped_pct > 0.95)
482 "rosconsole logger to DEBUG for more information.",
486 if ((
double)failed_out_the_back_count_ / (
double)dropped_message_count_ > 0.5)
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());
499 boost::mutex::scoped_lock lock(failure_signal_mutex_);
505 boost::mutex::scoped_lock lock(failure_signal_mutex_);
513 std::vector<std::string>
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.");
590 #pragma GCC diagnostic push 591 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 594 auto tf_client = context_->getTFClient();
597 #pragma GCC diagnostic pop 602 tf_filter_->registerCallback(boost::bind(&MessageFilterJointStateDisplay::incomingMessage,
this, _1));
605 #pragma GCC diagnostic push 606 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 609 context_->getFrameManager()->registerFilterForTransformStatusCheck(tf_filter_,
this);
612 #pragma GCC diagnostic pop 626 messages_received_ = 0;
635 context_->queueRender();
647 sub_.subscribe(update_nh_, topic_property_->getTopicStd(), 10);
648 setStatus(StatusProperty::Ok,
"Topic",
"OK");
652 setStatus(StatusProperty::Error,
"Topic", QString(
"Error subscribing: ") + e.what());
674 tf_filter_->setTargetFrame(fixed_frame_.toStdString());
688 ++messages_received_;
689 setStatus(StatusProperty::Ok,
"Topic", QString::number(messages_received_) +
" messages received");
697 virtual void processMessage(
const sensor_msgs::JointState::ConstPtr& msg) = 0;
714 void setEffort(
double e);
716 void setMaxEffort(
double m);
717 double getMaxEffort();
718 bool getEnabled()
const;
723 void updateVisibility();
749 void onInitialize()
override;
750 void reset()
override;
754 void updateColorAndAlpha();
755 void updateHistoryLength();
756 void updateRobotDescription();
757 void updateTfPrefix();
759 JointInfo* getJointInfo(
const std::string& joint);
760 JointInfo* createJoint(
const std::string& joint);
764 void onEnable()
override;
765 void onDisable()
override;
768 using MessageFilterJointStateDisplay::load;
779 void processMessage(
const sensor_msgs::JointState::ConstPtr& msg)
override;
783 boost::circular_buffer<boost::shared_ptr<EffortVisual> >
visuals_;
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_
uint64_t failed_out_the_back_count_
void add(const MConstPtr &message)
Manually add a message into this filter.
rviz::BoolProperty * all_enabled_property_
std::list< MEvent > L_Event
uint64_t dropped_message_count_
rviz::IntProperty * history_length_property_
void clear() override
Clear any messages currently in the queue.
boost::shared_ptr< M const > MConstPtr
MessageFilterJointStateDisplay()
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_
FailureSignal failure_signal_
boost::mutex failure_signal_mutex_
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_
uint32_t messages_received_
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...
#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.
bool warned_about_empty_frame_id_
uint32_t queue_size_
The maximum number of messages we queue up.
std::map< std::string, JointInfo * > M_JointInfo
~MessageFilterJointStateDisplay() override
bool add(const actionlib::TwoIntsGoal &req, actionlib::TwoIntsResult &res)
Property specialized to enforce floating point max/min.
void reset() override
Called to tell the display to clear its state.
Property specialized to provide max/min enforcement for integers.
void disconnectFailure(const message_filters::Connection &c)
uint64_t failed_transform_count_
boost::signals2::signal< void(const MConstPtr &, FilterFailureReason)> FailureSignal
boost::shared_ptr< urdf::Model > robot_model_
void connectInput(F &f)
Connect this filter's input to another filter'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
ros::Timer max_rate_timer_
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_
uint64_t successful_transform_count_
ros::Duration time_tolerance_
std::string target_frames_string_
virtual void unsubscribe()
ros::Time last_out_the_back_stamp_
#define ROS_STATIC_ASSERT(cond)
rviz::FloatProperty * width_property_
std::string getTargetFramesString()
Get the target frames as a string for debugging.
~MessageFilterJointState() override
Destructor.
void updateTopic() override
MessageFilterJointStateDisplay MFDClass
Convenience typedef so subclasses don'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_
uint64_t transform_message_count_
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)
uint64_t incoming_message_count_
bool warned_about_unresolved_name_
#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.
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_
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.
ros::Time next_failure_warning_
boost::mutex messages_mutex_
The mutex used for locking message list operations.
volatile bool new_transforms_
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)
std::string last_out_the_back_frame_
void maxRateTimerCallback(const ros::TimerEvent &)
L_Event messages_
The message list.
Helper superclass for MessageFilterDisplay, needed because Qt's moc and c++ templates don't work nice...