00001
00002
00003
00004
00005
00006
00007
00008 #include "planner_modules_pr2/tidyup_planning_scene_updater.h"
00009 #include <tidyup_utils/planning_scene_interface.h>
00010 #include <tidyup_utils/arm_state.h>
00011 #include <tidyup_utils/stringutil.h>
00012 #include <hardcoded_facts/geometryPoses.h>
00013 #include <ros/ros.h>
00014
00015 using std::vector;
00016 using std::map;
00017 using std::set;
00018 using std::string;
00019
00020 TidyupPlanningSceneUpdater* TidyupPlanningSceneUpdater::instance = NULL;
00021
00022 TidyupPlanningSceneUpdater::TidyupPlanningSceneUpdater() : logName("[psu]")
00023 {
00024 string doorLocationFileName;
00025 ros::param::get("/continual_planning_executive/door_location_file", doorLocationFileName);
00026 loadDoorPoses(doorLocationFileName);
00027
00028 defaultAttachPose.position.x = 0.032;
00029 defaultAttachPose.position.y = 0.015;
00030 defaultAttachPose.position.z = 0.0;
00031 defaultAttachPose.orientation.x = 0.707;
00032 defaultAttachPose.orientation.y = -0.106;
00033 defaultAttachPose.orientation.z = -0.690;
00034 defaultAttachPose.orientation.w = 0.105;
00035
00036 ROS_INFO("%s initialized.\n", logName.c_str());
00037 }
00038
00039 TidyupPlanningSceneUpdater::~TidyupPlanningSceneUpdater()
00040 {
00041 }
00042
00043 bool TidyupPlanningSceneUpdater::readState(
00044 const string& robotLocation,
00045 predicateCallbackType predicateCallback,
00046 numericalFluentCallbackType numericalFluentCallback,
00047 geometry_msgs::Pose& robotPose,
00048 map<string, geometry_msgs::Pose>& movableObjects,
00049 map<string, string>& graspedObjects,
00050 map<string, string>& objectsOnStatic,
00051 set<string>& openDoors)
00052 {
00053 if (instance == NULL) instance = new TidyupPlanningSceneUpdater();
00054 return instance->readState_(robotLocation, predicateCallback, numericalFluentCallback, robotPose, movableObjects, graspedObjects, objectsOnStatic, openDoors);
00055 }
00056
00057 bool TidyupPlanningSceneUpdater::readState_(
00058 const string& robotLocation,
00059 predicateCallbackType predicateCallback,
00060 numericalFluentCallbackType numericalFluentCallback,
00061 geometry_msgs::Pose& robotPose,
00062 map<string, geometry_msgs::Pose>& movableObjects,
00063 map<string, string>& graspedObjects,
00064 map<string, string>& objectsOnStatic,
00065 set<string>& openDoors)
00066 {
00067
00068 PlanningSceneInterface* psi = PlanningSceneInterface::instance();
00069
00070 geometry_msgs::Pose pose;
00071 const vector <arm_navigation_msgs::CollisionObject>& collisionObjects = psi->getCollisionObjects();
00072 for (vector <arm_navigation_msgs::CollisionObject>::const_iterator it = collisionObjects.begin();
00073 it != collisionObjects.end(); it++)
00074 {
00075 const string& objectName = it->id;
00076 if (StringUtil::startsWith(objectName, "table"))
00077 continue;
00078 if (StringUtil::startsWith(objectName, "door"))
00079 continue;
00080 if (StringUtil::startsWith(objectName, "sponge"))
00081 continue;
00082 if (! fillPoseFromState(pose, objectName, numericalFluentCallback))
00083 {
00084 psi->removeObject(objectName);
00085 }
00086 else
00087 {
00088 movableObjects.insert(make_pair(objectName, pose));
00089 }
00090 }
00091 const vector <arm_navigation_msgs::AttachedCollisionObject>& attachedObjects = psi->getAttachedCollisionObjects();
00092 for (vector <arm_navigation_msgs::AttachedCollisionObject>::const_iterator it = attachedObjects.begin(); it != attachedObjects.end(); it++)
00093 {
00094 const string& objectName = it->object.id;
00095 if (! fillPoseFromState(pose, objectName, numericalFluentCallback))
00096 {
00097 psi->removeObject(objectName);
00098 }
00099 else
00100 {
00101 movableObjects.insert(make_pair(objectName, pose));
00102 }
00103 }
00104
00105
00106 PredicateList* predicates = NULL;
00107 if (!predicateCallback(predicates))
00108 {
00109 ROS_ERROR("%s predicateCallback failed.", logName.c_str());
00110 return false;
00111 }
00112 ROS_ASSERT(predicates != NULL);
00113 for (PredicateList::iterator it = predicates->begin(); it != predicates->end(); it++)
00114 {
00115 Predicate p = *it;
00116 if (!p.value)
00117 continue;
00118 if (p.name == "on")
00119 {
00120 ROS_ASSERT(p.parameters.size() == 2);
00121
00122 objectsOnStatic.insert(make_pair(p.parameters.front().value, p.parameters.back().value));
00123 }
00124 else if (p.name == "grasped")
00125 {
00126 ROS_ASSERT(p.parameters.size() == 2);
00127
00128 graspedObjects.insert(make_pair(p.parameters.front().value, p.parameters.back().value));
00129 }
00130 else if (p.name == "door-open")
00131 {
00132 ROS_ASSERT(p.parameters.size() == 1);
00133
00134 openDoors.insert(p.parameters.front().value);
00135 }
00136 }
00137
00138
00139 if (! fillPoseFromState(robotPose, robotLocation, numericalFluentCallback))
00140 {
00141 ROS_ERROR("%s get robot location failed.", logName.c_str());
00142 }
00143 return true;
00144 }
00145
00146 bool TidyupPlanningSceneUpdater::update(const geometry_msgs::Pose& robotPose,
00147 const map<string, geometry_msgs::Pose>& movableObjects,
00148 const map<string, string>& graspedObjects,
00149 const set<string>& openDoors)
00150 {
00151 if (instance == NULL) instance = new TidyupPlanningSceneUpdater();
00152 return instance->update_(robotPose, movableObjects, graspedObjects, openDoors);
00153 }
00154
00155 bool TidyupPlanningSceneUpdater::update_(const geometry_msgs::Pose& robotPose,
00156 const map<string, geometry_msgs::Pose>& movableObjects,
00157 const map<string, string>& graspedObjects,
00158 const set<string>& openDoors)
00159 {
00160 PlanningSceneInterface* psi = PlanningSceneInterface::instance();
00161
00162
00163
00164 ROS_INFO("%s update robot state in planning scene", logName.c_str());
00165 arm_navigation_msgs::RobotState state = psi->getRobotState();
00166 state.multi_dof_joint_state.poses[0] = robotPose;
00167 ArmState::get("/arm_configurations/side_tuck/position/", "right_arm").replaceJointPositions(state.joint_state);
00168 ArmState::get("/arm_configurations/side_tuck/position/", "left_arm").replaceJointPositions(state.joint_state);
00169
00170
00171 for(map<string, geometry_msgs::Pose>::const_iterator movabelObjectIt = movableObjects.begin(); movabelObjectIt != movableObjects.end(); movabelObjectIt++)
00172 {
00173 string object_name = movabelObjectIt->first;
00174 ROS_INFO("%s updating object %s", logName.c_str(), object_name.c_str());
00175
00176 if (psi->getAttachedCollisionObject(object_name) != NULL)
00177 {
00178 psi->detachObjectAndAdd(object_name);
00179 }
00180
00181 if (psi->getCollisionObject(object_name) != NULL)
00182 {
00183 psi->updateObject(object_name, movabelObjectIt->second);
00184 }
00185 else
00186 {
00187 ROS_ERROR("%s object %s does not exist in planning scene.", logName.c_str(), object_name.c_str());
00188 return false;
00189 }
00190 }
00191
00192
00193
00194 for (map<string, string>::const_iterator graspedIt = graspedObjects.begin(); graspedIt != graspedObjects.end(); graspedIt++)
00195 {
00196 const string& objectName = graspedIt->first;
00197 const string& arm = graspedIt->second;
00198 ROS_INFO("%s attaching object %s to arm %s", logName.c_str(), objectName.c_str(), arm.c_str());
00199 ArmState::get("/arm_configurations/side_carry/position/", arm).replaceJointPositions(state.joint_state);
00200 psi->attachObjectToGripper(objectName, arm);
00201 psi->updateObject(objectName, defaultAttachPose);
00202 }
00203 psi->setRobotState(state);
00204
00205
00206 for (map<string, Door>::const_iterator doorIt = doors.begin(); doorIt != doors.end(); doorIt++)
00207 {
00208 if (openDoors.find(doorIt->first) != openDoors.end())
00209 {
00210
00211 psi->updateObject(doorIt->first, doorIt->second.openPose);
00212 }
00213 else
00214 {
00215
00216 psi->updateObject(doorIt->first, doorIt->second.closedPose);
00217 }
00218 }
00219
00220
00221 return psi->sendDiff();
00222 }
00223
00224 bool TidyupPlanningSceneUpdater::fillPoseFromState(geometry_msgs::Pose& pose,
00225 const string& poseName,
00226 numericalFluentCallbackType numericalFluentCallback)
00227 {
00228
00229 ParameterList startParams;
00230 startParams.push_back(Parameter("", "", poseName));
00231 NumericalFluentList nfRequest;
00232 nfRequest.reserve(7);
00233 nfRequest.push_back(NumericalFluent("x", startParams));
00234 nfRequest.push_back(NumericalFluent("y", startParams));
00235 nfRequest.push_back(NumericalFluent("z", startParams));
00236 nfRequest.push_back(NumericalFluent("qx", startParams));
00237 nfRequest.push_back(NumericalFluent("qy", startParams));
00238 nfRequest.push_back(NumericalFluent("qz", startParams));
00239 nfRequest.push_back(NumericalFluent("qw", startParams));
00240
00241
00242 NumericalFluentList* nfRequestP = &nfRequest;
00243 if (!numericalFluentCallback(nfRequestP))
00244 {
00245 ROS_ERROR("fillPoseFromState failed for object: %s", poseName.c_str());
00246 return false;
00247 }
00248
00249
00250 pose.position.x = nfRequest[0].value;
00251 pose.position.y = nfRequest[1].value;
00252 pose.position.z = nfRequest[2].value;
00253 pose.orientation.x = nfRequest[3].value;
00254 pose.orientation.y = nfRequest[4].value;
00255 pose.orientation.z = nfRequest[5].value;
00256 pose.orientation.w = nfRequest[6].value;
00257 return true;
00258 }
00259
00260 void TidyupPlanningSceneUpdater::loadDoorPoses(const string& doorLocationFileName)
00261 {
00262 GeometryPoses locations = GeometryPoses();
00263 ROS_ASSERT_MSG(locations.load(doorLocationFileName), "Could not load locations from \"%s\".", doorLocationFileName.c_str());
00264 const std::map<std::string, geometry_msgs::PoseStamped>& poses = locations.getPoses();
00265 for(std::map<std::string, geometry_msgs::PoseStamped>::const_iterator posesIterator = poses.begin(); posesIterator != poses.end(); posesIterator++)
00266 {
00267 string name = posesIterator->first;
00268 if (StringUtil::startsWith(name, "door"))
00269 {
00270 string doorName;
00271 bool open = false;
00272 if(StringUtil::endsWith(name, "_closed"))
00273 {
00274 doorName = name.substr(0, name.length()-7);
00275 }
00276 else if(StringUtil::endsWith(name, "_open"))
00277 {
00278 doorName = name.substr(0, name.length()-5);
00279 open = true;
00280 }
00281 else
00282 {
00283 ROS_ERROR("navstack planning scene: misformated door location entry %s in file %s", name.c_str(), doorLocationFileName.c_str());
00284 continue;
00285 }
00286 map<string, Door>::iterator doorIterator = doors.find(doorName);
00287 if (doorIterator == doors.end())
00288 {
00289 doors.insert(make_pair(doorName, Door(doorName)));
00290 doorIterator = doors.find(doorName);
00291 }
00292 Door& door = doorIterator->second;
00293 if (open)
00294 {
00295 door.openPose = posesIterator->second.pose;
00296 }
00297 else
00298 {
00299 door.closedPose = posesIterator->second.pose;
00300 }
00301 }
00302 }
00303 }
00304