motion_planning_frame.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2012, 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 */
00031 
00032 #include <moveit/motion_planning_rviz_plugin/motion_planning_frame.h>
00033 #include <moveit/motion_planning_rviz_plugin/motion_planning_display.h>
00034 
00035 #include <geometric_shapes/shape_operations.h>
00036 
00037 #include <rviz/display_context.h>
00038 #include <rviz/frame_manager.h>
00039 
00040 #include <QMessageBox>
00041 #include <QInputDialog>
00042 #include <QShortcut>
00043 
00044 #include "ui_motion_planning_rviz_plugin_frame.h"
00045 
00046 namespace moveit_rviz_plugin
00047 {
00048 
00049 MotionPlanningFrame::MotionPlanningFrame(MotionPlanningDisplay *pdisplay, rviz::DisplayContext *context, QWidget *parent) :
00050   QWidget(parent),
00051   planning_display_(pdisplay),
00052   context_(context),
00053   ui_(new Ui::MotionPlanningUI()),
00054   first_time_(true)
00055 {
00056   // set up the GUI
00057   ui_->setupUi(this);
00058 
00059   // connect bottons to actions; each action usually registers the function pointer for the actual computation,
00060   // to keep the GUI more responsive (using the background job processing)
00061   connect( ui_->plan_button, SIGNAL( clicked() ), this, SLOT( planButtonClicked() ));
00062   connect( ui_->execute_button, SIGNAL( clicked() ), this, SLOT( executeButtonClicked() ));
00063   connect( ui_->plan_and_execute_button, SIGNAL( clicked() ), this, SLOT( planAndExecuteButtonClicked() ));
00064   connect( ui_->use_start_state_button, SIGNAL( clicked() ), this, SLOT( useStartStateButtonClicked() ));
00065   connect( ui_->use_goal_state_button, SIGNAL( clicked() ), this, SLOT( useGoalStateButtonClicked() ));
00066   connect( ui_->database_connect_button, SIGNAL( clicked() ), this, SLOT( databaseConnectButtonClicked() ));
00067   connect( ui_->save_scene_button, SIGNAL( clicked() ), this, SLOT( saveSceneButtonClicked() ));
00068   connect( ui_->save_query_button, SIGNAL( clicked() ), this, SLOT( saveQueryButtonClicked() ));
00069   connect( ui_->delete_scene_button, SIGNAL( clicked() ), this, SLOT( deleteSceneButtonClicked() ));
00070   connect( ui_->delete_query_button, SIGNAL( clicked() ), this, SLOT( deleteQueryButtonClicked() ));
00071   connect( ui_->planning_scene_tree, SIGNAL( itemSelectionChanged() ), this, SLOT( planningSceneItemClicked() ));
00072   connect( ui_->load_scene_button, SIGNAL( clicked() ), this, SLOT( loadSceneButtonClicked() ));
00073   connect( ui_->load_query_button, SIGNAL( clicked() ), this, SLOT( loadQueryButtonClicked() ));
00074   connect( ui_->allow_looking, SIGNAL( toggled(bool) ), this, SLOT( allowLookingToggled(bool) ));
00075   connect( ui_->allow_replanning, SIGNAL( toggled(bool) ), this, SLOT( allowReplanningToggled(bool) ));
00076   connect( ui_->planning_algorithm_combo_box, SIGNAL( currentIndexChanged ( int ) ), this, SLOT( planningAlgorithmIndexChanged( int ) ));
00077   connect( ui_->import_file_button, SIGNAL( clicked() ), this, SLOT( importFileButtonClicked() ));
00078   connect( ui_->import_url_button, SIGNAL( clicked() ), this, SLOT( importUrlButtonClicked() ));
00079   connect( ui_->clear_scene_button, SIGNAL( clicked() ), this, SLOT( clearSceneButtonClicked() ));
00080   connect( ui_->scene_scale, SIGNAL( valueChanged(int) ), this, SLOT( sceneScaleChanged(int) ));
00081   connect( ui_->scene_scale, SIGNAL( sliderPressed() ), this, SLOT( sceneScaleStartChange() ));
00082   connect( ui_->scene_scale, SIGNAL( sliderReleased() ), this, SLOT( sceneScaleEndChange() ));
00083   connect( ui_->remove_object_button, SIGNAL( clicked() ), this, SLOT( removeObjectButtonClicked() ));
00084   connect( ui_->object_x, SIGNAL( valueChanged(double) ), this, SLOT( objectPoseValueChanged(double) ));
00085   connect( ui_->object_y, SIGNAL( valueChanged(double) ), this, SLOT( objectPoseValueChanged(double) ));
00086   connect( ui_->object_z, SIGNAL( valueChanged(double) ), this, SLOT( objectPoseValueChanged(double) ));
00087   connect( ui_->object_rx, SIGNAL( valueChanged(double) ), this, SLOT( objectPoseValueChanged(double) ));
00088   connect( ui_->object_ry, SIGNAL( valueChanged(double) ), this, SLOT( objectPoseValueChanged(double) ));
00089   connect( ui_->object_rz, SIGNAL( valueChanged(double) ), this, SLOT( objectPoseValueChanged(double) ));
00090   connect( ui_->publish_current_scene_button, SIGNAL( clicked() ), this, SLOT( publishSceneButtonClicked() ));
00091   connect( ui_->collision_objects_list, SIGNAL( itemSelectionChanged() ), this, SLOT( selectedCollisionObjectChanged() ));
00092   connect( ui_->collision_objects_list, SIGNAL( itemChanged( QListWidgetItem * ) ), this, SLOT( collisionObjectChanged( QListWidgetItem * ) ));
00093   connect( ui_->path_constraints_combo_box, SIGNAL( currentIndexChanged ( int ) ), this, SLOT( pathConstraintsIndexChanged( int ) ));
00094   connect( ui_->planning_scene_tree, SIGNAL( itemChanged( QTreeWidgetItem *, int ) ), this, SLOT( warehouseItemNameChanged( QTreeWidgetItem *, int ) ));
00095   connect( ui_->reset_db_button, SIGNAL( clicked() ), this, SLOT( resetDbButtonClicked() ));
00096   connect( ui_->export_scene_text_button, SIGNAL( clicked() ), this, SLOT( exportAsTextButtonClicked() ));
00097   connect( ui_->import_scene_text_button, SIGNAL( clicked() ), this, SLOT( importFromTextButtonClicked() ));
00098   connect( ui_->load_state_button, SIGNAL( clicked() ), this, SLOT( loadStateButtonClicked() ));
00099   connect( ui_->save_start_state_button, SIGNAL( clicked() ), this, SLOT( saveStartStateButtonClicked() ));
00100   connect( ui_->save_goal_state_button, SIGNAL( clicked() ), this, SLOT( saveGoalStateButtonClicked() ));
00101   connect( ui_->set_as_start_state_button, SIGNAL( clicked() ), this, SLOT( setAsStartStateButtonClicked() ));
00102   connect( ui_->set_as_goal_state_button, SIGNAL( clicked() ), this, SLOT( setAsGoalStateButtonClicked() ));
00103   connect( ui_->remove_state_button, SIGNAL( clicked() ), this, SLOT( removeStateButtonClicked() ));
00104   connect( ui_->clear_states_button, SIGNAL( clicked() ), this, SLOT( clearStatesButtonClicked() ));
00105   connect( ui_->approximate_ik, SIGNAL( stateChanged(int) ), this, SLOT( approximateIKChanged(int) ));
00106 
00107   connect( ui_->tabWidget, SIGNAL( currentChanged ( int ) ), this, SLOT( tabChanged( int ) ));
00108 
00109   QShortcut *copy_object_shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C), ui_->collision_objects_list);
00110   connect(copy_object_shortcut, SIGNAL( activated() ), this, SLOT( copySelectedCollisionObject() ) );
00111 
00112   ui_->reset_db_button->hide();
00113   ui_->background_job_progress->hide();
00114   ui_->background_job_progress->setMaximum(0);
00115 
00116   ui_->tabWidget->setCurrentIndex(0);
00117 
00118   known_collision_objects_version_ = 0;
00119 
00120   planning_scene_publisher_ = nh_.advertise<moveit_msgs::PlanningScene>("planning_scene", 1);
00121   planning_scene_world_publisher_ = nh_.advertise<moveit_msgs::PlanningSceneWorld>("planning_scene_world", 1);
00122 }
00123 
00124 MotionPlanningFrame::~MotionPlanningFrame()
00125 {
00126 }
00127 
00128 void MotionPlanningFrame::approximateIKChanged(int state)
00129 {
00130   planning_display_->useApproximateIK(state == Qt::Checked);
00131 }
00132 
00133 void MotionPlanningFrame::setItemSelectionInList(const std::string &item_name, bool selection, QListWidget *list)
00134 {
00135   QList<QListWidgetItem*> found_items = list->findItems(QString(item_name.c_str()), Qt::MatchExactly);
00136   for (std::size_t i = 0 ; i < found_items.size(); ++i)
00137     found_items[i]->setSelected(selection);
00138 }
00139 
00140 void MotionPlanningFrame::fillStateSelectionOptions()
00141 {
00142   ui_->start_state_selection->clear();
00143   ui_->goal_state_selection->clear();
00144 
00145   if (!planning_display_->getPlanningSceneMonitor())
00146     return;
00147 
00148   const robot_model::RobotModelConstPtr &kmodel = planning_display_->getRobotModel();
00149   std::string group = planning_display_->getCurrentPlanningGroup();
00150   if (group.empty())
00151     return;
00152   const robot_model::JointModelGroup *jmg = kmodel->getJointModelGroup(group);
00153   if (jmg)
00154   {
00155     ui_->start_state_selection->addItem(QString("<random>"));
00156     ui_->start_state_selection->addItem(QString("<current>"));
00157     ui_->start_state_selection->addItem(QString("<same as goal>"));
00158 
00159     ui_->goal_state_selection->addItem(QString("<random>"));
00160     ui_->goal_state_selection->addItem(QString("<current>"));
00161     ui_->goal_state_selection->addItem(QString("<same as start>"));
00162 
00163     std::vector<std::string> known_states;
00164     jmg->getKnownDefaultStates(known_states);
00165     if (!known_states.empty())
00166     {
00167       ui_->start_state_selection->insertSeparator(ui_->start_state_selection->count());
00168       ui_->goal_state_selection->insertSeparator(ui_->goal_state_selection->count());
00169       for (std::size_t i = 0 ; i < known_states.size() ; ++i)
00170       {
00171         ui_->start_state_selection->addItem(QString::fromStdString(known_states[i]));
00172         ui_->goal_state_selection->addItem(QString::fromStdString(known_states[i]));
00173       }
00174     }
00175     ui_->start_state_selection->setCurrentIndex(1);
00176     ui_->goal_state_selection->setCurrentIndex(0);
00177   }
00178 }
00179 
00180 void MotionPlanningFrame::changePlanningGroupHelper()
00181 {
00182   if (!planning_display_->getPlanningSceneMonitor())
00183     return;
00184 
00185   planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::fillStateSelectionOptions, this));
00186   planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::populateConstraintsList, this, std::vector<std::string>()));
00187 
00188   const robot_model::RobotModelConstPtr &kmodel = planning_display_->getRobotModel();
00189   std::string group = planning_display_->getCurrentPlanningGroup();
00190 
00191   if (!group.empty() && kmodel)
00192   {
00193     if (move_group_ && move_group_->getName() == group)
00194       return;
00195     ROS_INFO("Constructing new MoveGroup connection for group '%s'", group.c_str());
00196     moveit::planning_interface::MoveGroup::Options opt(group);
00197     opt.robot_model_ = kmodel;
00198     opt.robot_description_.clear();
00199     try
00200     {
00201       move_group_.reset(new moveit::planning_interface::MoveGroup(opt, context_->getFrameManager()->getTFClientPtr(), ros::Duration(30, 0)));
00202       if (planning_scene_storage_)
00203         move_group_->setConstraintsDatabase(ui_->database_host->text().toStdString(), ui_->database_port->value());
00204     }
00205     catch(std::runtime_error &ex)
00206     {
00207       ROS_ERROR("%s", ex.what());
00208     }
00209     if (move_group_)
00210     {
00211       move_group_->allowLooking(ui_->allow_looking->isChecked());
00212       move_group_->allowReplanning(ui_->allow_replanning->isChecked());
00213       moveit_msgs::PlannerInterfaceDescription desc;
00214       if (move_group_->getInterfaceDescription(desc))
00215         planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::populatePlannersList, this, desc));
00216       planning_display_->addBackgroundJob(boost::bind(&MotionPlanningFrame::populateConstraintsList, this), "populateConstraintsList");
00217 
00218       if (first_time_)
00219       {
00220         first_time_ = false;
00221         const planning_scene_monitor::LockedPlanningSceneRO &ps = planning_display_->getPlanningSceneRO();
00222         if (ps)
00223         {
00224           planning_display_->setQueryStartState(ps->getCurrentState());
00225           planning_display_->setQueryGoalState(ps->getCurrentState());
00226         }
00227       }
00228     }
00229   }
00230 }
00231 
00232 void MotionPlanningFrame::changePlanningGroup()
00233 {
00234   planning_display_->addBackgroundJob(boost::bind(&MotionPlanningFrame::changePlanningGroupHelper, this), "Frame::changePlanningGroup");
00235 }
00236 
00237 void MotionPlanningFrame::sceneUpdate(planning_scene_monitor::PlanningSceneMonitor::SceneUpdateType update_type)
00238 {
00239   if (update_type & planning_scene_monitor::PlanningSceneMonitor::UPDATE_GEOMETRY)
00240     planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::populateCollisionObjectsList, this));
00241 }
00242 
00243 void MotionPlanningFrame::importResource(const std::string &path)
00244 {
00245   if (planning_display_->getPlanningSceneMonitor())
00246   {
00247     shapes::Mesh *mesh = shapes::createMeshFromResource(path);
00248     if (mesh)
00249     {
00250       std::size_t slash = path.find_last_of("/\\");
00251       std::string name = path.substr(slash + 1);
00252       shapes::ShapeConstPtr shape(mesh);
00253       Eigen::Affine3d pose;
00254       pose.setIdentity();
00255 
00256       if (planning_display_->getPlanningSceneRO()->getCurrentState().hasAttachedBody(name))
00257       {
00258         QMessageBox::warning(this, QString("Duplicate names"),
00259                              QString("An attached object named '").append(name.c_str()).append("' already exists. Please rename the attached object before importing."));
00260         return;
00261       }
00262 
00263       //If the object already exists, ask the user whether to overwrite or rename
00264       if (planning_display_->getPlanningSceneRO()->getWorld()->hasObject(name))
00265       {
00266         QMessageBox msgBox;
00267         msgBox.setText("There exists another object with the same name.");
00268         msgBox.setInformativeText("Would you like to overwrite it?");
00269         msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
00270         msgBox.setDefaultButton(QMessageBox::No);
00271         int ret = msgBox.exec();
00272 
00273         switch (ret)
00274         {
00275           case QMessageBox::Yes:
00276             // Overwrite was clicked
00277             {
00278               planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00279               if (ps)
00280               {
00281                 ps->getWorldNonConst()->removeObject(name);
00282                 addObject(ps->getWorldNonConst(), name, shape, pose);
00283               }
00284             }
00285             break;
00286           case QMessageBox::No:
00287           {
00288             // Don't overwrite was clicked. Ask for another name
00289             bool ok = false;
00290             QString text = QInputDialog::getText(this, tr("Choose a new name"),
00291                                                  tr("Import the new object under the name:"), QLineEdit::Normal,
00292                                                  QString::fromStdString(name + "-" + boost::lexical_cast<std::string>
00293                                                                         (planning_display_->getPlanningSceneRO()->getWorld()->size())), &ok);
00294             if (ok)
00295             {
00296               if (!text.isEmpty())
00297               {
00298                 name = text.toStdString();
00299                 planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00300                 if (ps)
00301                 {
00302                   if (ps->getWorld()->hasObject(name))
00303                     QMessageBox::warning(this, "Name already exists", QString("The name '").append(name.c_str()).
00304                                          append("' already exists. Not importing object."));
00305                   else
00306                     addObject(ps->getWorldNonConst(), name, shape, pose);
00307                 }
00308               }
00309               else
00310                 QMessageBox::warning(this, "Object not imported", "Cannot use an empty name for an imported object");
00311             }
00312             break;
00313           }
00314           default:
00315             //Pressed cancel, do nothing
00316             break;
00317         }
00318       }
00319       else
00320       {
00321         planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00322         if (ps)
00323           addObject(ps->getWorldNonConst(), name, shape, pose);
00324       }
00325     }
00326     else
00327     {
00328       QMessageBox::warning(this, QString("Import error"), QString("Unable to import scene"));
00329       return;
00330     }
00331   }
00332 }
00333 
00334 void MotionPlanningFrame::enable()
00335 {
00336   ui_->planning_algorithm_combo_box->clear();
00337   ui_->library_label->setText("NO PLANNING LIBRARY LOADED");
00338   ui_->library_label->setStyleSheet("QLabel { color : red; font: bold }");
00339   ui_->object_status->setText("");
00340 
00341   // activate the frame
00342   show();
00343 }
00344 
00345 void MotionPlanningFrame::disable()
00346 {
00347   move_group_.reset();
00348   hide();
00349 }
00350 
00351 void MotionPlanningFrame::tabChanged(int index)
00352 {
00353   if (scene_marker_ && ui_->tabWidget->tabText(index) != "Scene Objects")
00354     scene_marker_.reset();
00355   else
00356     if (ui_->tabWidget->tabText(index) == "Scene Objects")
00357       selectedCollisionObjectChanged();
00358 }
00359 
00360 void MotionPlanningFrame::updateSceneMarkers(float wall_dt, float ros_dt)
00361 {
00362   if (scene_marker_)
00363     scene_marker_->update(wall_dt);
00364 }
00365 
00366 } // namespace


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