1 /***************************************************************************
2 
3     file                 : pathfinder.h
4     created              : Tue Oct 9 16:52:00 CET 2001
5     copyright            : (C) 2001-2002 by Bernhard Wymann
6     email                : berniw@bluewin.ch
7     version              : $Id: pathfinder.h,v 1.1.2.1 2008/11/09 17:50:19 berniw Exp $
8 
9  ***************************************************************************/
10 
11 /***************************************************************************
12  *                                                                         *
13  *   This program is free software; you can redistribute it and/or modify  *
14  *   it under the terms of the GNU General Public License as published by  *
15  *   the Free Software Foundation; either version 2 of the License, or     *
16  *   (at your option) any later version.                                   *
17  *                                                                         *
18  ***************************************************************************/
19 
20 /*
21 	should (!) compute a good path
22 */
23 
24 #ifndef _PATHFINDER_H_
25 #define _PATHFINDER_H_
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <cstring>
30 
31 #include <tgf.h>
32 #include <track.h>
33 #include <car.h>
34 #include <raceman.h>
35 #include <robot.h>
36 #include <robottools.h>
37 #include <math.h>
38 #include "trackdesc.h"
39 #include "mycar.h"
40 #include "spline.h"
41 #include "linalg.h"
42 
43 #define FNPF "drivers/berniw/parameter.dat"
44 #define FNIS "drivers/berniw/intsinsqr.dat"
45 #define FNIC "drivers/berniw/intcossqr.dat"
46 
47 /* how far we look forward for overtaking, collisions, etc */
48 #define AHEAD 500
49 
50 /* how many segments can i pass per simulation step, depends on TRACKRES, simulation->_deltaTime and speed */
51 #define SEGRANGE 3
52 
53 /* choose old path */
54 //#define PATH_BERNIW
55 
56 /* choose k1999 path */
57 #define PATH_K1999
58 
59 class MyCar;
60 class OtherCar;
61 
62 
63 /* holds a point of datafile from clothoid */
64 typedef struct {
65 	double x;
66 	double pd;
67 	double is;
68 	double ic;
69 } tParam;
70 
71 
72 /* holds data relative to my car */
73 typedef struct {
74 	double speedsqr;		/* on track direction projected speed squared of opponent */
75 	double speed;			/* same, but not squared */
76 	double time;			/* estimate of time to catch up the car */
77 	double cosalpha;		/* cos(alpha) from angle between my ond opponent */
78 	double disttomiddle;	/* distance to middle (for prediction) */
79 	int catchdist;
80 	int catchsegid;			/* segment, where i expect (or better guess!) to catch opponent */
81 	double dist;			/* #segments from me to the other car */
82 	OtherCar* collcar;		/* pointers to the cars */
83 	bool overtakee;			/* is this the guy to overtake? */
84 	double disttopath;		/* distance to my path */
85 	double brakedist;		/* distance needed for braking to the speed of this car */
86 	double mincorner;		/* corner nearest to my car */
87 	double minorthdist;		/* minimal distance relative to my car */
88 } tOCar;
89 
90 
91 /* holds data needed for let pass opponents */
92 typedef struct {
93 	double time;			/* how long is the opponent "in range" to overlap me */
94 } tOverlapTimer;
95 
96 
97 
98 class PathSeg
99 {
100 	public:
101 		void set(tdble ispeedsqr, tdble ilength, v3d* ip, v3d* id);
102 		void set(tdble ispeedsqr, tdble ilength, v3d* id);
setLoc(v3d * ip)103 		inline void setLoc(v3d* ip) { p = (*ip); }
setOptLoc(v3d * ip)104 		inline void setOptLoc(v3d* ip) { o = (*ip); }
setPitLoc(v3d * ip)105 		inline void setPitLoc(v3d* ip) { l = ip; }
106 
setSpeedsqr(tdble spsqr)107 		inline void setSpeedsqr(tdble spsqr) { speedsqr = spsqr; }
setWeight(tdble w)108 		inline void setWeight(tdble w) { weight = w; }
setRadius(tdble r)109 		inline void setRadius(tdble r) { radius = r; }
110 
getSpeedsqr()111 		inline tdble getSpeedsqr() { return speedsqr; }
getLength()112 		inline tdble getLength() { return length; }
getWeight()113 		inline tdble getWeight() { return weight; }
getRadius()114 		inline tdble getRadius() { return radius; }
115 
getOptLoc()116 		inline v3d* getOptLoc() { return &o; }
getPitLoc()117 		inline v3d* getPitLoc() { return l; }
getLoc()118 		inline v3d* getLoc() { return &p; }
getDir()119 		inline v3d* getDir() { return &d; }
120 
121 	private:
122 		tdble speedsqr;	/* max possible speed sqared (speed ist therefore sqrt(speedsqr) */
123 		tdble length;	/* dist to the next pathseg */
124 		tdble weight;	/* weight function value for superposition */
125 		tdble radius;	/* radius of current segment */
126 		v3d p;			/* position in space, dynamic trajectory */
127 		v3d o;			/* position in space, static trajectory */
128 		v3d d;			/* direction vector of dynamic trajectory */
129 		v3d* l;			/* trajectory for pit lane */
130 };
131 
132 
133 class Pathfinder
134 {
135 	public:
136 		Pathfinder(TrackDesc* itrack, tCarElt* car, tSituation *situation);
137 		~Pathfinder();
138 		void plan(int trackSegId, tCarElt* car, tSituation* situation, MyCar* myc, OtherCar* ocar);
139 		void plan(MyCar* myc);
140 
141 		void initPit(tCarElt* car);
isPitAvailable()142 		inline bool isPitAvailable() { return pit; }
getPitSegId()143 		inline int getPitSegId() { return pitSegId; }
144 		void setPitStop(bool p, int id);
getPitStop()145 		inline bool getPitStop() { return pitStop; }
146 		int segmentsToPit(int id);
147 		void plotPitStopPath(char* filename);
148 		void plotPath(char* filename);
149 
sqr(double a)150 		inline double sqr(double a) { return a*a; };
dist(v3d * a,v3d * b)151 		inline double dist(v3d* a, v3d* b) { return sqrt(sqr(a->x-b->x) + sqr(a->y-b->y) + sqr(a->z-b->z)); }
dist2D(v3d * a,v3d * b)152 		inline double dist2D(v3d* a, v3d* b) { return sqrt(sqr(a->x-b->x) + sqr(a->y-b->y)); }
getPathSeg(int pathSegId)153 		inline PathSeg* getPathSeg(int pathSegId) { return &ps[pathSegId]; }
154 		int getCurrentSegment(tCarElt* car);
155 		int getCurrentSegment(tCarElt* car, int range);
getnPathSeg()156 		inline int getnPathSeg() { return nPathSeg; }
getPitSpeedSqrLimit()157 		inline double getPitSpeedSqrLimit() { return pitspeedsqrlimit; }
158 		double distToPath(int trackSegId, v3d* p);
159 
160 	private:
161 		static const double COLLDIST;	/* up to this distance do we consider other cars as dangerous */
162 		static const double TPRES;		/* resolution of the steps */
163 		enum { PITPOINTS = 7 };			/* # points for pit spline */
164 		enum { NTPARAMS = 1001 };		/* # entries in dat files */
165 		tParam cp[NTPARAMS];			/* holds values needed for clothiod */
166 
167 		TrackDesc* track;		/* pointer to track data */
168 		int lastId;				/* segment id of the last call */
169 		PathSeg* ps;			/* array with the plan */
170 		int nPathSeg;			/* # of PathSeg's */
171 		int lastPlan;			/* start of the last plan */
172 		int lastPlanRange;		/* range of the last plan */
173 		bool pitStop;			/* pitstop ? */
174 		bool inPit;				/* internal pit state */
175 
176 		int s1, s3;				/* pitentrystart, pitentryend */
177 		int e1, e3;				/* pitexitstart, pitexitend */
178 
179 		v3d pitLoc;				/* location of pit */
180 		int pitSegId;			/* segment id of pit */
181 		bool pit;
182 		int changed;
183 		double pitspeedsqrlimit;	/* speed limit for pit lane squared */
184 
185 		int collcars;
186 		tOCar* o;
187 		tOverlapTimer* overlaptimer;
188 		v3d* pitcord;
189 
190 		void initPitStopPath(void);
191 		void getPitPoint(int j, int k, double slope, double dist, v3d* r);
192 		int collision(int trackSegId, tCarElt* mycar, tSituation *s, MyCar* myc, OtherCar* ocar);
193 		int overtake(int trackSegId, tSituation *s, MyCar* myc, OtherCar* ocar);
194 		double curvature(double xp, double yp, double x, double y, double xn, double yn);
195 		void adjustRadius(int s, int p, int e, double c, double carwidth);
196 		void stepInterpolate(int iMin, int iMax, int Step);
197 		void interpolate(int Step);
198 		void smooth(int Step);
199 
200 		int correctPath(int id, tCarElt* car, MyCar* myc);
201 
202 		bool loadClothoidParams(tParam* p);
203 		double intsinsqr(double alpha);
204 		double intcossqr(double alpha);
205 		double clothparam(double alpha);
206 		double clothsigma(double beta, double y);
207 		double clothlength(double beta, double y);
208 
209 		int findStartSegId(int id);
210 		int findEndSegId(int id);
211 		int initStraight(int id, double w);
212 		int initLeft(int id, double w);
213 		int initRight(int id, double w);
214 		double computeWeight(double x, double len);
215 		void setLocWeighted(int id, double newweight, v3d* newp);
216 		void smooth(int s, int e, int p, double w);
217 		void smooth(int id, double delta, double w);
218 		void optimize(int start, int range, double w);
219 		void optimize2(int start, int range, double w);
220 		void optimize3(int start, int range, double w);
221 		int updateOCar(int trackSegId, tSituation *s, MyCar* myc, OtherCar* ocar, tOCar* o);
222 		void updateOverlapTimer(int trackSegId, tSituation *s, MyCar* myc, OtherCar* ocar, tOCar* o, tOverlapTimer* ov);
223         int letoverlap(int trackSegId, tSituation *s, MyCar* myc, OtherCar* ocar, tOverlapTimer* ov);
224 		double pathSlope(int id);
225 		int countSegments(int from, int to);
226 };
227 
228 
distToPath(int trackSegId,v3d * p)229 inline double Pathfinder::distToPath(int trackSegId, v3d* p)
230 {
231 	v3d *toright = track->getSegmentPtr(trackSegId)->getToRight();
232 	v3d *pathdir = ps[trackSegId].getDir();
233 	v3d n1, torightpath;
234 	toright->crossProduct(pathdir, &n1);
235 	pathdir->crossProduct(&n1, &torightpath);
236 	return ((*p - *ps[trackSegId].getLoc())*torightpath)/torightpath.len();
237 }
238 
239 
set(tdble ispeedsqr,tdble ilength,v3d * ip,v3d * id)240 inline void PathSeg::set(tdble ispeedsqr, tdble ilength, v3d* ip, v3d* id) {
241 	speedsqr = ispeedsqr;
242 	length = ilength;
243 	p = (*ip);
244 	d = (*id);
245 }
246 
247 
set(tdble ispeedsqr,tdble ilength,v3d * id)248 inline void PathSeg::set(tdble ispeedsqr, tdble ilength, v3d* id) {
249 	speedsqr = ispeedsqr;
250 	length = ilength;
251 	d = (*id);
252 }
253 
254 
setPitStop(bool p,int id)255 inline void Pathfinder::setPitStop(bool p, int id) {
256 	if (isPitAvailable() && track->isBetween(e3, (s1 - AHEAD + nPathSeg) % nPathSeg, id) && p) {
257 		pitStop = true ;
258 	} else {
259 		pitStop = false;
260 	}
261 }
262 
263 
segmentsToPit(int id)264 inline int Pathfinder::segmentsToPit(int id) {
265 	if (id <= pitSegId) {
266 		return (pitSegId - id);
267 	} else {
268 		return (track->getnTrackSegments() - id + pitSegId);
269 	}
270 }
271 
272 
pathSlope(int id)273 inline double Pathfinder::pathSlope(int id) {
274 	int nextid = (id + 1) % nPathSeg;
275 	v3d dir = *ps[nextid].getLoc() - *ps[id].getLoc();
276 	double dp = dir*(*track->getSegmentPtr(id)->getToRight())/dir.len();
277 	double alpha = PI/2.0 - acos(dp);
278 	return tan(alpha);
279 }
280 
281 
282 /* get the segment on which the car is, searching ALL the segments */
getCurrentSegment(tCarElt * car)283 inline int Pathfinder::getCurrentSegment(tCarElt* car)
284 {
285 	lastId = track->getCurrentSegment(car);
286 	return lastId;
287 }
288 
289 
290 /* get the segment on which the car is, searching from the position of the last call within range */
getCurrentSegment(tCarElt * car,int range)291 inline int Pathfinder::getCurrentSegment(tCarElt* car, int range)
292 {
293 	lastId = track->getCurrentSegment(car, lastId, range);
294 	return lastId;
295 }
296 
297 
countSegments(int from,int to)298 inline int Pathfinder::countSegments(int from, int to)
299 {
300 	if ( to >= from) {
301 		return to - from;
302 	} else {
303 		return nPathSeg - from + to;
304 	}
305 }
306 
307 #endif // _PATHFINDER_H_
308 
309