00001
00009 #include <ros/ros.h>
00010 #include <tf/transform_listener.h>
00011 #include <std_msgs/String.h>
00012 #include <std_msgs/Bool.h>
00013 #include <std_srvs/Empty.h>
00014 #include <geometry_msgs/PoseStamped.h>
00015 #include <actionlib/client/simple_action_client.h>
00016 #include <actionlib_msgs/GoalStatus.h>
00017 #include <move_base_msgs/MoveBaseAction.h>
00018 #include <stdio.h>
00019 #include <string>
00020 #include <sstream>
00021 #include <open_door_detector/detect_open_door.h>
00022
00023
00024 ros::Time last_button_msg_time;
00025 int current_goal = 0;
00026
00027
00028 void createPoseFromParams(std::string param_name, geometry_msgs::PoseStamped* pose);
00029 void buttonCb(std_msgs::Bool msg);
00030 bool last_button_state = false;
00031 void createOffsetPose(geometry_msgs::PoseStamped* goal, float posX_off, float posY_off, float rotW_off);
00032
00033
00034 float posX_off;
00035 float posY_off;
00036 float rotW_off;
00037 float angle;
00038 float dist;
00039 float width;
00040
00041
00042
00043
00044
00045
00046 enum state {
00047 START, START_POS, WAIT_BUTTON, WAIT_ELEVATOR, DRIVE_DOOR, DRIVE_IN, ROTATION
00048 };
00049
00050 int main(int argc, char** argv) {
00051
00052
00053 ros::init(argc, argv, "state_machine_elevator");
00054 ros::NodeHandle nh;
00055 ros::Rate loop_rate(10);
00056
00057
00058 ros::Publisher speech_pub = nh.advertise<std_msgs::String>("/speech", 1);
00059
00060
00061 ros::Subscriber button_sub = nh.subscribe<std_msgs::Bool>("/pushed", 1, buttonCb);
00062
00063
00064 actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> client("move_base", true);
00065
00066
00067 ros::Time ask_time;
00068 last_button_msg_time = ros::Time(0);
00069
00070 move_base_msgs::MoveBaseGoal goal;
00071 goal.target_pose.header.frame_id = "map";
00072
00073
00074 state st = START;
00075
00076
00077 ros::Duration(10).sleep();
00078
00079
00080 tf::TransformListener listener;
00081 tf::StampedTransform transform;
00082
00083 geometry_msgs::PoseStamped door_pos;
00084
00085
00086
00087
00088 while(ros::ok()) {
00089
00090
00091
00092 switch(st) {
00093 case START: {
00094 ROS_INFO("START");
00095 createPoseFromParams("start", &(goal.target_pose));
00096 client.sendGoal(goal);
00097
00098 st=START_POS;
00099 ROS_INFO("Switching to state %d", st);
00100 break;
00101
00102 }
00103
00104 case START_POS: {
00105
00106
00107
00108 if (client.getState() == actionlib::SimpleClientGoalState::SUCCEEDED) {
00109 st = WAIT_BUTTON;
00110 ROS_INFO("Reached start position");
00111 ROS_INFO("Switching to state %d", st);
00112 }
00113
00114 break;
00115 }
00116 case WAIT_BUTTON: {
00117
00118
00119 std_msgs::String say_callelevator;
00120 say_callelevator.data = "Please call Elevator";
00121 speech_pub.publish(say_callelevator);
00122
00123
00124 if(last_button_state) {
00125 st = WAIT_ELEVATOR;
00126 ROS_INFO("Waiting for elevator");
00127 ROS_INFO("Switching to state %d", st);
00128
00129 }
00130 break;
00131 }
00132
00133 case WAIT_ELEVATOR: {
00134
00135
00136
00137 ros::ServiceClient client = nh.serviceClient<open_door_detector::detect_open_door>("detect_open_door");
00138 ros::ServiceClient mapclient = nh.serviceClient<std_srvs::Empty>("move_base/clear_costmaps");
00139 open_door_detector::detect_open_door srv;
00140 std_srvs::Empty mapSrv;
00141
00142
00143 ros::param::get("/goals/doorparams/apertureangle", angle);
00144 ros::param::get("/goals/doorparams/walldistance", dist);
00145 ros::param::get("/goals/doorparams/mindoorwidth", width);
00146
00147
00148
00149
00150 srv.request.aperture_angle = angle;
00151 srv.request.wall_distance = dist;
00152 srv.request.min_door_width = width;
00153
00154
00155 if (client.call(srv)){
00156
00157 door_pos = srv.response.door_pos;
00158
00159 } else {
00160 ROS_ERROR("Failed to call service detect_open_door");
00161 return 1;
00162
00163 }
00164 posX_off = door_pos.pose.position.x;
00165 posY_off = door_pos.pose.position.y;
00166
00167 if(posX_off != 0 || posY_off != 0) {
00168 ros::Duration(2).sleep();
00169 if (client.call(srv)){
00170
00171 door_pos = srv.response.door_pos;
00172
00173 } else {
00174 ROS_ERROR("Failed to call service detect_open_door");
00175 return 1;
00176
00177 }
00178 posX_off = door_pos.pose.position.x;
00179 posY_off = door_pos.pose.position.y;
00180 if(posX_off != 0 || posY_off != 0) {
00181 st = DRIVE_DOOR;
00182 ROS_INFO("posX is: %f", posX_off);
00183 ROS_INFO("posY is: %f", posY_off);
00184 mapclient.call(mapSrv);
00185 ros::Duration(0.5).sleep();
00186 }
00187 }
00188
00189
00190 ROS_INFO("Driving to Door");
00191 ROS_INFO("Switching to state %d", st);
00192
00193
00194
00195 break;
00196 }
00197
00198 case DRIVE_DOOR: {
00199
00200 createOffsetPose(&(goal.target_pose), posX_off, posY_off, rotW_off);
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 client.sendGoal(goal);
00220 st=DRIVE_IN;
00221
00222 break;
00223 }
00224
00225 case DRIVE_IN: {
00226 if (client.getState() == actionlib::SimpleClientGoalState::SUCCEEDED) {
00227
00228 ROS_INFO("Im at the door");
00229
00230 ros::param::get("/goals/endPose/x", posX_off);
00231 ros::param::get("/goals/endPose/y", posY_off);
00232 ros::param::get("/goals/endPose/w", rotW_off);
00233
00234 createOffsetPose(&(goal.target_pose), posX_off, posY_off, rotW_off);
00235 client.sendGoal(goal);
00236 st = ROTATION;
00237 ROS_INFO("Driving into the elevator");
00238 ROS_INFO("Switching to state %d", st);
00239 }
00240
00241 break;
00242
00243 }
00244
00245 case ROTATION: {
00246 if (client.getState() == actionlib::SimpleClientGoalState::SUCCEEDED) {
00247
00248
00249
00250 }
00251 break;
00252 }
00253 }
00254 ros::spinOnce();
00255
00256 }
00257
00258
00259
00260
00261
00262
00263 return 0;
00264 }
00265
00266 void buttonCb(std_msgs::Bool msg) {
00267 last_button_msg_time = ros::Time::now();
00268 last_button_state = msg.data;
00269 }
00270
00281 void createPoseFromParams(std::string param_name, geometry_msgs::PoseStamped* pose) {
00282 pose->header.stamp = ros::Time::now();
00283 ros::param::get("/goals/"+param_name+"/x", pose->pose.position.x);
00284 ros::param::get("/goals/"+param_name+"/y", pose->pose.position.y);
00285 ros::param::get("/goals/"+param_name+"/z", pose->pose.position.z);
00286 ros::param::get("/goals/"+param_name+"/q1", pose->pose.orientation.x);
00287 ros::param::get("/goals/"+param_name+"/q2", pose->pose.orientation.y);
00288 ros::param::get("/goals/"+param_name+"/q3", pose->pose.orientation.z);
00289 ros::param::get("/goals/"+param_name+"/q4", pose->pose.orientation.w);
00290 }
00291
00292 void createOffsetPose(geometry_msgs::PoseStamped* goal, float posX_off, float posY_off, float rotW_off) {
00293 goal->header.stamp = ros::Time::now();
00294 goal->pose.position.x = goal->pose.position.x + posX_off;
00295 goal->pose.position.y= goal->pose.position.y + posY_off;
00296
00297 tf::Quaternion quat(tf::Vector3(0,0,1), rotW_off);
00298 goal->pose.orientation.x = quat.x();
00299 goal->pose.orientation.y = quat.y();
00300 goal->pose.orientation.z = quat.z();
00301 goal->pose.orientation.w = quat.w();
00302
00303 }
00304
00305
00306
00307