7.1 Collecting Data About Opponents

Introduction

In this chapter we implement the ability to avoid collisions and to overtake opponents. I show you quite simple implementations, therefore there is much room left for improvements. For me it is one of the most interesting parts of the robots, because you can implement it in very different ways and it is not easy to predict which ideas will work well and which will not. The following implementation starts with collecting data about the opponents. After that we implement collision avoidance and finally overtaking.

The Opponent Class

First we define a class for our opponents. It holds data about the opponents relative to our robot, e. g. the distance between opponent X's car and ours. For simplicity I will also put some data into it which is just dependent of the opponent. This is not efficient if we run more than one robot with our module, it would be better to put that data into a separate class whose instances are visible from all robots of our module and are just updated once per timestep (e. g. when we start bt 1 and bt 2 both will compute the speed of opponent X, that is neither efficient nor necessary). You can achieve such an update with checking the simulation time and just update the data when the simulation time has changed. The code would then look somelike that:

static double currenttime;   /* class variable in Driver */
...
if (currenttime != situation->currentTime) {
    currenttime = situation->currentTime;
    allcars.update();
}

The Opponents Class

The Opponents class will just hold an array of opponents.

The opponent.h File

Put the following stuff into opponent.h in the bt directory. I will explain the details in the discussion of opponent.cpp.

/***************************************************************************

    file                 : opponent.h
    created              : Thu Apr 22 01:20:19 CET 2003
    copyright            : (C) 2003 Bernhard Wymann

 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef _OPPONENT_H_
#define _OPPONENT_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include <tgf.h>
#include <track.h>
#include <car.h>
#include <raceman.h>
#include <robottools.h>
#include <robot.h>

#include "linalg.h"
#include "driver.h"

The following lines define bitmasks which we will use to classify the opponents. I will explain them later.

#define OPP_IGNORE	0
#define OPP_FRONT	(1<<0)
#define OPP_BACK	(1<<1)
#define OPP_SIDE	(1<<2)
#define OPP_COLL	(1<<3)

Because of a cross dependency we need to define a Driver class prototype. After that the declaration of the Opponent class starts.

class Driver;

/* Opponent maintains the data for one opponent */
class Opponent {
    public:
        Opponent();

        void setCarPtr(tCarElt *car) { this->car = car; }
        static void setTrackPtr(tTrack *track) { Opponent::track = track; }

        static float getSpeed(tCarElt *car);
        tCarElt *getCarPtr() { return car; }
        int getState() { return state; }
        float getCatchDist() { return catchdist; }
        float getDistance() { return distance; }
        float getSideDist() { return sidedist; }
        float getWidth() { return width; }
        float getSpeed() { return speed; }

        void update(tSituation *s, Driver *driver);

    private:
        float getDistToSegStart();

        tCarElt *car;       /* pointer to the opponents car */
        float distance;     /* approximation of the real distance */
        float speed;        /* speed in direction of the track */
        float catchdist;    /* distance needed to catch the opponent */
        float width;        /* the cars needed width on the track */
        float sidedist;     /* distance of center of gravity of the cars */
        int state;          /* state bitmask of the opponent */

        /* class variables */
        static tTrack *track;

        /* constants */
        static float FRONTCOLLDIST;
        static float BACKCOLLDIST;
        static float SIDECOLLDIST;
        static float LENGTH_MARGIN;
        static float SIDE_MARGIN;
};

Finally follows the declaration of the Opponents class. Like you can see it is just responsible for the update of the opponents.

/* The Opponents class holds an array of all Opponents */
class Opponents {
    public:
        Opponents(tSituation *s, Driver *driver);
        ~Opponents();

        void update(tSituation *s, Driver *driver);
        Opponent *getOpponentPtr() { return opponent; }
        int getNOpponents() { return nopponents; }

    private:
        Opponent *opponent;
        int nopponents;
};


#endif // _OPPONENT_H_

Summary

  • You have created opponent.h.
  • You have an idea of the data we collect.