marker_display.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Willow Garage, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <sstream>
31 
32 #include <tf/transform_listener.h>
33 
36 #include "rviz/display_context.h"
37 #include "rviz/frame_manager.h"
45 #include "rviz/validate_floats.h"
47 
49 
50 namespace rviz
51 {
52 
54 
56  : Display()
57 {
58  marker_topic_property_ = new RosTopicProperty( "Marker Topic", "visualization_marker",
59  QString::fromStdString( ros::message_traits::datatype<visualization_msgs::Marker>() ),
60  "visualization_msgs::Marker topic to subscribe to. <topic>_array will also"
61  " automatically be subscribed with type visualization_msgs::MarkerArray.",
62  this, SLOT( updateTopic() ));
63 
64  queue_size_property_ = new IntProperty( "Queue Size", 100,
65  "Advanced: set the size of the incoming Marker message queue. Increasing this is"
66  " useful if your incoming TF data is delayed significantly from your Marker data, "
67  "but it can greatly increase memory usage if the messages are big.",
68  this, SLOT( updateQueueSize() ));
70 
71  namespaces_category_ = new Property( "Namespaces", QVariant(), "", this );
72 }
73 
75 {
77  fixed_frame_.toStdString(),
79  update_nh_ );
80 
84 
86 }
87 
89 {
90  if ( initialized() )
91  {
92  unsubscribe();
93 
94  clearMarkers();
95 
96  delete tf_filter_;
97  }
98 }
99 
100 void MarkerDisplay::load(const Config& config)
101 {
102  Display::load(config);
103 
104  Config c = config.mapGetChild("Namespaces");
105  for( Config::MapIterator iter = c.mapIterator(); iter.isValid(); iter.advance() )
106  {
107  QString key = iter.currentKey();
108  const Config& child = iter.currentChild();
109  namespace_config_enabled_state_[key] = child.getValue().toBool();
110  }
111 }
112 
114 {
115  markers_.clear();
116  markers_with_expiration_.clear();
117  frame_locked_markers_.clear();
118  tf_filter_->clear();
120  namespaces_.clear();
121 }
122 
124 {
125  subscribe();
126 }
127 
129 {
130  unsubscribe();
131  tf_filter_->clear();
132 
133  clearMarkers();
134 }
135 
137 {
139 }
140 
142 {
143  unsubscribe();
144  subscribe();
145 }
146 
148 {
149  if( !isEnabled() )
150  {
151  return;
152  }
153 
154  std::string marker_topic = marker_topic_property_->getTopicStd();
155  if( !marker_topic.empty() )
156  {
158  sub_.unsubscribe();
159 
160  try
161  {
162  sub_.subscribe( update_nh_, marker_topic, queue_size_property_->getInt() );
164  setStatus( StatusProperty::Ok, "Topic", "OK" );
165  }
166  catch( ros::Exception& e )
167  {
168  setStatus( StatusProperty::Error, "Topic", QString("Error subscribing: ") + e.what() );
169  }
170  }
171 }
172 
174 {
175  sub_.unsubscribe();
177 }
178 
180 {
181  deleteMarkerStatus( id );
182 
183  M_IDToMarker::iterator it = markers_.find( id );
184  if( it != markers_.end() )
185  {
186  markers_with_expiration_.erase(it->second);
187  frame_locked_markers_.erase(it->second);
188  markers_.erase(it);
189  }
190 }
191 
192 void MarkerDisplay::deleteMarkersInNamespace( const std::string& ns )
193 {
194  std::vector<MarkerID> to_delete;
195 
196  // TODO: this is inefficient, should store every in-use id per namespace and lookup by that
197  M_IDToMarker::iterator marker_it = markers_.begin();
198  M_IDToMarker::iterator marker_end = markers_.end();
199  for (; marker_it != marker_end; ++marker_it)
200  {
201  if (marker_it->first.first == ns)
202  {
203  to_delete.push_back(marker_it->first);
204  }
205  }
206 
207  {
208  std::vector<MarkerID>::iterator it = to_delete.begin();
209  std::vector<MarkerID>::iterator end = to_delete.end();
210  for (; it != end; ++it)
211  {
212  deleteMarker(*it);
213  }
214  }
215 }
216 
218 {
219  std::vector<MarkerID> to_delete;
220  M_IDToMarker::iterator marker_it = markers_.begin();
221  for (; marker_it != markers_.end(); ++marker_it)
222  {
223  to_delete.push_back(marker_it->first);
224  }
225 
226  for (std::vector<MarkerID>::iterator it = to_delete.begin(); it != to_delete.end(); ++it)
227  {
228  deleteMarker( *it );
229  }
230 }
231 
232 void MarkerDisplay::setMarkerStatus(MarkerID id, StatusLevel level, const std::string& text)
233 {
234  std::stringstream ss;
235  ss << id.first << "/" << id.second;
236  std::string marker_name = ss.str();
237  setStatusStd(level, marker_name, text);
238 }
239 
241 {
242  std::stringstream ss;
243  ss << id.first << "/" << id.second;
244  std::string marker_name = ss.str();
245  deleteStatusStd(marker_name);
246 }
247 
248 void MarkerDisplay::incomingMarkerArray(const visualization_msgs::MarkerArray::ConstPtr& array)
249 {
250  std::vector<visualization_msgs::Marker>::const_iterator it = array->markers.begin();
251  std::vector<visualization_msgs::Marker>::const_iterator end = array->markers.end();
252  for (; it != end; ++it)
253  {
254  const visualization_msgs::Marker& marker = *it;
255  tf_filter_->add(visualization_msgs::Marker::Ptr(new visualization_msgs::Marker(marker)));
256  }
257 }
258 
259 void MarkerDisplay::incomingMarker( const visualization_msgs::Marker::ConstPtr& marker )
260 {
261  boost::mutex::scoped_lock lock(queue_mutex_);
262 
263  message_queue_.push_back(marker);
264 }
265 
267 {
268  visualization_msgs::Marker::ConstPtr marker = marker_evt.getConstMessage();
269  if (marker->action == visualization_msgs::Marker::DELETE ||
270  marker->action == 3) // TODO: visualization_msgs::Marker::DELETEALL when message changes in a future version of ROS
271  {
272  return this->processMessage(marker);
273  }
274  std::string authority = marker_evt.getPublisherName();
275  std::string error = context_->getFrameManager()->discoverFailureReason(marker->header.frame_id, marker->header.stamp, authority, reason);
276  setMarkerStatus(MarkerID(marker->ns, marker->id), StatusProperty::Error, error);
277 }
278 
279 bool validateFloats(const visualization_msgs::Marker& msg)
280 {
281  bool valid = true;
282  valid = valid && validateFloats(msg.pose);
283  valid = valid && validateFloats(msg.scale);
284  valid = valid && validateFloats(msg.color);
285  valid = valid && validateFloats(msg.points);
286  return valid;
287 }
288 
289 void MarkerDisplay::processMessage( const visualization_msgs::Marker::ConstPtr& message )
290 {
291  if ( !validateFloats( *message ))
292  {
293  setMarkerStatus( MarkerID( message->ns, message->id ), StatusProperty::Error,
294  "Contains invalid floating point values (nans or infs)" );
295  return;
296  }
297 
298  if( !validateQuaternions( message->pose ))
299  {
300  ROS_WARN_ONCE_NAMED( "quaternions", "Marker '%s/%d' contains unnormalized quaternions. "
301  "This warning will only be output once but may be true for others; "
302  "enable DEBUG messages for ros.rviz.quaternions to see more details.",
303  message->ns.c_str(), message->id );
304  ROS_DEBUG_NAMED( "quaternions", "Marker '%s/%d' contains unnormalized quaternions.",
305  message->ns.c_str(), message->id );
306  }
307 
308  switch ( message->action )
309  {
310  case visualization_msgs::Marker::ADD:
311  processAdd( message );
312  break;
313 
314  case visualization_msgs::Marker::DELETE:
315  processDelete( message );
316  break;
317 
318  case 3: // TODO: visualization_msgs::Marker::DELETEALL when message changes in a future version of ROS
320  break;
321 
322  default:
323  ROS_ERROR( "Unknown marker action: %d\n", message->action );
324  }
325 }
326 
327 void MarkerDisplay::processAdd( const visualization_msgs::Marker::ConstPtr& message )
328 {
329  QString namespace_name = QString::fromStdString( message->ns );
330  M_Namespace::iterator ns_it = namespaces_.find( namespace_name );
331  if( ns_it == namespaces_.end() )
332  {
333  ns_it = namespaces_.insert( namespace_name, new MarkerNamespace( namespace_name, namespaces_category_, this ));
334 
335  // Adding a new namespace, determine if it's configured to be disabled
336  if( namespace_config_enabled_state_.count(namespace_name) > 0 &&
337  !namespace_config_enabled_state_[namespace_name] )
338  {
339  ns_it.value()->setValue(false); // Disable the namespace
340  }
341  }
342 
343  if( !ns_it.value()->isEnabled() )
344  {
345  return;
346  }
347 
348  deleteMarkerStatus( MarkerID( message->ns, message->id ));
349 
350  bool create = true;
351  MarkerBasePtr marker;
352 
353  M_IDToMarker::iterator it = markers_.find( MarkerID(message->ns, message->id) );
354  if ( it != markers_.end() )
355  {
356  marker = it->second;
357  markers_with_expiration_.erase(marker);
358  if ( message->type == marker->getMessage()->type )
359  {
360  create = false;
361  }
362  else
363  {
364  markers_.erase( it );
365  }
366  }
367 
368  if ( create )
369  {
370  marker.reset(createMarker(message->type, this, context_, scene_node_));
371  if (!marker) {
372  ROS_ERROR( "Unknown marker type: %d", message->type );
373  }
374  markers_.insert(std::make_pair(MarkerID(message->ns, message->id), marker));
375  }
376 
377  if (marker)
378  {
379  marker->setMessage(message);
380 
381  if (message->lifetime.toSec() > 0.0001f)
382  {
383  markers_with_expiration_.insert(marker);
384  }
385 
386  if (message->frame_locked)
387  {
388  frame_locked_markers_.insert(marker);
389  }
390 
392  }
393 }
394 
395 void MarkerDisplay::processDelete( const visualization_msgs::Marker::ConstPtr& message )
396 {
397  deleteMarker(MarkerID(message->ns, message->id));
398 
400 }
401 
402 void MarkerDisplay::update(float wall_dt, float ros_dt)
403 {
404  V_MarkerMessage local_queue;
405 
406  {
407  boost::mutex::scoped_lock lock(queue_mutex_);
408 
409  local_queue.swap( message_queue_ );
410  }
411 
412  if ( !local_queue.empty() )
413  {
414  V_MarkerMessage::iterator message_it = local_queue.begin();
415  V_MarkerMessage::iterator message_end = local_queue.end();
416  for ( ; message_it != message_end; ++message_it )
417  {
418  visualization_msgs::Marker::ConstPtr& marker = *message_it;
419 
420  processMessage( marker );
421  }
422  }
423 
424  {
425  S_MarkerBase::iterator it = markers_with_expiration_.begin();
426  S_MarkerBase::iterator end = markers_with_expiration_.end();
427  for (; it != end;)
428  {
429  MarkerBasePtr marker = *it;
430  if (marker->expired())
431  {
432  ++it;
433  deleteMarker(marker->getID());
434  }
435  else
436  {
437  ++it;
438  }
439  }
440  }
441 
442  {
443  S_MarkerBase::iterator it = frame_locked_markers_.begin();
444  S_MarkerBase::iterator end = frame_locked_markers_.end();
445  for (; it != end; ++it)
446  {
447  MarkerBasePtr marker = *it;
448  marker->updateFrameLocked();
449  }
450  }
451 }
452 
454 {
455  tf_filter_->setTargetFrame( fixed_frame_.toStdString() );
456 
457  clearMarkers();
458 }
459 
461 {
462  Display::reset();
463  clearMarkers();
464 }
465 
466 void MarkerDisplay::setTopic( const QString &topic, const QString &datatype )
467 {
469 }
470 
472 // MarkerNamespace
473 
474 MarkerNamespace::MarkerNamespace( const QString& name, Property* parent_property, MarkerDisplay* owner )
475  : BoolProperty( name, true,
476  "Enable/disable all markers in this namespace.",
477  parent_property )
478  , owner_( owner )
479 {
480  // Can't do this connect in chained constructor above because at
481  // that point it doesn't really know that "this" is a
482  // MarkerNamespace*, so the signal doesn't get connected.
483  connect( this, SIGNAL( changed() ), this, SLOT( onEnableChanged() ));
484 }
485 
487 {
488  if( !isEnabled() )
489  {
490  owner_->deleteMarkersInNamespace( getName().toStdString() );
491  }
492 
493  // Update the configuration that stores the enabled state of all markers
495 }
496 
497 } // namespace rviz
498 
void setStatusStd(StatusProperty::Level level, const std::string &name, const std::string &text)
Show status level and text, using a std::string. Convenience function which converts std::string to Q...
Definition: display.h:157
void processMessage(const visualization_msgs::Marker::ConstPtr &message)
Processes a marker message.
void deleteStatusStd(const std::string &name)
Delete the status entry with the given std::string name. This is thread-safe.
Definition: display.h:166
virtual void update(float wall_dt, float ros_dt)
Called periodically by the visualization manager.
virtual void setString(const QString &str)
void processAdd(const visualization_msgs::Marker::ConstPtr &message)
Processes an "Add" marker message.
void connectInput(F &f)
std::string discoverFailureReason(const std::string &frame_id, const ros::Time &stamp, const std::string &caller_id, tf::FilterFailureReason reason)
Create a description of a transform problem.
void processDelete(const visualization_msgs::Marker::ConstPtr &message)
Processes a "Delete" marker message.
S_MarkerBase frame_locked_markers_
void setMarkerStatus(MarkerID id, StatusLevel level, const std::string &text)
RosTopicProperty * marker_topic_property_
virtual tf::TransformListener * getTFClient() const =0
Convenience function: returns getFrameManager()->getTFClient().
MarkerNamespace(const QString &name, Property *parent_property, MarkerDisplay *owner)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
DisplayContext * context_
This DisplayContext pointer is the main connection a Display has into the rest of rviz...
Definition: display.h:256
void changed()
Emitted by setValue() just after the value has changed.
void add(const MEvent &evt)
std::vector< visualization_msgs::Marker::ConstPtr > V_MarkerMessage
M_Namespace namespaces_
virtual int getInt() const
Return the internal property value as an integer.
Definition: int_property.h:73
MarkerDisplay * owner_
ros::NodeHandle update_nh_
A NodeHandle whose CallbackQueue is run from the main GUI thread (the "update" thread).
Definition: display.h:269
A single element of a property tree, with a name, value, description, and possibly children...
Definition: property.h:100
IntProperty * queue_size_property_
boost::mutex queue_mutex_
virtual void reset()
Called to tell the display to clear its state.
void incomingMarker(const visualization_msgs::Marker::ConstPtr &marker)
ROS callback notifying us of a new marker.
void setMin(int min)
bool isValid()
Return true if the iterator currently points to a valid entry, false if not.
Definition: config.cpp:385
virtual void unsubscribe()
Unsubscribes from the "visualization_marker" "visualization_marker_array" topics. ...
Property specialized to provide max/min enforcement for integers.
Definition: int_property.h:38
Ogre::SceneNode * scene_node_
The Ogre::SceneNode to hold all 3D scene elements shown by this Display.
Definition: display.h:264
M_EnabledState namespace_config_enabled_state_
void deleteMarker(MarkerID id)
bool isEnabled() const
Return true if this Display is enabled, false if not.
Definition: display.cpp:281
Configuration data storage class.
Definition: config.h:125
Property * namespaces_category_
void incomingMarkerArray(const visualization_msgs::MarkerArray::ConstPtr &array)
Process a MarkerArray message.
QString fixed_frame_
A convenience variable equal to context_->getFixedFrame().
Definition: display.h:281
virtual void setQueueSize(uint32_t new_queue_size)
const std::string & getPublisherName() const
MarkerBase * createMarker(int marker_type, MarkerDisplay *owner, DisplayContext *context, Ogre::SceneNode *parent_node)
void deleteMarkersInNamespace(const std::string &ns)
Delete all the markers within the given namespace.
std::pair< std::string, int32_t > MarkerID
#define ROS_DEBUG_NAMED(name,...)
const boost::shared_ptr< ConstMessage > & getConstMessage() const
M_IDToMarker markers_
Map of marker id to the marker info structure.
virtual void removeChildren(int start_index=0, int count=-1)
Remove and delete some or all child Properties. Does not change the value of this Property...
Definition: property.cpp:100
bool isEnabled() const
bool validateFloats(const sensor_msgs::CameraInfo &msg)
virtual void reset()
Called to tell the display to clear its state.
Definition: display.cpp:300
V_MarkerMessage message_queue_
virtual void load(const Config &config)
Load the settings for this display from the given Config node, which must be a map.
virtual void onDisable()
Derived classes override this to do the actual work of disabling themselves.
QVariant getValue() const
If this config object is valid and is a Value type, this returns its value. Otherwise it returns an i...
Definition: config.cpp:312
void deleteMarkerStatus(MarkerID id)
virtual void fixedFrameChanged()
Called by setFixedFrame(). Override to respond to changes to fixed_frame_.
Iterator class for looping over all entries in a Map type Config Node.
Definition: config.h:282
message_filters::Connection registerFailureCallback(const FailureCallback &callback)
virtual FrameManager * getFrameManager() const =0
Return the FrameManager instance.
ros::Subscriber array_sub_
message_filters::Subscriber< visualization_msgs::Marker > sub_
#define ROS_WARN_ONCE_NAMED(name,...)
friend class MarkerNamespace
tf::MessageFilter< visualization_msgs::Marker > * tf_filter_
void failedMarker(const ros::MessageEvent< visualization_msgs::Marker > &marker_evt, tf::FilterFailureReason reason)
S_MarkerBase markers_with_expiration_
virtual void subscribe()
Subscribes to the "visualization_marker" and "visualization_marker_array" topics. ...
virtual void queueRender()=0
Queues a render. Multiple calls before a render happens will only cause a single render.
virtual void load(const Config &config)
Load the settings for this display from the given Config node, which must be a map.
Definition: display.cpp:242
virtual void onEnable()
Derived classes override this to do the actual work of enabling themselves.
MapIterator mapIterator() const
Return a new iterator for looping over key/value pairs.
Definition: config.cpp:344
virtual void setTopic(const QString &topic, const QString &datatype)
Set the ROS topic to listen to for this display.
void deleteAllMarkers()
Delete all known markers to this plugin, regardless of id or namespace.
void subscribe(ros::NodeHandle &nh, const std::string &topic, uint32_t queue_size, const ros::TransportHints &transport_hints=ros::TransportHints(), ros::CallbackQueueInterface *callback_queue=0)
Property(const QString &name=QString(), const QVariant default_value=QVariant(), const QString &description=QString(), Property *parent=0, const char *changed_slot=0, QObject *receiver=0)
Constructor.
Definition: property.cpp:54
bool validateQuaternions(const visualization_msgs::InteractiveMarker &marker)
Property specialized to provide getter for booleans.
Definition: bool_property.h:38
void setTargetFrame(const std::string &target_frame)
Config mapGetChild(const QString &key) const
If the referenced Node is a Map and it has a child with the given key, return a reference to the chil...
Definition: config.cpp:201
bool initialized() const
Returns true if the display has been initialized.
Definition: display.h:247
std::string getTopicStd() const
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
Displays "markers" sent in by other ROS nodes on the "visualization_marker" topic.
#define ROS_ERROR(...)
void clearMarkers()
Removes all the markers.
virtual void setStatus(StatusProperty::Level level, const QString &name, const QString &text)
Show status level and text. This is thread-safe.
Definition: display.cpp:186
virtual QString getName() const
Return the name of this Property as a QString.
Definition: property.cpp:159
Connection registerCallback(const C &callback)
virtual void onInitialize()
Override this function to do subclass-specific initialization.


rviz
Author(s): Dave Hershberger, David Gossow, Josh Faust
autogenerated on Sat Apr 27 2019 02:33:41