Esempio n. 1
0
  con_vec drive(situation &s)       // This is the robot "driver" function:
  {
    con_vec result = CON_VEC_EMPTY; // This is what is returned.
    double alpha, vc;             // components of result
    double bias;                  // added to servo's alpha result when entering curve
    double speed;                 // target speed for curve (next curve if straightaway)
    double speed_next = 0.0;      // target speed for next curve when in a curve, fps.
    double width;                 // track width, feet
    double to_end;                // distance to end of present segment in feet.
    static double lane;           // target distance from left wall, feet
    static double lane0;          // value of lane during early part of straightaway
    static int rad_was = 0;       // 0, 1, or -1 to indicate type of previous segment
    static double lane_inc = 0.0; // an adjustment to "lane", for passing

    // 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(s.starting)                // will be true only once
      lane = lane0 = s.to_lft;    // better not to change lanes during "dragout"

    // Set "lane" during curves.  This robot sets "lane" during curves to
    // try to maintain a small fixed distance to the inner rail.
    if(s.cur_rad > 0.0)           // turning left
    {
      lane = MARGIN;
      rad_was = 1;                // set this appropriate to curve.
    }
    else if(s.cur_rad < 0.0)      // turning right
    {
      lane = width - MARGIN;
      rad_was = -1;               // set this appropriate to curve.
    }
    else                          // straightaway:
    {
      // We will let the car go down the straigtaway in whatever "lane" it
      // comes out of the turn.
      if(rad_was)                 // If we just came out of a turn, then:
      {
        lane = s.to_lft;          // set "lane" where we are now.
        if(lane < .5 * width)     // but maybe push it a little more to right?
          lane += MARG2;          // (add MARG2 if we were to left of center)
        lane0 = lane;             // save a copy of the new "lane" value.
        rad_was = 0;              // set this appropriate to straightaway.
      }
      // This is for the transition from straight to left turn.  If we are
      // in a transition zone near the end of the straight, then set lane to
      // a linear function of s.to_end.  During this zone, "lane" will change
      // from "lane0" upon entering the zone to MARG2 upon reaching the end
      // of the straightaway.  ENT_SLOPE is the change in lane per change in
      // s.to_end.
      if(s.to_end < (lane0 - MARG2) / ENT_SLOPE)
        lane = MARG2 + ENT_SLOPE * s.to_end;
    }

    // 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 + MARGIN);
      else if(s.nex_rad < 0.0)
        speed = corn_spd(-s.nex_rad + MARGIN);
      else
        speed = 250.0;  // This should not execute, for a normal track file
    }
    else                     // we are in a curve:
    {
      if(s.nex_rad == 0.0)
        speed_next = 250.0;
      else
        speed_next = corn_spd(fabs(s.nex_rad) + MARGIN);
      speed = corn_spd(fabs(s.cur_rad) + MARGIN + fabs(lane_inc));
      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:
    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 > TOO_FAST * speed)             // if we're a little too fast,
           vc = s.v - BRAKE_SLIP;                // brake hard.
         else if(s.v < speed/TOO_FAST)         // if we're a little 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.
      }
    }
    else       // This is when we are in a curve:  (seek correct speed)
    {
      // calculate distance to end of curve:
      if(s.cur_rad > 0.0)
        to_end = s.to_end * (s.cur_rad + MARGIN);
      else
        to_end = -s.to_end * (s.cur_rad - MARGIN);
      // compute required braking distance and compare:
      // This is to slow us down for then next curve, if necessary:
      if(to_end <= CritDist(s.v, speed_next, BRK_CRV_ACC))
        vc = s.v - BRK_CRV_SLIP;
      // but if there is a straight, or a faster curve next, then
      // we may want to accelerate:
      else if(to_end/width < CURVE_END && speed_next > speed)
        vc = .5 * (s.v + speed_next)/cos(alpha);
      else   // normally, just calculate vc to maintain speed in corner
        vc = .5 * (s.v + speed)/cos(alpha);
    }

    // Passing and anti-collision code:
    // This code first tries to predict a collision; if no collision is
    // predicted, it does nothing.  Collision prediction is approximate, and
    // is based on linear extrapolation.  This can work because it is
    // repeated eighteen times per second of simulated time.
    // If a collision is predicted, then it gradually changes the
    // lane_inc static variable which changes alpha.
    // The hope is to steer around the car.  When no collision is
    // predicted then lane_inc is gradually brought back to zero.
    // If a crash is about to occur, medium hard braking occurs.
    double x, y, vx, vy, dot, vsqr, c_time, y_close, x_close;
    int kount;     // counts cars that are in danger of collision
    kount = 0;
    for(int i=0;i<3;i++) if (s.nearby[i].who<16)  // if there is a close car
    {
      y=s.nearby[i].rel_y;         // get forward distance (center-to-center)
      x=s.nearby[i].rel_x;         // get right distance
      vx=s.nearby[i].rel_xdot;     // get forward relative speed
      vy=s.nearby[i].rel_ydot;     // get lateral relative speed
      // if the cars are getting closer, then the dot product of the relative
      // position and velocity vectors will be negative.
      dot = x * vx + y * vy;     // compute dot product of vectors
      if(dot > -0.1)            // no action if car is not approaching.
        continue;
      vsqr = vx*vx + vy*vy;      // compute relative speed squared
      // Time to closest approach is dot product divided by speed squared:
      c_time = -dot / vsqr;     // compute time to closest approach
      if(c_time > 3.0)          // ignore if over three seconds
        continue;
      /* If the execution gets this far, it means that there is a car
      ahead of you, and getting closer, and less than 3.0 seconds
      away.  Evaluate the situation more carefully to decide if
      evasive action is warranted: */
      x_close = x + c_time * vx;      // x coord at closest approach
      y_close = y + c_time * vy;      // y coord at closest approach
      /*  Due to the length of the cars, a collision will occur if
          x changes sign while y is less than CARLEN.  This
          can happen before the center-to-center distance reaches its
          point of closest approach. */
      // check if collision would occur prior to closest approach
      // if so, reduce c_time, re-calculate x_close and y_close:
      if(x_close * x < 0.0 && y < 1.1 * CARLEN)
      {
        c_time = (fabs(x) - CARWID) / fabs(vx);
        x_close = x + c_time * vx;      // x coord at closest approach
        y_close = y + c_time * vy;      // y coord at closest approach
      }
      // Will it be a hit or a miss?
      if(fabs(x_close) > 2 * CARWID || fabs(y_close) > 1.25 * CARLEN)
        continue;            // this when a miss is predicted
      // If we get here there is a collision predicted
      ++kount;    // This counts how many cars are in the way.
      if(kount > 1 || c_time < .85)  // if more than one problem car, or if
        vc = s.v - BRK_CRV_SLIP;    // car within .85 sec of collision, brake!
      // steer to avoid the other car:
      // if there is room, we try to pass with least x deviation
      if(s.cur_rad > 0.0)
        if(x_close < 0.0 || s.to_lft < MARGIN)  // avoid scraping the inside
          lane_inc += DELTA_LANE;
        else
          lane_inc -= DELTA_LANE;
      else if(s.cur_rad < 0.0)
        if(x_close > 0.0 || s.to_rgt < MARGIN)
          lane_inc -= DELTA_LANE;
        else
          lane_inc += DELTA_LANE;
      else if(x_close < 0.0)      // on straights, pass with least x deviation
        lane_inc += DELTA_LANE;
      else
        lane_inc -= DELTA_LANE;
      if(lane_inc > .25 * width)  // limit the lane alteration to 1/4 width:
        lane_inc = .25 * width;
      else if(lane_inc < -.25 * width)
        lane_inc = -.25 * width;
    }

    // Here we gradually reduce lane_inc to zero if no collision is predicted:
    if(!kount)
      if(lane_inc > .1)
        lane_inc -= .5*DELTA_LANE;
      else if(lane_inc < -.001)
        lane_inc += .5*DELTA_LANE;

    // lane_inc represents an adjustment to the lane variable.  This is
    // accomplished by changing alpha an amount equal to that which the
    // steering servo would have done had lane actually been changed.
    result.vc = vc;   result.alpha = alpha - STEER_GAIN * lane_inc / width;

    // Pit: if the fuel is too low
    //  Fuel: full
    //  Damage: repair all
    if( s.fuel<10.0 )
    {
      result.request_pit   = 1;
      result.repair_amount = s.damage;
      result.fuel_amount = MAX_FUEL;
    }

    return result;
  }
