Go to the documentation of this file.00001 #include <nj_oa_laser/twist_handler.h>
00002
00003 #include <ros/ros.h>
00004
00005 namespace nj_oa_laser
00006 {
00007
00008 TwistHandler::TwistHandler(const double robot_radius) :
00009 robot_radius(robot_radius),
00010 min_distance(1.5 * robot_radius),
00011 long_distance(5 * robot_radius),
00012 short_lateral_distance(2 * robot_radius),
00013 long_lateral_distance(1.5 * short_lateral_distance),
00014 force_turn_left_factor(3),
00015 turnrate_collide(0.4),
00016 vel_close_obstacle(0.5),
00017 turnrate_factor(0.9),
00018 max_linear_velocity(1),
00019 max_angular_velocity(1)
00020 {
00021 }
00022
00034 geometry_msgs::Twist TwistHandler::getTwist(const sensor_msgs::LaserScan& scan)
00035 {
00036 bool collide = false;
00037 bool go_straight = true;
00038 double sum_distance_front = 0;
00039 unsigned int count_distance_front = 0;
00040 double sum_y = 0;
00041 unsigned int count_y = 0;
00042 double integral_collide = 0;
00043
00044 double x;
00045 double y;
00046
00047 double previous_x_yplus = min_distance;
00048 double previous_x_yminus = 0;
00049
00050 for (unsigned int i = 0; i < scan.ranges.size(); ++i)
00051 {
00052 const double angle = angles::normalize_angle(scan.angle_min + i * scan.angle_increment);
00053 if ((angle < -M_PI_2) || (angle > M_PI_2))
00054 {
00055
00056 continue;
00057 }
00058
00059 if ((-M_PI_4 < angle) && (angle < M_PI_4))
00060 {
00061 sum_distance_front += scan.ranges[i];
00062 count_distance_front++;
00063 }
00064
00065 x = scan.ranges[i] * std::cos(angle);
00066 y = scan.ranges[i] * std::sin(angle);
00067
00068 if (x < min_distance)
00069 {
00070 if ((-short_lateral_distance < y) && (y < short_lateral_distance))
00071 {
00072 if (y > 0)
00073 {
00074 integral_collide += y * (previous_x_yplus - x);
00075 previous_x_yplus = x;
00076 }
00077 else
00078 {
00079 integral_collide += y * (x - previous_x_yminus);
00080 previous_x_yminus = x;
00081 }
00082 collide = true;
00083 }
00084 else
00085 {
00086
00087
00088 if (y > 0)
00089 {
00090 integral_collide += short_lateral_distance * (previous_x_yplus - x);
00091 previous_x_yplus = x;
00092 }
00093 else
00094 {
00095 integral_collide -= short_lateral_distance * (x - previous_x_yminus);
00096 previous_x_yminus = x;
00097 }
00098 }
00099 }
00100
00101 if ((x < long_distance) && (-long_lateral_distance < y) && (y < long_lateral_distance))
00102 {
00103 go_straight = false;
00104 }
00105 sum_y += y;
00106 count_y++;
00107 }
00108
00109
00110 integral_collide += short_lateral_distance * previous_x_yplus;
00111 integral_collide -= short_lateral_distance * (min_distance - previous_x_yminus);
00112
00113
00114 const bool force_turn_left = (count_distance_front > 0) &&
00115 (sum_distance_front / count_distance_front < force_turn_left_factor * min_distance);
00116
00117 geometry_msgs::Twist twist;
00118 if (force_turn_left)
00119 {
00120 twist.angular.z = turnrate_collide;
00121 ROS_DEBUG("Mean dist to obstacle within %.3f, force left turn",
00122 force_turn_left_factor * min_distance);
00123 }
00124 else if (collide)
00125 {
00126 twist.linear.x = 0;
00127 if (integral_collide > 0)
00128 {
00129
00130 twist.angular.z = turnrate_collide;
00131 ROS_DEBUG("Obstacle on the right, turn left");
00132 }
00133 else
00134 {
00135 twist.angular.z = -turnrate_collide;
00136 ROS_DEBUG("Obstacle on the left, turn right");
00137 }
00138 }
00139 else if (go_straight)
00140 {
00141 twist.linear.x = max_linear_velocity;
00142 twist.angular.z = 0;
00143 ROS_DEBUG("No obstacle");
00144 }
00145 else
00146 {
00147 twist.linear.x = vel_close_obstacle;
00148 twist.angular.z = turnrate_factor * sum_y / ((double) count_y);
00149 ROS_DEBUG("Obstacle seen within %.3f, %.3f", long_distance, long_lateral_distance);
00150 }
00151
00152 if (twist.linear.x < -max_linear_velocity)
00153 {
00154 twist.linear.x = -max_linear_velocity;
00155 }
00156 else if (twist.linear.x > max_linear_velocity)
00157 {
00158 twist.linear.x = max_linear_velocity;
00159 }
00160
00161 if (twist.angular.z < -max_angular_velocity)
00162 {
00163 twist.angular.z = -max_angular_velocity;
00164 }
00165 else if (twist.angular.z > max_angular_velocity)
00166 {
00167 twist.angular.z = max_angular_velocity;
00168 }
00169
00170 return twist;
00171 }
00172
00173 }
00174