HOG2
Racetrack.cpp
Go to the documentation of this file.
1 //
2 // Racetrack.cpp
3 // hog2
4 //
5 
6 #include "Racetrack.h"
7 #include "TemplateAStar.h"
8 
9 
10 
11 std::ostream &operator<<(std::ostream &out, const RacetrackState &s)
12 {
13  out << "{" << s.xLoc << ", " << s.yLoc << "}:(" << s.xVelocity << ", " << s.yVelocity << ")";
14  return out;
15 }
16 
17 bool operator==(const RacetrackState &l1, const RacetrackState &l2) {
18  return
19  ((l1.xLoc == l2.xLoc) &&
20  (l1.yLoc == l2.yLoc) &&
21  (l1.xVelocity == l2.xVelocity) &&
22  (l1.yVelocity == l2.yVelocity));
23 }
24 
25 bool operator!=(const RacetrackState &l1, const RacetrackState &l2) {
26  return !(l1 == l2);
27 }
28 
29 std::ostream &operator<<(std::ostream &out, const RacetrackMove &m)
30 {
31  out << "(" << +m.xDelta << ", " << +m.yDelta << ")";
32  return out;
33 }
34 
35 bool operator==(const RacetrackMove &m1, const RacetrackMove &m2) {
36  return (m1.xDelta == m2.xDelta) && (m1.yDelta == m2.yDelta);
37 }
38 
39 
41 :me(0)
42 {
43  UpdateMap(map);
44 }
45 
46 
48 {
49  delete me;
50 }
51 
53 {
54  delete me;
55  me = new MapEnvironment(map);
56  this->map = map;
58  std::vector<xyLoc> path;
60  astar.SetStopAfterGoal(false);
61  int goals = 0;
62  for (int y = 0; y < map->GetMapHeight(); y++)
63  {
64  for (int x = 0; x < map->GetMapWidth(); x++)
65  {
66  if (map->GetTerrainType(x, y) == kEndTerrain)
67  {
68  xyLoc f(x, y);
69  if (goals == 0)
70  astar.InitializeSearch(me, f, f, path);
71  else
72  astar.AddAdditionalStartState(f);
73  goals++;
74  }
75  }
76  }
77  while (astar.GetNumOpenItems() > 0)
78  astar.DoSingleSearchStep(path);
80  for (int x = 0; x < astar.GetNumItems(); x++)
81  {
82  auto i = astar.GetItem(x);
83  heuristic[GetIndex(i.data.x, i.data.y)] = i.g;
84  }
85 }
86 
88 {
89  s.xVelocity = 0;
90  s.yVelocity = 0;
91  for (int x = 0; x < map->GetMapWidth(); x++ )
92  {
93  for (int y = 0; y < map->GetMapHeight(); y++ )
94  {
95  if (map->GetTerrainType(x, y) == kStartTerrain)
96  {
97  s.xLoc = x;
98  s.yLoc = y;
99  return;
100  }
101  }
102  }
103  std::cout << "No start terrain found! \n";
104  exit(1);
105 }
106 
107 
108 void Racetrack::GetSuccessors(const RacetrackState &nodeID, std::vector<RacetrackState> &neighbors) const
109 {
110  static std::vector<RacetrackMove> actions;
111  this->GetActions(nodeID, actions);
112  neighbors.clear();
113 
114  for (int i=0; i < actions.size(); i++)
115  {
116  RacetrackState temp = nodeID; //resets the temporary state to its original
117  ApplyAction(temp, actions[i]); // applies the action to get the state
118  neighbors.push_back(temp); // adds the state to the vector
119  }
120 }
121 
122 void Racetrack::GetActions(const RacetrackState &nodeID, std::vector<RacetrackMove> &actions) const
123 {
124  actions.clear();
125 
126 // RacetrackMove up(0, -1);
127 // RacetrackMove down(0, 1);
128 // RacetrackMove left(-1, 0);
129 // RacetrackMove right(1, 0);
130 // RacetrackMove same(0, 0);
131 
132  for (int x = -1; x <= 1; x++)
133  {
134  for (int y = -1; y <= 1; y++)
135  {
136  RacetrackMove m(x, y);
137  if (Legal(nodeID, m))
138  actions.push_back(m);
139  }
140  }
141 // if (this->Legal(nodeID, up) == true)
142 // {
143 // actions.push_back(up);
144 // }
145 // if (this->Legal(nodeID, down) == true)
146 // {
147 // actions.push_back(down);
148 // }
149 // if (this->Legal(nodeID, left)==true)
150 // {
151 // actions.push_back(left);
152 // }
153 // if (this->Legal(nodeID, right)==true)
154 // {
155 // actions.push_back(right);
156 // }
157 // if (this->Legal(nodeID, same)==true)
158 // {
159 // actions.push_back(same);
160 // }
161 }
162 
163 
164 
166 { // When x y velocity and action is applied -- location changes when velocity changes
167  if (a.hitGoal)
168  {
169  s.xVelocity += a.xDelta;
170  s.yVelocity += a.yDelta;
171  s.xLoc = a.xGoal;
172  s.yLoc = a.yGoal;
173  }
174  else {
175  s.xVelocity += a.xDelta;
176  s.yVelocity += a.yDelta;
177  s.xLoc += s.xVelocity;
178  s.yLoc += s.yVelocity;
179  }
180 
181 // this->Boundaries(s, a);
182 }
183 
184 // ------------ Boundaries ----------- //
185 
187 {
188  if (s.xLoc > 60000)
189  {
190  s.xLoc = 0;
191  s.xVelocity = 0;
192  //v.xDelta = 0;
193  }
194  else if (s.xLoc >= map->GetMapWidth() - 1)
195  {
196  s.xLoc = map->GetMapWidth()-1;
197  s.xVelocity = 0;
198  //v.xDelta = 0;
199  }
200  if (s.yLoc > 60000)
201  {
202  // makes the agent stop
203  s.yLoc = 0;
204  s.yVelocity = 0;
205  //v.yDelta = 0;
206  }
207 
208  else if (s.yLoc >= map->GetMapHeight() - 1)
209  {
210  s.yLoc = map->GetMapHeight()-1;
211  s.yVelocity = 0;
212  //v.yDelta = 0;
213  }
214 
215 
216 
217 }
218 
219 
220 
221 
223 {
224  // Actions are not invertable
225  return false;
226 }
227 
229 {
230  RacetrackMove m;
231  int newX = s1.xLoc + s1.xVelocity;
232  int expectedX = s2.xLoc;
233  m.xDelta = expectedX-newX;
234 
235  int newY = s1.yLoc + s1.yVelocity;
236  int expectedY = s2.yLoc;
237  m.xDelta = expectedY-newY;
238 
239  return m;
240 }
241 
242 
243 /*
244  * The goal is implicit: We reach the goal if we have reached kEndTerrain.
245  * So, we ignore the speicfic goal state
246  */
248 {
249  // Use the node to see if the location matches the goal location
250 
251  if (map->GetTerrainType(node.xLoc, node.yLoc) == kEndTerrain)
252  {
253  //std::cout << "Touched the goal! \n";
254  return true;
255  }
256  return false;
257 }
258 
259 // --- The legal function, which checks whether an action is legal --- //
260 bool Racetrack::Legal(const RacetrackState &node1, RacetrackMove &act) const
261 {
262  // Check if move goes out of bounds -- note -- you can pass the goal and then
263  // go out of bounds, so this isn't sufficient
264 // if ((node1.xLoc + node1.xVelocity + act.xDelta >= map->GetMapWidth()) ||
265 // (node1.xLoc + node1.xVelocity + act.xDelta < 0))
266 // return false;
267 // if ((node1.yLoc + node1.yVelocity + act.yDelta >= map->GetMapHeight()) ||
268 // (node1.yLoc + node1.yVelocity + act.yDelta < 0))
269 // return false;
270 
271 
272  // Check if moving too fast
273  if ((node1.xVelocity + act.xDelta > maxVelocity) ||
274  (node1.xVelocity + act.xDelta < -maxVelocity))
275  return false;
276  if ((node1.yVelocity + act.yDelta > maxVelocity) ||
277  (node1.yVelocity + act.yDelta < -maxVelocity))
278  return false;
279 
280  // Check if not moving - can't stay in place
281  if (node1.xVelocity == 0 && act.xDelta == 0 && node1.yVelocity == 0 && act.yDelta == 0)
282  return false;
283 
284  // Check locations - every x border and y border
285  act.hitGoal = false;
286  RacetrackState node2 = node1;
287  ApplyAction(node2, act);
288  Graphics::point s(node1.xLoc, node1.yLoc);
289  Graphics::point g(node2.xLoc, node2.yLoc);
290 
291  // We only have to be consistent with ourselves, so we do a simple
292  // line sweep and check 5 points on each sweep location
293  int numSegments = static_cast<int>(2*ceilf((g-s).length()));
294  for (int x = 1; x <= numSegments; x ++)
295  {
296  Graphics::point next;
297  float ratio = static_cast<float>(x)/static_cast<float>(numSegments);
298  next = s*(1-ratio)+g*(ratio);
299  float offsets[5][2] = {{0, 0}, {0.4f, 0.4f}, {-0.4f, -0.4f}, {-0.4f, 0.4f}, {0.4f, -0.4f}};
300  for (int y = 0; y < 5; y++)
301  {
302  // check if next is overlapping blocked cells or the goal
303  int xNext = static_cast<int>(roundf(next.x+offsets[y][0]));
304  int yNext = static_cast<int>(roundf(next.y+offsets[y][1]));
305  if ((xNext >= map->GetMapWidth()) || (xNext < 0))
306  return false;
307  if ((yNext >= map->GetMapHeight()) || (yNext < 0))
308  return false;
309 
310  auto terrain = map->GetTerrainType(xNext, yNext);
311  if (terrain == kObstacle)
312  return false;
313  if (terrain == kEndTerrain)
314  {
315  act.hitGoal = true;
316  act.xGoal = xNext;
317  act.yGoal = yNext;
318  return true;
319  } // mark goal for efficiency
320  }
321  }
322  return true;
323 }
324 double Racetrack::HCost(const RacetrackState &node1, const RacetrackState &node2) const
325 {
326  return HCost(node1);
327 }
328 
330 {
331  int len = heuristic[GetIndex(node.xLoc, node.yLoc)];
332  int speed = abs(node.xVelocity)+abs(node.yVelocity);
333  int h = 0;
334  // Could do this much faster with rather simple math
335  while (len > 0)
336  {
337  h++;
338  speed = std::min((speed+2), 8); // max speed is 8
339  len -= speed;
340  }
341  return h;
342 }
343 
344 
346 {
347  return ((static_cast<uint64_t>(node.xLoc)<<32) | (static_cast<uint64_t>(node.yLoc)<<16) | (static_cast<uint64_t>(node.xVelocity+maxVelocity)<<8) | (static_cast<uint64_t>(node.yVelocity+maxVelocity)));
348 }
349 
351 {
352  assert(false);
353  return 0;
354 }
355 
356 void Racetrack::Draw(Graphics::Display &display) const
357 {
358  me->Draw(display);
359 }
360 
361 void Racetrack::Draw(Graphics::Display &display, const RacetrackState &s) const
362 {
363  // draws agent location and movement vector
364  xyLoc temp(s.xLoc + (s.xVelocity), s.yLoc + (s.yVelocity)); // predicted next location
365 // xyLoc temp2(s.xLoc-s.xVelocity, s.yLoc-s.yVelocity); // location from where agent was before to where it is now
366 
367  xyLoc agent(static_cast<uint16_t>(s.xLoc), static_cast<uint16_t>(s.yLoc));
368  if (temp.x < map->GetMapWidth() && temp.y < map->GetMapHeight() && temp.x > 0 && temp.y > 0)
369  {
371  me->DrawLine(display, agent, temp, 2.0);
372  }
373 // me->SetColor(Colors::red);
374 // me->DrawLine(display, s.loc, temp2);
375 
376  me->SetColor(GetColor()); // sets agent color
377 // me->Draw(display, agent); // draws agent location
378 // GLdouble xx, yy, zz, rad;
379 // map->GetOpenGLCoord(s.xLoc, s.yLoc, xx, yy, zz, rad);
380 //
381 // Graphics::point center(xx, yy);
382 // Graphics::point p1(s.xVelocity, s.yVelocity);
383 // p1.normalise();
384 // if (s.xVelocity == 0 && s.yVelocity == 0)
385 // p1.x = 1;
386 // p1 = p1*(rad);
387 // Graphics::point p2(-s.yVelocity, s.xVelocity);
388 // p2.normalise();
389 // if (s.xVelocity == 0 && s.yVelocity == 0)
390 // p2.y = 1;
391 // p2 = p2*(0.5f*rad);
392 // display.FillTriangle(center+p1, center-p1+p2, center-p1-p2, this->color);
393  Graphics::point c, p1, p2, p3;
394  GetCarCoordinates(s, c, p1, p2, p3);
395 
396  display.FillTriangle(c+p1, c+p2, c+p3, GetColor());
397 }
398 
400 {
401  GLdouble xx, yy, zz, r;
402  map->GetOpenGLCoord(s.xLoc, s.yLoc, xx, yy, zz, r);
403  float rad = (float)r;
404 
405  center = Graphics::point(xx, yy);
407  p1.normalise();
408  if (s.xVelocity == 0 && s.yVelocity == 0)
409  p1.y = 1;
410  p1 = p1*(rad);
412  p2.normalise();
413  if (s.xVelocity == 0 && s.yVelocity == 0)
414  p2.x = 1;
415  Graphics::point zero;
416  p2 = p2*(0.5f*rad);
417  t1 = p1;
418  t2 = zero-p1+p2;
419  t3 = zero-p1-p2;
420 }
421 
423 {
424  // draws agent location and movement vector
425 
426  xyLoc temp(s.xLoc + (s.xVelocity + a.xDelta), s.yLoc + (s.yVelocity + a.yDelta)); // predicted next location
427  xyLoc temp2(s.xLoc-s.xVelocity, s.yLoc-s.yVelocity); // location from where agent was before to where it is now
428 
429  xyLoc agent(static_cast<uint16_t>(s.xLoc), static_cast<uint16_t>(s.yLoc));
431  me->DrawLine(display, agent, temp);
433  me->DrawLine(display, agent, temp2);
434  me->SetColor(Colors::black); // sets agent color to black
435  me->Draw(display, agent); // draws agent location
436 }
437 
438 void Racetrack::Draw(Graphics::Display &display, const RacetrackState &s, const RacetrackState &t, float v) const
439 {
441 // xyLoc agent1(static_cast<uint16_t>(s.xLoc), static_cast<uint16_t>(s.yLoc));
442 // xyLoc agent2(static_cast<uint16_t>(t.xLoc), static_cast<uint16_t>(t.yLoc));
443 // me->Draw(display, agent1, agent2, v);
444 
445  Graphics::point c1, c2;
446  Graphics::point p1, p2, p3;
447  GetCarCoordinates(s, c1, p1, p2, p3);
448  Graphics::point q1, q2, q3;
449  GetCarCoordinates(t, c2, q1, q2, q3);
450  Graphics::point middle = c1*(1-v)+c2*v;
451 
452  if (v < 0.1) // turn
453  {
454  display.FillTriangle((middle+p1)*(1-v)+(middle+q1)*v, (middle+p2)*(1-v)+(middle+q2)*v, (middle+p3)*(1-v)+(middle+q3)*v, GetColor());
455  }
456  else {
457  display.FillTriangle(middle+q1, middle+q2, middle+q3, GetColor());
458  }
459 
460 
461 }
462 
463 void Racetrack::DrawLine(Graphics::Display &display, const RacetrackState &c, const RacetrackState &d, float width) const
464 {
465  // TODO: draw line between two locations
466  xyLoc agent1(static_cast<uint16_t>(c.xLoc), static_cast<uint16_t>(c.yLoc));
467  xyLoc agent2(static_cast<uint16_t>(d.xLoc), static_cast<uint16_t>(d.yLoc));
468  me->SetColor(GetColor());
469  me->DrawLine(display, agent1, agent2, width);
470 }
Graphics::point
Definition: Graphics.h:32
Graphics::point::y
float y
Definition: Graphics.h:36
Racetrack::GetActions
void GetActions(const RacetrackState &nodeID, std::vector< RacetrackMove > &actions) const
Definition: Racetrack.cpp:122
Racetrack::UpdateMap
void UpdateMap(Map *map)
Definition: Racetrack.cpp:52
maxVelocity
const int maxVelocity
Definition: Racetrack.h:34
RacetrackMove::xDelta
int xDelta
Definition: Racetrack.h:21
operator!=
bool operator!=(const RacetrackState &l1, const RacetrackState &l2)
Definition: Racetrack.cpp:25
TemplateAStar::SetStopAfterGoal
void SetStopAfterGoal(bool val)
Definition: TemplateAStar.h:139
min
double min(double a, double b)
Definition: FPUtil.h:35
MapEnvironment::SetFourConnected
void SetFourConnected()
Definition: Map2DEnvironment.h:211
Graphics::Display::FillTriangle
void FillTriangle(point p1, point p2, point p3, rgbColor c)
Definition: Graphics.cpp:146
operator<<
std::ostream & operator<<(std::ostream &out, const RacetrackState &s)
Definition: Racetrack.cpp:11
Racetrack::Racetrack
Racetrack(Map *map)
Definition: Racetrack.cpp:40
Racetrack::Legal
bool Legal(const RacetrackState &node1, RacetrackMove &act) const
Definition: Racetrack.cpp:260
xyLoc::y
uint16_t y
Definition: Map2DEnvironment.h:42
Racetrack::GetCarCoordinates
void GetCarCoordinates(const RacetrackState &s, Graphics::point &center, Graphics::point &p1, Graphics::point &p2, Graphics::point &p3) const
Definition: Racetrack.cpp:399
d
mcData d[]
Definition: MotionCaptureMovement.cpp:21
Racetrack::GetIndex
int GetIndex(int x, int y) const
Definition: Racetrack.h:96
xyLoc
Definition: Map2DEnvironment.h:37
width
int width
Definition: SFML_HOG.cpp:54
Graphics::point::normalise
void normalise()
Definition: Graphics.h:69
operator==
bool operator==(const RacetrackState &l1, const RacetrackState &l2)
Definition: Racetrack.cpp:17
RacetrackMove::xGoal
int xGoal
Definition: Racetrack.h:25
RacetrackState::xVelocity
int xVelocity
Definition: Racetrack.h:31
TemplateAStar::GetNumOpenItems
unsigned int GetNumOpenItems()
Definition: TemplateAStar.h:113
MapEnvironment::Draw
void Draw(Graphics::Display &disp) const
Definition: Map2DEnvironment.cpp:1039
xyLoc::x
uint16_t x
Definition: Map2DEnvironment.h:41
Racetrack::DrawLine
void DrawLine(Graphics::Display &display, const RacetrackState &x, const RacetrackState &y, float width) const
Definition: Racetrack.cpp:463
kObstacle
const tTerrain kObstacle
Definition: Racetrack.h:45
RacetrackMove::hitGoal
bool hitGoal
Definition: Racetrack.h:24
SearchEnvironment::SetColor
virtual void SetColor(const rgbColor &r) const
Definition: SearchEnvironment.h:102
Racetrack::map
Map * map
Definition: Racetrack.h:94
MapEnvironment
Definition: Map2DEnvironment.h:133
Racetrack::GetStateHash
uint64_t GetStateHash(const RacetrackState &node) const
Definition: Racetrack.cpp:345
Colors::black
const rgbColor black
Definition: Colors.h:119
Graphics::Display
Definition: Graphics.h:146
TemplateAStar::AddAdditionalStartState
void AddAdditionalStartState(const state &newState)
Add additional start state to the search.
Definition: TemplateAStar.h:285
RacetrackMove::yGoal
int yGoal
Definition: Racetrack.h:25
TemplateAStar
A templated version of A*, based on HOG genericAStar.
Definition: TemplateAStar.h:73
Map::GetMapWidth
long GetMapWidth() const
return the width of the map
Definition: Map.h:163
TemplateAStar.h
SearchEnvironment< RacetrackState, RacetrackMove >::GetColor
virtual rgbColor GetColor() const
Definition: SearchEnvironment.h:105
Racetrack::Boundaries
void Boundaries(RacetrackState &s, RacetrackMove &v) const
Definition: Racetrack.cpp:186
Racetrack::GoalTest
bool GoalTest(const RacetrackState &node, const RacetrackState &goal) const
Definition: Racetrack.cpp:247
Map::GetTerrainType
long GetTerrainType(long x, long y, tSplitSide split=kWholeTile) const
Get the terrain type of the (split) tile at x, y.
Definition: Map.cpp:1028
Racetrack::heuristic
std::vector< int > heuristic
Definition: Racetrack.h:95
Racetrack::GetActionHash
uint64_t GetActionHash(RacetrackMove act) const
Definition: Racetrack.cpp:350
Racetrack::Reset
void Reset(RacetrackState &s) const
Definition: Racetrack.cpp:87
TemplateAStar::GetItem
const AStarOpenClosedDataWithF< state > & GetItem(unsigned int which)
Definition: TemplateAStar.h:116
RacetrackState
Definition: Racetrack.h:29
Racetrack::HCost
double HCost(const RacetrackState &node1, const RacetrackState &node2) const
Heuristic value between two arbitrary nodes.
Definition: Racetrack.cpp:324
path
std::vector< xyLoc > path
Definition: Sample.cpp:43
Racetrack::Draw
void Draw(Graphics::Display &display) const
Definition: Racetrack.cpp:356
Graphics::point::x
float x
Definition: Graphics.h:36
TemplateAStar::GetNumItems
const int GetNumItems()
Definition: TemplateAStar.h:115
Racetrack::GetSuccessors
void GetSuccessors(const RacetrackState &nodeID, std::vector< RacetrackState > &neighbors) const
Definition: Racetrack.cpp:108
Colors::red
const rgbColor red
Definition: Colors.h:128
TemplateAStar::InitializeSearch
bool InitializeSearch(environment *env, const state &from, const state &to, std::vector< state > &thePath)
Initialize the A* search.
Definition: TemplateAStar.h:257
Racetrack.h
Map::GetMapHeight
long GetMapHeight() const
return the height of the map
Definition: Map.h:165
RacetrackMove
Definition: Racetrack.h:20
MapEnvironment::DrawLine
void DrawLine(Graphics::Display &disp, const xyLoc &x, const xyLoc &y, double width=1.0) const
Definition: Map2DEnvironment.cpp:1430
Colors::blue
const rgbColor blue
Definition: Colors.h:142
Racetrack::InvertAction
bool InvertAction(RacetrackMove &a) const
Definition: Racetrack.cpp:222
Racetrack::me
MapEnvironment * me
Definition: Racetrack.h:93
kStartTerrain
const tTerrain kStartTerrain
Definition: Racetrack.h:43
Map::GetOpenGLCoord
bool GetOpenGLCoord(int _x, int _y, GLdouble &x, GLdouble &y, GLdouble &z, GLdouble &radius) const
Get the openGL coordinates of a given tile.
Definition: Map.cpp:1826
Racetrack::~Racetrack
~Racetrack()
Definition: Racetrack.cpp:47
path
A linked list of nodes which form a continuous path.
Definition: Path.h:20
RacetrackState::xLoc
int xLoc
Definition: Racetrack.h:30
Racetrack::ApplyAction
void ApplyAction(RacetrackState &s, RacetrackMove a) const
Definition: Racetrack.cpp:165
RacetrackMove::yDelta
int yDelta
Definition: Racetrack.h:23
RacetrackState::yVelocity
int yVelocity
Definition: Racetrack.h:31
kEndTerrain
const tTerrain kEndTerrain
Definition: Racetrack.h:44
TemplateAStar::DoSingleSearchStep
bool DoSingleSearchStep(std::vector< state > &thePath)
Expand a single node.
Definition: TemplateAStar.h:314
node
Nodes to be stored within a Graph.
Definition: Graph.h:170
Map
A tile-based representation of the world.
Definition: Map.h:142
RacetrackState::yLoc
int yLoc
Definition: Racetrack.h:30
Racetrack::GetAction
RacetrackMove GetAction(const RacetrackState &s1, RacetrackState &s2) const
Definition: Racetrack.cpp:228