Styled code consistently,
based on Google C++ style guide. Re #183. git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@3115 30fe4595-0a0c-4342-8851-515496e4dcbd Former-commit-id: 7cf19bbb7bfcc767975d5bceec053d0158de249b Former-commit-id: d4b766544d33e0bd5ace939461b6cfe7c0033d67
This commit is contained in:
parent
3061980a7a
commit
017d1d3e54
10 changed files with 1540 additions and 1531 deletions
File diff suppressed because it is too large
Load diff
|
@ -81,65 +81,68 @@ class KDriver {
|
|||
void endRace(tSituation * s);
|
||||
std::string bot; // to make it possible to differentiate between Kilo & Dots
|
||||
|
||||
// Used by Opponents
|
||||
tCarElt *getCarPtr() { return m_car;}
|
||||
tTrack *getTrackPtr() { return m_track;}
|
||||
double getSpeed() { return m_mycardata->getSpeedInTrackDirection(); }
|
||||
// Used by Opponents & Pit
|
||||
tCarElt *car_ptr() const { return car_;}
|
||||
tTrack *track_ptr() const { return track_;}
|
||||
double speed() const { return my_cardata_->getSpeedInTrackDirection(); }
|
||||
|
||||
protected:
|
||||
// Initialize
|
||||
void initCa();
|
||||
void initCw();
|
||||
void initTireMu();
|
||||
void initTCLFilter();
|
||||
double initSkill(tSituation * s);
|
||||
void InitCa();
|
||||
void InitCw();
|
||||
void InitTireMu();
|
||||
void InitTCLFilter();
|
||||
double InitSkill(tSituation * s);
|
||||
|
||||
// Driving aids
|
||||
double filterTCL_RWD();
|
||||
double filterTCL_FWD();
|
||||
double filterTCL_4WD();
|
||||
double filterTCL(const double accel);
|
||||
double filterTrk(double accel);
|
||||
double brakeDist(double allowedspeed, double mu);
|
||||
double filterABS(double brake);
|
||||
double filterBPit(double brake);
|
||||
double FilterTCL_RWD();
|
||||
double FilterTCL_FWD();
|
||||
double FilterTCL_4WD();
|
||||
double FilterTCL(double accel);
|
||||
double FilterTrk(double accel);
|
||||
double FilterABS(double brake);
|
||||
double FilterBPit(double brake);
|
||||
|
||||
// Steering
|
||||
double getSteer(tSituation * s);
|
||||
double calcSteer(double targetAngle, int rl);
|
||||
double correctSteering(double avoidsteer, double racesteer);
|
||||
double smoothSteering(double steercmd);
|
||||
vec2f getTargetPoint();
|
||||
double GetSteer(tSituation * s);
|
||||
double CalcSteer(double targetAngle, int rl);
|
||||
double CorrectSteering(double avoidsteer, double racesteer);
|
||||
double SmoothSteering(double steercmd);
|
||||
double GetOffset();
|
||||
vec2f TargetPoint();
|
||||
|
||||
// Throttle/brake handling
|
||||
void CalcSpeed();
|
||||
double GetAccel();
|
||||
double GetBrake();
|
||||
double BrakeDist(double allowedspeed, double mu) const;
|
||||
double FilterBrakeSpeed(double brake);
|
||||
double FilterBColl(double brake);
|
||||
double FilterOverlap(double accel);
|
||||
|
||||
// Gear/clutch
|
||||
int GetGear();
|
||||
double GetClutch();
|
||||
|
||||
// 'own' utilities
|
||||
void update(tSituation * s);
|
||||
double filterBrakeSpeed(double brake);
|
||||
double filterBColl(double brake);
|
||||
double filterOverlap(double accel);
|
||||
void calcSpeed();
|
||||
void setAvoidRight() {m_avoidmode |= AVOIDRIGHT;}
|
||||
void setAvoidLeft() {m_avoidmode |= AVOIDLEFT;}
|
||||
void setMode(int newmode);
|
||||
bool oppTooFarOnSide(tCarElt *ocar);
|
||||
bool isStuck();
|
||||
double getDistToSegEnd();
|
||||
double getOffset();
|
||||
double getAccel();
|
||||
double getBrake();
|
||||
int getGear();
|
||||
double getClutch();
|
||||
double getWidth() { return m_mycardata->getWidthOnTrack();}
|
||||
void checkPitStatus(tSituation *s);
|
||||
void * loadDefaultSetup() const;
|
||||
void mergeCarSetups(void **oldHandle, void *newHandle);
|
||||
void Update(tSituation * s);
|
||||
bool IsStuck();
|
||||
inline double GetDistToSegEnd() const;
|
||||
void CheckPitStatus(tSituation *s);
|
||||
void * LoadDefaultSetup() const;
|
||||
void MergeCarSetups(void **oldHandle, void *newHandle) const;
|
||||
void set_avoid_right() { avoid_mode_ |= AVOIDRIGHT; }
|
||||
void set_avoid_left() { avoid_mode_ |= AVOIDLEFT; }
|
||||
double width() const { return my_cardata_->getWidthOnTrack(); }
|
||||
double mass() const { return CARMASS + car_->_fuel; }
|
||||
double current_speed_sqr() const { return car_->_speed_x * car_->_speed_x; }
|
||||
void set_mode(int newmode);
|
||||
|
||||
// Opponent handling
|
||||
Opponent * getOverlappingOpp();
|
||||
Opponent * getTakeoverOpp();
|
||||
Opponent * getSidecollOpp();
|
||||
double filterOverlappedOffset(Opponent *o);
|
||||
double filterTakeoverOffset(Opponent *o);
|
||||
double filterSidecollOffset(Opponent *o, const double);
|
||||
Opponent * GetTakeoverOpp();
|
||||
double FilterOverlappedOffset(const Opponent *o);
|
||||
double FilterTakeoverOffset(const Opponent *o);
|
||||
double FilterSidecollOffset(const Opponent *o, const double incfactor);
|
||||
|
||||
|
||||
// Constants.
|
||||
|
@ -147,65 +150,74 @@ class KDriver {
|
|||
enum { TEAM_FRIEND = 1, TEAM_FOE };
|
||||
enum { AVOIDLEFT = 1, AVOIDRIGHT = 2, AVOIDSIDE = 4 };
|
||||
|
||||
tCarElt *m_car; // Pointer to tCarElt struct.
|
||||
LRaceLine *m_raceline;
|
||||
Opponents *m_opponents; // The container for opponents.
|
||||
Pit *m_pit; // Pointer to the pit instance.
|
||||
KStrategy *m_strategy; // Pit stop strategy.
|
||||
tTrack *m_track; // Track variables.
|
||||
// Pointers to other classes
|
||||
tCarElt *car_; // Pointer to tCarElt struct.
|
||||
LRaceLine *raceline_; // The racing line
|
||||
Opponents *opponents_; // The container for opponents.
|
||||
Pit *pit_; // Pointer to the pit instance.
|
||||
KStrategy *strategy_; // Pit stop strategy.
|
||||
tTrack *track_; // Track variables.
|
||||
|
||||
static Cardata *m_cardata; // Data about all cars shared by all instances.
|
||||
SingleCardata *m_mycardata; // Pointer to "global" data about my car.
|
||||
static Cardata *cardata_; // Data about all cars shared by all instances.
|
||||
SingleCardata *my_cardata_; // Pointer to "global" data about my car.
|
||||
|
||||
static double m_currentSimTime; // Store time to avoid useless updates.
|
||||
static double current_sim_time_; // Store time to avoid useless updates.
|
||||
|
||||
// Per robot global data
|
||||
int m_mode;
|
||||
int m_avoidmode;
|
||||
int m_lastmode;
|
||||
int m_stuckCounter;
|
||||
double m_speedangle; // the angle of the speed vector
|
||||
// relative to trackangle, > 0.0 points to right.
|
||||
double m_angle;
|
||||
double m_mass; // Mass of car + fuel.
|
||||
double m_myoffset; // Offset to the track middle.
|
||||
double m_laststeer;
|
||||
double m_lastNSasteer;
|
||||
double m_simTime; // how long since the race started
|
||||
double m_avoidTime; // how long since we began avoiding
|
||||
double m_correctTimer; // how long we've been correcting
|
||||
double m_correctLimit; // level of divergence with raceline steering
|
||||
double m_brakeDelay;
|
||||
double m_currentSpeedSqr; // Square of the current speed_x.
|
||||
double m_clutchTime; // Clutch timer.
|
||||
double m_oldLookahead; // Lookahead for steering in the previous step.
|
||||
double m_raceSteer; // steer command to get to raceline
|
||||
double m_rLookahead; // how far ahead on the track we look for steering
|
||||
double m_raceOffset; // offset from middle of track towards which
|
||||
int car_index_;
|
||||
std::string car_type_;
|
||||
|
||||
// Driving modes
|
||||
int mode_;
|
||||
int avoid_mode_;
|
||||
int last_mode_;
|
||||
|
||||
// Timers
|
||||
double sim_time_; // how long since the race started
|
||||
double avoid_time_; // how long since we began avoiding
|
||||
double correct_timer_; // how long we've been correcting
|
||||
double correct_limit_; // level of divergence with raceline steering
|
||||
double clutch_time_; // clutch timer
|
||||
int stuck_counter_; // to determine if we are stuck
|
||||
|
||||
// Car state
|
||||
double angle_;
|
||||
double speed_angle_; // the angle of the speed vector
|
||||
// relative to trackangle, > 0.0 points to right.
|
||||
double my_offset_; // Offset to the track middle.
|
||||
|
||||
// Raceline data
|
||||
double old_lookahead_; // Lookahead for steering in the previous step.
|
||||
double race_offset_; // offset from middle of track towards which
|
||||
// raceline is steering
|
||||
double m_avoidLftOffset; // closest opponent on the left
|
||||
double m_avoidRgtOffset; // closest opponent on the right
|
||||
double m_raceSpeed; // how fast raceline code says we should be going
|
||||
double m_avoidSpeed; // how fast we should go if avoiding
|
||||
double m_accelCmd;
|
||||
double m_brakeCmd;
|
||||
double m_pitOffset;
|
||||
v2d m_raceTarget; // the 2d point the raceline is driving at.
|
||||
double m_mincatchdist;
|
||||
double m_rgtinc;
|
||||
double m_lftinc;
|
||||
double m_maxoffset;
|
||||
double m_minoffset;
|
||||
double m_rInverse;
|
||||
std::string m_carType;
|
||||
int m_carIndex;
|
||||
double race_speed_; // how fast raceline code says we should be going
|
||||
double avoid_speed_; // how fast we should go if avoiding
|
||||
double brake_delay_; // configurable, brake a wee bit late
|
||||
double pit_offset_; // configurable, pit lane can start late/early
|
||||
|
||||
// Commands
|
||||
double accel_cmd_; // throttle pedal command [0..1]
|
||||
double brake_cmd_; // brake pedal command [0..1]
|
||||
double race_steer_; // steer command to get to raceline
|
||||
double last_steer_; // previous steer command
|
||||
double last_nsa_steer_;
|
||||
|
||||
// Handling traffic
|
||||
double min_catch_dist_; // used in considering takeover
|
||||
double avoid_lft_offset_; // closest opponent on the left
|
||||
double avoid_rgt_offset_; // closest opponent on the right
|
||||
double rgt_inc_;
|
||||
double lft_inc_;
|
||||
double max_offset_;
|
||||
double min_offset_;
|
||||
double r_inverse_;
|
||||
|
||||
// Skilling
|
||||
double m_skill;
|
||||
double m_filterBrakeSkill;
|
||||
double m_filterAccelSkill;
|
||||
double m_filterLookaheadSkill;
|
||||
double m_filterSideSkill;
|
||||
double skill_;
|
||||
double brake_skill_;
|
||||
double accel_skill_;
|
||||
double lookahead_skill_;
|
||||
double side_skill_;
|
||||
|
||||
// Data that should stay constant after first initialization.
|
||||
int MAX_UNSTUCK_COUNT;
|
||||
|
@ -234,6 +246,7 @@ class KDriver {
|
|||
static const double LOOKAHEAD_FACTOR;
|
||||
static const double WIDTHDIV;
|
||||
static const double BORDER_OVERTAKE_MARGIN;
|
||||
static const double SIDECOLL_MARGIN;
|
||||
static const double OVERTAKE_OFFSET_SPEED;
|
||||
static const double PIT_LOOKAHEAD;
|
||||
static const double PIT_BRAKE_AHEAD;
|
||||
|
@ -246,9 +259,6 @@ class KDriver {
|
|||
static const double CATCH_FACTOR;
|
||||
static const double TEAM_REAR_DIST;
|
||||
static const double LET_OVERTAKE_FACTOR;
|
||||
|
||||
public:
|
||||
static const int TEAM_DAMAGE_CHANGE_LEAD; // Used in opponent.cpp too
|
||||
};
|
||||
|
||||
#endif // SRC_DRIVERS_KILO2008_KDRIVER_H_
|
||||
|
|
|
@ -35,8 +35,6 @@
|
|||
using std::string;
|
||||
using std::list;
|
||||
|
||||
// class variables and constants.
|
||||
tTrack * Opponent::m_track;
|
||||
// [m] distance on the track ahead to check other cars.
|
||||
const double Opponent::FRONTCOLLDIST = 200.0;
|
||||
// [m] distance on the track behind to check other cars.
|
||||
|
@ -53,58 +51,62 @@ const double Opponent::LAP_BACK_TIME_PENALTY = -30.0;
|
|||
const double Opponent::OVERLAP_WAIT_TIME = 5.0;
|
||||
// [m/s] avoid overlapping opponents to stuck behind me.
|
||||
const double Opponent::SPEED_PASS_MARGIN = 5.0;
|
||||
// When to change position in the team?
|
||||
const int Opponent::TEAM_DAMAGE_CHANGE_LEAD = 800;
|
||||
|
||||
const double Opponents::TEAM_REAR_DIST = 50.0;
|
||||
|
||||
|
||||
// Constructor
|
||||
Opponent::Opponent(tCarElt *car, SingleCardata * cardata, int index) {
|
||||
m_car = car;
|
||||
m_cardata = cardata;
|
||||
m_index = index;
|
||||
m_teammate = false;
|
||||
car_ = car;
|
||||
cardata_ = cardata;
|
||||
index_ = index;
|
||||
teammate_ = false;
|
||||
}
|
||||
|
||||
|
||||
void Opponent::update(tSituation *s, KDriver *driver) {
|
||||
void Opponent::Update(tSituation *s, KDriver *driver) {
|
||||
// Init state of opponent to ignore.
|
||||
m_state = OPP_IGNORE;
|
||||
state_ = OPP_IGNORE;
|
||||
|
||||
// If this car is out of the simulation or is in pits, ignore it.
|
||||
if ((m_car->_state & RM_CAR_STATE_NO_SIMU)
|
||||
|| (m_car->_state & RM_CAR_STATE_PIT))
|
||||
if ((car_->_state & RM_CAR_STATE_NO_SIMU)
|
||||
|| (car_->_state & RM_CAR_STATE_PIT))
|
||||
return;
|
||||
|
||||
// Updating distance along the middle.
|
||||
tCarElt *mycar = driver->getCarPtr();
|
||||
double oppToStart = m_car->_trkPos.seg->lgfromstart + getDistToSegStart();
|
||||
m_distance = oppToStart - mycar->_distFromStartLine;
|
||||
if (m_distance > m_track->length / 2.0) {
|
||||
m_distance -= m_track->length;
|
||||
} else if (m_distance < -m_track->length / 2.0) {
|
||||
m_distance += m_track->length;
|
||||
tCarElt *mycar = driver->car_ptr();
|
||||
tTrack *track = driver->track_ptr();
|
||||
double oppToStart = car_->_trkPos.seg->lgfromstart + DistToSegStart();
|
||||
distance_ = oppToStart - mycar->_distFromStartLine;
|
||||
if (distance_ > track->length / 2.0) {
|
||||
distance_ -= track->length;
|
||||
} else if (distance_ < -track->length / 2.0) {
|
||||
distance_ += track->length;
|
||||
}
|
||||
|
||||
const double SIDECOLLDIST = MAX(m_car->_dimension_x, mycar->_dimension_x);
|
||||
const double SIDECOLLDIST = MAX(car_->_dimension_x, mycar->_dimension_x);
|
||||
|
||||
// Is opponent in relevant range BACKCOLLDIST..FRONTCOLLDIST?
|
||||
if (BetweenStrict(m_distance, BACKCOLLDIST, FRONTCOLLDIST)) {
|
||||
if (BetweenStrict(distance_, BACKCOLLDIST, FRONTCOLLDIST)) {
|
||||
// Is opponent aside?
|
||||
if (BetweenStrict(m_distance, -SIDECOLLDIST, SIDECOLLDIST)) {
|
||||
m_sidedist = m_car->_trkPos.toMiddle - mycar->_trkPos.toMiddle;
|
||||
m_state |= OPP_SIDE;
|
||||
if (BetweenStrict(distance_, -SIDECOLLDIST, SIDECOLLDIST)) {
|
||||
state_ |= OPP_SIDE;
|
||||
}
|
||||
|
||||
// Is opponent in front and slower?
|
||||
if (m_distance > SIDECOLLDIST && getSpeed() <= driver->getSpeed()) {
|
||||
m_state |= OPP_FRONT;
|
||||
if (distance_ > SIDECOLLDIST && speed() <= driver->speed()) {
|
||||
state_ |= OPP_FRONT;
|
||||
|
||||
if (isQuickerTeammate(mycar))
|
||||
m_state |= OPP_FRONT_FOLLOW;
|
||||
if (IsQuickerTeammate(mycar))
|
||||
state_ |= OPP_FRONT_FOLLOW;
|
||||
|
||||
m_distance -= SIDECOLLDIST;
|
||||
m_distance -= LENGTH_MARGIN;
|
||||
distance_ -= SIDECOLLDIST;
|
||||
distance_ -= LENGTH_MARGIN;
|
||||
|
||||
// If the distance is small we compute it more accurate.
|
||||
if (m_distance < EXACT_DIST) {
|
||||
if (distance_ < EXACT_DIST) {
|
||||
straight2f carFrontLine(
|
||||
mycar->_corner_x(FRNT_LFT),
|
||||
mycar->_corner_y(FRNT_LFT),
|
||||
|
@ -114,96 +116,75 @@ void Opponent::update(tSituation *s, KDriver *driver) {
|
|||
mycar->_corner_y(FRNT_LFT));
|
||||
|
||||
double mindist = FLT_MAX;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
vec2f corner(m_car->_corner_x(i), m_car->_corner_y(i));
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
vec2f corner(car_->_corner_x(i), car_->_corner_y(i));
|
||||
double dist = carFrontLine.dist(corner);
|
||||
mindist = MIN(dist, mindist);
|
||||
}
|
||||
m_distance = MIN(m_distance, mindist);
|
||||
distance_ = MIN(distance_, mindist);
|
||||
} // if small distance
|
||||
|
||||
m_catchdist = driver->getSpeed() * m_distance
|
||||
/ (driver->getSpeed() - getSpeed());
|
||||
|
||||
m_sidedist = m_car->_trkPos.toMiddle - mycar->_trkPos.toMiddle;
|
||||
double cardist = fabs(m_sidedist) - fabs(getWidth() / 2.0) -
|
||||
double side_dist = car_->_trkPos.toMiddle - mycar->_trkPos.toMiddle;
|
||||
double cardist = fabs(side_dist) - fabs(width() / 2.0) -
|
||||
mycar->_dimension_y / 2.0;
|
||||
if (cardist < SIDE_MARGIN)
|
||||
m_state |= OPP_COLL;
|
||||
} else if (m_distance < -SIDECOLLDIST
|
||||
&& getSpeed() > driver->getSpeed() - SPEED_PASS_MARGIN) {
|
||||
state_ |= OPP_COLL;
|
||||
} else if (distance_ < -SIDECOLLDIST
|
||||
&& speed() > driver->speed() - SPEED_PASS_MARGIN) {
|
||||
// Is opponent behind and faster.
|
||||
m_catchdist = driver->getSpeed() * m_distance
|
||||
/ (getSpeed() - driver->getSpeed());
|
||||
m_state |= OPP_BACK;
|
||||
m_distance -= SIDECOLLDIST;
|
||||
m_distance -= LENGTH_MARGIN;
|
||||
} else if (m_distance > SIDECOLLDIST && getSpeed() > driver->getSpeed()) {
|
||||
state_ |= OPP_BACK;
|
||||
distance_ -= SIDECOLLDIST;
|
||||
distance_ -= LENGTH_MARGIN;
|
||||
} else if (distance_ > SIDECOLLDIST && speed() > driver->speed()) {
|
||||
// Opponent is in front and faster.
|
||||
m_state |= OPP_FRONT_FAST;
|
||||
if (isQuickerTeammate(mycar))
|
||||
m_state |= OPP_FRONT_FOLLOW;
|
||||
m_distance -= SIDECOLLDIST;
|
||||
if (m_distance < 20.0 - (getSpeed() - driver->getSpeed()) * 4)
|
||||
m_state |= OPP_FRONT;
|
||||
state_ |= OPP_FRONT_FAST;
|
||||
if (IsQuickerTeammate(mycar))
|
||||
state_ |= OPP_FRONT_FOLLOW;
|
||||
distance_ -= SIDECOLLDIST;
|
||||
if (distance_ < 20.0 - (speed() - driver->speed()) * 4)
|
||||
state_ |= OPP_FRONT;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we should let overtake the opponent.
|
||||
updateOverlapTimer(s, mycar);
|
||||
if (m_overlaptimer > OVERLAP_WAIT_TIME)
|
||||
m_state |= OPP_LETPASS;
|
||||
|
||||
m_brakedistance = m_distance - m_car->_dimension_x;
|
||||
} // update
|
||||
UpdateOverlapTimer(s, mycar);
|
||||
} // Update
|
||||
|
||||
|
||||
// Compute the length to the start of the segment.
|
||||
double Opponent::getDistToSegStart() const {
|
||||
double ret = (m_car->_trkPos.seg->type == TR_STR)
|
||||
? m_car->_trkPos.toStart
|
||||
: m_car->_trkPos.toStart * m_car->_trkPos.seg->radius;
|
||||
inline double Opponent::DistToSegStart() const {
|
||||
double ret = (car_->_trkPos.seg->type == TR_STR)
|
||||
? car_->_trkPos.toStart
|
||||
: car_->_trkPos.toStart * car_->_trkPos.seg->radius;
|
||||
return ret;
|
||||
} // getDistToSegStart
|
||||
|
||||
|
||||
// Update overlaptimers of opponents.
|
||||
void Opponent::updateOverlapTimer(tSituation * const s, tCarElt * const mycar) {
|
||||
if ((m_car->race.laps > mycar->race.laps) || isQuickerTeammate(mycar)) {
|
||||
if (isState(OPP_BACK | OPP_SIDE)) {
|
||||
m_overlaptimer += s->deltaTime;
|
||||
} else if (isState(OPP_FRONT)) {
|
||||
m_overlaptimer = LAP_BACK_TIME_PENALTY;
|
||||
void Opponent::UpdateOverlapTimer(tSituation * const s, tCarElt * const mycar) {
|
||||
if ((car_->race.laps > mycar->race.laps) || IsQuickerTeammate(mycar)) {
|
||||
if (HasState(OPP_BACK | OPP_SIDE)) {
|
||||
overlap_timer_ += s->deltaTime;
|
||||
} else if (HasState(OPP_FRONT)) {
|
||||
overlap_timer_ = LAP_BACK_TIME_PENALTY;
|
||||
} else {
|
||||
if (m_overlaptimer > 0.0) {
|
||||
if (isState(OPP_FRONT_FAST)) {
|
||||
m_overlaptimer = MIN(0.0, m_overlaptimer);
|
||||
if (overlap_timer_ > 0.0) {
|
||||
if (HasState(OPP_FRONT_FAST)) {
|
||||
overlap_timer_ = MIN(0.0, overlap_timer_);
|
||||
} else {
|
||||
m_overlaptimer -= s->deltaTime;
|
||||
overlap_timer_ -= s->deltaTime;
|
||||
}
|
||||
} else {
|
||||
m_overlaptimer += s->deltaTime;
|
||||
overlap_timer_ += s->deltaTime;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m_overlaptimer = 0.0;
|
||||
overlap_timer_ = 0.0;
|
||||
}
|
||||
} // updateOverlapTimer
|
||||
|
||||
|
||||
/**
|
||||
* Returns true, if the other car is our teammate
|
||||
* and has significantly less damage
|
||||
* (defined in KDriver::TEAM_DAMAGE_CHANGE_LEAD)
|
||||
*
|
||||
* @param mycar pointer to the other car
|
||||
* @return true, if the opponent is our teammate
|
||||
*/
|
||||
bool
|
||||
Opponent::isQuickerTeammate(tCarElt * const mycar) {
|
||||
return (isTeammate()
|
||||
&& (mycar->_dammage - m_car->_dammage > KDriver::TEAM_DAMAGE_CHANGE_LEAD));
|
||||
} // isQuickerTeammate
|
||||
if (overlap_timer_ > OVERLAP_WAIT_TIME)
|
||||
state_ |= OPP_LETPASS;
|
||||
} // UpdateOverlapTimer
|
||||
|
||||
|
||||
/**
|
||||
|
@ -216,11 +197,11 @@ Opponent::isQuickerTeammate(tCarElt * const mycar) {
|
|||
* @param c Opponent car data
|
||||
*/
|
||||
Opponents::Opponents(tSituation *s, KDriver *driver, Cardata *c) {
|
||||
m_opps = new list<Opponent>;
|
||||
const tCarElt *ownCar = driver->getCarPtr();
|
||||
opps_ = new list<Opponent>;
|
||||
const tCarElt *ownCar = driver->car_ptr();
|
||||
|
||||
// Step through all the cars
|
||||
for (int i = 0; i < s->_ncars; i++) {
|
||||
for (int i = 0; i < s->_ncars; ++i) {
|
||||
// If it is not our own car
|
||||
if (s->cars[i] != ownCar) {
|
||||
// Create and set up new opponent
|
||||
|
@ -228,46 +209,44 @@ Opponents::Opponents(tSituation *s, KDriver *driver, Cardata *c) {
|
|||
s->cars[i], // car ptr
|
||||
c->findCar(s->cars[i]), // car data ptr
|
||||
i); // index
|
||||
m_opps->push_back(opp); // Store it in list
|
||||
opps_->push_back(opp); // Store it in list
|
||||
} // if s->cars[i]
|
||||
} // for i
|
||||
|
||||
Opponent::setTrackPtr(driver->getTrackPtr());
|
||||
} // Opponents::Opponents
|
||||
|
||||
|
||||
/**
|
||||
* update
|
||||
* Update
|
||||
* Makes every opponent update its own data.
|
||||
*
|
||||
* @param s Situation provided by TORCS
|
||||
* @param driver Our own robot
|
||||
*/
|
||||
void Opponents::update(tSituation *s, KDriver *driver) {
|
||||
void Opponents::Update(tSituation *s, KDriver *driver) {
|
||||
// for_each(begin(), end(), update);
|
||||
for (list<Opponent>::iterator it = begin(); it != end(); it++)
|
||||
it->update(s, driver);
|
||||
} // update
|
||||
for (list<Opponent>::iterator it = begin(); it != end(); ++it)
|
||||
it->Update(s, driver);
|
||||
} // Update
|
||||
|
||||
|
||||
// for find()
|
||||
inline bool operator==(const Opponent& o, const std::string s)
|
||||
{ return !s.compare(o.getCarPtr()->_name); }
|
||||
{ return !s.compare(o.car_ptr()->_name); }
|
||||
/**
|
||||
* setTeamMate
|
||||
* SetTeamMate
|
||||
* Search the opponent list for our own teammate,
|
||||
* based on the teammate name given in the config as "teammate".
|
||||
*
|
||||
* @param car Our own car, to read its config
|
||||
*/
|
||||
void Opponents::setTeamMate(const tCarElt *car) {
|
||||
void Opponents::SetTeamMate(const tCarElt *car) {
|
||||
string teammate(
|
||||
GfParmGetStr(car->_paramsHandle, KILO_SECT_PRIV, KILO_ATT_TEAMMATE, ""));
|
||||
|
||||
list<Opponent>::iterator found = find(begin(), end(), teammate);
|
||||
if (found != end())
|
||||
found->markAsTeamMate();
|
||||
} // setTeamMate
|
||||
found->set_teammate();
|
||||
} // SetTeamMate
|
||||
|
||||
|
||||
/**
|
||||
|
@ -276,13 +255,102 @@ void Opponents::setTeamMate(const tCarElt *car) {
|
|||
* @param [in] state: we only care for an opponent in this state
|
||||
* @return pointer to the opponent we've found, or NULL
|
||||
*/
|
||||
Opponent * Opponents::getOppByState(const int state) {
|
||||
Opponent * Opponents::GetOppByState(const int state) {
|
||||
Opponent *ret = NULL;
|
||||
for (list<Opponent>::iterator it = begin(); it != end(); it++) {
|
||||
if (it->isState(state)) {
|
||||
for (list<Opponent>::iterator it = begin(); it != end(); ++it) {
|
||||
if (it->HasState(state)) {
|
||||
ret = &(*it);
|
||||
break;
|
||||
}
|
||||
} // for it
|
||||
return ret;
|
||||
} // getOppByState
|
||||
} // GetOppByState
|
||||
|
||||
|
||||
/**
|
||||
* Decide if there is a car on the side we are to collide with...
|
||||
*
|
||||
* @param[in] car Our own car
|
||||
* @return Side collision car pointer or NULL
|
||||
*/
|
||||
Opponent * Opponents::GetSidecollOpp(const tCarElt *car) {
|
||||
Opponent *ret = NULL;
|
||||
for (list<Opponent>::iterator it = begin(); it != end(); ++it) {
|
||||
tCarElt *ocar = it->car_ptr();
|
||||
|
||||
if (ocar->_state > RM_CAR_STATE_PIT) // Dont care for opponents in the pit
|
||||
continue;
|
||||
|
||||
// if opp is too far on side
|
||||
if (it->IsTooFarOnSide(car))
|
||||
continue;
|
||||
|
||||
if (it->HasState(OPP_SIDE)) { // If opponent is on our side
|
||||
ret = &(*it);
|
||||
break;
|
||||
} // if OPP_SIDE
|
||||
} // for it
|
||||
|
||||
return ret;
|
||||
} // GetSidecollOpp
|
||||
|
||||
|
||||
/**
|
||||
* Decide if there is a car behind overlapping us.
|
||||
*
|
||||
* A1) Teammate behind with more laps should overtake.
|
||||
* A2) Slipstreaming: the less damaged teammate is also allowed to pass
|
||||
* if on the same lap.
|
||||
* The position change happens when the damage difference is greater
|
||||
* than TEAM_DAMAGE_CHANGE_LEAD.
|
||||
* B) Let other, overlapping opponents get by.
|
||||
|
||||
* @return overlapping car pointer or NULL
|
||||
*/
|
||||
Opponent * Opponents::GetOverlappingOpp(const tCarElt *car) {
|
||||
Opponent *ret = NULL;
|
||||
double mindist = -1000.0;
|
||||
|
||||
for (list<Opponent>::iterator it = begin(); it != end(); ++it) {
|
||||
tCarElt *ocar = it->car_ptr();
|
||||
double oppDistance = it->distance();
|
||||
|
||||
if (( // If teammate has more laps under his belt,
|
||||
(it->teammate() && ocar->race.laps > car->race.laps)
|
||||
|| // or teammate is less damaged, let him go
|
||||
it->IsQuickerTeammate(car))
|
||||
&& (oppDistance > -TEAM_REAR_DIST) // if close enough
|
||||
&& (oppDistance < -car->_dimension_x)) {
|
||||
// Behind, larger distances are smaller ("more negative").
|
||||
if (oppDistance > mindist) {
|
||||
mindist = oppDistance;
|
||||
ret = &(*it);
|
||||
}
|
||||
} else if (it->HasState(OPP_LETPASS)) {
|
||||
// Behind, larger distances are smaller ("more negative").
|
||||
if (oppDistance > mindist) {
|
||||
mindist = oppDistance;
|
||||
ret = &(*it);
|
||||
}
|
||||
} // else if
|
||||
} // for i
|
||||
|
||||
return ret;
|
||||
} // GetOverlappingOpp
|
||||
|
||||
|
||||
/**
|
||||
* Checks if opponent is too much on either side of the track,
|
||||
* (doesn't occupy center part of the segment)
|
||||
* and whether we are 5+ metres far.
|
||||
*
|
||||
* @param [in] ocar the opponent car
|
||||
* @return true if the opp. is too far on either side
|
||||
*/
|
||||
bool Opponent::IsTooFarOnSide(const tCarElt *mycar) const {
|
||||
bool ret = false;
|
||||
if (fabs(car_->_trkPos.toMiddle) > mycar->_trkPos.seg->width / 2 + 3.0
|
||||
&& fabs(mycar->_trkPos.toMiddle - car_->_trkPos.toMiddle) >= 5.0)
|
||||
ret = true;
|
||||
return ret;
|
||||
} // IsTooFarOnSide
|
||||
|
|
|
@ -50,49 +50,45 @@ class Opponent {
|
|||
public:
|
||||
Opponent(tCarElt *car, SingleCardata *cardata, int index);
|
||||
|
||||
static void setTrackPtr(tTrack * const track) {Opponent::m_track = track;}
|
||||
|
||||
tCarElt *getCarPtr() const {return m_car;}
|
||||
double getDistance() const {return m_distance;}
|
||||
double getWidth() const {return m_cardata->getWidthOnTrack();}
|
||||
double getSpeed() const {return m_cardata->getSpeedInTrackDirection();}
|
||||
int getIndex() const {return m_index;}
|
||||
// Accessors
|
||||
inline tCarElt *car_ptr() const { return car_; }
|
||||
inline double distance() const { return distance_; }
|
||||
inline double width() const { return cardata_->getWidthOnTrack(); }
|
||||
inline double speed() const { return cardata_->getSpeedInTrackDirection(); }
|
||||
inline int index() const { return index_; }
|
||||
inline bool teammate() const { return teammate_; }
|
||||
|
||||
inline bool isState(const int state) const
|
||||
{ return static_cast<bool>(m_state & state); }
|
||||
inline bool isTeammate() const {return m_teammate;}
|
||||
bool isQuickerTeammate(tCarElt * const mycar);
|
||||
inline bool isOnRight(const double dMiddle)
|
||||
{ return (dMiddle > m_car->_trkPos.toMiddle) ? true : false; }
|
||||
// State queries
|
||||
inline bool HasState(const int state) const
|
||||
{ return static_cast<bool>(state_ & state); }
|
||||
inline bool IsQuickerTeammate(const tCarElt *mycar) const
|
||||
{ return (teammate_
|
||||
&& (mycar->_dammage - car_->_dammage > TEAM_DAMAGE_CHANGE_LEAD));}
|
||||
inline bool IsOnRight(const double dMiddle) const
|
||||
{ return (dMiddle > car_->_trkPos.toMiddle) ? true : false; }
|
||||
bool IsTooFarOnSide(const tCarElt *mycar) const;
|
||||
|
||||
// Mutators
|
||||
inline void set_teammate() {teammate_ = true;}
|
||||
void Update(tSituation *s, KDriver *driver);
|
||||
|
||||
inline void markAsTeamMate() {m_teammate = true;}
|
||||
void update(tSituation *s, KDriver *driver);
|
||||
|
||||
private:
|
||||
double getDistToSegStart() const;
|
||||
void updateOverlapTimer(tSituation * const s, tCarElt * const mycar);
|
||||
// distance minus opponent car length
|
||||
inline double brake_distance() const {return distance_ - car_->_dimension_x;}
|
||||
inline double DistToSegStart() const;
|
||||
void UpdateOverlapTimer(tSituation * const s, tCarElt * const mycar);
|
||||
|
||||
// approximation of the real distance, negative if the opponent is behind.
|
||||
double m_distance;
|
||||
// distance minus opponent car length
|
||||
double m_brakedistance;
|
||||
// distance needed to catch the opponent (linear estimate).
|
||||
double m_catchdist;
|
||||
// approx distance of center of gravity of the cars.
|
||||
double m_sidedist;
|
||||
// State variable to characterize the relation to the opponent,
|
||||
// e. g. opponent is behind.
|
||||
int m_state;
|
||||
int m_index;
|
||||
double m_overlaptimer;
|
||||
double distance_;
|
||||
|
||||
tCarElt *m_car;
|
||||
SingleCardata *m_cardata; // Pointer to global data about this opponent.
|
||||
bool m_teammate; // Is this opponent a team mate of me
|
||||
// TODO(kilo): configure it in setup XML?
|
||||
|
||||
// class variables.
|
||||
static tTrack *m_track;
|
||||
int state_; // State describes the relation to the opp, eg. opp is behind
|
||||
int index_;
|
||||
double overlap_timer_;
|
||||
tCarElt *car_;
|
||||
SingleCardata *cardata_; // Pointer to global data about this opponent.
|
||||
bool teammate_; // Is this opponent a team mate of me
|
||||
|
||||
// constants.
|
||||
static const double FRONTCOLLDIST;
|
||||
|
@ -103,6 +99,7 @@ class Opponent {
|
|||
static const double LAP_BACK_TIME_PENALTY;
|
||||
static const double OVERLAP_WAIT_TIME;
|
||||
static const double SPEED_PASS_MARGIN;
|
||||
static const int TEAM_DAMAGE_CHANGE_LEAD;
|
||||
};
|
||||
|
||||
|
||||
|
@ -111,17 +108,20 @@ class Opponent {
|
|||
class Opponents {
|
||||
public:
|
||||
Opponents(tSituation *s, KDriver *driver, Cardata *cardata);
|
||||
~Opponents() {delete m_opps;}
|
||||
~Opponents() { if (opps_ != NULL) delete opps_;}
|
||||
|
||||
void update(tSituation *s, KDriver *driver);
|
||||
void setTeamMate(const tCarElt *car);
|
||||
Opponent *getOppByState(const int state);
|
||||
void Update(tSituation *s, KDriver *driver);
|
||||
void SetTeamMate(const tCarElt *car);
|
||||
Opponent *GetOppByState(const int state);
|
||||
Opponent *GetSidecollOpp(const tCarElt *car);
|
||||
Opponent *GetOverlappingOpp(const tCarElt *car);
|
||||
|
||||
inline std::list<Opponent>::iterator begin() {return m_opps->begin();}
|
||||
inline std::list<Opponent>::iterator end() {return m_opps->end();}
|
||||
inline std::list<Opponent>::iterator begin() {return opps_->begin();}
|
||||
inline std::list<Opponent>::iterator end() {return opps_->end();}
|
||||
|
||||
private:
|
||||
std::list<Opponent> *m_opps;
|
||||
std::list<Opponent> *opps_;
|
||||
static const double TEAM_REAR_DIST;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -32,160 +32,160 @@ const double Pit::SPEED_LIMIT_MARGIN = 0.5;
|
|||
|
||||
|
||||
Pit::Pit(const tSituation * s, KDriver * driver, const double pitoffset) {
|
||||
m_track = driver->getTrackPtr();
|
||||
m_car = driver->getCarPtr();
|
||||
m_mypit = driver->getCarPtr()->_pit;
|
||||
m_pitinfo = &m_track->pits;
|
||||
m_pitstop = m_inpitlane = false;
|
||||
m_pittimer = 0.0;
|
||||
track_ = driver->track_ptr();
|
||||
car_ = driver->car_ptr();
|
||||
mypit_ = driver->car_ptr()->_pit;
|
||||
pitinfo_ = &track_->pits;
|
||||
pit_planned_ = in_pitlane_ = false;
|
||||
pit_timer_ = 0.0;
|
||||
|
||||
if (m_mypit != NULL) {
|
||||
m_speedlimit = m_pitinfo->speedLimit - SPEED_LIMIT_MARGIN;
|
||||
m_speedlimitsqr = pow(m_speedlimit, 2);
|
||||
m_pitspeedlimitsqr = pow(m_pitinfo->speedLimit, 2);
|
||||
if (mypit_ != NULL) {
|
||||
speed_limit_ = pitinfo_->speedLimit - SPEED_LIMIT_MARGIN;
|
||||
pit_speed_limit_sqr_ = pow(pitinfo_->speedLimit, 2);
|
||||
|
||||
// Compute pit spline points along the track.
|
||||
m_p[3].x = m_mypit->pos.seg->lgfromstart + m_mypit->pos.toStart;
|
||||
m_p[2].x = m_p[3].x - m_pitinfo->len;
|
||||
m_p[4].x = m_p[3].x + m_pitinfo->len;
|
||||
m_p[0].x = m_pitinfo->pitEntry->lgfromstart + pitoffset;
|
||||
m_p[1].x = m_pitinfo->pitStart->lgfromstart;
|
||||
points_[3].x = mypit_->pos.seg->lgfromstart + mypit_->pos.toStart;
|
||||
points_[2].x = points_[3].x - pitinfo_->len;
|
||||
points_[4].x = points_[3].x + pitinfo_->len;
|
||||
points_[0].x = pitinfo_->pitEntry->lgfromstart + pitoffset;
|
||||
points_[1].x = pitinfo_->pitStart->lgfromstart;
|
||||
// Use nPitSeg to respect the pit speed limit on Migrants e.a.
|
||||
m_p[5].x = m_pitinfo->pitStart->lgfromstart
|
||||
+ m_pitinfo->nPitSeg * m_pitinfo->len;
|
||||
m_p[6].x = m_pitinfo->pitExit->lgfromstart;
|
||||
points_[5].x = pitinfo_->pitStart->lgfromstart
|
||||
+ pitinfo_->nPitSeg * pitinfo_->len;
|
||||
points_[6].x = pitinfo_->pitExit->lgfromstart;
|
||||
|
||||
m_pitentry = m_p[0].x;
|
||||
m_pitexit = m_p[6].x;
|
||||
pit_entry_ = points_[0].x;
|
||||
pit_exit_ = points_[6].x;
|
||||
|
||||
// Normalizing spline segments to >= 0.0.
|
||||
for (int i = 0; i < NPOINTS; i++) {
|
||||
m_p[i].s = 0.0;
|
||||
m_p[i].x = toSplineCoord(m_p[i].x);
|
||||
points_[i].s = 0.0;
|
||||
points_[i].x = ToSplineCoord(points_[i].x);
|
||||
} // for i
|
||||
|
||||
// Fix broken pit exit.
|
||||
if (m_p[6].x < m_p[5].x)
|
||||
m_p[6].x = m_p[5].x + 50.0;
|
||||
if (points_[6].x < points_[5].x)
|
||||
points_[6].x = points_[5].x + 50.0;
|
||||
|
||||
// Fix point for first pit if necessary.
|
||||
if (m_p[1].x > m_p[2].x)
|
||||
m_p[1].x = m_p[2].x;
|
||||
if (points_[1].x > points_[2].x)
|
||||
points_[1].x = points_[2].x;
|
||||
|
||||
// Fix point for last pit if necessary.
|
||||
if (m_p[4].x > m_p[5].x)
|
||||
m_p[5].x = m_p[4].x;
|
||||
if (points_[4].x > points_[5].x)
|
||||
points_[5].x = points_[4].x;
|
||||
|
||||
double sign = (m_pitinfo->side == TR_LFT) ? 1.0 : -1.0;
|
||||
m_p[0].y = 0.0;
|
||||
m_p[6].y = 0.0;
|
||||
double sign = (pitinfo_->side == TR_LFT) ? 1.0 : -1.0;
|
||||
points_[0].y = 0.0;
|
||||
points_[6].y = 0.0;
|
||||
for (int i = 1; i < NPOINTS - 1; i++) {
|
||||
m_p[i].y = fabs(m_pitinfo->driversPits->pos.toMiddle) - m_pitinfo->width;
|
||||
m_p[i].y *= sign;
|
||||
points_[i].y = fabs(pitinfo_->driversPits->pos.toMiddle)
|
||||
- pitinfo_->width;
|
||||
points_[i].y *= sign;
|
||||
} // for i
|
||||
|
||||
m_p[3].y = fabs(m_pitinfo->driversPits->pos.toMiddle + 1.0) * sign;
|
||||
m_spline = new Spline(NPOINTS, m_p);
|
||||
points_[3].y = fabs(pitinfo_->driversPits->pos.toMiddle + 1.0) * sign;
|
||||
spline_ = new Spline(NPOINTS, points_);
|
||||
} // if pit not null
|
||||
} // Pit::Pit
|
||||
|
||||
|
||||
Pit::~Pit() {
|
||||
if (m_mypit != NULL)
|
||||
delete m_spline;
|
||||
if (mypit_ != NULL)
|
||||
delete spline_;
|
||||
} // Pit::~Pit
|
||||
|
||||
|
||||
// Transforms track coordinates to spline parameter coordinates.
|
||||
double Pit::toSplineCoord(const double x) const {
|
||||
double ret = x - m_pitentry;
|
||||
double Pit::ToSplineCoord(const double x) const {
|
||||
double ret = x - pit_entry_;
|
||||
while (ret < 0.0)
|
||||
ret += m_track->length;
|
||||
ret += track_->length;
|
||||
|
||||
return ret;
|
||||
} // toSplineCoord
|
||||
} // ToSplineCoord
|
||||
|
||||
|
||||
// Computes offset to track middle for trajectory.
|
||||
double Pit::getPitOffset(const double offset, double fromstart) {
|
||||
if (m_mypit != NULL) {
|
||||
if (getInPit() || (getPitstop() && isBetween(fromstart))) {
|
||||
fromstart = toSplineCoord(fromstart);
|
||||
return m_spline->evaluate(fromstart);
|
||||
double Pit::CalcPitOffset(const double offset, double fromstart) {
|
||||
if (mypit_ != NULL) {
|
||||
if (in_pitlane() || (pit_planned() && is_between(fromstart))) {
|
||||
fromstart = ToSplineCoord(fromstart);
|
||||
return spline_->evaluate(fromstart);
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
} // getPitOffset
|
||||
} // CalcPitOffset
|
||||
|
||||
|
||||
// Sets the pitstop flag if we are not in the pit range.
|
||||
void Pit::setPitstop(bool pitstop) {
|
||||
if (m_mypit != NULL) {
|
||||
double fromstart = m_car->_distFromStartLine;
|
||||
void Pit::set_pitstop(bool pitstop) {
|
||||
if (mypit_ != NULL) {
|
||||
double fromstart = car_->_distFromStartLine;
|
||||
|
||||
if (!isBetween(fromstart)) {
|
||||
m_pitstop = pitstop;
|
||||
if (!is_between(fromstart)) {
|
||||
pit_planned_ = pitstop;
|
||||
} else {
|
||||
if (!pitstop) {
|
||||
m_pitstop = pitstop;
|
||||
m_pittimer = 0.0;
|
||||
pit_planned_ = pitstop;
|
||||
pit_timer_ = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // setPitstop
|
||||
} // set_pitstop
|
||||
|
||||
|
||||
// Check if the argument fromstart is in the range of the pit.
|
||||
bool Pit::isBetween(const double fromstart) const {
|
||||
bool Pit::is_between(const double fromstart) const {
|
||||
bool ret = false;
|
||||
|
||||
if (m_pitentry <= m_pitexit) {
|
||||
if (fromstart >= m_pitentry && fromstart <= m_pitexit) {
|
||||
if (pit_entry_ <= pit_exit_) {
|
||||
if (fromstart >= pit_entry_ && fromstart <= pit_exit_) {
|
||||
ret = true;
|
||||
}
|
||||
} else {
|
||||
// Warning: TORCS reports sometimes negative values for "fromstart"!
|
||||
if (fromstart <= m_pitexit || fromstart >= m_pitentry) {
|
||||
if (fromstart <= pit_exit_ || fromstart >= pit_entry_) {
|
||||
ret = true;
|
||||
}
|
||||
} // if pitentry <= pitexit
|
||||
|
||||
return ret;
|
||||
} // isBetween
|
||||
} // is_between
|
||||
|
||||
|
||||
// Checks if we stay too long without getting captured by the pit.
|
||||
// Distance is the distance to the pit along the track, when the pit is
|
||||
// ahead it is > 0, if we overshoot the pit it is < 0.
|
||||
bool Pit::isTimeout(const double distance) {
|
||||
bool Pit::is_timeout(const double distance) {
|
||||
bool ret = false;
|
||||
|
||||
if (m_car->_speed_x > 1.0 || distance > 3.0 || !getPitstop()) {
|
||||
m_pittimer = 0.0;
|
||||
if (car_->_speed_x > 1.0 || distance > 3.0 || !pit_planned()) {
|
||||
pit_timer_ = 0.0;
|
||||
} else {
|
||||
m_pittimer += RCM_MAX_DT_ROBOTS;
|
||||
if (m_pittimer > 3.0) {
|
||||
m_pittimer = 0.0;
|
||||
pit_timer_ += RCM_MAX_DT_ROBOTS;
|
||||
if (pit_timer_ > 3.0) {
|
||||
pit_timer_ = 0.0;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
} // isTimeout
|
||||
} // is_timeout
|
||||
|
||||
|
||||
// Update pit data and strategy.
|
||||
void Pit::update() {
|
||||
if (m_mypit != NULL) {
|
||||
if (isBetween(m_car->_distFromStartLine)) {
|
||||
if (getPitstop()) {
|
||||
setInPit(true);
|
||||
void Pit::Update() {
|
||||
if (mypit_ != NULL) {
|
||||
if (is_between(car_->_distFromStartLine)) {
|
||||
if (pit_planned()) {
|
||||
in_pitlane_ = true;
|
||||
}
|
||||
} else {
|
||||
setInPit(false);
|
||||
in_pitlane_ = false;
|
||||
}
|
||||
|
||||
if (getPitstop())
|
||||
m_car->_raceCmd = RM_CMD_PIT_ASKED;
|
||||
if (pit_planned())
|
||||
car_->_raceCmd = RM_CMD_PIT_ASKED;
|
||||
}
|
||||
} // update
|
||||
} // Update
|
||||
|
|
|
@ -36,52 +36,47 @@ class Pit {
|
|||
Pit(const tSituation * s, KDriver * driver, const double PitOffset);
|
||||
~Pit();
|
||||
|
||||
void setPitstop(const bool pitstop);
|
||||
inline bool getPitstop() const {return m_pitstop;}
|
||||
inline void setInPit(const bool inpitlane) {m_inpitlane = inpitlane;}
|
||||
inline bool getInPit() const {return m_inpitlane;}
|
||||
inline bool pit_planned() const { return pit_planned_; }
|
||||
inline bool in_pitlane() const { return in_pitlane_; }
|
||||
inline double speed_limit() const { return speed_limit_; }
|
||||
inline double speed_limit_sqr() const { return pow(speed_limit_, 2); }
|
||||
|
||||
double getPitOffset(const double offset, double fromstart);
|
||||
inline double n_start() const { return points_[1].x; }
|
||||
inline double n_loc() const { return points_[3].x; }
|
||||
inline double n_end() const { return points_[5].x; }
|
||||
inline double n_entry() const { return points_[0].x; }
|
||||
|
||||
bool isBetween(const double fromstart) const;
|
||||
bool isTimeout(const double distance);
|
||||
inline double speed_limit_brake(const double speedsqr) const
|
||||
{ return (speedsqr - speed_limit_sqr())
|
||||
/ (pit_speed_limit_sqr_ - speed_limit_sqr()); }
|
||||
|
||||
inline double getNPitStart() const {return m_p[1].x;}
|
||||
inline double getNPitLoc() const {return m_p[3].x;}
|
||||
inline double getNPitEnd() const {return m_p[5].x;}
|
||||
inline double getNPitEntry() const {return m_p[0].x;}
|
||||
|
||||
double toSplineCoord(double x) const;
|
||||
|
||||
inline double getSpeedlimitSqr() const {return m_speedlimitsqr;}
|
||||
inline double getSpeedlimit() const {return m_speedlimit;}
|
||||
inline double getSpeedLimitBrake(const double speedsqr) const
|
||||
{return (speedsqr - m_speedlimitsqr)
|
||||
/ (m_pitspeedlimitsqr - m_speedlimitsqr);}
|
||||
|
||||
void update();
|
||||
void set_pitstop(const bool pitstop);
|
||||
bool is_timeout(const double distance);
|
||||
double CalcPitOffset(const double offset, double fromstart);
|
||||
double ToSplineCoord(double x) const;
|
||||
void Update();
|
||||
|
||||
private:
|
||||
tTrack *m_track;
|
||||
tCarElt *m_car;
|
||||
tTrackOwnPit *m_mypit; // Pointer to my pit.
|
||||
tTrackPitInfo *m_pitinfo; // General pit info.
|
||||
bool is_between(const double fromstart) const;
|
||||
|
||||
enum
|
||||
{ NPOINTS = 7 };
|
||||
SplinePoint m_p[NPOINTS]; // Spline points.
|
||||
Spline *m_spline; // Spline.
|
||||
tTrack *track_;
|
||||
tCarElt *car_;
|
||||
tTrackOwnPit *mypit_; // Pointer to my pit.
|
||||
tTrackPitInfo *pitinfo_; // General pit info.
|
||||
|
||||
bool m_pitstop; // Pitstop planned.
|
||||
bool m_inpitlane; // We are still in the pit lane.
|
||||
double m_pitentry; // Distance to start line of the pit entry.
|
||||
double m_pitexit; // Distance to the start line of the pit exit.
|
||||
enum { NPOINTS = 7 };
|
||||
SplinePoint points_[NPOINTS]; // Spline points.
|
||||
Spline *spline_; // Spline.
|
||||
|
||||
double m_speedlimitsqr; // Pit speed limit squared.
|
||||
double m_speedlimit; // Pit speed limit.
|
||||
double m_pitspeedlimitsqr; // The original speedlimit squared.
|
||||
bool pit_planned_; // Pitstop planned.
|
||||
bool in_pitlane_; // We are still in the pit lane.
|
||||
double pit_entry_; // Distance to start line of the pit entry.
|
||||
double pit_exit_; // Distance to the start line of the pit exit.
|
||||
|
||||
double m_pittimer; // Timer for pit timeouts.
|
||||
double speed_limit_; // Pit speed limit.
|
||||
double pit_speed_limit_sqr_; // The original speedlimit squared.
|
||||
|
||||
double pit_timer_; // Timer for pit timeouts.
|
||||
|
||||
static const double SPEED_LIMIT_MARGIN;
|
||||
};
|
||||
|
|
|
@ -77,7 +77,7 @@ void LRaceLine::SetSegmentInfo(const tTrackSeg * pseg,
|
|||
const int i, const double l) {
|
||||
if (pseg) {
|
||||
std::pair<int, double> info(i, l);
|
||||
m_SegInfo.push_back(info);
|
||||
seg_info_.push_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ void LRaceLine::SetSegmentInfo(const tTrackSeg * pseg,
|
|||
void LRaceLine::SplitTrack(const tTrack * const ptrack,
|
||||
const int rl,
|
||||
const tSituation *s) {
|
||||
m_lDivLength = 3; // Length of path elements in meters
|
||||
div_length_ = 3; // Length of path elements in meters
|
||||
const tTrackSeg *psegCurrent = ptrack->seg;
|
||||
|
||||
double dAngle = psegCurrent->angle[TR_ZS];
|
||||
|
@ -115,10 +115,10 @@ void LRaceLine::SplitTrack(const tTrack * const ptrack,
|
|||
} // if pits.type
|
||||
|
||||
|
||||
m_SegInfo.reserve(ptrack->nseg);
|
||||
seg_info_.reserve(ptrack->nseg);
|
||||
unsigned int i = 0;
|
||||
do {
|
||||
int Divisions = static_cast<int>(psegCurrent->length / m_lDivLength) + 1;
|
||||
int Divisions = static_cast<int>(psegCurrent->length / div_length_) + 1;
|
||||
double Step = psegCurrent->length / Divisions;
|
||||
|
||||
SetSegmentInfo(psegCurrent, i, Step);
|
||||
|
@ -220,30 +220,30 @@ void LRaceLine::SplitTrack(const tTrack * const ptrack,
|
|||
double dx = -psegCurrent->width * sin(dAngle) / 2;
|
||||
double dy = psegCurrent->width * cos(dAngle) / 2;
|
||||
|
||||
if (m_Seg.size() <= i) { // if it is the first run
|
||||
if (seg_.size() <= i) { // if it is the first run
|
||||
// Create & store new segment
|
||||
rlSegment *newSeg = new rlSegment;
|
||||
m_Seg.push_back(*newSeg);
|
||||
seg_.push_back(*newSeg);
|
||||
delete newSeg;
|
||||
}
|
||||
|
||||
// We can be quite sure m_Seg[i] exists as we created it just above
|
||||
m_Seg[i].txLeft = dXPos + dx;
|
||||
m_Seg[i].tyLeft = dYPos + dy;
|
||||
m_Seg[i].txRight = dXPos - dx;
|
||||
m_Seg[i].tyRight = dYPos - dy;
|
||||
m_Seg[i].tLane = 0.5;
|
||||
m_Seg[i].tLaneLMargin = lft_margin;
|
||||
m_Seg[i].tLaneRMargin = rgt_margin;
|
||||
m_Seg[i].tFriction = psegCurrent->surface->kFriction;
|
||||
SetSegCamber(psegCurrent, i);
|
||||
// We can be quite sure seg_[i] exists as we created it just above
|
||||
seg_[i].txLeft = dXPos + dx;
|
||||
seg_[i].tyLeft = dYPos + dy;
|
||||
seg_[i].txRight = dXPos - dx;
|
||||
seg_[i].tyRight = dYPos - dy;
|
||||
seg_[i].tLane = 0.5;
|
||||
seg_[i].tLaneLMargin = lft_margin;
|
||||
seg_[i].tLaneRMargin = rgt_margin;
|
||||
seg_[i].tFriction = psegCurrent->surface->kFriction;
|
||||
SetSegmentCamber(psegCurrent, i);
|
||||
// cerr << i << " " << psegCurrent->name << endl;
|
||||
|
||||
// ??? ugly trick for dirt
|
||||
// if (m_Seg[i].tFriction < 1)
|
||||
// m_Seg[i].tFriction *= 0.90;
|
||||
// if (seg_[i].tFriction < 1)
|
||||
// seg_[i].tFriction *= 0.90;
|
||||
|
||||
m_Seg[i].UpdateTxTy(rl);
|
||||
seg_[i].UpdateTxTy(rl);
|
||||
|
||||
i++;
|
||||
} // for j
|
||||
|
@ -251,26 +251,26 @@ void LRaceLine::SplitTrack(const tTrack * const ptrack,
|
|||
psegCurrent = psegCurrent->next;
|
||||
} while (psegCurrent != ptrack->seg);
|
||||
|
||||
m_cDivs = i - 1; // m_Seg.size-1!
|
||||
m_dWidth = psegCurrent->width;
|
||||
divs_ = i - 1; // seg_.size-1!
|
||||
width_ = psegCurrent->width;
|
||||
} // SplitTrack
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Compute the inverse of the radius
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
double LRaceLine::getRInverse(const int prev,
|
||||
double LRaceLine::rinverse(const int prev,
|
||||
const double x,
|
||||
const double y,
|
||||
const int next,
|
||||
const int rl) const {
|
||||
// vector<rlSegment>::iterator itNext = m_Seg[next];
|
||||
double x1 = m_Seg[next].tx[rl] - x;
|
||||
double y1 = m_Seg[next].ty[rl] - y;
|
||||
double x2 = m_Seg[prev].tx[rl] - x;
|
||||
double y2 = m_Seg[prev].ty[rl] - y;
|
||||
double x3 = m_Seg[next].tx[rl] - m_Seg[prev].tx[rl];
|
||||
double y3 = m_Seg[next].ty[rl] - m_Seg[prev].ty[rl];
|
||||
// vector<rlSegment>::iterator itNext = seg_[next];
|
||||
double x1 = seg_[next].tx[rl] - x;
|
||||
double y1 = seg_[next].ty[rl] - y;
|
||||
double x2 = seg_[prev].tx[rl] - x;
|
||||
double y2 = seg_[prev].ty[rl] - y;
|
||||
double x3 = seg_[next].tx[rl] - seg_[prev].tx[rl];
|
||||
double y3 = seg_[next].ty[rl] - seg_[prev].ty[rl];
|
||||
|
||||
double det = x1 * y2 - x2 * y1;
|
||||
double n1 = x1 * x1 + y1 * y1;
|
||||
|
@ -279,7 +279,7 @@ double LRaceLine::getRInverse(const int prev,
|
|||
double nnn = sqrt(n1 * n2 * n3);
|
||||
|
||||
return 2 * det / nnn;
|
||||
} // getRInverse
|
||||
} // rinverse
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -288,53 +288,53 @@ double LRaceLine::getRInverse(const int prev,
|
|||
void LRaceLine::AdjustRadius(int prev, int i, int next,
|
||||
double TargetRInverse, int rl,
|
||||
double Security) {
|
||||
double OldLane = m_Seg[i].tLane;
|
||||
double OldLane = seg_[i].tLane;
|
||||
|
||||
// Start by aligning points for a reasonable initial lane
|
||||
m_Seg[i].tLane = (-(m_Seg[next].ty[rl] - m_Seg[prev].ty[rl])
|
||||
* (m_Seg[i].txLeft - m_Seg[prev].tx[rl])
|
||||
+ (m_Seg[next].tx[rl] - m_Seg[prev].tx[rl])
|
||||
* (m_Seg[i].tyLeft - m_Seg[prev].ty[rl])) /
|
||||
((m_Seg[next].ty[rl] - m_Seg[prev].ty[rl])
|
||||
* (m_Seg[i].txRight - m_Seg[i].txLeft)
|
||||
- (m_Seg[next].tx[rl] - m_Seg[prev].tx[rl])
|
||||
* (m_Seg[i].tyRight - m_Seg[i].tyLeft));
|
||||
seg_[i].tLane = (-(seg_[next].ty[rl] - seg_[prev].ty[rl])
|
||||
* (seg_[i].txLeft - seg_[prev].tx[rl])
|
||||
+ (seg_[next].tx[rl] - seg_[prev].tx[rl])
|
||||
* (seg_[i].tyLeft - seg_[prev].ty[rl])) /
|
||||
((seg_[next].ty[rl] - seg_[prev].ty[rl])
|
||||
* (seg_[i].txRight - seg_[i].txLeft)
|
||||
- (seg_[next].tx[rl] - seg_[prev].tx[rl])
|
||||
* (seg_[i].tyRight - seg_[i].tyLeft));
|
||||
|
||||
if (rl == LINE_RL) {
|
||||
m_Seg[i].tLane = MAX(m_Seg[i].tLane, -1.2 - m_Seg[i].tLaneLMargin);
|
||||
m_Seg[i].tLane = MIN(m_Seg[i].tLane, 1.2 + m_Seg[i].tLaneRMargin);
|
||||
seg_[i].tLane = MAX(seg_[i].tLane, -1.2 - seg_[i].tLaneLMargin);
|
||||
seg_[i].tLane = MIN(seg_[i].tLane, 1.2 + seg_[i].tLaneRMargin);
|
||||
} // if rl
|
||||
m_Seg[i].UpdateTxTy(rl);
|
||||
seg_[i].UpdateTxTy(rl);
|
||||
|
||||
//
|
||||
// Newton-like resolution method
|
||||
//
|
||||
const double dLane = 0.0001;
|
||||
|
||||
double dx = dLane * (m_Seg[i].txRight - m_Seg[i].txLeft);
|
||||
double dy = dLane * (m_Seg[i].tyRight - m_Seg[i].tyLeft);
|
||||
double dx = dLane * (seg_[i].txRight - seg_[i].txLeft);
|
||||
double dy = dLane * (seg_[i].tyRight - seg_[i].tyLeft);
|
||||
|
||||
double dRInverse =
|
||||
getRInverse(prev, m_Seg[i].tx[rl] + dx, m_Seg[i].ty[rl] + dy, next, rl);
|
||||
rinverse(prev, seg_[i].tx[rl] + dx, seg_[i].ty[rl] + dy, next, rl);
|
||||
|
||||
if (dRInverse > 0.000000001) {
|
||||
m_Seg[i].tLane += (dLane / dRInverse) * TargetRInverse;
|
||||
seg_[i].tLane += (dLane / dRInverse) * TargetRInverse;
|
||||
|
||||
double ExtLane = MIN((m_dExtMargin + Security) / m_dWidth, 0.5);
|
||||
double IntLane = MIN((m_dIntMargin + Security) / m_dWidth, 0.5);
|
||||
double ExtLane = MIN((ext_margin_ + Security) / width_, 0.5);
|
||||
double IntLane = MIN((int_margin_ + Security) / width_, 0.5);
|
||||
// ~ //kilo HACK E-track-1
|
||||
// ~ if(BetweenLoose(i, 1077, 1112)) //bus-stop
|
||||
// ~ {
|
||||
// ~ //ExtLane = MIN((m_dExtMargin + 20.0) / m_dWidth, 0.5);
|
||||
// ~ //IntLane = MIN((m_dIntMargin + 0.0) / m_dWidth, 0.5);
|
||||
// ~ //ExtLane = MIN((ext_margin_ + 20.0) / width_, 0.5);
|
||||
// ~ //IntLane = MIN((int_margin_ + 0.0) / width_, 0.5);
|
||||
// ~ IntLane = 0.27;
|
||||
// ~ }
|
||||
// ~ //end kilo HACK
|
||||
// ~ //kilo HACK Alpine-2
|
||||
// ~ if(BetweenLoose(i, 1470, 1490)) //left-right bump after tunnel
|
||||
// ~ {
|
||||
// ExtLane = MIN((m_dExtMargin + 20.0) / m_dWidth, 0.5);
|
||||
// IntLane = MIN((m_dIntMargin + 0.0) / m_dWidth, 0.5);
|
||||
// ExtLane = MIN((ext_margin_ + 20.0) / width_, 0.5);
|
||||
// IntLane = MIN((int_margin_ + 0.0) / width_, 0.5);
|
||||
// ExtLane = 4.0;
|
||||
// IntLane = 0.3;
|
||||
// ~ }
|
||||
|
@ -342,64 +342,64 @@ void LRaceLine::AdjustRadius(int prev, int i, int next,
|
|||
|
||||
if (rl == LINE_RL) {
|
||||
if (TargetRInverse >= 0.0) {
|
||||
IntLane -= m_Seg[i].tLaneLMargin;
|
||||
ExtLane -= m_Seg[i].tLaneRMargin;
|
||||
IntLane -= seg_[i].tLaneLMargin;
|
||||
ExtLane -= seg_[i].tLaneRMargin;
|
||||
} else {
|
||||
ExtLane -= m_Seg[i].tLaneLMargin;
|
||||
IntLane -= m_Seg[i].tLaneRMargin;
|
||||
ExtLane -= seg_[i].tLaneLMargin;
|
||||
IntLane -= seg_[i].tLaneRMargin;
|
||||
}
|
||||
} // if rl
|
||||
|
||||
if (TargetRInverse >= 0.0) {
|
||||
if (m_Seg[i].tLane < IntLane)
|
||||
m_Seg[i].tLane = IntLane;
|
||||
if (seg_[i].tLane < IntLane)
|
||||
seg_[i].tLane = IntLane;
|
||||
|
||||
if (1 - m_Seg[i].tLane < ExtLane) {
|
||||
if (1 - seg_[i].tLane < ExtLane) {
|
||||
if (1 - OldLane < ExtLane) {
|
||||
m_Seg[i].tLane = MIN(OldLane, m_Seg[i].tLane);
|
||||
seg_[i].tLane = MIN(OldLane, seg_[i].tLane);
|
||||
} else {
|
||||
m_Seg[i].tLane = 1 - ExtLane;
|
||||
seg_[i].tLane = 1 - ExtLane;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (m_Seg[i].tLane < ExtLane) {
|
||||
if (seg_[i].tLane < ExtLane) {
|
||||
if (OldLane < ExtLane) {
|
||||
m_Seg[i].tLane = MAX(OldLane, m_Seg[i].tLane);
|
||||
seg_[i].tLane = MAX(OldLane, seg_[i].tLane);
|
||||
} else {
|
||||
m_Seg[i].tLane = ExtLane;
|
||||
seg_[i].tLane = ExtLane;
|
||||
}
|
||||
}
|
||||
|
||||
if (1 - m_Seg[i].tLane < IntLane)
|
||||
m_Seg[i].tLane = 1 - IntLane;
|
||||
if (1 - seg_[i].tLane < IntLane)
|
||||
seg_[i].tLane = 1 - IntLane;
|
||||
}
|
||||
}
|
||||
|
||||
m_Seg[i].UpdateTxTy(rl);
|
||||
seg_[i].UpdateTxTy(rl);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Smooth path
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void LRaceLine::Smooth(const int Step, const int rl) {
|
||||
int prev = ((m_cDivs - Step) / Step) * Step;
|
||||
int prev = ((divs_ - Step) / Step) * Step;
|
||||
int prevprev = prev - Step;
|
||||
int next = Step;
|
||||
int nextnext = next + Step;
|
||||
|
||||
for (int i = 0; i <= m_cDivs - Step; i += Step) {
|
||||
double ri0 = getRInverse(prevprev, m_Seg[prev].tx[rl],
|
||||
m_Seg[prev].ty[rl], i, rl);
|
||||
double ri1 = getRInverse(i, m_Seg[next].tx[rl],
|
||||
m_Seg[next].ty[rl], nextnext, rl);
|
||||
double lPrev = Mag(m_Seg[i].tx[rl] - m_Seg[prev].tx[rl],
|
||||
m_Seg[i].ty[rl] - m_Seg[prev].ty[rl]);
|
||||
double lNext = Mag(m_Seg[i].tx[rl] - m_Seg[next].tx[rl],
|
||||
m_Seg[i].ty[rl] - m_Seg[next].ty[rl]);
|
||||
for (int i = 0; i <= divs_ - Step; i += Step) {
|
||||
double ri0 = rinverse(prevprev, seg_[prev].tx[rl],
|
||||
seg_[prev].ty[rl], i, rl);
|
||||
double ri1 = rinverse(i, seg_[next].tx[rl],
|
||||
seg_[next].ty[rl], nextnext, rl);
|
||||
double lPrev = Mag(seg_[i].tx[rl] - seg_[prev].tx[rl],
|
||||
seg_[i].ty[rl] - seg_[prev].ty[rl]);
|
||||
double lNext = Mag(seg_[i].tx[rl] - seg_[next].tx[rl],
|
||||
seg_[i].ty[rl] - seg_[next].ty[rl]);
|
||||
|
||||
double TargetRInverse = (lNext * ri0 + lPrev * ri1) / (lNext + lPrev);
|
||||
|
||||
double Security = lPrev * lNext / (8 * m_dSecurityRadius);
|
||||
double Security = lPrev * lNext / (8 * security_radius_);
|
||||
|
||||
if (rl == LINE_RL) {
|
||||
if (ri0 * ri1 > 0) {
|
||||
|
@ -422,7 +422,7 @@ void LRaceLine::Smooth(const int Step, const int rl) {
|
|||
prev = i;
|
||||
next = nextnext;
|
||||
nextnext = next + Step;
|
||||
if (nextnext > m_cDivs - Step)
|
||||
if (nextnext > divs_ - Step)
|
||||
nextnext = 0;
|
||||
}
|
||||
} // Smooth
|
||||
|
@ -432,22 +432,22 @@ void LRaceLine::Smooth(const int Step, const int rl) {
|
|||
// Interpolate between two control points
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void LRaceLine::StepInterpolate(int iMin, int iMax, int Step, int rl) {
|
||||
int next = (iMax + Step) % m_cDivs;
|
||||
if (next > m_cDivs - Step)
|
||||
int next = (iMax + Step) % divs_;
|
||||
if (next > divs_ - Step)
|
||||
next = 0;
|
||||
|
||||
int prev = (((m_cDivs + iMin - Step) % m_cDivs) / Step) * Step;
|
||||
if (prev > m_cDivs - Step)
|
||||
int prev = (((divs_ + iMin - Step) % divs_) / Step) * Step;
|
||||
if (prev > divs_ - Step)
|
||||
prev -= Step;
|
||||
|
||||
double ir0 = getRInverse(prev, m_Seg[iMin].tx[rl],
|
||||
m_Seg[iMin].ty[rl], iMax % m_cDivs, rl);
|
||||
double ir1 = getRInverse(iMin, m_Seg[iMax % m_cDivs].tx[rl],
|
||||
m_Seg[iMax % m_cDivs].ty[rl], next, rl);
|
||||
double ir0 = rinverse(prev, seg_[iMin].tx[rl],
|
||||
seg_[iMin].ty[rl], iMax % divs_, rl);
|
||||
double ir1 = rinverse(iMin, seg_[iMax % divs_].tx[rl],
|
||||
seg_[iMax % divs_].ty[rl], next, rl);
|
||||
for (int k = iMax; --k > iMin;) {
|
||||
double x = static_cast<double>(k - iMin) / static_cast<double>(iMax - iMin);
|
||||
double TargetRInverse = x * ir1 + (1 - x) * ir0;
|
||||
AdjustRadius(iMin, k, iMax % m_cDivs, TargetRInverse, rl);
|
||||
AdjustRadius(iMin, k, iMax % divs_, TargetRInverse, rl);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -458,41 +458,41 @@ void LRaceLine::StepInterpolate(int iMin, int iMax, int Step, int rl) {
|
|||
void LRaceLine::Interpolate(int Step, int rl) {
|
||||
if (Step > 1) {
|
||||
int i;
|
||||
for (i = Step; i <= m_cDivs - Step; i += Step)
|
||||
for (i = Step; i <= divs_ - Step; i += Step)
|
||||
StepInterpolate(i - Step, i, Step, rl);
|
||||
StepInterpolate(i - Step, m_cDivs, Step, rl);
|
||||
StepInterpolate(i - Step, divs_, Step, rl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LRaceLine::InitTrack(const tTrack * const track, void **parm_handle,
|
||||
const tSituation *s, const double filterSideSkill) {
|
||||
m_dMinCornerInverse = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
min_corner_inverse_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
KILO_ATT_MINCORNER, NULL, 0.002);
|
||||
m_dCornerSpeed = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
corner_speed_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
KILO_ATT_CORNERSP, NULL, 15.0);
|
||||
m_dAvoidSpeedAdjust = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
avoid_speed_adjust_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
KILO_ATT_AVOIDSP, NULL, 2.0);
|
||||
m_dCornerAccel = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
corner_accel_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
KILO_ATT_CORNERACC, NULL, 1.0);
|
||||
m_dIntMargin = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
int_margin_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
KILO_ATT_INTMARG, NULL, 1.0);
|
||||
m_dExtMargin = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
ext_margin_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
KILO_ATT_EXTMARG, NULL, 2.0);
|
||||
m_dBrakeDelay = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
brake_delay_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
KILO_ATT_BRDELAY, NULL, 10.0);
|
||||
m_dSecurityRadius = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
security_radius_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
|
||||
KILO_ATT_SECRAD, NULL, 100.0);
|
||||
|
||||
if (s->_raceType != RM_TYPE_PRACTICE) {
|
||||
m_dExtMargin *= filterSideSkill;
|
||||
m_dIntMargin *= filterSideSkill;
|
||||
ext_margin_ *= filterSideSkill;
|
||||
int_margin_ *= filterSideSkill;
|
||||
} // if not practice
|
||||
|
||||
// split track
|
||||
for (int rl = LINE_MID; rl <= LINE_RL; rl++) {
|
||||
g_rl = rl;
|
||||
std::for_each(m_Seg.begin(), m_Seg.end(), Nullify);
|
||||
std::for_each(seg_.begin(), seg_.end(), Nullify);
|
||||
|
||||
SplitTrack(track, rl, s);
|
||||
|
||||
|
@ -507,28 +507,28 @@ void LRaceLine::InitTrack(const tTrack * const track, void **parm_handle,
|
|||
}
|
||||
|
||||
// Compute curvature and speed along the path
|
||||
for (int i = m_cDivs; --i >= 0;) {
|
||||
double TireAccel = m_dCornerSpeed * m_Seg[i].tFriction;
|
||||
for (int i = divs_; --i >= 0;) {
|
||||
double TireAccel = corner_speed_ * seg_[i].tFriction;
|
||||
if (rl == LINE_MID)
|
||||
TireAccel += m_dAvoidSpeedAdjust;
|
||||
int next = (i + 1) % m_cDivs;
|
||||
int prev = (i - 1 + m_cDivs) % m_cDivs;
|
||||
TireAccel += avoid_speed_adjust_;
|
||||
int next = (i + 1) % divs_;
|
||||
int prev = (i - 1 + divs_) % divs_;
|
||||
|
||||
double rInverse = getRInverse(prev,
|
||||
m_Seg[i].tx[rl],
|
||||
m_Seg[i].ty[rl],
|
||||
double rInverse = rinverse(prev,
|
||||
seg_[i].tx[rl],
|
||||
seg_[i].ty[rl],
|
||||
next,
|
||||
rl);
|
||||
m_Seg[i].tRInverse = rInverse;
|
||||
seg_[i].tRInverse = rInverse;
|
||||
|
||||
double MaxSpeed = 10000.0;
|
||||
double dAbsInverse = fabs(rInverse);
|
||||
if (dAbsInverse > m_dMinCornerInverse * 1.01)
|
||||
MaxSpeed = sqrt(TireAccel / (dAbsInverse - m_dMinCornerInverse));
|
||||
if (dAbsInverse > min_corner_inverse_ * 1.01)
|
||||
MaxSpeed = sqrt(TireAccel / (dAbsInverse - min_corner_inverse_));
|
||||
|
||||
// Increase or decrease speed depending on track camber
|
||||
if (dAbsInverse > 0.002) {
|
||||
double camber = m_Seg[i].dCamber;
|
||||
double camber = seg_[i].dCamber;
|
||||
|
||||
if (camber < -0.02) { // bad camber. slow us down.
|
||||
MaxSpeed -= MIN(MaxSpeed/4, fabs(camber) * 20);
|
||||
|
@ -541,34 +541,34 @@ void LRaceLine::InitTrack(const tTrack * const track, void **parm_handle,
|
|||
|
||||
// TODO(kilo): increase or decrease speed depending on approaching bumps
|
||||
|
||||
m_Seg[i].tSpeed[rl] = m_Seg[i].tMaxSpeed = MaxSpeed;
|
||||
seg_[i].tSpeed[rl] = seg_[i].tMaxSpeed = MaxSpeed;
|
||||
} // for i
|
||||
|
||||
// Anticipate braking
|
||||
for (int j = 32; --j >= 0;) {
|
||||
for (int i = m_cDivs; --i >= 0;) {
|
||||
double TireAccel = m_dCornerSpeed * m_Seg[i].tFriction;
|
||||
int prev = (i - 1 + m_cDivs) % m_cDivs;
|
||||
for (int i = divs_; --i >= 0;) {
|
||||
double TireAccel = corner_speed_ * seg_[i].tFriction;
|
||||
int prev = (i - 1 + divs_) % divs_;
|
||||
|
||||
double dx = m_Seg[i].tx[rl] - m_Seg[prev].tx[rl];
|
||||
double dy = m_Seg[i].ty[rl] - m_Seg[prev].ty[rl];
|
||||
double dx = seg_[i].tx[rl] - seg_[prev].tx[rl];
|
||||
double dy = seg_[i].ty[rl] - seg_[prev].ty[rl];
|
||||
|
||||
double dist = Mag(dx, dy);
|
||||
double Speed = (m_Seg[i].tSpeed[rl] + m_Seg[prev].tSpeed[rl]) / 2;
|
||||
double Speed = (seg_[i].tSpeed[rl] + seg_[prev].tSpeed[rl]) / 2;
|
||||
|
||||
double LatA = m_Seg[i].tSpeed[rl] * m_Seg[i].tSpeed[rl] *
|
||||
(fabs(m_Seg[prev].tRInverse) + fabs(m_Seg[i].tRInverse)) / 2;
|
||||
double LatA = seg_[i].tSpeed[rl] * seg_[i].tSpeed[rl] *
|
||||
(fabs(seg_[prev].tRInverse) + fabs(seg_[i].tRInverse)) / 2;
|
||||
|
||||
double TanA = TireAccel * TireAccel +
|
||||
m_dMinCornerInverse * Speed * Speed - LatA * LatA;
|
||||
min_corner_inverse_ * Speed * Speed - LatA * LatA;
|
||||
double brakedelay =
|
||||
m_dBrakeDelay + (rl == LINE_MID ? m_dAvoidSpeedAdjust : 0.0);
|
||||
brake_delay_ + (rl == LINE_MID ? avoid_speed_adjust_ : 0.0);
|
||||
TanA = MAX(TanA, 0.0);
|
||||
TanA = MIN(TanA, brakedelay * m_Seg[i].tFriction);
|
||||
TanA = MIN(TanA, brakedelay * seg_[i].tFriction);
|
||||
|
||||
double Time = dist / Speed;
|
||||
double MaxSpeed = m_Seg[i].tSpeed[rl] + TanA * Time;
|
||||
m_Seg[prev].tSpeed[rl] = MIN(MaxSpeed, m_Seg[prev].tMaxSpeed);
|
||||
double MaxSpeed = seg_[i].tSpeed[rl] + TanA * Time;
|
||||
seg_[prev].tSpeed[rl] = MIN(MaxSpeed, seg_[prev].tMaxSpeed);
|
||||
} // for i
|
||||
} // for j
|
||||
} // for rl
|
||||
|
@ -579,13 +579,13 @@ void LRaceLine::InitTrack(const tTrack * const track, void **parm_handle,
|
|||
// New race
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void LRaceLine::NewRace() {
|
||||
const tPrivCar * const cp = &m_pCar->priv;
|
||||
m_dWheelBase = (cp->wheel[FRNT_RGT].relPos.x +
|
||||
const tPrivCar * const cp = &car_->priv;
|
||||
wheel_base_ = (cp->wheel[FRNT_RGT].relPos.x +
|
||||
cp->wheel[FRNT_LFT].relPos.x -
|
||||
cp->wheel[REAR_RGT].relPos.x -
|
||||
cp->wheel[REAR_LFT].relPos.x) / 2;
|
||||
|
||||
m_dWheelTrack = (cp->wheel[FRNT_LFT].relPos.y +
|
||||
wheel_track_ = (cp->wheel[FRNT_LFT].relPos.y +
|
||||
cp->wheel[REAR_LFT].relPos.y -
|
||||
cp->wheel[FRNT_RGT].relPos.y -
|
||||
cp->wheel[REAR_RGT].relPos.y) / 2;
|
||||
|
@ -604,110 +604,110 @@ LRaceLine::GetRaceLineData(const tSituation * const s,
|
|||
double *lookahead,
|
||||
double *racesteer) {
|
||||
// Find index in data arrays
|
||||
tTrackSeg *pSeg = m_pCar->_trkPos.seg;
|
||||
double dist = MAX(m_pCar->_trkPos.toStart, 0.0);
|
||||
tTrackSeg *pSeg = car_->_trkPos.seg;
|
||||
double dist = MAX(car_->_trkPos.toStart, 0.0);
|
||||
if (pSeg->type != TR_STR)
|
||||
dist *= pSeg->radius;
|
||||
int Index = m_SegInfo[pSeg->id].first
|
||||
+ static_cast<int>(dist / m_SegInfo[pSeg->id].second);
|
||||
This = Index;
|
||||
int Index = seg_info_[pSeg->id].first
|
||||
+ static_cast<int>(dist / seg_info_[pSeg->id].second);
|
||||
this_ = Index;
|
||||
|
||||
Index = (Index + m_cDivs - 5) % m_cDivs;
|
||||
static const double Time = s->deltaTime * 9 + m_dCornerAccel / 80.0;
|
||||
// ??? 0.50 + m_dCornerAccel/80;
|
||||
double X = m_pCar->_pos_X + m_pCar->_speed_X * Time / 2;
|
||||
double Y = m_pCar->_pos_Y + m_pCar->_speed_Y * Time / 2;
|
||||
Index = (Index + divs_ - 5) % divs_;
|
||||
static const double Time = s->deltaTime * 9 + corner_accel_ / 80.0;
|
||||
// ??? 0.50 + corner_accel_/80;
|
||||
double X = car_->_pos_X + car_->_speed_X * Time / 2;
|
||||
double Y = car_->_pos_Y + car_->_speed_Y * Time / 2;
|
||||
// *lookahead = 0.0;
|
||||
|
||||
while (1) {
|
||||
Next = (Index + 1) % m_cDivs;
|
||||
double dx = m_Seg[Next].tx[LINE_RL] - m_pCar->_pos_X;
|
||||
double dy = m_Seg[Next].ty[LINE_RL] - m_pCar->_pos_Y;
|
||||
next_ = (Index + 1) % divs_;
|
||||
double dx = seg_[next_].tx[LINE_RL] - car_->_pos_X;
|
||||
double dy = seg_[next_].ty[LINE_RL] - car_->_pos_Y;
|
||||
*lookahead = Mag(dx, dy);
|
||||
if (*lookahead > 10.0 &&
|
||||
(m_Seg[Next].tx[LINE_RL] - m_Seg[Index].tx[LINE_RL])
|
||||
* (X - m_Seg[Next].tx[LINE_RL]) +
|
||||
(m_Seg[Next].ty[LINE_RL] - m_Seg[Index].ty[LINE_RL])
|
||||
* (Y - m_Seg[Next].ty[LINE_RL]) < 0.1)
|
||||
(seg_[next_].tx[LINE_RL] - seg_[Index].tx[LINE_RL])
|
||||
* (X - seg_[next_].tx[LINE_RL]) +
|
||||
(seg_[next_].ty[LINE_RL] - seg_[Index].ty[LINE_RL])
|
||||
* (Y - seg_[next_].ty[LINE_RL]) < 0.1)
|
||||
break;
|
||||
Index = Next;
|
||||
Index = next_;
|
||||
}
|
||||
|
||||
double toMiddle = m_pCar->_trkPos.toMiddle;
|
||||
if ((m_Seg[Next].tRInverse > 0.0 && toMiddle < 0.0)
|
||||
|| (m_Seg[Next].tRInverse < 0.0 && toMiddle > 0.0)) {
|
||||
double toMiddle = car_->_trkPos.toMiddle;
|
||||
if ((seg_[next_].tRInverse > 0.0 && toMiddle < 0.0)
|
||||
|| (seg_[next_].tRInverse < 0.0 && toMiddle > 0.0)) {
|
||||
*lookahead *= MIN(4.0, 1.5 + fabs(toMiddle * 0.3));
|
||||
} else {
|
||||
*lookahead *= MAX(0.7, 1.5 - fabs(toMiddle * 0.2));
|
||||
}
|
||||
|
||||
if ((m_Seg[Next].tRInverse < 0.0 && toMiddle > 0.0)
|
||||
|| (m_Seg[Next].tRInverse > 0.0 && toMiddle < 0.0)) {
|
||||
if ((seg_[next_].tRInverse < 0.0 && toMiddle > 0.0)
|
||||
|| (seg_[next_].tRInverse > 0.0 && toMiddle < 0.0)) {
|
||||
*lookahead *= MAX(1.0, MIN(3.6, 1.0 +
|
||||
(MIN(2.6, fabs(toMiddle) / (pSeg->width / 2)) / 2)
|
||||
* (1.0 + fabs(m_Seg[Next].tRInverse) * 65.0 +
|
||||
m_pCar->_speed_x / 120.0)));
|
||||
} else if ((m_Seg[Next].tRInverse < 0.0 && m_pCar->_trkPos.toRight < 5.0)
|
||||
|| (m_Seg[Next].tRInverse > 0.0 && m_pCar->_trkPos.toLeft < 5.0)) {
|
||||
* (1.0 + fabs(seg_[next_].tRInverse) * 65.0 +
|
||||
car_->_speed_x / 120.0)));
|
||||
} else if ((seg_[next_].tRInverse < 0.0 && car_->_trkPos.toRight < 5.0)
|
||||
|| (seg_[next_].tRInverse > 0.0 && car_->_trkPos.toLeft < 5.0)) {
|
||||
*lookahead *= MAX(0.8, MIN(1.0, 1.0 -
|
||||
fabs(m_Seg[Next].tRInverse) * 200.0 *
|
||||
((5.0 - MIN(m_pCar->_trkPos.toRight, m_pCar->_trkPos.toLeft)) / 5.0)));
|
||||
fabs(seg_[next_].tRInverse) * 200.0 *
|
||||
((5.0 - MIN(car_->_trkPos.toRight, car_->_trkPos.toLeft)) / 5.0)));
|
||||
}
|
||||
|
||||
target->x = m_Seg[Next].tx[LINE_RL];
|
||||
target->y = m_Seg[Next].ty[LINE_RL];
|
||||
target->x = seg_[next_].tx[LINE_RL];
|
||||
target->y = seg_[next_].ty[LINE_RL];
|
||||
|
||||
//
|
||||
// Find target speed
|
||||
//
|
||||
double c0 =
|
||||
(m_Seg[Next].tx[LINE_RL] - m_Seg[Index].tx[LINE_RL])
|
||||
* (m_Seg[Next].tx[LINE_RL] - X) +
|
||||
(m_Seg[Next].ty[LINE_RL] - m_Seg[Index].ty[LINE_RL])
|
||||
* (m_Seg[Next].ty[LINE_RL] - Y);
|
||||
(seg_[next_].tx[LINE_RL] - seg_[Index].tx[LINE_RL])
|
||||
* (seg_[next_].tx[LINE_RL] - X) +
|
||||
(seg_[next_].ty[LINE_RL] - seg_[Index].ty[LINE_RL])
|
||||
* (seg_[next_].ty[LINE_RL] - Y);
|
||||
double c1 =
|
||||
(m_Seg[Next].tx[LINE_RL] - m_Seg[Index].tx[LINE_RL])
|
||||
* (X - m_Seg[Index].tx[LINE_RL]) +
|
||||
(m_Seg[Next].ty[LINE_RL] - m_Seg[Index].ty[LINE_RL])
|
||||
* (Y - m_Seg[Index].ty[LINE_RL]);
|
||||
(seg_[next_].tx[LINE_RL] - seg_[Index].tx[LINE_RL])
|
||||
* (X - seg_[Index].tx[LINE_RL]) +
|
||||
(seg_[next_].ty[LINE_RL] - seg_[Index].ty[LINE_RL])
|
||||
* (Y - seg_[Index].ty[LINE_RL]);
|
||||
|
||||
double sum = c0 + c1;
|
||||
c0 /= sum;
|
||||
c1 /= sum;
|
||||
|
||||
m_dTargetSpeed =
|
||||
(1 - c0) * m_Seg[Next].tSpeed[LINE_RL] + c0 * m_Seg[Index].tSpeed[LINE_RL];
|
||||
*avspeed = MAX(10.0, m_Seg[Next].tSpeed[LINE_MID]);
|
||||
*speed = MAX(*avspeed, m_dTargetSpeed);
|
||||
target_speed_ =
|
||||
(1 - c0) * seg_[next_].tSpeed[LINE_RL] + c0 * seg_[Index].tSpeed[LINE_RL];
|
||||
*avspeed = MAX(10.0, seg_[next_].tSpeed[LINE_MID]);
|
||||
*speed = MAX(*avspeed, target_speed_);
|
||||
|
||||
if ((m_Seg[Next].tRInverse > 0.0 && m_Seg[Next].tLane > m_Seg[Index].tLane
|
||||
&& m_pCar->_trkPos.toLeft <= m_Seg[Next].tLane * m_dWidth + 1.0)
|
||||
|| (m_Seg[Next].tRInverse < 0.0 && m_Seg[Next].tLane < m_Seg[Index].tLane
|
||||
&& m_pCar->_trkPos.toLeft >= m_Seg[Next].tLane * m_dWidth - 1.0)) {
|
||||
if ((seg_[next_].tRInverse > 0.0 && seg_[next_].tLane > seg_[Index].tLane
|
||||
&& car_->_trkPos.toLeft <= seg_[next_].tLane * width_ + 1.0)
|
||||
|| (seg_[next_].tRInverse < 0.0 && seg_[next_].tLane < seg_[Index].tLane
|
||||
&& car_->_trkPos.toLeft >= seg_[next_].tLane * width_ - 1.0)) {
|
||||
*avspeed = MAX(*speed, *avspeed);
|
||||
} else if ((m_Seg[Next].tRInverse > 0.001
|
||||
&& m_Seg[Next].tLane < m_Seg[Index].tLane
|
||||
&& m_pCar->_trkPos.toLeft < m_Seg[Next].tLane * m_dWidth - 1.0)
|
||||
|| (m_Seg[Next].tRInverse < -0.001
|
||||
&& m_Seg[Next].tLane > m_Seg[Index].tLane
|
||||
&& m_pCar->_trkPos.toLeft > m_Seg[Next].tLane * m_dWidth + 1.0)) {
|
||||
*avspeed *= MAX(0.7, 1.0 - fabs(m_Seg[Next].tRInverse) * 100);
|
||||
} else if ((seg_[next_].tRInverse > 0.001
|
||||
&& seg_[next_].tLane < seg_[Index].tLane
|
||||
&& car_->_trkPos.toLeft < seg_[next_].tLane * width_ - 1.0)
|
||||
|| (seg_[next_].tRInverse < -0.001
|
||||
&& seg_[next_].tLane > seg_[Index].tLane
|
||||
&& car_->_trkPos.toLeft > seg_[next_].tLane * width_ + 1.0)) {
|
||||
*avspeed *= MAX(0.7, 1.0 - fabs(seg_[next_].tRInverse) * 100);
|
||||
}
|
||||
|
||||
double laneoffset = m_dWidth / 2 - (m_Seg[Next].tLane * m_dWidth);
|
||||
double laneoffset = width_ / 2 - (seg_[next_].tLane * width_);
|
||||
*raceoffset = laneoffset;
|
||||
|
||||
//
|
||||
// Find target curveture (for the inside wheel)
|
||||
//
|
||||
double TargetCurvature = (1 - c0) * m_Seg[Next].tRInverse
|
||||
+ c0 * m_Seg[Index].tRInverse;
|
||||
double TargetCurvature = (1 - c0) * seg_[next_].tRInverse
|
||||
+ c0 * seg_[Index].tRInverse;
|
||||
if (fabs(TargetCurvature) > 0.01) {
|
||||
double r = 1 / TargetCurvature;
|
||||
if (r > 0) {
|
||||
r -= m_dWheelTrack / 2;
|
||||
r -= wheel_track_ / 2;
|
||||
} else {
|
||||
r += m_dWheelTrack / 2;
|
||||
r += wheel_track_ / 2;
|
||||
}
|
||||
TargetCurvature = 1 / r;
|
||||
}
|
||||
|
@ -717,30 +717,30 @@ LRaceLine::GetRaceLineData(const tSituation * const s,
|
|||
//
|
||||
double Error = 0;
|
||||
double VnError = 0;
|
||||
double carspeed = Mag(m_pCar->_speed_X, m_pCar->_speed_Y);
|
||||
double carspeed = Mag(car_->_speed_X, car_->_speed_Y);
|
||||
|
||||
//
|
||||
// Ideal value
|
||||
//
|
||||
double steer = atan(m_dWheelBase * TargetCurvature) / m_pCar->_steerLock;
|
||||
double steer = atan(wheel_base_ * TargetCurvature) / car_->_steerLock;
|
||||
|
||||
//
|
||||
// Servo system to stay on the pre-computed path
|
||||
//
|
||||
{
|
||||
double dx = m_Seg[Next].tx[LINE_RL] - m_Seg[Index].tx[LINE_RL];
|
||||
double dy = m_Seg[Next].ty[LINE_RL] - m_Seg[Index].ty[LINE_RL];
|
||||
double dx = seg_[next_].tx[LINE_RL] - seg_[Index].tx[LINE_RL];
|
||||
double dy = seg_[next_].ty[LINE_RL] - seg_[Index].ty[LINE_RL];
|
||||
Error =
|
||||
(dx * (Y - m_Seg[Index].ty[LINE_RL]) -
|
||||
dy * (X - m_Seg[Index].tx[LINE_RL])) / Mag(dx, dy);
|
||||
(dx * (Y - seg_[Index].ty[LINE_RL]) -
|
||||
dy * (X - seg_[Index].tx[LINE_RL])) / Mag(dx, dy);
|
||||
}
|
||||
|
||||
int Prev = (Index + m_cDivs - 1) % m_cDivs;
|
||||
int NextNext = (Next + 1) % m_cDivs;
|
||||
double Prevdx = m_Seg[Next].tx[LINE_RL] - m_Seg[Prev].tx[LINE_RL];
|
||||
double Prevdy = m_Seg[Next].ty[LINE_RL] - m_Seg[Prev].ty[LINE_RL];
|
||||
double Nextdx = m_Seg[NextNext].tx[LINE_RL] - m_Seg[Index].tx[LINE_RL];
|
||||
double Nextdy = m_Seg[NextNext].ty[LINE_RL] - m_Seg[Index].ty[LINE_RL];
|
||||
int Prev = (Index + divs_ - 1) % divs_;
|
||||
int NextNext = (next_ + 1) % divs_;
|
||||
double Prevdx = seg_[next_].tx[LINE_RL] - seg_[Prev].tx[LINE_RL];
|
||||
double Prevdy = seg_[next_].ty[LINE_RL] - seg_[Prev].ty[LINE_RL];
|
||||
double Nextdx = seg_[NextNext].tx[LINE_RL] - seg_[Index].tx[LINE_RL];
|
||||
double Nextdy = seg_[NextNext].ty[LINE_RL] - seg_[Index].ty[LINE_RL];
|
||||
double dx = c0 * Prevdx + (1 - c0) * Nextdx;
|
||||
double dy = c0 * Prevdy + (1 - c0) * Nextdy;
|
||||
double n = Mag(dx, dy);
|
||||
|
@ -748,34 +748,34 @@ LRaceLine::GetRaceLineData(const tSituation * const s,
|
|||
dy /= n;
|
||||
|
||||
double sError =
|
||||
(dx * m_pCar->_speed_Y - dy * m_pCar->_speed_X) / (carspeed + 0.01);
|
||||
(dx * car_->_speed_Y - dy * car_->_speed_X) / (carspeed + 0.01);
|
||||
double cError =
|
||||
(dx * m_pCar->_speed_X + dy * m_pCar->_speed_Y) / (carspeed + 0.01);
|
||||
(dx * car_->_speed_X + dy * car_->_speed_Y) / (carspeed + 0.01);
|
||||
VnError = asin(sError);
|
||||
if (cError < 0)
|
||||
VnError = PI - VnError;
|
||||
|
||||
steer -= (atan(Error * (300 / (carspeed + 300)) / 15) + VnError)
|
||||
/ m_pCar->_steerLock;
|
||||
/ car_->_steerLock;
|
||||
|
||||
//
|
||||
// Steer into the skid
|
||||
//
|
||||
double vx = m_pCar->_speed_X;
|
||||
double vy = m_pCar->_speed_Y;
|
||||
double dirx = cos(m_pCar->_yaw);
|
||||
double diry = sin(m_pCar->_yaw);
|
||||
double vx = car_->_speed_X;
|
||||
double vy = car_->_speed_Y;
|
||||
double dirx = cos(car_->_yaw);
|
||||
double diry = sin(car_->_yaw);
|
||||
double Skid = (dirx * vy - vx * diry) / (carspeed + 0.1);
|
||||
if (Skid > 0.9) Skid = 0.9;
|
||||
if (Skid < -0.9) Skid = -0.9;
|
||||
steer += (asin(Skid) / m_pCar->_steerLock) * 0.9;
|
||||
steer += (asin(Skid) / car_->_steerLock) * 0.9;
|
||||
|
||||
double yr = carspeed * TargetCurvature;
|
||||
double diff = m_pCar->_yaw_rate - yr;
|
||||
steer -= (0.06 * (100 / (carspeed + 100)) * diff) / m_pCar->_steerLock;
|
||||
double diff = car_->_yaw_rate - yr;
|
||||
steer -= (0.06 * (100 / (carspeed + 100)) * diff) / car_->_steerLock;
|
||||
|
||||
double trackangle = RtTrackSideTgAngleL(&(m_pCar->_trkPos));
|
||||
double angle = trackangle - m_pCar->_yaw;
|
||||
double trackangle = RtTrackSideTgAngleL(&(car_->_trkPos));
|
||||
double angle = trackangle - car_->_yaw;
|
||||
NORM_PI_PI(angle);
|
||||
angle = -angle;
|
||||
|
||||
|
@ -796,9 +796,9 @@ LRaceLine::GetRaceLineData(const tSituation * const s,
|
|||
bool LRaceLine::isOnLine() const {
|
||||
bool ret = false;
|
||||
|
||||
double lane2left = m_Seg[Next].tLane * m_dWidth;
|
||||
if (fabs(m_pCar->_trkPos.toLeft - lane2left) <
|
||||
MAX(0.1, 1.0 - (m_pCar->_speed_x * (m_pCar->_speed_x / 10)) / 600))
|
||||
double lane2left = seg_[next_].tLane * width_;
|
||||
if (fabs(car_->_trkPos.toLeft - lane2left) <
|
||||
MAX(0.1, 1.0 - (car_->_speed_x * (car_->_speed_x / 10)) / 600))
|
||||
ret = true;
|
||||
|
||||
return ret;
|
||||
|
@ -807,23 +807,23 @@ bool LRaceLine::isOnLine() const {
|
|||
|
||||
void LRaceLine::GetPoint(const double offset, const double lookahead,
|
||||
vec2f * const rt) const {
|
||||
double dLane = (m_dWidth / 2.0 - offset) / m_dWidth;
|
||||
double dLane = (width_ / 2.0 - offset) / width_;
|
||||
vec2f last;
|
||||
last.x = dLane * m_Seg[This].txRight + (1.0 - dLane) * m_Seg[This].txLeft;
|
||||
last.y = dLane * m_Seg[This].tyRight + (1.0 - dLane) * m_Seg[This].tyLeft;
|
||||
last.x = dLane * seg_[this_].txRight + (1.0 - dLane) * seg_[this_].txLeft;
|
||||
last.y = dLane * seg_[this_].tyRight + (1.0 - dLane) * seg_[this_].tyLeft;
|
||||
|
||||
int ndiv = Next;
|
||||
int ndiv = next_;
|
||||
double dLength = 0.0;
|
||||
double la = static_cast<double>(lookahead)
|
||||
* MIN(1.0, MAX(0.8, m_pCar->_speed_x / m_dTargetSpeed));
|
||||
int iLookaheadLimit = static_cast<int>(la / m_lDivLength);
|
||||
* MIN(1.0, MAX(0.8, car_->_speed_x / target_speed_));
|
||||
int iLookaheadLimit = static_cast<int>(la / div_length_);
|
||||
for (int count = 0; count < iLookaheadLimit && dLength < la; count++) {
|
||||
rt->x = dLane * m_Seg[ndiv].txRight + (1 - dLane) * m_Seg[ndiv].txLeft;
|
||||
rt->y = dLane * m_Seg[ndiv].tyRight + (1 - dLane) * m_Seg[ndiv].tyLeft;
|
||||
rt->x = dLane * seg_[ndiv].txRight + (1 - dLane) * seg_[ndiv].txLeft;
|
||||
rt->y = dLane * seg_[ndiv].tyRight + (1 - dLane) * seg_[ndiv].tyLeft;
|
||||
vec2f d = (*rt) - last;
|
||||
dLength += Mag(d.x, d.y);
|
||||
|
||||
ndiv = (ndiv + 1) % m_cDivs;
|
||||
ndiv = (ndiv + 1) % divs_;
|
||||
last = (*rt);
|
||||
} // for
|
||||
} // GetPoint
|
||||
|
@ -832,61 +832,37 @@ void LRaceLine::GetPoint(const double offset, const double lookahead,
|
|||
// this returns true if we're approaching a corner & are significantly
|
||||
// inside the ideal racing line. The idea is to prevent a sudden outwards
|
||||
// movement at a time when we should be looking to turn in.
|
||||
double LRaceLine::correctLimit(void) const {
|
||||
double toLeft = m_pCar->_trkPos.toLeft;
|
||||
double nlane2left = m_Seg[Next].tLane * m_dWidth;
|
||||
double LRaceLine::CorrectLimit(void) const {
|
||||
double toLeft = car_->_trkPos.toLeft;
|
||||
double nlane2left = seg_[next_].tLane * width_;
|
||||
|
||||
if ((m_Seg[Next].tRInverse > 0.001 && toLeft < nlane2left - 2.0)
|
||||
|| (m_Seg[Next].tRInverse < -0.001 && toLeft > nlane2left + 2.0))
|
||||
return MAX(0.2, MIN(1.0, 1.0 - fabs(m_Seg[Next].tRInverse) * 100.0));
|
||||
if ((seg_[next_].tRInverse > 0.001 && toLeft < nlane2left - 2.0)
|
||||
|| (seg_[next_].tRInverse < -0.001 && toLeft > nlane2left + 2.0))
|
||||
return MAX(0.2, MIN(1.0, 1.0 - fabs(seg_[next_].tRInverse) * 100.0));
|
||||
|
||||
int nnext = (Next + static_cast<int>(m_pCar->_speed_x / 3)) % m_cDivs;
|
||||
double nnlane2left = m_Seg[nnext].tLane * m_dWidth;
|
||||
if ((m_Seg[nnext].tRInverse > 0.001 && toLeft < nnlane2left - 2.0)
|
||||
|| (m_Seg[nnext].tRInverse < -0.001 && toLeft > nnlane2left + 2.0))
|
||||
return MAX(0.3, MIN(1.0, 1.0 - fabs(m_Seg[nnext].tRInverse) * 40.0));
|
||||
int nnext = (next_ + static_cast<int>(car_->_speed_x / 3)) % divs_;
|
||||
double nnlane2left = seg_[nnext].tLane * width_;
|
||||
if ((seg_[nnext].tRInverse > 0.001 && toLeft < nnlane2left - 2.0)
|
||||
|| (seg_[nnext].tRInverse < -0.001 && toLeft > nnlane2left + 2.0))
|
||||
return MAX(0.3, MIN(1.0, 1.0 - fabs(seg_[nnext].tRInverse) * 40.0));
|
||||
|
||||
// ok, we're not inside the racing line. Check and see
|
||||
// if we're outside it and turning into a corner,
|
||||
// in which case we want to correct more to try
|
||||
// and get closer to the apex.
|
||||
if ((m_Seg[Next].tRInverse > 0.001
|
||||
&& m_Seg[Next].tLane <= m_Seg[This].tLane
|
||||
if ((seg_[next_].tRInverse > 0.001
|
||||
&& seg_[next_].tLane <= seg_[this_].tLane
|
||||
&& toLeft > nlane2left + 2.0)
|
||||
|| (m_Seg[Next].tRInverse < -0.001
|
||||
&& m_Seg[Next].tLane >= m_Seg[This].tLane
|
||||
|| (seg_[next_].tRInverse < -0.001
|
||||
&& seg_[next_].tLane >= seg_[this_].tLane
|
||||
&& toLeft < nlane2left - 2.0))
|
||||
return MAX(1.0, MIN(1.5, 1.0 + fabs(m_Seg[Next].tRInverse)));
|
||||
return MAX(1.0, MIN(1.5, 1.0 + fabs(seg_[next_].tRInverse)));
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
|
||||
double LRaceLine::getAvoidSpeed(const double distance1,
|
||||
const double distance2) const {
|
||||
double speed1 = 1000.0;
|
||||
double speed2 = 1000.0;
|
||||
|
||||
int i = Next;
|
||||
int dist_limit = static_cast<int>(distance1 / m_lDivLength);
|
||||
for (int count = 0; count < dist_limit; count++, i++) {
|
||||
i = i % m_cDivs;
|
||||
speed1 = MIN(speed1, m_Seg[i].tSpeed[LINE_MID]);
|
||||
}
|
||||
|
||||
dist_limit = static_cast<int>(MIN(distance2, distance1 * 3) - distance1)
|
||||
/ m_lDivLength;
|
||||
for (int count = 0; count < dist_limit; count++, i++) {
|
||||
i = i % m_cDivs;
|
||||
speed2 = MIN(speed2, m_Seg[i].tSpeed[LINE_MID]
|
||||
+ static_cast<double>(count) * 0.25);
|
||||
}
|
||||
|
||||
return MIN(speed1, speed2);
|
||||
}
|
||||
|
||||
|
||||
void LRaceLine::SetSegCamber(const tTrackSeg *seg, const int div) {
|
||||
void LRaceLine::SetSegmentCamber(const tTrackSeg *seg, const int div) {
|
||||
double dDistRatio = 0.7;
|
||||
double dCamberStart = seg->vertex[TR_SR].z - seg->vertex[TR_SL].z;
|
||||
double dCamberEnd = seg->vertex[TR_ER].z - seg->vertex[TR_EL].z;
|
||||
|
@ -896,7 +872,7 @@ void LRaceLine::SetSegCamber(const tTrackSeg *seg, const int div) {
|
|||
dCamberEnd /= seg->width;
|
||||
dCamber /= seg->width;
|
||||
|
||||
if (m_Seg[div].tRInverse < 0.0) {
|
||||
if (seg_[div].tRInverse < 0.0) {
|
||||
dCamber *= -1.0;
|
||||
dCamberStart *= -1.0;
|
||||
dCamberEnd *= -1.0;
|
||||
|
@ -908,6 +884,6 @@ void LRaceLine::SetSegCamber(const tTrackSeg *seg, const int div) {
|
|||
dCamber += (dCamberEnd - dCamberStart) * 0.4;
|
||||
}
|
||||
|
||||
m_Seg[div].dCamber = dCamber;
|
||||
} // SetSegCamber
|
||||
seg_[div].dCamber = dCamber;
|
||||
} // SetSegmentCamber
|
||||
|
||||
|
|
|
@ -86,7 +86,11 @@ class LRaceLine {
|
|||
LRaceLine() {}
|
||||
virtual ~LRaceLine() {}
|
||||
|
||||
inline void setCar(tCarElt * const car) {m_pCar = car;}
|
||||
inline double rinverse(void) const { return seg_[next_].tRInverse; }
|
||||
inline double rinverse(const double distance) const {
|
||||
int d = ((next_ + static_cast<int>(distance / div_length_)) % divs_);
|
||||
return seg_[d].tRInverse; }
|
||||
inline void set_car(tCarElt * const car) {car_ = car;}
|
||||
|
||||
void InitTrack(const tTrack * const track, void **carParmHandle,
|
||||
const tSituation *s, const double filterSideSkill);
|
||||
|
@ -97,53 +101,46 @@ class LRaceLine {
|
|||
void GetPoint(const double offset, const double lookahead,
|
||||
vec2f * const rt) const;
|
||||
bool isOnLine(void) const;
|
||||
double correctLimit(void) const;
|
||||
inline double getRInverse(void) const {return m_Seg[Next].tRInverse;}
|
||||
inline double getRInverse(const double distance) const {
|
||||
int d = ((Next + static_cast<int>(distance / m_lDivLength)) % m_cDivs);
|
||||
return m_Seg[d].tRInverse;
|
||||
}
|
||||
double CorrectLimit(void) const;
|
||||
|
||||
private:
|
||||
double rinverse(const int prev, const double x, const double y,
|
||||
const int next, const int rl) const;
|
||||
void SetSegmentInfo(const tTrackSeg * pseg, const int i, const double l);
|
||||
void SetSegmentCamber(const tTrackSeg *seg, const int div);
|
||||
void SplitTrack(const tTrack * const ptrack, const int rl,
|
||||
const tSituation *s);
|
||||
double getRInverse(const int prev, const double x, const double y,
|
||||
const int next, const int rl) const;
|
||||
void AdjustRadius(int prev, int i, int next, double TargetRInverse, int rl,
|
||||
double Security = 0);
|
||||
double Security = 0);
|
||||
void Smooth(const int Step, const int rl);
|
||||
void StepInterpolate(int iMin, int iMax, int Step, int rl);
|
||||
void Interpolate(int Step, int rl);
|
||||
double getAvoidSpeed(const double distance1, const double distance2) const;
|
||||
void SetSegCamber(const tTrackSeg *seg, const int div);
|
||||
|
||||
private:
|
||||
double m_dMinCornerInverse;
|
||||
double m_dCornerSpeed;
|
||||
double m_dCornerAccel;
|
||||
double m_dBrakeDelay;
|
||||
double m_dIntMargin;
|
||||
double m_dExtMargin;
|
||||
double m_dAvoidSpeedAdjust;
|
||||
double m_dSecurityRadius;
|
||||
tCarElt * m_pCar;
|
||||
tCarElt *car_;
|
||||
double min_corner_inverse_;
|
||||
double corner_speed_;
|
||||
double corner_accel_;
|
||||
double brake_delay_;
|
||||
double int_margin_;
|
||||
double ext_margin_;
|
||||
double avoid_speed_adjust_;
|
||||
double security_radius_;
|
||||
double wheel_base_;
|
||||
double wheel_track_;
|
||||
|
||||
double m_dWheelBase;
|
||||
double m_dWheelTrack;
|
||||
|
||||
int m_cDivs;
|
||||
int m_lDivLength;
|
||||
double m_dTargetSpeed;
|
||||
double m_dWidth;
|
||||
int divs_;
|
||||
int div_length_;
|
||||
double target_speed_;
|
||||
double width_;
|
||||
|
||||
// first: segment index, second: elem length
|
||||
std::vector< std::pair<int, double> > m_SegInfo;
|
||||
std::vector< std::pair<int, double> > seg_info_;
|
||||
|
||||
std::vector<rlSegment> m_Seg;
|
||||
std::vector<rlSegment> seg_;
|
||||
|
||||
int Next;
|
||||
int This;
|
||||
int next_;
|
||||
int this_;
|
||||
};
|
||||
|
||||
#endif // SRC_DRIVERS_KILO2008_RACELINE_H_
|
||||
|
|
|
@ -43,13 +43,13 @@ const int KStrategy::LAST_LAPS = 10;
|
|||
|
||||
|
||||
KStrategy::KStrategy() {
|
||||
m_last_damages = new std::deque<int>;
|
||||
last_damages_ = new std::deque<int>;
|
||||
|
||||
m_laps = 0;
|
||||
m_fuel_checked = false;
|
||||
m_fuel_per_lap = 0.0;
|
||||
m_last_pit_fuel = 0.0;
|
||||
m_fuel_sum = 0.0;
|
||||
laps_ = 0;
|
||||
fuel_checked_ = false;
|
||||
fuel_per_lap_ = 0.0;
|
||||
last_pit_fuel_ = 0.0;
|
||||
fuel_sum_ = 0.0;
|
||||
} // KStrategy
|
||||
|
||||
|
||||
|
@ -69,13 +69,13 @@ void KStrategy::SetFuelAtRaceStart(const tTrack * const t,
|
|||
const double fuel =
|
||||
GfParmGetNum(*carParmHandle, KILO_SECT_PRIV, KILO_ATT_FUELPERLAP,
|
||||
NULL, t->length * MAX_FUEL_PER_METER);
|
||||
m_expected_fuel_per_lap = fuel;
|
||||
expected_fuel_per_lap_ = fuel;
|
||||
// Pittime is pittime without refuel.
|
||||
m_pittime = GfParmGetNum(*carParmHandle, KILO_SECT_PRIV,
|
||||
pittime_ = GfParmGetNum(*carParmHandle, KILO_SECT_PRIV,
|
||||
KILO_ATT_PITTIME, NULL, 25.0);
|
||||
m_best_lap = GfParmGetNum(*carParmHandle, KILO_SECT_PRIV,
|
||||
best_lap_ = GfParmGetNum(*carParmHandle, KILO_SECT_PRIV,
|
||||
KILO_ATT_BESTLAP, NULL, 87.0);
|
||||
m_worst_lap = GfParmGetNum(*carParmHandle, KILO_SECT_PRIV,
|
||||
worst_lap_ = GfParmGetNum(*carParmHandle, KILO_SECT_PRIV,
|
||||
KILO_ATT_WORSTLAP, NULL, 87.0);
|
||||
// Fuel tank capacity
|
||||
const double maxfuel = GfParmGetNum(*carParmHandle, SECT_CAR,
|
||||
|
@ -88,7 +88,7 @@ void KStrategy::SetFuelAtRaceStart(const tTrack * const t,
|
|||
|
||||
// Compute race times for min to min + 9 pit stops.
|
||||
ComputeBestNumberOfPits(maxfuel, fuelForRace, s->_totLaps, true);
|
||||
m_last_fuel = m_fuel_per_stint;
|
||||
last_fuel_ = fuel_per_stint_;
|
||||
|
||||
// If the setup defines initial fuel amount, use that value in races.
|
||||
// Otherwise use computed amount.
|
||||
|
@ -100,7 +100,7 @@ void KStrategy::SetFuelAtRaceStart(const tTrack * const t,
|
|||
} else {
|
||||
// Add fuel dependent on index to avoid fuel stop in the same lap.
|
||||
GfParmSetNum(*carParmHandle, SECT_CAR, PRM_FUEL, NULL,
|
||||
m_last_fuel + index * m_expected_fuel_per_lap);
|
||||
last_fuel_ + index * expected_fuel_per_lap_);
|
||||
}
|
||||
} else {
|
||||
// Use fuel for whole 'race', ie qualy or practice N laps.
|
||||
|
@ -121,14 +121,14 @@ void KStrategy::SetFuelAtRaceStart(const tTrack * const t,
|
|||
void KStrategy::UpdateFuelStrategy() {
|
||||
// Required additional fuel for the rest of the race.
|
||||
// +1 because the computation happens right after crossing the start line.
|
||||
double fuelperlap = MAX(m_fuel_per_lap, 2.5); // average
|
||||
double required_fuel = ((LapsToGo() + 1) - ceil(m_car->_fuel / fuelperlap))
|
||||
double fuelperlap = MAX(fuel_per_lap_, 2.5); // average
|
||||
double required_fuel = ((LapsToGo() + 1) - ceil(car_->_fuel / fuelperlap))
|
||||
* fuelperlap;
|
||||
|
||||
// We don't have enough fuel to end the race, need at least one stop.
|
||||
if (required_fuel >= 0.0) {
|
||||
// Compute race times for different pit strategies.
|
||||
ComputeBestNumberOfPits(m_car->_tank, required_fuel, LapsToGo(), FALSE);
|
||||
ComputeBestNumberOfPits(car_->_tank, required_fuel, LapsToGo(), FALSE);
|
||||
}
|
||||
} // UpdateFuelStrategy
|
||||
|
||||
|
@ -141,19 +141,19 @@ double KStrategy::PitRefuel() {
|
|||
UpdateFuelStrategy();
|
||||
|
||||
double fuel;
|
||||
if (m_remaining_stops > 1) {
|
||||
fuel = MIN(MAX(m_fuel_per_stint, MAXFUEL_FOR_THIS_RACE),
|
||||
m_car->_tank - m_car->_fuel); // !!!
|
||||
--m_remaining_stops;
|
||||
if (remaining_stops_ > 1) {
|
||||
fuel = MIN(MAX(fuel_per_stint_, MAXFUEL_FOR_THIS_RACE),
|
||||
car_->_tank - car_->_fuel); // !!!
|
||||
--remaining_stops_;
|
||||
} else {
|
||||
double cmpfuel = (m_fuel_per_lap == 0.0)
|
||||
? m_expected_fuel_per_lap
|
||||
: m_fuel_per_lap;
|
||||
fuel = MAX(MIN((LapsToGo() + 1.0) * cmpfuel - m_car->_fuel,
|
||||
m_car->_tank - m_car->_fuel), 0.0);
|
||||
double cmpfuel = (fuel_per_lap_ == 0.0)
|
||||
? expected_fuel_per_lap_
|
||||
: fuel_per_lap_;
|
||||
fuel = MAX(MIN((LapsToGo() + 1.0) * cmpfuel - car_->_fuel,
|
||||
car_->_tank - car_->_fuel), 0.0);
|
||||
}
|
||||
|
||||
m_last_pit_fuel = fuel;
|
||||
last_pit_fuel_ = fuel;
|
||||
return fuel;
|
||||
} // pitRefuel
|
||||
|
||||
|
@ -174,16 +174,16 @@ void KStrategy::ComputeBestNumberOfPits(const double tankCapacity,
|
|||
for (int i = 0; i < (preRace ? 5 : 4); ++i) {
|
||||
double stintFuel = requiredFuel / (pitstopMin + i); // + 1);
|
||||
double fillratio = stintFuel / tankCapacity;
|
||||
double avglapest = m_best_lap + (m_worst_lap - m_best_lap) * fillratio;
|
||||
double racetime = (pitstopMin + i) * (m_pittime + stintFuel / 8.0) +
|
||||
double avglapest = best_lap_ + (worst_lap_ - best_lap_) * fillratio;
|
||||
double racetime = (pitstopMin + i) * (pittime_ + stintFuel / 8.0) +
|
||||
remainingLaps * avglapest;
|
||||
if (mintime > racetime) {
|
||||
mintime = racetime;
|
||||
beststops = pitstopMin + i - (preRace ? 1 : 0);
|
||||
m_fuel_per_stint = stintFuel;
|
||||
fuel_per_stint_ = stintFuel;
|
||||
}
|
||||
}
|
||||
m_remaining_stops = beststops;
|
||||
remaining_stops_ = beststops;
|
||||
} // ComputeBestNumberOfPits
|
||||
|
||||
|
||||
|
@ -198,45 +198,45 @@ void KStrategy::ComputeBestNumberOfPits(const double tankCapacity,
|
|||
* @return: -
|
||||
*/
|
||||
void KStrategy::Update() {
|
||||
if (m_car->_laps > m_laps) { // If a new lap has been finished
|
||||
m_laps = m_car->_laps;
|
||||
m_last_damages->push_front(m_car->_dammage); // store last lap's damage
|
||||
if (static_cast<int>(m_last_damages->size()) > LAST_LAPS)
|
||||
m_last_damages->pop_back(); // and keep deque size at limit
|
||||
if (car_->_laps > laps_) { // If a new lap has been finished
|
||||
laps_ = car_->_laps;
|
||||
last_damages_->push_front(car_->_dammage); // store last lap's damage
|
||||
if (static_cast<int>(last_damages_->size()) > LAST_LAPS)
|
||||
last_damages_->pop_back(); // and keep deque size at limit
|
||||
|
||||
#ifdef STRAT_DEBUG
|
||||
// print damage values in reverse order
|
||||
cerr << car->_name << ": damages";
|
||||
for (deque<int>::reverse_iterator rit = m_last_damages->rbegin();
|
||||
rit < m_last_damages->rend();
|
||||
rit++)
|
||||
for (deque<int>::reverse_iterator rit = last_damages_->rbegin();
|
||||
rit < last_damages_->rend();
|
||||
++rit)
|
||||
cerr << " " << *rit;
|
||||
cerr << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Update best & worst lap times
|
||||
m_best_lap = MIN((m_best_lap == 0.0 ? m_car->_lastLapTime : m_best_lap),
|
||||
m_car->_lastLapTime);
|
||||
m_worst_lap = MAX(m_worst_lap, m_car->_lastLapTime);
|
||||
best_lap_ = MIN((best_lap_ == 0.0 ? car_->_lastLapTime : best_lap_),
|
||||
car_->_lastLapTime);
|
||||
worst_lap_ = MAX(worst_lap_, car_->_lastLapTime);
|
||||
|
||||
|
||||
// Fuel statistics update.
|
||||
int id = m_car->_trkPos.seg->id;
|
||||
int id = car_->_trkPos.seg->id;
|
||||
// Range must include enough segments to be executed once guaranteed.
|
||||
if (id >= 0 && id < 5 && !m_fuel_checked) {
|
||||
if (m_car->race.laps > 1) {
|
||||
m_fuel_sum += (m_last_fuel + m_last_pit_fuel - m_car->priv.fuel);
|
||||
m_fuel_per_lap = (m_fuel_sum / (m_car->race.laps - 1));
|
||||
if (id >= 0 && id < 5 && !fuel_checked_) {
|
||||
if (car_->race.laps > 1) {
|
||||
fuel_sum_ += (last_fuel_ + last_pit_fuel_ - car_->priv.fuel);
|
||||
fuel_per_lap_ = (fuel_sum_ / (car_->race.laps - 1));
|
||||
// This is here for adding strategy decisions, otherwise
|
||||
// it could be moved to pitRefuel for efficiency.
|
||||
UpdateFuelStrategy();
|
||||
}
|
||||
m_last_fuel = m_car->priv.fuel;
|
||||
m_last_pit_fuel = 0.0;
|
||||
m_fuel_checked = true;
|
||||
last_fuel_ = car_->priv.fuel;
|
||||
last_pit_fuel_ = 0.0;
|
||||
fuel_checked_ = true;
|
||||
} else if (id > 5) {
|
||||
m_fuel_checked = false;
|
||||
fuel_checked_ = false;
|
||||
}
|
||||
} // update
|
||||
|
||||
|
@ -255,14 +255,14 @@ bool KStrategy::NeedPitstop() const {
|
|||
bool ret = false;
|
||||
|
||||
// Question makes sense only if there is a pit.
|
||||
if (m_car->_pit != NULL) {
|
||||
if (car_->_pit != NULL) {
|
||||
// Ideally we shouldn't pit on the last lap for any reason,
|
||||
// just get to the finish line somehow.
|
||||
if (LapsToGo() > 0) {
|
||||
// Do we need to refuel?
|
||||
double cmpfuel = (m_fuel_per_lap == 0.0)
|
||||
? m_expected_fuel_per_lap
|
||||
: m_fuel_per_lap;
|
||||
double cmpfuel = (fuel_per_lap_ == 0.0)
|
||||
? expected_fuel_per_lap_
|
||||
: fuel_per_lap_;
|
||||
|
||||
#ifdef STRAT_DEBUG
|
||||
if (strcmp(car->_name, "Kilo 1") == 0 && car->_fuel < 5.0)
|
||||
|
@ -278,20 +278,20 @@ bool KStrategy::NeedPitstop() const {
|
|||
<< endl;
|
||||
#endif
|
||||
cmpfuel *= MIN(SAFE_LAPS, LapsToGo());
|
||||
if (m_car->_fuel < cmpfuel) {
|
||||
if (car_->_fuel < cmpfuel) {
|
||||
#ifdef STRAT_DEBUG
|
||||
cerr << car->_name << " REFUEL" << endl;
|
||||
#endif
|
||||
ret = true;
|
||||
} else {
|
||||
// Do we need to repair and is the pit free?
|
||||
if (m_car->_dammage > PIT_DAMAGE) {
|
||||
if (car_->_dammage > PIT_DAMAGE) {
|
||||
// Let's see if we can make it somehow onto the finish line
|
||||
// BEWARE doesnt check for limits, works for races > 5 laps!!!
|
||||
if (LapsToGo() <= LAST_LAPS) {
|
||||
// If prediction shows we would top the damage limit,
|
||||
// let's visit the pit
|
||||
if (m_car->_dammage + GetAvgDamage() * LapsToGo() >= 10000) {
|
||||
if (car_->_dammage + GetAvgDamage() * LapsToGo() >= 10000) {
|
||||
ret = IsPitFree();
|
||||
}
|
||||
} else {
|
||||
|
@ -314,8 +314,8 @@ bool KStrategy::NeedPitstop() const {
|
|||
* @return average damage increment
|
||||
*/
|
||||
int KStrategy::GetAvgDamage(void) const {
|
||||
return (m_last_damages->front() - m_last_damages->back())
|
||||
/ MAX(m_last_damages->size(), 1);
|
||||
return (last_damages_->front() - last_damages_->back())
|
||||
/ MAX(last_damages_->size(), 1);
|
||||
} // GetAvgDamage
|
||||
|
||||
|
||||
|
@ -331,7 +331,7 @@ int KStrategy::GetAvgDamage(void) const {
|
|||
int KStrategy::PitRepair() const {
|
||||
int ret = (LapsToGo() <= LAST_LAPS) // In the last N laps
|
||||
? GetAvgDamage() * LapsToGo() // repair only as much as really needed.
|
||||
: m_car->_dammage; // Otherwise repair everything.
|
||||
: car_->_dammage; // Otherwise repair everything.
|
||||
|
||||
#ifdef STRAT_DEBUG
|
||||
cerr << car->_name
|
||||
|
@ -340,14 +340,14 @@ int KStrategy::PitRepair() const {
|
|||
#endif
|
||||
|
||||
// Clear buffer
|
||||
m_last_damages->clear();
|
||||
last_damages_->clear();
|
||||
|
||||
return ret;
|
||||
} // pitRepair
|
||||
|
||||
|
||||
bool KStrategy::IsPitFree() const {
|
||||
if (m_car->_pit != NULL && m_car->_pit->pitCarIndex == TR_PIT_STATE_FREE)
|
||||
if (car_->_pit != NULL && car_->_pit->pitCarIndex == TR_PIT_STATE_FREE)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
class KStrategy {
|
||||
public:
|
||||
KStrategy();
|
||||
~KStrategy() {delete m_last_damages;}
|
||||
~KStrategy() {delete last_damages_;}
|
||||
|
||||
// Interface
|
||||
void Update();
|
||||
|
@ -50,33 +50,33 @@ class KStrategy {
|
|||
void ** const carParmHandle,
|
||||
const tSituation * const s,
|
||||
const int index);
|
||||
void set_car(const tCarElt * const car) {this->m_car = car;}
|
||||
void set_car(const tCarElt * const car) {this->car_ = car;}
|
||||
|
||||
protected:
|
||||
bool IsPitFree() const;
|
||||
int GetAvgDamage() const;
|
||||
inline int LapsToGo() const
|
||||
{return m_car->_remainingLaps - m_car->_lapsBehindLeader;}
|
||||
{return car_->_remainingLaps - car_->_lapsBehindLeader;}
|
||||
void UpdateFuelStrategy();
|
||||
void ComputeBestNumberOfPits(const double tankCapacity,
|
||||
const double requiredFuel,
|
||||
const int remainingLaps,
|
||||
const bool preRace);
|
||||
|
||||
const tCarElt * m_car;
|
||||
int m_laps;
|
||||
std::deque<int> *m_last_damages;
|
||||
int m_remaining_stops;
|
||||
double m_fuel_per_stint;
|
||||
double m_pittime; // Expected additional time for pit stop.
|
||||
double m_best_lap; // Best possible lap, empty tank and alone.
|
||||
double m_worst_lap; // Worst possible lap, full tank and alone.
|
||||
bool m_fuel_checked; // Fuel statistics updated.
|
||||
double m_fuel_per_lap; // Maximum amount of fuel we needed for a lap.
|
||||
double m_last_pit_fuel; // Amount refueled, special case when we refuel.
|
||||
double m_last_fuel; // Fuel available when we cross the start lane.
|
||||
double m_expected_fuel_per_lap; // Expected fuel per lap (may be inaccurate).
|
||||
double m_fuel_sum; // All the fuel used.
|
||||
const tCarElt * car_;
|
||||
int laps_;
|
||||
std::deque<int> *last_damages_;
|
||||
int remaining_stops_;
|
||||
double fuel_per_stint_;
|
||||
double pittime_; // Expected additional time for pit stop.
|
||||
double best_lap_; // Best possible lap, empty tank and alone.
|
||||
double worst_lap_; // Worst possible lap, full tank and alone.
|
||||
bool fuel_checked_; // Fuel statistics updated.
|
||||
double fuel_per_lap_; // Maximum amount of fuel we needed for a lap.
|
||||
double last_pit_fuel_; // Amount refueled, special case when we refuel.
|
||||
double last_fuel_; // Fuel available when we cross the start lane.
|
||||
double expected_fuel_per_lap_; // Expected fuel per lap (may be inaccurate).
|
||||
double fuel_sum_; // All the fuel used.
|
||||
|
||||
static const double MAX_FUEL_PER_METER; // [kg/m] fuel consumtion.
|
||||
static const int PIT_DAMAGE; // If damage > we request a pit stop.
|
||||
|
|
Loading…
Reference in a new issue