motion_planning_display.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 /* Author: Ioan Sucan, Dave Coleman, Adam Leeper */
00031 
00032 #include <moveit/motion_planning_rviz_plugin/motion_planning_display.h>
00033 #include <moveit/rviz_plugin_render_tools/planning_link_updater.h>
00034 #include <moveit/rviz_plugin_render_tools/robot_state_visualization.h>
00035 #include <rviz/visualization_manager.h>
00036 #include <rviz/robot/robot.h>
00037 #include <rviz/robot/robot_link.h>
00038 
00039 #include <rviz/properties/property.h>
00040 #include <rviz/properties/string_property.h>
00041 #include <rviz/properties/bool_property.h>
00042 #include <rviz/properties/float_property.h>
00043 #include <rviz/properties/ros_topic_property.h>
00044 #include <rviz/properties/editable_enum_property.h>
00045 #include <rviz/properties/color_property.h>
00046 #include <rviz/display_context.h>
00047 #include <rviz/frame_manager.h>
00048 #include <rviz/panel_dock_widget.h>
00049 #include <rviz/window_manager_interface.h>
00050 #include <rviz/display_factory.h>
00051 #include <rviz/ogre_helpers/movable_text.h>
00052 
00053 #include <OGRE/OgreSceneManager.h>
00054 #include <rviz/ogre_helpers/shape.h>
00055 
00056 #include <tf/transform_listener.h>
00057 
00058 #include <moveit/robot_state/conversions.h>
00059 #include <moveit/trajectory_processing/trajectory_tools.h>
00060 
00061 #include <boost/format.hpp>
00062 #include <boost/algorithm/string/replace.hpp>
00063 #include <boost/algorithm/string/trim.hpp>
00064 #include <boost/lexical_cast.hpp>
00065 
00066 #include <QShortcut>
00067 
00068 #include "ui_motion_planning_rviz_plugin_frame.h"
00069 
00070 namespace moveit_rviz_plugin
00071 {
00072 
00073 // ******************************************************************************************
00074 // Base class contructor
00075 // ******************************************************************************************
00076 MotionPlanningDisplay::MotionPlanningDisplay() :
00077   PlanningSceneDisplay(),
00078   frame_(NULL),
00079   frame_dock_(NULL),
00080   animating_path_(false),
00081   int_marker_display_(NULL),
00082   private_handle_("~"),
00083   menu_handler_start_(new interactive_markers::MenuHandler),
00084   menu_handler_goal_(new interactive_markers::MenuHandler)
00085 {
00086   // Category Groups
00087   plan_category_  = new rviz::Property( "Planning Request",   QVariant(), "", this );
00088   metrics_category_ = new rviz::Property( "Planning Metrics", QVariant(), "", this );
00089   path_category_  = new rviz::Property( "Planned Path",   QVariant(), "", this );
00090 
00091   // Metrics category -----------------------------------------------------------------------------------------
00092   compute_weight_limit_property_ = new rviz::BoolProperty( "Show Weight Limit", false, "Shows the weight limit at a particular pose for an end-effector",
00093                                                            metrics_category_,
00094                                                            SLOT( changedShowWeightLimit() ), this );
00095 
00096   show_manipulability_index_property_ = new rviz::BoolProperty( "Show Manipulability Index", false, "Shows the manipulability index for an end-effector",
00097                                                                 metrics_category_,
00098                                                                 SLOT( changedShowManipulabilityIndex() ), this );
00099 
00100   show_manipulability_property_ = new rviz::BoolProperty( "Show Manipulability", false, "Shows the manipulability for an end-effector",
00101                                                           metrics_category_,
00102                                                           SLOT( changedShowManipulability() ), this );
00103 
00104   show_joint_torques_property_ = new rviz::BoolProperty( "Show Joint Torques", false, "Shows the joint torques for a given configuration and payload",
00105                                                          metrics_category_,
00106                                                          SLOT( changedShowJointTorques() ), this );
00107 
00108   metrics_set_payload_property_ =
00109     new rviz::FloatProperty( "Payload", 1.0f, "Specify the payload at the end effector (kg)",
00110                              metrics_category_,
00111                              SLOT( changedMetricsSetPayload() ), this );
00112   metrics_set_payload_property_->setMin( 0.0 );
00113 
00114   metrics_text_height_property_ =
00115     new rviz::FloatProperty( "TextHeight", 0.08f, "Text height",
00116                              metrics_category_,
00117                              SLOT( changedMetricsTextHeight() ), this );
00118   metrics_text_height_property_->setMin( 0.001 );
00119 
00120   // Planning request category -----------------------------------------------------------------------------------------
00121 
00122   planning_group_property_ = new rviz::EditableEnumProperty("Planning Group", "", "The name of the group of links to plan for (from the ones defined in the SRDF)",
00123                                                             plan_category_,
00124                                                             SLOT( changedPlanningGroup() ), this );
00125   show_workspace_property_ = new rviz::BoolProperty( "Show Workspace", false, "Shows the axis-aligned bounding box for the workspace allowed for planning",
00126                                                      plan_category_,
00127                                                      SLOT( changedWorkspace() ), this );
00128   query_start_state_property_ = new rviz::BoolProperty( "Query Start State", true, "Shows the start state for the motion planning query",
00129                                                         plan_category_,
00130                                                         SLOT( changedQueryStartState() ), this );
00131   query_goal_state_property_ = new rviz::BoolProperty( "Query Goal State", true, "Shows the goal state for the motion planning query",
00132                                                        plan_category_,
00133                                                        SLOT( changedQueryGoalState() ), this );
00134   query_marker_scale_property_ = new rviz::FloatProperty( "Interactive Marker Size", 0.0f, "Specifies scale of the interactive marker overlayed on the robot",
00135                                                           plan_category_,
00136                                                           SLOT( changedQueryMarkerScale() ), this );
00137   query_marker_scale_property_->setMin(0.0f);
00138 
00139   query_start_color_property_ = new rviz::ColorProperty("Start State Color", QColor(0, 255, 0), "The highlight color for the start state",
00140                                                         plan_category_,
00141                                                         SLOT( changedQueryStartColor() ), this);
00142   query_start_alpha_property_ = new rviz::FloatProperty( "Start State Alpha", 1.0f, "Specifies the alpha for the robot links",
00143                                                          plan_category_,
00144                                                          SLOT( changedQueryStartAlpha() ), this );
00145   query_start_alpha_property_->setMin( 0.0 );
00146   query_start_alpha_property_->setMax( 1.0 );
00147 
00148 
00149   query_goal_color_property_ = new rviz::ColorProperty( "Goal State Color", QColor(250, 128, 0), "The highlight color for the goal state",
00150                                                         plan_category_,
00151                                                         SLOT( changedQueryGoalColor() ), this );
00152 
00153   query_goal_alpha_property_ =
00154     new rviz::FloatProperty( "Goal State Alpha", 1.0f, "Specifies the alpha for the robot links",
00155                              plan_category_,
00156                              SLOT( changedQueryGoalAlpha() ), this );
00157   query_goal_alpha_property_->setMin( 0.0 );
00158   query_goal_alpha_property_->setMax( 1.0 );
00159 
00160   query_colliding_link_color_property_ = new rviz::ColorProperty( "Colliding Link Color", QColor(255, 0, 0), "The highlight color for colliding links",
00161                                                                   plan_category_,
00162                                                                   SLOT( changedQueryCollidingLinkColor() ), this );
00163 
00164   query_outside_joint_limits_link_color_property_ = new rviz::ColorProperty( "Joint Violation Color", QColor(255, 0, 255),
00165                                                                              "The highlight color for child links of joints that are outside bounds",
00166                                                                              plan_category_,
00167                                                                              SLOT( changedQueryJointViolationColor() ), this );
00168   // Path category ----------------------------------------------------------------------------------------------------
00169 
00170   trajectory_topic_property_ =
00171     new rviz::RosTopicProperty( "Trajectory Topic", "/move_group/display_planned_path",
00172                                 ros::message_traits::datatype<moveit_msgs::DisplayTrajectory>(),
00173                                 "The topic on which the moveit_msgs::DisplayTrajectory messages are received",
00174                                 path_category_,
00175                                 SLOT( changedTrajectoryTopic() ), this );
00176 
00177   display_path_visual_enabled_property_ =
00178     new rviz::BoolProperty( "Show Robot Visual", true, "Indicates whether the geometry of the robot as defined for visualisation purposes should be displayed",
00179                             path_category_,
00180                             SLOT( changedDisplayPathVisualEnabled() ), this );
00181 
00182   display_path_collision_enabled_property_ =
00183     new rviz::BoolProperty( "Show Robot Collision", false, "Indicates whether the geometry of the robot as defined for collision detection purposes should be displayed",
00184                             path_category_,
00185                             SLOT( changedDisplayPathCollisionEnabled() ), this );
00186 
00187   robot_path_alpha_property_ =
00188     new rviz::FloatProperty( "Robot Alpha", 0.5f, "Specifies the alpha for the robot links",
00189                              path_category_,
00190                              SLOT( changedRobotPathAlpha() ), this );
00191   robot_path_alpha_property_->setMin( 0.0 );
00192   robot_path_alpha_property_->setMax( 1.0 );
00193 
00194   state_display_time_property_ =  new rviz::EditableEnumProperty("State Display Time", "0.05 s",
00195                                                                  "The amount of wall-time to wait in between displaying states along a received trajectory path",
00196                                                                  path_category_,
00197                                                                  SLOT( changedStateDisplayTime() ), this );
00198   state_display_time_property_->addOptionStd("REALTIME");
00199   state_display_time_property_->addOptionStd("0.05 s");
00200   state_display_time_property_->addOptionStd("0.1 s");
00201   state_display_time_property_->addOptionStd("0.5 s");
00202 
00203   loop_display_property_ =
00204     new rviz::BoolProperty( "Loop Animation", false, "Indicates whether the last received path is to be animated in a loop",
00205                             path_category_,
00206                             SLOT( changedLoopDisplay() ), this );
00207 
00208   trail_display_property_ =
00209     new rviz::BoolProperty( "Show Trail", false, "Show a path trail",
00210                             path_category_,
00211                             SLOT( changedShowTrail() ), this );
00212 
00213   background_process_.setJobUpdateEvent(boost::bind(&MotionPlanningDisplay::backgroundJobUpdate, this, _1));
00214 }
00215 
00216 // ******************************************************************************************
00217 // Deconstructor
00218 // ******************************************************************************************
00219 MotionPlanningDisplay::~MotionPlanningDisplay()
00220 {
00221   background_process_.setJobUpdateEvent(BackgroundProcessing::JobUpdateCallback());
00222   clearJobs();
00223 
00224   clearTrajectoryTrail();
00225   trajectory_message_to_display_.reset();
00226   displaying_trajectory_message_.reset();
00227 
00228   display_path_robot_.reset();
00229   query_robot_start_.reset();
00230   query_robot_goal_.reset();
00231 
00232   delete text_to_display_;
00233   delete int_marker_display_;
00234   delete frame_dock_;
00235 }
00236 
00237 void MotionPlanningDisplay::onInitialize()
00238 {
00239   PlanningSceneDisplay::onInitialize();
00240 
00241   display_path_robot_.reset(new RobotStateVisualization(planning_scene_node_, context_, "Planned Path", path_category_));
00242   display_path_robot_->setVisualVisible(display_path_visual_enabled_property_->getBool() );
00243   display_path_robot_->setCollisionVisible( display_path_collision_enabled_property_->getBool() );
00244   display_path_robot_->setVisible(false);
00245 
00246   query_robot_start_.reset(new RobotStateVisualization(planning_scene_node_, context_, "Planning Request Start", NULL));
00247   query_robot_start_->setCollisionVisible(false);
00248   query_robot_start_->setVisualVisible(true);
00249   query_robot_start_->setVisible( query_start_state_property_->getBool() );
00250   std_msgs::ColorRGBA color; QColor qcolor = query_start_color_property_->getColor();
00251   color.r = qcolor.redF(); color.g = qcolor.greenF(); color.b = qcolor.blueF(); color.a = 1.0f;
00252   query_robot_start_->setDefaultAttachedObjectColor(color);
00253 
00254   query_robot_goal_.reset(new RobotStateVisualization(planning_scene_node_, context_, "Planning Request Goal", NULL ));
00255   query_robot_goal_->setCollisionVisible(false);
00256   query_robot_goal_->setVisualVisible(true);
00257   query_robot_goal_->setVisible( query_goal_state_property_->getBool() );
00258   qcolor = query_goal_color_property_->getColor();
00259   color.r = qcolor.redF(); color.g = qcolor.greenF(); color.b = qcolor.blueF();
00260   query_robot_goal_->setDefaultAttachedObjectColor(color);
00261 
00262   rviz::WindowManagerInterface* window_context = context_->getWindowManager();
00263   frame_ = new MotionPlanningFrame(this, context_, window_context ? window_context->getParentWindow() : NULL);
00264   resetStatusTextColor();
00265   addStatusText("Initialized.");
00266 
00267   if (window_context)
00268     frame_dock_ = window_context->addPane("Motion Planning", frame_);
00269 
00270   int_marker_display_ = context_->getDisplayFactory()->make("rviz/InteractiveMarkers");
00271   int_marker_display_->initialize(context_);
00272 
00273   text_display_scene_node_ = planning_scene_node_->createChildSceneNode();
00274   text_to_display_ = new rviz::MovableText("EMPTY");
00275   text_to_display_->setTextAlignment(rviz::MovableText::H_CENTER, rviz::MovableText::V_CENTER);
00276   text_to_display_->setCharacterHeight(metrics_text_height_property_->getFloat());
00277   text_to_display_->showOnTop();
00278   text_to_display_->setVisible(false);
00279   text_display_for_start_ = false;
00280   text_display_scene_node_->attachObject(text_to_display_);
00281 
00282   if (context_ && context_->getWindowManager() && context_->getWindowManager()->getParentWindow())
00283   {
00284     QShortcut *im_reset_shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_R), context_->getWindowManager()->getParentWindow());
00285     connect(im_reset_shortcut, SIGNAL( activated() ), this, SLOT( resetInteractiveMarkers() ) );
00286   }
00287 }
00288 
00289 void MotionPlanningDisplay::reset()
00290 {
00291   clearTrajectoryTrail();
00292   text_to_display_->setVisible(false);
00293   trajectory_message_to_display_.reset();
00294   displaying_trajectory_message_.reset();
00295   animating_path_ = false;
00296 
00297   display_path_robot_->clear();
00298   query_robot_start_->clear();
00299   query_robot_goal_->clear();
00300 
00301   PlanningSceneDisplay::reset();
00302 
00303   frame_->disable();
00304   frame_->enable();
00305 
00306   query_robot_start_->setVisible( query_start_state_property_->getBool() );
00307   query_robot_goal_->setVisible( query_goal_state_property_->getBool() );
00308   display_path_robot_->setVisualVisible(display_path_visual_enabled_property_->getBool() );
00309   display_path_robot_->setCollisionVisible(display_path_collision_enabled_property_->getBool());
00310   display_path_robot_->setVisible(false);
00311 }
00312 
00313 void MotionPlanningDisplay::backgroundJobUpdate(BackgroundProcessing::JobEvent )
00314 {
00315   addMainLoopJob(boost::bind(&MotionPlanningDisplay::updateBackgroundJobProgressBar, this));
00316 }
00317 
00318 void MotionPlanningDisplay::updateBackgroundJobProgressBar()
00319 {
00320   if (!frame_)
00321     return;
00322   QProgressBar *p = frame_->ui_->background_job_progress;
00323   std::size_t n = background_process_.getJobCount();
00324 
00325   if (n == 0)
00326   {
00327     p->setValue(p->maximum());
00328     p->update();
00329     p->hide();
00330     p->setMaximum(0);
00331   }
00332   else
00333   {
00334     if (n == 1)
00335     {
00336       if (p->maximum() == 0)
00337         p->setValue(0);
00338       else
00339         p->setValue(p->maximum() - 1);
00340     }
00341     else
00342     {
00343       if (p->maximum() < n)
00344         p->setMaximum(n);
00345       else
00346         p->setValue(p->maximum() - n);
00347     }
00348     p->show();
00349     p->update();
00350   }
00351 }
00352 
00353 void MotionPlanningDisplay::changedShowWeightLimit()
00354 {
00355   if (text_display_for_start_)
00356   {
00357     if (query_start_state_property_->getBool())
00358       displayMetrics(true);
00359   }
00360   else
00361   {
00362     if (query_goal_state_property_->getBool())
00363       displayMetrics(false);
00364   }
00365 }
00366 
00367 void MotionPlanningDisplay::changedShowManipulabilityIndex()
00368 {
00369   if (text_display_for_start_)
00370   {
00371     if (query_start_state_property_->getBool())
00372       displayMetrics(true);
00373   }
00374   else
00375   {
00376     if (query_goal_state_property_->getBool())
00377       displayMetrics(false);
00378   }
00379 }
00380 
00381 void MotionPlanningDisplay::changedShowManipulability()
00382 {
00383   if (text_display_for_start_)
00384   {
00385     if (query_start_state_property_->getBool())
00386       displayMetrics(true);
00387   }
00388   else
00389   {
00390     if (query_goal_state_property_->getBool())
00391       displayMetrics(false);
00392   }
00393 }
00394 
00395 void MotionPlanningDisplay::changedShowJointTorques()
00396 {
00397   if (text_display_for_start_)
00398   {
00399     if (query_start_state_property_->getBool())
00400       displayMetrics(true);
00401   }
00402   else
00403   {
00404     if (query_goal_state_property_->getBool())
00405       displayMetrics(false);
00406   }
00407 }
00408 
00409 void MotionPlanningDisplay::changedMetricsSetPayload()
00410 {
00411   if (text_display_for_start_)
00412   {
00413     if (query_start_state_property_->getBool())
00414       displayMetrics(true);
00415   }
00416   else
00417   {
00418     if (query_goal_state_property_->getBool())
00419       displayMetrics(false);
00420   }
00421 }
00422 
00423 void MotionPlanningDisplay::changedMetricsTextHeight()
00424 {
00425   text_to_display_->setCharacterHeight( metrics_text_height_property_->getFloat() );
00426 }
00427 
00428 void MotionPlanningDisplay::displayTable(const std::map<std::string, double> &values,
00429                                          const Ogre::ColourValue &color,
00430                                          const Ogre::Vector3 &pos,
00431                                          const Ogre::Quaternion &orient)
00432 {
00433   // the line we want to render
00434   std::stringstream ss;
00435   for (std::map<std::string, double>::const_iterator it = values.begin() ; it != values.end() ; ++it)
00436     ss << boost::format("%-10s %-4.2f") % it->first % it->second << std::endl;
00437 
00438   if (ss.str().empty())
00439   {
00440     text_to_display_->setVisible(false);
00441     return;
00442   }
00443 
00444   text_to_display_->setCaption(ss.str());
00445   text_to_display_->setColor(color);
00446   text_display_scene_node_->setPosition(pos);
00447   text_display_scene_node_->setOrientation(orient);
00448 
00449   // make sure the node is visible
00450   text_to_display_->setVisible(true);
00451 }
00452 
00453 void MotionPlanningDisplay::clearTrajectoryTrail()
00454 {
00455   for (std::size_t i = 0 ; i < trajectory_trail_.size() ; ++i)
00456     delete trajectory_trail_[i];
00457   trajectory_trail_.clear();
00458 }
00459 
00460 void MotionPlanningDisplay::changedLoopDisplay()
00461 {
00462   display_path_robot_->setVisible(isEnabled() && displaying_trajectory_message_ && animating_path_);
00463 }
00464 
00465 void MotionPlanningDisplay::changedShowTrail()
00466 {
00467   clearTrajectoryTrail();
00468 
00469   if (!trail_display_property_->getBool() || !planning_scene_monitor_)
00470     return;
00471   robot_trajectory::RobotTrajectoryPtr t = trajectory_message_to_display_;
00472   if (!t)
00473     t = displaying_trajectory_message_;
00474   if (!t)
00475     return;
00476 
00477   trajectory_trail_.resize(t->getWayPointCount());
00478   for (std::size_t i = 0 ; i < trajectory_trail_.size() ; ++i)
00479   {
00480     rviz::Robot *r = new rviz::Robot(planning_scene_node_, context_, "Trail Robot " + boost::lexical_cast<std::string>(i), NULL);
00481     r->load(*getRobotModel()->getURDF());
00482     r->setVisualVisible(display_path_visual_enabled_property_->getBool());
00483     r->setCollisionVisible(display_path_collision_enabled_property_->getBool());
00484     r->update(PlanningLinkUpdater(t->getWayPointPtr(i)));
00485     r->setVisible(isEnabled() && (!animating_path_ || i <= current_state_));
00486     trajectory_trail_[i] = r;
00487   }
00488 }
00489 
00490 void MotionPlanningDisplay::changedRobotPathAlpha()
00491 {
00492   display_path_robot_->setAlpha(robot_path_alpha_property_->getFloat());
00493   for (std::size_t i = 0 ; i < trajectory_trail_.size() ; ++i)
00494     trajectory_trail_[i]->setAlpha(robot_path_alpha_property_->getFloat());
00495 }
00496 
00497 void MotionPlanningDisplay::renderWorkspaceBox()
00498 {
00499   if (!frame_ || !show_workspace_property_->getBool())
00500   {
00501     if (workspace_box_)
00502       workspace_box_.reset();
00503     return;
00504   }
00505 
00506   if (!workspace_box_)
00507   {
00508     workspace_box_.reset(new rviz::Shape(rviz::Shape::Cube,
00509                                          context_->getSceneManager(), planning_scene_node_));
00510     workspace_box_->setColor(0.0f, 0.0f, 0.6f, 0.3f);
00511   }
00512 
00513   Ogre::Vector3 center(frame_->ui_->wcenter_x->value(),
00514                        frame_->ui_->wcenter_y->value(),
00515                        frame_->ui_->wcenter_z->value());
00516   Ogre::Vector3 extents(frame_->ui_->wsize_x->value(),
00517                         frame_->ui_->wsize_y->value(),
00518                         frame_->ui_->wsize_z->value());
00519   workspace_box_->setScale(extents);
00520   workspace_box_->setPosition(center);
00521 }
00522 
00523 void MotionPlanningDisplay::changedTrajectoryTopic()
00524 {
00525   trajectory_topic_sub_.shutdown();
00526   if (!trajectory_topic_property_->getStdString().empty())
00527     trajectory_topic_sub_ = update_nh_.subscribe(trajectory_topic_property_->getStdString(), 2, &MotionPlanningDisplay::incomingDisplayTrajectory, this);
00528 }
00529 
00530 void MotionPlanningDisplay::computeMetrics(bool start, const std::string &group, double payload)
00531 {
00532   if (!robot_interaction_)
00533     return;
00534   const std::vector<robot_interaction::RobotInteraction::EndEffector> &eef = robot_interaction_->getActiveEndEffectors();
00535   if (eef.empty())
00536     return;
00537   boost::mutex::scoped_lock slock(update_metrics_lock_);
00538 
00539   robot_state::RobotStateConstPtr state = start ? getQueryStartState() : getQueryGoalState();
00540   for (std::size_t i = 0 ; i < eef.size() ; ++i)
00541     if (eef[i].parent_group == group)
00542       computeMetricsInternal(computed_metrics_[std::make_pair(start, group)], eef[i], *state, payload);
00543 }
00544 
00545 void MotionPlanningDisplay::computeMetricsInternal(std::map<std::string, double> &metrics, const robot_interaction::RobotInteraction::EndEffector &ee,
00546                                                    const robot_state::RobotState &state, double payload)
00547 {
00548   metrics.clear();
00549   dynamics_solver::DynamicsSolverPtr ds;
00550   std::map<std::string, dynamics_solver::DynamicsSolverPtr>::const_iterator it = dynamics_solver_.find(ee.parent_group);
00551   if (it != dynamics_solver_.end())
00552     ds = it->second;
00553 
00554   // Max payload
00555   if (ds)
00556   {
00557     double max_payload;
00558     unsigned int saturated_joint;
00559     std::vector<double> joint_values;
00560     state.getJointStateGroup(ee.parent_group)->getVariableValues(joint_values);
00561     if (ds->getMaxPayload(joint_values, max_payload, saturated_joint))
00562     {
00563       metrics["max_payload"] = max_payload;
00564       metrics["saturated_joint"] = saturated_joint;
00565     }
00566     std::vector<double> joint_torques;
00567     joint_torques.resize(joint_values.size());
00568     if (ds->getPayloadTorques(joint_values, payload, joint_torques))
00569     {
00570       for (std::size_t i = 0 ; i < joint_torques.size() ; ++i)
00571       {
00572         std::stringstream stream;
00573         stream << "torque[" << i << "]";
00574         metrics[stream.str()] = joint_torques[i];
00575       }
00576     }
00577   }
00578 
00579   if (kinematics_metrics_)
00580   {
00581     if (position_only_ik_.find(ee.parent_group) == position_only_ik_.end())
00582       private_handle_.param(ee.parent_group + "/position_only_ik", position_only_ik_[ee.parent_group], false);
00583 
00584     double manipulability_index, manipulability;
00585     bool position_ik = position_only_ik_[ee.parent_group];
00586     if (kinematics_metrics_->getManipulabilityIndex(state, ee.parent_group, manipulability_index, position_ik))
00587       metrics["manipulability_index"] = manipulability_index;
00588     if (kinematics_metrics_->getManipulability(state, ee.parent_group, manipulability))
00589       metrics["manipulability"] = manipulability;
00590   }
00591 }
00592 
00593 namespace
00594 {
00595 inline void copyItemIfExists(const std::map<std::string, double> &source, std::map<std::string, double> &dest, const std::string &key)
00596 {
00597   std::map<std::string, double>::const_iterator it = source.find(key);
00598   if (it != source.end())
00599     dest[key] = it->second;
00600 }
00601 }
00602 
00603 void MotionPlanningDisplay::displayMetrics(bool start)
00604 {
00605   if (!robot_interaction_ || !planning_scene_monitor_)
00606     return;
00607 
00608   static const Ogre::Quaternion orientation( 1.0, 0.0, 0.0, 0.0 );
00609   const std::vector<robot_interaction::RobotInteraction::EndEffector> &eef = robot_interaction_->getActiveEndEffectors();
00610   if (eef.empty())
00611     return;
00612 
00613   robot_state::RobotStateConstPtr state = start ? getQueryStartState() : getQueryGoalState();
00614 
00615   for (std::size_t i = 0 ; i < eef.size() ; ++i)
00616   {
00617     Ogre::Vector3 position(0.0, 0.0, 0.0);
00618     std::map<std::string, double> text_table;
00619     const std::map<std::string, double> &metrics_table = computed_metrics_[std::make_pair(start, eef[i].parent_group)];
00620     if (compute_weight_limit_property_->getBool())
00621     {
00622       copyItemIfExists(metrics_table, text_table, "max_payload");
00623       copyItemIfExists(metrics_table, text_table, "saturated_joint");
00624     }
00625     if (show_manipulability_index_property_->getBool())
00626       copyItemIfExists(metrics_table, text_table, "manipulability_index");
00627     if (show_manipulability_property_->getBool())
00628       copyItemIfExists(metrics_table, text_table, "manipulability");
00629     if (show_joint_torques_property_->getBool())
00630     {
00631       std::size_t nj = getRobotModel()->getJointModelGroup(eef[i].parent_group)->getJointModelNames().size();
00632       for(size_t j = 0 ; j < nj ; ++j)
00633       {
00634         std::stringstream stream;
00635         stream << "torque[" << j << "]";
00636         copyItemIfExists(metrics_table, text_table, stream.str());
00637       }
00638     }
00639 
00640     const robot_state::LinkState *ls = NULL;
00641     const robot_model::JointModelGroup *jmg = getRobotModel()->getJointModelGroup(eef[i].parent_group);
00642     if (jmg)
00643       if (!jmg->getLinkModelNames().empty())
00644         ls = state->getLinkState(jmg->getLinkModelNames().back());
00645     if (ls)
00646     {
00647       const Eigen::Vector3d &t = ls->getGlobalLinkTransform().translation();
00648       position[0] = t.x();
00649       position[1] = t.y();
00650       position[2] = t.z() + 0.2;
00651     }
00652     if (start)
00653       displayTable(text_table, query_start_color_property_->getOgreColor(), position, orientation);
00654     else
00655       displayTable(text_table, query_goal_color_property_->getOgreColor(), position, orientation);
00656     text_display_for_start_ = start;
00657   }
00658 }
00659 
00660 void MotionPlanningDisplay::drawQueryStartState()
00661 {
00662   if (!planning_scene_monitor_)
00663     return;
00664 
00665   if (query_start_state_property_->getBool())
00666   {
00667     if (isEnabled())
00668     {
00669       robot_state::RobotStateConstPtr state = getQueryStartState();
00670       // update link poses
00671       query_robot_start_->update(state);
00672       query_robot_start_->setVisible(true);
00673 
00674       // update link colors
00675       std::vector<std::string> collision_links;
00676       getPlanningSceneRO()->getCollidingLinks(collision_links, *state);
00677       collision_links_start_.clear();
00678       for (std::size_t i = 0 ; i < collision_links.size() ; ++i)
00679         collision_links_start_[collision_links[i]] = 0;
00680       if (!collision_links.empty())
00681       {
00682         setStatusTextColor(query_start_color_property_->getColor());
00683         addStatusText("Start state colliding links:");
00684         addStatusText(collision_links);
00685       }
00686       std::vector<std::string> outside_bounds;
00687       const std::vector<robot_state::JointState*> &jstates = state->getJointStateVector();
00688       for (std::size_t i = 0 ; i < jstates.size() ; ++i)
00689         if (!jstates[i]->satisfiesBounds(jstates[i]->getJointModel()->getMaximumExtent() * 1e-2))
00690         {
00691           outside_bounds.push_back(jstates[i]->getJointModel()->getChildLinkModel()->getName());
00692           collision_links_start_[outside_bounds.back()] = 1;
00693         }
00694       if (!outside_bounds.empty())
00695       {
00696         setStatusTextColor(query_start_color_property_->getColor());
00697         addStatusText("Links descending from joints that are outside bounds in start state:");
00698         addStatusText(outside_bounds);
00699       }
00700 
00701       updateLinkColors();
00702       // update metrics text
00703       displayMetrics(true);
00704     }
00705   }
00706   else
00707     query_robot_start_->setVisible(false);
00708   context_->queueRender();
00709 }
00710 
00711 void MotionPlanningDisplay::resetStatusTextColor()
00712 {
00713   setStatusTextColor(Qt::darkGray);
00714 }
00715 
00716 void MotionPlanningDisplay::setStatusTextColor(const QColor &color)
00717 {
00718   if (frame_)
00719     frame_->ui_->status_text->setTextColor(color);
00720 }
00721 
00722 void MotionPlanningDisplay::addStatusText(const std::string &text)
00723 {
00724   if (frame_)
00725     frame_->ui_->status_text->append(QString::fromStdString(text));
00726 }
00727 
00728 void MotionPlanningDisplay::addStatusText(const std::vector<std::string> &text)
00729 {
00730   for (std::size_t i = 0 ; i < text.size() ; ++i)
00731     addStatusText(text[i]);
00732 }
00733 
00734 void MotionPlanningDisplay::recomputeQueryStartStateMetrics()
00735 {
00736   std::string group = planning_group_property_->getStdString();
00737   if (!group.empty())
00738     computeMetrics(true, group, metrics_set_payload_property_->getFloat());
00739 }
00740 
00741 void MotionPlanningDisplay::recomputeQueryGoalStateMetrics()
00742 {
00743   std::string group = planning_group_property_->getStdString();
00744   if (!group.empty())
00745     computeMetrics(false, group, metrics_set_payload_property_->getFloat());
00746 }
00747 
00748 void MotionPlanningDisplay::changedQueryStartState()
00749 {
00750   if (!planning_scene_monitor_)
00751     return;
00752   setStatusTextColor(query_start_color_property_->getColor());
00753   addStatusText("Changed start state");
00754   drawQueryStartState();
00755   addBackgroundJob(boost::bind(&MotionPlanningDisplay::publishInteractiveMarkers, this, true), "publishInteractiveMarkers");
00756 }
00757 
00758 void MotionPlanningDisplay::changedQueryGoalState()
00759 {
00760   if (!planning_scene_monitor_)
00761     return;
00762   setStatusTextColor(query_goal_color_property_->getColor());
00763   addStatusText("Changed goal state");
00764   drawQueryGoalState();
00765   addBackgroundJob(boost::bind(&MotionPlanningDisplay::publishInteractiveMarkers, this, true), "publishInteractiveMarkers");
00766 }
00767 
00768 void MotionPlanningDisplay::drawQueryGoalState()
00769 {
00770   if (!planning_scene_monitor_)
00771     return;
00772   if (query_goal_state_property_->getBool())
00773   {
00774     if (isEnabled())
00775     {
00776       robot_state::RobotStateConstPtr state = getQueryGoalState();
00777 
00778       // update link poses
00779       query_robot_goal_->update(state);
00780       query_robot_goal_->setVisible(true);
00781 
00782       // update link colors
00783       std::vector<std::string> collision_links;
00784       getPlanningSceneRO()->getCollidingLinks(collision_links, *state);
00785       collision_links_goal_.clear();
00786       for (std::size_t i = 0 ; i < collision_links.size() ; ++i)
00787         collision_links_goal_[collision_links[i]] = 0;
00788       if (!collision_links.empty())
00789       {
00790         setStatusTextColor(query_goal_color_property_->getColor());
00791         addStatusText("Goal state colliding links:");
00792         addStatusText(collision_links);
00793       }
00794 
00795       const std::vector<robot_state::JointState*> &jstates = state->getJointStateVector();
00796       std::vector<std::string> outside_bounds;
00797       for (std::size_t i = 0 ; i < jstates.size() ; ++i)
00798         if (!jstates[i]->satisfiesBounds(std::numeric_limits<float>::epsilon()))
00799         {
00800           outside_bounds.push_back(jstates[i]->getJointModel()->getChildLinkModel()->getName());
00801           collision_links_goal_[outside_bounds.back()] = 1;
00802         }
00803 
00804       if (!outside_bounds.empty())
00805       {
00806         setStatusTextColor(query_goal_color_property_->getColor());
00807         addStatusText("Links descending from joints that are outside bounds in goal state:");
00808         addStatusText(outside_bounds);
00809       }
00810 
00811       updateLinkColors();
00812 
00813       // update metrics text
00814       displayMetrics(false);
00815     }
00816   }
00817   else
00818     query_robot_goal_->setVisible(false);
00819   context_->queueRender();
00820 }
00821 
00822 void MotionPlanningDisplay::resetInteractiveMarkers()
00823 {
00824   query_start_state_->clearError();
00825   query_goal_state_->clearError();
00826   addBackgroundJob(boost::bind(&MotionPlanningDisplay::publishInteractiveMarkers, this, false), "publishInteractiveMarkers");
00827 }
00828 
00829 void MotionPlanningDisplay::publishInteractiveMarkers(bool pose_update)
00830 {
00831   if (robot_interaction_)
00832   {
00833     if (pose_update &&
00834         robot_interaction_->showingMarkers(query_start_state_) == query_start_state_property_->getBool() &&
00835         robot_interaction_->showingMarkers(query_goal_state_) == query_goal_state_property_->getBool())
00836     {
00837       if (query_start_state_property_->getBool())
00838         robot_interaction_->updateInteractiveMarkers(query_start_state_);
00839       if (query_goal_state_property_->getBool())
00840         robot_interaction_->updateInteractiveMarkers(query_goal_state_);
00841     }
00842     else
00843     {
00844       robot_interaction_->clearInteractiveMarkers();
00845       if (query_start_state_property_->getBool())
00846         robot_interaction_->addInteractiveMarkers(query_start_state_, query_marker_scale_property_->getFloat());
00847       if (query_goal_state_property_->getBool())
00848         robot_interaction_->addInteractiveMarkers(query_goal_state_, query_marker_scale_property_->getFloat());
00849       robot_interaction_->publishInteractiveMarkers();
00850     }
00851   }
00852 }
00853 
00854 void MotionPlanningDisplay::changedQueryStartColor()
00855 {
00856   std_msgs::ColorRGBA color;
00857   QColor qcolor = query_start_color_property_->getColor();
00858   color.r = qcolor.redF();
00859   color.g = qcolor.greenF();
00860   color.b = qcolor.blueF();
00861   color.a = 1.0f;
00862   query_robot_start_->setDefaultAttachedObjectColor(color);
00863   changedQueryStartState();
00864 }
00865 
00866 void MotionPlanningDisplay::changedQueryStartAlpha()
00867 {
00868   query_robot_start_->setAlpha(query_start_alpha_property_->getFloat());
00869   changedQueryStartState();
00870 }
00871 
00872 void MotionPlanningDisplay::changedQueryMarkerScale()
00873 {
00874   if (!planning_scene_monitor_)
00875     return;
00876 
00877   if (isEnabled())
00878   {
00879     // Clear the interactive markers and re-add them:
00880     publishInteractiveMarkers(false);
00881   }
00882 }
00883 
00884 void MotionPlanningDisplay::changedQueryGoalColor()
00885 {
00886   std_msgs::ColorRGBA color;
00887   QColor qcolor = query_goal_color_property_->getColor();
00888   color.r = qcolor.redF();
00889   color.g = qcolor.greenF();
00890   color.b = qcolor.blueF();
00891   color.a = 1.0f;
00892   query_robot_goal_->setDefaultAttachedObjectColor(color);
00893   changedQueryGoalState();
00894 }
00895 
00896 void MotionPlanningDisplay::changedQueryGoalAlpha()
00897 {
00898   query_robot_goal_->setAlpha(query_goal_alpha_property_->getFloat());
00899   changedQueryGoalState();
00900 }
00901 
00902 void MotionPlanningDisplay::changedQueryCollidingLinkColor()
00903 {
00904   changedQueryStartState();
00905   changedQueryGoalState();
00906 }
00907 
00908 void MotionPlanningDisplay::changedQueryJointViolationColor()
00909 {
00910   changedQueryStartState();
00911   changedQueryGoalState();
00912 }
00913 
00914 void MotionPlanningDisplay::scheduleDrawQueryStartState(robot_interaction::RobotInteraction::InteractionHandler *, bool error_state_changed)
00915 {
00916   if (!planning_scene_monitor_)
00917     return;
00918   if (error_state_changed)
00919     addBackgroundJob(boost::bind(&MotionPlanningDisplay::publishInteractiveMarkers, this, false), "publishInteractiveMarkers");
00920   recomputeQueryStartStateMetrics();
00921   addMainLoopJob(boost::bind(&MotionPlanningDisplay::drawQueryStartState, this));
00922   context_->queueRender();
00923 }
00924 
00925 void MotionPlanningDisplay::scheduleDrawQueryGoalState(robot_interaction::RobotInteraction::InteractionHandler *, bool error_state_changed)
00926 {
00927   if (!planning_scene_monitor_)
00928     return;
00929   if (error_state_changed)
00930     addBackgroundJob(boost::bind(&MotionPlanningDisplay::publishInteractiveMarkers, this, false), "publishInteractiveMarkers");
00931   recomputeQueryGoalStateMetrics();
00932   addMainLoopJob(boost::bind(&MotionPlanningDisplay::drawQueryGoalState, this));
00933   context_->queueRender();
00934 }
00935 
00936 void MotionPlanningDisplay::updateQueryStartState()
00937 {
00938   recomputeQueryStartStateMetrics();
00939   addMainLoopJob(boost::bind(&MotionPlanningDisplay::changedQueryStartState, this));
00940   context_->queueRender();
00941 }
00942 
00943 void MotionPlanningDisplay::updateQueryGoalState()
00944 {
00945   recomputeQueryGoalStateMetrics();
00946   addMainLoopJob(boost::bind(&MotionPlanningDisplay::changedQueryGoalState, this));
00947   context_->queueRender();
00948 }
00949 
00950 void MotionPlanningDisplay::setQueryStartState(const robot_state::RobotState &start)
00951 {
00952   query_start_state_->setState(start);
00953   updateQueryStartState();
00954 }
00955 
00956 void MotionPlanningDisplay::setQueryGoalState(const robot_state::RobotState &goal)
00957 {
00958   query_goal_state_->setState(goal);
00959   updateQueryGoalState();
00960 }
00961 
00962 void MotionPlanningDisplay::useApproximateIK(bool flag)
00963 {
00964   if (query_start_state_)
00965   {
00966     kinematics::KinematicsQueryOptions o = query_start_state_->getKinematicsQueryOptions();
00967     o.return_approximate_solution = flag;
00968     query_start_state_->setKinematicsQueryOptions(o);
00969   }
00970   if (query_goal_state_)
00971   {
00972     kinematics::KinematicsQueryOptions o = query_goal_state_->getKinematicsQueryOptions();
00973     o.return_approximate_solution = flag;
00974     query_goal_state_->setKinematicsQueryOptions(o);
00975   }  
00976 }
00977 
00978 bool MotionPlanningDisplay::isIKSolutionCollisionFree(robot_state::JointStateGroup *group, const std::vector<double> &ik_solution) const
00979 {
00980   if (frame_->ui_->collision_aware_ik->isChecked() && planning_scene_monitor_)
00981   {
00982     group->setVariableValues(ik_solution);
00983     bool res = !getPlanningSceneRO()->isStateColliding(*group->getRobotState(), group->getName());
00984     return res;
00985   }
00986   else
00987     return true;
00988 }
00989 
00990 void MotionPlanningDisplay::updateLinkColors()
00991 {
00992   unsetAllColors(&query_robot_start_->getRobot());
00993   unsetAllColors(&query_robot_goal_->getRobot());
00994   std::string group = planning_group_property_->getStdString();
00995   if (!group.empty())
00996   {
00997     setGroupColor(&query_robot_start_->getRobot(), group, query_start_color_property_->getColor());
00998     setGroupColor(&query_robot_goal_->getRobot(), group, query_goal_color_property_->getColor());
00999 
01000     for (std::map<std::string, int>::const_iterator it = collision_links_start_.begin() ; it != collision_links_start_.end() ; ++it)
01001       if (it->second == 0)
01002         setLinkColor(&query_robot_start_->getRobot(), it->first, query_colliding_link_color_property_->getColor());
01003       else
01004         setLinkColor(&query_robot_start_->getRobot(), it->first, query_outside_joint_limits_link_color_property_->getColor());
01005 
01006     for (std::map<std::string, int>::const_iterator it = collision_links_goal_.begin() ; it != collision_links_goal_.end() ; ++it)
01007       if (it->second == 0)
01008         setLinkColor(&query_robot_goal_->getRobot(), it->first, query_colliding_link_color_property_->getColor());
01009       else
01010         setLinkColor(&query_robot_goal_->getRobot(), it->first, query_outside_joint_limits_link_color_property_->getColor());
01011   }
01012 }
01013 
01014 void MotionPlanningDisplay::changePlanningGroup(const std::string& group)
01015 {
01016   if (!getRobotModel() || !robot_interaction_)
01017     return;
01018 
01019   if (getRobotModel()->hasJointModelGroup(group))
01020   {
01021     planning_group_property_->setStdString(group);
01022     changedPlanningGroup();
01023   }
01024   else {
01025     ROS_ERROR("Group [%s] not found in the robot model.", group.c_str());
01026   }
01027 }
01028 
01029 void MotionPlanningDisplay::changedPlanningGroup()
01030 {
01031   if (!getRobotModel() || !robot_interaction_)
01032     return;
01033 
01034   if (!planning_group_property_->getStdString().empty())
01035     if (!getRobotModel()->hasJointModelGroup(planning_group_property_->getStdString()))
01036     {
01037       planning_group_property_->setStdString("");
01038       return;
01039     }
01040   modified_groups_.insert(planning_group_property_->getStdString());
01041 
01042   if (robot_interaction_)
01043     robot_interaction_->decideActiveComponents(planning_group_property_->getStdString());
01044   
01045   updateQueryStartState();
01046   updateQueryGoalState();
01047   updateLinkColors();
01048 
01049   if (frame_)
01050     frame_->changePlanningGroup();
01051   addBackgroundJob(boost::bind(&MotionPlanningDisplay::publishInteractiveMarkers, this, false), "publishInteractiveMarkers");
01052 }
01053 
01054 void MotionPlanningDisplay::changedWorkspace()
01055 {
01056   renderWorkspaceBox();
01057 }
01058 
01059 std::string MotionPlanningDisplay::getCurrentPlanningGroup() const
01060 {
01061   return planning_group_property_->getStdString();
01062 }
01063 
01064 void MotionPlanningDisplay::changedStateDisplayTime()
01065 {
01066 }
01067 
01068 void MotionPlanningDisplay::changedDisplayPathVisualEnabled()
01069 {
01070   if (isEnabled())
01071   {
01072     display_path_robot_->setVisualVisible( display_path_visual_enabled_property_->getBool() );
01073     display_path_robot_->setVisible(isEnabled() && displaying_trajectory_message_ && animating_path_);
01074     for (std::size_t i = 0 ; i < trajectory_trail_.size() ; ++i)
01075       trajectory_trail_[i]->setVisualVisible( display_path_visual_enabled_property_->getBool() );
01076   }
01077 }
01078 
01079 // ******************************************************************************************
01080 // Collision Visible
01081 // ******************************************************************************************
01082 
01083 void MotionPlanningDisplay::changedDisplayPathCollisionEnabled()
01084 {
01085   if (isEnabled())
01086   {
01087     display_path_robot_->setCollisionVisible( display_path_collision_enabled_property_->getBool() );
01088     display_path_robot_->setVisible(isEnabled() && displaying_trajectory_message_ && animating_path_);
01089     for (std::size_t i = 0 ; i < trajectory_trail_.size() ; ++i)
01090       trajectory_trail_[i]->setCollisionVisible( display_path_collision_enabled_property_->getBool() );
01091   }
01092 }
01093 
01094 void MotionPlanningDisplay::setQueryStateHelper(bool use_start_state,
01095                                                 const std::string &state_name)
01096 {
01097 
01098   robot_state::RobotState state = use_start_state ? *getQueryStartState() : *getQueryGoalState();
01099 
01100   std::string v = "<" + state_name + ">";
01101 
01102   if (v == "<random>")
01103   {
01104     if (robot_state::JointStateGroup *jsg = state.getJointStateGroup(getCurrentPlanningGroup()))
01105       jsg->setToRandomValues();
01106   }
01107   else
01108     if (v == "<current>")
01109     {
01110       const planning_scene_monitor::LockedPlanningSceneRO &ps = getPlanningSceneRO();
01111       if (ps)
01112         state = ps->getCurrentState();
01113     }
01114     else
01115       if (v == "<same as goal>")
01116       {
01117         state = *getQueryGoalState();
01118       }
01119       else
01120         if (v == "<same as start>")
01121         {
01122           state = *getQueryStartState();
01123         }
01124         else
01125         {
01126           // maybe it is a named state
01127           if (robot_state::JointStateGroup *jsg = state.getJointStateGroup(getCurrentPlanningGroup()))
01128             jsg->setToDefaultState(v);
01129         }
01130 
01131   use_start_state ? setQueryStartState(state) : setQueryGoalState(state);
01132 }
01133 
01134 void MotionPlanningDisplay::populateMenuHandler(boost::shared_ptr<interactive_markers::MenuHandler>& mh)
01135 {
01136   typedef interactive_markers::MenuHandler immh;
01137   std::vector<std::string> state_names;
01138   state_names.push_back("random");
01139   state_names.push_back("current");
01140   state_names.push_back("same as start");
01141   state_names.push_back("same as goal");
01142 
01143   // hacky way to distinguish between the start and goal handlers...
01144   bool is_start = (mh.get() == menu_handler_start_.get());
01145 
01146   // Commands for changing the state
01147   immh::EntryHandle menu_states = mh->insert( is_start ? "Set start state to" : "Set goal state to" ,
01148                                               immh::FeedbackCallback());
01149   for (int i = 0; i < state_names.size(); ++i )
01150   {
01151     // Don't add "same as start" to the start state handler, and vice versa.
01152     if ((state_names[i] == "same as start" && is_start) || (state_names[i] == "same as goal"  && !is_start))
01153       continue;
01154     mh->insert(menu_states, state_names[i],
01155                boost::bind( &MotionPlanningDisplay::setQueryStateHelper, this, is_start, state_names[i] ));
01156   }
01157 
01158 //  // Group commands, which end up being the same for both interaction handlers
01159 //  const std::vector<std::string>& group_names = getRobotModel()->getJointModelGroupNames();
01160 //  immh::EntryHandle menu_groups = mh->insert("Planning Group", immh::FeedbackCallback());
01161 //  for (int i = 0; i < group_names.size(); ++i )
01162 //    mh->insert(menu_groups, group_names[i],
01163 //               boost::bind( &MotionPlanningDisplay::changePlanningGroup, this, group_names[i]));
01164 
01165 }
01166 
01167 void MotionPlanningDisplay::onRobotModelLoaded()
01168 {
01169   PlanningSceneDisplay::onRobotModelLoaded();
01170 
01171   robot_interaction_.reset(new robot_interaction::RobotInteraction(getRobotModel(), "rviz_moveit_motion_planning_display"));
01172   int_marker_display_->subProp("Update Topic")->setValue(QString::fromStdString(robot_interaction_->getServerTopic() + "/update"));
01173   display_path_robot_->load(*getRobotModel()->getURDF());
01174   query_robot_start_->load(*getRobotModel()->getURDF());
01175   query_robot_goal_->load(*getRobotModel()->getURDF());
01176 
01177   robot_state::RobotStatePtr ks(new robot_state::RobotState(getPlanningSceneRO()->getCurrentState()));
01178   query_start_state_.reset(new robot_interaction::RobotInteraction::InteractionHandler("start", *ks, planning_scene_monitor_->getTFClient()));
01179   query_goal_state_.reset(new robot_interaction::RobotInteraction::InteractionHandler("goal", *getQueryStartState(), planning_scene_monitor_->getTFClient()));
01180   query_start_state_->setUpdateCallback(boost::bind(&MotionPlanningDisplay::scheduleDrawQueryStartState, this, _1, _2));
01181   query_goal_state_->setUpdateCallback(boost::bind(&MotionPlanningDisplay::scheduleDrawQueryGoalState, this, _1, _2));
01182   query_start_state_->setStateValidityCallback(boost::bind(&MotionPlanningDisplay::isIKSolutionCollisionFree, this, _1, _2));
01183   query_goal_state_->setStateValidityCallback(boost::bind(&MotionPlanningDisplay::isIKSolutionCollisionFree, this, _1, _2));
01184 
01185   // Interactive marker menus
01186   populateMenuHandler(menu_handler_start_);
01187   populateMenuHandler(menu_handler_goal_);
01188   query_start_state_->setMenuHandler(menu_handler_start_);
01189   query_goal_state_->setMenuHandler(menu_handler_goal_);
01190 
01191   if (!planning_group_property_->getStdString().empty())
01192     if (!getRobotModel()->hasJointModelGroup(planning_group_property_->getStdString()))
01193       planning_group_property_->setStdString("");
01194 
01195   const std::vector<std::string> &groups = getRobotModel()->getJointModelGroupNames();
01196   planning_group_property_->clearOptions();
01197   for (std::size_t i = 0 ; i < groups.size() ; ++i)
01198     planning_group_property_->addOptionStd(groups[i]);
01199   planning_group_property_->sortOptions();
01200   if (!groups.empty() && planning_group_property_->getStdString().empty())
01201     planning_group_property_->setStdString(groups[0]);
01202 
01203   modified_groups_.clear();
01204   kinematics_metrics_.reset(new kinematics_metrics::KinematicsMetrics(getRobotModel()));
01205 
01206   geometry_msgs::Vector3 gravity_vector;
01207   gravity_vector.x = 0.0;
01208   gravity_vector.y = 0.0;
01209   gravity_vector.z = 9.81;
01210 
01211   dynamics_solver_.clear();
01212   for (std::size_t i = 0 ; i < groups.size() ; ++i)
01213     if (getRobotModel()->getJointModelGroup(groups[i])->isChain())
01214       dynamics_solver_[groups[i]].reset(new dynamics_solver::DynamicsSolver(getRobotModel(),
01215                                                                             groups[i],
01216                                                                             gravity_vector));
01217   addMainLoopJob(boost::bind(&MotionPlanningDisplay::changedPlanningGroup, this));
01218 }
01219 
01220 void MotionPlanningDisplay::updateStateExceptModified(robot_state::RobotState &dest, const robot_state::RobotState &src)
01221 {
01222   robot_state::RobotState src_copy = src;
01223   for (std::set<std::string>::const_iterator it = modified_groups_.begin() ; it != modified_groups_.end() ; ++it)
01224   {
01225     const robot_state::JointStateGroup *jsg = dest.getJointStateGroup(*it);
01226     if (jsg)
01227     {
01228       std::map<std::string, double> values_to_keep;
01229       jsg->getVariableValues(values_to_keep);
01230       src_copy.setStateValues(values_to_keep);
01231     }
01232   }
01233 
01234   // overwrite the destination state
01235   dest = src_copy;
01236 }
01237 
01238 void MotionPlanningDisplay::onSceneMonitorReceivedUpdate(planning_scene_monitor::PlanningSceneMonitor::SceneUpdateType update_type)
01239 {
01240   PlanningSceneDisplay::onSceneMonitorReceivedUpdate(update_type);
01241   robot_state::RobotState current_state = getPlanningSceneRO()->getCurrentState();
01242   std::string group = planning_group_property_->getStdString();
01243 
01244   if (query_start_state_property_->getBool() && !group.empty())
01245   {
01246     robot_state::RobotState start = *getQueryStartState();
01247     updateStateExceptModified(start, current_state);
01248     setQueryStartState(start);
01249   }
01250 
01251   if (query_goal_state_property_->getBool() && !group.empty())
01252   {
01253     robot_state::RobotState goal = *getQueryGoalState();
01254     updateStateExceptModified(goal, current_state);
01255     setQueryGoalState(goal);
01256   }
01257 
01258   if (frame_)
01259     frame_->sceneUpdate(update_type);
01260 }
01261 
01262 // ******************************************************************************************
01263 // Enable
01264 // ******************************************************************************************
01265 void MotionPlanningDisplay::onEnable()
01266 {
01267   PlanningSceneDisplay::onEnable();
01268 
01269   display_path_robot_->setVisualVisible( display_path_visual_enabled_property_->getBool() );
01270   display_path_robot_->setCollisionVisible( display_path_collision_enabled_property_->getBool() );
01271   display_path_robot_->setVisible(displaying_trajectory_message_ && animating_path_);
01272   for (std::size_t i = 0 ; i < trajectory_trail_.size() ; ++i)
01273   {
01274     trajectory_trail_[i]->setVisualVisible( display_path_visual_enabled_property_->getBool() );
01275     trajectory_trail_[i]->setCollisionVisible( display_path_collision_enabled_property_->getBool() );
01276     trajectory_trail_[i]->setVisible(true);
01277   }
01278 
01279   text_to_display_->setVisible(false);
01280 
01281   query_robot_start_->setVisible(query_start_state_property_->getBool());
01282   query_robot_goal_->setVisible(query_goal_state_property_->getBool());
01283   frame_->enable();
01284 
01285   int_marker_display_->setEnabled(true);
01286   int_marker_display_->setFixedFrame(fixed_frame_);
01287 
01288   changedTrajectoryTopic(); // load topic at startup if default used
01289 }
01290 
01291 // ******************************************************************************************
01292 // Disable
01293 // ******************************************************************************************
01294 void MotionPlanningDisplay::onDisable()
01295 {
01296   if (robot_interaction_)
01297     robot_interaction_->clear();
01298   int_marker_display_->setEnabled(false);
01299 
01300   display_path_robot_->setVisible(false);
01301   for (std::size_t i = 0 ; i < trajectory_trail_.size() ; ++i)
01302     trajectory_trail_[i]->setVisible(false);
01303   displaying_trajectory_message_.reset();
01304 
01305   query_robot_start_->setVisible(false);
01306   query_robot_goal_->setVisible(false);
01307   frame_->disable();
01308   text_to_display_->setVisible(false);
01309 
01310   PlanningSceneDisplay::onDisable();
01311 }
01312 
01313 float MotionPlanningDisplay::getStateDisplayTime()
01314 {
01315   std::string tm = state_display_time_property_->getStdString();
01316   if (tm == "REALTIME")
01317     return -1.0;
01318   else
01319   {
01320     boost::replace_all(tm, "s", "");
01321     boost::trim(tm);
01322     float t = 0.05f;
01323     try
01324     {
01325       t = boost::lexical_cast<float>(tm);
01326     }
01327     catch(const boost::bad_lexical_cast &ex)
01328     {
01329       state_display_time_property_->setStdString("0.05 s");
01330     }
01331     return t;
01332   }
01333 }
01334 
01335 // ******************************************************************************************
01336 // Update
01337 // ******************************************************************************************
01338 void MotionPlanningDisplay::update(float wall_dt, float ros_dt)
01339 {
01340   if (int_marker_display_)
01341     int_marker_display_->update(wall_dt, ros_dt);
01342   if (frame_)
01343     frame_->updateSceneMarkers(wall_dt, ros_dt);
01344 
01345   PlanningSceneDisplay::update(wall_dt, ros_dt);
01346 }
01347 
01348 void MotionPlanningDisplay::updateInternal(float wall_dt, float ros_dt)
01349 {
01350   PlanningSceneDisplay::updateInternal(wall_dt, ros_dt);
01351 
01352   if (!animating_path_ && !trajectory_message_to_display_ && loop_display_property_->getBool() && displaying_trajectory_message_)
01353   {
01354     animating_path_ = true;
01355     current_state_ = -1;
01356     current_state_time_ = std::numeric_limits<float>::infinity();
01357     display_path_robot_->setVisible(isEnabled());
01358   }
01359 
01360   if (!animating_path_ && trajectory_message_to_display_ && !trajectory_message_to_display_->empty())
01361   {
01362     planning_scene_monitor_->updateFrameTransforms();
01363     displaying_trajectory_message_ = trajectory_message_to_display_;
01364     display_path_robot_->setVisible(isEnabled());
01365     trajectory_message_to_display_.reset();
01366     animating_path_ = true;
01367     current_state_ = -1;
01368     current_state_time_ = std::numeric_limits<float>::infinity();
01369     display_path_robot_->update(displaying_trajectory_message_->getFirstWayPointPtr());
01370   }
01371 
01372   if (animating_path_)
01373   {
01374     float tm = getStateDisplayTime();
01375     if (tm < 0.0) // if we should use realtime
01376       tm = displaying_trajectory_message_->getWayPointDurationFromPrevious(current_state_ + 1);
01377     if (current_state_time_ > tm)
01378     {
01379       ++current_state_;
01380       if ((std::size_t) current_state_ < displaying_trajectory_message_->getWayPointCount())
01381       {
01382         display_path_robot_->update(displaying_trajectory_message_->getWayPointPtr(current_state_));
01383         for (std::size_t i = 0 ; i < trajectory_trail_.size() ; ++i)
01384           trajectory_trail_[i]->setVisible(i <= current_state_);
01385       }
01386       else
01387       {
01388         animating_path_ = false;
01389         display_path_robot_->setVisible(loop_display_property_->getBool());
01390       }
01391       current_state_time_ = 0.0f;
01392     }
01393     current_state_time_ += wall_dt;
01394   }
01395 
01396   renderWorkspaceBox();
01397 }
01398 
01399 void MotionPlanningDisplay::load( const rviz::Config& config )
01400 {
01401   PlanningSceneDisplay::load(config);
01402   if (frame_)
01403   {
01404     QString host;
01405     if (config.mapGetString( "MoveIt_Warehouse_Host", &host))
01406       frame_->ui_->database_host->setText(host);
01407     int port;
01408     if (config.mapGetInt( "MoveIt_Warehouse_Port", &port))
01409       frame_->ui_->database_port->setValue(port);
01410     float d;
01411     if (config.mapGetFloat( "MoveIt_Planning_Time", &d))
01412       frame_->ui_->planning_time->setValue(d);
01413     if (config.mapGetFloat( "MoveIt_Goal_Tolerance", &d))
01414       frame_->ui_->goal_tolerance->setValue(d);
01415     bool b;
01416     if (config.mapGetBool( "MoveIt_Use_Constraint_Aware_IK", &b))
01417       frame_->ui_->collision_aware_ik->setChecked(b);
01418   }
01419 }
01420 
01421 void MotionPlanningDisplay::save( rviz::Config config ) const
01422 {
01423   PlanningSceneDisplay::save(config);
01424   if (frame_)
01425   {
01426     config.mapSetValue( "MoveIt_Warehouse_Host", frame_->ui_->database_host->text());
01427     config.mapSetValue( "MoveIt_Warehouse_Port", frame_->ui_->database_port->value());
01428     config.mapSetValue( "MoveIt_Planning_Time", frame_->ui_->planning_time->value());
01429     config.mapSetValue( "MoveIt_Goal_Tolerance", frame_->ui_->goal_tolerance->value());
01430     config.mapSetValue( "MoveIt_Use_Constraint_Aware_IK", frame_->ui_->collision_aware_ik->isChecked());
01431   }
01432 }
01433 
01434 void MotionPlanningDisplay::incomingDisplayTrajectory(const moveit_msgs::DisplayTrajectory::ConstPtr& msg)
01435 {
01436   if (!planning_scene_monitor_)
01437     return;
01438 
01439   if (!msg->model_id.empty() && msg->model_id != getRobotModel()->getName())
01440     ROS_WARN("Received a trajectory to display for model '%s' but model '%s' was expected",
01441              msg->model_id.c_str(), getRobotModel()->getName().c_str());
01442 
01443   trajectory_message_to_display_.reset();
01444 
01445   robot_trajectory::RobotTrajectoryPtr t(new robot_trajectory::RobotTrajectory(planning_scene_monitor_->getRobotModel(), ""));
01446   for (std::size_t i = 0 ; i < msg->trajectory.size() ; ++i)
01447     if (t->empty())
01448     {
01449       const planning_scene_monitor::LockedPlanningSceneRO &ps = getPlanningSceneRO();
01450       t->setRobotTrajectoryMsg(ps->getCurrentState(), msg->trajectory_start, msg->trajectory[i]);
01451     }
01452     else
01453     {
01454       robot_trajectory::RobotTrajectory tmp(planning_scene_monitor_->getRobotModel(), "");
01455       tmp.setRobotTrajectoryMsg(t->getLastWayPoint(), msg->trajectory[i]);
01456       t->append(tmp, 0.0);
01457     }
01458 
01459   if (!t->empty())
01460     trajectory_message_to_display_.swap(t);
01461 
01462   if (trail_display_property_->getBool())
01463     changedShowTrail();
01464 }
01465 
01466 void MotionPlanningDisplay::fixedFrameChanged()
01467 {
01468   PlanningSceneDisplay::fixedFrameChanged();
01469   if (int_marker_display_)
01470     int_marker_display_->setFixedFrame(fixed_frame_);
01471   changedPlanningGroup();
01472 }
01473 
01474 
01475 } // namespace moveit_rviz_plugin


visualization
Author(s): Ioan Sucan , Dave Coleman
autogenerated on Mon Oct 6 2014 02:34:03