putdown_modules.cpp
Go to the documentation of this file.
00001 #include "planner_modules_pr2/putdown_modules.h"
00002 #include "planner_modules_pr2/module_param_cache.h"
00003 //#include "tidyup_utils/arm_state.h"
00004 //#include "tidyup_utils/planning_scene_interface.h"
00005 #include "planner_modules_pr2/tidyup_planning_scene_updater.h"
00006 #include "tidyup_utils/planning_scene_interface.h"
00007 //#include "tidyup_utils/transformer.h"
00008 #include <ros/ros.h>
00009 #include <geometry_msgs/PoseStamped.h>
00010 #include <map>
00011 #include <set>
00012 using std::set;
00013 using std::map;
00014 #include <utility>
00015 using std::pair; using std::make_pair;
00016 //#include <boost/foreach.hpp>
00017 //#ifdef __CDT_PARSER__
00018 //#define forEach(a, b) for(a : b)
00019 //#else
00020 //#define forEach BOOST_FOREACH
00021 //#endif
00022 #include <sys/times.h>
00023 //#include <tf/tf.h>
00024 //#include <tf/transform_listener.h>
00025 #include <arm_navigation_msgs/ArmNavigationErrorCodes.h>
00026 #include <arm_navigation_msgs/convert_messages.h>
00027 //#include <boost/tuple/tuple.hpp>
00028 //#include <boost/tuple/tuple_comparison.hpp>
00029 #include <tidyup_msgs/GetPutdownPose.h>
00030 #include <sstream>
00031 #include "tidyup_utils/stringutil.h"
00032 
00033 VERIFY_CONDITIONCHECKER_DEF(canPutdown);
00034 VERIFY_APPLYEFFECT_DEF(updatePutdownPose);
00035 
00036 string g_WorldFrame;
00037 ros::NodeHandle* g_NodeHandle = NULL;
00038 ros::ServiceClient g_GetPutdownPose;
00039 
00040 ModuleParamCacheString paramCache;
00041 string separator = " ";
00042 
00043 string logName;
00044 geometry_msgs::Pose defaultAttachPose;
00045 
00046 
00047 void putdown_init(int argc, char** argv)
00048 {
00049     ROS_ASSERT(argc == 2);
00050     logName = "[putdownModule]";
00051 
00052     g_NodeHandle = new ros::NodeHandle();
00053     string service_name = "/tidyup/request_putdown_pose";
00054 
00055     while (!ros::service::waitForService(service_name, ros::Duration(3.0)))
00056     {
00057         ROS_ERROR("%s Service %s not available - waiting.", logName.c_str(), service_name.c_str());
00058     }
00059 
00060     g_GetPutdownPose = g_NodeHandle->serviceClient<tidyup_msgs::GetPutdownPose>(service_name, true);
00061     if (!g_GetPutdownPose)
00062     {
00063         ROS_FATAL("%s Could not initialize get putdown service from %s (client name: %s)", logName.c_str(), service_name.c_str(), g_GetPutdownPose.getService().c_str());
00064     }
00065 
00066     // initialize cache
00067     paramCache.initialize("putdown", g_NodeHandle);
00068 
00069     defaultAttachPose.position.x = 0.032;
00070     defaultAttachPose.position.y = 0.015;
00071     defaultAttachPose.position.z = 0.0;
00072     defaultAttachPose.orientation.x = 0.707;
00073     defaultAttachPose.orientation.y = -0.106;
00074     defaultAttachPose.orientation.z = -0.690;
00075     defaultAttachPose.orientation.w = 0.105;
00076 
00077     ROS_INFO("%s Initialized Putdown Module.\n", logName.c_str());
00078 }
00079 
00080 bool callFindPutdownPoseService(tidyup_msgs::GetPutdownPose & srv)
00081 {
00082     if (!g_GetPutdownPose)
00083     {
00084         ROS_ERROR("%s Persistent service connection to %s failed.", logName.c_str(), g_GetPutdownPose.getService().c_str());
00085         // FIXME reconnect - this shouldn't happen.
00086         return false;
00087     }
00088 
00089     // statistics about using the ros service
00090     static double plannerCalls = 0;
00091     static ros::Duration totalCallsTime = ros::Duration(0.0);
00092     plannerCalls += 1.0;
00093     ros::Time callStartTime = ros::Time::now();
00094 
00095     // perform the actual path planner call
00096     if (! g_GetPutdownPose.call(srv))
00097     {
00098         ROS_ERROR("%s Failed to call service %s.", logName.c_str(), g_GetPutdownPose.getService().c_str());
00099         return false;
00100     }
00101     if (g_Debug)
00102     {
00103         ros::Time callEndTime = ros::Time::now();
00104         ros::Duration dt = callEndTime - callStartTime;
00105         totalCallsTime += dt;
00106         ROS_DEBUG("%s ServiceCall took: %f, avg: %f (num %f).", logName.c_str(),
00107                 dt.toSec(), totalCallsTime.toSec()/plannerCalls, plannerCalls);
00108     }
00109 //
00110 //    if (srv.response.error_code.val == arm_navigation_msgs::ArmNavigationErrorCodes::SUCCESS)
00111 //    {
00112 //        ROS_INFO("%s Got a putdown pose.", logName.c_str());
00113 //        return true;
00114 //    }
00115 //
00116 //    ROS_WARN("%s GetPutdownPose failed. Reason: %s (%d)", logName.c_str(),
00117 //            arm_navigation_msgs::armNavigationErrorCodeToString(srv.response.error_code).c_str(),
00118 //            srv.response.error_code.val);
00119     return true;
00120 }
00121 
00122 string writePoseToString(const geometry_msgs::Pose& pose)
00123 {
00124     std::stringstream stream;
00125     stream.precision(0);
00126     stream << std::fixed;
00127     stream << pose.position.x << separator;
00128     stream << pose.position.y << separator;
00129     stream << pose.position.z << separator;
00130     stream << pose.orientation.x << separator;
00131     stream << pose.orientation.y << separator;
00132     stream << pose.orientation.z << separator;
00133     stream << pose.orientation.w << separator;
00134     return stream.str();
00135 }
00136 
00137 bool readPoseFromString(const string cacheValue, geometry_msgs::Pose& pose)
00138 {
00139     std::stringstream stream;
00140     stream << cacheValue;
00141     vector<double> coordinates;
00142     coordinates.resize(7);
00143     for(size_t i = 0; ! stream.eof() && i < coordinates.size(); i++)
00144     {
00145         stream >> coordinates[i];
00146     }
00147     if (!stream.good())
00148         return false;
00149     pose.position.x = coordinates[0];
00150     pose.position.y = coordinates[1];
00151     pose.position.z = coordinates[2];
00152     pose.orientation.x = coordinates[3];
00153     pose.orientation.y = coordinates[4];
00154     pose.orientation.z = coordinates[5];
00155     pose.orientation.w = coordinates[6];
00156     return true;
00157 }
00158 
00159 string createCacheKey(const string& putdownObject,
00160         const string& arm,
00161         const string& staticObject,
00162         const map<string, geometry_msgs::Pose>& movableObjects,
00163         const map<string, string>& objectsOnStatic)
00164 {
00165     ROS_DEBUG("%s createCacheKey %s %s %s", logName.c_str(), putdownObject.c_str(), arm.c_str(), staticObject.c_str());
00166     std::stringstream stream;
00167     stream.precision(0);
00168     stream << std::fixed << putdownObject << arm << staticObject;
00169     for (map<string, string>::const_iterator objectIt = objectsOnStatic.begin(); objectIt != objectsOnStatic.end(); objectIt++)
00170     {
00171         ROS_DEBUG("%s object %s on %s", logName.c_str(), objectIt->first.c_str(), objectIt->second.c_str());
00172         if (objectIt->second == staticObject)
00173         {
00174             const geometry_msgs::Pose& pose = movableObjects.find(objectIt->first)->second;
00175             // the actual values don't matter as long as they are unique for this object
00176             // cannot use doubles here, as param keys are not allowed to contain '.'
00177             std::string poseParamString = createPoseParamString(pose);
00178             stream << poseParamString;
00179         }
00180     }
00181     return stream.str();
00182 }
00183 
00184 bool findPutdownPose(const ParameterList & parameterList,
00185         predicateCallbackType predicateCallback,
00186         numericalFluentCallbackType numericalFluentCallback,
00187         geometry_msgs::Pose& putdown_pose)
00188 {
00189     // (canPutdown ?o - movable_object ?a - arm ?s - static_object ?g - manipulation_location)
00190     ROS_ASSERT(parameterList.size() == 4);
00191     Parameter putdown_object = parameterList[0];
00192     Parameter arm = parameterList[1];
00193     Parameter static_object = parameterList[2];
00194     Parameter robot_location = parameterList[3];
00195 
00196     // read state
00197     geometry_msgs::Pose robotPose;
00198     map<string, geometry_msgs::Pose> movableObjects;
00199     map<string, string> graspedObjects;
00200     map<string, string> objectsOnStatic;
00201     set<string> openDoors;
00202     arm_navigation_msgs::PlanningScene world = PlanningSceneInterface::instance()->getCurrentScene();
00203     if (! TidyupPlanningSceneUpdater::readState(robot_location.value, predicateCallback, numericalFluentCallback, robotPose, movableObjects, graspedObjects, objectsOnStatic, openDoors))
00204     {
00205         ROS_ERROR("%s read state failed.", logName.c_str());
00206         return false;
00207     }
00208 
00209     tidyup_msgs::GetPutdownPose srv;
00210     srv.request.static_object = static_object.value;
00211     srv.request.putdown_object = putdown_object.value;
00212     srv.request.arm = arm.value;
00213     ROS_INFO("%s putdown request: %s, %s, %s, %s", logName.c_str(), parameterList[0].value.c_str(), parameterList[1].value.c_str(), parameterList[2].value.c_str(), parameterList[3].value.c_str());
00214 
00215     string cacheKey = createCacheKey(srv.request.putdown_object, srv.request.arm, srv.request.static_object, movableObjects, objectsOnStatic);
00216     ROS_DEBUG("%s cacheKey: %s", logName.c_str(), cacheKey.c_str());
00217     // retrieved cached result
00218     string cacheValue;
00219     if (paramCache.get(cacheKey, cacheValue))
00220     {
00221         // cache hit. either 'impossible' or a valid pose
00222         if (cacheValue == "impossible")
00223         {
00224             ROS_DEBUG("%s cache hit: impossible", logName.c_str());
00225             return false;
00226         }
00227         else
00228         {
00229             if (! readPoseFromString(cacheValue, putdown_pose))
00230             {
00231                 ROS_ERROR("%s could not read cached value. cache may be corrupt.", logName.c_str());
00232                 return false;
00233             }
00234             ROS_DEBUG("%s cache hit: pose from cache", logName.c_str());
00235             return true;
00236         }
00237     }
00238 
00239     // no cache entry, set planning scene
00240     PlanningSceneInterface::instance()->resetPlanningScene();
00241     ROS_DEBUG("%s set planning scene", logName.c_str());
00242     if (! TidyupPlanningSceneUpdater::update(robotPose, movableObjects, graspedObjects, openDoors))
00243     {
00244         ROS_ERROR("%s update planning scene failed.", logName.c_str());
00245         return false;
00246     }
00247 
00248     // set planning scene in server call
00249     srv.request.planning_scene = PlanningSceneInterface::instance()->getCurrentScene();
00250 
00251     // call putdown service
00252     ROS_INFO("%s call putdown service", logName.c_str());
00253     if (! callFindPutdownPoseService(srv))
00254     {
00255         ROS_ERROR("%s service call failed", logName.c_str());
00256         return false;
00257     }
00258     if (srv.response.error_code.val == srv.response.error_code.PLANNING_FAILED)
00259     {
00260         ROS_INFO("%s service returned: impossible", logName.c_str());
00261         paramCache.set(cacheKey, "impossible", true);
00262         return false;
00263     }
00264     if  (srv.response.error_code.val == srv.response.error_code.SUCCESS)
00265     {
00266         // insert results into cache
00267         ROS_INFO("%s service returned: pose found, adding to cache", logName.c_str());
00268         putdown_pose = srv.response.putdown_pose.pose;
00269         paramCache.set(cacheKey, writePoseToString(putdown_pose), true);
00270         return true;
00271     }
00272 
00273     ROS_ERROR("%s GetPutdownPose failed. Reason: %s (%d)", logName.c_str(),
00274             arm_navigation_msgs::armNavigationErrorCodeToString(srv.response.error_code).c_str(),
00275             srv.response.error_code.val);
00276     return false;
00277 }
00278 
00279 
00280 double canPutdown(const ParameterList & parameterList,
00281         predicateCallbackType predicateCallback,
00282         numericalFluentCallbackType numericalFluentCallback,
00283         int relaxed)
00284 {
00285     if (relaxed != 0)
00286     {
00287         // skip computation for heuristic
00288         return 0;
00289     }
00290     if (g_Debug)
00291     { // prevent spamming ROS_DEBUG calls unless we really want debug
00292         // debugging raw planner calls
00293         static unsigned int calls = 0;
00294         calls++;
00295         if (calls % 10000 == 0)
00296         {
00297             ROS_DEBUG("%s Got %d putdown module calls.\n", logName.c_str(), calls);
00298         }
00299     }
00300 
00301     geometry_msgs::Pose putdownPose;
00302     if (! findPutdownPose(parameterList, predicateCallback, numericalFluentCallback, putdownPose))
00303     {
00304         return INFINITE_COST;
00305     }
00306     return 0;
00307 }
00308 
00309 int updatePutdownPose(const ParameterList & parameterList, predicateCallbackType predicateCallback,
00310         numericalFluentCallbackType numericalFluentCallback, std::vector<double> & writtenVars)
00311 {
00312     geometry_msgs::Pose putdownPose;
00313     if (! findPutdownPose(parameterList, predicateCallback, numericalFluentCallback, putdownPose))
00314     {
00315         return 1;
00316     }
00317     // write the pose to state:
00318     writtenVars[0] = putdownPose.position.x;
00319     writtenVars[1] = putdownPose.position.y;
00320     writtenVars[2] = putdownPose.position.z;
00321     writtenVars[3] = putdownPose.orientation.x;
00322     writtenVars[4] = putdownPose.orientation.y;
00323     writtenVars[5] = putdownPose.orientation.z;
00324     writtenVars[6] = putdownPose.orientation.w;
00325     return 0;
00326 }
00327 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends Defines


planner_modules_pr2
Author(s): Christian Dornhege, Andreas Hertle
autogenerated on Wed Dec 26 2012 15:49:38