Go to the documentation of this file.00001 #include <boost/bind.hpp>
00002 #include <string>
00003 #include <ros/ros.h>
00004 #include <turtlesim/Pose.h>
00005
00006 #include <geometry_msgs/Twist.h>
00007 #include <turtlesim/Spawn.h>
00008 #include <std_srvs/Empty.h>
00009 #include <gateway_msgs/GatewayInfo.h>
00010
00011 turtlesim::PoseConstPtr g_pose;
00012 turtlesim::Pose g_goal;
00013 double x_vel = 1.0;
00014 double z_vel = 0.4;
00015 double square_scale = 1.0;
00016
00017 enum State
00018 {
00019 FORWARD,
00020 STOP_FORWARD,
00021 TURN,
00022 STOP_TURN,
00023 };
00024
00025 State g_state = FORWARD;
00026 State g_last_state = FORWARD;
00027 bool g_first_goal_set = false;
00028
00029 #define PI 3.141592
00030
00031 void poseCallback(const turtlesim::PoseConstPtr& pose)
00032 {
00033 g_pose = pose;
00034 }
00035
00036 bool hasReachedGoal()
00037 {
00038 return fabsf(g_pose->x - g_goal.x) < 0.1 && fabsf(g_pose->y - g_goal.y) < 0.1 && fabsf(g_pose->theta - g_goal.theta) < 0.01;
00039 }
00040
00041 bool hasStopped()
00042 {
00043 return g_pose->angular_velocity < 0.0001 && g_pose->linear_velocity < 0.0001;
00044 }
00045
00046 void printGoal()
00047 {
00048 ROS_INFO("New goal [%f %f, %f]", g_goal.x, g_goal.y, g_goal.theta);
00049 }
00050
00051 void commandTurtle(ros::Publisher twist_pub, float linear, float angular)
00052 {
00053
00054 geometry_msgs::Twist twist;
00055 twist.linear.x = linear;
00056 twist.angular.z = angular;
00057 twist_pub.publish(twist);
00058 }
00059
00060 void stopForward(ros::Publisher twist_pub)
00061 {
00062 if (hasStopped())
00063 {
00064 ROS_INFO("Reached goal");
00065 g_state = TURN;
00066 g_goal.x = g_pose->x;
00067 g_goal.y = g_pose->y;
00068 g_goal.theta = fmod(g_pose->theta + PI/2.0, 2*PI);
00069 printGoal();
00070 }
00071 else
00072 {
00073 commandTurtle(twist_pub, 0, 0);
00074 }
00075 }
00076
00077 void stopTurn(ros::Publisher twist_pub)
00078 {
00079 if (hasStopped())
00080 {
00081 ROS_INFO("Reached goal");
00082 g_state = FORWARD;
00083 g_goal.x = cos(g_pose->theta) * 2 * square_scale + g_pose->x;
00084 g_goal.y = sin(g_pose->theta) * 2 * square_scale + g_pose->y;
00085 g_goal.theta = g_pose->theta;
00086 printGoal();
00087 }
00088 else
00089 {
00090 commandTurtle(twist_pub, 0, 0);
00091 }
00092 }
00093
00094
00095 void forward(ros::Publisher twist_pub)
00096 {
00097 if (hasReachedGoal())
00098 {
00099 g_state = STOP_FORWARD;
00100 commandTurtle(twist_pub, 0, 0);
00101 }
00102 else
00103 {
00104 commandTurtle(twist_pub, x_vel, 0.0);
00105 }
00106 }
00107
00108 void turn(ros::Publisher twist_pub)
00109 {
00110 if (hasReachedGoal())
00111 {
00112 g_state = STOP_TURN;
00113 commandTurtle(twist_pub, 0, 0);
00114 }
00115 else
00116 {
00117 commandTurtle(twist_pub, 0.0, z_vel);
00118 }
00119 }
00120
00121 void timerCallback(const ros::TimerEvent&, ros::Publisher twist_pub)
00122 {
00123 if (!g_pose)
00124 {
00125 return;
00126 }
00127
00128 if (!g_first_goal_set)
00129 {
00130 g_first_goal_set = true;
00131 g_state = FORWARD;
00132 g_goal.x = cos(g_pose->theta) * 2 * square_scale + g_pose->x;
00133 g_goal.y = sin(g_pose->theta) * 2 * square_scale + g_pose->y;
00134 g_goal.theta = g_pose->theta;
00135 printGoal();
00136 }
00137
00138 if (g_state == FORWARD)
00139 {
00140 forward(twist_pub);
00141 }
00142 else if (g_state == STOP_FORWARD)
00143 {
00144 stopForward(twist_pub);
00145 }
00146 else if (g_state == TURN)
00147 {
00148 turn(twist_pub);
00149 }
00150 else if (g_state == STOP_TURN)
00151 {
00152 stopTurn(twist_pub);
00153 }
00154 }
00155
00156 int main(int argc, char** argv)
00157 {
00158 ros::init(argc, argv, "turtle_stroll");
00159 std::string simulation_namespace;
00160 ros::NodeHandle pnh("~");
00161 if ( !pnh.getParam("simulation_namespace", simulation_namespace) ) {
00162 ROS_WARN_STREAM("TurtleStroll: simulation_namespace parameter not set.");
00163 }
00164 if ( !pnh.getParam("turtle_x_vel", x_vel) ) {
00165 ROS_WARN_STREAM("TurtleStroll: turtle_x_vel parameter not set.");
00166 }
00167 if ( !pnh.getParam("turtle_z_vel", z_vel) ) {
00168 ROS_WARN_STREAM("TurtleStroll: turtle_z_vel parameter not set.");
00169 }
00170 if ( !pnh.getParam("square_scale", square_scale) ) {
00171 ROS_WARN_STREAM("TurtleStroll: square_size parameter not set.");
00172 }
00173
00174 ros::NodeHandle snh(simulation_namespace);
00175 ros::Subscriber pose_sub = snh.subscribe("pose", 1, poseCallback);
00176 ros::Publisher twist_pub = snh.advertise<geometry_msgs::Twist>("cmd_vel", 1);
00177
00178 ros::NodeHandle nh;
00179 ros::Timer timer = nh.createTimer(ros::Duration(0.016), boost::bind(timerCallback, _1, twist_pub));
00180
00181 ros::spin();
00182 }