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
00032
00033
00034
00035
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 <tf/tf.h>
00043 #include <angles/angles.h>
00044
00045
00046 typedef enum _SimpleNavigationState {
00047
00048 SN_STOPPED = 1,
00049 SN_MOVING = 2,
00050 SN_ROTATING = 3,
00051 SN_MOVING_AS = 4,
00052 SN_ROTATING_AS = 5
00053
00054 } SimpleNavigationState;
00055
00056
00057 SimpleNavigationState state;
00058
00059
00060 std::string global_frame_id;
00061
00062
00063 geometry_msgs::PoseStamped goal;
00064
00065 nav_msgs::Odometry odom;
00066
00067 bool rotate_in_place;
00068
00069 void goalReceived(const geometry_msgs::PoseStamped::ConstPtr& msg)
00070 {
00071 goal = *msg;
00072
00073 if(rotate_in_place) state = SN_ROTATING;
00074 else state = SN_MOVING;
00075 }
00076
00077 void odomReceived(const nav_msgs::Odometry::ConstPtr& msg)
00078 {
00079 odom = *msg;
00080 }
00081
00082
00083 int main(int argc, char** argv)
00084 {
00085 ros::init(argc, argv, "move_base_simple");
00086
00087 ROS_INFO("Move Base Simple for ROS");
00088
00089 ros::NodeHandle n;
00090 ros::NodeHandle pn("~");
00091
00092
00093 double rate;
00094 double in_place_angular_velocity;
00095 double max_linear_velocity;
00096 double min_linear_velocity;
00097 double alpha;
00098 double attraction_coefficient;
00099 double repulsion_coefficient;
00100 double goal_tolerance;
00101 double angular_threshold;
00102
00103 bool visualization;
00104
00105 pn.param("rate", rate, 3.0);
00106 pn.param("in_place_angular_velocity", in_place_angular_velocity, 3.0);
00107 pn.param("max_linear_velocity", max_linear_velocity, 0.2);
00108 pn.param("min_linear_velocity", min_linear_velocity, 0.05);
00109 pn.param("alpha", alpha, 0.5);
00110 pn.param("attraction_coefficient", attraction_coefficient, 0.5);
00111 pn.param("goal_tolerance", goal_tolerance, 0.10);
00112 pn.param("angular_threshold", angular_threshold, 0.4);
00113 pn.param("visualization", visualization, false);
00114
00115 if(angular_threshold == 0.0)
00116 {
00117 rotate_in_place = false;
00118 ROS_INFO("MoveBase Simple -- Not using in-place rotations.");
00119 }
00120 else
00121 {
00122 rotate_in_place = true;
00123 ROS_INFO("MoveBase Simple -- Using in-place rotations.");
00124 }
00125
00126 pn.param<std::string>("global_frame_id", global_frame_id, "/base_link");
00127
00128 ROS_INFO("MoveBase Simple -- Using %s as the global frame.", global_frame_id.c_str());
00129
00130
00131 ros::Publisher cmd_vel_pub = n.advertise<geometry_msgs::Twist>("/cmd_vel", 10);
00132 ros::Subscriber odom_sub = n.subscribe<nav_msgs::Odometry>("/odom", 20, odomReceived);
00133 ros::Subscriber goal_sub = n.subscribe<geometry_msgs::PoseStamped>("/move_base_simple/goal", 10, goalReceived);
00134
00135 state = SN_STOPPED;
00136
00137
00138 ros::Rate r(rate);
00139 while(n.ok())
00140 {
00141 double linear_velocity = 0.0;
00142 double angular_velocity = 0.0;
00143
00144 double current_orientation = tf::getYaw(odom.pose.pose.orientation);
00145 double current_x = odom.pose.pose.position.x;
00146 double current_y = odom.pose.pose.position.y;
00147
00148
00149 if((state == SN_MOVING || state == SN_MOVING_AS || state == SN_ROTATING || state == SN_ROTATING_AS) && sqrt(pow(current_x-goal.pose.position.x,2)+pow(current_y-goal.pose.position.y,2)) < goal_tolerance)
00150 {
00151 state = SN_STOPPED;
00152 linear_velocity = 0.0;
00153 angular_velocity = 0.0;
00154 }
00155
00156
00157 if(state == SN_MOVING || state == SN_MOVING_AS || state == SN_ROTATING || state == SN_ROTATING_AS)
00158 {
00159 double G_attr_x = -attraction_coefficient*(current_x-goal.pose.position.x);
00160 double G_attr_y = -attraction_coefficient*(current_y-goal.pose.position.y);
00161
00162 double target_orientation = atan2(G_attr_y, G_attr_x);
00163
00164 linear_velocity = sqrt(G_attr_x*G_attr_x + G_attr_y*G_attr_y);
00165 if(fabs(linear_velocity) > max_linear_velocity) linear_velocity = (linear_velocity > 0 ? max_linear_velocity : -max_linear_velocity);
00166 if(fabs(linear_velocity) < min_linear_velocity) linear_velocity = (linear_velocity > 0 ? min_linear_velocity : -min_linear_velocity);
00167
00168 angular_velocity = -alpha*(angles::shortest_angular_distance(target_orientation, current_orientation));
00169
00170
00171 if(state == SN_ROTATING || state == SN_ROTATING_AS)
00172 {
00173 linear_velocity = 0.0;
00174 angular_velocity = (angular_velocity < 0 ? -in_place_angular_velocity : in_place_angular_velocity);
00175
00176 if(fabs(angles::shortest_angular_distance(current_orientation, target_orientation)) < angular_threshold)
00177 {
00178 angular_velocity = 0.0;
00179 if(state == SN_ROTATING) state = SN_MOVING;
00180 else if(state == SN_ROTATING_AS) state = SN_MOVING_AS;
00181 }
00182 }
00183 }
00184
00185
00186 geometry_msgs::Twist cmd_vel;
00187
00188 cmd_vel.linear.x = linear_velocity;
00189 cmd_vel.angular.z = angular_velocity;
00190
00191 cmd_vel_pub.publish(cmd_vel);
00192
00193 ros::spinOnce();
00194 r.sleep();
00195 }
00196
00197 return(0);
00198 }
00199
00200
00201