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
00033
00034
00035
00036
00037 #include <moveit/motion_planning_rviz_plugin/motion_planning_frame.h>
00038 #include <moveit/motion_planning_rviz_plugin/motion_planning_display.h>
00039
00040 #include <moveit/kinematic_constraints/utils.h>
00041 #include <moveit/robot_state/conversions.h>
00042 #include <object_recognition_msgs/ObjectRecognitionGoal.h>
00043
00044 #include "ui_motion_planning_rviz_plugin_frame.h"
00045
00046 namespace moveit_rviz_plugin
00047 {
00049 void MotionPlanningFrame::detectObjectsButtonClicked()
00050 {
00051 if (!semantic_world_)
00052 {
00053 const planning_scene_monitor::LockedPlanningSceneRO& ps = planning_display_->getPlanningSceneRO();
00054 if (ps)
00055 {
00056 semantic_world_.reset(new moveit::semantic_world::SemanticWorld(ps));
00057 }
00058 if (semantic_world_)
00059 {
00060 semantic_world_->addTableCallback(boost::bind(&MotionPlanningFrame::updateTables, this));
00061 }
00062 }
00063 planning_display_->addBackgroundJob(boost::bind(&MotionPlanningFrame::triggerObjectDetection, this), "detect "
00064 "objects");
00065 }
00066
00067 void MotionPlanningFrame::processDetectedObjects()
00068 {
00069 pick_object_name_.clear();
00070
00071 std::vector<std::string> objects, object_ids;
00072 double min_x = ui_->roi_center_x->value() - ui_->roi_size_x->value() / 2.0;
00073 double min_y = ui_->roi_center_y->value() - ui_->roi_size_y->value() / 2.0;
00074 double min_z = ui_->roi_center_z->value() - ui_->roi_size_z->value() / 2.0;
00075
00076 double max_x = ui_->roi_center_x->value() + ui_->roi_size_x->value() / 2.0;
00077 double max_y = ui_->roi_center_y->value() + ui_->roi_size_y->value() / 2.0;
00078 double max_z = ui_->roi_center_z->value() + ui_->roi_size_z->value() / 2.0;
00079
00080 ros::Time start_time = ros::Time::now();
00081 while (object_ids.empty() && ros::Time::now() - start_time <= ros::Duration(3.0))
00082 {
00083 object_ids =
00084 planning_scene_interface_->getKnownObjectNamesInROI(min_x, min_y, min_z, max_x, max_y, max_z, true, objects);
00085 ros::Duration(0.5).sleep();
00086 }
00087
00088 ROS_DEBUG("Found %d objects", (int)object_ids.size());
00089 updateDetectedObjectsList(object_ids, objects);
00090 }
00091
00092 void MotionPlanningFrame::selectedDetectedObjectChanged()
00093 {
00094 QList<QListWidgetItem*> sel = ui_->detected_objects_list->selectedItems();
00095 if (sel.empty())
00096 {
00097 ROS_INFO("No objects to select");
00098 return;
00099 }
00100 planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00101 std_msgs::ColorRGBA pick_object_color;
00102 pick_object_color.r = 1.0;
00103 pick_object_color.g = 0.0;
00104 pick_object_color.b = 0.0;
00105 pick_object_color.a = 1.0;
00106
00107 if (ps)
00108 {
00109 if (!selected_object_name_.empty())
00110 ps->removeObjectColor(selected_object_name_);
00111 selected_object_name_ = sel[0]->text().toStdString();
00112 ps->setObjectColor(selected_object_name_, pick_object_color);
00113 }
00114 }
00115
00116 void MotionPlanningFrame::detectedObjectChanged(QListWidgetItem* item)
00117 {
00118 }
00119
00120 void MotionPlanningFrame::triggerObjectDetection()
00121 {
00122 if (!object_recognition_client_)
00123 {
00124 object_recognition_client_.reset(
00125 new actionlib::SimpleActionClient<object_recognition_msgs::ObjectRecognitionAction>(OBJECT_RECOGNITION_ACTION,
00126 false));
00127 try
00128 {
00129 waitForAction(object_recognition_client_, nh_, ros::Duration(3.0), OBJECT_RECOGNITION_ACTION);
00130 }
00131 catch (std::runtime_error& ex)
00132 {
00133 ROS_ERROR("Object recognition action: %s", ex.what());
00134 return;
00135 }
00136 }
00137 object_recognition_msgs::ObjectRecognitionGoal goal;
00138 object_recognition_client_->sendGoal(goal);
00139 if (!object_recognition_client_->waitForResult())
00140 {
00141 ROS_INFO_STREAM("Object recognition client returned early");
00142 }
00143 if (object_recognition_client_->getState() != actionlib::SimpleClientGoalState::SUCCEEDED)
00144 {
00145 ROS_WARN_STREAM("Fail: " << object_recognition_client_->getState().toString() << ": "
00146 << object_recognition_client_->getState().getText());
00147 }
00148 }
00149
00150 void MotionPlanningFrame::listenDetectedObjects(const object_recognition_msgs::RecognizedObjectArrayPtr& msg)
00151 {
00152 ros::Duration(1.0).sleep();
00153 planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::processDetectedObjects, this));
00154 }
00155
00156 void MotionPlanningFrame::updateDetectedObjectsList(const std::vector<std::string>& object_ids,
00157 const std::vector<std::string>& objects)
00158 {
00159 ui_->detected_objects_list->setUpdatesEnabled(false);
00160 bool oldState = ui_->detected_objects_list->blockSignals(true);
00161 ui_->detected_objects_list->clear();
00162 {
00163 for (std::size_t i = 0; i < object_ids.size(); ++i)
00164 {
00165 QListWidgetItem* item =
00166 new QListWidgetItem(QString::fromStdString(object_ids[i]), ui_->detected_objects_list, (int)i);
00167 item->setToolTip(item->text());
00168 Qt::ItemFlags flags = item->flags();
00169 flags &= ~(Qt::ItemIsUserCheckable);
00170 item->setFlags(flags);
00171 ui_->detected_objects_list->addItem(item);
00172 }
00173 }
00174 ui_->detected_objects_list->blockSignals(oldState);
00175 ui_->detected_objects_list->setUpdatesEnabled(true);
00176 if (!object_ids.empty())
00177 ui_->pick_button->setEnabled(true);
00178 }
00179
00181 void MotionPlanningFrame::updateTables()
00182 {
00183 ROS_DEBUG("Update table callback");
00184 planning_display_->addBackgroundJob(boost::bind(&MotionPlanningFrame::publishTables, this), "publish tables");
00185 }
00186
00187 void MotionPlanningFrame::publishTables()
00188 {
00189 semantic_world_->addTablesToCollisionWorld();
00190 planning_display_->addMainLoopJob(boost::bind(&MotionPlanningFrame::updateSupportSurfacesList, this));
00191 }
00192
00193 void MotionPlanningFrame::selectedSupportSurfaceChanged()
00194 {
00195 QList<QListWidgetItem*> sel = ui_->support_surfaces_list->selectedItems();
00196 if (sel.empty())
00197 {
00198 ROS_INFO("No tables to select");
00199 return;
00200 }
00201 planning_scene_monitor::LockedPlanningSceneRW ps = planning_display_->getPlanningSceneRW();
00202 std_msgs::ColorRGBA selected_support_surface_color;
00203 selected_support_surface_color.r = 0.0;
00204 selected_support_surface_color.g = 0.0;
00205 selected_support_surface_color.b = 1.0;
00206 selected_support_surface_color.a = 1.0;
00207
00208 if (ps)
00209 {
00210 if (!selected_support_surface_name_.empty())
00211 ps->removeObjectColor(selected_support_surface_name_);
00212 selected_support_surface_name_ = sel[0]->text().toStdString();
00213 ps->setObjectColor(selected_support_surface_name_, selected_support_surface_color);
00214 }
00215 }
00216
00217 void MotionPlanningFrame::updateSupportSurfacesList()
00218 {
00219 double min_x = ui_->roi_center_x->value() - ui_->roi_size_x->value() / 2.0;
00220 double min_y = ui_->roi_center_y->value() - ui_->roi_size_y->value() / 2.0;
00221 double min_z = ui_->roi_center_z->value() - ui_->roi_size_z->value() / 2.0;
00222
00223 double max_x = ui_->roi_center_x->value() + ui_->roi_size_x->value() / 2.0;
00224 double max_y = ui_->roi_center_y->value() + ui_->roi_size_y->value() / 2.0;
00225 double max_z = ui_->roi_center_z->value() + ui_->roi_size_z->value() / 2.0;
00226 std::vector<std::string> support_ids = semantic_world_->getTableNamesInROI(min_x, min_y, min_z, max_x, max_y, max_z);
00227 ROS_INFO("%d Tables in collision world", (int)support_ids.size());
00228
00229 ui_->support_surfaces_list->setUpdatesEnabled(false);
00230 bool oldState = ui_->support_surfaces_list->blockSignals(true);
00231 ui_->support_surfaces_list->clear();
00232 {
00233 for (std::size_t i = 0; i < support_ids.size(); ++i)
00234 {
00235 QListWidgetItem* item =
00236 new QListWidgetItem(QString::fromStdString(support_ids[i]), ui_->support_surfaces_list, (int)i);
00237 item->setToolTip(item->text());
00238 Qt::ItemFlags flags = item->flags();
00239 flags &= ~(Qt::ItemIsUserCheckable);
00240 item->setFlags(flags);
00241 ui_->support_surfaces_list->addItem(item);
00242 }
00243 }
00244 ui_->support_surfaces_list->blockSignals(oldState);
00245 ui_->support_surfaces_list->setUpdatesEnabled(true);
00246 }
00247
00249 void MotionPlanningFrame::pickObjectButtonClicked()
00250 {
00251 QList<QListWidgetItem*> sel = ui_->detected_objects_list->selectedItems();
00252 QList<QListWidgetItem*> sel_table = ui_->support_surfaces_list->selectedItems();
00253
00254 std::string group_name = planning_display_->getCurrentPlanningGroup();
00255 if (sel.empty())
00256 {
00257 ROS_INFO("No objects to pick");
00258 return;
00259 }
00260 pick_object_name_[group_name] = sel[0]->text().toStdString();
00261
00262 if (!sel_table.empty())
00263 support_surface_name_ = sel_table[0]->text().toStdString();
00264 else
00265 {
00266 if (semantic_world_)
00267 {
00268 std::vector<std::string> object_names;
00269 object_names.push_back(pick_object_name_[group_name]);
00270 std::map<std::string, geometry_msgs::Pose> object_poses = planning_scene_interface_->getObjectPoses(object_names);
00271 if (object_poses.find(pick_object_name_[group_name]) != object_poses.end())
00272 {
00273 ROS_DEBUG("Finding current table for object: %s", pick_object_name_[group_name].c_str());
00274 support_surface_name_ = semantic_world_->findObjectTable(object_poses[pick_object_name_[group_name]]);
00275 }
00276 else
00277 support_surface_name_.clear();
00278 }
00279 else
00280 support_surface_name_.clear();
00281 }
00282 ROS_INFO("Trying to pick up object %s from support surface %s", pick_object_name_[group_name].c_str(),
00283 support_surface_name_.c_str());
00284 planning_display_->addBackgroundJob(boost::bind(&MotionPlanningFrame::pickObject, this), "pick");
00285 }
00286
00287 void MotionPlanningFrame::placeObjectButtonClicked()
00288 {
00289 QList<QListWidgetItem*> sel_table = ui_->support_surfaces_list->selectedItems();
00290 std::string group_name = planning_display_->getCurrentPlanningGroup();
00291
00292 if (!sel_table.empty())
00293 support_surface_name_ = sel_table[0]->text().toStdString();
00294 else
00295 {
00296 support_surface_name_.clear();
00297 ROS_ERROR("Need to specify table to place object on");
00298 return;
00299 }
00300
00301 ui_->pick_button->setEnabled(false);
00302 ui_->place_button->setEnabled(false);
00303
00304 std::vector<const robot_state::AttachedBody*> attached_bodies;
00305 const planning_scene_monitor::LockedPlanningSceneRO& ps = planning_display_->getPlanningSceneRO();
00306 if (!ps)
00307 {
00308 ROS_ERROR("No planning scene");
00309 return;
00310 }
00311 const robot_model::JointModelGroup* jmg = ps->getCurrentState().getJointModelGroup(group_name);
00312 if (jmg)
00313 ps->getCurrentState().getAttachedBodies(attached_bodies, jmg);
00314
00315 if (attached_bodies.empty())
00316 {
00317 ROS_ERROR("No bodies to place");
00318 return;
00319 }
00320
00321 geometry_msgs::Quaternion upright_orientation;
00322 upright_orientation.w = 1.0;
00323
00324
00325 place_poses_.clear();
00326 place_poses_ = semantic_world_->generatePlacePoses(support_surface_name_, attached_bodies[0]->getShapes()[0],
00327 upright_orientation, 0.1);
00328 planning_display_->visualizePlaceLocations(place_poses_);
00329 place_object_name_ = attached_bodies[0]->getName();
00330 planning_display_->addBackgroundJob(boost::bind(&MotionPlanningFrame::placeObject, this), "place");
00331 }
00332
00333 void MotionPlanningFrame::pickObject()
00334 {
00335 std::string group_name = planning_display_->getCurrentPlanningGroup();
00336 ui_->pick_button->setEnabled(false);
00337 if (pick_object_name_.find(group_name) == pick_object_name_.end())
00338 {
00339 ROS_ERROR("No pick object set for this group");
00340 return;
00341 }
00342 if (!support_surface_name_.empty())
00343 {
00344 move_group_->setSupportSurfaceName(support_surface_name_);
00345 }
00346 if (move_group_->pick(pick_object_name_[group_name]))
00347 {
00348 ui_->place_button->setEnabled(true);
00349 }
00350 }
00351
00352 void MotionPlanningFrame::placeObject()
00353 {
00354 move_group_->place(place_object_name_, place_poses_);
00355 return;
00356 }
00357 }