interactive_marker.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, 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 <boost/make_shared.hpp>
31 
32 #include <QMenu>
33 
34 #include <OgreSceneNode.h>
35 #include <OgreSceneManager.h>
36 #include <OgreMaterialManager.h>
37 #include <OgreResourceGroupManager.h>
38 #include <OgreSubEntity.h>
39 #include <OgreMath.h>
40 #include <OgreRenderWindow.h>
41 
42 #include <ros/ros.h>
44 
45 #include "rviz/frame_manager.h"
46 #include "rviz/display_context.h"
48 #include "rviz/frame_manager.h"
49 #include "rviz/render_panel.h"
50 #include "rviz/geometry.h"
52 
55 
56 namespace rviz
57 {
58 InteractiveMarker::InteractiveMarker(Ogre::SceneNode* scene_node, DisplayContext* context)
59  : context_(context)
60  , pose_changed_(false)
61  , time_since_last_feedback_(0)
62  , dragging_(false)
63  , pose_update_requested_(false)
64  , heart_beat_t_(0)
65  , show_visual_aids_(false)
66 {
67  reference_node_ = scene_node->createChildSceneNode();
68  axes_ = new Axes(context->getSceneManager(), reference_node_, 1, 0.05);
69 }
70 
72 {
73  delete axes_;
74  context_->getSceneManager()->destroySceneNode(reference_node_);
75 }
76 
77 void InteractiveMarker::processMessage(const visualization_msgs::InteractiveMarkerPose& message)
78 {
79  boost::recursive_mutex::scoped_lock lock(mutex_);
80  Ogre::Vector3 position(message.pose.position.x, message.pose.position.y, message.pose.position.z);
81  Ogre::Quaternion orientation(message.pose.orientation.w, message.pose.orientation.x,
82  message.pose.orientation.y, message.pose.orientation.z);
83 
84  if (orientation.w == 0 && orientation.x == 0 && orientation.y == 0 && orientation.z == 0)
85  {
86  orientation.w = 1;
87  }
88 
89  reference_time_ = message.header.stamp;
90  reference_frame_ = message.header.frame_id;
91  frame_locked_ = (message.header.stamp == ros::Time(0));
92 
93  requestPoseUpdate(position, orientation);
95 }
96 
97 bool InteractiveMarker::processMessage(const visualization_msgs::InteractiveMarker& message)
98 {
99  boost::recursive_mutex::scoped_lock lock(mutex_);
100 
101  // copy values
102  name_ = message.name;
103  description_ = message.description;
104 
105  if (message.controls.empty())
106  {
107  Q_EMIT statusUpdate(StatusProperty::Ok, name_, "Marker empty.");
108  return false;
109  }
110 
111  scale_ = message.scale;
112 
113  reference_frame_ = message.header.frame_id;
114  reference_time_ = message.header.stamp;
115  frame_locked_ = (message.header.stamp == ros::Time(0));
116 
117  position_ = Ogre::Vector3(message.pose.position.x, message.pose.position.y, message.pose.position.z);
118 
119  normalizeQuaternion(message.pose.orientation, orientation_);
120 
121  pose_changed_ = false;
123 
124  // setup axes
127  axes_->set(scale_, scale_ * 0.05);
128 
129  has_menu_ = !message.menu_entries.empty();
130 
132 
133  // Instead of just erasing all the old controls and making new ones
134  // here, we want to preserve as much as possible from the old ones,
135  // so that we don't lose the drag action in progress if a control is
136  // being dragged when this update comes in.
137  //
138  // Controls are stored in a map from control name to control
139  // pointer, so we loop over the incoming control messages looking
140  // for names we already know about. When we find them, we just call
141  // the control's processMessage() function to update it. When we
142  // don't find them, we create a new Control. We also keep track of
143  // which control names we used to have but which are not present in
144  // the incoming message, which we use to delete the unwanted
145  // controls.
146 
147  // Make set of old-names called old-names-to-delete.
148  std::set<std::string> old_names_to_delete;
149  M_ControlPtr::const_iterator ci;
150  for (ci = controls_.begin(); ci != controls_.end(); ci++)
151  {
152  old_names_to_delete.insert((*ci).first);
153  }
154 
155  // Loop over new array:
156  for (unsigned i = 0; i < message.controls.size(); i++)
157  {
158  const visualization_msgs::InteractiveMarkerControl& control_message = message.controls[i];
159  M_ControlPtr::iterator search_iter = controls_.find(control_message.name);
161 
162  // If message->name in map,
163  if (search_iter != controls_.end())
164  {
165  // Use existing control
166  control = (*search_iter).second;
167  }
168  else
169  {
170  // Else make new control
171  control = boost::make_shared<InteractiveMarkerControl>(context_, reference_node_, this);
172  controls_[control_message.name] = control;
173  }
174  // Update the control with the message data
175  control->processMessage(control_message);
176  control->setShowVisualAids(show_visual_aids_);
177 
178  // Remove message->name from old-names-to-delete
179  old_names_to_delete.erase(control_message.name);
180  }
181 
182  // Loop over old-names-to-delete
183  std::set<std::string>::iterator si;
184  for (si = old_names_to_delete.begin(); si != old_names_to_delete.end(); si++)
185  {
186  // Remove Control object from map for name-to-delete
187  controls_.erase(*si);
188  }
189 
190  description_control_ = boost::make_shared<InteractiveMarkerControl>(context_, reference_node_, this);
191 
192  if (!message.description.empty())
193  description_control_->processMessage(interactive_markers::makeTitle(message));
194 
195  // create menu
196  menu_entries_.clear();
197  menu_.reset();
198  if (has_menu_)
199  {
200  menu_.reset(new QMenu());
201  top_level_menu_ids_.clear();
202 
203  // Put all menu entries into the menu_entries_ map and create the
204  // tree of menu entry ids.
205  for (unsigned m = 0; m < message.menu_entries.size(); m++)
206  {
207  const visualization_msgs::MenuEntry& entry = message.menu_entries[m];
208  MenuNode node;
209  node.entry = entry;
210  menu_entries_[entry.id] = node;
211  if (entry.parent_id == 0)
212  {
213  top_level_menu_ids_.push_back(entry.id);
214  }
215  else
216  {
217  // Find the parent node and add this entry to the parent's list of children.
218  std::map<uint32_t, MenuNode>::iterator parent_it = menu_entries_.find(entry.parent_id);
219  if (parent_it == menu_entries_.end())
220  {
221  ROS_ERROR("interactive marker menu entry %u found before its parent id %u. Ignoring.",
222  entry.id, entry.parent_id);
223  }
224  else
225  {
226  (*parent_it).second.child_ids.push_back(entry.id);
227  }
228  }
229  }
231  }
232 
233  if (frame_locked_)
234  {
235  std::ostringstream s;
236  s << "Locked to frame " << reference_frame_;
237  Q_EMIT statusUpdate(StatusProperty::Ok, name_, s.str());
238  }
239  else
240  {
241  Q_EMIT statusUpdate(StatusProperty::Ok, name_, "Position is fixed.");
242  }
243  return true;
244 }
245 
246 // Recursively append menu and submenu entries to menu, based on a
247 // vector of menu entry id numbers describing the menu entries at the
248 // current level.
249 void InteractiveMarker::populateMenu(QMenu* menu, std::vector<uint32_t>& ids)
250 {
251  for (size_t id_index = 0; id_index < ids.size(); id_index++)
252  {
253  uint32_t id = ids[id_index];
254  std::map<uint32_t, MenuNode>::iterator node_it = menu_entries_.find(id);
255  ROS_ASSERT_MSG(node_it != menu_entries_.end(),
256  "interactive marker menu entry %u not found during populateMenu().", id);
257  MenuNode node = (*node_it).second;
258 
259  if (node.child_ids.empty())
260  {
262  new IntegerAction(makeMenuString(node.entry.title), menu, (int)node.entry.id);
263  connect(action, SIGNAL(triggered(int)), this, SLOT(handleMenuSelect(int)));
264  menu->addAction(action);
265  }
266  else
267  {
268  // make sub-menu
269  QMenu* sub_menu = menu->addMenu(makeMenuString(node.entry.title));
270  populateMenu(sub_menu, node.child_ids);
271  }
272  }
273 }
274 
275 QString InteractiveMarker::makeMenuString(const std::string& entry)
276 {
277  QString menu_entry;
278  if (entry.find("[x]") == 0)
279  {
280  menu_entry = QChar(0x2611) + QString::fromStdString(entry.substr(3));
281  }
282  else if (entry.find("[ ]") == 0)
283  {
284  menu_entry = QChar(0x2610) + QString::fromStdString(entry.substr(3));
285  }
286  else
287  {
288  menu_entry = QChar(0x3000) + QString::fromStdString(entry);
289  }
290  return menu_entry;
291 }
292 
293 
295 {
296  boost::recursive_mutex::scoped_lock lock(mutex_);
297  Ogre::Vector3 reference_position;
298  Ogre::Quaternion reference_orientation;
299 
300  // if we're frame-locked, we need to find out what the most recent transformation time
301  // actually is so we send back correct feedback
302  if (frame_locked_)
303  {
304  std::string fixed_frame = context_->getFrameManager()->getFixedFrame();
305  if (reference_frame_ == fixed_frame)
306  {
307  // if the two frames are identical, we don't need to do anything.
308  // This should be ros::Time::now(), but then the computer running
309  // RViz has to be time-synced with the server
311  }
312  else
313  {
314  std::string error;
315 // TODO(wjwwood): remove this and use tf2 interface instead
316 #ifndef _WIN32
317 #pragma GCC diagnostic push
318 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
319 #endif
320 
322  reference_frame_, fixed_frame, reference_time_, &error);
323 
324 #ifndef _WIN32
325 #pragma GCC diagnostic pop
326 #endif
327  if (retval != tf::NO_ERROR)
328  {
329  std::ostringstream s;
330  s << "Error getting time of latest transform between " << reference_frame_ << " and "
331  << fixed_frame << ": " << error << " (error code: " << retval << ")";
332  Q_EMIT statusUpdate(StatusProperty::Error, name_, s.str());
333  reference_node_->setVisible(false);
334  return;
335  }
336  }
337  }
338 
339  if (!context_->getFrameManager()->getTransform(reference_frame_, ros::Time(), reference_position,
340  reference_orientation))
341  {
342  std::string error;
344  Q_EMIT statusUpdate(StatusProperty::Error, name_, error);
345  reference_node_->setVisible(false);
346  return;
347  }
348 
349  reference_node_->setPosition(reference_position);
350  reference_node_->setOrientation(reference_orientation);
351  reference_node_->setVisible(true, false);
352 
354 }
355 
356 
357 void InteractiveMarker::update(float wall_dt)
358 {
359  boost::recursive_mutex::scoped_lock lock(mutex_);
360  time_since_last_feedback_ += wall_dt;
361  if (frame_locked_)
362  {
364  }
365 
366  M_ControlPtr::iterator it;
367  for (it = controls_.begin(); it != controls_.end(); it++)
368  {
369  (*it).second->update();
370  }
372  {
373  description_control_->update();
374  }
375 
376  if (dragging_)
377  {
378  if (pose_changed_)
379  {
380  publishPose();
381  }
382  else if (time_since_last_feedback_ > 0.25)
383  {
384  // send keep-alive so we don't use control over the marker
385  visualization_msgs::InteractiveMarkerFeedback feedback;
386  feedback.event_type = visualization_msgs::InteractiveMarkerFeedback::KEEP_ALIVE;
387  publishFeedback(feedback);
388  }
389  }
390 }
391 
393 {
394  boost::recursive_mutex::scoped_lock lock(mutex_);
395  visualization_msgs::InteractiveMarkerFeedback feedback;
396  feedback.event_type = visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE;
397  feedback.control_name = last_control_name_;
398  publishFeedback(feedback);
399  pose_changed_ = false;
400 }
401 
402 void InteractiveMarker::requestPoseUpdate(Ogre::Vector3 position, Ogre::Quaternion orientation)
403 {
404  boost::recursive_mutex::scoped_lock lock(mutex_);
405  if (dragging_)
406  {
407  pose_update_requested_ = true;
408  requested_position_ = position;
409  requested_orientation_ = orientation;
410  }
411  else
412  {
414  setPose(position, orientation, "");
415  }
416 }
417 
418 void InteractiveMarker::setPose(Ogre::Vector3 position,
419  Ogre::Quaternion orientation,
420  const std::string& control_name)
421 {
422  boost::recursive_mutex::scoped_lock lock(mutex_);
423  position_ = position;
424  orientation_ = orientation;
425  pose_changed_ = true;
426  last_control_name_ = control_name;
427 
430 
431  M_ControlPtr::iterator it;
432  for (it = controls_.begin(); it != controls_.end(); it++)
433  {
434  (*it).second->interactiveMarkerPoseChanged(position_, orientation_);
435  }
437  {
438  description_control_->interactiveMarkerPoseChanged(position_, orientation_);
439  }
440 }
441 
443 {
444  boost::recursive_mutex::scoped_lock lock(mutex_);
445  if (description_control_.get())
446  {
447  description_control_->setVisible(show);
448  }
449 }
450 
452 {
453  boost::recursive_mutex::scoped_lock lock(mutex_);
454  axes_->getSceneNode()->setVisible(show);
455 }
456 
458 {
459  boost::recursive_mutex::scoped_lock lock(mutex_);
460  M_ControlPtr::iterator it;
461  for (it = controls_.begin(); it != controls_.end(); it++)
462  {
463  (*it).second->setShowVisualAids(show);
464  }
465  show_visual_aids_ = show;
466 }
467 
468 void InteractiveMarker::translate(Ogre::Vector3 delta_position, const std::string& control_name)
469 {
470  boost::recursive_mutex::scoped_lock lock(mutex_);
471  setPose(position_ + delta_position, orientation_, control_name);
472 }
473 
474 void InteractiveMarker::rotate(Ogre::Quaternion delta_orientation, const std::string& control_name)
475 {
476  boost::recursive_mutex::scoped_lock lock(mutex_);
477  setPose(position_, delta_orientation * orientation_, control_name);
478 }
479 
481 {
482  boost::recursive_mutex::scoped_lock lock(mutex_);
483  dragging_ = true;
484  pose_changed_ = false;
485 }
486 
488 {
489  boost::recursive_mutex::scoped_lock lock(mutex_);
490  dragging_ = false;
492  {
495  pose_update_requested_ = false;
496  }
497 }
498 
500  const Ogre::Vector3& cursor_pos,
501  const Ogre::Quaternion& /*cursor_rot*/,
502  const std::string& control_name)
503 {
504  boost::recursive_mutex::scoped_lock lock(mutex_);
505 
506  if (event.acting_button == Qt::LeftButton)
507  {
508  Ogre::Vector3 point_rel_world = cursor_pos;
509  bool got_3D_point = true;
510 
511  visualization_msgs::InteractiveMarkerFeedback feedback;
512  feedback.control_name = control_name;
513  feedback.marker_name = name_;
514 
515  // make sure we've published a last pose update
516  feedback.event_type = ((uint8_t)visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE);
517  publishFeedback(feedback, got_3D_point, point_rel_world);
518 
519  feedback.event_type = (event.type == QEvent::MouseButtonPress ?
520  (uint8_t)visualization_msgs::InteractiveMarkerFeedback::MOUSE_DOWN :
521  (uint8_t)visualization_msgs::InteractiveMarkerFeedback::MOUSE_UP);
522  publishFeedback(feedback, got_3D_point, point_rel_world);
523  }
524 
525  if (!dragging_ && menu_.get())
526  {
527  // Event.right() will be false during a right-button-up event. We
528  // want to swallow (with the "return true") all other
529  // right-button-related mouse events.
530  if (event.right())
531  {
532  return true;
533  }
534  if (event.rightUp() && event.buttons_down == Qt::NoButton)
535  {
536  // Save the 3D mouse point to send with the menu feedback, if any.
537  Ogre::Vector3 three_d_point = cursor_pos;
538  bool valid_point = true;
539  Ogre::Vector2 mouse_pos = project3DPointToViewportXY(event.viewport, cursor_pos);
540  QCursor::setPos(event.panel->mapToGlobal(QPoint(mouse_pos.x, mouse_pos.y)));
541  showMenu(event, control_name, three_d_point, valid_point);
542  return true;
543  }
544  }
545 
546  return false;
547 }
548 
549 bool InteractiveMarker::handleMouseEvent(ViewportMouseEvent& event, const std::string& control_name)
550 {
551  boost::recursive_mutex::scoped_lock lock(mutex_);
552 
553  if (event.acting_button == Qt::LeftButton)
554  {
555  Ogre::Vector3 point_rel_world;
556  bool got_3D_point =
557  context_->getSelectionManager()->get3DPoint(event.viewport, event.x, event.y, point_rel_world);
558 
559  visualization_msgs::InteractiveMarkerFeedback feedback;
560  feedback.control_name = control_name;
561  feedback.marker_name = name_;
562 
563  // make sure we've published a last pose update
564  feedback.event_type = ((uint8_t)visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE);
565  publishFeedback(feedback, got_3D_point, point_rel_world);
566 
567  feedback.event_type = (event.type == QEvent::MouseButtonPress ?
568  (uint8_t)visualization_msgs::InteractiveMarkerFeedback::MOUSE_DOWN :
569  (uint8_t)visualization_msgs::InteractiveMarkerFeedback::MOUSE_UP);
570  publishFeedback(feedback, got_3D_point, point_rel_world);
571  }
572 
573  if (!dragging_ && menu_.get())
574  {
575  // Event.right() will be false during a right-button-up event. We
576  // want to swallow (with the "return true") all other
577  // right-button-related mouse events.
578  if (event.right())
579  {
580  return true;
581  }
582  if (event.rightUp() && event.buttons_down == Qt::NoButton)
583  {
584  // Save the 3D mouse point to send with the menu feedback, if any.
585  Ogre::Vector3 three_d_point;
586  bool valid_point =
587  context_->getSelectionManager()->get3DPoint(event.viewport, event.x, event.y, three_d_point);
588  showMenu(event, control_name, three_d_point, valid_point);
589  return true;
590  }
591  }
592 
593  return false;
594 }
595 
596 
598  const std::string& control_name,
599  const Ogre::Vector3& three_d_point,
600  bool valid_point)
601 {
602  // Save the 3D mouse point to send with the menu feedback, if any.
603  got_3d_point_for_menu_ = valid_point;
604  three_d_point_for_menu_ = three_d_point;
605 
606  event.panel->showContextMenu(menu_);
607  last_control_name_ = control_name;
608 }
609 
610 
612 {
613  boost::recursive_mutex::scoped_lock lock(mutex_);
614 
615  std::map<uint32_t, MenuNode>::iterator it = menu_entries_.find(menu_item_id);
616 
617  if (it != menu_entries_.end())
618  {
619  visualization_msgs::MenuEntry& entry = it->second.entry;
620 
621  std::string command = entry.command;
622  uint8_t command_type = entry.command_type;
623 
624  if (command_type == visualization_msgs::MenuEntry::FEEDBACK)
625  {
626  visualization_msgs::InteractiveMarkerFeedback feedback;
627  feedback.event_type = visualization_msgs::InteractiveMarkerFeedback::MENU_SELECT;
628  feedback.menu_entry_id = entry.id;
629  feedback.control_name = last_control_name_;
631  }
632  else if (command_type == visualization_msgs::MenuEntry::ROSRUN)
633  {
634  std::string sys_cmd = "rosrun " + command;
635  ROS_INFO_STREAM("Running system command: " << sys_cmd);
636  sys_thread_ =
637  boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&system, sys_cmd.c_str())));
638  // system( sys_cmd.c_str() );
639  }
640  else if (command_type == visualization_msgs::MenuEntry::ROSLAUNCH)
641  {
642  std::string sys_cmd = "roslaunch " + command;
643  ROS_INFO_STREAM("Running system command: " << sys_cmd);
644  sys_thread_ =
645  boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&system, sys_cmd.c_str())));
646  // system( sys_cmd.c_str() );
647  }
648  }
649 }
650 
651 
652 void InteractiveMarker::publishFeedback(visualization_msgs::InteractiveMarkerFeedback& feedback,
653  bool mouse_point_valid,
654  const Ogre::Vector3& mouse_point_rel_world)
655 {
656  boost::recursive_mutex::scoped_lock lock(mutex_);
657 
658  feedback.marker_name = name_;
659 
660  if (frame_locked_)
661  {
662  // frame-locked IMs will return their pose in the same coordinate frame
663  // as they were set up with (the "reference frame").
664  // The transformation's timestamp will be the one used for placing
665  // the reference frame into the fixed frame
666  feedback.header.frame_id = reference_frame_;
667  feedback.header.stamp = reference_time_;
668  feedback.pose.position.x = position_.x;
669  feedback.pose.position.y = position_.y;
670  feedback.pose.position.z = position_.z;
671  feedback.pose.orientation.x = orientation_.x;
672  feedback.pose.orientation.y = orientation_.y;
673  feedback.pose.orientation.z = orientation_.z;
674  feedback.pose.orientation.w = orientation_.w;
675 
676  feedback.mouse_point_valid = mouse_point_valid;
677  if (mouse_point_valid)
678  {
679  Ogre::Vector3 mouse_rel_reference =
680  reference_node_->convertWorldToLocalPosition(mouse_point_rel_world);
681  feedback.mouse_point.x = mouse_rel_reference.x;
682  feedback.mouse_point.y = mouse_rel_reference.y;
683  feedback.mouse_point.z = mouse_rel_reference.z;
684  }
685  }
686  else
687  {
688  // Timestamped IMs will return feedback in RViz's fixed frame
689  feedback.header.frame_id = context_->getFixedFrame().toStdString();
690  // This should be ros::Time::now(), but then the computer running
691  // RViz has to be time-synced with the server
692  feedback.header.stamp = ros::Time();
693 
694  Ogre::Vector3 world_position = reference_node_->convertLocalToWorldPosition(position_);
695  Ogre::Quaternion world_orientation = reference_node_->convertLocalToWorldOrientation(orientation_);
696 
697  feedback.pose.position.x = world_position.x;
698  feedback.pose.position.y = world_position.y;
699  feedback.pose.position.z = world_position.z;
700  feedback.pose.orientation.x = world_orientation.x;
701  feedback.pose.orientation.y = world_orientation.y;
702  feedback.pose.orientation.z = world_orientation.z;
703  feedback.pose.orientation.w = world_orientation.w;
704 
705  feedback.mouse_point_valid = mouse_point_valid;
706  feedback.mouse_point.x = mouse_point_rel_world.x;
707  feedback.mouse_point.y = mouse_point_rel_world.y;
708  feedback.mouse_point.z = mouse_point_rel_world.z;
709  }
710 
711  Q_EMIT userFeedback(feedback);
712 
714 }
715 
716 } // end namespace rviz
boost::recursive_mutex mutex_
void translate(Ogre::Vector3 delta_position, const std::string &control_name)
void setOrientation(const Ogre::Quaternion &orientation) override
Set the orientation of the object.
Definition: axes.cpp:88
bool transformHasProblems(const std::string &frame, ros::Time time, std::string &error)
Check to see if a transform is known between a given frame and the fixed frame.
void setShowDescription(bool show)
void rotate(Ogre::Quaternion delta_orientation, const std::string &control_name)
XmlRpcServer s
INTERACTIVE_MARKERS_PUBLIC visualization_msgs::InteractiveMarkerControl makeTitle(const visualization_msgs::InteractiveMarker &msg)
Ogre::Vector3 three_d_point_for_menu_
void populateMenu(QMenu *menu, std::vector< uint32_t > &ids)
boost::shared_ptr< boost::thread > sys_thread_
Ogre::Vector2 project3DPointToViewportXY(const Ogre::Viewport *view, const Ogre::Vector3 &pos)
Given a viewport and a 3D position in world coordinates, project that point into the view plane...
Definition: geometry.cpp:75
QString makeMenuString(const std::string &entry)
void publishFeedback(visualization_msgs::InteractiveMarkerFeedback &feedback, bool mouse_point_valid=false, const Ogre::Vector3 &mouse_point_rel_world=Ogre::Vector3(0, 0, 0))
Pure-virtual base class for objects which give Display subclasses context in which to work...
void handleMenuSelect(int menu_item_id)
ROSLIB_DECL std::string command(const std::string &cmd)
bool handle3DCursorEvent(ViewportMouseEvent &event, const Ogre::Vector3 &cursor_pos, const Ogre::Quaternion &cursor_rot, const std::string &control_name)
bool processMessage(const visualization_msgs::InteractiveMarker &message)
#define ROS_ASSERT_MSG(cond,...)
InteractiveMarker(Ogre::SceneNode *scene_node, DisplayContext *context)
Ogre::Quaternion requested_orientation_
InteractiveMarkerControlPtr description_control_
virtual FrameManager * getFrameManager() const =0
Return the FrameManager instance.
virtual SelectionManager * getSelectionManager() const =0
Return a pointer to the SelectionManager.
void showMenu(ViewportMouseEvent &event, const std::string &control_name, const Ogre::Vector3 &three_d_point, bool valid_point)
tf::TransformListener * getTFClient()
Return the tf::TransformListener used to receive transform data.
const std::string & getFixedFrame()
Return the current fixed frame name.
float normalizeQuaternion(float &w, float &x, float &y, float &z)
An object that displays a set of X/Y/Z axes, with X=Red, Y=Green, Z=Blue.
Definition: axes.h:59
action
visualization_msgs::MenuEntry entry
void userFeedback(visualization_msgs::InteractiveMarkerFeedback &feedback)
std::vector< uint32_t > top_level_menu_ids_
void setPosition(const Ogre::Vector3 &position) override
Set the position of this object.
Definition: axes.cpp:83
int getLatestCommonTime(const std::string &source_frame, const std::string &target_frame, ros::Time &time, std::string *error_string) const
virtual Ogre::SceneManager * getSceneManager() const =0
Returns the Ogre::SceneManager used for the main RenderPanel.
virtual void queueRender()=0
Queues a render. Multiple calls before a render happens will only cause a single render.
virtual QString getFixedFrame() const =0
Return the fixed frame name.
#define ROS_INFO_STREAM(args)
void setPose(Ogre::Vector3 position, Ogre::Quaternion orientation, const std::string &control_name)
void statusUpdate(StatusProperty::Level level, const std::string &name, const std::string &text)
bool getTransform(const Header &header, Ogre::Vector3 &position, Ogre::Quaternion &orientation)
Return the pose for a header, relative to the fixed frame, in Ogre classes.
void set(float length, float radius)
Set the parameters on this object.
Definition: axes.cpp:68
boost::shared_ptr< QMenu > menu_
Ogre::Quaternion orientation_
void update(float wall_dt)
void requestPoseUpdate(Ogre::Vector3 position, Ogre::Quaternion orientation)
bool handleMouseEvent(ViewportMouseEvent &event, const std::string &control_name)
std::map< uint32_t, MenuNode > menu_entries_
Ogre::SceneNode * getSceneNode()
Get the scene node associated with this object.
Definition: axes.h:95
bool get3DPoint(Ogre::Viewport *viewport, const int x, const int y, Ogre::Vector3 &result_point)
#define ROS_ERROR(...)
Ogre::SceneNode * reference_node_
NO_ERROR


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