Mercurial > hg > nsaunier > traffic-intelligence
comparison python/events.py @ 708:a37c565f4b68
merged dev
| author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
|---|---|
| date | Wed, 22 Jul 2015 14:17:44 -0400 |
| parents | e395bffe1412 |
| children | 4e89341edd29 |
comparison
equal
deleted
inserted
replaced
| 707:7efa36b9bcfd | 708:a37c565f4b68 |
|---|---|
| 4 | 4 |
| 5 import moving, prediction, indicators, utils, cvutils | 5 import moving, prediction, indicators, utils, cvutils |
| 6 from base import VideoFilenameAddable | 6 from base import VideoFilenameAddable |
| 7 | 7 |
| 8 import numpy as np | 8 import numpy as np |
| 9 from numpy import arccos | |
| 10 | 9 |
| 11 import multiprocessing | 10 import multiprocessing |
| 12 import itertools | 11 import itertools |
| 13 | 12 |
| 14 | 13 |
| 88 '', | 87 '', |
| 89 's', | 88 's', |
| 90 '', | 89 '', |
| 91 ''] | 90 ''] |
| 92 | 91 |
| 92 timeIndicators = ['Time to Collision', 'predicted Post Encroachment Time'] | |
| 93 | |
| 93 def __init__(self, num = None, timeInterval = None, roaduserNum1 = None, roaduserNum2 = None, roadUser1 = None, roadUser2 = None, categoryNum = None): | 94 def __init__(self, num = None, timeInterval = None, roaduserNum1 = None, roaduserNum2 = None, roadUser1 = None, roadUser2 = None, categoryNum = None): |
| 94 moving.STObject.__init__(self, num, timeInterval) | 95 moving.STObject.__init__(self, num, timeInterval) |
| 95 if timeInterval is None and roadUser1 is not None and roadUser2 is not None: | 96 if timeInterval is None and roadUser1 is not None and roadUser2 is not None: |
| 96 self.timeInterval = roadUser1.commonTimeInterval(roadUser2) | 97 self.timeInterval = roadUser1.commonTimeInterval(roadUser2) |
| 97 self.roadUser1 = roadUser1 | 98 self.roadUser1 = roadUser1 |
| 111 | 112 |
| 112 def getRoadUserNumbers(self): | 113 def getRoadUserNumbers(self): |
| 113 return self.roadUserNumbers | 114 return self.roadUserNumbers |
| 114 | 115 |
| 115 def setRoadUsers(self, objects): | 116 def setRoadUsers(self, objects): |
| 116 nums = list(self.getRoadUserNumbers()) | 117 nums = sorted(list(self.getRoadUserNumbers())) |
| 117 if objects[nums[0]].getNum() == nums[0]: | 118 if nums[0]<len(objects) and objects[nums[0]].getNum() == nums[0]: |
| 118 self.roadUser1 = objects[nums[0]] | 119 self.roadUser1 = objects[nums[0]] |
| 119 if objects[nums[1]].getNum() == nums[1]: | 120 if nums[1]<len(objects) and objects[nums[1]].getNum() == nums[1]: |
| 120 self.roadUser2 = objects[nums[1]] | 121 self.roadUser2 = objects[nums[1]] |
| 121 | 122 |
| 122 i = 0 | 123 if self.roadUser1 is None or self.roadUser2 is None: |
| 123 while i < len(objects) and self.roadUser2 is None: | 124 self.roadUser1 = None |
| 124 if objects[i].getNum() in nums: | 125 self.roadUser2 = None |
| 125 if self.roadUser1 is None: | 126 i = 0 |
| 126 self.roadUser1 = objects[i] | 127 while i < len(objects) and self.roadUser2 is None: |
| 127 else: | 128 if objects[i].getNum() in nums: |
| 128 self.roadUser2 = objects[i] | 129 if self.roadUser1 is None: |
| 129 i += 1 | 130 self.roadUser1 = objects[i] |
| 131 else: | |
| 132 self.roadUser2 = objects[i] | |
| 133 i += 1 | |
| 130 | 134 |
| 131 def getIndicator(self, indicatorName): | 135 def getIndicator(self, indicatorName): |
| 132 return self.indicators.get(indicatorName, None) | 136 return self.indicators.get(indicatorName, None) |
| 133 | 137 |
| 134 def addIndicator(self, indicator): | 138 def addIndicator(self, indicator): |
| 175 for instant in self.timeInterval: | 179 for instant in self.timeInterval: |
| 176 deltap = self.roadUser1.getPositionAtInstant(instant)-self.roadUser2.getPositionAtInstant(instant) | 180 deltap = self.roadUser1.getPositionAtInstant(instant)-self.roadUser2.getPositionAtInstant(instant) |
| 177 v1 = self.roadUser1.getVelocityAtInstant(instant) | 181 v1 = self.roadUser1.getVelocityAtInstant(instant) |
| 178 v2 = self.roadUser2.getVelocityAtInstant(instant) | 182 v2 = self.roadUser2.getVelocityAtInstant(instant) |
| 179 deltav = v2-v1 | 183 deltav = v2-v1 |
| 180 velocityAngles[instant] = arccos(moving.Point.dot(v1, v2)/(v1.norm2()*v2.norm2())) | 184 velocityAngles[instant] = np.arccos(moving.Point.dot(v1, v2)/(v1.norm2()*v2.norm2())) |
| 181 collisionCourseDotProducts[instant] = moving.Point.dot(deltap, deltav) | 185 collisionCourseDotProducts[instant] = moving.Point.dot(deltap, deltav) |
| 182 distances[instant] = deltap.norm2() | 186 distances[instant] = deltap.norm2() |
| 183 speedDifferentials[instant] = deltav.norm2() | 187 speedDifferentials[instant] = deltav.norm2() |
| 184 if collisionCourseDotProducts[instant] > 0: | 188 if collisionCourseDotProducts[instant] > 0: |
| 185 interactionInstants.append(instant) | 189 interactionInstants.append(instant) |
| 186 if distances[instant] != 0 and speedDifferentials[instant] != 0: | 190 if distances[instant] != 0 and speedDifferentials[instant] != 0: |
| 187 collisionCourseAngles[instant] = arccos(collisionCourseDotProducts[instant]/(distances[instant]*speedDifferentials[instant])) | 191 collisionCourseAngles[instant] = np.arccos(collisionCourseDotProducts[instant]/(distances[instant]*speedDifferentials[instant])) |
| 188 | 192 |
| 189 if len(interactionInstants) >= 2: | 193 if len(interactionInstants) >= 2: |
| 190 self.interactionInterval = moving.TimeInterval(interactionInstants[0], interactionInstants[-1]) | 194 self.interactionInterval = moving.TimeInterval(interactionInstants[0], interactionInstants[-1]) |
| 191 else: | 195 else: |
| 192 self.interactionInterval = moving.TimeInterval() | 196 self.interactionInterval = moving.TimeInterval() |
| 193 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[0], collisionCourseDotProducts)) | 197 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[0], collisionCourseDotProducts)) |
| 194 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[1], collisionCourseAngles)) | 198 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[1], collisionCourseAngles)) |
| 195 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[2], distances)) | 199 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[2], distances, mostSevereIsMax = False)) |
| 196 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[4], velocityAngles)) | 200 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[4], velocityAngles)) |
| 197 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[5], speedDifferentials)) | 201 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[5], speedDifferentials)) |
| 198 | 202 |
| 199 # if we have features, compute other indicators | 203 # if we have features, compute other indicators |
| 200 if self.roadUser1.hasFeatures() and self.roadUser2.hasFeatures(): | 204 if self.roadUser1.hasFeatures() and self.roadUser2.hasFeatures(): |
| 201 minDistance={} | 205 minDistances={} |
| 202 for instant in self.timeInterval: | 206 for instant in self.timeInterval: |
| 203 minDistance[instant] = moving.MovingObject.minDistance(self.roadUser1, self.roadUser2, instant) | 207 minDistances[instant] = moving.MovingObject.minDistance(self.roadUser1, self.roadUser2, instant) |
| 204 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[3], minDistance)) | 208 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[3], minDistances, mostSevereIsMax = False)) |
| 205 | 209 |
| 206 def computeCrossingsCollisions(self, predictionParameters, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False, timeInterval = None, nProcesses = 1, usePrototypes=False, route1= (-1,-1), route2=(-1,-1), prototypes={}, secondStepPrototypes={}, nMatching={}, objects=[], noiseEntryNums=[], noiseExitNums=[], minSimilarity=0.1, mostMatched=None, useDestination=True, useSpeedPrototype=True, acceptPartialLength=30, step=1): | 210 def computeCrossingsCollisions(self, predictionParameters, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False, timeInterval = None, nProcesses = 1, usePrototypes=False, route1= (-1,-1), route2=(-1,-1), prototypes={}, secondStepPrototypes={}, nMatching={}, objects=[], noiseEntryNums=[], noiseExitNums=[], minSimilarity=0.1, mostMatched=None, useDestination=True, useSpeedPrototype=True, acceptPartialLength=30, step=1): |
| 207 '''Computes all crossing and collision points at each common instant for two road users. ''' | 211 '''Computes all crossing and collision points at each common instant for two road users. ''' |
| 208 TTCs = {} | 212 TTCs = {} |
| 209 if usePrototypes: | 213 if usePrototypes: |
| 215 else: | 219 else: |
| 216 commonTimeInterval = self.timeInterval | 220 commonTimeInterval = self.timeInterval |
| 217 self.collisionPoints, crossingZones = predictionParameters.computeCrossingsCollisions(self.roadUser1, self.roadUser2, collisionDistanceThreshold, timeHorizon, computeCZ, debug, commonTimeInterval, nProcesses,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype,acceptPartialLength, step) | 221 self.collisionPoints, crossingZones = predictionParameters.computeCrossingsCollisions(self.roadUser1, self.roadUser2, collisionDistanceThreshold, timeHorizon, computeCZ, debug, commonTimeInterval, nProcesses,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype,acceptPartialLength, step) |
| 218 for i, cp in self.collisionPoints.iteritems(): | 222 for i, cp in self.collisionPoints.iteritems(): |
| 219 TTCs[i] = prediction.SafetyPoint.computeExpectedIndicator(cp) | 223 TTCs[i] = prediction.SafetyPoint.computeExpectedIndicator(cp) |
| 220 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[7], TTCs, mostSevereIsMax=False)) | 224 if len(TTCs) > 0: |
| 225 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[7], TTCs, mostSevereIsMax=False)) | |
| 221 | 226 |
| 222 # crossing zones and pPET | 227 # crossing zones and pPET |
| 223 if computeCZ: | 228 if computeCZ: |
| 224 self.crossingZones[predictionParameters.name] = crossingZones | 229 self.crossingZones = crossingZones |
| 225 pPETs = {} | 230 pPETs = {} |
| 226 for i, cz in self.crossingZones.iteritems(): | 231 for i, cz in self.crossingZones.iteritems(): |
| 227 pPETs[i] = prediction.SafetyPoint.computeExpectedIndicator(cz) | 232 pPETs[i] = prediction.SafetyPoint.computeExpectedIndicator(cz) |
| 228 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[9], pPETs, mostSevereIsMax=False)) | 233 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[9], pPETs, mostSevereIsMax=False)) |
| 229 # TODO add probability of collision, and probability of successful evasive action | 234 # TODO add probability of collision, and probability of successful evasive action |
| 240 if hasattr(self, 'collision'): | 245 if hasattr(self, 'collision'): |
| 241 return self.collision | 246 return self.collision |
| 242 else: | 247 else: |
| 243 return None | 248 return None |
| 244 | 249 |
| 245 def getCrossingZones(self, predictionMethodName): | 250 def getCollisionPoints(self): |
| 246 if self.crossingZones is not None: | 251 return self.collisionPoints |
| 247 return self.crossingZones[predictionMethodName] | 252 |
| 248 else: | 253 def getCrossingZones(self): |
| 249 return None | 254 return self.crossingZones |
| 250 | |
| 251 def getCollisionPoints(self, predictionMethodName): | |
| 252 if self.collisionPoints is not None: | |
| 253 return self.collisionPoints[predictionMethodName] | |
| 254 else: | |
| 255 return None | |
| 256 | |
| 257 | 255 |
| 258 def createInteractions(objects, _others = None): | 256 def createInteractions(objects, _others = None): |
| 259 '''Create all interactions of two co-existing road users''' | 257 '''Create all interactions of two co-existing road users''' |
| 260 if _others is not None: | 258 if _others is not None: |
| 261 others = _others | 259 others = _others |
| 280 if i<len(interactions): | 278 if i<len(interactions): |
| 281 return interactions[i] | 279 return interactions[i] |
| 282 else: | 280 else: |
| 283 return None | 281 return None |
| 284 | 282 |
| 285 def aggregateSafetyPoints(interactions, predictionMethodName = None, pointType = 'collision'): | 283 def aggregateSafetyPoints(interactions, pointType = 'collision'): |
| 286 '''Put all collision points or crossing zones in a list for display''' | 284 '''Put all collision points or crossing zones in a list for display''' |
| 287 if predictionMethodName is None and len(interactions)>0: | |
| 288 predictionMethodName = interactions[0].collisionPoints.keys()[0] | |
| 289 | |
| 290 allPoints = [] | 285 allPoints = [] |
| 291 if pointType == 'collision': | 286 if pointType == 'collision': |
| 292 for i in interactions: | 287 for i in interactions: |
| 293 for points in i.collisionPoints[predictionMethodName].values(): | 288 for points in i.collisionPoints.values(): |
| 294 allPoints += points | 289 allPoints += points |
| 295 elif pointType == 'crossing': | 290 elif pointType == 'crossing': |
| 296 for i in interactions: | 291 for i in interactions: |
| 297 for points in i.crossingZones[predictionMethodName].values(): | 292 for points in i.crossingZones.values(): |
| 298 allPoints += points | 293 allPoints += points |
| 299 else: | 294 else: |
| 300 print('unknown type of point '+pointType) | 295 print('unknown type of point: '+pointType) |
| 301 return allPoints | 296 return allPoints |
| 302 | 297 |
| 303 def prototypeCluster(interactions, similarityMatrix, alignmentMatrix, indicatorName, minSimilarity): | 298 def prototypeCluster(interactions, similarityMatrix, alignmentMatrix, indicatorName, minSimilarity): |
| 304 '''Finds exemplar indicator time series for all interactions | 299 '''Finds exemplar indicator time series for all interactions |
| 305 Returns the prototype indices (in the interaction list) and the label of each indicator (interaction) | 300 Returns the prototype indices (in the interaction list) and the label of each indicator (interaction) |
| 341 if any interaction indicator time series is different enough (<minSimilarity), | 336 if any interaction indicator time series is different enough (<minSimilarity), |
| 342 it will become a new prototype. | 337 it will become a new prototype. |
| 343 Non-prototype interactions will be assigned to an existing prototype if all indicators are similar enough''' | 338 Non-prototype interactions will be assigned to an existing prototype if all indicators are similar enough''' |
| 344 pass | 339 pass |
| 345 | 340 |
| 346 # TODO: | |
| 347 #http://stackoverflow.com/questions/3288595/multiprocessing-using-pool-map-on-a-function-defined-in-a-class | |
| 348 #http://www.rueckstiess.net/research/snippets/show/ca1d7d90 | |
| 349 def calculateIndicatorPipe(pairs, predParam, timeHorizon=75,collisionDistanceThreshold=1.8): | |
| 350 collisionPoints, crossingZones = prediction.computeCrossingsCollisions(pairs.roadUser1, pairs.roadUser2, predParam, collisionDistanceThreshold, timeHorizon) | |
| 351 #print pairs.num | |
| 352 # Ignore empty collision points | |
| 353 empty = 1 | |
| 354 for i in collisionPoints: | |
| 355 if(collisionPoints[i] != []): | |
| 356 empty = 0 | |
| 357 if(empty == 1): | |
| 358 pairs.hasCP = 0 | |
| 359 else: | |
| 360 pairs.hasCP = 1 | |
| 361 pairs.CP = collisionPoints | |
| 362 | |
| 363 # Ignore empty crossing zones | |
| 364 empty = 1 | |
| 365 for i in crossingZones: | |
| 366 if(crossingZones[i] != []): | |
| 367 empty = 0 | |
| 368 if(empty == 1): | |
| 369 pairs.hasCZ = 0 | |
| 370 else: | |
| 371 pairs.hasCZ = 1 | |
| 372 pairs.CZ = crossingZones | |
| 373 return pairs | |
| 374 | |
| 375 def calculateIndicatorPipe_star(a_b): | |
| 376 """Convert `f([1,2])` to `f(1,2)` call.""" | |
| 377 return calculateIndicatorPipe(*a_b) | |
| 378 | |
| 379 class VehPairs(): | |
| 380 '''Create a veh-pairs object from objects list''' | |
| 381 def __init__(self,objects): | |
| 382 self.pairs = createInteractions(objects) | |
| 383 self.interactionCount = 0 | |
| 384 self.CPcount = 0 | |
| 385 self.CZcount = 0 | |
| 386 | |
| 387 # Process indicator calculation with support for multi-threading | |
| 388 def calculateIndicators(self,predParam,threads=1,timeHorizon=75,collisionDistanceThreshold=1.8): | |
| 389 if(threads > 1): | |
| 390 pool = multiprocessing.Pool(threads) | |
| 391 self.pairs = pool.map(calculateIndicatorPipe_star, itertools.izip(self.pairs, itertools.repeat(predParam))) | |
| 392 pool.close() | |
| 393 else: | |
| 394 #prog = Tools.ProgressBar(0, len(self.pairs), 77) #Removed in traffic-intelligenc port | |
| 395 for j in xrange(len(self.pairs)): | |
| 396 #prog.updateAmount(j) #Removed in traffic-intelligenc port | |
| 397 collisionPoints, crossingZones = prediction.computeCrossingsCollisions(self.pairs[j].roadUser1, self.pairs[j].roadUser2, predParam, collisionDistanceThreshold, timeHorizon) | |
| 398 | |
| 399 # Ignore empty collision points | |
| 400 empty = 1 | |
| 401 for i in collisionPoints: | |
| 402 if(collisionPoints[i] != []): | |
| 403 empty = 0 | |
| 404 if(empty == 1): | |
| 405 self.pairs[j].hasCP = 0 | |
| 406 else: | |
| 407 self.pairs[j].hasCP = 1 | |
| 408 self.pairs[j].CP = collisionPoints | |
| 409 | |
| 410 # Ignore empty crossing zones | |
| 411 empty = 1 | |
| 412 for i in crossingZones: | |
| 413 if(crossingZones[i] != []): | |
| 414 empty = 0 | |
| 415 if(empty == 1): | |
| 416 self.pairs[j].hasCZ = 0 | |
| 417 else: | |
| 418 self.pairs[j].hasCZ = 1 | |
| 419 self.pairs[j].CZ = crossingZones | |
| 420 | |
| 421 for j in self.pairs: | |
| 422 self.interactionCount = self.interactionCount + len(j.CP) | |
| 423 self.CPcount = len(self.getCPlist()) | |
| 424 self.Czcount = len(self.getCZlist()) | |
| 425 | |
| 426 | |
| 427 def getPairsWCP(self): | |
| 428 lists = [] | |
| 429 for j in self.pairs: | |
| 430 if(j.hasCP): | |
| 431 lists.append(j.num) | |
| 432 return lists | |
| 433 | |
| 434 def getPairsWCZ(self): | |
| 435 lists = [] | |
| 436 for j in self.pairs: | |
| 437 if(j.hasCZ): | |
| 438 lists.append(j.num) | |
| 439 return lists | |
| 440 | |
| 441 def getCPlist(self,indicatorThreshold=float('Inf')): | |
| 442 lists = [] | |
| 443 for j in self.pairs: | |
| 444 if(j.hasCP): | |
| 445 for k in j.CP: | |
| 446 if(j.CP[k] != [] and j.CP[k][0].indicator < indicatorThreshold): | |
| 447 lists.append([k,j.CP[k][0]]) | |
| 448 return lists | |
| 449 | |
| 450 def getCZlist(self,indicatorThreshold=float('Inf')): | |
| 451 lists = [] | |
| 452 for j in self.pairs: | |
| 453 if(j.hasCZ): | |
| 454 for k in j.CZ: | |
| 455 if(j.CZ[k] != [] and j.CZ[k][0].indicator < indicatorThreshold): | |
| 456 lists.append([k,j.CZ[k][0]]) | |
| 457 return lists | |
| 458 | |
| 459 def genIndicatorHistogram(self, CPlist=False, bins=range(0,100,1)): | |
| 460 if(not CPlist): | |
| 461 CPlist = self.getCPlist() | |
| 462 if(not CPlist): | |
| 463 return False | |
| 464 TTC_list = [] | |
| 465 for i in CPlist: | |
| 466 TTC_list.append(i[1].indicator) | |
| 467 histo = np.histogram(TTC_list,bins=bins) | |
| 468 histo += (histo[0].astype(float)/np.sum(histo[0]),) | |
| 469 return histo | |
| 470 | 341 |
| 471 class Crossing(moving.STObject): | 342 class Crossing(moving.STObject): |
| 472 '''Class for the event of a street crossing | 343 '''Class for the event of a street crossing |
| 473 | 344 |
| 474 TODO: detecter passage sur la chaussee | 345 TODO: detecter passage sur la chaussee |
