Mercurial Hosting > traffic-intelligence
comparison trafficintelligence/prediction.py @ 1212:af329f3330ba
work in progress on 3D safety analysis
author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
---|---|
date | Tue, 02 May 2023 17:11:24 -0400 |
parents | a095d4fbb2ea |
children | 01c24c1cdb70 |
comparison
equal
deleted
inserted
replaced
1211:a095d4fbb2ea | 1212:af329f3330ba |
---|---|
70 if nTimeSteps > 0 and not nTimeSteps in self.predictedPositions: | 70 if nTimeSteps > 0 and not nTimeSteps in self.predictedPositions: |
71 self.predictPosition(nTimeSteps-1) | 71 self.predictPosition(nTimeSteps-1) |
72 self.predictedPositions[nTimeSteps] = self.predictedPositions[nTimeSteps-1]+self.initialVelocity | 72 self.predictedPositions[nTimeSteps] = self.predictedPositions[nTimeSteps-1]+self.initialVelocity |
73 return self.predictedPositions[nTimeSteps] | 73 return self.predictedPositions[nTimeSteps] |
74 | 74 |
75 class PredictedPolyTrajectoryConstant(PredictedTrajectory): | 75 class PredictedPolyTrajectoryConstantVelocity(PredictedTrajectory): |
76 '''Predicted trajectory of an object with an outline represented by a polygon | 76 '''Predicted trajectory of an object with an outline represented by a polygon |
77 Simple method that just translates the polygon corners''' | 77 Simple method that just translates the polygon corners (set of moving.Point)''' |
78 def __init__(self, polyCorners, initialVelocity, probability = 1.): | 78 def __init__(self, polyCorners, initialVelocity, probability = 1.): |
79 self.probability = probability | 79 self.probability = probability |
80 self.predictedPositions = {0: polyCorners} | 80 self.predictedPositions = {0: moving.pointsToShapely(polyCorners)} |
81 self.initialVelocity = initialVelocity | 81 self.initialVelocity = initialVelocity |
82 self.predictedTrajectories = [PredictedTrajectoryConstant(p, initialVelocity) for p in polyCorners] | 82 self.predictedTrajectories = [PredictedTrajectoryConstantVelocity(p, initialVelocity) for p in polyCorners] |
83 | 83 |
84 def predictPosition(self, nTimeSteps): | |
85 if nTimeSteps > 0 and not nTimeSteps in self.predictedPositions: | |
86 self.predictedPositions[nTimeSteps] = moving.pointsToShapely([t.predictPosition(nTimeSteps) for t in self.predictedTrajectories]) | |
87 return self.predictedPositions[nTimeSteps] | |
88 | |
89 def hasCollisionWith(self, other, t, collisionDistanceThreshold): | |
90 poly1 = self.predictPosition(t) | |
91 poly2 = other.predictPosition(t) | |
92 return poly1.overlaps(poly2), poly1, poly2 | |
93 | |
84 class PredictedTrajectoryPrototype(PredictedTrajectory): | 94 class PredictedTrajectoryPrototype(PredictedTrajectory): |
85 '''Predicted trajectory that follows a prototype trajectory | 95 '''Predicted trajectory that follows a prototype trajectory |
86 The prototype is in the format of a moving.Trajectory: it could be | 96 The prototype is in the format of a moving.Trajectory: it could be |
87 1. an observed trajectory (extracted from video) | 97 1. an observed trajectory (extracted from video) |
88 2. a generic polyline (eg the road centerline) that a vehicle is supposed to follow | 98 2. a generic polyline (eg the road centerline) that a vehicle is supposed to follow |
194 while t < timeHorizon and not collision: | 204 while t < timeHorizon and not collision: |
195 t += 1 | 205 t += 1 |
196 collision, p1, p2 = predictedTrajectory1.hasCollisionWith(predictedTrajectory2, t, collisionDistanceThreshold) | 206 collision, p1, p2 = predictedTrajectory1.hasCollisionWith(predictedTrajectory2, t, collisionDistanceThreshold) |
197 return collision, t, p1, p2 | 207 return collision, t, p1, p2 |
198 | 208 |
199 def computeCollisionTimePolygon(predictedTrajectories1, predictedTrajectories2, timeHorizon): | |
200 '''Computes the first instant | |
201 at which two objects represented by a series of points (eg box) | |
202 Computes all the times including timeHorizon | |
203 | |
204 User has to check the first variable collision to know about a collision''' | |
205 t = 1 | |
206 poly1 = moving.pointsToShapely([t1.predictPosition(t) for t1 in predictedTrajectories1]) | |
207 poly2 = moving.pointsToShapely([t2.predictPosition(t) for t2 in predictedTrajectories2]) | |
208 collision = poly1.overlaps(poly2) | |
209 while t < timeHorizon and not collision: | |
210 t += 1 | |
211 poly1 = moving.pointsToShapely([t1.predictPosition(t) for t1 in predictedTrajectories1]) | |
212 poly2 = moving.pointsToShapely([t2.predictPosition(t) for t2 in predictedTrajectories2]) | |
213 collision = poly1.overlaps(poly2) | |
214 return collision, t | |
215 | |
216 def savePredictedTrajectoriesFigure(currentInstant, obj1, obj2, predictedTrajectories1, predictedTrajectories2, timeHorizon, printFigure = True): | 209 def savePredictedTrajectoriesFigure(currentInstant, obj1, obj2, predictedTrajectories1, predictedTrajectories2, timeHorizon, printFigure = True): |
217 from matplotlib.pyplot import figure, axis, title, clf, savefig | 210 from matplotlib.pyplot import figure, axis, title, clf, savefig |
218 if printFigure: | 211 if printFigure: |
219 clf() | 212 clf() |
220 else: | 213 else: |
312 prototypeTrajectories=findPrototypes(prototypes,nMatching,objects,route,partialObjPositions,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched) | 305 prototypeTrajectories=findPrototypes(prototypes,nMatching,objects,route,partialObjPositions,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched) |
313 return prototypeTrajectories | 306 return prototypeTrajectories |
314 | 307 |
315 | 308 |
316 class PredictionParameters(object): | 309 class PredictionParameters(object): |
317 def __init__(self, name, maxSpeed, useCurvilinear = False): | 310 def __init__(self, name, maxSpeed = None, useCurvilinear = False): |
318 self.name = name | 311 self.name = name |
319 self.maxSpeed = maxSpeed | 312 self.maxSpeed = maxSpeed |
320 self.useCurvilinear = useCurvilinear | 313 self.useCurvilinear = useCurvilinear |
321 | 314 |
322 def __str__(self): | 315 def __str__(self): |
323 return '{0} {1}'.format(self.name, self.maxSpeed) | 316 return '{0} {1}'.format(self.name, self.maxSpeed) |
324 | 317 |
325 def generatePredictedTrajectories(self, obj, instant): | 318 def generatePredictedTrajectories(self, obj, instant): |
326 return None | 319 return None |
320 | |
321 def computeCollisionPoint(self, p1, p2, probability, t): | |
322 return SafetyPoint((p1+p2)*0.5, probability, t) | |
327 | 323 |
328 def computeCrossingsCollisionsAtInstant(self, currentInstant, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False): | 324 def computeCrossingsCollisionsAtInstant(self, currentInstant, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False): |
329 '''returns the lists of collision points and crossing zones''' | 325 '''returns the lists of collision points and crossing zones''' |
330 predictedTrajectories1 = self.generatePredictedTrajectories(obj1, currentInstant) | 326 predictedTrajectories1 = self.generatePredictedTrajectories(obj1, currentInstant) |
331 predictedTrajectories2 = self.generatePredictedTrajectories(obj2, currentInstant) | 327 predictedTrajectories2 = self.generatePredictedTrajectories(obj2, currentInstant) |
337 crossingZones = None | 333 crossingZones = None |
338 for et1 in predictedTrajectories1: | 334 for et1 in predictedTrajectories1: |
339 for et2 in predictedTrajectories2: | 335 for et2 in predictedTrajectories2: |
340 collision, t, p1, p2 = computeCollisionTime(et1, et2, collisionDistanceThreshold, timeHorizon) | 336 collision, t, p1, p2 = computeCollisionTime(et1, et2, collisionDistanceThreshold, timeHorizon) |
341 if collision: | 337 if collision: |
342 collisionPoints.append(SafetyPoint((p1+p2)*0.5, et1.probability*et2.probability, t)) | 338 collisionPoints.append(self.computeCollisionPoint(p1, p2, et1.probability*et2.probability, t)) |
343 elif computeCZ: # check if there is a crossing zone | 339 elif computeCZ: # check if there is a crossing zone |
344 # TODO same computation as PET with metric + concatenate past trajectory with future trajectory | 340 # TODO same computation as PET with metric + concatenate past trajectory with future trajectory |
345 cz = None | 341 cz = None |
346 t1 = 0 | 342 t1 = 0 |
347 while not cz and t1 < timeHorizon: # t1 <= timeHorizon-1 | 343 while not cz and t1 < timeHorizon: # t1 <= timeHorizon-1 |
410 PredictionParameters.__init__(self, 'constant velocity') | 406 PredictionParameters.__init__(self, 'constant velocity') |
411 | 407 |
412 def generatePredictedTrajectories(self, obj, instant): | 408 def generatePredictedTrajectories(self, obj, instant): |
413 return [PredictedTrajectoryConstantVelocity(obj.getPositionAtInstant(instant), obj.getVelocityAtInstant(instant))] | 409 return [PredictedTrajectoryConstantVelocity(obj.getPositionAtInstant(instant), obj.getVelocityAtInstant(instant))] |
414 | 410 |
411 class ConstantPolyPredictionParameters(PredictionParameters): | |
412 def __init__(self): | |
413 PredictionParameters.__init__(self, 'constant velocity for polygon representation') | |
414 | |
415 def generatePredictedTrajectories(self, obj, instant): | |
416 return [PredictedPolyTrajectoryConstantVelocity(obj.getBoundingPolygon(instant), obj.getVelocityAtInstant(instant))] | |
417 | |
418 def computeCollisionPoint(self, p1, p2, probability, t): | |
419 polyRepr1 = p1.representative_point() | |
420 polyRepr2 = p2.representative_point() | |
421 p = moving.Point(polyRepr1.x+polyRepr2.x, polyRepr1.y+polyRepr2.y) | |
422 return SafetyPoint(p, probability, t) | |
423 | |
415 class NormalAdaptationPredictionParameters(PredictionParameters): | 424 class NormalAdaptationPredictionParameters(PredictionParameters): |
416 def __init__(self, maxSpeed, nPredictedTrajectories, accelerationDistribution, steeringDistribution, useFeatures = False): | 425 def __init__(self, maxSpeed, nPredictedTrajectories, accelerationDistribution, steeringDistribution, useFeatures = False): |
417 '''An example of acceleration and steering distributions is | 426 '''An example of acceleration and steering distributions is |
418 lambda: random.triangular(-self.maxAcceleration, self.maxAcceleration, 0.) | 427 lambda: random.triangular(-self.maxAcceleration, self.maxAcceleration, 0.) |
419 ''' | 428 ''' |
467 predictedTrajectories.append(PredictedTrajectoryConstantVelocity(initialPosition, initialVelocity, probability = probability)) | 476 predictedTrajectories.append(PredictedTrajectoryConstantVelocity(initialPosition, initialVelocity, probability = probability)) |
468 return predictedTrajectories | 477 return predictedTrajectories |
469 else: | 478 else: |
470 print('Object {} has no features'.format(obj.getNum())) | 479 print('Object {} has no features'.format(obj.getNum())) |
471 return None | 480 return None |
472 | |
473 | 481 |
474 class EvasiveActionPredictionParameters(PredictionParameters): | 482 class EvasiveActionPredictionParameters(PredictionParameters): |
475 def __init__(self, maxSpeed, nPredictedTrajectories, accelerationDistribution, steeringDistribution, useFeatures = False): | 483 def __init__(self, maxSpeed, nPredictedTrajectories, accelerationDistribution, steeringDistribution, useFeatures = False): |
476 '''Suggested acceleration distribution may not be symmetric, eg | 484 '''Suggested acceleration distribution may not be symmetric, eg |
477 lambda: random.triangular(self.minAcceleration, self.maxAcceleration, 0.)''' | 485 lambda: random.triangular(self.minAcceleration, self.maxAcceleration, 0.)''' |
506 moving.NormAngle(self.accelerationDistribution(), | 514 moving.NormAngle(self.accelerationDistribution(), |
507 self.steeringDistribution()), | 515 self.steeringDistribution()), |
508 probability, | 516 probability, |
509 self.maxSpeed)) | 517 self.maxSpeed)) |
510 return predictedTrajectories | 518 return predictedTrajectories |
511 | |
512 | 519 |
513 class CVDirectPredictionParameters(PredictionParameters): | 520 class CVDirectPredictionParameters(PredictionParameters): |
514 '''Prediction parameters of prediction at constant velocity | 521 '''Prediction parameters of prediction at constant velocity |
515 using direct computation of the intersecting point | 522 using direct computation of the intersecting point |
516 Warning: the computed time to collision may be higher than timeHorizon (not used)''' | 523 Warning: the computed time to collision may be higher than timeHorizon (not used)''' |