Esempio n. 2
0
  con_vec drive(situation &s) 
  { 
    con_vec result = CON_VEC_EMPTY;    // 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, width; 

    if( s.starting )
    {
      result.fuel_amount = MAX_FUEL;     // fuel when starting
    }

    // 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. 
    if(s.cur_rad == 0.0) 
    { 
      bias = 0.0; 
      speed = corn_spd(s.nex_rad + DIST_FROM_INSIDE); 
    } 
    else  
    { 
      speed = corn_spd(s.cur_rad + DIST_FROM_INSIDE); 
      // See initial paragraphs for discussion of this formula. 
      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(s.to_end > ACCEL_FRACTION * s.cur_len)  // if we are far from the end, 
      {
        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 = .95 * s.v;              // brake hard. 
        else if(s.v < .98 * speed)     // if we're 2% too slow, 
          vc = 1.05 * 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) 
    {
      vc = .5 * (s.v + speed)/cos(alpha);   // to maintain speed in corner 
    } 

    // 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; 

    // Pit: if the fuel is too low
    //  Fuel: full
    //  Damage: repair all
    if( s.fuel<10.0 ) 
    {
      result.request_pit   = 1;
      result.repair_amount = s.damage;
      result.fuel_amount = MAX_FUEL;
    }

    return result; 
  }