$search
00001 /* 00002 * Navigator stop line controller 00003 * 00004 * Copyright (C) 2007, 2010, Austin Robot Technology 00005 * License: Modified BSD Software License Agreement 00006 * 00007 * $Id: stop_line.cc 872 2010-11-28 13:31:07Z jack.oquin $ 00008 */ 00009 00010 #include <art_msgs/ArtVehicle.h> 00011 using art_msgs::ArtVehicle; 00012 00013 #include <art/DARPA_rules.h> 00014 #include "navigator_internal.h" 00015 #include "Controller.h" 00016 #include "course.h" 00017 #include "stop_line.h" 00018 00042 StopLine::StopLine(Navigator *navptr, int _verbose): 00043 Controller(navptr, _verbose) 00044 { 00045 reset_me(); 00046 }; 00047 00048 StopLine::~StopLine() {}; 00049 00063 Controller::result_t StopLine::control(pilot_command_t &pcmd, 00064 float topspeed) 00065 { 00066 result_t result = OK; 00067 00068 // distance from front bumper to stop way-point 00069 float wayptdist = 00070 (Euclidean::DistanceToWaypt(MapPose(estimate->pose.pose), 00071 course->stop_waypt) 00072 - ArtVehicle::front_bumper_px + config_->stop_distance); 00073 // stop_latency compensates for latency in the braking system. 00074 float abs_speed = fabsf(estimate->twist.twist.linear.x); 00075 float latencydist = abs_speed * config_->stop_latency; 00076 float D = wayptdist - latencydist; 00077 00078 // According to the model, deceleration should be constant, but in 00079 // the real world control latency will cause it to vary, so apply 00080 // feedback and recompute the model every cycle. 00081 if (abs_speed < Epsilon::speed) 00082 abs_speed = 0.0; 00083 00084 float V = -abs_speed; 00085 float A = V*V/(2.0*D); 00086 ElementID stop_id = course->stop_waypt.id; 00087 00088 // see if it is time to begin stopping 00089 if ((D <= config_->min_stop_distance || A >= config_->stop_deceleration) 00090 && !stopping) 00091 { 00092 stopping = true; 00093 initial_speed = fmaxf(topspeed,abs_speed); 00094 ART_MSG(8, "begin stopping for waypoint %s", 00095 stop_id.name().str); 00096 } 00097 00098 // Once stopping is initiated, keep doing it until reset(), no 00099 // matter how V changes. 00100 if (stopping) 00101 { 00102 00103 // check whether front bumper is within stop way-point polygon 00104 Polar front_bumper(0.0, ArtVehicle::front_bumper_px); 00105 00106 if (D <= config_->stop_distance || 00107 pops->pointInPoly(front_bumper, MapPose(estimate->pose.pose), 00108 course->stop_poly)) 00109 { 00110 pcmd.velocity = 0.0; // halt immediately. 00111 00112 // report Finished when stopped within stop polygon 00113 if (abs_speed < Epsilon::speed) 00114 { 00115 // Consider this way-point "reached". 00116 course->new_waypoint_reached(stop_id); 00117 course->stop_waypt.id = ElementID(); // reset way-point 00118 result = Finished; 00119 } 00120 } 00121 else if (!creeping && abs_speed >= Epsilon::speed) 00122 { 00123 // Not there yet. Do not let the requested speed increase 00124 // above initial speed when stopping began, even when the 00125 // car was accelerating. 00126 pcmd.velocity = fminf(pcmd.velocity, abs_speed - A); 00127 pcmd.velocity = fminf(pcmd.velocity, initial_speed); 00128 if (pcmd.velocity < 0.0) 00129 pcmd.velocity = 0.0; // do not change direction 00130 } 00131 else if (D <= config_->max_creep_distance) 00132 { 00133 creeping=true; 00134 // stopped too soon, keep creeping forward 00135 pcmd.velocity = fminf(pcmd.velocity, config_->stop_creep_speed); 00136 } 00137 00138 if (verbose >= 2) 00139 { 00140 ART_MSG(8, "stop %.3f m away for waypoint %s (%.3f,%.3f)," 00141 " %.3f m latency", 00142 wayptdist - config_->stop_distance, stop_id.name().str, 00143 course->stop_waypt.map.x, course->stop_waypt.map.y, 00144 latencydist); 00145 ART_MSG(8, "current, desired speed %.3f m/s, %.3f m/s," 00146 " decel %.3f m/s/s", 00147 abs_speed, pcmd.velocity, A); 00148 } 00149 } 00150 00151 trace("stop_line controller", pcmd, result); 00152 return result; 00153 }; 00154 00155 // reset controller and any subordinates 00156 void StopLine::reset(void) 00157 { 00158 trace_reset("StopLine"); 00159 reset_me(); 00160 }; 00161 00162 // reset this controller only 00163 void StopLine::reset_me(void) 00164 { 00165 stopping = false; 00166 creeping = false; 00167 initial_speed = 0.0; 00168 };