ORCAAgent.cpp
Go to the documentation of this file.
1 
7 #include "ORCAAgent.h"
8 
9 ORCAAgent::ORCAAgent() : Agent() { fakeRadius = 0;}
10 
11 
12 ORCAAgent::ORCAAgent(const int &id, const Point &start, const Point &goal, const Map &map,
13  const EnvironmentOptions &options, AgentParam param)
14  : Agent(id, start, goal, map, options, param) { fakeRadius = param.rEps + param.radius;}
15 
16 
17 ORCAAgent::ORCAAgent(const ORCAAgent &obj) : Agent(obj) {fakeRadius = obj.fakeRadius;}
18 
19 
20 ORCAAgent::~ORCAAgent() = default;
21 
22 
24 {
25  ORCALines.clear();
26 
27 
28  // Получение ORCA-линий препятсвий
29  for (int i = 0; i < NeighboursObst.size(); i++)
30  {
31  Line line;
32 
33  Vertex *left = &(NeighboursObst[i].second.left);
34  Vertex *right = &(NeighboursObst[i].second.right);
35 
36  Vector lRelativePosition = *left - position;
37  Vector rRelativePosition = *right - position;
38 
39 
40  bool alreadyCovered = false;
41 
42  for (int j = 0; j < ORCALines.size(); j++)
43  {
44  if ((lRelativePosition * invTimeBoundaryObst - ORCALines[j].liesOn).Det(ORCALines[j].dir) - invTimeBoundaryObst * fakeRadius >= -CN_EPS &&
45  (rRelativePosition * invTimeBoundaryObst - ORCALines[j].liesOn).Det(ORCALines[j].dir) - invTimeBoundaryObst * fakeRadius >= -CN_EPS)
46  {
47  alreadyCovered = true;
48  break;
49  }
50  }
51  if (alreadyCovered)
52  continue;
53 
54  float lSqDist = lRelativePosition.SquaredEuclideanNorm();
55  float rSqDist = rRelativePosition.SquaredEuclideanNorm();
56 
57  float sqFakeRadius = fakeRadius * fakeRadius;
58  float sqTrueRadius = param.radius * param.radius;
59 
60  Vector obstacleVector = *right - *left;
61  float s = -lRelativePosition.ScalarProduct(obstacleVector) / obstacleVector.SquaredEuclideanNorm();
62  float lineSqDist = (-lRelativePosition - obstacleVector * s).SquaredEuclideanNorm();
63 
64  if ((s < 0.0f && lSqDist < sqTrueRadius) || (s > 1.0f && rSqDist < sqTrueRadius) ||
65  (s >= 0.0f && s < 1.0f && lineSqDist < sqTrueRadius))
66  {
67  collisionsObst++;
68  }
69 
70 
71  if (s < 0.0f && lSqDist < sqFakeRadius)
72  {
73 
74  if (left->IsConvex())
75  {
76  line.liesOn = Point();
77  line.dir = Point(-lRelativePosition.Y(), lRelativePosition.X()) / sqrt(lSqDist); // Построение единичного вектора, нормального к относительному положению
78  ORCALines.push_back(line);
79  }
80 
81  continue;
82  }
83  else if (s > 1.0f && rSqDist < sqFakeRadius)
84  {
85 
86  if (right->IsConvex() && rRelativePosition.Det(NeighboursObst[i].second.next->dir) >= 0.0f)
87  {
88  line.liesOn = Point();
89  line.dir = Point(-rRelativePosition.Y(), rRelativePosition.X()) / sqrt(rSqDist);
90  ORCALines.push_back(line);
91  }
92 
93  continue;
94  }
95  else if (s >= 0.0f && s < 1.0f && lineSqDist < sqFakeRadius)
96  {
97  line.liesOn = Point();
98  line.dir = -(NeighboursObst[i].second.dir);
99  ORCALines.push_back(line);
100  continue;
101  }
102 
103 
104  Vector lLegDirection, rLegDirection;
105 
106  if (s < 0.0f && lineSqDist <= sqFakeRadius)
107  {
108 
109  if (!left->IsConvex())
110  {
111  continue;
112  }
113 
114  right = left;
115 
116  float leg1 = sqrt(lSqDist - sqFakeRadius);
117 
118  lLegDirection = Point(lRelativePosition.X() * leg1 - lRelativePosition.Y() * fakeRadius, lRelativePosition.X() * fakeRadius + lRelativePosition.Y() * leg1) / lSqDist;
119  rLegDirection = Point(lRelativePosition.X() * leg1 + lRelativePosition.Y() * fakeRadius, -lRelativePosition.X() * fakeRadius + lRelativePosition.Y() * leg1) / lSqDist;
120  }
121  else if (s > 1.0f && lineSqDist <= sqFakeRadius)
122  {
123 
124  if (!right->IsConvex())
125  {
126  continue;
127  }
128 
129  left = right;
130 
131  float leg2 = std::sqrt(rSqDist - sqFakeRadius);
132  lLegDirection = Point(rRelativePosition.X() * leg2 - rRelativePosition.Y() * fakeRadius, rRelativePosition.X() * fakeRadius + rRelativePosition.Y() * leg2) / rSqDist;
133  rLegDirection = Point(rRelativePosition.X() * leg2 + rRelativePosition.Y() * fakeRadius, -rRelativePosition.X() * fakeRadius + rRelativePosition.Y() * leg2) / rSqDist;
134  }
135  else
136  {
137  if (left->IsConvex())
138  {
139  float leg1 = std::sqrt(lSqDist - sqFakeRadius);
140  lLegDirection = Point(lRelativePosition.X() * leg1 - lRelativePosition.Y() * fakeRadius, lRelativePosition.X() * fakeRadius + lRelativePosition.Y() * leg1) / lSqDist;
141  }
142  else
143  {
144  lLegDirection = -NeighboursObst[i].second.dir;
145  }
146 
147  if (right->IsConvex())
148  {
149  float leg2 = std::sqrt(rSqDist - sqFakeRadius);
150  rLegDirection = Point(rRelativePosition.X() * leg2 + rRelativePosition.Y() * fakeRadius, -rRelativePosition.X() * fakeRadius + rRelativePosition.Y() * leg2) / rSqDist;
151  }
152  else
153  {
154  rLegDirection = NeighboursObst[i].second.dir;
155  }
156  }
157 
158  ObstacleSegment *leftNeighbor = NeighboursObst[i].second.prev;
159 
160  bool isLLegForeign = false, isRLegForeign = false;
161 
162  if (left->IsConvex() && lLegDirection.Det(-leftNeighbor->dir) >= 0.0f)
163  {
164  lLegDirection = -leftNeighbor->dir;
165  isLLegForeign = true;
166  }
167 
168  if (right->IsConvex() && rLegDirection.Det(NeighboursObst[i].second.next->dir) <= 0.0f)
169  {
170  rLegDirection = NeighboursObst[i].second.next->dir;
171  isRLegForeign = true;
172  }
173 
174  Point leftCutoff = (*left - position) * invTimeBoundaryObst;
175  Point rightCutoff = (*right - position) * invTimeBoundaryObst;
176  Vector cutoffVec = rightCutoff - leftCutoff;
177 
178  const float t = (right == left ? 0.5f : ((currV - leftCutoff).ScalarProduct(cutoffVec)) / cutoffVec.SquaredEuclideanNorm());
179  const float tLeft = ((currV - leftCutoff).ScalarProduct(lLegDirection));
180  const float tRight = ((currV - rightCutoff).ScalarProduct(rLegDirection));
181 
182  if ((t < 0.0f && tLeft < 0.0f) || (left == right && tLeft < 0.0f && tRight < 0.0f))
183  {
184  Vector unitW = (currV - leftCutoff)/(currV - leftCutoff).EuclideanNorm();
185 
186  line.dir = Vector(unitW.Y(), -unitW.X());
187  line.liesOn = leftCutoff + unitW * fakeRadius * invTimeBoundaryObst;
188  ORCALines.push_back(line);
189  continue;
190  }
191  else if (t > 1.0f && tRight < 0.0f)
192  {
193  Vector unitW = (currV - rightCutoff)/(currV - rightCutoff).EuclideanNorm();
194 
195  line.dir = Vector(unitW.Y(), -unitW.X());
196  line.liesOn = rightCutoff + unitW * fakeRadius * invTimeBoundaryObst ;
197  ORCALines.push_back(line);
198  continue;
199  }
200 
201  float cutoffSqDist = ((t < 0.0f || t > 1.0f || right == left) ? std::numeric_limits<float>::infinity() : (currV - (leftCutoff + cutoffVec * t)).SquaredEuclideanNorm());
202  float lLegSqDist = ((tLeft < 0.0f) ? std::numeric_limits<float>::infinity() : (currV - (leftCutoff + lLegDirection * tLeft)).SquaredEuclideanNorm());
203  float rLegSqDist = ((tRight < 0.0f) ? std::numeric_limits<float>::infinity() : (currV - (rightCutoff + rLegDirection * tRight)).SquaredEuclideanNorm());
204 
205  if (cutoffSqDist <= lLegSqDist && cutoffSqDist <= rLegSqDist)
206  {
207  line.dir = -NeighboursObst[i].second.dir;
208  line.liesOn = leftCutoff + Point(-line.dir.Y(), line.dir.X()) * fakeRadius * invTimeBoundaryObst;
209  ORCALines.push_back(line);
210  continue;
211  }
212  else if (lLegSqDist <= rLegSqDist)
213  {
214  if (isLLegForeign)
215  {
216  continue;
217  }
218 
219  line.dir = lLegDirection;
220  line.liesOn = leftCutoff + Point(-line.dir.Y(), line.dir.X()) * fakeRadius * invTimeBoundaryObst;;
221  ORCALines.push_back(line);
222  continue;
223  }
224  else
225  {
226  if (isRLegForeign)
227  {
228  continue;
229  }
230 
231  line.dir = -rLegDirection;
232  line.liesOn = rightCutoff + Point(-line.dir.Y(), line.dir.X()) * fakeRadius * invTimeBoundaryObst;
233  ORCALines.push_back(line);
234  continue;
235  }
236  }
237 
238 
239  size_t numObstLines = ORCALines.size();
240 
241  //Получение ORCA-линий агентов
242  //std::sort(Neighbours.begin(),Neighbours.end(), Compare);
243 
244  Line currline;
245  ORCAAgent *curragent;
246  Vector u, w;
247 
248  unsigned long minMaxNum = (param.agentsMaxNum < Neighbours.size()) ? param.agentsMaxNum : Neighbours.size();
249 
250 
251  for(unsigned long i = 0; i < minMaxNum; i++)
252  {
253  auto Neighbour = Neighbours[i];
254  curragent = dynamic_cast<ORCAAgent *>(Neighbour.second);
255  auto circlecenter = curragent->position - this->position; //(P_b - P_a)
256 
257  auto relvelocity = this->currV - curragent->currV; //(V_a - V_b)
258 
259  float radiussum = fakeRadius + curragent->fakeRadius; //(R_a + R_b)
260  float radiussum2 = radiussum * radiussum;
261  float distSq = circlecenter.SquaredEuclideanNorm();
262  float trueSqRadSum = (param.radius + curragent->param.radius) * (param.radius + curragent->param.radius);
263 
264  if(distSq < trueSqRadSum )
265  {
266  collisions++;
267  }
268 
269  if(distSq >= radiussum2)
270  {
271  w = relvelocity - (circlecenter * invTimeBoundary); //w -- вектор на плоскости скоростей от центра малой окружности (основания VO) до скорости другого агента относительно этого
272  float sqwlength = w.SquaredEuclideanNorm();
273  float wproj = w.ScalarProduct(circlecenter);
274 
275  // если эти условия выполняются, то вектор w отложенный из центра окружности-основания VO будет своим концом ближе к
276  // этой самой окружности, а значит и ближайшая точка на границе VO -- это какая-то точка на этой окружнрости
277 
278  if(wproj < 0.0f && (wproj * wproj) > sqwlength * radiussum2)
279  {
280  const float wlength = std::sqrt(sqwlength);
281  const Vector nw = w / wlength;
282  currline.dir = Vector(nw.Y(), -nw.X());
283  u = nw * (radiussum * invTimeBoundary - wlength);
284  }
285  else
286  {
287  //иначе проекция на стороны VO
288  //длина проекции вектора относительных положений на сторону VO
289 
290  float leg = std::sqrt(distSq - radiussum2);
291 
292  if(circlecenter.Det(w) > 0.0f) //если точка ближе к левой стороне VO
293  {
294  currline.dir = Vector(circlecenter.X() * leg - circlecenter.Y() * radiussum, circlecenter.X() * radiussum + circlecenter.Y() * leg) / distSq;
295  }
296  else //если точка ближе к правой стороне VO
297  {
298  currline.dir = -(Vector(circlecenter.X() * leg + circlecenter.Y() * radiussum, -circlecenter.X() * radiussum + circlecenter.Y() * leg) / distSq);
299  }
300 
301  float rvproj = relvelocity.ScalarProduct(currline.dir);
302 
303  u = currline.dir * rvproj - relvelocity;
304  }
305  }
306  else
307  {
308  const float invTimeStep = 1.0f / options->timestep;
309 
310  Vector w = relvelocity - circlecenter * invTimeStep;
311  float wlength = w.EuclideanNorm();
312  Vector wn = w / wlength;
313  currline.dir = Vector(wn.Y(), -wn.X());
314  u = wn * (radiussum * invTimeStep - wlength);
315  }
316 
317  currline.liesOn = this->currV + u * 0.5f;
318  ORCALines.push_back(currline);
319  Neighbours.pop_back();
320  }
321 
322  auto lineFail = Utils::linearProgram2(ORCALines, param.maxSpeed, this->prefV, false, this->newV);
323  if(lineFail < this->ORCALines.size())
324  {
325  Utils::linearProgram3(ORCALines, numObstLines, lineFail, param.maxSpeed, this->newV);
326  }
327 
328  Neighbours.clear();
329 }
330 
331 
333 {
334  currV = newV;
335 }
336 
337 
339 {
340  Point next;
341  if (planner->GetNext(position, next))
342  {
343  Vector goalVector = next - position;
344  float dist = goalVector.EuclideanNorm();
345  if(next == goal && dist < options->delta)
346  {
347  prefV = Point();
348  return true;
349  }
350 
351  if(dist > CN_EPS)
352  {
353  goalVector = (goalVector/dist) * param.maxSpeed;
354  }
355 
356  prefV = goalVector;
357  return true;
358  }
359  prefV = Point();
360  return false;
361 }
362 
364 {
365 
366  if(this != &obj)
367  {
368  Agent::operator=(obj);
369  fakeRadius = obj.fakeRadius;
370  }
371  return *this;
372 }
373 
374 bool ORCAAgent::operator == (const ORCAAgent &another) const
375 {
376  return this->id == another.id;
377 }
378 
379 bool ORCAAgent::operator != (const ORCAAgent &another) const
380 {
381  return this->id != another.id;
382 }
383 
385 {
386  return new ORCAAgent(*this);
387 }
bool operator==(const ORCAAgent &another) const
Comparisons operator. Compares id of agents.
Definition: ORCAAgent.cpp:374
float SquaredEuclideanNorm() const
Computes squared euclidean norm of vector.
Definition: Geom.h:480
Agent & operator=(const Agent &obj)
Assignment operator.
Definition: Agent.cpp:208
void ApplyNewVelocity() override
Method for state updating and appling computed velocity.
Definition: ORCAAgent.cpp:332
Vector dir
Vector (right-left)/|right-left|.
Definition: Geom.h:320
Vector dir
direction vector of line.
Definition: Geom.h:205
float radius
Size of the agent (radius of the agent).
Definition: Agent.h:75
The class defines a line in 2D space.
Definition: Geom.h:202
ORCAAgent()
ORCAAgent default constructor.
Definition: ORCAAgent.cpp:9
ObstacleSegment * prev
Previous edge in obstacle.
Definition: Geom.h:322
float rEps
Buffer size (more about buffer see Main page).
Definition: Agent.h:76
The ObstacleSegment class defines an edge of an obstacle polygon.
Definition: Geom.h:274
The Point class defines a position (or euclidean vector from (0,0)) in 2D space.
Definition: Geom.h:61
Class AgentParam contains agent and algoritms parameters.
Definition: Agent.h:38
#define Vector
Vector type definition.
Definition: Const.h:11
float EuclideanNorm() const
Computes euclidean norm of vector.
Definition: Geom.h:486
Agent class implements base agent interface and behavior.
Definition: Agent.h:95
bool operator!=(const ORCAAgent &another) const
Comparisons operator. Compares id of agents.
Definition: ORCAAgent.cpp:379
Class EnvironmentOptions contains environment and algoritms parameters.
bool IsConvex() const
Return convexity of vertex.
Definition: Geom.cpp:55
Map class describes static environment.
Definition: Map.h:36
File contains ORCAAgent class.
void linearProgram3(const std::vector< Line > &lines, size_t numObstLines, size_t beginLine, float radius, Vector &result)
Solves a two-dimensional linear program subject to linear constraints defined by lines and a circular...
Definition: Geom.cpp:214
void ComputeNewVelocity() override
Computes new velocity of agent using ORCA algorithm and linear programing.
Definition: ORCAAgent.cpp:23
float ScalarProduct(const Point &another) const
Computes scalar product of vectors (this * anoher)
Definition: Geom.h:449
ORCAAgent class implements agent with ORCA algoritm behavior.
Definition: ORCAAgent.h:26
unsigned long int linearProgram2(const std::vector< Line > &lines, float radius, const Vector &optVelocity, bool directionOpt, Vector &result)
Solves a two-dimensional linear program subject to linear constraints defined by lines and a circular...
Definition: Geom.cpp:179
ORCAAgent * Clone() const override
Method for cloning objects. Creates copy of object in memmory and return pointer to copy...
Definition: ORCAAgent.cpp:384
ORCAAgent & operator=(const ORCAAgent &obj)
Assignment operator.
Definition: ORCAAgent.cpp:363
~ORCAAgent()
Virtual destructor.
bool UpdatePrefVelocity() override
Method for computing preffered velocity and chosing current goal from global path.
Definition: ORCAAgent.cpp:338
Point liesOn
point on line.
Definition: Geom.h:206
The Vertex class defines a vertex of an obstacle polygon.
Definition: Geom.h:213
#define CN_EPS
Epsilon for float number operations definition.
Definition: Const.h:14


ORCAStar
Author(s): Stepan Drgachev
autogenerated on Wed Jul 15 2020 16:13:14