14 :
Agent(id, start, goal, map, options, param) { fakeRadius = param.
rEps + param.
radius;}
29 for (
int i = 0; i < NeighboursObst.size(); i++)
33 Vertex *left = &(NeighboursObst[i].second.left);
34 Vertex *right = &(NeighboursObst[i].second.right);
36 Vector lRelativePosition = *left - position;
37 Vector rRelativePosition = *right - position;
40 bool alreadyCovered =
false;
42 for (
int j = 0; j < ORCALines.size(); j++)
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)
47 alreadyCovered =
true;
55 float rSqDist = rRelativePosition.SquaredEuclideanNorm();
57 float sqFakeRadius = fakeRadius * fakeRadius;
58 float sqTrueRadius = param.radius * param.radius;
60 Vector obstacleVector = *right - *left;
61 float s = -lRelativePosition.
ScalarProduct(obstacleVector) / obstacleVector.SquaredEuclideanNorm();
62 float lineSqDist = (-lRelativePosition - obstacleVector * s).SquaredEuclideanNorm();
64 if ((s < 0.0f && lSqDist < sqTrueRadius) || (s > 1.0f && rSqDist < sqTrueRadius) ||
65 (s >= 0.0f && s < 1.0f && lineSqDist < sqTrueRadius))
71 if (s < 0.0f && lSqDist < sqFakeRadius)
77 line.
dir =
Point(-lRelativePosition.Y(), lRelativePosition.X()) / sqrt(lSqDist);
78 ORCALines.push_back(line);
83 else if (s > 1.0f && rSqDist < sqFakeRadius)
86 if (right->
IsConvex() && rRelativePosition.Det(NeighboursObst[i].second.next->dir) >= 0.0f)
89 line.
dir =
Point(-rRelativePosition.Y(), rRelativePosition.X()) / sqrt(rSqDist);
90 ORCALines.push_back(line);
95 else if (s >= 0.0f && s < 1.0f && lineSqDist < sqFakeRadius)
98 line.
dir = -(NeighboursObst[i].second.dir);
99 ORCALines.push_back(line);
104 Vector lLegDirection, rLegDirection;
106 if (s < 0.0f && lineSqDist <= sqFakeRadius)
109 if (!left->IsConvex())
116 float leg1 = sqrt(lSqDist - sqFakeRadius);
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;
121 else if (s > 1.0f && lineSqDist <= sqFakeRadius)
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;
137 if (left->IsConvex())
139 float leg1 = std::sqrt(lSqDist - sqFakeRadius);
140 lLegDirection =
Point(lRelativePosition.X() * leg1 - lRelativePosition.Y() * fakeRadius, lRelativePosition.X() * fakeRadius + lRelativePosition.Y() * leg1) / lSqDist;
144 lLegDirection = -NeighboursObst[i].second.dir;
149 float leg2 = std::sqrt(rSqDist - sqFakeRadius);
150 rLegDirection =
Point(rRelativePosition.X() * leg2 + rRelativePosition.Y() * fakeRadius, -rRelativePosition.X() * fakeRadius + rRelativePosition.Y() * leg2) / rSqDist;
154 rLegDirection = NeighboursObst[i].second.dir;
160 bool isLLegForeign =
false, isRLegForeign =
false;
162 if (left->IsConvex() && lLegDirection.Det(-leftNeighbor->
dir) >= 0.0f)
164 lLegDirection = -leftNeighbor->
dir;
165 isLLegForeign =
true;
168 if (right->
IsConvex() && rLegDirection.Det(NeighboursObst[i].second.next->dir) <= 0.0f)
170 rLegDirection = NeighboursObst[i].second.next->dir;
171 isRLegForeign =
true;
174 Point leftCutoff = (*left - position) * invTimeBoundaryObst;
175 Point rightCutoff = (*right - position) * invTimeBoundaryObst;
176 Vector cutoffVec = rightCutoff - leftCutoff;
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));
182 if ((t < 0.0f && tLeft < 0.0f) || (left == right && tLeft < 0.0f && tRight < 0.0f))
184 Vector unitW = (currV - leftCutoff)/(currV - leftCutoff).EuclideanNorm();
186 line.
dir =
Vector(unitW.Y(), -unitW.X());
187 line.
liesOn = leftCutoff + unitW * fakeRadius * invTimeBoundaryObst;
188 ORCALines.push_back(line);
191 else if (t > 1.0f && tRight < 0.0f)
193 Vector unitW = (currV - rightCutoff)/(currV - rightCutoff).EuclideanNorm();
195 line.
dir =
Vector(unitW.Y(), -unitW.X());
196 line.
liesOn = rightCutoff + unitW * fakeRadius * invTimeBoundaryObst ;
197 ORCALines.push_back(line);
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());
205 if (cutoffSqDist <= lLegSqDist && cutoffSqDist <= rLegSqDist)
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);
212 else if (lLegSqDist <= rLegSqDist)
219 line.
dir = lLegDirection;
220 line.
liesOn = leftCutoff +
Point(-line.
dir.Y(), line.
dir.X()) * fakeRadius * invTimeBoundaryObst;;
221 ORCALines.push_back(line);
231 line.
dir = -rLegDirection;
232 line.
liesOn = rightCutoff +
Point(-line.
dir.Y(), line.
dir.X()) * fakeRadius * invTimeBoundaryObst;
233 ORCALines.push_back(line);
239 size_t numObstLines = ORCALines.size();
248 unsigned long minMaxNum = (param.agentsMaxNum < Neighbours.size()) ? param.agentsMaxNum : Neighbours.size();
251 for(
unsigned long i = 0; i < minMaxNum; i++)
253 auto Neighbour = Neighbours[i];
254 curragent =
dynamic_cast<ORCAAgent *
>(Neighbour.second);
255 auto circlecenter = curragent->position - this->position;
257 auto relvelocity = this->currV - curragent->currV;
259 float radiussum = fakeRadius + curragent->fakeRadius;
260 float radiussum2 = radiussum * radiussum;
261 float distSq = circlecenter.SquaredEuclideanNorm();
262 float trueSqRadSum = (param.radius + curragent->param.radius) * (param.radius + curragent->param.radius);
264 if(distSq < trueSqRadSum )
269 if(distSq >= radiussum2)
271 w = relvelocity - (circlecenter * invTimeBoundary);
272 float sqwlength = w.SquaredEuclideanNorm();
273 float wproj = w.ScalarProduct(circlecenter);
278 if(wproj < 0.0f && (wproj * wproj) > sqwlength * radiussum2)
280 const float wlength = std::sqrt(sqwlength);
281 const Vector nw = w / wlength;
283 u = nw * (radiussum * invTimeBoundary - wlength);
290 float leg = std::sqrt(distSq - radiussum2);
292 if(circlecenter.Det(w) > 0.0f)
294 currline.
dir =
Vector(circlecenter.X() * leg - circlecenter.Y() * radiussum, circlecenter.X() * radiussum + circlecenter.Y() * leg) / distSq;
298 currline.
dir = -(
Vector(circlecenter.X() * leg + circlecenter.Y() * radiussum, -circlecenter.X() * radiussum + circlecenter.Y() * leg) / distSq);
301 float rvproj = relvelocity.ScalarProduct(currline.
dir);
303 u = currline.
dir * rvproj - relvelocity;
308 const float invTimeStep = 1.0f / options->timestep;
310 Vector w = relvelocity - circlecenter * invTimeStep;
311 float wlength = w.EuclideanNorm();
314 u = wn * (radiussum * invTimeStep - wlength);
317 currline.
liesOn = this->currV + u * 0.5f;
318 ORCALines.push_back(currline);
319 Neighbours.pop_back();
323 if(lineFail < this->ORCALines.size())
341 if (planner->GetNext(position, next))
343 Vector goalVector = next - position;
345 if(next == goal && dist < options->delta)
353 goalVector = (goalVector/dist) * param.maxSpeed;
369 fakeRadius = obj.fakeRadius;
376 return this->
id == another.id;
381 return this->
id != another.id;
bool operator==(const ORCAAgent &another) const
Comparisons operator. Compares id of agents.
float SquaredEuclideanNorm() const
Computes squared euclidean norm of vector.
Agent & operator=(const Agent &obj)
Assignment operator.
void ApplyNewVelocity() override
Method for state updating and appling computed velocity.
Vector dir
Vector (right-left)/|right-left|.
Vector dir
direction vector of line.
float radius
Size of the agent (radius of the agent).
The class defines a line in 2D space.
ORCAAgent()
ORCAAgent default constructor.
ObstacleSegment * prev
Previous edge in obstacle.
float rEps
Buffer size (more about buffer see Main page).
The ObstacleSegment class defines an edge of an obstacle polygon.
The Point class defines a position (or euclidean vector from (0,0)) in 2D space.
Class AgentParam contains agent and algoritms parameters.
#define Vector
Vector type definition.
float EuclideanNorm() const
Computes euclidean norm of vector.
Agent class implements base agent interface and behavior.
bool operator!=(const ORCAAgent &another) const
Comparisons operator. Compares id of agents.
Class EnvironmentOptions contains environment and algoritms parameters.
bool IsConvex() const
Return convexity of vertex.
Map class describes static environment.
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...
void ComputeNewVelocity() override
Computes new velocity of agent using ORCA algorithm and linear programing.
float ScalarProduct(const Point &another) const
Computes scalar product of vectors (this * anoher)
ORCAAgent class implements agent with ORCA algoritm behavior.
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...
ORCAAgent * Clone() const override
Method for cloning objects. Creates copy of object in memmory and return pointer to copy...
ORCAAgent & operator=(const ORCAAgent &obj)
Assignment operator.
~ORCAAgent()
Virtual destructor.
bool UpdatePrefVelocity() override
Method for computing preffered velocity and chosing current goal from global path.
Point liesOn
point on line.
The Vertex class defines a vertex of an obstacle polygon.
#define CN_EPS
Epsilon for float number operations definition.