00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
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
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
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
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
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
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
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
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
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
00671 query_robot_start_->update(state);
00672 query_robot_start_->setVisible(true);
00673
00674
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
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
00779 query_robot_goal_->update(state);
00780 query_robot_goal_->setVisible(true);
00781
00782
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
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
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
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
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
01144 bool is_start = (mh.get() == menu_handler_start_.get());
01145
01146
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
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
01159
01160
01161
01162
01163
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
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
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
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();
01289 }
01290
01291
01292
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
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)
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 }