Go to the documentation of this file.00001 #include <carl_safety/teleop_safety.h>
00002
00003 using namespace std;
00004
00005 teleop_safety::teleop_safety()
00006 {
00007
00008 ros::NodeHandle private_nh("~");
00009
00010
00011 cmd_vel_pub = node.advertise<geometry_msgs::Twist>("cmd_vel", 10);
00012 cmd_vel_safety_check = node.subscribe<geometry_msgs::Twist>("/cmd_vel_safety_check", 10, &teleop_safety::cmd_vel_safety_check_cback, this);
00013 scan_sub = node.subscribe<sensor_msgs::LaserScan>("/scan", 10, &teleop_safety::scan_cback, this);
00014 map_sub = node.subscribe<nav_msgs::OccupancyGrid>("/map", 10, &teleop_safety::map_cback, this);
00015 amcl_pose_sub = node.subscribe<geometry_msgs::PoseWithCovarianceStamped>("/amcl_pose", 10, &teleop_safety::amcl_pose_cback, this);
00016
00017
00018 pListener = new (tf::TransformListener);
00019
00020 forward_throttle_safety_factor_base = 0.0;
00021 reverse_throttle_safety_factor_base = 0.0;
00022 }
00023
00024 teleop_safety::~teleop_safety()
00025 {
00026 delete pListener;
00027 }
00028
00029 void teleop_safety::cmd_vel_safety_check_cback(const geometry_msgs::Twist::ConstPtr& cmd)
00030 {
00031 twist = *cmd;
00032 if(twist.linear.x > 0){
00033 twist.linear.x *= forward_throttle_safety_factor_base;
00034 }
00035 else if(twist.linear.x < 0){
00036 twist.linear.x *= reverse_throttle_safety_factor_base;
00037 }
00038 cmd_vel_pub.publish(twist);
00039 }
00040
00041 void teleop_safety::scan_cback(const sensor_msgs::LaserScan::ConstPtr& ptr)
00042 {
00043 static int index = 0;
00044 static double closestDists[2];
00045 geometry_msgs::PointStamped laser_point;
00046 geometry_msgs::PointStamped base_point;
00047
00048 sensor_msgs::LaserScan scan = *ptr;
00049
00050 laser_point.header.frame_id = "hokuyo_link";
00051 laser_point.header.stamp = scan.header.stamp;
00052 laser_point.point.z = 0.0;
00053
00054 int i = 0;
00055 double currentAngle;
00056 double closestDist = scan.range_max;
00057
00058 for(currentAngle = scan.angle_min; currentAngle < scan.angle_max; currentAngle+=scan.angle_increment){
00059
00060 if(scan.ranges[i] < scan.range_min || scan.ranges[i] > scan.range_max || isnan(scan.ranges[i])){
00061 i++;
00062 continue;
00063 }
00064
00065
00066 laser_point.point.x = cos(currentAngle) * scan.ranges[i];
00067 laser_point.point.y = sin(currentAngle) * scan.ranges[i];
00068 try{
00069
00070 pListener->transformPoint("base_link", laser_point, base_point);
00071 }
00072 catch(tf::TransformException& ex){
00073 i++;
00074 continue;
00075 }
00076
00077
00078 double dist = sqrt(pow(base_point.point.x,2.0)+pow(base_point.point.y,2.0));
00079
00080 if(dist < closestDist){
00081 closestDist = dist;
00082 }
00083 i++;
00084 }
00085
00086
00087 closestDists[index] = closestDist;
00088 if(index+1==2) index=0;
00089 else index++;
00090
00091
00092 closestDist = scan.range_max;
00093 for(i = 0; i < 2; i++)
00094 if(closestDists[i] < closestDist)
00095 closestDist = closestDists[i];
00096
00097
00098 if(closestDist < MIN_FORWARD_SAFE_DIST)
00099 forward_throttle_safety_factor_base = 0.0;
00100 else if(closestDist > START_FORWARD_SAFETY_THROTTLE_DIST)
00101 forward_throttle_safety_factor_base = 1.0;
00102 else{
00103 forward_throttle_safety_factor_base = (closestDist-MIN_FORWARD_SAFE_DIST)/(START_FORWARD_SAFETY_THROTTLE_DIST-MIN_FORWARD_SAFE_DIST);
00104 if(forward_throttle_safety_factor_base < 0.1) forward_throttle_safety_factor_base = 0.1;
00105 }
00106
00107 }
00108
00109 void teleop_safety::map_cback(const nav_msgs::OccupancyGrid::ConstPtr& map){
00110
00111 savedMap = *map;
00112 }
00113
00114 void teleop_safety::amcl_pose_cback(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& pose){
00115
00116 static double startTrottleDistMap = START_REVERSE_SAFETY_THROTTLE_DIST/savedMap.info.resolution;
00117 static double minSafeDistMap = MIN_REVERSE_SAFE_DIST/savedMap.info.resolution;
00118
00119
00120 double angle = tf::getYaw(pose->pose.pose.orientation);
00121 double closestDist;
00122
00123
00124 int i = round(pose->pose.pose.position.y/savedMap.info.resolution);
00125 int j = round(pose->pose.pose.position.x/savedMap.info.resolution);
00126
00127 closestDist = startTrottleDistMap;
00128 reverse_throttle_safety_factor_base = 0.8;
00129
00130 for(int x = i - (int)round(startTrottleDistMap); x < i + (int)round(startTrottleDistMap); x++){
00131 for(int y = j - (int)round(startTrottleDistMap); y < j + (int)round(startTrottleDistMap); y++){
00132
00133
00134 if(x >= 0 && x < savedMap.info.height && y >= 0 && y < savedMap.info.width
00135 && savedMap.data[(x*savedMap.info.width) + y] != 0){
00136
00137
00138 double ptAngle = atan2(x-i,y-j);
00139 double dist = sqrt(pow(x-i,2)+pow(y-j,2));
00140
00141 double angleDiff = angle-ptAngle;
00142 while (angleDiff < -M_PI) angleDiff += (2*M_PI);
00143 while (angleDiff > M_PI) angleDiff -= (2*M_PI);
00144
00145
00146 if(dist<=closestDist && angleDiff>(3*M_PI/4)){
00147
00148 closestDist = dist;
00149
00150 if(closestDist < minSafeDistMap)
00151 reverse_throttle_safety_factor_base = 0.0;
00152
00153
00154 else if(closestDist <= startTrottleDistMap){
00155 reverse_throttle_safety_factor_base = (closestDist-minSafeDistMap)/(startTrottleDistMap-minSafeDistMap);
00156 if(reverse_throttle_safety_factor_base < 0.1) reverse_throttle_safety_factor_base = 0.1;
00157 }
00158 }
00159
00160 }
00161 }
00162 }
00163
00164 if(reverse_throttle_safety_factor_base > 0.8) reverse_throttle_safety_factor_base = 0.8;
00165 }
00166
00167 int main(int argc, char **argv)
00168 {
00169
00170 ros::init(argc, argv, "teleop_safety");
00171 teleop_safety t;
00172 ros::Rate loop_rate(60);
00173 while (ros::ok())
00174 {
00175 ros::spinOnce();
00176 loop_rate.sleep();
00177 }
00178
00179 return EXIT_SUCCESS;
00180 }