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/warehouse/planning_scene_storage.h>
00033
00034 #include <moveit/motion_planning_rviz_plugin/motion_planning_frame.h>
00035 #include <moveit/motion_planning_rviz_plugin/motion_planning_display.h>
00036 #include <moveit/robot_state/conversions.h>
00037 #include <moveit/robot_interaction/interactive_marker_helpers.h>
00038
00039 #include <interactive_markers/tools.h>
00040
00041 #include <rviz/display_context.h>
00042 #include <rviz/frame_manager.h>
00043 #include <rviz/window_manager_interface.h>
00044
00045 #include <eigen_conversions/eigen_msg.h>
00046 #include <geometric_shapes/shape_operations.h>
00047
00048 #include <QMessageBox>
00049 #include <QInputDialog>
00050 #include <QFileDialog>
00051
00052 #include "ui_motion_planning_rviz_plugin_frame.h"
00053
00054 namespace moveit_rviz_plugin
00055 {
00056
00057 void MotionPlanningFrame::importFileButtonClicked()
00058 {
00059 QString path = QFileDialog::getOpenFileName(this, tr("Import Object"));
00060 if (!path.isEmpty())
00061 importResource("file://" + path.toStdString());
00062 }
00063
00064 void MotionPlanningFrame::importUrlButtonClicked()
00065 {
00066 bool ok = false;
00067 QString url = QInputDialog::getText(this, tr("Import Object"),
00068 tr("URL for file to import:"), QLineEdit::Normal,
00069 QString("http://"), &ok);
00070 if (ok && !url.isEmpty())
00071 importResource(url.toStdString());
00072 }
00073
00074 void MotionPlanningFrame::clearSceneButtonClicked()
00075 {
00076 planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00077 if (ps)
00078 {
00079 ps->getWorldNonConst()->clearObjects();
00080 ps->getCurrentStateNonConst().clearAttachedBodies();
00081 moveit_msgs::PlanningScene msg;
00082 ps->getPlanningSceneMsg(msg);
00083 planning_scene_publisher_.publish(msg);
00084 planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::populateCollisionObjectsList, this));
00085 planning_display_->queueRenderSceneGeometry();
00086 }
00087 }
00088
00089 void MotionPlanningFrame::sceneScaleChanged(int value)
00090 {
00091 if (scaled_object_)
00092 {
00093 planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00094 if (ps)
00095 {
00096 if (ps->getWorld()->hasObject(scaled_object_->id_))
00097 {
00098 ps->getWorldNonConst()->removeObject(scaled_object_->id_);
00099 for (std::size_t i = 0 ; i < scaled_object_->shapes_.size() ; ++i)
00100 {
00101 shapes::Shape *s = scaled_object_->shapes_[i]->clone();
00102 s->scale((double)value / 100.0);
00103 ps->getWorldNonConst()->addToObject(scaled_object_->id_, shapes::ShapeConstPtr(s), scaled_object_->shape_poses_[i]);
00104 }
00105 planning_display_->queueRenderSceneGeometry();
00106 }
00107 else
00108 scaled_object_.reset();
00109 }
00110 else
00111 scaled_object_.reset();
00112 }
00113 }
00114
00115 void MotionPlanningFrame::sceneScaleStartChange()
00116 {
00117 QList<QListWidgetItem *> sel = ui_->collision_objects_list->selectedItems();
00118 if (sel.empty())
00119 return;
00120 if (planning_display_->getPlanningSceneMonitor() && sel[0]->checkState() == Qt::Unchecked)
00121 {
00122 planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00123 if (ps)
00124 {
00125 scaled_object_ = ps->getWorld()->getObject(sel[0]->text().toStdString());
00126 }
00127 }
00128 }
00129
00130 void MotionPlanningFrame::sceneScaleEndChange()
00131 {
00132 scaled_object_.reset();
00133 ui_->scene_scale->setSliderPosition(100);
00134 }
00135
00136 void MotionPlanningFrame::removeObjectButtonClicked()
00137 {
00138 QList<QListWidgetItem *> sel = ui_->collision_objects_list->selectedItems();
00139 if (sel.empty())
00140 return;
00141 planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00142 if (ps)
00143 {
00144 for (int i = 0 ; i < sel.count() ; ++i)
00145 if (sel[i]->checkState() == Qt::Unchecked)
00146 ps->getWorldNonConst()->removeObject(sel[i]->text().toStdString());
00147 else
00148 ps->getCurrentStateNonConst().clearAttachedBody(sel[i]->text().toStdString());
00149 scene_marker_.reset();
00150 planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::populateCollisionObjectsList, this));
00151 planning_display_->queueRenderSceneGeometry();
00152 }
00153 }
00154
00155 static QString decideStatusText(const collision_detection::CollisionWorld::ObjectConstPtr &obj)
00156 {
00157 QString status_text = "'" + QString::fromStdString(obj->id_) + "' is a collision object with ";
00158 if (obj->shapes_.empty())
00159 status_text += "no geometry";
00160 else
00161 {
00162 std::vector<QString> shape_names;
00163 for (std::size_t i = 0 ; i < obj->shapes_.size() ; ++i)
00164 shape_names.push_back(QString::fromStdString(shapes::shapeStringName(obj->shapes_[i].get())));
00165 if (shape_names.size() == 1)
00166 status_text += "one " + shape_names[0];
00167 else
00168 {
00169 status_text += QString::fromStdString(boost::lexical_cast<std::string>(shape_names.size())) + " shapes:";
00170 for (std::size_t i = 0 ; i < shape_names.size() ; ++i)
00171 status_text += " " + shape_names[i];
00172 }
00173 }
00174 return status_text;
00175 }
00176
00177 static QString decideStatusText(const robot_state::AttachedBody *attached_body)
00178 {
00179 QString status_text = "'" + QString::fromStdString(attached_body->getName()) + "' is attached to '" +
00180 QString::fromStdString(attached_body->getAttachedLinkName()) + "'";
00181 return status_text;
00182 }
00183
00184 void MotionPlanningFrame::selectedCollisionObjectChanged()
00185 {
00186 QList<QListWidgetItem *> sel = ui_->collision_objects_list->selectedItems();
00187 if (sel.empty())
00188 {
00189 bool oldState = ui_->object_x->blockSignals(true);
00190 ui_->object_x->setValue(0.0);
00191 ui_->object_x->blockSignals(oldState);
00192
00193 oldState = ui_->object_y->blockSignals(true);
00194 ui_->object_y->setValue(0.0);
00195 ui_->object_y->blockSignals(oldState);
00196
00197 oldState = ui_->object_z->blockSignals(true);
00198 ui_->object_z->setValue(0.0);
00199 ui_->object_z->blockSignals(oldState);
00200
00201 oldState = ui_->object_rx->blockSignals(true);
00202 ui_->object_rx->setValue(0.0);
00203 ui_->object_rx->blockSignals(oldState);
00204
00205 oldState = ui_->object_ry->blockSignals(true);
00206 ui_->object_ry->setValue(0.0);
00207 ui_->object_ry->blockSignals(oldState);
00208
00209 oldState = ui_->object_rz->blockSignals(true);
00210 ui_->object_rz->setValue(0.0);
00211 ui_->object_rz->blockSignals(oldState);
00212
00213 ui_->object_status->setText("");
00214 scene_marker_.reset();
00215 ui_->scene_scale->setEnabled(false);
00216 }
00217 else
00218 if (planning_display_->getPlanningSceneMonitor())
00219 {
00220
00221 if (sel[0]->checkState() == Qt::Unchecked)
00222 {
00223 ui_->scene_scale->setEnabled(true);
00224 bool update_scene_marker = false;
00225 Eigen::Affine3d obj_pose;
00226 {
00227 const planning_scene_monitor::LockedPlanningSceneRO &ps = planning_display_->getPlanningSceneRO();
00228 const collision_detection::CollisionWorld::ObjectConstPtr &obj = ps->getWorld()->getObject(sel[0]->text().toStdString());
00229 if (obj)
00230 {
00231 ui_->object_status->setText(decideStatusText(obj));
00232
00233 if (obj->shapes_.size() == 1)
00234 {
00235 obj_pose = obj->shape_poses_[0];
00236 Eigen::Vector3d xyz = obj_pose.rotation().eulerAngles(0, 1, 2);
00237 update_scene_marker = true;
00238
00239 bool oldState = ui_->object_x->blockSignals(true);
00240 ui_->object_x->setValue(obj_pose.translation()[0]);
00241 ui_->object_x->blockSignals(oldState);
00242
00243 oldState = ui_->object_y->blockSignals(true);
00244 ui_->object_y->setValue(obj_pose.translation()[1]);
00245 ui_->object_y->blockSignals(oldState);
00246
00247 oldState = ui_->object_z->blockSignals(true);
00248 ui_->object_z->setValue(obj_pose.translation()[2]);
00249 ui_->object_z->blockSignals(oldState);
00250
00251 oldState = ui_->object_rx->blockSignals(true);
00252 ui_->object_rx->setValue(xyz[0]);
00253 ui_->object_rx->blockSignals(oldState);
00254
00255 oldState = ui_->object_ry->blockSignals(true);
00256 ui_->object_ry->setValue(xyz[1]);
00257 ui_->object_ry->blockSignals(oldState);
00258
00259 oldState = ui_->object_rz->blockSignals(true);
00260 ui_->object_rz->setValue(xyz[2]);
00261 ui_->object_rz->blockSignals(oldState);
00262 }
00263 }
00264 else
00265 ui_->object_status->setText("ERROR: '" + sel[0]->text() + "' should be a collision object but it is not");
00266 }
00267 if (update_scene_marker)
00268 {
00269 if (!scene_marker_)
00270 createSceneInteractiveMarker();
00271 if (scene_marker_)
00272 {
00273 Eigen::Quaterniond eq(obj_pose.rotation());
00274
00275 scene_marker_->setPose(Ogre::Vector3(obj_pose.translation()[0], obj_pose.translation()[1], obj_pose.translation()[2]),
00276 Ogre::Quaternion(eq.w(), eq.x(), eq.y(), eq.z()), "");
00277 }
00278 }
00279 }
00280 else
00281 {
00282 ui_->scene_scale->setEnabled(false);
00283
00284 scene_marker_.reset();
00285 const planning_scene_monitor::LockedPlanningSceneRO &ps = planning_display_->getPlanningSceneRO();
00286 const robot_state::AttachedBody *attached_body = ps->getCurrentState().getAttachedBody(sel[0]->text().toStdString());
00287 if (attached_body)
00288 ui_->object_status->setText(decideStatusText(attached_body));
00289 else
00290 ui_->object_status->setText("ERROR: '" + sel[0]->text() + "' should be an attached object but it is not");
00291 }
00292 }
00293 }
00294
00295 void MotionPlanningFrame::objectPoseValueChanged(double )
00296 {
00297 updateCollisionObjectPose(true);
00298 }
00299
00300 void MotionPlanningFrame::updateCollisionObjectPose(bool update_marker_position)
00301 {
00302 QList<QListWidgetItem *> sel = ui_->collision_objects_list->selectedItems();
00303 if (sel.empty())
00304 return;
00305 planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00306 if (ps)
00307 {
00308 collision_detection::CollisionWorld::ObjectConstPtr obj = ps->getWorld()->getObject(sel[0]->text().toStdString());
00309 if (obj && obj->shapes_.size() == 1)
00310 {
00311 Eigen::Affine3d p;
00312 p.translation()[0] = ui_->object_x->value();
00313 p.translation()[1] = ui_->object_y->value();
00314 p.translation()[2] = ui_->object_z->value();
00315
00316 p = Eigen::Translation3d(p.translation()) *
00317 (Eigen::AngleAxisd(ui_->object_rx->value(), Eigen::Vector3d::UnitX()) *
00318 Eigen::AngleAxisd(ui_->object_ry->value(), Eigen::Vector3d::UnitY()) *
00319 Eigen::AngleAxisd(ui_->object_rz->value(), Eigen::Vector3d::UnitZ()));
00320
00321 ps->getWorldNonConst()->moveShapeInObject(obj->id_, obj->shapes_[0], p);
00322 planning_display_->queueRenderSceneGeometry();
00323
00324
00325 if (update_marker_position && scene_marker_)
00326 {
00327 Eigen::Quaterniond eq(p.rotation());
00328 scene_marker_->setPose(Ogre::Vector3(ui_->object_x->value(), ui_->object_y->value(), ui_->object_z->value()),
00329 Ogre::Quaternion(eq.w(), eq.x(), eq.y(), eq.z()), "");
00330 }
00331 }
00332 }
00333 }
00334
00335 void MotionPlanningFrame::collisionObjectChanged(QListWidgetItem *item)
00336 {
00337 if (item->type() < (int)known_collision_objects_.size() &&
00338 planning_display_->getPlanningSceneMonitor())
00339 {
00340
00341 if (known_collision_objects_[item->type()].first != item->text().toStdString())
00342 renameCollisionObject(item);
00343 else
00344 {
00345 bool checked = item->checkState() == Qt::Checked;
00346 if (known_collision_objects_[item->type()].second != checked)
00347 attachDetachCollisionObject(item);
00348 }
00349 }
00350 }
00351
00352
00353 void MotionPlanningFrame::imProcessFeedback(visualization_msgs::InteractiveMarkerFeedback &feedback)
00354 {
00355 bool oldState = ui_->object_x->blockSignals(true);
00356 ui_->object_x->setValue(feedback.pose.position.x);
00357 ui_->object_x->blockSignals(oldState);
00358
00359 oldState = ui_->object_y->blockSignals(true);
00360 ui_->object_y->setValue(feedback.pose.position.y);
00361 ui_->object_y->blockSignals(oldState);
00362
00363 oldState = ui_->object_z->blockSignals(true);
00364 ui_->object_z->setValue(feedback.pose.position.z);
00365 ui_->object_z->blockSignals(oldState);
00366
00367 Eigen::Quaterniond q;
00368 tf::quaternionMsgToEigen(feedback.pose.orientation, q);
00369 Eigen::Vector3d xyz = q.matrix().eulerAngles(0, 1, 2);
00370
00371 oldState = ui_->object_rx->blockSignals(true);
00372 ui_->object_rx->setValue(xyz[0]);
00373 ui_->object_rx->blockSignals(oldState);
00374
00375 oldState = ui_->object_ry->blockSignals(true);
00376 ui_->object_ry->setValue(xyz[1]);
00377 ui_->object_ry->blockSignals(oldState);
00378
00379 oldState = ui_->object_rz->blockSignals(true);
00380 ui_->object_rz->setValue(xyz[2]);
00381 ui_->object_rz->blockSignals(oldState);
00382
00383 updateCollisionObjectPose(false);
00384 }
00385
00386 void MotionPlanningFrame::copySelectedCollisionObject()
00387 {
00388 QList<QListWidgetItem *> sel = ui_->collision_objects_list->selectedItems();
00389 if (sel.empty())
00390 return;
00391
00392 planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00393 if (!ps)
00394 return;
00395
00396 for (int i = 0 ; i < sel.size() ; ++i)
00397 {
00398 std::string name = sel[i]->text().toStdString();
00399 collision_detection::CollisionWorld::ObjectConstPtr obj = ps->getWorld()->getObject(name);
00400 if (!obj)
00401 continue;
00402
00403
00404 name = "Copy of " + name;
00405 if (ps->getWorld()->hasObject(name))
00406 {
00407 name += " ";
00408 unsigned int n = 1;
00409 while (ps->getWorld()->hasObject(name + boost::lexical_cast<std::string>(n)))
00410 n++;
00411 name += boost::lexical_cast<std::string>(n);
00412 }
00413 ps->getWorldNonConst()->addToObject(name, obj->shapes_, obj->shape_poses_);
00414 ROS_DEBUG("Copied collision object to '%s'", name.c_str());
00415 }
00416 planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::populateCollisionObjectsList, this));
00417 }
00418
00419 void MotionPlanningFrame::computeSaveSceneButtonClicked()
00420 {
00421 if (planning_scene_storage_)
00422 {
00423 moveit_msgs::PlanningScene msg;
00424 planning_display_->getPlanningSceneRO()->getPlanningSceneMsg(msg);
00425 try
00426 {
00427 planning_scene_storage_->removePlanningScene(msg.name);
00428 planning_scene_storage_->addPlanningScene(msg);
00429 }
00430 catch (std::runtime_error &ex)
00431 {
00432 ROS_ERROR("%s", ex.what());
00433 }
00434
00435 planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::populatePlanningSceneTreeView, this));
00436 }
00437 }
00438
00439 void MotionPlanningFrame::computeSaveQueryButtonClicked(const std::string &scene, const std::string &query_name)
00440 {
00441 moveit_msgs::MotionPlanRequest mreq;
00442 constructPlanningRequest(mreq);
00443 if (planning_scene_storage_)
00444 {
00445 try
00446 {
00447 if (!query_name.empty())
00448 planning_scene_storage_->removePlanningQuery(scene, query_name);
00449 planning_scene_storage_->addPlanningQuery(mreq, scene, query_name);
00450 }
00451 catch (std::runtime_error &ex)
00452 {
00453 ROS_ERROR("%s", ex.what());
00454 }
00455
00456 planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::populatePlanningSceneTreeView, this));
00457 }
00458 }
00459
00460 void MotionPlanningFrame::computeDeleteSceneButtonClicked()
00461 {
00462 if (planning_scene_storage_)
00463 {
00464 QList<QTreeWidgetItem *> sel = ui_->planning_scene_tree->selectedItems();
00465 if (!sel.empty())
00466 {
00467 QTreeWidgetItem *s = sel.front();
00468 if (s->type() == ITEM_TYPE_SCENE)
00469 {
00470 std::string scene = s->text(0).toStdString();
00471 try
00472 {
00473 planning_scene_storage_->removePlanningScene(scene);
00474 }
00475 catch (std::runtime_error &ex)
00476 {
00477 ROS_ERROR("%s", ex.what());
00478 }
00479 }
00480 else
00481 {
00482
00483 std::string scene = s->parent()->text(0).toStdString();
00484 try
00485 {
00486 planning_scene_storage_->removePlanningScene(scene);
00487 }
00488 catch (std::runtime_error &ex)
00489 {
00490 ROS_ERROR("%s", ex.what());
00491 }
00492 }
00493 planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::populatePlanningSceneTreeView, this));
00494 }
00495 }
00496 }
00497
00498 void MotionPlanningFrame::computeDeleteQueryButtonClicked()
00499 {
00500 if (planning_scene_storage_)
00501 {
00502 QList<QTreeWidgetItem *> sel = ui_->planning_scene_tree->selectedItems();
00503 if (!sel.empty())
00504 {
00505 QTreeWidgetItem *s = sel.front();
00506 if (s->type() == ITEM_TYPE_QUERY)
00507 {
00508 std::string scene = s->parent()->text(0).toStdString();
00509 std::string query_name = s->text(0).toStdString();
00510 try
00511 {
00512 planning_scene_storage_->removePlanningQuery(scene, query_name);
00513 }
00514 catch (std::runtime_error &ex)
00515 {
00516 ROS_ERROR("%s", ex.what());
00517 }
00518 planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::computeDeleteQueryButtonClickedHelper, this, s));
00519 }
00520 }
00521 }
00522 }
00523
00524 void MotionPlanningFrame::computeDeleteQueryButtonClickedHelper(QTreeWidgetItem *s)
00525 {
00526 ui_->planning_scene_tree->setUpdatesEnabled(false);
00527 s->parent()->removeChild(s);
00528 ui_->planning_scene_tree->setUpdatesEnabled(true);
00529 }
00530
00531 void MotionPlanningFrame::checkPlanningSceneTreeEnabledButtons()
00532 {
00533 QList<QTreeWidgetItem *> sel = ui_->planning_scene_tree->selectedItems();
00534 if (sel.empty())
00535 {
00536 ui_->load_scene_button->setEnabled(false);
00537 ui_->load_query_button->setEnabled(false);
00538 ui_->save_query_button->setEnabled(false);
00539 ui_->delete_scene_button->setEnabled(false);
00540 }
00541 else
00542 {
00543 ui_->save_query_button->setEnabled(true);
00544
00545 QTreeWidgetItem *s = sel.front();
00546
00547
00548 if (s->type() == ITEM_TYPE_SCENE)
00549 {
00550 ui_->load_scene_button->setEnabled(true);
00551 ui_->load_query_button->setEnabled(false);
00552 ui_->delete_scene_button->setEnabled(true);
00553 ui_->delete_query_button->setEnabled(false);
00554 ui_->save_query_button->setEnabled(true);
00555 }
00556 else
00557 {
00558
00559 ui_->load_scene_button->setEnabled(false);
00560 ui_->load_query_button->setEnabled(true);
00561 ui_->delete_scene_button->setEnabled(false);
00562 ui_->delete_query_button->setEnabled(true);
00563 }
00564 }
00565 }
00566
00567 void MotionPlanningFrame::computeLoadSceneButtonClicked()
00568 {
00569 if (planning_scene_storage_)
00570 {
00571 QList<QTreeWidgetItem *> sel = ui_->planning_scene_tree->selectedItems();
00572 if (!sel.empty())
00573 {
00574 QTreeWidgetItem *s = sel.front();
00575 if (s->type() == ITEM_TYPE_SCENE)
00576 {
00577 std::string scene = s->text(0).toStdString();
00578 ROS_DEBUG("Attempting to load scene '%s'", scene.c_str());
00579 moveit_warehouse::PlanningSceneWithMetadata scene_m;
00580 bool got_ps = false;
00581 try
00582 {
00583 got_ps = planning_scene_storage_->getPlanningScene(scene_m, scene);
00584 }
00585 catch (std::runtime_error &ex)
00586 {
00587 ROS_ERROR("%s", ex.what());
00588 }
00589
00590 if (got_ps)
00591 {
00592 ROS_INFO("Loaded scene '%s'", scene.c_str());
00593 if (planning_display_->getPlanningSceneMonitor())
00594 {
00595 if (scene_m->robot_model_name != planning_display_->getRobotModel()->getName())
00596 {
00597 ROS_INFO("Scene '%s' was saved for robot '%s' but we are using robot '%s'. Using scene geometry only",
00598 scene.c_str(), scene_m->robot_model_name.c_str(),
00599 planning_display_->getRobotModel()->getName().c_str());
00600 planning_scene_world_publisher_.publish(scene_m->world);
00601
00602 moveit_msgs::PlanningScene diff;
00603 diff.is_diff = true;
00604 diff.name = scene_m->name;
00605 planning_scene_publisher_.publish(diff);
00606 }
00607 else
00608 planning_scene_publisher_.publish(static_cast<const moveit_msgs::PlanningScene&>(*scene_m));
00609 }
00610 else
00611 planning_scene_publisher_.publish(static_cast<const moveit_msgs::PlanningScene&>(*scene_m));
00612 }
00613 else
00614 ROS_WARN("Failed to load scene '%s'. Has the message format changed since the scene was saved?", scene.c_str());
00615 }
00616 }
00617 }
00618 }
00619
00620 void MotionPlanningFrame::computeLoadQueryButtonClicked()
00621 {
00622 if (planning_scene_storage_)
00623 {
00624 QList<QTreeWidgetItem *> sel = ui_->planning_scene_tree->selectedItems();
00625 if (!sel.empty())
00626 {
00627 QTreeWidgetItem *s = sel.front();
00628 if (s->type() == ITEM_TYPE_QUERY)
00629 {
00630 std::string scene = s->parent()->text(0).toStdString();
00631 std::string query_name = s->text(0).toStdString();
00632 moveit_warehouse::MotionPlanRequestWithMetadata mp;
00633 bool got_q = false;
00634 try
00635 {
00636 got_q = planning_scene_storage_->getPlanningQuery(mp, scene, query_name);
00637 }
00638 catch (std::runtime_error &ex)
00639 {
00640 ROS_ERROR("%s", ex.what());
00641 }
00642
00643 if (got_q)
00644 {
00645 robot_state::RobotStatePtr start_state(new robot_state::RobotState(*planning_display_->getQueryStartState()));
00646 robot_state::robotStateMsgToRobotState(planning_display_->getPlanningSceneRO()->getTransforms(), mp->start_state, *start_state);
00647 planning_display_->setQueryStartState(*start_state);
00648
00649 robot_state::RobotStatePtr goal_state(new robot_state::RobotState(*planning_display_->getQueryGoalState()));
00650 for (std::size_t i = 0 ; i < mp->goal_constraints.size() ; ++i)
00651 if (mp->goal_constraints[i].joint_constraints.size() > 0)
00652 {
00653 std::map<std::string, double> vals;
00654 for (std::size_t j = 0 ; j < mp->goal_constraints[i].joint_constraints.size() ; ++j)
00655 vals[mp->goal_constraints[i].joint_constraints[j].joint_name] = mp->goal_constraints[i].joint_constraints[j].position;
00656 goal_state->setStateValues(vals);
00657 break;
00658 }
00659 planning_display_->setQueryGoalState(*goal_state);
00660 }
00661 else
00662 ROS_ERROR("Failed to load planning query '%s'. Has the message format changed since the query was saved?", query_name.c_str());
00663 }
00664 }
00665 }
00666 }
00667
00668 void MotionPlanningFrame::addObject(const collision_detection::WorldPtr &world, const std::string &id,
00669 const shapes::ShapeConstPtr &shape, const Eigen::Affine3d &pose)
00670 {
00671 world->addToObject(id, shape, pose);
00672
00673 planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::populateCollisionObjectsList, this));
00674
00675
00676 planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::setItemSelectionInList, this, id, true, ui_->collision_objects_list));
00677
00678 planning_display_->queueRenderSceneGeometry();
00679 }
00680
00681 void MotionPlanningFrame::createSceneInteractiveMarker()
00682 {
00683 QList<QListWidgetItem *> sel = ui_->collision_objects_list->selectedItems();
00684 if (sel.empty() || planning_display_->getRobotInteraction()->getActiveEndEffectors().empty())
00685 return;
00686
00687 const planning_scene_monitor::LockedPlanningSceneRO &ps = planning_display_->getPlanningSceneRO();
00688 if (!ps)
00689 return;
00690
00691 const collision_detection::CollisionWorld::ObjectConstPtr &obj = ps->getWorld()->getObject(sel[0]->text().toStdString());
00692 if (!scene_marker_ && obj && obj->shapes_.size() == 1)
00693 {
00694 Eigen::Quaterniond eq(obj->shape_poses_[0].rotation());
00695 geometry_msgs::PoseStamped shape_pose;
00696 shape_pose.pose.position.x = obj->shape_poses_[0].translation()[0];
00697 shape_pose.pose.position.y = obj->shape_poses_[0].translation()[1];
00698 shape_pose.pose.position.z = obj->shape_poses_[0].translation()[2];
00699 shape_pose.pose.orientation.x = eq.x();
00700 shape_pose.pose.orientation.y = eq.y();
00701 shape_pose.pose.orientation.z = eq.z();
00702 shape_pose.pose.orientation.w = eq.w();
00703
00704
00705 visualization_msgs::InteractiveMarker int_marker = robot_interaction::make6DOFMarker(std::string("marker_") + sel[0]->text().toStdString(), shape_pose, 1.0);
00706 int_marker.header.frame_id = context_->getFrameManager()->getFixedFrame();
00707 int_marker.description = sel[0]->text().toStdString();
00708
00709 rviz::InteractiveMarker* imarker = new rviz::InteractiveMarker(planning_display_->getSceneNode(), context_ );
00710 interactive_markers::autoComplete(int_marker);
00711 imarker->processMessage(int_marker);
00712 imarker->setShowAxes(false);
00713 scene_marker_.reset(imarker);
00714
00715
00716 connect( imarker, SIGNAL( userFeedback(visualization_msgs::InteractiveMarkerFeedback &)), this,
00717 SLOT( imProcessFeedback(visualization_msgs::InteractiveMarkerFeedback &) ));
00718 }
00719 }
00720
00721 void MotionPlanningFrame::renameCollisionObject(QListWidgetItem *item)
00722 {
00723 long unsigned int version = known_collision_objects_version_;
00724 if (item->text().isEmpty())
00725 {
00726 QMessageBox::warning(this, "Invalid object name", "Cannot set an empty object name.");
00727 if (version == known_collision_objects_version_)
00728 item->setText(QString::fromStdString(known_collision_objects_[item->type()].first));
00729 return;
00730 }
00731
00732 std::string item_text = item->text().toStdString();
00733 bool already_exists = planning_display_->getPlanningSceneRO()->getWorld()->hasObject(item_text);
00734 if (!already_exists)
00735 already_exists = planning_display_->getPlanningSceneRO()->getCurrentState().hasAttachedBody(item_text);
00736 if (already_exists)
00737 {
00738 QMessageBox::warning(this, "Duplicate object name", QString("The name '").append(item->text()).
00739 append("' already exists. Not renaming object ").append((known_collision_objects_[item->type()].first.c_str())));
00740 if (version == known_collision_objects_version_)
00741 item->setText(QString::fromStdString(known_collision_objects_[item->type()].first));
00742 return;
00743 }
00744
00745 if (item->checkState() == Qt::Unchecked)
00746 {
00747 planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00748 collision_detection::CollisionWorld::ObjectConstPtr obj = ps->getWorld()->getObject(known_collision_objects_[item->type()].first);
00749 if (obj)
00750 {
00751 known_collision_objects_[item->type()].first = item_text;
00752 ps->getWorldNonConst()->removeObject(obj->id_);
00753 ps->getWorldNonConst()->addToObject(known_collision_objects_[item->type()].first, obj->shapes_, obj->shape_poses_);
00754 if (scene_marker_)
00755 {
00756 scene_marker_.reset();
00757 planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::createSceneInteractiveMarker, this));
00758 }
00759 }
00760 }
00761 else
00762 {
00763
00764 planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00765 robot_state::RobotState &cs = ps->getCurrentStateNonConst();
00766 const robot_state::AttachedBody *ab = cs.getAttachedBody(known_collision_objects_[item->type()].first);
00767 if (ab)
00768 {
00769 known_collision_objects_[item->type()].first = item_text;
00770 robot_state::AttachedBody *new_ab = new robot_state::AttachedBody(ab->getAttachedLink(),
00771 known_collision_objects_[item->type()].first,
00772 ab->getShapes(), ab->getFixedTransforms(),
00773 ab->getTouchLinks(),
00774 ab->getDetachPosture());
00775 cs.clearAttachedBody(ab->getName());
00776 cs.attachBody(new_ab);
00777 }
00778 }
00779 }
00780
00781 void MotionPlanningFrame::attachDetachCollisionObject(QListWidgetItem *item)
00782 {
00783 long unsigned int version = known_collision_objects_version_;
00784 bool checked = item->checkState() == Qt::Checked;
00785 std::pair<std::string, bool> data = known_collision_objects_[item->type()];
00786 moveit_msgs::AttachedCollisionObject aco;
00787
00788 if (checked)
00789 {
00790 QStringList links;
00791 const std::vector<std::string> &links_std = planning_display_->getRobotModel()->getLinkModelNames();
00792 for (std::size_t i = 0 ; i < links_std.size() ; ++i)
00793 links.append(QString::fromStdString(links_std[i]));
00794 bool ok = false;
00795 QString response = QInputDialog::getItem(this, tr("Select Link Name"), tr("Choose the link to attach to:"),
00796 links, 0, false, &ok);
00797 if (!ok)
00798 {
00799 if (version == known_collision_objects_version_)
00800 item->setCheckState(Qt::Unchecked);
00801 return;
00802 }
00803 aco.link_name = response.toStdString();
00804 aco.object.id = data.first;
00805 aco.object.operation = moveit_msgs::CollisionObject::ADD;
00806 }
00807 else
00808 {
00809 const planning_scene_monitor::LockedPlanningSceneRO &ps = planning_display_->getPlanningSceneRO();
00810 const robot_state::AttachedBody *attached_body = ps->getCurrentState().getAttachedBody(data.first);
00811 if (attached_body)
00812 {
00813 aco.link_name = attached_body->getAttachedLinkName();
00814 aco.object.id = attached_body->getName();
00815 aco.object.operation = moveit_msgs::CollisionObject::REMOVE;
00816 }
00817 }
00818 {
00819 planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00820
00821 for (std::size_t i = 0 ; i < known_collision_objects_.size() ; ++i)
00822 if (known_collision_objects_[i].first == data.first)
00823 {
00824 known_collision_objects_[i].second = checked;
00825 break;
00826 }
00827 ps->processAttachedCollisionObjectMsg(aco);
00828 }
00829
00830 selectedCollisionObjectChanged();
00831 planning_display_->queueRenderSceneGeometry();
00832 }
00833
00834 void MotionPlanningFrame::populateCollisionObjectsList()
00835 {
00836 ui_->collision_objects_list->setUpdatesEnabled(false);
00837 bool oldState = ui_->collision_objects_list->blockSignals(true);
00838
00839 {
00840 QList<QListWidgetItem *> sel = ui_->collision_objects_list->selectedItems();
00841 std::set<std::string> to_select;
00842 for (int i = 0 ; i < sel.size() ; ++i)
00843 to_select.insert(sel[i]->text().toStdString());
00844 ui_->collision_objects_list->clear();
00845 known_collision_objects_.clear();
00846 known_collision_objects_version_++;
00847
00848 planning_scene_monitor::LockedPlanningSceneRO ps = planning_display_->getPlanningSceneRO();
00849 if (ps)
00850 {
00851 const std::vector<std::string> &collision_object_names = ps->getWorld()->getObjectIds();
00852 for (std::size_t i = 0 ; i < collision_object_names.size() ; ++i)
00853 {
00854 if (collision_object_names[i] == planning_scene::PlanningScene::OCTOMAP_NS ||
00855 collision_object_names[i] == planning_scene::PlanningScene::COLLISION_MAP_NS)
00856 continue;
00857
00858 QListWidgetItem *item = new QListWidgetItem(QString::fromStdString(collision_object_names[i]),
00859 ui_->collision_objects_list, (int)i);
00860 item->setFlags(item->flags() | Qt::ItemIsEditable);
00861 item->setToolTip(item->text());
00862 item->setCheckState(Qt::Unchecked);
00863 if (to_select.find(collision_object_names[i]) != to_select.end())
00864 item->setSelected(true);
00865 ui_->collision_objects_list->addItem(item);
00866 known_collision_objects_.push_back(std::make_pair(collision_object_names[i], false));
00867 }
00868
00869 const robot_state::RobotState &cs = ps->getCurrentState();
00870 std::vector<const robot_state::AttachedBody*> attached_bodies;
00871 cs.getAttachedBodies(attached_bodies);
00872 for (std::size_t i = 0 ; i < attached_bodies.size() ; ++i)
00873 {
00874 QListWidgetItem *item = new QListWidgetItem(QString::fromStdString(attached_bodies[i]->getName()),
00875 ui_->collision_objects_list, (int)(i + collision_object_names.size()));
00876 item->setFlags(item->flags() | Qt::ItemIsEditable);
00877 item->setToolTip(item->text());
00878 item->setCheckState(Qt::Checked);
00879 if (to_select.find(attached_bodies[i]->getName()) != to_select.end())
00880 item->setSelected(true);
00881 ui_->collision_objects_list->addItem(item);
00882 known_collision_objects_.push_back(std::make_pair(attached_bodies[i]->getName(), true));
00883 }
00884 }
00885 }
00886
00887 ui_->collision_objects_list->blockSignals(oldState);
00888 ui_->collision_objects_list->setUpdatesEnabled(true);
00889 selectedCollisionObjectChanged();
00890 }
00891
00892 void MotionPlanningFrame::exportAsTextButtonClicked()
00893 {
00894 QString path = QFileDialog::getSaveFileName(this, tr("Export Scene Geometry"), tr(""), tr("Scene Geometry (*.scene)"));
00895 if (!path.isEmpty())
00896 planning_display_->addBackgroundJob(boost::bind(&MotionPlanningFrame::computeExportAsText, this, path.toStdString()), "export as text");
00897 }
00898
00899 void MotionPlanningFrame::computeExportAsText(const std::string &path)
00900 {
00901 planning_scene_monitor::LockedPlanningSceneRO ps = planning_display_->getPlanningSceneRO();
00902 if (ps)
00903 {
00904 std::string p = (path.length() < 7 || path.substr(path.length() - 6) != ".scene") ? path + ".scene" : path;
00905 std::ofstream fout(p.c_str());
00906 if (fout.good())
00907 {
00908 ps->saveGeometryToStream(fout);
00909 fout.close();
00910 ROS_INFO("Saved current scene geometry to '%s'", p.c_str());
00911 }
00912 else
00913 ROS_WARN("Unable to save current scene geometry to '%s'", p.c_str());
00914 }
00915 }
00916
00917 void MotionPlanningFrame::computeImportFromText(const std::string &path)
00918 {
00919 planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00920 if (ps)
00921 {
00922 std::ifstream fin(path.c_str());
00923 if (fin.good())
00924 {
00925 ps->loadGeometryFromStream(fin);
00926 fin.close();
00927 ROS_INFO("Loaded scene geometry from '%s'", path.c_str());
00928 planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::populateCollisionObjectsList, this));
00929 planning_display_->queueRenderSceneGeometry();
00930 }
00931 else
00932 ROS_WARN("Unable to load scene geometry from '%s'", path.c_str());
00933 }
00934 }
00935
00936 void MotionPlanningFrame::importFromTextButtonClicked()
00937 {
00938 QString path = QFileDialog::getOpenFileName(this, tr("Import Scene Geometry"), tr(""), tr("Scene Geometry (*.scene)"));
00939 if (!path.isEmpty())
00940 planning_display_->addBackgroundJob(boost::bind(&MotionPlanningFrame::computeImportFromText, this, path.toStdString()), "import from text");
00941 }
00942
00943
00944 }