- Update Shadow's driver

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@6807 30fe4595-0a0c-4342-8851-515496e4dcbd

Former-commit-id: b87e36785eae588746234881369ecd4c266efb91
Former-commit-id: f352314d14eb3eb79e9c3fb69ebfcd5b33e7da16
This commit is contained in:
torcs-ng 2020-01-12 19:50:17 +00:00
parent 0ebd6b6a12
commit 5b3c1bc9c7
10 changed files with 2103 additions and 27 deletions

View file

@ -11,6 +11,8 @@ SET(ROBOT_SOURCES src/Array.h
src/AveragedData.h
src/Avoidance.cpp
src/Avoidance.h
src/CarBounds2d.cpp
src/CarBounds2d.h
src/CarModel.cpp
src/CarModel.h
src/ClothoidPath.cpp
@ -58,6 +60,8 @@ SET(ROBOT_SOURCES src/Array.h
src/Span.h
src/Strategy.cpp
src/Strategy.h
src/Stuck.cpp
src/Stuck.h
src/TeamInfo.cpp
src/TeamInfo.h
src/Utils.cpp

View file

@ -0,0 +1,242 @@
#include "CarBounds2d.h"
#include "Utils.h"
using namespace std;
static const int s_next_corner[] = {FRNT_LFT, REAR_LFT, REAR_RGT, FRNT_RGT};
CarBounds2d::CarBounds2d( const tCarElt* car )
{
/*
xAxis = Vec2d(car->pub.DynGC.pos.az);
yAxis = xAxis.GetNormal();
Vec2d middle(car->pub.DynGC.pos.x, car->pub.DynGC.pos.y);
pts[FRNT_LFT] = middle + xAxis * car->pub.corner[FRNT_LFT].x + yAxis * car->pub.corner[FRNT_LFT].y;
pts[FRNT_RGT] = middle + xAxis * car->pub.corner[FRNT_RGT].x + yAxis * car->pub.corner[FRNT_RGT].y;
pts[REAR_LFT] = middle + xAxis * car->pub.corner[REAR_LFT].x + yAxis * car->pub.corner[REAR_LFT].y;
pts[REAR_RGT] = middle + xAxis * car->pub.corner[REAR_RGT].x + yAxis * car->pub.corner[REAR_RGT].y;
*/
pts[FRNT_LFT] = Vec2d(car->pub.corner[FRNT_LFT].ax, car->pub.corner[FRNT_LFT].ay);
pts[FRNT_RGT] = Vec2d(car->pub.corner[FRNT_RGT].ax, car->pub.corner[FRNT_RGT].ay);
pts[REAR_LFT] = Vec2d(car->pub.corner[REAR_LFT].ax, car->pub.corner[REAR_LFT].ay);
pts[REAR_RGT] = Vec2d(car->pub.corner[REAR_RGT].ax, car->pub.corner[REAR_RGT].ay);
xAxis = Vec2d(pts[FRNT_LFT] - pts[REAR_LFT]).GetUnit();
yAxis = Vec2d(pts[FRNT_LFT] - pts[FRNT_RGT]).GetUnit();
}
double CarBounds2d::distToSide( int side, double maxDist, const CarBounds2d& other ) const
{
vector<Vec2d> pts;
pts.push_back( other.pts[FRNT_RGT] );
pts.push_back( other.pts[FRNT_LFT] );
pts.push_back( other.pts[REAR_LFT] );
pts.push_back( other.pts[REAR_RGT] );
pts.push_back( other.pts[FRNT_RGT] );
return distToSide(side, maxDist, pts);
}
double CarBounds2d::distToSide( int side, double maxDist, const vector<Vec2d>& pts ) const
{
CarBounds2d temp(*this);
Vec2d midPt;
double midLen = 0;
switch( side )
{
case SIDE_FRONT:
temp.pts[REAR_LFT] = temp.pts[FRNT_LFT];
temp.pts[REAR_RGT] = temp.pts[FRNT_RGT];
midPt = (temp.pts[FRNT_LFT] + temp.pts[FRNT_RGT]) * 0.5;
midLen = temp.pts[FRNT_LFT].dist(temp.pts[FRNT_RGT]);
break;
case SIDE_REAR:
temp.pts[FRNT_LFT] = temp.pts[REAR_LFT];
temp.pts[FRNT_RGT] = temp.pts[REAR_RGT];
midPt = (temp.pts[REAR_LFT] + temp.pts[REAR_RGT]) * 0.5;
midLen = temp.pts[REAR_LFT].dist(temp.pts[REAR_RGT]);
break;
case SIDE_LEFT:
temp.pts[FRNT_RGT] = temp.pts[FRNT_LFT];
temp.pts[REAR_RGT] = temp.pts[REAR_LFT];
midPt = (temp.pts[FRNT_LFT] + temp.pts[REAR_LFT]) * 0.5;
midLen = temp.pts[FRNT_LFT].dist(temp.pts[REAR_LFT]);
break;
case SIDE_RIGHT:
temp.pts[FRNT_LFT] = temp.pts[FRNT_RGT];
temp.pts[REAR_LFT] = temp.pts[REAR_RGT];
midPt = (temp.pts[FRNT_RGT] + temp.pts[REAR_RGT]) * 0.5;
midLen = temp.pts[FRNT_RGT].dist(temp.pts[REAR_RGT]);
break;
}
double filterDistSq = (midLen + maxDist) * (midLen + maxDist);
if( temp.collidesWith(pts, midPt, filterDistSq) )
return 0;
temp.inflateSide( side, maxDist );
if( !temp.collidesWith(pts, midPt, filterDistSq) )
return maxDist;
double incr = maxDist * 0.5;
double dist = maxDist - incr;
temp.inflateSide( side, -incr );
while( incr > 0.01 )
{
if( temp.collidesWith(pts, midPt, filterDistSq) )
{
incr *= 0.5;
dist -= incr;
temp.inflateSide( side, -incr );
}
else
{
incr *= 0.5;
dist += incr;
temp.inflateSide( side, incr );
}
}
if( !temp.collidesWith(pts, midPt, filterDistSq) )
dist -= incr;
return dist;
}
void CarBounds2d::inflateSide( int side, double delta )
{
switch( side )
{
case SIDE_FRONT:
pts[FRNT_LFT] += xAxis * delta;
pts[FRNT_RGT] += xAxis * delta;
break;
case SIDE_REAR:
pts[REAR_LFT] -= xAxis * delta;
pts[REAR_RGT] -= xAxis * delta;
break;
case SIDE_LEFT:
pts[FRNT_LFT] += yAxis * delta;
pts[REAR_LFT] += yAxis * delta;
break;
case SIDE_RIGHT:
pts[FRNT_RGT] -= yAxis * delta;
pts[REAR_RGT] -= yAxis * delta;
break;
}
}
void CarBounds2d::inflate( double deltaX, double deltaY )
{
inflate( deltaX, deltaX, deltaY, deltaY );
}
void CarBounds2d::inflate( double deltaFront, double deltaRear, double deltaLeft, double deltaRight )
{
pts[FRNT_LFT] += xAxis * deltaFront + yAxis * deltaLeft;
pts[REAR_LFT] += -xAxis * deltaRear + yAxis * deltaLeft;
pts[REAR_RGT] += -xAxis * deltaRear - yAxis * deltaRight;
pts[FRNT_RGT] += xAxis * deltaFront - yAxis * deltaRight;
}
bool CarBounds2d::contains( const Vec2d& pt ) const
{
for( int i = 0; i < 4; i++ )
{
if( Vec2d(pts[s_next_corner[i]] - pts[i]).GetNormal() * (pt - pts[i]) > 0 )
return false;
}
return true;
}
bool CarBounds2d::collidesWith( const CarBounds2d& other ) const
{
// test for points contained.
for( int i = 0; i < 4; i++ )
{
if( contains(other.pts[i]) || other.contains(pts[i]) )
return true;
}
// test the edges crossing too.
double t1, t2;
for( int i = 0; i < 4; i++ )
{
Vec2d v = pts[s_next_corner[i]] - pts[i];
for( int j = 0; j < 4; j++ )
{
Vec2d ov = other.pts[s_next_corner[j]] - other.pts[j];
if( Utils::LineCrossesLine(pts[i], v, other.pts[j], ov, t1, t2) )
{
if( t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1 )
return true;
}
}
}
return false;
}
bool CarBounds2d::collidesWith( const Vec2d& pt1, const Vec2d& pt2 ) const
{
double t1, t2;
Vec2d lv = pt2 - pt1;
for( int i = 0; i < 4; i++ )
{
Vec2d v = pts[s_next_corner[i]] - pts[i];
if( Utils::LineCrossesLine(pts[i], v, pt1, lv, t1, t2) )
{
if( t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1 )
return true;
}
}
return false;
}
bool CarBounds2d::collidesWith( const std::vector<Vec2d>& otherPts, const Vec2d& filterPt, double filterDistSqLimit ) const
{
if( otherPts.empty() )
return false;
bool lastIsOk = filterDistSqLimit < 0 || otherPts[0].DistSq(filterPt) <= filterDistSqLimit;
double t1, t2;
for( int i = 1; i < (int)otherPts.size(); i++ )
{
bool currIsOk = filterDistSqLimit < 0 || otherPts[i].DistSq(filterPt) <= filterDistSqLimit;
if( lastIsOk && currIsOk )
{
Vec2d otherV = otherPts[i] - otherPts[i - 1];
for( int j = 0; j < 4; j++ )
{
Vec2d v = pts[s_next_corner[j]] - pts[j];
if( Utils::LineCrossesLine(otherPts[i - 1], otherV, pts[j], v, t1, t2) )
{
if( t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1 )
return true;
}
}
}
lastIsOk = currIsOk;
}
return false;
}

View file

@ -0,0 +1,45 @@
#ifndef MOUSE_CAR_BOUNDARY_2D_
#define MOUSE_CAR_BOUNDARY_2D_
#include "car.h"
#include "Vec2d.h"
#include <vector>
// The "SHADOW" logger instance.
extern GfLogger* PLogSHADOW;
#define LogSHADOW (*PLogSHADOW)
class CarBounds2d
{
Vec2d pts[4];
Vec2d xAxis; // direction that is forwards.
Vec2d yAxis; // direction this is to the right.
public:
enum
{
SIDE_FRONT,
SIDE_REAR,
SIDE_LEFT,
SIDE_RIGHT,
};
public:
CarBounds2d( const tCarElt* car );
const Vec2d& operator[]( int index ) const { return pts[index]; }
double distToSide( int side, double maxDist, const CarBounds2d& other ) const;
double distToSide( int side, double maxDist, const std::vector<Vec2d>& pts ) const;
void inflateSide( int sideX, double delta );
void inflate( double deltaX, double deltaY );
void inflate( double deltaX1, double deltaX2, double deltaY1, double deltaY2 );
bool contains( const Vec2d& pt ) const;
bool collidesWith( const CarBounds2d& other ) const;
bool collidesWith( const Vec2d& pt1, const Vec2d& pt2 ) const;
bool collidesWith( const std::vector<Vec2d>& pts, const Vec2d& filterPt, double filterDistSqLimit = -1 ) const;
};
#endif // MOUSE_CAR_BOUNDARY_2D_

View file

@ -770,10 +770,23 @@ void TDriver::NewRace( tCarElt* pCar, tSituation* pS )
LogSHADOW.debug("End Shadow NewRace\n");
}
bool TDriver::Pitting(int path, double pos) const
{
return m_Strategy->needPitstop(car, m_Situation) &&
m_pitPath[path].ContainsPos(pos);
}
bool TDriver::Pitting(tCarElt* car) const
{
double pos = m_track.CalcPos(car);
return Pitting(PATH_NORMAL, pos);
}
void TDriver::GetPtInfo( int path, double pos, PtInfo& pi ) const
{
if( m_Strategy->needPitstop(car, m_Situation) && m_pitPath[path].ContainsPos(pos) )
if(m_Strategy->needPitstop(car, m_Situation) && m_pitPath[path].ContainsPos(pos) )
m_pitPath[path].GetPtInfo( pos, pi );
else
m_path[path].GetPtInfo( pos, pi );
@ -1858,6 +1871,19 @@ void TDriver::Drive( tSituation* s )
m_LastAccel = acc;
m_LastAbsDriftAngle = m_AbsDriftAngle;
const Opponent::Sit& mySit = m_opp[car->index].GetInfo().sit;
m_stuck = NOT_STUCK;
bool doStuckThing = true;
if (Pitting(car))
{
doStuckThing = false;
}
if (doStuckThing)
m_stuckThing.execute(m_track, s, car, mySit);
m_Strategy->update(car, s);
//m_Strategy->needPitstop(car, m_Situation);

View file

@ -39,6 +39,7 @@
#include "LinePath.h"
#include "PtInfo.h"
#include "Strategy.h"
#include "Stuck.h"
#include "teammanager.h"
#define SECT_PRIV "private"
@ -189,6 +190,13 @@ public:
void InitTrack(tTrack* track, void* carHandle, void** carParmHandle, tSituation* s);
void NewRace(tCarElt* car, tSituation* s );
void Drive(tSituation* s);
int PitCmd(tSituation* s);
void EndRace(tSituation* s);
void Shutdown();
bool Pitting(int path, double pos) const;
bool Pitting(tCarElt* car) const;
void GetPtInfo( int path, double pos, PtInfo& pi ) const;
void GetPosInfo( double pos, PtInfo& pi, double u, double v ) const;
@ -232,11 +240,6 @@ public:
void SpeedControl6(double targetSpd, double spd0, CarElt* car, double& acc, double& brk );
void SpeedControl( int which, double targetSpd, double spd0, CarElt* car, double& acc, double& brk );
void Drive(tSituation* s );
int PitCmd(tSituation* s );
void EndRace(tSituation* s );
void Shutdown();
double CurrSimTime; // Current simulation time
double Frc; // Friction coefficient
//bool UseBrakeLimit; // Enable/disable brakelimit
@ -358,6 +361,11 @@ private:
MAX_OPP = 100
};
enum StuckAction
{
NOT_STUCK, STUCK_GO_BACKWARDS, STUCK_GO_FORWARDS,
};
private:
MyTrack m_track;
OptimisedPath m_path[N_PATHS];
@ -481,19 +489,21 @@ private:
double m_JumpOffset; // Offset for calculation of jumps
bool m_FirstJump;
int m_Flying; // Flag prepare landing
int m_nCars;
int m_myOppIdx;
Opponent *m_opp; // info about other cars.
double m_avgAY;
bool m_raceStart;
double m_avoidS; // where we are LR->T (0..1).
double m_avoidSVel;
double m_avoidT; // where we are L->R (-1..1).
double m_avoidTVel;
double m_avoidU;
double m_avoidV;
double m_attractor; // where we want to be.
int m_followPath; // path we want to follow;
int m_nCars;
int m_myOppIdx;
Opponent *m_opp; // info about other cars.
double m_avgAY;
bool m_raceStart;
double m_avoidS; // where we are LR->T (0..1).
double m_avoidSVel;
double m_avoidT; // where we are L->R (-1..1).
double m_avoidTVel;
double m_avoidU;
double m_avoidV;
double m_attractor; // where we want to be.
int m_followPath; // path we want to follow;
Stuck m_stuckThing;
StuckAction m_stuck;
LinearRegression m_accBrkCoeff; //
double m_brkCoeff[50];

View file

@ -32,6 +32,8 @@ public:
double oang; // global angle.
double toL; // distance to edge of track on left.
double toR; // distance to edge of track on right.
double extL;
double extR;
double k; // curvature at point.
double kz; // curvature in z at point
double spd; // speed.

View file

@ -47,9 +47,11 @@ SimpleStrategy::SimpleStrategy()
fuelPerLap = 0.0f; // [Kg] The maximum amount of fuel we needed for a lap.
lastPitFuel = 0.0f; // [Kg] Amount refueled, special case when we refuel.
fuelSum = 0.0f; // [Kg] All the fuel used.
fuelSumPerMeter = 0.0;
counterFuelLaps = 0; // [-] Counter of the total laps.
countPitStop = 0; // [-] Counter of the total pitStop.
avgFuelPerLap = 0.0; // [Kg] Average fuel per lap.
avgFuelPerMeter = 0.0;
m_maxDamage = 0; // [-] max damage before we request a pit stop.
m_Fuel = 0; // [Kg] Security fuel at the strat race.
m_expectedfuelperlap = 0; // [Kg] Expected fuel per lap
@ -78,7 +80,7 @@ void SimpleStrategy::setFuelAtRaceStart(tTrack* t, void **carParmHandle, tSituat
maxFuel = (tdble)(GfParmGetNum(*carParmHandle, SECT_CAR, PRM_TANK, (char*)NULL, (tdble) MAX_FUEL_TANK));
LogSHADOW.info("Strategy max fuel = %.2f\n", maxFuel);
FuelperMeters = GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_FUELPERMETERS, (char*)NULL, (tdble) MAX_FUEL_PER_METER);
LogSHADOW.info("Strategy fuel per meters = %.5f\n", FuelperMeters);
LogSHADOW.info("Strategy fuel per meters = %.7f\n", FuelperMeters);
fuelPerLap = (tdble) (TrackLength * FuelperMeters);
LogSHADOW.info("Strategy fuel per lap = %.2f\n", fuelPerLap);
fullfuel = GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_FULL_FUEL, (char*)NULL, 0.0);
@ -161,14 +163,14 @@ void SimpleStrategy::setFuelAtRaceStart(tTrack* t, void **carParmHandle, tSituat
m_fuel = 0;
//m_FuelStart = ((raceLaps / 2) * fuelPerLap) + 0.3;
m_FuelStart = (tdble)(1.92 * fuelPerLap);
fprintf(stderr,"...Check PitStop Enabled!\n");
LogSHADOW.info("...Check PitStop Enabled!\n");
//maybe we need to check Best Lap Time for qualifying
} else if (test_qualifTime && s->_raceType == RM_TYPE_PRACTICE)
{
qualifRace = true;
m_fuel = 0;
m_FuelStart = s->_totLaps * fuelPerLap;
fprintf(stderr,"...Check QualifTime Enabled!\n");
LogSHADOW.info("...Check QualifTime Enabled!\n");
}
if (m_FuelStart > maxFuel)
@ -185,7 +187,7 @@ void SimpleStrategy::setFuelAtRaceStart(tTrack* t, void **carParmHandle, tSituat
m_FuelStart = (tdble)(MIN(m_FuelStart, maxFuel));
fprintf(stderr,"# SHADOW Index %d : Laps = %d, Fuel per Lap = %.2f, securityFuel = + %.2f, Fuel at Start Race = %.2f\n",
LogSHADOW.debug("# SHADOW Index %d : Laps = %d, Fuel per Lap = %.2f, securityFuel = + %.2f, Fuel at Start Race = %.2f\n",
index, s->_totLaps, fuelPerLap, m_fuel, m_FuelStart);
GfParmSetNum(*carParmHandle, SECT_CAR, PRM_FUEL, (char*)NULL, m_FuelStart);
@ -203,9 +205,14 @@ void SimpleStrategy::update(tCarElt* car, tSituation *s)
{
//fuelPerLap = MAX(fuelPerLap, (lastFuel + lastPitFuel - car->priv.fuel));
fuelSum += (lastFuel + lastPitFuel - car->priv.fuel);
fuelSumPerMeter += (lastFuel - car->_fuel);
fuelPerLap = (fuelSum/(car->race.laps - 1));
counterFuelLaps++;
avgFuelPerLap = fuelSum / counterFuelLaps;
avgFuelPerMeter = fuelSumPerMeter / car->_distRaced;
LogSHADOW.info(" # Fuel per meter = %.7f\n", avgFuelPerMeter);
if (strategy_verbose)
{
@ -290,7 +297,7 @@ bool SimpleStrategy::needPitstop(tCarElt* car, tSituation *s)
{
if (!m_checkFuel)
{
LogSHADOW.debug("%s Go to Pit the next lap to refuel: reqFuel= %.2f, carFuel= %.2f, remLap= %d\n",
LogSHADOW.info("%s Go to Pit the next lap to refuel: reqFuel= %.2f, carFuel= %.2f, remLap= %d\n",
car->_name, reqfuel, car->_fuel, car->_remainingLaps);
m_checkFuel = true;
}
@ -407,7 +414,8 @@ float SimpleStrategy::pitRefuel(tCarElt* car, tSituation *s)
{
LogSHADOW.debug(">> [PitStrat 2] ");
}
LogSHADOW.debug(" %s in Pit to refuel < PitStop %d >\n", car->_name, countPitStop);
LogSHADOW.info(" %s in Pit to refuel < PitStop %d >\n", car->_name, countPitStop);
m_fuelperstint = (tdble)((fuelToEnd / num_remStops) + addFuel);
@ -434,13 +442,14 @@ float SimpleStrategy::pitRefuel(tCarElt* car, tSituation *s)
if (m_remainingstops >= 1)
{
m_fuelperstint = (tdble)((fuelToEnd / num_remStops) + addFuel);
} else if (m_remainingstops <= 0)
}
else if (m_remainingstops <= 0)
{
m_fuelperstint = (tdble)((lapsToEnd * fuelPerLap) + addMinFuel);
}
fuel = MIN(m_fuelperstint - car->_fuel, car->_tank - car->_fuel);
LogSHADOW.debug(" %s in Pit to refuel %.2fl < PitStop %d >\n", car->_name, fuel, countPitStop);
LogSHADOW.info(" %s in Pit to refuel %.2fl < PitStop %d >\n", car->_name, fuel, countPitStop);
}

View file

@ -134,9 +134,11 @@ protected:
float lastPitFuel; // Amount refueled, special case when we refuel.
float lastFuel; // The fuel available when we cross the start lane.
float fuelSum; // All the fuel used needed for the race.
double fuelSumPerMeter;
int counterFuelLaps; // Counter of the total laps.
int countPitStop; // Counter of the total pits stop.
double avgFuelPerLap; // The average amount of fuel we needed for a lap.
double avgFuelPerMeter;
int m_maxDamage; // The Max damage set in the XML file.
float m_Fuel; // The new average fuel per lap
float m_expectedfuelperlap; // Expected fuel per lap (may be very inaccurate).

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,319 @@
#ifndef _STUCK_H
#define _STUCK_H
#include <vector>
#include <queue>
#include <car.h>
#include <robot.h>
#include "Utils.h"
#include "MyTrack.h"
#include "Opponent.h"
// The "SHADOW" logger instance.
extern GfLogger* PLogSHADOW;
#define LogSHADOW (*PLogSHADOW)
class Stuck
{
public:
Stuck();
~Stuck();
bool execute( const MyTrack& track, const tSituation* s, tCarElt* me, const Opponent::Sit& mySit );
private:
void executeRacing( const MyTrack& track, const tSituation* s, const tCarElt* me, const Opponent::Sit& mySit );
void executeReorient(const MyTrack& track, const tSituation* s, tCarElt* me, const Opponent::Sit& mySit );
void executeInit( const MyTrack& track, const tSituation* s, tCarElt* me );
void executeSolving( const MyTrack& track, const tSituation* s, tCarElt* me );
void executePlan( const MyTrack& track, const tSituation* s, tCarElt* me );
private:
enum { N_ANGLES = 64 };
enum { HALF_ANGLE = N_ANGLES / 2 };
enum { ANGLE_MASK = N_ANGLES - 1 };
enum { OCTANT = N_ANGLES / 8 };
enum { HALF_OCTANT = OCTANT / 2 };
enum { GRID_RAD = 50 };
enum { GRID_SIZE = 2 * GRID_RAD + 1 };
enum { CAR_RAD = 4 };
enum { SPD = 4 }; // speed of car while getting unstuck.
enum State { RACING, REORIENT_FORWARDS, REORIENT_BACKWARDS, REINIT, SOLVING, EXEC_PLAN };
static inline int fwang( int iang, bool fw ) { return (iang << 1) | int(fw); }
struct GridPoint
{
unsigned int pt; // current position.
float est_time; // estimated time to finish.
float time; // current time.
GridPoint()
: pt(0), est_time(0), time(0)
{
}
GridPoint( int p )
: pt(p), est_time(0), time(0)
{
}
GridPoint( int x, int y, int iang, bool fw, float time, float est )
{
set(x, y, iang, fw, time, est);
}
GridPoint( int x, int y, float ang, bool fw, float time, float est )
{
set(x, y, ang, fw, time, est);
}
GridPoint( const Stuck& stuck, const tCarElt* car, bool fw, float est )
{
float dx = car->pub.DynGCg.pos.x - stuck._gridOrigin.x;
float dy = car->pub.DynGCg.pos.y - stuck._gridOrigin.y;
int x = (int)floor(dx + 0.5);
int y = (int)floor(dy + 0.5);
set(x, y, (float)car->pub.DynGCg.pos.az, fw, 0.0f, est);
}
bool operator<( const GridPoint& other ) const
{
return est_time > other.est_time;
}
bool isValid() const
{
return false;
}
void set( int x, int y, int iang, bool fw, float tm, float est )
{
x = x & 0xFF;
y = y & 0xFF;
iang = iang & ANGLE_MASK;
pt = (fw << 24) | (x << 16) | (y << 8) | (iang);
time = tm;
est_time = est;
}
void set( int x, int y, float ang, bool fw, float time, float est )
{
int iang = to_iang(ang);
set(x, y, iang, fw, time, est);
}
void set_fw( bool fw )
{
pt = (fw << 24) | (0x00FFFFFF & pt);
}
double dist( const GridPoint& other ) const
{
int dx = x() - other.x();
int dy = y() - other.y();
int da = iang() - other.iang();
if( da > 32 )
da -= 64;
else if( da < -32 )
da += 64;
return dx*dx + dy*dy + da*da*0.001;
}
bool fw() const { return (pt >> 24) != 0; }
bool bw() const { return (pt >> 24) == 0; }
int x() const { return (pt >> 16) & 0xFF; }
int y() const { return ((pt >> 8) & 0xFF); }
int iang() const { return pt & 0xFF; }
int fwang() const { return (iang() << 1) | int(fw()); }
};
struct Cell
{
enum { EDGE_MASK = 0x80000000 };
unsigned int occupied_mask;
float est_time_to_car;
float est_time_to_dest;
int dist_from_walls;
float times[N_ANGLES * 2]; // indexed by fwang
int from[N_ANGLES * 2]; // indexed by fwang
char solution[N_ANGLES * 2]; // indexed by fwang
Cell() { clear(); }
void clear()
{
occupied_mask = EDGE_MASK; // track edges...
//occupied_mask = 0;
est_time_to_car = -1;
est_time_to_dest = -1;
dist_from_walls = 0;
for( int i = 0; i < N_ANGLES * 2; i++ )
{
times[i] = 9e9f;
from[i] = -1;
solution[i] = 0;
}
}
void addCarMask( int carIdx ) { occupied_mask |= (1u << carIdx); };
void removeCarMask( int carIdx ) { occupied_mask &= ~(1u << carIdx); };
void clearAllCarMasks() { occupied_mask &= EDGE_MASK; };
void addEdgeMask() { occupied_mask |= EDGE_MASK; };
void removeEdgeMask() { occupied_mask &= ~EDGE_MASK; };
bool isAvailable() const { return occupied_mask == 0; }
bool isAvailable( int fwang ) const { return occupied_mask == 0 && times[fwang] >= 0; }
void setSolution( int fwang ) { solution[fwang] = 1; times[fwang] = 9e9f; }
bool isSolution( int fwang ) const { return solution[fwang] == 1; }
};
struct Edge
{
int sy; // starting y value
int ey; // ending y value
float sx; // starting x value
float dX; // for a step of size 1 in y
int x; // current x value
Edge( float x1, float y1, float x2, float y2 )
{
if( y1 > y2 )
{
std::swap( x1, x2 );
std::swap( y1, y2 );
}
sy = (int)ceil(y1);
ey = (int)floor(y2);
dX = y1 < y2 ? (x2 - x1) / (y2 - y1) : 0;
sx = x1 + (sy - y1) * dX;
x = 0;
}
bool operator<( const Edge& other ) const
{
return x < other.x;
}
int calcX(int y) { return (int)floor(sx + (y - sy) * dX); }
};
struct OppInfo
{
double x;
double y;
int ix;
int iy;
const tCarElt* car;
OppInfo() : x(0), y(0), ix(0), iy(0), car(0) {}
OppInfo( double X, double Y, const tCarElt* CAR )
: x(X), y(Y), car(CAR)
{
ix = (int)floor(x + 0.5);
iy = (int)floor(x + 0.5);
}
bool operator==( const OppInfo& other ) const
{
return ix == other.ix && iy == other.iy && car == other.car;
}
bool operator!=( const OppInfo& other ) const
{
return !operator==(other);
}
};
static const int delta8_x[8];
static const int delta8_y[8];
static const float delta8_t[8];
static const float delta64_t[64];
private:
void updateStuckTime( const tCarElt* me, const tSituation* s );
void makeOpponentsList( const tSituation* s, const tCarElt* me,
std::vector<OppInfo>* opponents );
bool clearAhead( const MyTrack& track, const tSituation* s, const tCarElt* me ) const;
bool opponentsChanged( const tSituation* s, const tCarElt* me );
bool isInitialised() const { return _me != 0; }
void reorient( const tCarElt* me, double dirAng );
void init( const MyTrack& track, const tSituation* s, const tCarElt* me );
void fillCarCells( int carI, double carX, double carY, double carAng, double dx, double dy, double rad, bool addMask );
void fillTrackCells( const MyTrack& track );
bool solve( const tCarElt* me );
bool solveR( const tCarElt* me );
void dumpGrid() const;
void getUnstuck( const MyTrack& track, tCarElt* me, const tSituation* s );
private:
const Cell& at( int x, int y ) const { return _grid[x][y]; }
Cell& at( int x, int y ) { return _grid[x][y]; }
const Cell& at( const GridPoint& pt ) const { return _grid[pt.x()][pt.y()]; }
Cell& at( const GridPoint& pt ) { return _grid[pt.x()][pt.y()]; }
bool isValid( int x, int y ) const { return x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE; }
const Cell& operator[]( const GridPoint& pt ) const { return at(pt); }
double calcCarDist( bool fw, double maxDist, const tCarElt* me, const tSituation* s ) const;
void generateSuccessorsN( const GridPoint& from, std::vector<GridPoint>& succs ) const;
void generateSuccessorsR( const GridPoint& from, std::vector<GridPoint>& succs ) const;
static int to_iang( double ang )
{
const float ang_step = float(N_ANGLES / (2 * 3.14159265));
int iang = (int)floor(ang * ang_step + 0.5);
return iang & ANGLE_MASK;
}
static int reverse( int iang ) { return (iang + N_ANGLES / 2) & ANGLE_MASK; }
static void sort( std::vector<Edge>& row, int y );
private:
const tCarElt* _me;
Vec2d _gridOrigin;
std::vector<std::vector<Cell>> _grid;
State _stuckState;
double _stuckTime;
int _stuckCount;
// track points for collision detection.
std::vector<Vec2d> _leftPoints;
std::vector<Vec2d> _rightPoints;
// intialisation variables
std::vector<OppInfo> _opponents;
GridPoint _origCarPt;
// for debugging
std::vector<GridPoint> _destinations;
// solver variables
int _expansionsN;
std::priority_queue<GridPoint> _pqN;
int _expansionsR;
std::priority_queue<GridPoint> _pqR;
float _bestTime;
GridPoint _bestPt;
// plan variables
std::vector<GridPoint> _plan;
int _planIndex;
};
#endif // _STUCK_H