multi_move_base_simple.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 * Software License Agreement (BSD License)
00004 *
00005 *  Copyright (c) 2012, ISR University of Coimbra.
00006 *  All rights reserved.
00007 *
00008 *  Redistribution and use in source and binary forms, with or without
00009 *  modification, are permitted provided that the following conditions
00010 *  are met:
00011 *
00012 *   * Redistributions of source code must retain the above copyright
00013 *     notice, this list of conditions and the following disclaimer.
00014 *   * Redistributions in binary form must reproduce the above
00015 *     copyright notice, this list of conditions and the following
00016 *     disclaimer in the documentation and/or other materials provided
00017 *     with the distribution.
00018 *   * Neither the name of the ISR University of Coimbra nor the names of its
00019 *     contributors may be used to endorse or promote products derived
00020 *     from this software without specific prior written permission.
00021 *
00022 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030 *  CAUSED AND ON ANY TH#include <angles/angles.h>EORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033 *  POSSIBILITY OF SUCH DAMAGE.
00034 *
00035 * Author: Gonçalo Cabrita on 03/09/2012
00036 *********************************************************************/
00037 
00038 #include <ros/ros.h>
00039 #include <geometry_msgs/PoseStamped.h>
00040 #include <geometry_msgs/Twist.h>
00041 #include <nav_msgs/Odometry.h>
00042 #include <nav_msgs/OccupancyGrid.h>
00043 #include <tf/tf.h>
00044 #include <tf/transform_listener.h>
00045 #include <tf/message_filter.h>
00046 #include <message_filters/subscriber.h>
00047 #include <angles/angles.h>
00048 #include <visualization_msgs/Marker.h>
00049 
00050 #include <actionlib/server/simple_action_server.h>
00051 #include <move_base_msgs/MoveBaseAction.h>
00052 
00053 //typedefs to help us out with the action server so that we don't hace to type so much
00054 typedef actionlib::SimpleActionServer<move_base_msgs::MoveBaseAction> MoveBaseActionServer;
00055 
00056 MoveBaseActionServer * as;
00057 
00058 ros::NodeHandle * n_ptr;
00059 ros::Publisher * cmd_vel_pub_ptr;
00060 ros::Publisher * marker_pub_ptr;
00061 
00062 nav_msgs::OccupancyGrid map;
00063 
00064 // Simple Navigation States
00065 typedef enum _SimpleNavigationState {
00066     
00067     SN_STOPPED = 1,
00068     SN_MOVING = 2,
00069     SN_ROTATING = 3,
00070     SN_MOVING_AS = 4,
00071     SN_ROTATING_AS = 5
00072     
00073 } SimpleNavigationState;
00074 
00075 // Simple Navigation State
00076 SimpleNavigationState state;
00077 
00078 // tf
00079 tf::TransformListener * tf_listener;
00080 
00081 double distance_travelled;
00082 
00083 // Parameters
00084 std::string global_frame_id;
00085 double rate;
00086 double in_place_angular_velocity;
00087 double max_linear_velocity;
00088 double min_linear_velocity;
00089 double alpha;
00090 double attraction_coefficient;
00091 double repulsion_coefficient_robots;
00092 double repulsion_coefficient_obstacles;
00093 double goal_tolerance;
00094 double angular_threshold;
00095 double repulsion_threshold_robots;
00096 double repulsion_threshold_obstacles;
00097 ros::Duration delay;
00098 double max_distance;
00099 ros::Duration goal_timeout;
00100 
00101 bool visualization;
00102 
00103 int simple_goal = 0;
00104 
00105 // Robot data structure
00106 class Robot
00107 {
00108     public:
00109     Robot(int id) : pose(), prefix()
00110     {
00111         this->id = id;
00112 
00113         prefix = "/robot_";
00114         prefix.append<int>(1, 48+id);
00115     };
00116     
00117     Robot(const Robot& r) : pose(), prefix()
00118     {
00119         id = r.id;
00120         
00121         pose = r.pose;
00122         
00123         odom_sub = r.odom_sub;
00124         tf_filter = r.tf_filter;
00125 
00126         prefix = r.prefix;
00127     };
00128     
00129     // Robot ID
00130     int id;
00131     
00132     // Robot data
00133     geometry_msgs::PoseStamped pose;
00134     
00135     // Subscribers
00136     message_filters::Subscriber<nav_msgs::Odometry> * odom_sub;
00137     tf::MessageFilter<nav_msgs::Odometry> * tf_filter;
00138 
00139     std::string prefix;
00140 };
00141 
00142 // The robots
00143 std::vector<Robot> robots;
00144 
00145 int me;
00146 
00147 bool rotate_in_place;
00148 
00149 double calculateVelocities(double current_x, double current_y, double current_orientation, double goal_x, double goal_y, double * linear_velocity, double * angular_velocity)
00150 {
00151         // Attraction
00152         double G_attr_x = -attraction_coefficient*(current_x - goal_x);
00153         double G_attr_y = -attraction_coefficient*(current_y - goal_y);
00154             
00155         // Repulsion
00156         double G_rep_x = 0.0;
00157         double G_rep_y = 0.0;
00158 
00159         // Robots
00160         for(int i=0 ; i<robots.size() ; i++)
00161         {
00162                 if(i==me) continue;
00163                 
00164                 double distance = sqrt(pow(current_x-robots[i].pose.pose.position.x,2)+pow(current_y-robots[i].pose.pose.position.y,2));
00165                 if(distance <= repulsion_threshold_robots)
00166                 {
00167                         G_rep_x += -repulsion_coefficient_robots*(current_x-robots[i].pose.pose.position.x)*(1/pow(distance,2)-repulsion_threshold_robots/pow(distance,3));
00168                         G_rep_y += -repulsion_coefficient_robots*(current_y-robots[i].pose.pose.position.y)*(1/pow(distance,2)-repulsion_threshold_robots/pow(distance,3));
00169                 }
00170         }
00171 
00172         // Obstacles on the map
00173         int current_x_index = current_x/map.info.resolution;
00174         int current_y_index = current_y/map.info.resolution;
00175 
00176         int rep = ceil(repulsion_threshold_obstacles/map.info.resolution)+1;
00177         for(int i=(current_x_index-rep<0 ? 0 : current_x_index-rep) ; i<(current_x_index+rep>map.info.width ? map.info.width : current_x_index+rep) ; i++)
00178         {
00179                 for(int j=(current_y_index-rep<0 ? 0 : current_y_index-rep) ; j<(current_y_index+rep>map.info.height ? map.info.height : current_y_index+rep) ; j++)
00180                 {
00181                         double distance = sqrt(pow(current_x-i*map.info.resolution,2)+pow(current_y-j*map.info.resolution,2));
00182                         if(map.data[j*map.info.width+i] != 0 && distance <= repulsion_threshold_obstacles)
00183                         {
00184                                 G_rep_x += -repulsion_coefficient_obstacles*(current_x-i*map.info.resolution)*(1/pow(distance,2)-repulsion_threshold_obstacles/pow(distance,3));
00185                                 G_rep_y += -repulsion_coefficient_obstacles*(current_y-j*map.info.resolution)*(1/pow(distance,2)-repulsion_threshold_obstacles/pow(distance,3));
00186                         }
00187                 }
00188         }
00189 
00190         double G_x = G_attr_x + G_rep_x;
00191         double G_y = G_attr_y + G_rep_y;
00192 
00193         double target_orientation = atan2(G_y, G_x);
00194             
00195         *linear_velocity = sqrt(G_x*G_x + G_y*G_y);
00196         if(fabs(*linear_velocity) > max_linear_velocity) *linear_velocity = (*linear_velocity > 0 ? max_linear_velocity : -max_linear_velocity);
00197         if(fabs(*linear_velocity) < min_linear_velocity) *linear_velocity = (*linear_velocity > 0 ? min_linear_velocity : -min_linear_velocity);
00198             
00199         double delta_yaw = angles::shortest_angular_distance(target_orientation, current_orientation);
00200 
00201         *angular_velocity = -alpha*(delta_yaw);
00202 
00203         if(visualization)
00204         {
00205                 visualization_msgs::Marker marker;
00206                 // Set the frame ID and timestamp.  See the TF tutorials for information on these.
00207                 std::string frame_id = robots[me].prefix;
00208                 frame_id.append("/base_link");
00209                 marker.header.frame_id = frame_id;
00210                 marker.header.stamp = ros::Time::now();
00211 
00212                 // Set the namespace and id for this marker.  This serves to create a unique ID
00213                 // Any marker sent with the same namespace and id will overwrite the old one
00214                 marker.ns = "attraction_repulsion_vectors";
00215                 marker.id = robots[me].id;
00216 
00217                 // Set the marker type.  Initially this is CUBE, and cycles between that and SPHERE, ARROW, and CYLINDER
00218                 marker.type = visualization_msgs::Marker::ARROW;
00219 
00220                 // Set the marker action.  Options are ADD and DELETE
00221                 marker.action = visualization_msgs::Marker::ADD;
00222 
00223                 // Set the pose of the marker.  This is a full 6DOF pose relative to the frame/time specified in the header
00224                 marker.pose.position.x = 0.10;
00225                 marker.pose.position.y = 0;
00226                 marker.pose.position.z = 0.10;
00227                 marker.pose.orientation = tf::createQuaternionMsgFromYaw(-1*delta_yaw);
00228 
00229                 // Set the scale of the marker
00230                 marker.scale.x = 0.4;
00231                 marker.scale.y = 0.4;
00232                 marker.scale.z = fabs(*linear_velocity)*0.5/max_linear_velocity;
00233 
00234                 // Set the color -- be sure to set alpha to something non-zero!
00235                 marker.color.r = 1.0f;
00236                 marker.color.g = 1.0f;
00237                 marker.color.b = 0.0f;
00238                 marker.color.a = 1.0;
00239 
00240                 marker.lifetime = ros::Duration();
00241 
00242                 // Publish the marker
00243                 marker_pub_ptr->publish(marker);
00244         }
00245 
00246         return delta_yaw;
00247 }
00248 
00249 void displayGoal(double goal_x, double goal_y)
00250 {
00251         visualization_msgs::Marker goal_marker;
00252         // Set the frame ID and timestamp.  See the TF tutorials for information on these.
00253         goal_marker.header.frame_id = global_frame_id;
00254         goal_marker.header.stamp = ros::Time::now();
00255 
00256         // Set the namespace and id for this marker.  This serves to create a unique ID
00257         // Any marker sent with the same namespace and id will overwrite the old one
00258         goal_marker.ns = "goals";
00259         goal_marker.id = robots[me].id;
00260 
00261         // Set the marker type.  Initially this is CUBE, and cycles between that and SPHERE, ARROW, and CYLINDER
00262         goal_marker.type = visualization_msgs::Marker::CYLINDER;
00263 
00264         // Set the marker action.  Options are ADD and DELETE
00265         goal_marker.action = visualization_msgs::Marker::ADD;
00266 
00267         // Set the pose of the marker.  This is a full 6DOF pose relative to the frame/time specified in the header
00268         goal_marker.pose.position.x = goal_x;
00269         goal_marker.pose.position.y = goal_y;
00270         goal_marker.pose.position.z = 0.0;
00271         goal_marker.pose.orientation = tf::createQuaternionMsgFromYaw(0.0);
00272 
00273         // Set the scale of the marker
00274         goal_marker.scale.x = goal_tolerance*2.0;
00275         goal_marker.scale.y = goal_tolerance*2.0;
00276         goal_marker.scale.z = 0.01;
00277 
00278         // Set the color -- be sure to set alpha to something non-zero!
00279         goal_marker.color.r = 0.0f;
00280         goal_marker.color.g = 1.0f;
00281         goal_marker.color.b = 0.0f;
00282         goal_marker.color.a = 0.5;
00283 
00284         goal_marker.lifetime = ros::Duration();
00285 
00286         // Publish the marker
00287         marker_pub_ptr->publish(goal_marker);
00288 }
00289 
00290 void publishVelocities(double linear_velocity, double angular_velocity)
00291 {
00292         // Send the new velocities to the robot...
00293         geometry_msgs::Twist cmd_vel;
00294         
00295         cmd_vel.linear.x = linear_velocity;
00296         cmd_vel.angular.z = angular_velocity;
00297         cmd_vel_pub_ptr->publish(cmd_vel);
00298 }
00299 
00300 //  ********************* Simple goal *********************
00301 void goalReceived(const geometry_msgs::PoseStamped::ConstPtr& msg)
00302 {
00303     ros::Time start_time = ros::Time::now();
00304     simple_goal++;
00305 
00306     if(state == SN_ROTATING_AS || state == SN_MOVING_AS)
00307     {
00308         ROS_ERROR("MoveBase Simple - %s - Ignoring goal because there is already an ActionServer goal in progress!", __FUNCTION__);
00309         return;
00310     }
00311 
00312     if(msg->header.frame_id != global_frame_id)
00313     {
00314         ROS_ERROR("MoveBase Simple - %s - Ignoring goal because frame_id is not the global frame!", __FUNCTION__);
00315         return;
00316     }
00317 
00318     geometry_msgs::PoseStamped goal = *msg;
00319 
00320     displayGoal(goal.pose.position.x, goal.pose.position.y);
00321 
00322     state = SN_MOVING;
00323     distance_travelled = 0.0;
00324 
00325     ros::Rate r(rate);
00326     while(n_ptr->ok())
00327     {
00328         if(state == SN_ROTATING_AS || state == SN_MOVING_AS || simple_goal>1) return;   
00329 
00330         double linear_velocity;
00331         double angular_velocity;
00332         
00333         double current_orientation = tf::getYaw(robots[me].pose.pose.orientation);
00334         double current_x = robots[me].pose.pose.position.x;
00335         double current_y = robots[me].pose.pose.position.y;
00336 
00337         // If we've been at this for too long...
00338         if(ros::Time::now() - start_time > goal_timeout)
00339         {
00340                 publishVelocities(0.0, 0.0);
00341                 state = SN_STOPPED;
00342                 return;
00343         }
00344         
00345         // If we reached our target position 
00346         if(sqrt((current_x-goal.pose.position.x)*(current_x-goal.pose.position.x)+(current_y-goal.pose.position.y)*(current_y-goal.pose.position.y)) < goal_tolerance)
00347         {
00348                 publishVelocities(0.0, 0.0);
00349                 state = SN_STOPPED;
00350                 simple_goal--;
00351                 return;
00352         }
00353 
00354         // If we travelled more than max distance pause
00355         if(distance_travelled > max_distance) 
00356         {
00357                 publishVelocities(0.0, 0.0);
00358                 distance_travelled = 0.0;
00359                 delay.sleep();
00360         }
00361         
00362         double delta_yaw = calculateVelocities(current_x, current_y, current_orientation, goal.pose.position.x, goal.pose.position.y, &linear_velocity, &angular_velocity);
00363 
00364         // If we are too far from our target orientation rotate in place
00365         if(state == SN_MOVING && fabs(delta_yaw) > angular_threshold)
00366         {
00367                 state = SN_ROTATING;
00368                 distance_travelled = 0.0;
00369                 delay.sleep();
00370         }
00371 
00372         // If we intend to rotate before moving forward...
00373         if(state == SN_ROTATING)
00374         {
00375                 linear_velocity = 0.0;
00376                 angular_velocity = (angular_velocity < 0 ? -in_place_angular_velocity : in_place_angular_velocity);
00377                 if(fabs(delta_yaw) < angular_threshold) angular_velocity = 0.0;
00378         }
00379         
00380         publishVelocities(linear_velocity, angular_velocity);
00381         if(state == SN_ROTATING && fabs(delta_yaw) < angular_threshold)
00382         {
00383                 state = SN_MOVING;
00384                 distance_travelled = 0.0;
00385                 delay.sleep();
00386         }
00387         
00388         ros::spinOnce();
00389         r.sleep();
00390     }
00391 }
00392 //  *******************************************************
00393 
00394 // ********************* Action server goal *********************
00395 void asCallback(const move_base_msgs::MoveBaseGoalConstPtr& move_base_goal)
00396 {
00397         ros::Time start_time = ros::Time::now();
00398 
00399         if(move_base_goal->target_pose.header.frame_id.compare(global_frame_id) != 0)
00400         {
00401                 as->setAborted(move_base_msgs::MoveBaseResult(), "Aborting on goal because frame_id is not the global frame!");
00402                 return;
00403         }
00404 
00405         geometry_msgs::PoseStamped goal = move_base_goal->target_pose;
00406 
00407         displayGoal(goal.pose.position.x, goal.pose.position.y);
00408         
00409         state = SN_MOVING_AS;
00410         distance_travelled = 0.0;
00411 
00412         ros::Rate r(rate);
00413         while(n_ptr->ok())
00414         {
00415                 if(as->isPreemptRequested())
00416                 {
00417                         publishVelocities(0.0, 0.0);
00418                         as->setPreempted();
00419                         state = SN_STOPPED;
00420                         return;
00421                 }
00422 
00423                 double linear_velocity;
00424                 double angular_velocity;
00425         
00426                 double current_orientation = tf::getYaw(robots[me].pose.pose.orientation);
00427                 double current_x = robots[me].pose.pose.position.x;
00428                 double current_y = robots[me].pose.pose.position.y;
00429 
00430                 // If we've been at this for too long...
00431                 if(ros::Time::now() - start_time > goal_timeout)
00432                 {
00433                         publishVelocities(0.0, 0.0);
00434                         as->setAborted();
00435                         state = SN_STOPPED;
00436                         return;
00437                 }
00438         
00439                 // If we reached our target position 
00440                 if(sqrt((current_x-goal.pose.position.x)*(current_x-goal.pose.position.x)+(current_y-goal.pose.position.y)*(current_y-goal.pose.position.y)) < goal_tolerance)
00441                 {
00442                         publishVelocities(0.0, 0.0);
00443                         as->setSucceeded();
00444                         state = SN_STOPPED;
00445                         return;
00446                 }
00447 
00448                 // If we travelled more than max distance pause
00449                 if(distance_travelled > max_distance) 
00450                 {
00451                         publishVelocities(0.0, 0.0);
00452                         distance_travelled = 0.0;
00453                         delay.sleep();
00454                 }
00455   
00456                 double delta_yaw = calculateVelocities(current_x, current_y, current_orientation, goal.pose.position.x, goal.pose.position.y, &linear_velocity, &angular_velocity);
00457 
00458                 // If we are too far from our target orientation rotate in place
00459                 if(state == SN_MOVING_AS && fabs(delta_yaw) > angular_threshold)
00460                 {
00461                         state = SN_ROTATING_AS;
00462                         distance_travelled = 0.0;
00463                         delay.sleep();
00464                 }
00465 
00466                 // If we intend to rotate before moving forward...
00467                 if(state == SN_ROTATING_AS)
00468                 {
00469                         linear_velocity = 0.0;
00470                         angular_velocity = (angular_velocity < 0 ? -in_place_angular_velocity : in_place_angular_velocity);
00471                         if(fabs(delta_yaw) < angular_threshold) angular_velocity = 0.0;
00472                 }
00473 
00474                 // Publish feedback
00475                 move_base_msgs::MoveBaseFeedback feedback;
00476 
00477                 feedback.base_position = robots[me].pose;
00478                 as->publishFeedback(feedback);
00479 
00480                 publishVelocities(linear_velocity, angular_velocity);
00481                 if(state == SN_ROTATING_AS && fabs(delta_yaw) < angular_threshold)
00482                 {
00483                         state = SN_MOVING_AS;
00484                         distance_travelled = 0.0;
00485                         delay.sleep();
00486                 }
00487         
00488                 ros::spinOnce();
00489                 r.sleep();
00490         }
00491 }
00492 //  *************************************************************
00493 
00494 void odomCallback(int index, const boost::shared_ptr<const nav_msgs::Odometry>& msg)
00495 {
00496     geometry_msgs::PoseStamped pose;
00497     pose.header.frame_id = msg->header.frame_id;
00498     pose.header.stamp = msg->header.stamp;
00499     pose.pose = msg->pose.pose;
00500 
00501     geometry_msgs::PoseStamped global_frame_id_pose;
00502             
00503     try 
00504     {
00505         // Transform the nose pose into a pose in the map frame
00506         tf_listener->transformPose(global_frame_id, pose, global_frame_id_pose);
00507     }
00508     catch(tf::TransformException &ex) 
00509     {
00510         ROS_ERROR("MoveBase Simple - %s - Error: %s", __FUNCTION__, ex.what());
00511         return;
00512     }
00513 
00514     if(index == me && max_distance > 0.0) distance_travelled += sqrt(pow(robots[index].pose.pose.position.x-global_frame_id_pose.pose.position.x, 2)+pow(robots[index].pose.pose.position.y-global_frame_id_pose.pose.position.y, 2));
00515 
00516     robots[index].pose = global_frame_id_pose;
00517 }
00518 
00519 void mapCallback(const nav_msgs::OccupancyGrid::ConstPtr& msg)
00520 {
00521         map = *msg;
00522 }
00523 
00524 int main(int argc, char** argv)
00525 {
00526     ros::init(argc, argv, "move_base_simple");
00527     
00528     ROS_INFO("Move Base Simple for ROS");
00529     
00530     ros::NodeHandle n;
00531     ros::NodeHandle pn("~");
00532 
00533     n_ptr = &n;
00534 
00535     tf_listener = new tf::TransformListener();
00536 
00537     as = new MoveBaseActionServer(ros::NodeHandle(), "move_base", boost::bind(asCallback, _1), false);
00538     
00539     // Parameters
00540     pn.param<std::string>("global_frame_id", global_frame_id, "/map");
00541 
00542     // Lets load the list of robot ids...raries: libros.
00543     XmlRpc::XmlRpcValue list_of_ids;
00544     if( n.getParam("/list_of_ids", list_of_ids) )
00545     {
00546         int my_id;
00547         if( !pn.getParam("my_id", my_id) )
00548         {
00549             ROS_FATAL("MoveBase Simple -- A list of ids was defined but my_id was not!!!");
00550             ROS_BREAK();
00551         }
00552         
00553         ROS_ASSERT(list_of_ids.getType() == XmlRpc::XmlRpcValue::TypeArray);
00554         
00555         for(int i=0 ; i<list_of_ids.size() ; ++i) 
00556         {
00557             ROS_ASSERT(list_of_ids[i].getType() == XmlRpc::XmlRpcValue::TypeInt);
00558             
00559             robots.push_back(Robot(static_cast<int>(list_of_ids[i])));
00560             
00561             robots[i].odom_sub = new message_filters::Subscriber<nav_msgs::Odometry>();
00562             std::string topic = robots[i].prefix;
00563             topic.append("/odom");
00564             robots[i].odom_sub->subscribe(n, topic, 20);
00565             robots[i].tf_filter = new tf::MessageFilter<nav_msgs::Odometry>(*robots[i].odom_sub, *tf_listener, global_frame_id, 20);
00566             robots[i].tf_filter->registerCallback( boost::bind(odomCallback, i, _1) );
00567             
00568             // Now you can access your data using robots[me].wahetever_you_need!
00569             if(robots[i].id == my_id) me = i;
00570         }
00571     }
00572     else
00573     // If a list of ids is not defined...
00574     {
00575         ROS_FATAL("MoveBase Simple -- A list of ids was not defined!!!");
00576         ROS_BREAK();
00577     }
00578     
00579     pn.param("rate", rate, 3.0);
00580     pn.param("in_place_angular_velocity", in_place_angular_velocity, 3.0);
00581     pn.param("max_linear_velocity", max_linear_velocity, 0.2);
00582     pn.param("min_linear_velocity", min_linear_velocity, 0.05);
00583     pn.param("alpha", alpha, 0.5);
00584     pn.param("attraction_coefficient", attraction_coefficient, 0.5);
00585     pn.param("repulsion_coefficient_robots", repulsion_coefficient_robots, 0.5);
00586     pn.param("repulsion_coefficient_obstacles", repulsion_coefficient_obstacles, 0.5);
00587     pn.param("goal_tolerance", goal_tolerance, 0.10);
00588     pn.param("angular_threshold", angular_threshold, 0.4);
00589     pn.param("repulsion_threshold_robots", repulsion_threshold_robots, 0.5);
00590     pn.param("repulsion_threshold_obstacles", repulsion_threshold_obstacles, 0.0);
00591     double delay_sec = 0.0;
00592     pn.param("delay", delay_sec, 0.0);
00593     delay = ros::Duration(delay_sec);
00594     pn.param("visualization", visualization, false);
00595     pn.param("max_distance", max_distance, 0.5);
00596     double goal_timeout_sec = 0.0;
00597     pn.param("goal_timeout", goal_timeout_sec, 60.0);
00598     goal_timeout = ros::Duration(goal_timeout_sec);
00599 
00600     if(angular_threshold == 0.0)
00601     {
00602         rotate_in_place = false;
00603         ROS_INFO("MoveBase Simple -- Not using in-place rotations.");
00604     }
00605     else
00606     {
00607         rotate_in_place = true;
00608         ROS_INFO("MoveBase Simple -- Using in-place rotations.");
00609     }
00610     
00611     ROS_INFO("Using %s as the global frame.", global_frame_id.c_str());
00612         
00613     // Making all the publishing and subscriptions...
00614     std::string topic;
00615 
00616     topic = robots[me].prefix;
00617     topic.append("/cmd_vel");
00618     ros::Publisher cmd_vel_pub = n.advertise<geometry_msgs::Twist>(topic, 10);
00619     cmd_vel_pub_ptr = &cmd_vel_pub;
00620 
00621     ros::Publisher marker_pub;
00622     if(visualization)
00623     {
00624         marker_pub = n.advertise<visualization_msgs::Marker>("/simple_navigation_markers", 10);
00625         marker_pub_ptr = &marker_pub;
00626     }
00627 
00628     topic = robots[me].prefix;
00629     topic.append("/move_base_simple/goal");
00630     ros::Subscriber goal_sub = n.subscribe<geometry_msgs::PoseStamped>(topic, 10, goalReceived);
00631 
00632     ros::Subscriber map_sub = n.subscribe<nav_msgs::OccupancyGrid>("/map", 1, mapCallback);
00633     
00634     ROS_INFO("idx:%d id:%d %s", me, robots[me].id, topic.c_str());
00635 
00636     state = SN_STOPPED;
00637 
00638     // Start the action server!
00639     as->start();
00640     
00641     ros::spin();
00642 
00643     return(0);
00644 }
00645 
00646 // EOF
00647 


move_base_simple
Author(s): Gonçalo Cabrita
autogenerated on Mon Jan 6 2014 11:25:58