forked from speed-dreams/speed-dreams-code
More code cleanup.
Re #183. git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@2805 30fe4595-0a0c-4342-8851-515496e4dcbd Former-commit-id: f676c3d1119a9774e6520f7b064f3585a58f5c2e Former-commit-id: 9f562ec22146aec23c6f3b7e56b0fce94696b4a5
This commit is contained in:
parent
75221cb6db
commit
c901c15f59
9 changed files with 458 additions and 574 deletions
|
@ -762,10 +762,10 @@ Driver::getTargetPoint()
|
|||
raceline->GetPoint(offset, lookahead, &rt);
|
||||
double dx = t.x - car->_pos_X;
|
||||
double dy = t.y - car->_pos_Y;
|
||||
double dist1 = sqrt(dx * dx + dy * dy);
|
||||
double dist1 = Mag(dx, dy);
|
||||
dx = rt.x - car->_pos_X;
|
||||
dy = rt.y - car->_pos_Y;
|
||||
double dist2 = sqrt(dx * dx + dy * dy);
|
||||
double dist2 = Mag(dx, dy);
|
||||
if(dist2 > dist1)
|
||||
t = rt;
|
||||
}
|
||||
|
@ -1116,6 +1116,6 @@ Driver::brakedist(double allowedspeed, double mu)
|
|||
double c = mu * G;
|
||||
double d = (CA * mu + CW) / mass;
|
||||
double v1sqr = currentspeedsqr;
|
||||
double v2sqr = allowedspeed * allowedspeed;
|
||||
double v2sqr = pow(allowedspeed, 2);
|
||||
return -log((c + v2sqr * d) / (c + v1sqr * d)) / (2.0 * d);
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#define BT_ATT_BESTLAP "bestlap"
|
||||
#define BT_ATT_WORSTLAP "worstlap"
|
||||
#define BT_ATT_TEAMMATE "teammate"
|
||||
#define BT_ATT_SECRADIUS "securityradius"
|
||||
|
||||
|
||||
class Opponents;
|
||||
|
|
|
@ -55,7 +55,12 @@ KDriver::KDriver(int index):Driver(index)
|
|||
m_rInverse = 0.0;
|
||||
}
|
||||
|
||||
// Drive during race.
|
||||
|
||||
/**
|
||||
* Drive during the race.
|
||||
*
|
||||
* @param[in] s Situation provided by the sim.
|
||||
*/
|
||||
void
|
||||
KDriver::drive(tSituation * s)
|
||||
{
|
||||
|
@ -91,7 +96,11 @@ KDriver::drive(tSituation * s)
|
|||
}//drive
|
||||
|
||||
|
||||
// Check if I'm stuck.
|
||||
/**
|
||||
* Checks if I'm stuck.
|
||||
*
|
||||
* @return true if stuck
|
||||
*/
|
||||
bool
|
||||
KDriver::isStuck()
|
||||
{
|
||||
|
@ -113,7 +122,13 @@ KDriver::isStuck()
|
|||
}//isStuck
|
||||
|
||||
|
||||
// Reduces the brake value such that it fits the speed (more downforce -> more braking).
|
||||
/**
|
||||
* Reduces the brake value such that it fits the speed
|
||||
* (more downforce -> more braking).
|
||||
*
|
||||
* @param[in] brake Original braking value
|
||||
* @return Modified braking value
|
||||
*/
|
||||
double
|
||||
KDriver::filterBrakeSpeed(double brake)
|
||||
{
|
||||
|
@ -121,7 +136,7 @@ KDriver::filterBrakeSpeed(double brake)
|
|||
double maxForce = weight + CA * MAX_SPEED * MAX_SPEED;
|
||||
double force = weight + CA * currentspeedsqr;
|
||||
return brake * force / maxForce;
|
||||
}
|
||||
}//filterBrakeSpeed
|
||||
|
||||
|
||||
// Compute offset to normal target point for overtaking or let pass an opponent.
|
||||
|
@ -176,21 +191,21 @@ KDriver::getOffset()
|
|||
}
|
||||
|
||||
//Check for side collision
|
||||
o = get_sidecoll_opp();
|
||||
o = getSidecollOpp();
|
||||
if(o != NULL)
|
||||
return filter_sidecoll_offset(o, incfactor);
|
||||
return filterSidecollOffset(o, incfactor);
|
||||
|
||||
|
||||
// If we have someone to take over, let's try it
|
||||
o = get_takeover_opp();
|
||||
o = getTakeoverOpp();
|
||||
if(o != NULL)
|
||||
return filter_takeover_offset(o);
|
||||
return filterTakeoverOffset(o);
|
||||
|
||||
|
||||
// If there is someone overlapping, move out of the way
|
||||
o = get_overlapping_opp();
|
||||
o = getOverlappingOpp();
|
||||
if(o != NULL)
|
||||
return filter_overlapped_offset(o);
|
||||
return filterOverlappedOffset(o);
|
||||
|
||||
|
||||
// no-one to avoid, work back towards raceline
|
||||
|
@ -213,10 +228,7 @@ KDriver::getOffset()
|
|||
}//getOffset
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* name: get_overlapping_opp
|
||||
*
|
||||
/**
|
||||
* Decide if there is a car behind overlapping us.
|
||||
*
|
||||
* A1) Teammate behind with more laps should overtake.
|
||||
|
@ -226,121 +238,93 @@ KDriver::getOffset()
|
|||
* than TEAM_DAMAGE_CHANGE_LEAD.
|
||||
* B) Let other, overlapping opponents get by.
|
||||
|
||||
* @param: -
|
||||
* @return: Opponent *, overlapping car pointer or NULL
|
||||
* @return overlapping car pointer or NULL
|
||||
*/
|
||||
Opponent *
|
||||
KDriver::get_overlapping_opp()
|
||||
KDriver::getOverlappingOpp()
|
||||
{
|
||||
Opponent *ret = NULL;
|
||||
double mindist = -1000.0;
|
||||
|
||||
for(list<Opponent>::iterator it = opponents->begin();
|
||||
it != opponents->end();
|
||||
it++)
|
||||
{
|
||||
tCarElt *ocar = it->getCarPtr();
|
||||
double opp_distance = it->getDistance();
|
||||
it++) {
|
||||
tCarElt *ocar = it->getCarPtr();
|
||||
double oppDistance = it->getDistance();
|
||||
|
||||
if(
|
||||
(//if teammate has more laps under his belt,
|
||||
(it->is_teammate() && ocar->race.laps > car->race.laps)
|
||||
|| //or teammate is less damaged, let him go
|
||||
it->is_quicker_teammate(car)
|
||||
)
|
||||
&& //if close enough
|
||||
(opp_distance > -TEAM_REAR_DIST)
|
||||
&&
|
||||
(opp_distance < -car->_dimension_x)
|
||||
)
|
||||
{
|
||||
// Behind, larger distances are smaller ("more negative").
|
||||
if(opp_distance > mindist) {
|
||||
mindist = opp_distance;
|
||||
ret = &(*it);
|
||||
}
|
||||
} // if teammate
|
||||
else if(it->is_state(OPP_LETPASS))
|
||||
{
|
||||
// Behind, larger distances are smaller ("more negative").
|
||||
if(opp_distance > mindist) {
|
||||
mindist = opp_distance;
|
||||
ret = &(*it);
|
||||
}
|
||||
} // else if
|
||||
} // for i
|
||||
if((//if teammate has more laps under his belt,
|
||||
(it->isTeammate() && 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->isState(OPP_LETPASS)) {
|
||||
// Behind, larger distances are smaller ("more negative").
|
||||
if(oppDistance > mindist) {
|
||||
mindist = oppDistance;
|
||||
ret = &(*it);
|
||||
}
|
||||
} // else if
|
||||
} // for i
|
||||
|
||||
return ret;
|
||||
}//get_overlapping_opp
|
||||
}//getOverlappingOpp
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* name: filter_overlapped_offset
|
||||
*
|
||||
/**
|
||||
* Modifies the member 'myoffset' so that the car moves out of the way
|
||||
* of the overlapping opponent.
|
||||
*
|
||||
* @param Opponent *o: the opponent we should let go
|
||||
* @return: double, new offset. Equals member 'myoffset'
|
||||
* @param [in] o: the opponent we should let go
|
||||
* @return new offset. Equals member 'myoffset'
|
||||
*
|
||||
*/
|
||||
double
|
||||
KDriver::filter_overlapped_offset(Opponent *o)
|
||||
KDriver::filterOverlappedOffset(Opponent *o)
|
||||
{
|
||||
double w = car->_trkPos.seg->width / WIDTHDIV - BORDER_OVERTAKE_MARGIN;
|
||||
|
||||
if(opp_is_on_right(o))
|
||||
{
|
||||
if(myoffset < w)
|
||||
myoffset += OVERTAKE_OFFSET_INC * m_lftinc / 1;//2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(myoffset > -w)
|
||||
myoffset -= OVERTAKE_OFFSET_INC * m_rgtinc / 1;//2;
|
||||
}
|
||||
if(o->isOnRight(car->_trkPos.toMiddle)) {
|
||||
if(myoffset < w)
|
||||
myoffset += OVERTAKE_OFFSET_INC * m_lftinc / 1;//2;
|
||||
} else {
|
||||
if(myoffset > -w)
|
||||
myoffset -= OVERTAKE_OFFSET_INC * m_rgtinc / 1;//2;
|
||||
}
|
||||
setMode(BEING_OVERLAPPED);
|
||||
|
||||
myoffset = MIN(avoidlftoffset, MAX(avoidrgtoffset, myoffset));
|
||||
return myoffset;
|
||||
}
|
||||
}//filterOverlappedOffset
|
||||
|
||||
/*
|
||||
*
|
||||
* name: filterOverlap
|
||||
*
|
||||
|
||||
/**
|
||||
* If there is an opponent overlapping us, reduce accelerator.
|
||||
*
|
||||
* @param double accel: original acceleration value
|
||||
* @return: double, possibly reduced acceleration value
|
||||
* @param [in] accel: original acceleration value
|
||||
* @return possibly reduced acceleration value
|
||||
*/
|
||||
double
|
||||
KDriver::filterOverlap(double accel)
|
||||
{
|
||||
return (get_opp_by_state(OPP_LETPASS) ? MIN(accel, LET_OVERTAKE_FACTOR) : accel);
|
||||
}
|
||||
return (opponents->getOppByState(OPP_LETPASS)
|
||||
? MIN(accel, LET_OVERTAKE_FACTOR)
|
||||
: accel);
|
||||
}//filterOverlap
|
||||
|
||||
Opponent *
|
||||
KDriver::get_opp_by_state(const int state)
|
||||
{
|
||||
Opponent *ret = NULL;
|
||||
for(list<Opponent>::iterator it = opponents->begin();
|
||||
it != opponents->end();
|
||||
it++)
|
||||
{
|
||||
if(it->is_state(state))
|
||||
{
|
||||
ret = &(*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* If opponent is too much on either side of the track,
|
||||
* (doesn't occupy center part of the segment)
|
||||
* and we are 5+ metres far
|
||||
*
|
||||
* @param [in] ocar the opponent car
|
||||
* @return true if the opp. is too far on either side
|
||||
*/
|
||||
bool
|
||||
KDriver::oppTooFarOnSide(tCarElt *ocar)
|
||||
|
@ -350,76 +334,76 @@ KDriver::oppTooFarOnSide(tCarElt *ocar)
|
|||
&& fabs(car->_trkPos.toMiddle - ocar->_trkPos.toMiddle) >= 5.0)
|
||||
ret = true;
|
||||
return ret;
|
||||
}
|
||||
}//oppTooFarOnSide
|
||||
|
||||
/*
|
||||
*
|
||||
* name: get_takeover_opp
|
||||
*
|
||||
|
||||
/**
|
||||
* Decide if there is a car ahead we can take over.
|
||||
*
|
||||
* @param: -
|
||||
* @return: Opponent *, overlapping car pointer or NULL
|
||||
* @return Overlap car pointer or NULL
|
||||
*/
|
||||
Opponent*
|
||||
KDriver::get_takeover_opp()
|
||||
KDriver::getTakeoverOpp()
|
||||
{
|
||||
Opponent *ret = NULL;
|
||||
|
||||
m_mincatchdist = MAX(30.0, 1500.0 - fabs(m_rInverse) * 10000);
|
||||
int otry_success = 0;
|
||||
int otrySuccess = 0;
|
||||
|
||||
for(int otry = 0; otry <= 1; otry++)
|
||||
{
|
||||
for(list<Opponent>::iterator it = opponents->begin();
|
||||
it != opponents->end();
|
||||
it++)
|
||||
{
|
||||
tCarElt *ocar = it->getCarPtr();
|
||||
for(int otry = 0; otry <= 1; otry++) {
|
||||
for(list<Opponent>::iterator it = opponents->begin();
|
||||
it != opponents->end();
|
||||
it++) {
|
||||
tCarElt *ocar = it->getCarPtr();
|
||||
|
||||
// If opponent is clearly ahead of us, we don't care
|
||||
if(it->is_state(OPP_FRONT_FOLLOW))
|
||||
continue;
|
||||
// If opponent is clearly ahead of us, we don't care
|
||||
if(it->isState(OPP_FRONT_FOLLOW))
|
||||
continue;
|
||||
|
||||
if(oppTooFarOnSide(ocar))
|
||||
continue;
|
||||
if(oppTooFarOnSide(ocar))
|
||||
continue;
|
||||
|
||||
// If opponent is in pit, let him be ;)
|
||||
if(ocar->_state > RM_CAR_STATE_PIT)
|
||||
continue;
|
||||
// If opponent is in pit, let him be ;)
|
||||
if(ocar->_state > RM_CAR_STATE_PIT)
|
||||
continue;
|
||||
|
||||
// If opponent is ahead, and is not a quicker teammate of ours
|
||||
if((it->is_state(OPP_FRONT))
|
||||
&& !it->is_quicker_teammate(car))
|
||||
{
|
||||
double otry_factor = (otry ? (0.2 + (1.0 - ((currentsimtime - avoidtime) / 7.0)) * 0.8) : 1.0);
|
||||
double distance = it->getDistance() * otry_factor; //how far ahead is he
|
||||
double speed = MIN(avoidspeed, getSpeed() + MAX(0.0, 10.0 - distance));
|
||||
double ospeed = it->getSpeed(); //opponent's speed
|
||||
double catchdist = MIN(speed * distance / (speed - ospeed),
|
||||
distance * CATCH_FACTOR) * otry_factor; //when will we reach the opponent
|
||||
// If opponent is ahead, and is not a quicker teammate of ours
|
||||
if((it->isState(OPP_FRONT))
|
||||
&& !it->isQuickerTeammate(car)) {
|
||||
double otry_factor = (otry ? (0.2 + (1.0 - ((currentsimtime - avoidtime) / 7.0)) * 0.8) : 1.0);
|
||||
double distance = it->getDistance() * otry_factor; //how far ahead is he
|
||||
double speed = MIN(avoidspeed, getSpeed() + MAX(0.0, 10.0 - distance));
|
||||
double ospeed = it->getSpeed(); //opponent's speed
|
||||
double catchdist = MIN(speed * distance / (speed - ospeed),
|
||||
distance * CATCH_FACTOR) * otry_factor; //when will we reach the opponent
|
||||
|
||||
//if we are close enough, check again with avoidance speed taken into account
|
||||
if(catchdist < m_mincatchdist && distance < fabs(speed - ospeed) * 2)
|
||||
{
|
||||
m_mincatchdist = catchdist;
|
||||
ret = &(*it); //This is the guy we need to take over
|
||||
otry_success = otry;
|
||||
}
|
||||
}
|
||||
} //for it
|
||||
if (ret) break;
|
||||
if (mode != AVOIDING) break;
|
||||
} //for otry
|
||||
//if we are close enough, check again with avoidance speed taken into account
|
||||
if(catchdist < m_mincatchdist && distance < fabs(speed - ospeed) * 2) {
|
||||
m_mincatchdist = catchdist;
|
||||
ret = &(*it); //This is the guy we need to take over
|
||||
otrySuccess = otry;
|
||||
}
|
||||
}//if it state
|
||||
} //for it
|
||||
if (ret) break;
|
||||
if (mode != AVOIDING) break;
|
||||
} //for otry
|
||||
|
||||
if(ret != NULL && otry_success == 0)
|
||||
if(ret != NULL && otrySuccess == 0)
|
||||
avoidtime = currentsimtime;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}//getTakeoverOpp
|
||||
|
||||
|
||||
/**
|
||||
* Change offset value if we are to overtake a car.
|
||||
*
|
||||
* @param [in] o the opponent
|
||||
* @return new offset
|
||||
*/
|
||||
double
|
||||
KDriver::filter_takeover_offset(Opponent *o)
|
||||
KDriver::filterTakeoverOffset(Opponent *o)
|
||||
{
|
||||
setMode(AVOIDING);
|
||||
tCarElt *ocar = o->getCarPtr();
|
||||
|
@ -435,166 +419,154 @@ KDriver::filter_takeover_offset(Opponent *o)
|
|||
(otm > (ocar->_trkPos.seg->width - 5.0) && m_rInverse > 0.0))
|
||||
sidemargin += fabs(m_rInverse) * 150;
|
||||
|
||||
if (otm > (ocar->_trkPos.seg->width - 5.0) ||
|
||||
(car->_trkPos.toLeft > ocar->_trkPos.toLeft &&
|
||||
(sidedist < sidemargin || o->is_state(OPP_COLL))))
|
||||
{
|
||||
myoffset -= OVERTAKE_OFFSET_INC * m_rgtinc;
|
||||
setAvoidLeft();
|
||||
if (otm > (ocar->_trkPos.seg->width - 5.0)
|
||||
|| (car->_trkPos.toLeft > ocar->_trkPos.toLeft
|
||||
&& (sidedist < sidemargin || o->isState(OPP_COLL)))) {
|
||||
myoffset -= OVERTAKE_OFFSET_INC * m_rgtinc;
|
||||
setAvoidLeft();
|
||||
} else if (otm < -(ocar->_trkPos.seg->width - 5.0)
|
||||
|| (car->_trkPos.toLeft < ocar->_trkPos.toLeft
|
||||
&& (sidedist < sidemargin || o->isState(OPP_COLL)))) {
|
||||
myoffset += OVERTAKE_OFFSET_INC * m_lftinc;
|
||||
setAvoidRight();
|
||||
} else {
|
||||
// If the opponent is near the middle we try to move the offset toward
|
||||
// the inside of the expected turn.
|
||||
// Try to find out the characteristic of the track up to catchdist.
|
||||
tTrackSeg *seg = car->_trkPos.seg;
|
||||
double length = getDistToSegEnd();
|
||||
double oldlen, seglen = length;
|
||||
double lenright = 0.0, lenleft = 0.0;
|
||||
m_mincatchdist = MIN(m_mincatchdist, DISTCUTOFF);
|
||||
|
||||
do {
|
||||
switch(seg->type) {
|
||||
case TR_LFT:
|
||||
lenleft += seglen;
|
||||
break;
|
||||
case TR_RGT:
|
||||
lenright += seglen;
|
||||
break;
|
||||
default:
|
||||
// Do nothing.
|
||||
break;
|
||||
}//switch seg->type
|
||||
seg = seg->next;
|
||||
seglen = seg->length;
|
||||
oldlen = length;
|
||||
length += seglen;
|
||||
} while(oldlen < m_mincatchdist);
|
||||
|
||||
// If we are on a straight look for the next turn.
|
||||
if(lenleft == 0.0 && lenright == 0.0) {
|
||||
while(seg->type == TR_STR)
|
||||
seg = seg->next;
|
||||
|
||||
// Assume: left or right if not straight.
|
||||
if(seg->type == TR_LFT)
|
||||
lenleft = 1.0;
|
||||
else
|
||||
lenright = 1.0;
|
||||
}//if lenleft/lenright == 0
|
||||
|
||||
// Because we are inside we can go to the limit.
|
||||
if ((lenleft > lenright && m_rInverse < 0.0) ||
|
||||
(lenleft <= lenright && m_rInverse > 0.0)) {
|
||||
// avoid more if on the outside of opponent on a bend. Stops us
|
||||
// from cutting in too much and colliding...
|
||||
sidemargin += fabs(m_rInverse) * 150;
|
||||
}
|
||||
else if (otm < -(ocar->_trkPos.seg->width - 5.0) ||
|
||||
(car->_trkPos.toLeft < ocar->_trkPos.toLeft &&
|
||||
(sidedist < sidemargin || o->is_state(OPP_COLL))))
|
||||
{
|
||||
myoffset += OVERTAKE_OFFSET_INC * m_lftinc;
|
||||
setAvoidRight();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the opponent is near the middle we try to move the offset toward
|
||||
// the inside of the expected turn.
|
||||
// Try to find out the characteristic of the track up to catchdist.
|
||||
tTrackSeg *seg = car->_trkPos.seg;
|
||||
double length = getDistToSegEnd();
|
||||
double oldlen, seglen = length;
|
||||
double lenright = 0.0, lenleft = 0.0;
|
||||
m_mincatchdist = MIN(m_mincatchdist, DISTCUTOFF);
|
||||
|
||||
do
|
||||
{
|
||||
switch(seg->type)
|
||||
{
|
||||
case TR_LFT:
|
||||
lenleft += seglen;
|
||||
break;
|
||||
case TR_RGT:
|
||||
lenright += seglen;
|
||||
break;
|
||||
default:
|
||||
// Do nothing.
|
||||
break;
|
||||
}
|
||||
seg = seg->next;
|
||||
seglen = seg->length;
|
||||
oldlen = length;
|
||||
length += seglen;
|
||||
}
|
||||
while(oldlen < m_mincatchdist);
|
||||
|
||||
// If we are on a straight look for the next turn.
|
||||
if(lenleft == 0.0 && lenright == 0.0)
|
||||
{
|
||||
while(seg->type == TR_STR)
|
||||
{
|
||||
seg = seg->next;
|
||||
}
|
||||
// Assume: left or right if not straight.
|
||||
if(seg->type == TR_LFT)
|
||||
lenleft = 1.0;
|
||||
else
|
||||
lenright = 1.0;
|
||||
}
|
||||
|
||||
// Because we are inside we can go to the border.
|
||||
if ((lenleft > lenright && m_rInverse < 0.0) ||
|
||||
(lenleft <= lenright && m_rInverse > 0.0))
|
||||
{
|
||||
// avoid more if on the outside of opponent on a bend. Stops us
|
||||
// from cutting in too much and colliding...
|
||||
sidemargin += fabs(m_rInverse) * 150;
|
||||
}
|
||||
|
||||
if(sidedist < sidemargin || o->is_state(OPP_COLL))
|
||||
{
|
||||
if(lenleft > lenright)
|
||||
{
|
||||
myoffset += OVERTAKE_OFFSET_INC * m_lftinc;// * 0.7;
|
||||
setAvoidRight();
|
||||
}
|
||||
else
|
||||
{
|
||||
myoffset -= OVERTAKE_OFFSET_INC * m_rgtinc;// * 0.7;
|
||||
setAvoidLeft();
|
||||
}//if lenleft
|
||||
}//if sidedist
|
||||
}//if opp near middle
|
||||
if(sidedist < sidemargin || o->isState(OPP_COLL)) {
|
||||
if(lenleft > lenright) {
|
||||
myoffset += OVERTAKE_OFFSET_INC * m_lftinc;// * 0.7;
|
||||
setAvoidRight();
|
||||
} else {
|
||||
myoffset -= OVERTAKE_OFFSET_INC * m_rgtinc;// * 0.7;
|
||||
setAvoidLeft();
|
||||
}//if lenleft > lenright
|
||||
}//if sidedist
|
||||
}//if opp near middle
|
||||
|
||||
myoffset = MIN(avoidlftoffset, MAX(avoidrgtoffset, myoffset));
|
||||
myoffset = MIN(m_maxoffset, MAX(m_minoffset, myoffset));
|
||||
return myoffset;
|
||||
}//filter_takeover_offset
|
||||
}//filterTakeoverOffset
|
||||
|
||||
|
||||
/**
|
||||
* Decide if there is a car on the side we are to collide with...
|
||||
*
|
||||
* @return Side collision car pointer or NULL
|
||||
*/
|
||||
Opponent *
|
||||
KDriver::get_sidecoll_opp()
|
||||
KDriver::getSidecollOpp()
|
||||
{
|
||||
Opponent *ret = NULL;
|
||||
for(list<Opponent>::iterator it = opponents->begin();
|
||||
it != opponents->end();
|
||||
it++)
|
||||
{
|
||||
tCarElt *ocar = it->getCarPtr();
|
||||
it++) {
|
||||
tCarElt *ocar = it->getCarPtr();
|
||||
|
||||
if(ocar->_state > RM_CAR_STATE_PIT) //Dont care for opponents in the pit
|
||||
continue;
|
||||
if(ocar->_state > RM_CAR_STATE_PIT) //Dont care for opponents in the pit
|
||||
continue;
|
||||
|
||||
if(oppTooFarOnSide(ocar))
|
||||
continue;
|
||||
if(oppTooFarOnSide(ocar))
|
||||
continue;
|
||||
|
||||
if(it->is_state(OPP_SIDE)) //If opponent is on our side
|
||||
{
|
||||
setMode(AVOIDING);
|
||||
ret = &(*it);
|
||||
break;
|
||||
} //if OPP_SIDE
|
||||
} //for it
|
||||
if(it->isState(OPP_SIDE)) { //If opponent is on our side
|
||||
setMode(AVOIDING);
|
||||
ret = &(*it);
|
||||
break;
|
||||
} //if OPP_SIDE
|
||||
} //for it
|
||||
|
||||
return ret;
|
||||
}
|
||||
}//getSidecollOpp
|
||||
|
||||
|
||||
double
|
||||
KDriver::filter_sidecoll_offset(Opponent *o,
|
||||
const double incfactor)
|
||||
KDriver::filterSidecollOffset(Opponent *o, const double incfactor)
|
||||
{
|
||||
double myToLeft = car->_trkPos.toLeft;
|
||||
double oppToLeft = o->getCarPtr()->_trkPos.toLeft;
|
||||
double sidedist = fabs(oppToLeft - myToLeft);
|
||||
double sidemargin = o->getWidth() + getWidth() + 2.0;
|
||||
|
||||
bool oppOnRight = o->isOnRight(car->_trkPos.toMiddle);
|
||||
// avoid more if on the outside of opponent on a bend.
|
||||
// Stops us from cutting in too much and colliding...
|
||||
if((opp_is_on_right(o) && m_rInverse < 0.0)
|
||||
|| (!opp_is_on_right(o) && m_rInverse > 0.0))
|
||||
if((oppOnRight && m_rInverse < 0.0)
|
||||
|| (!oppOnRight && m_rInverse > 0.0))
|
||||
sidemargin += fabs(m_rInverse) * 150;
|
||||
|
||||
if(opp_is_on_right(o))
|
||||
if(oppOnRight)
|
||||
sidemargin -= MIN(0.0, m_rInverse * 100);
|
||||
else
|
||||
sidemargin += MAX(0.0, m_rInverse * 100);
|
||||
sidedist = MIN(sidedist, sidemargin);
|
||||
|
||||
if(sidedist < sidemargin)
|
||||
{
|
||||
double sdiff = 3.0 - (sidemargin - sidedist) / sidemargin;
|
||||
|
||||
if(opp_is_on_right(o)) //He is on the right, we must move to the left
|
||||
myoffset += OVERTAKE_OFFSET_INC * m_lftinc * MAX(0.2, MIN(1.0, sdiff));
|
||||
else //He is on the left, we must move to the right
|
||||
myoffset -= OVERTAKE_OFFSET_INC * m_rgtinc * MAX(0.2, MIN(1.0, sdiff));
|
||||
}
|
||||
else if(sidedist > sidemargin + 3.0)
|
||||
{
|
||||
if(raceoffset > myoffset + OVERTAKE_OFFSET_INC * incfactor)
|
||||
myoffset += OVERTAKE_OFFSET_INC * m_lftinc / 4;
|
||||
else if (raceoffset < myoffset - OVERTAKE_OFFSET_INC * incfactor)
|
||||
myoffset -= OVERTAKE_OFFSET_INC * m_rgtinc / 4;
|
||||
}
|
||||
if(sidedist < sidemargin) {
|
||||
double sdiff = 3.0 - (sidemargin - sidedist) / sidemargin;
|
||||
|
||||
if(oppOnRight) //He is on the right, we must move to the left
|
||||
myoffset += OVERTAKE_OFFSET_INC * m_lftinc * MAX(0.2, MIN(1.0, sdiff));
|
||||
else //He is on the left, we must move to the right
|
||||
myoffset -= OVERTAKE_OFFSET_INC * m_rgtinc * MAX(0.2, MIN(1.0, sdiff));
|
||||
} else if(sidedist > sidemargin + 3.0) {
|
||||
if(raceoffset > myoffset + OVERTAKE_OFFSET_INC * incfactor)
|
||||
myoffset += OVERTAKE_OFFSET_INC * m_lftinc / 4;
|
||||
else if (raceoffset < myoffset - OVERTAKE_OFFSET_INC * incfactor)
|
||||
myoffset -= OVERTAKE_OFFSET_INC * m_rgtinc / 4;
|
||||
}
|
||||
|
||||
opp_is_on_right(o) ? setAvoidRight() : setAvoidLeft();
|
||||
oppOnRight ? setAvoidRight() : setAvoidLeft();
|
||||
avoidmode |= AVOIDSIDE;
|
||||
|
||||
myoffset = MIN(m_maxoffset, MAX(m_minoffset, myoffset));
|
||||
return myoffset;
|
||||
}
|
||||
}//filterSidecollOffset
|
||||
|
||||
|
||||
void
|
||||
KDriver::initTrack(tTrack * t, void *carHandle, void **carParmHandle,
|
||||
|
@ -650,6 +622,7 @@ KDriver::initTrack(tTrack * t, void *carHandle, void **carParmHandle,
|
|||
*carParmHandle = newhandle;
|
||||
}
|
||||
|
||||
|
||||
// Create a pit stop strategy object.
|
||||
strategy = new KStrategy();
|
||||
// Init fuel.
|
||||
|
@ -661,53 +634,35 @@ KDriver::initTrack(tTrack * t, void *carHandle, void **carParmHandle,
|
|||
MU_FACTOR = GfParmGetNum(*carParmHandle, BT_SECT_PRIV, BT_ATT_MUFACTOR,
|
||||
(char *) NULL, 0.69f);
|
||||
|
||||
double MinCornerInverse =
|
||||
GfParmGetNum(*carParmHandle, BT_SECT_PRIV, "MinCornerInverse",
|
||||
(char *) NULL, 0.002);
|
||||
double CornerSpeed =
|
||||
GfParmGetNum(*carParmHandle, BT_SECT_PRIV, "CornerSpeed",
|
||||
(char *) NULL, 15.0);
|
||||
double AvoidSpeed =
|
||||
GfParmGetNum(*carParmHandle, BT_SECT_PRIV, "AvoidSpeedAdjust",
|
||||
(char *) NULL, 2.0);
|
||||
double CornerAccel =
|
||||
GfParmGetNum(*carParmHandle, BT_SECT_PRIV, "CornerAccel",
|
||||
(char *) NULL, 1.0);
|
||||
double IntMargin = GfParmGetNum(*carParmHandle, BT_SECT_PRIV, "IntMargin",
|
||||
(char *) NULL, 1.0);
|
||||
double ExtMargin = GfParmGetNum(*carParmHandle, BT_SECT_PRIV, "ExtMargin",
|
||||
(char *) NULL, 2.0);
|
||||
brakedelay = GfParmGetNum(*carParmHandle, BT_SECT_PRIV, "BrakeDelay",
|
||||
(char *) NULL, 10.0);
|
||||
PitOffset = GfParmGetNum(*carParmHandle, BT_SECT_PRIV, "PitOffset",
|
||||
(char *) NULL, 10.0);
|
||||
brakedelay = GfParmGetNum(*carParmHandle, BT_SECT_PRIV, "BrakeDelay",
|
||||
(char *) NULL, 10.0);
|
||||
|
||||
raceline->InitTrack(track, carParmHandle, s);
|
||||
}
|
||||
|
||||
// Update my private data every timestep.
|
||||
/**
|
||||
* Update own private data on every timestep.
|
||||
*
|
||||
* @param [in] s situation provided by the sim
|
||||
*/
|
||||
void
|
||||
KDriver::update(tSituation * s)
|
||||
{
|
||||
// Update global car data (shared by all instances) just once per timestep.
|
||||
if(currentsimtime != s->currentTime)
|
||||
{
|
||||
currentsimtime = s->currentTime;
|
||||
cardata->update();
|
||||
}
|
||||
// Update the local data rest.
|
||||
if(currentsimtime != s->currentTime) {
|
||||
currentsimtime = s->currentTime;
|
||||
cardata->update();
|
||||
}
|
||||
// Update the rest of local data
|
||||
speedangle = -(mycardata->getTrackangle() -
|
||||
atan2(car->_speed_Y, car->_speed_X));
|
||||
NORM_PI_PI(speedangle);
|
||||
mass = CARMASS + car->_fuel;
|
||||
currentspeedsqr = car->_speed_x * car->_speed_x;
|
||||
currentspeedsqr = pow(car->_speed_x, 2);
|
||||
|
||||
opponents->update(s, this);
|
||||
strategy->update();
|
||||
|
||||
check_pit_status(s);
|
||||
checkPitStatus(s);
|
||||
pit->update();
|
||||
simtime = s->currentTime;
|
||||
|
||||
|
@ -715,21 +670,17 @@ KDriver::update(tSituation * s)
|
|||
angle = trackangle - car->_yaw;
|
||||
NORM_PI_PI(angle);
|
||||
angle = -angle;
|
||||
}
|
||||
}//update
|
||||
|
||||
/*
|
||||
*
|
||||
* name: check_pit_status
|
||||
*
|
||||
/**
|
||||
* Checks if we need to plan a pitstop.
|
||||
* If yes, checks availability of the pit,
|
||||
* is it free or occupied by teammate.
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
* @param [in] s Situation provided by the sim
|
||||
*/
|
||||
void
|
||||
KDriver::check_pit_status(tSituation *s)
|
||||
KDriver::checkPitStatus(tSituation *s)
|
||||
{
|
||||
//If our car is still in the race
|
||||
if(car->_state <= RM_CAR_STATE_PIT)
|
||||
|
@ -753,7 +704,7 @@ KDriver::check_pit_status(tSituation *s)
|
|||
{
|
||||
tCarElt *ocar = it->getCarPtr();
|
||||
//If the other car is our teammate, still in the race
|
||||
if(it->is_teammate() && ocar->_state <= RM_CAR_STATE_PIT)
|
||||
if(it->isTeammate() && ocar->_state <= RM_CAR_STATE_PIT)
|
||||
{
|
||||
int idx = it->getIndex();
|
||||
if(pitstatus[idx] == 1
|
||||
|
@ -773,35 +724,40 @@ KDriver::check_pit_status(tSituation *s)
|
|||
}
|
||||
else
|
||||
pitstatus[carindex] = 0;
|
||||
}
|
||||
}//checkPitStatus
|
||||
|
||||
|
||||
// Brake filter for collision avoidance.
|
||||
/**
|
||||
* Brake filter for collision avoidance.
|
||||
* If there is an opponent we are to collide, brake brake brake!
|
||||
*
|
||||
* @param [in] brake Original brake value
|
||||
* @return Possibly modified brake value
|
||||
*/
|
||||
double
|
||||
KDriver::filterBColl(double brake)
|
||||
KDriver::filterBColl(const double brake)
|
||||
{
|
||||
if(simtime < 1.5)
|
||||
return brake;
|
||||
double ret = brake;
|
||||
|
||||
if(simtime >= 1.5) {
|
||||
double mu = car->_trkPos.seg->surface->kFriction;
|
||||
for(list<Opponent>::iterator it = opponents->begin();
|
||||
it != opponents->end();
|
||||
it++) {
|
||||
if(it->isState(OPP_COLL)) { //Endangered species
|
||||
double ospeed = it->getSpeed();
|
||||
if(brakedist(ospeed, mu) + MIN(1.0, 0.5 + MAX(0.0,(getSpeed() - ospeed) / 4))
|
||||
> it->getDistance()) { //Damn, too close, brake hard!!!
|
||||
accelcmd = 0.0;
|
||||
ret = 1.0;
|
||||
break;
|
||||
}//if brakedist
|
||||
}//if state OPP_COLL
|
||||
}//for it
|
||||
|
||||
return ret;
|
||||
}//filterBColl
|
||||
|
||||
double mu = car->_trkPos.seg->surface->kFriction;
|
||||
for(list<Opponent>::iterator it = opponents->begin();
|
||||
it != opponents->end();
|
||||
it++)
|
||||
{
|
||||
if(it->is_state(OPP_COLL))
|
||||
{
|
||||
double ospeed = it->getSpeed();
|
||||
if(brakedist(ospeed, mu)
|
||||
+ MIN(1.0, 0.5 + MAX(0.0,(getSpeed() - ospeed) / 4))
|
||||
> it->getDistance())
|
||||
{
|
||||
accelcmd = 0.0;
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return brake;
|
||||
}
|
||||
|
||||
// Set pitstop commands.
|
||||
int
|
||||
|
@ -812,14 +768,16 @@ KDriver::pitCommand(tSituation * s)
|
|||
// This should be the only place where the pit stop is set to false!
|
||||
pit->setPitstop(false);
|
||||
return ROB_PIT_IM; // return immediately.
|
||||
}
|
||||
}//pitCommand
|
||||
|
||||
|
||||
void
|
||||
KDriver::newRace(tCarElt * car, tSituation * s)
|
||||
{
|
||||
strategy->setCar(car);
|
||||
Driver::newRace(car, s);
|
||||
}
|
||||
}//newRace
|
||||
|
||||
|
||||
void
|
||||
KDriver::calcSpeed()
|
||||
|
@ -851,9 +809,3 @@ KDriver::calcSpeed()
|
|||
brakecmd = MIN(1.0, -(MAX(10.0, brakedelay * 0.7)) * x);
|
||||
}//calcSpeed
|
||||
|
||||
inline bool
|
||||
KDriver::opp_is_on_right(Opponent *o) {
|
||||
return (car->_trkPos.toMiddle > o->getCarPtr()->_trkPos.toMiddle)
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
|
|
|
@ -57,15 +57,13 @@ protected:
|
|||
bool oppTooFarOnSide(tCarElt *ocar);
|
||||
|
||||
//'own' utilities
|
||||
Opponent * get_overlapping_opp();
|
||||
Opponent * get_takeover_opp();
|
||||
Opponent * get_sidecoll_opp();
|
||||
double filter_overlapped_offset(Opponent *o);
|
||||
double filter_takeover_offset(Opponent *o);
|
||||
double filter_sidecoll_offset(Opponent *o, const double);
|
||||
Opponent * get_opp_by_state(const int state);
|
||||
inline bool opp_is_on_right(Opponent *o);
|
||||
void check_pit_status(tSituation *s);
|
||||
Opponent * getOverlappingOpp();
|
||||
Opponent * getTakeoverOpp();
|
||||
Opponent * getSidecollOpp();
|
||||
double filterOverlappedOffset(Opponent *o);
|
||||
double filterTakeoverOffset(Opponent *o);
|
||||
double filterSidecollOffset(Opponent *o, const double);
|
||||
void checkPitStatus(tSituation *s);
|
||||
|
||||
//'own' variables
|
||||
double m_mincatchdist;
|
||||
|
|
|
@ -97,7 +97,7 @@ Opponent::update(tSituation *s, Driver *driver)
|
|||
{
|
||||
m_state |= OPP_FRONT;
|
||||
|
||||
if(is_quicker_teammate(mycar))
|
||||
if(isQuickerTeammate(mycar))
|
||||
m_state |= OPP_FRONT_FOLLOW;
|
||||
|
||||
m_distance -= SIDECOLLDIST;
|
||||
|
@ -145,7 +145,7 @@ Opponent::update(tSituation *s, Driver *driver)
|
|||
else if(m_distance > SIDECOLLDIST && getSpeed() > driver->getSpeed())
|
||||
{
|
||||
m_state |= OPP_FRONT_FAST;
|
||||
if(is_quicker_teammate(mycar))
|
||||
if(isQuickerTeammate(mycar))
|
||||
m_state |= OPP_FRONT_FOLLOW;
|
||||
m_distance -= SIDECOLLDIST;
|
||||
if (m_distance < 20.0 - (getSpeed() - driver->getSpeed()) * 4)
|
||||
|
@ -177,17 +177,17 @@ Opponent::getDistToSegStart() const
|
|||
void
|
||||
Opponent::updateOverlapTimer(tSituation * const s, tCarElt * const mycar)
|
||||
{
|
||||
if((m_car->race.laps > mycar->race.laps) || is_quicker_teammate(mycar))
|
||||
if((m_car->race.laps > mycar->race.laps) || isQuickerTeammate(mycar))
|
||||
{
|
||||
if(is_state(OPP_BACK | OPP_SIDE))
|
||||
if(isState(OPP_BACK | OPP_SIDE))
|
||||
m_overlaptimer += s->deltaTime;
|
||||
else if(is_state(OPP_FRONT))
|
||||
else if(isState(OPP_FRONT))
|
||||
m_overlaptimer = LAP_BACK_TIME_PENALTY;
|
||||
else
|
||||
{
|
||||
if(m_overlaptimer > 0.0)
|
||||
{
|
||||
if(is_state(OPP_FRONT_FAST))
|
||||
if(isState(OPP_FRONT_FAST))
|
||||
m_overlaptimer = MIN(0.0, m_overlaptimer);
|
||||
else
|
||||
m_overlaptimer -= s->deltaTime;
|
||||
|
@ -202,8 +202,6 @@ Opponent::updateOverlapTimer(tSituation * const s, tCarElt * const mycar)
|
|||
|
||||
|
||||
/**
|
||||
* is_quicker_teammate
|
||||
*
|
||||
* Returns true, if the other car is our teammate
|
||||
* and has significantly less damage
|
||||
* (defined in Driver::TEAM_DAMAGE_CHANGE_LEAD)
|
||||
|
@ -212,11 +210,11 @@ Opponent::updateOverlapTimer(tSituation * const s, tCarElt * const mycar)
|
|||
* @return true, if the opponent is our teammate
|
||||
*/
|
||||
bool
|
||||
Opponent::is_quicker_teammate(tCarElt * const mycar)
|
||||
Opponent::isQuickerTeammate(tCarElt * const mycar)
|
||||
{
|
||||
return (is_teammate()
|
||||
return (isTeammate()
|
||||
&& (mycar->_dammage - m_car->_dammage > Driver::TEAM_DAMAGE_CHANGE_LEAD));
|
||||
}//is_quicker_teammate
|
||||
}//isQuickerTeammate
|
||||
|
||||
|
||||
/**
|
||||
|
@ -291,45 +289,21 @@ Opponents::setTeamMate(const tCarElt *car)
|
|||
}//setTeamMate
|
||||
|
||||
|
||||
#if 0
|
||||
void
|
||||
TeamTacticsMatrix(tCarElt *car_A, tCarElt *car_B, int *order_A, int *order_B)
|
||||
/**
|
||||
* Searches the first opponent with the given state.
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
tCarElt *car_front;
|
||||
tCarElt *car_behind;
|
||||
|
||||
//Decide which car is ahead
|
||||
if(car_A->_distRaced >= car_B->_distRaced)
|
||||
{
|
||||
car_front = car_A;
|
||||
car_behind = car_B;
|
||||
}
|
||||
else
|
||||
{
|
||||
car_front = car_B;
|
||||
car_behind = car_A;
|
||||
}
|
||||
|
||||
//For easier handling, f_: front, b_: behind
|
||||
int f_laps = car_front->_laps;
|
||||
int b_laps = car_behind->_laps;
|
||||
int f_damage = car_front->_dammage;
|
||||
int b_damage = car_behind->_dammage;
|
||||
|
||||
|
||||
if(b_laps > f_laps) //Case 1,2,3
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if(b_laps == f_laps) //Case 4,5,6
|
||||
{
|
||||
}
|
||||
else //Case 7,8,9
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Opponent *ret = NULL;
|
||||
for(list<Opponent>::iterator it = begin(); it != end(); it++) {
|
||||
if(it->isState(state)) {
|
||||
ret = &(*it);
|
||||
break;
|
||||
}
|
||||
}//for it
|
||||
return ret;
|
||||
}//getOppByState
|
||||
|
|
|
@ -59,9 +59,11 @@ public:
|
|||
double getSpeed() const {return m_cardata->getSpeedInTrackDirection();}
|
||||
int getIndex() const {return m_index;}
|
||||
|
||||
inline bool is_state(const int state) const {return bool(m_state & state);}
|
||||
inline bool is_teammate() const {return m_teammate;}
|
||||
bool is_quicker_teammate(tCarElt * const mycar);
|
||||
inline bool isState(const int state) const {return 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;}
|
||||
|
||||
inline void markAsTeamMate() {m_teammate = true;}
|
||||
void update(tSituation *s, Driver *driver);
|
||||
|
@ -107,6 +109,8 @@ public:
|
|||
|
||||
void update(tSituation *s, Driver *driver);
|
||||
void setTeamMate(const tCarElt *car);
|
||||
Opponent *getOppByState(const int state);
|
||||
|
||||
inline list<Opponent>::iterator begin() {return m_opps->begin();}
|
||||
inline list<Opponent>::iterator end() {return m_opps->end();}
|
||||
|
||||
|
|
|
@ -33,91 +33,78 @@ const double
|
|||
|
||||
Pit::Pit(const tSituation * s, Driver * driver, const double pitoffset)
|
||||
{
|
||||
track = driver->getTrackPtr();
|
||||
car = driver->getCarPtr();
|
||||
mypit = driver->getCarPtr()->_pit;
|
||||
pitinfo = &track->pits;
|
||||
pitstop = inpitlane = false;
|
||||
pittimer = 0.0;
|
||||
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;
|
||||
|
||||
if(mypit != NULL)
|
||||
{
|
||||
speedlimit = pitinfo->speedLimit - SPEED_LIMIT_MARGIN;
|
||||
speedlimitsqr = speedlimit * speedlimit;
|
||||
pitspeedlimitsqr = pitinfo->speedLimit * pitinfo->speedLimit;
|
||||
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);
|
||||
|
||||
// Compute pit spline points along the track.
|
||||
p[3].x = mypit->pos.seg->lgfromstart + mypit->pos.toStart;
|
||||
p[2].x = p[3].x - pitinfo->len;
|
||||
p[4].x = p[3].x + pitinfo->len;
|
||||
p[0].x = pitinfo->pitEntry->lgfromstart + pitoffset;
|
||||
p[1].x = pitinfo->pitStart->lgfromstart;
|
||||
p[5].x = pitinfo->pitStart->lgfromstart + pitinfo->nMaxPits * pitinfo->len;
|
||||
p[6].x = pitinfo->pitExit->lgfromstart;
|
||||
// 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;
|
||||
m_p[5].x = m_pitinfo->pitStart->lgfromstart + m_pitinfo->nMaxPits * m_pitinfo->len;
|
||||
m_p[6].x = m_pitinfo->pitExit->lgfromstart;
|
||||
|
||||
pitentry = p[0].x;
|
||||
pitexit = p[6].x;
|
||||
m_pitentry = m_p[0].x;
|
||||
m_pitexit = m_p[6].x;
|
||||
|
||||
// Normalizing spline segments to >= 0.0.
|
||||
for(int i = 0; i < NPOINTS; i++)
|
||||
{
|
||||
p[i].s = 0.0;
|
||||
p[i].x = toSplineCoord(p[i].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);
|
||||
}//for i
|
||||
|
||||
// Fix broken pit exit.
|
||||
if(p[6].x < p[5].x)
|
||||
{
|
||||
//printf("bt: Pitexit broken on track %s.\n", track->name);
|
||||
p[6].x = p[5].x + 50.0;
|
||||
}
|
||||
// Fix broken pit exit.
|
||||
if(m_p[6].x < m_p[5].x)
|
||||
m_p[6].x = m_p[5].x + 50.0;
|
||||
|
||||
// Fix point for first pit if necessary.
|
||||
if(p[1].x > p[2].x)
|
||||
{
|
||||
p[1].x = p[2].x;
|
||||
}
|
||||
// Fix point for first pit if necessary.
|
||||
if(m_p[1].x > m_p[2].x)
|
||||
m_p[1].x = m_p[2].x;
|
||||
|
||||
// Fix point for last pit if necessary.
|
||||
if(p[4].x > p[5].x)
|
||||
{
|
||||
p[5].x = p[4].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;
|
||||
|
||||
double sign = (pitinfo->side == TR_LFT) ? 1.0 : -1.0;
|
||||
p[0].y = 0.0;
|
||||
p[6].y = 0.0;
|
||||
for(int i = 1; i < NPOINTS - 1; i++)
|
||||
{
|
||||
p[i].y = fabs(pitinfo->driversPits->pos.toMiddle) - pitinfo->width;
|
||||
p[i].y *= sign;
|
||||
}
|
||||
double sign = (m_pitinfo->side == TR_LFT) ? 1.0 : -1.0;
|
||||
m_p[0].y = 0.0;
|
||||
m_p[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;
|
||||
}//for i
|
||||
|
||||
p[3].y = fabs(pitinfo->driversPits->pos.toMiddle + 1.0) * sign;
|
||||
spline = new Spline(NPOINTS, p);
|
||||
}
|
||||
}
|
||||
m_p[3].y = fabs(m_pitinfo->driversPits->pos.toMiddle + 1.0) * sign;
|
||||
m_spline = new Spline(NPOINTS, m_p);
|
||||
}//if pit not null
|
||||
}//Pit::Pit
|
||||
|
||||
|
||||
Pit::~Pit()
|
||||
{
|
||||
if(mypit != NULL)
|
||||
{
|
||||
delete spline;
|
||||
}
|
||||
}
|
||||
if(m_mypit != NULL)
|
||||
delete m_spline;
|
||||
}//Pit::~Pit
|
||||
|
||||
|
||||
// Transforms track coordinates to spline parameter coordinates.
|
||||
double
|
||||
Pit::toSplineCoord(double x) const
|
||||
Pit::toSplineCoord(const double x) const
|
||||
{
|
||||
x -= pitentry;
|
||||
while(x < 0.0)
|
||||
{
|
||||
x += track->length;
|
||||
}
|
||||
return x;
|
||||
double ret = x - m_pitentry;
|
||||
while(ret < 0.0)
|
||||
ret += m_track->length;
|
||||
|
||||
return ret;
|
||||
}//toSplineCoord
|
||||
|
||||
|
||||
|
@ -125,69 +112,51 @@ Pit::toSplineCoord(double x) const
|
|||
double
|
||||
Pit::getPitOffset(const double offset, double fromstart)
|
||||
{
|
||||
if(mypit != NULL)
|
||||
{
|
||||
if(getInPit() || (getPitstop() && isBetween(fromstart)))
|
||||
{
|
||||
fromstart = toSplineCoord(fromstart);
|
||||
return spline->evaluate(fromstart);
|
||||
}
|
||||
if(m_mypit != NULL) {
|
||||
if(getInPit() || (getPitstop() && isBetween(fromstart))) {
|
||||
fromstart = toSplineCoord(fromstart);
|
||||
return m_spline->evaluate(fromstart);
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
}//getPitOffset
|
||||
|
||||
|
||||
// Sets the pitstop flag if we are not in the pit range.
|
||||
void
|
||||
Pit::setPitstop(bool pitstop)
|
||||
{
|
||||
if(mypit != NULL)
|
||||
{
|
||||
double fromstart = car->_distFromStartLine;
|
||||
if(m_mypit != NULL) {
|
||||
double fromstart = m_car->_distFromStartLine;
|
||||
|
||||
if(!isBetween(fromstart))
|
||||
{
|
||||
this->pitstop = pitstop;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!pitstop)
|
||||
{
|
||||
this->pitstop = pitstop;
|
||||
pittimer = 0.0;
|
||||
}
|
||||
}
|
||||
if(!isBetween(fromstart)) {
|
||||
m_pitstop = pitstop;
|
||||
} else {
|
||||
if(!pitstop) {
|
||||
m_pitstop = pitstop;
|
||||
m_pittimer = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}//setPitstop
|
||||
|
||||
|
||||
// Check if the argument fromstart is in the range of the pit.
|
||||
bool
|
||||
Pit::isBetween(const double fromstart) const
|
||||
{
|
||||
if(pitentry <= pitexit)
|
||||
{
|
||||
if(fromstart >= pitentry && fromstart <= pitexit)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Warning: TORCS reports sometimes negative values for "fromstart"!
|
||||
if(fromstart <= pitexit || fromstart >= pitentry)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool ret = false;
|
||||
|
||||
if(m_pitentry <= m_pitexit) {
|
||||
if(fromstart >= m_pitentry && fromstart <= m_pitexit)
|
||||
ret = true;
|
||||
} else {
|
||||
// Warning: TORCS reports sometimes negative values for "fromstart"!
|
||||
if(fromstart <= m_pitexit || fromstart >= m_pitentry)
|
||||
ret = true;
|
||||
}//if pitentry <= pitexit
|
||||
|
||||
return ret;
|
||||
}//isBetween
|
||||
|
||||
|
||||
|
@ -197,24 +166,19 @@ Pit::isBetween(const double fromstart) const
|
|||
bool
|
||||
Pit::isTimeout(const double distance)
|
||||
{
|
||||
if(car->_speed_x > 1.0 || distance > 3.0 || !getPitstop())
|
||||
{
|
||||
pittimer = 0.0;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pittimer += RCM_MAX_DT_ROBOTS;
|
||||
if(pittimer > 3.0)
|
||||
{
|
||||
pittimer = 0.0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool ret = false;
|
||||
|
||||
if(m_car->_speed_x > 1.0 || distance > 3.0 || !getPitstop()) {
|
||||
m_pittimer = 0.0;
|
||||
} else {
|
||||
m_pittimer += RCM_MAX_DT_ROBOTS;
|
||||
if(m_pittimer > 3.0) {
|
||||
m_pittimer = 0.0;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}//isTimeout
|
||||
|
||||
|
||||
|
@ -222,23 +186,15 @@ Pit::isTimeout(const double distance)
|
|||
void
|
||||
Pit::update()
|
||||
{
|
||||
if(mypit != NULL)
|
||||
{
|
||||
if(isBetween(car->_distFromStartLine))
|
||||
{
|
||||
if(getPitstop())
|
||||
{
|
||||
setInPit(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setInPit(false);
|
||||
}
|
||||
|
||||
if(m_mypit != NULL) {
|
||||
if(isBetween(m_car->_distFromStartLine)) {
|
||||
if(getPitstop())
|
||||
{
|
||||
car->_raceCmd = RM_CMD_PIT_ASKED;
|
||||
}
|
||||
setInPit(true);
|
||||
} else {
|
||||
setInPit(false);
|
||||
}
|
||||
|
||||
if(getPitstop())
|
||||
m_car->_raceCmd = RM_CMD_PIT_ASKED;
|
||||
}
|
||||
}//update
|
||||
|
|
|
@ -39,50 +39,51 @@ public:
|
|||
~Pit();
|
||||
|
||||
void setPitstop(const bool pitstop);
|
||||
inline bool getPitstop() const {return pitstop;}
|
||||
inline void setInPit(const bool inpitlane) {this->inpitlane = inpitlane;}
|
||||
inline bool getInPit() const {return inpitlane;}
|
||||
inline bool getPitstop() const {return m_pitstop;}
|
||||
inline void setInPit(const bool inpitlane) {m_inpitlane = inpitlane;}
|
||||
inline bool getInPit() const {return m_inpitlane;}
|
||||
|
||||
double getPitOffset(const double offset, double fromstart);
|
||||
|
||||
bool isBetween(const double fromstart) const;
|
||||
bool isTimeout(const double distance);
|
||||
|
||||
inline double getNPitStart() const {return p[1].x;}
|
||||
inline double getNPitLoc() const {return p[3].x;}
|
||||
inline double getNPitEnd() const {return p[5].x;}
|
||||
inline double getNPitEntry() const {return p[0].x;}
|
||||
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 speedlimitsqr;}
|
||||
inline double getSpeedlimit() const {return speedlimit;}
|
||||
inline double getSpeedlimitSqr() const {return m_speedlimitsqr;}
|
||||
inline double getSpeedlimit() const {return m_speedlimit;}
|
||||
inline double getSpeedLimitBrake(const double speedsqr) const
|
||||
{return (speedsqr - speedlimitsqr) / (pitspeedlimitsqr - speedlimitsqr);}
|
||||
{return (speedsqr - m_speedlimitsqr)
|
||||
/ (m_pitspeedlimitsqr - m_speedlimitsqr);}
|
||||
|
||||
void update();
|
||||
|
||||
private:
|
||||
tTrack * track;
|
||||
tCarElt *car;
|
||||
tTrackOwnPit *mypit; // Pointer to my pit.
|
||||
tTrackPitInfo *pitinfo; // General pit info.
|
||||
tTrack *m_track;
|
||||
tCarElt *m_car;
|
||||
tTrackOwnPit *m_mypit; // Pointer to my pit.
|
||||
tTrackPitInfo *m_pitinfo; // General pit info.
|
||||
|
||||
enum
|
||||
{ NPOINTS = 7 };
|
||||
SplinePoint p[NPOINTS]; // Spline points.
|
||||
Spline *spline; // Spline.
|
||||
SplinePoint m_p[NPOINTS]; // Spline points.
|
||||
Spline *m_spline; // Spline.
|
||||
|
||||
bool pitstop; // Pitstop planned.
|
||||
bool inpitlane; // We are still in the pit lane.
|
||||
double pitentry; // Distance to start line of the pit entry.
|
||||
double pitexit; // Distance to the start line of the pit exit.
|
||||
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.
|
||||
|
||||
double speedlimitsqr; // Pit speed limit squared.
|
||||
double speedlimit; // Pit speed limit.
|
||||
double pitspeedlimitsqr; // The original speedlimit squared.
|
||||
double m_speedlimitsqr; // Pit speed limit squared.
|
||||
double m_speedlimit; // Pit speed limit.
|
||||
double m_pitspeedlimitsqr; // The original speedlimit squared.
|
||||
|
||||
double pittimer; // Timer for pit timeouts.
|
||||
double m_pittimer; // Timer for pit timeouts.
|
||||
|
||||
static const double SPEED_LIMIT_MARGIN;
|
||||
};
|
||||
|
|
|
@ -498,7 +498,7 @@ LRaceLine::InitTrack(const tTrack * const track, void **carParmHandle, const tSi
|
|||
(char *) NULL, 2.0);
|
||||
m_dBrakeDelay = GfParmGetNum(*carParmHandle, BT_SECT_PRIV, "BrakeDelay",
|
||||
(char *) NULL, 10.0);
|
||||
m_dSecurityRadius = GfParmGetNum(*carParmHandle, BT_SECT_PRIV, BT_ATT_SECRADIUS,
|
||||
m_dSecurityRadius = GfParmGetNum(*carParmHandle, BT_SECT_PRIV, "securityradius",
|
||||
(char *) NULL, 100.0);
|
||||
|
||||
// split track
|
||||
|
|
Loading…
Reference in a new issue