home *** CD-ROM | disk | FTP | other *** search
- /* TUT5.CPP - yet another RARS 'bot, by M. Timin, April '95
- // for ver. 0.60
-
- This file is the fifth in our tutorial series. It is also a working
- robot. The robot function name, and its displayed name, is "TutManTu".
- This file may be compiled and linked just as any other RARS driver.
- It has been tested, and it runs very well on almost all tracks.
-
- This code is closely based on the first four tutorials. I will try to
- explain where and why it differs in the comments of the code. There are
- two other files that all of our readers should get from the ftp site.
- They are vectors.txt and vectors.pcx. The first is an explanation of
- the vector relationships used in the car model. The second is a PCX
- file of an accompanying sketch.
-
- The file CNTRL0.CPP is still useful as a reference for some details
- of robot code that are not explained below.
-
- m */
-
- #include <string.h>
- #include <stdlib.h>
- #include <math.h>
- #include "car.h"
-
- // parameters to tinker with:
- const double DELTA_LANE = 1.0; // when car "dead_ahead, change "lane" this much
- const double CORN_MYU = .92; // lateral g's expected when cornering
- const double BRAKE_ACCEL = -30.0; // acceleration when braking on straight
- const double BRAKE_RATIO = .935; // tire speed ratio when braking "
- const double BRK_CRV_ACC = -25.0; // acceleration when braking in curve
- const double BRK_CRV_SLIP = 5.0; // tire slip for braking in curve
- const double DIST_FROM_INSIDE = 12.0; // target distance from curve's inner rail
- const double STEER_GAIN = 0.5; // gain of steering servo loop
- const double DAMP_GAIN = 1.1; // damping of steering servo loop
- const double BIG_SLIP = 9.0; // affects the bias of steering servo loop
-
- double corn_spd(double radius) // returns maximum cornering speed, fps
- {
- // MUST NEVER CALL THIS ROUTINE WITH ZERO ARGUMENT!
- return sqrt(radius * 32.2 * CORN_MYU); // compute the speed
- }
-
- // Calculates the critical distance necessary to bring a car from speed
- // v0 to speed v1 when the braking acceleration is "a", ft per sec^2.
- // Speeds are in fps. ("a" should be negative)
- double CritDist(double v0, double v1, double a)
- {
- double dv;
-
- dv = v1 - v0;
- if(dv > 0.0) // this saves having such a test in the caller
- return(0.0);
- return (v0 + .5 * dv) * dv / a;
- }
-
- con_vec TutMan3(situation &s)
- {
- const char name[] = "TutMan3"; // This is the robot driver's name!
- static int init_flag = 1; // cleared by first call
- con_vec result; // This is what is returned.
- double alpha, vc; // components of result
- static double lane = -10000; // an absurd value to show not initialized
- double bias, speed, speed_next, width, to_end;
-
- if(init_flag == 1) { // first time only, copy name:
- my_name_is(name); // copy the name string into the host program
- init_flag = 0;
- result.alpha = result.vc = 0;
- return result;
- }
-
- // service routine in the host software to handle getting unstuck from
- // from crashes and pileups:
- if(stuck(s.backward, s.v,s.vn, s.to_lft,s.to_rgt, &result.alpha,&result.vc))
- return result;
-
- width = s.to_lft + s.to_rgt; // compute width of track
-
- // This is a little trick so that the car will not try to change lanes
- // during the "dragout" at the start of the race. We set "lane" to
- // whatever position we have been placed by the host.
- if(lane < -9000) // will be true only once
- lane = s.to_lft; // better not to change lanes at the start
-
- // Set "lane" during curves. This robot sets "lane" during curves to
- // try to maintain a fixed distance to the inner rail.
- // For straightaways, we leave "lane" unchanged until later.
- if(s.cur_rad > 0.0) // turning left
- lane = DIST_FROM_INSIDE;
- else if(s.cur_rad < 0.0) // turning right
- lane = width - DIST_FROM_INSIDE;
-
- // set the bias:
- // Bias is an additive term in the steering servo, so that the servo
- // doesn't have to "hunt" much for the correct alpha value. It is an
- // estimate of the alpha value that would be found by the servo if there
- // was plenty of settling time. It is zero for straightaways.
- // Also, for convenience, we call the corn_spd() function here. On
- // the straightaway, we call it to find out the correct speed for the
- // corner ahead, using s.nex_rad for the radius. In the curve we of
- // course use the radius of the curve we are in. But also, we call it
- // for the next segment, to find out our target speed for the end of
- // the current segment, which we call speed_next.
- if(s.cur_rad == 0.0) {
- bias = 0.0;
- if(s.nex_rad > 0.0)
- speed = corn_spd(s.nex_rad + DIST_FROM_INSIDE);
- else if(s.nex_rad < 0.0)
- speed = corn_spd(-s.nex_rad + DIST_FROM_INSIDE);
- else
- speed = 250.0;
- }
- else {
- if(s.nex_rad == 0.0)
- speed_next = 250.0;
- else
- speed_next = corn_spd(fabs(s.nex_rad) + DIST_FROM_INSIDE);
- speed = corn_spd(fabs(s.cur_rad) + DIST_FROM_INSIDE);
- bias = (s.v*s.v/(speed*speed)) * atan(BIG_SLIP / speed);
- if(s.cur_rad < 0.0) // bias must be negative for right turn
- bias = -bias;
- }
-
- // set alpha: (This line is the complete steering servo.)
- alpha = STEER_GAIN * (s.to_lft - lane)/width - DAMP_GAIN * s.vn/s.v + bias;
-
- // set vc: When nearing end of straight, change "lane" for the turn, also.
- if(s.cur_rad == 0.0) { // If we are on a straightaway,
- // if we are far from the end,
- if(s.to_end > CritDist(s.v, speed, BRAKE_ACCEL))
- vc = s.v + 50.0; // pedal to the metal!
- else { // otherwise, adjust speed for the coming turn:
- if(s.v > 1.02 * speed) // if we're 2% too fast,
- vc = BRAKE_RATIO * s.v; // brake hard.
- else if(s.v < .98 * speed) // if we're 2% too slow,
- vc = 1.1 * speed; // accelerate hard.
- else // if we are very close to speed,
- vc = .5 * (s.v + speed); // approach the speed gently.
- // approach the lane you want for the turn:
- if(s.nex_rad > 0.0)
- lane = DIST_FROM_INSIDE;
- else
- lane = width - DIST_FROM_INSIDE;
- }
- }
- else { // This is when we are in a curve: (seek correct speed)
- // calculate vc to maintain speed in corner
- vc = .5 * (s.v + speed)/cos(alpha);
- // calculate distance to end of curve:
- if(s.cur_rad > 0.0)
- to_end = s.to_end * (s.cur_rad + DIST_FROM_INSIDE);
- else
- to_end = -s.to_end * (s.cur_rad - DIST_FROM_INSIDE);
- // compute required braking distance and compare:
- if(to_end <= CritDist(s.v, speed_next, BRK_CRV_ACC)) {
- vc = s.v - BRK_CRV_SLIP;
- }
- }
-
- // During the acceleration portion of a straightaway, the lane variable
- // is not changed by the code above. Hence the code below changes it a
- // little at a time until there is no car dead_ahead. This code here has
- // no affect at all in the turns, nor in the braking portion
- // of the straight.
- if(s.dead_ahead) // Change the lane a little if someone's
- if(s.to_lft > s.to_rgt) // in your way.
- lane -= DELTA_LANE; // lane must be a static variable
- else
- lane += DELTA_LANE;
-
- result.vc = vc; result.alpha = alpha;
- return result;
- }
-