waypoints_nav.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  * Copyright (c) 2014, Daiki Maekawa and Robot Design and Control Lab.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  *
00011  *  * Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  *  * Redistributions in binary form must reproduce the above
00014  *    copyright notice, this list of conditions and the following
00015  *    disclaimer in the documentation and/or other materials provided
00016  *    with the distribution.
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00018  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00021  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00024  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00025  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00026  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00027  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028  * POSSIBILITY OF SUCH DAMAGE.
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             //ROS_INFO_STREAM("waypoints \n" << waypoints_[i]);
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 }


waypoints_navigation
Author(s): Daiki Maekawa
autogenerated on Wed Nov 4 2015 11:28:10