Go to the documentation of this file.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 #include <ros/ros.h>
00032 #include <std_msgs/String.h>
00033 #include <std_srvs/Empty.h>
00034 #include <geometry_msgs/PointStamped.h>
00035 #include <geometry_msgs/PoseStamped.h>
00036 #include <geometry_msgs/Twist.h>
00037 #include <move_base_msgs/MoveBaseAction.h>
00038 #include <actionlib/client/simple_action_client.h>
00039 #include <tf/tf.h>
00040 #include <tf/transform_listener.h>
00041
00042 #include <yaml-cpp/yaml.h>
00043
00044 #include <vector>
00045 #include <fstream>
00046 #include <string>
00047
00048 #include <visualization_msgs/MarkerArray.h>
00049
00050 #ifdef NEW_YAMLCPP
00051 template<typename T>
00052 void operator >> (const YAML::Node& node, T& i)
00053 {
00054 i = node.as<T>();
00055 }
00056 #endif
00057
00058 class WaypointsNavigation{
00059 public:
00060 WaypointsNavigation() :
00061 has_activate_(false),
00062 is_stop_(false),
00063 in_stop_(false),
00064 move_base_action_("move_base", true),
00065 rate_(10),
00066 last_moved_time_(0)
00067 {
00068 while((move_base_action_.waitForServer(ros::Duration(1.0)) == false) && (ros::ok() == true))
00069 {
00070 ROS_INFO("Waiting...");
00071 }
00072
00073 ros::NodeHandle private_nh("~");
00074 private_nh.param("robot_frame", robot_frame_, std::string("/base_link"));
00075 private_nh.param("world_frame", world_frame_, std::string("/map"));
00076
00077 double max_update_rate;
00078 private_nh.param("max_update_rate", max_update_rate, 10.0);
00079 rate_ = ros::Rate(max_update_rate);
00080 std::string filename = "";
00081 private_nh.param("filename", filename, filename);
00082 if(filename != ""){
00083 ROS_INFO_STREAM("Read waypoints data from " << filename);
00084 readFile(filename);
00085 }
00086
00087 ros::NodeHandle nh;
00088 syscommand_sub_ = nh.subscribe("syscommand", 1, &WaypointsNavigation::syscommandCallback, this);
00089 cmd_vel_sub_ = nh.subscribe("icart_mini/cmd_vel", 1, &WaypointsNavigation::cmdVelCallback, this);
00090 stop_point_sub_ = nh.subscribe("stop_point",1,&WaypointsNavigation::stopPointCallback, this);
00091 marker_pub_ = nh.advertise<visualization_msgs::MarkerArray>("visualization_marker", 10);
00092 clear_costmaps_srv_ = nh.serviceClient<std_srvs::Empty>("/move_base/clear_costmaps");
00093 }
00094
00095 void syscommandCallback(const std_msgs::String &msg){
00096 if(msg.data == "start"){
00097 has_activate_ = true;
00098 }
00099 if(msg.data == "restart"){
00100 has_restart_ = true;
00101 ROS_INFO_STREAM("restart command received");
00102 }
00103 }
00104
00105 void cmdVelCallback(const geometry_msgs::Twist &msg){
00106 if(msg.linear.x > -0.001 && msg.linear.x < 0.001 &&
00107 msg.linear.y > -0.001 && msg.linear.y < 0.001 &&
00108 msg.linear.z > -0.001 && msg.linear.z < 0.001 &&
00109 msg.angular.x > -0.001 && msg.angular.x < 0.001 &&
00110 msg.angular.y > -0.001 && msg.angular.y < 0.001 &&
00111 msg.angular.z > -0.001 && msg.angular.z < 0.001){
00112
00113 ROS_INFO("command velocity all zero");
00114 }else{
00115 last_moved_time_ = ros::Time::now().toSec();
00116 }
00117 }
00118
00119 void stopPointCallback(const geometry_msgs::PointStamped &msg){
00120 is_stop_ = true;
00121 stop_point_.point.x = msg.point.x;
00122 stop_point_.point.y = msg.point.y;
00123 stop_point_.point.z = msg.point.z;
00124 }
00125
00126 bool readFile(const std::string &filename){
00127 waypoints_.clear();
00128 try{
00129 std::ifstream ifs(filename.c_str(), std::ifstream::in);
00130 if(ifs.good() == false){
00131 return false;
00132 }
00133
00134 YAML::Node node;
00135
00136 #ifdef NEW_YAMLCPP
00137 node = YAML::Load(ifs);
00138 #else
00139 YAML::Parser parser(ifs);
00140 parser.GetNextDocument(node);
00141 #endif
00142
00143 #ifdef NEW_YAMLCPP
00144 const YAML::Node &wp_node_tmp = node["waypoints"];
00145 const YAML::Node *wp_node = wp_node_tmp ? &wp_node_tmp : NULL;
00146 #else
00147 const YAML::Node *wp_node = node.FindValue("waypoints");
00148 #endif
00149
00150 if(wp_node != NULL){
00151 for(int i=0; i < wp_node->size(); i++){
00152 geometry_msgs::PointStamped point;
00153
00154 (*wp_node)[i]["point"]["x"] >> point.point.x;
00155 (*wp_node)[i]["point"]["y"] >> point.point.y;
00156 (*wp_node)[i]["point"]["z"] >> point.point.z;
00157
00158 waypoints_.push_back(point);
00159
00160 }
00161 }else{
00162 return false;
00163 }
00164
00165 #ifdef NEW_YAMLCPP
00166 const YAML::Node &fp_node_tmp = node["finish_pose"];
00167 const YAML::Node *fp_node = fp_node_tmp ? &fp_node_tmp : NULL;
00168 #else
00169 const YAML::Node *fp_node = node.FindValue("finish_pose");
00170 #endif
00171
00172 if(fp_node != NULL){
00173 (*fp_node)["pose"]["position"]["x"] >> finish_pose_.position.x;
00174 (*fp_node)["pose"]["position"]["y"] >> finish_pose_.position.y;
00175 (*fp_node)["pose"]["position"]["z"] >> finish_pose_.position.z;
00176
00177 (*fp_node)["pose"]["orientation"]["x"] >> finish_pose_.orientation.x;
00178 (*fp_node)["pose"]["orientation"]["y"] >> finish_pose_.orientation.y;
00179 (*fp_node)["pose"]["orientation"]["z"] >> finish_pose_.orientation.z;
00180 (*fp_node)["pose"]["orientation"]["w"] >> finish_pose_.orientation.w;
00181 }else{
00182 return false;
00183 }
00184
00185 }catch(YAML::ParserException &e){
00186 return false;
00187
00188 }catch(YAML::RepresentationException &e){
00189 return false;
00190 }
00191
00192 return true;
00193 }
00194
00195 bool shouldSendGoal(){
00196 bool ret = true;
00197 actionlib::SimpleClientGoalState state = move_base_action_.getState();
00198 if((state != actionlib::SimpleClientGoalState::ACTIVE) &&
00199 (state != actionlib::SimpleClientGoalState::PENDING) &&
00200 (state != actionlib::SimpleClientGoalState::RECALLED) &&
00201 (state != actionlib::SimpleClientGoalState::PREEMPTED))
00202 {
00203 ret = false;
00204 }
00205
00206 if(waypoints_.empty()){
00207 ret = false;
00208 }
00209
00210 return ret;
00211 }
00212
00213 bool navigationFinished(){
00214 return move_base_action_.getState() == actionlib::SimpleClientGoalState::SUCCEEDED;
00215 }
00216
00217 bool onNavigationPoint(const geometry_msgs::Point &dest, double dist_err = 0.8){
00218 tf::StampedTransform robot_gl = getRobotPosGL();
00219
00220 const double wx = dest.x;
00221 const double wy = dest.y;
00222 const double rx = robot_gl.getOrigin().x();
00223 const double ry = robot_gl.getOrigin().y();
00224 const double dist = std::sqrt(std::pow(wx - rx, 2) + std::pow(wy - ry, 2));
00225
00226 return dist < dist_err;
00227 }
00228
00229 tf::StampedTransform getRobotPosGL(){
00230 tf::StampedTransform robot_gl;
00231 try{
00232 tf_listener_.lookupTransform(world_frame_, robot_frame_, ros::Time(0.0), robot_gl);
00233 }catch(tf::TransformException &e){
00234 ROS_WARN_STREAM("tf::TransformException: " << e.what());
00235 }
00236
00237 return robot_gl;
00238 }
00239
00240 void sleep(){
00241 rate_.sleep();
00242 ros::spinOnce();
00243 publishMarkers();
00244 }
00245
00246 void startNavigationGL(const geometry_msgs::Point &dest){
00247 geometry_msgs::Pose pose;
00248 pose.position = dest;
00249 pose.orientation = tf::createQuaternionMsgFromYaw(0.0);
00250 startNavigationGL(pose);
00251 }
00252
00253 void startNavigationGL(const geometry_msgs::Pose &dest){
00254 move_base_msgs::MoveBaseGoal move_base_goal;
00255 move_base_goal.target_pose.header.stamp = ros::Time::now();
00256 move_base_goal.target_pose.header.frame_id = world_frame_;
00257 move_base_goal.target_pose.pose.position = dest.position;
00258 move_base_goal.target_pose.pose.orientation = dest.orientation;
00259
00260 move_base_action_.sendGoal(move_base_goal);
00261 }
00262
00263 void publishMarkers(){
00264 visualization_msgs::MarkerArray markers_array;
00265 for(int i=0; i < waypoints_.size(); i++){
00266 visualization_msgs::Marker marker, label;
00267 marker.header.frame_id = world_frame_;
00268 marker.header.stamp = ros::Time::now();
00269 marker.scale.x = 0.2;
00270 marker.scale.y = 0.2;
00271 marker.scale.z = 0.2;
00272 marker.pose.position.z = marker.scale.z / 2.0;
00273 marker.color.r = 0.8f;
00274 marker.color.g = 0.2f;
00275 marker.color.b = 0.2f;
00276
00277 std::stringstream name;
00278 name << "waypoint " << i;
00279 marker.ns = name.str();
00280 marker.id = i;
00281 marker.pose.position.x = waypoints_[i].point.x;
00282 marker.pose.position.y = waypoints_[i].point.y;
00283 marker.type = visualization_msgs::Marker::SPHERE;
00284 marker.action = visualization_msgs::Marker::ADD;
00285 marker.color.a = 1.0f;
00286 markers_array.markers.push_back(marker);
00287
00288
00289 }
00290 marker_pub_.publish(markers_array);
00291 }
00292
00293 void run(){
00294 while(ros::ok()){
00295 if(has_activate_){
00296 std::vector<geometry_msgs::PointStamped>::iterator waypoints_it = waypoints_.begin();
00297 for(waypoints_it; waypoints_it != waypoints_.end(); ++waypoints_it){
00298 if(!ros::ok()) break;
00299
00300 if(is_stop_ && !in_stop_){
00301 ROS_INFO_STREAM("waypoint = " << *waypoints_it);
00302 waypoints_.insert(waypoints_it, stop_point_);
00303 ROS_INFO_STREAM("Stop point received");
00304 is_stop_ = false;
00305 in_stop_ = true;
00306 }
00307
00308 startNavigationGL(waypoints_it->point);
00309 double start_nav_time = ros::Time::now().toSec();
00310 while(!onNavigationPoint(waypoints_it->point)){
00311 double time = ros::Time::now().toSec();
00312 if(time - start_nav_time > 10.0 && time - last_moved_time_ > 10.0){
00313 ROS_WARN("Resend the navigation goal.");
00314 std_srvs::Empty empty;
00315 clear_costmaps_srv_.call(empty);
00316 startNavigationGL(waypoints_it->point);
00317 start_nav_time = time;
00318 }
00319 actionlib::SimpleClientGoalState state = move_base_action_.getState();
00320 sleep();
00321 }
00322 ROS_INFO("waypoint goal");
00323
00324 ROS_INFO_STREAM("waypoint = " << *waypoints_it);
00325 if(!is_stop_ && in_stop_ ){
00326 while(!has_restart_){
00327 sleep();
00328 ROS_INFO_STREAM("Wait for restart");
00329 }
00330 ROS_INFO_STREAM("Restart");
00331 has_restart_ = false;
00332 in_stop_ = false;
00333 }
00334 }
00335 ROS_INFO("waypoints clear");
00336 waypoints_.clear();
00337 startNavigationGL(finish_pose_);
00338 while(!navigationFinished() && ros::ok()) sleep();
00339 has_activate_ = false;
00340 }
00341
00342 sleep();
00343 }
00344 }
00345
00346 private:
00347 actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> move_base_action_;
00348 std::vector<geometry_msgs::PointStamped> waypoints_;
00349 geometry_msgs::PointStamped stop_point_;
00350 geometry_msgs::Pose finish_pose_;
00351 bool has_activate_;
00352 bool is_stop_;
00353 bool in_stop_;
00354 bool has_restart_;
00355 std::string robot_frame_, world_frame_;
00356 tf::TransformListener tf_listener_;
00357 ros::Rate rate_;
00358 ros::Subscriber syscommand_sub_;
00359 ros::Subscriber cmd_vel_sub_;
00360 ros::Subscriber stop_point_sub_;
00361 ros::Publisher marker_pub_;
00362 ros::ServiceClient clear_costmaps_srv_;
00363 double last_moved_time_;
00364 };
00365
00366 int main(int argc, char *argv[]){
00367 ros::init(argc, argv, ROS_PACKAGE_NAME);
00368 WaypointsNavigation w_nav;
00369 w_nav.run();
00370
00371 return 0;
00372 }