interactive_marker_display.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008, 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 <tf/transform_listener.h>
31 
32 #include "rviz/frame_manager.h"
36 #include "rviz/validate_floats.h"
38 #include "rviz/display_context.h"
39 
41 
42 
43 namespace rviz
44 {
46 bool validateFloats(const visualization_msgs::InteractiveMarker& msg)
47 {
48  bool valid = true;
49  valid = valid && validateFloats(msg.pose);
50  valid = valid && validateFloats(msg.scale);
51  for (unsigned c = 0; c < msg.controls.size(); c++)
52  {
53  valid = valid && validateFloats(msg.controls[c].orientation);
54  for (unsigned m = 0; m < msg.controls[c].markers.size(); m++)
55  {
56  valid = valid && validateFloats(msg.controls[c].markers[m].pose);
57  valid = valid && validateFloats(msg.controls[c].markers[m].scale);
58  valid = valid && validateFloats(msg.controls[c].markers[m].color);
59  valid = valid && validateFloats(msg.controls[c].markers[m].points);
60  }
61  }
62  return valid;
63 }
64 
65 bool validateQuaternions(const visualization_msgs::InteractiveMarker& marker)
66 {
67  if (!validateQuaternions(marker.pose.orientation))
68  return false;
69  for (size_t c = 0; c < marker.controls.size(); ++c)
70  {
71  if (!validateQuaternions(marker.controls[c].orientation))
72  return false;
73  for (size_t m = 0; m < marker.controls[c].markers.size(); ++m)
74  {
75  if (!validateQuaternions(marker.controls[c].markers[m].pose.orientation))
76  return false;
77  }
78  }
79  return true;
80 }
82 
83 
85 {
87  "Update Topic", "", ros::message_traits::datatype<visualization_msgs::InteractiveMarkerUpdate>(),
88  "visualization_msgs::InteractiveMarkerUpdate topic to subscribe to.", this, SLOT(updateTopic()));
89 
91  new BoolProperty("Show Descriptions", true,
92  "Whether or not to show the descriptions of each Interactive Marker.", this,
93  SLOT(updateShowDescriptions()));
94 
96  new BoolProperty("Show Axes", false, "Whether or not to show the axes of each Interactive Marker.",
97  this, SLOT(updateShowAxes()));
98 
100  "Show Visual Aids", false,
101  "Whether or not to show visual helpers while moving/rotating Interactive Markers.", this,
102  SLOT(updateShowVisualAids()));
104  "Enable Transparency", true,
105  "Whether or not to allow transparency for auto-completed markers (e.g. rings and arrows).", this,
106  SLOT(updateEnableTransparency()));
107 }
108 
110 {
111 // TODO(wjwwood): remove this and use tf2 interface instead
112 #ifndef _WIN32
113 #pragma GCC diagnostic push
114 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
115 #endif
116 
118 
119 #ifndef _WIN32
120 #pragma GCC diagnostic pop
121 #endif
123 
124  im_client_->setInitCb(boost::bind(&InteractiveMarkerDisplay::initCb, this, _1));
125  im_client_->setUpdateCb(boost::bind(&InteractiveMarkerDisplay::updateCb, this, _1));
126  im_client_->setResetCb(boost::bind(&InteractiveMarkerDisplay::resetCb, this, _1));
127  im_client_->setStatusCb(boost::bind(&InteractiveMarkerDisplay::statusCb, this, _1, _2, _3));
128 
130 
131  onEnable();
132 }
133 
134 void InteractiveMarkerDisplay::setTopic(const QString& topic, const QString& /*datatype*/)
135 {
137 }
138 
140 {
141  subscribe();
142 }
143 
145 {
146  unsubscribe();
147 }
148 
150 {
151  unsubscribe();
152 
153  std::string update_topic = marker_update_topic_property_->getTopicStd();
154 
155  size_t idx = update_topic.find("/update");
156  if (idx != std::string::npos)
157  {
158  topic_ns_ = update_topic.substr(0, idx);
159  subscribe();
160  }
161  else
162  {
163  setStatusStd(StatusProperty::Error, "Topic", "Invalid topic name: " + update_topic);
164  }
165 }
166 
168 {
169  if (isEnabled())
170  {
171  im_client_->subscribe(topic_ns_);
172 
173  std::string feedback_topic = topic_ns_ + "/feedback";
174  feedback_pub_ =
175  update_nh_.advertise<visualization_msgs::InteractiveMarkerFeedback>(feedback_topic, 100, false);
176  }
177 }
178 
179 void InteractiveMarkerDisplay::publishFeedback(visualization_msgs::InteractiveMarkerFeedback& feedback)
180 {
181  feedback.client_id = client_id_;
182  feedback_pub_.publish(feedback);
183 }
184 
186  const std::string& name,
187  const std::string& text)
188 {
189  setStatusStd(level, name, text);
190 }
191 
193 {
194  if (im_client_)
195  {
196  im_client_->shutdown();
197  }
199  Display::reset();
200 }
201 
202 void InteractiveMarkerDisplay::update(float wall_dt, float /*ros_dt*/)
203 {
204  im_client_->update();
205 
206  M_StringToStringToIMPtr::iterator server_it;
207  for (server_it = interactive_markers_.begin(); server_it != interactive_markers_.end(); server_it++)
208  {
209  M_StringToIMPtr::iterator im_it;
210  for (im_it = server_it->second.begin(); im_it != server_it->second.end(); im_it++)
211  {
212  im_it->second->update(wall_dt);
213  }
214  }
215 }
216 
218 {
219  M_StringToStringToIMPtr::iterator im_map_it = interactive_markers_.find(server_id);
220 
221  if (im_map_it == interactive_markers_.end())
222  {
223  im_map_it = interactive_markers_.insert(std::make_pair(server_id, M_StringToIMPtr())).first;
224  }
225 
226  return im_map_it->second;
227 }
228 
230  const std::string& server_id,
231  const std::vector<visualization_msgs::InteractiveMarker>& markers)
232 {
233  M_StringToIMPtr& im_map = getImMap(server_id);
234 
235  for (size_t i = 0; i < markers.size(); i++)
236  {
237  const visualization_msgs::InteractiveMarker& marker = markers[i];
238 
239  if (!validateFloats(marker))
240  {
241  setStatusStd(StatusProperty::Error, marker.name, "Marker contains invalid floats!");
242  // setStatusStd( StatusProperty::Error, "General", "Marker " + marker.name + " contains invalid
243  // floats!" );
244  continue;
245  }
246 
247  if (!validateQuaternions(marker))
248  {
249  ROS_WARN_ONCE_NAMED("quaternions",
250  "Interactive marker '%s' contains unnormalized quaternions. "
251  "This warning will only be output once but may be true for others; "
252  "enable DEBUG messages for ros.rviz.quaternions to see more details.",
253  marker.name.c_str());
254  ROS_DEBUG_NAMED("quaternions", "Interactive marker '%s' contains unnormalized quaternions.",
255  marker.name.c_str());
256  }
257  ROS_DEBUG("Processing interactive marker '%s'. %d", marker.name.c_str(), (int)marker.controls.size());
258 
259  std::map<std::string, IMPtr>::iterator int_marker_entry = im_map.find(marker.name);
260 
261  if (int_marker_entry == im_map.end())
262  {
263  int_marker_entry =
264  im_map
265  .insert(std::make_pair(marker.name, IMPtr(new InteractiveMarker(getSceneNode(), context_))))
266  .first;
267  connect(int_marker_entry->second.get(),
268  SIGNAL(userFeedback(visualization_msgs::InteractiveMarkerFeedback&)), this,
269  SLOT(publishFeedback(visualization_msgs::InteractiveMarkerFeedback&)));
270  connect(int_marker_entry->second.get(),
271  SIGNAL(statusUpdate(StatusProperty::Level, const std::string&, const std::string&)), this,
272  SLOT(onStatusUpdate(StatusProperty::Level, const std::string&, const std::string&)));
273  }
274 
275  if (int_marker_entry->second->processMessage(marker))
276  {
277  int_marker_entry->second->setShowAxes(show_axes_property_->getBool());
278  int_marker_entry->second->setShowVisualAids(show_visual_aids_property_->getBool());
279  int_marker_entry->second->setShowDescription(show_descriptions_property_->getBool());
280  }
281  else
282  {
283  unsubscribe();
284  return;
285  }
286  }
287 }
288 
289 void InteractiveMarkerDisplay::eraseMarkers(const std::string& server_id,
290  const std::vector<std::string>& erases)
291 {
292  M_StringToIMPtr& im_map = getImMap(server_id);
293 
294  for (size_t i = 0; i < erases.size(); i++)
295  {
296  im_map.erase(erases[i]);
297  deleteStatusStd(erases[i]);
298  }
299 }
300 
302  const std::string& server_id,
303  const std::vector<visualization_msgs::InteractiveMarkerPose>& marker_poses)
304 {
305  M_StringToIMPtr& im_map = getImMap(server_id);
306 
307  for (size_t i = 0; i < marker_poses.size(); i++)
308  {
309  const visualization_msgs::InteractiveMarkerPose& marker_pose = marker_poses[i];
310 
311  if (!validateFloats(marker_pose.pose))
312  {
313  setStatusStd(StatusProperty::Error, marker_pose.name, "Pose message contains invalid floats!");
314  return;
315  }
316 
317  if (!validateQuaternions(marker_pose.pose))
318  {
319  setStatusStd(StatusProperty::Error, marker_pose.name,
320  "Pose message contains invalid quaternions (length not equal to 1)!");
321  return;
322  }
323 
324  std::map<std::string, IMPtr>::iterator int_marker_entry = im_map.find(marker_pose.name);
325 
326  if (int_marker_entry != im_map.end())
327  {
328  int_marker_entry->second->processMessage(marker_pose);
329  }
330  else
331  {
332  setStatusStd(StatusProperty::Error, marker_pose.name,
333  "Pose received for non-existing marker '" + marker_pose.name);
334  unsubscribe();
335  return;
336  }
337  }
338 }
339 
340 void InteractiveMarkerDisplay::initCb(visualization_msgs::InteractiveMarkerInitConstPtr msg)
341 {
342  resetCb(msg->server_id);
343  updateMarkers(msg->server_id, msg->markers);
344 }
345 
346 void InteractiveMarkerDisplay::updateCb(visualization_msgs::InteractiveMarkerUpdateConstPtr msg)
347 {
348  updateMarkers(msg->server_id, msg->markers);
349  updatePoses(msg->server_id, msg->poses);
350  eraseMarkers(msg->server_id, msg->erases);
351 }
352 
353 void InteractiveMarkerDisplay::resetCb(std::string server_id)
354 {
355  interactive_markers_.erase(server_id);
356  deleteStatusStd(server_id);
357 }
358 
360  const std::string& server_id,
361  const std::string& msg)
362 {
363  setStatusStd(static_cast<StatusProperty::Level>(status), server_id, msg);
364 }
365 
367 {
368  if (im_client_)
369  im_client_->setTargetFrame(fixed_frame_.toStdString());
370  reset();
371 }
372 
374 {
375  Display::reset();
376  unsubscribe();
377  subscribe();
378 }
379 
381 {
383 
384  M_StringToStringToIMPtr::iterator server_it;
385  for (server_it = interactive_markers_.begin(); server_it != interactive_markers_.end(); server_it++)
386  {
387  M_StringToIMPtr::iterator im_it;
388  for (im_it = server_it->second.begin(); im_it != server_it->second.end(); im_it++)
389  {
390  im_it->second->setShowDescription(show);
391  }
392  }
393 }
394 
396 {
397  bool show = show_axes_property_->getBool();
398 
399  M_StringToStringToIMPtr::iterator server_it;
400  for (server_it = interactive_markers_.begin(); server_it != interactive_markers_.end(); server_it++)
401  {
402  M_StringToIMPtr::iterator im_it;
403  for (im_it = server_it->second.begin(); im_it != server_it->second.end(); im_it++)
404  {
405  im_it->second->setShowAxes(show);
406  }
407  }
408 }
409 
411 {
413 
414  M_StringToStringToIMPtr::iterator server_it;
415  for (server_it = interactive_markers_.begin(); server_it != interactive_markers_.end(); server_it++)
416  {
417  M_StringToIMPtr::iterator im_it;
418  for (im_it = server_it->second.begin(); im_it != server_it->second.end(); im_it++)
419  {
420  im_it->second->setShowVisualAids(show);
421  }
422  }
423 }
424 
426 {
427  // This is not very efficient... but it should do the trick.
428  unsubscribe();
429  im_client_->setEnableAutocompleteTransparency(enable_transparency_property_->getBool());
430  subscribe();
431 }
432 
433 } // namespace rviz
434 
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:163
void deleteStatusStd(const std::string &name)
Delete the status entry with the given std::string name. This is thread-safe.
Definition: display.h:172
virtual void setString(const QString &str)
void updateMarkers(const std::string &server_id, const std::vector< visualization_msgs::InteractiveMarker > &markers)
void setTopic(const QString &topic, const QString &datatype) override
Set the ROS topic to listen to for this display.
void initCb(visualization_msgs::InteractiveMarkerInitConstPtr msg)
M_StringToIMPtr & getImMap(std::string server_id)
DisplayContext * context_
This DisplayContext pointer is the main connection a Display has into the rest of rviz...
Definition: display.h:287
void fixedFrameChanged() override
Called by setFixedFrame(). Override to respond to changes to fixed_frame_.
void eraseMarkers(const std::string &server_id, const std::vector< std::string > &names)
void updateCb(visualization_msgs::InteractiveMarkerUpdateConstPtr msg)
ros::NodeHandle update_nh_
A NodeHandle whose CallbackQueue is run from the main GUI thread (the "update" thread).
Definition: display.h:300
void onEnable() override
Derived classes override this to do the actual work of enabling themselves.
ROSCPP_DECL const std::string & getName()
void onDisable() override
Derived classes override this to do the actual work of disabling themselves.
boost::shared_ptr< interactive_markers::InteractiveMarkerClient > im_client_
std::string getTopicStd() const
void statusCb(interactive_markers::InteractiveMarkerClient::StatusT status, const std::string &server_id, const std::string &msg)
void updatePoses(const std::string &server_id, const std::vector< visualization_msgs::InteractiveMarkerPose > &marker_poses)
QString fixed_frame_
A convenience variable equal to context_->getFixedFrame().
Definition: display.h:312
#define ROS_DEBUG_NAMED(name,...)
void publish(const boost::shared_ptr< M > &message) const
std::map< std::string, IMPtr > M_StringToIMPtr
void publishFeedback(visualization_msgs::InteractiveMarkerFeedback &feedback)
bool validateFloats(const sensor_msgs::CameraInfo &msg)
Ogre::SceneNode * getSceneNode() const
Return the Ogre::SceneNode holding all 3D scene elements shown by this Display.
Definition: display.h:186
virtual void reset()
Called to tell the display to clear its state.
Definition: display.cpp:287
void show()
Show this Property in any PropertyTreeWidgets.
Definition: property.h:410
virtual FrameManager * getFrameManager() const =0
Return the FrameManager instance.
tf::TransformListener * getTFClient()
Return the tf::TransformListener used to receive transform data.
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
#define ROS_WARN_ONCE_NAMED(name,...)
std::string getNameStd() const
Return the name of this Property as a std::string.
Definition: property.h:180
BoolProperty(const QString &name=QString(), bool default_value=false, const QString &description=QString(), Property *parent=nullptr, const char *changed_slot=nullptr, QObject *receiver=nullptr)
Displays Interactive Markers.
bool isEnabled() const
Return true if this Display is enabled, false if not.
Definition: display.cpp:268
void reset() override
Called to tell the display to clear its state.
bool validateQuaternions(const visualization_msgs::InteractiveMarker &marker)
M_StringToStringToIMPtr interactive_markers_
void update(float wall_dt, float ros_dt) override
Called periodically by the visualization manager.
void onStatusUpdate(StatusProperty::Level level, const std::string &name, const std::string &text)
virtual bool getBool() const
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
void onInitialize() override
Override this function to do subclass-specific initialization.
#define ROS_DEBUG(...)


rviz
Author(s): Dave Hershberger, David Gossow, Josh Faust
autogenerated on Sat May 27 2023 02:06:24