2.1 Basic Getting Unstuck

Introduction

So far our robot is just able to drive forward. That means if we hit the wall with the front of the car, we still try to drive forward and stuck in the wall. The only way to resolve the situation is to recognize it, and then to back up. Such a recovery procedure is essential even if we drive perfect, because we can be hit by opponents and spin of the track into the wall. It's also important that it works always and fast, because every second counts in the race.

Basic Algorithm

Here is the draft for the algorithm to detect if we are stuck:

  • Init a counter to 0.
  • If the absolute value of the angle between the track and the car is smaller than a certain value, reset counter to 0 and return "not stuck".
  • If the counter is smaller than a certain limit, increase the counter and return "not stuck", else return "stuck".

The algorithm to drive is then:

  • If we are stuck get unstuck else drive normal.

// counter
static int stuck = 0;

/* check if the car is stuck */
bool isStuck(tCarElt* car)
{
    float angle = RtTrackSideTgAngleL(&(car->_trkPos)) - car->_yaw;
    NORM_PI_PI(angle);
    // angle smaller than 30 degrees?
    if (fabs(angle) < 30.0/180.0*PI) {
        stuck = 0;
        return false;
    }
    if (stuck < 100) {
        stuck++;
        return false;
    } else {
        return true;
    }
}


/* Drive during race. */
static void
drive(int index, tCarElt* car, tSituation *s)
{
    float angle;
    const float SC = 1.0;

    memset(&car->ctrl, 0, sizeof(tCarCtrl));

    if (isStuck(car)) {
        angle = -RtTrackSideTgAngleL(&(car->_trkPos)) + car->_yaw;
        NORM_PI_PI(angle); // put the angle back in the range from -PI to PI
        car->ctrl.steer = angle / car->_steerLock;
        car->ctrl.gear = -1; // reverse gear
        car->ctrl.accelCmd = 0.3; // 30% accelerator pedal
        car->ctrl.brakeCmd = 0.0; // no brakes
    } else {
        angle = RtTrackSideTgAngleL(&(car->_trkPos)) - car->_yaw;
        NORM_PI_PI(angle); // put the angle back in the range from -PI to PI
        angle -= SC*car->_trkPos.toMiddle/car->_trkPos.seg->width;
        car->ctrl.steer = angle / car->_steerLock;
        car->ctrl.gear = 1; // first gear
        car->ctrl.accelCmd = 0.3; // 30% accelerator pedal
        car->ctrl.brakeCmd = 0.0; // no brakes
    }
}

Try to understand why this algorithm works sometimes and implement it in bt.cpp. There is also a case where the algorithm fails, we will fix that in chapter 2.6, but try to find out what's wrong with it. The simulation timestep is 0.02 seconds, so the angle needs to be for 2 (0.02 times 100) seconds greater than 30 degrees, till we start getting unstuck. We will stop getting unstuck, when the angle becomes smaller than 30 degrees.

Downloads

In case you got lost, you can download my robot for TORCS 1.2.0 or later.

Summary

  • You have implemented the above stuff and played with it.
  • You have found the bug in isStuck(tCarElt * car), eventually.