00001
00002
00003
00004
00005
00006
00007
00008 #ifndef _DEF_ROBOT_TASK
00009 #define _DEF_ROBOT_TASK
00010
00011
00012 #ifndef SINGLE_GOAL
00013 #define MULTI_GOAL
00014 #endif
00015
00016 namespace robot_task{
00017
00018
00019
00020 }
00021
00022 #ifdef SINGLE_GOAL
00023 #include <actionlib/server/simple_action_server.h>
00024 #endif
00025 #ifdef MULTI_GOAL
00026 #include <robot_task/MultiGoalActionServer.h>
00027 #include <map>
00028 #include <boost/thread.hpp>
00029 #endif
00030
00031 #include <robot_task/RobotTaskAction.h>
00032 #include <robot_task/StringOperations.h>
00033 #include <sstream>
00034 #include <iostream>
00035
00036 namespace robot_task{
00037
00038 using namespace std;
00039 using namespace robot_task;
00040 using namespace robot_task_strings;
00041
00042 class RobotTask{
00043 public:
00044 static const int32_t FAIL = 1;
00045 static const int32_t SUCCESS = 0;
00046 static const int32_t PLAN=-1;
00047
00048 protected:
00049 typedef RobotTaskFeedback FEEDBACK;
00050 typedef RobotTaskResult RESULT;
00051 #ifdef SINGLE_GOAL
00052 typedef RobotTaskGoalConstPtr GOAL;
00053 typedef actionlib::SimpleActionServer<RobotTaskAction> Server;
00054 #endif
00055 #ifdef MULTI_GOAL
00056 typedef actionlib::MGActionServer<RobotTaskAction>::GoalHandle GOAL;
00057 typedef actionlib::MGActionServer<RobotTaskAction> Server;
00058 #endif
00059
00060 protected:
00061 ros::NodeHandle _node;
00062 Server _server;
00063 string _name;
00064 FEEDBACK _feedback;
00065 RESULT _result;
00066
00067 RobotTask(string name):
00068 _node(),
00069 _server(_node, name, boost::bind(&RobotTask::abstract_task, this, _1), false),
00070 _name(name)
00071 {
00072 _server.start();
00073 ROS_INFO("instance of %s started.",_name.c_str());
00074 }
00075
00076 virtual ~RobotTask(){}
00077
00078 #ifdef SINGLE_GOAL
00079 void finish(const int32_t& success, const std::string& description, const string& plan, bool AbortForUnsuccess = true){
00080 #define GOAL_SUCCESS _server.setSucceeded(_result);
00081 #define GOAL_ABORT _server.setAborted(_result);
00082 #define GOAL_PREEMPTED _server.setPreempted();
00083 #endif
00084 #ifdef MULTI_GOAL
00085 void finish(GOAL goalH, const int32_t& success, const std::string& description, const string& plan, bool AbortForUnsuccess = true){
00086 #define GOAL_SUCCESS _server.setSucceeded(goalH, _result);
00087 #define GOAL_ABORT _server.setAborted(goalH, _result);
00088 #define GOAL_PREEMPTED _server.setPreempted(goalH);
00089 #endif
00090 _result.success = success;
00091 _result.description = description;
00092 if(success <= 0)
00093 {
00094 ROS_INFO("%s: Succeeded. %s", _name.c_str(), description.c_str());
00095 if(success == PLAN){
00096 ROS_INFO("%s: New plan. %s", _name.c_str(), description.c_str());
00097 _result.plan = plan;
00098 }
00099 GOAL_SUCCESS
00100 }else{
00101 if(AbortForUnsuccess){
00102 ROS_INFO("%s: Aborted. %s", _name.c_str(), description.c_str());
00103 GOAL_ABORT
00104 }else{
00105 ROS_INFO("%s: Preempted", _name.c_str());
00106 GOAL_PREEMPTED
00107 }
00108 }
00109 }
00110
00111 class TaskResult{
00112 friend class RobotTask;
00113 protected:
00114 int32_t success;
00115 string plan;
00116 string description;
00117 bool preempted;
00118
00119 TaskResult(bool preempted)
00120 :success(RobotTask::FAIL), plan(""), description("Preempted"), preempted(preempted){}
00121
00122 public:
00123 TaskResult(const string& plan, const std::string& description )
00124 :success(RobotTask::PLAN), plan(plan), description(description), preempted(false){}
00125
00126 TaskResult(const int32_t success, const std::string& description)
00127 :success(success), plan(""), description(description), preempted(false){}
00128
00129
00130 TaskResult(const TaskResult& o)
00131 :success(o.success), plan(o.plan), description(o.description), preempted(o.preempted){ }
00132
00133 static TaskResult PREEMPTED(){ return TaskResult(true); }
00134 static TaskResult FAIL(){ return TaskResult(RobotTask::FAIL,"Unexpected exception"); }
00135 static TaskResult SUCCESS(){ return TaskResult(RobotTask::SUCCESS,"success"); }
00136 };
00137
00138 virtual RobotTask::TaskResult task(const string& name, const string& uid, Arguments& args)=0;
00139
00140 #ifdef MULTI_GOAL
00141 std::map<boost::thread::id,GOAL> goalsByThread;
00142 #endif
00143 bool isPreempt(){
00144 #ifdef SINGLE_GOAL
00145 return (_server.isPreemptRequested() || !ros::ok());
00146 #endif
00147 #ifdef MULTI_GOAL
00148 GOAL goal = goalsByThread[boost::this_thread::get_id()];
00149 return (_server.isPreemptRequested(goal) || !ros::ok());
00150 #endif
00151 }
00152
00153 void sleep(long millisec){
00154 boost::this_thread::sleep(boost::posix_time::millisec(millisec));
00155 }
00156
00157 #ifdef SINGLE_GOAL
00158 void abstract_task(const GOAL &goal){
00159 #endif
00160 #ifdef MULTI_GOAL
00161 void abstract_task(GOAL goal_handle){
00162 goalsByThread[boost::this_thread::get_id()]=goal_handle;
00163 const RobotTaskGoalConstPtr& goal = goal_handle.getGoal();
00164 #endif
00165
00166 ROS_INFO("%s: Start: task name = %s", _name.c_str(), goal->name.c_str());
00167 ROS_INFO("%s: Start: task id = %s", _name.c_str(), goal->uid.c_str());
00168 ROS_INFO("%s: Start: task params = %s", _name.c_str(), goal->parameters.c_str());
00169
00170
00171 Arguments args;
00172 try{
00173 args = parseArguments(goal->parameters);
00174 }catch(...){
00175 ROS_INFO("%s: WARNING: argument parser report about parameters problem.", _name.c_str());
00176 }
00177
00178 RobotTask::TaskResult res = task(goal->name, goal->uid, args);
00179
00180 #ifdef SINGLE_GOAL
00181 finish( res.success, res.description, res.plan, !res.preempted);
00182 #endif
00183 #ifdef MULTI_GOAL
00184 finish( goal_handle, res.success, res.description, res.plan, !res.preempted);
00185 goalsByThread.erase(boost::this_thread::get_id());
00186 #endif
00187 }
00188 };
00189
00190
00191 }
00192
00193 class SSTREAM{
00194 typedef const char* c_str_t;
00195 boost::shared_ptr<std::stringstream> stream;
00196 public:
00197 operator c_str_t()const{ return c_str(); }
00198 c_str_t c_str()const{ if(stream.get()) return stream->str().c_str(); return 0; }
00199 operator std::string()const{ return str(); }
00200 std::string str()const{ if(stream.get()) return stream->str(); return ""; }
00201 SSTREAM(const SSTREAM& str):stream(str.stream){}
00202 SSTREAM():stream(new std::stringstream()){}
00203 template <typename T>
00204 SSTREAM& operator<<(const T& t){ if(stream.get()) *(stream.get()) << t; return *this; }
00205 };
00206 #define STR(X) ((SSTREAM()<<X).c_str())
00207
00208 #endif // _DEF_ROBOT_TASK