Mercurial > hg > nsaunier > traffic-intelligence
comparison python/events.py @ 614:5e09583275a4
Merged Nicolas/trafficintelligence into default
| author | Mohamed Gomaa <eng.m.gom3a@gmail.com> |
|---|---|
| date | Fri, 05 Dec 2014 12:13:53 -0500 |
| parents | 07b1bd0785cd |
| children | 84690dfe5560 |
comparison
equal
deleted
inserted
replaced
| 598:11f96bd08552 | 614:5e09583275a4 |
|---|---|
| 6 from numpy import arccos | 6 from numpy import arccos |
| 7 | 7 |
| 8 import multiprocessing | 8 import multiprocessing |
| 9 import itertools | 9 import itertools |
| 10 | 10 |
| 11 import moving | 11 import moving, prediction, indicators, utils |
| 12 import prediction | |
| 13 import indicators | |
| 14 | 12 |
| 15 __metaclass__ = type | 13 __metaclass__ = type |
| 16 | 14 |
| 17 class Interaction(moving.STObject): | 15 class Interaction(moving.STObject): |
| 18 '''Class for an interaction between two road users | 16 '''Class for an interaction between two road users |
| 20 | 18 |
| 21 link to the moving objects | 19 link to the moving objects |
| 22 contains the indicators in a dictionary with the names as keys | 20 contains the indicators in a dictionary with the names as keys |
| 23 ''' | 21 ''' |
| 24 | 22 |
| 25 categories = {'headon': 0, | 23 categories = {'Head On': 0, |
| 26 'rearend': 1, | 24 'rearend': 1, |
| 27 'side': 2, | 25 'side': 2, |
| 28 'parallel': 3} | 26 'parallel': 3} |
| 29 | 27 |
| 30 def __init__(self, num = None, timeInterval = None, roaduserNum1 = None, roaduserNum2 = None, movingObject1 = None, movingObject2 = None, categoryNum = None): | 28 indicatorNames = ['Collision Course Dot Product', |
| 29 'Collision Course Angle', | |
| 30 'Distance', | |
| 31 'Minimum Distance', | |
| 32 'Velocity Angle', | |
| 33 'Speed Differential', | |
| 34 'Collision Probability', | |
| 35 'Time to Collision', | |
| 36 'Probability of Successful Evasive Action', | |
| 37 'predicted Post Encroachment Time'] | |
| 38 | |
| 39 indicatorNameToIndices = utils.inverseEnumeration(indicatorNames) | |
| 40 | |
| 41 indicatorShortNames = ['CCDP', | |
| 42 'CCA', | |
| 43 'Dist', | |
| 44 'MinDist', | |
| 45 'VA', | |
| 46 'SD', | |
| 47 'PoC', | |
| 48 'TTC', | |
| 49 'P(SEA)', | |
| 50 'pPET'] | |
| 51 | |
| 52 indicatorUnits = ['', | |
| 53 'rad', | |
| 54 'm', | |
| 55 'm', | |
| 56 'rad', | |
| 57 'm/s', | |
| 58 '', | |
| 59 's', | |
| 60 '', | |
| 61 ''] | |
| 62 | |
| 63 def __init__(self, num = None, timeInterval = None, roaduserNum1 = None, roaduserNum2 = None, roadUser1 = None, roadUser2 = None, categoryNum = None): | |
| 31 moving.STObject.__init__(self, num, timeInterval) | 64 moving.STObject.__init__(self, num, timeInterval) |
| 32 self.roaduserNumbers = set([roaduserNum1, roaduserNum2]) | 65 if timeInterval == None and roadUser1 != None and roadUser2 != None: |
| 33 self.movingObject1 = movingObject1 | 66 self.timeInterval = roadUser1.commonTimeInterval(roadUser2) |
| 34 self.movingObject2 = movingObject2 | 67 self.roadUser1 = roadUser1 |
| 68 self.roadUser2 = roadUser2 | |
| 69 if roaduserNum1 != None and roaduserNum2 != None: | |
| 70 self.roadUserNumbers = set([roaduserNum1, roaduserNum2]) | |
| 71 elif roadUser1 != None and roadUser2 != None: | |
| 72 self.roadUserNumbers = set(roadUser1.getNum(), roadUser2.getNum()) | |
| 73 else: | |
| 74 self.roadUserNumbers = None | |
| 35 self.categoryNum = categoryNum | 75 self.categoryNum = categoryNum |
| 36 self.indicators = {} | 76 self.indicators = {} |
| 77 self.interactionInterval = None | |
| 78 | |
| 79 def getRoadUserNumbers(self): | |
| 80 return self.roadUserNumbers | |
| 37 | 81 |
| 38 def getIndicator(self, indicatorName): | 82 def getIndicator(self, indicatorName): |
| 39 return self.indicators[indicatorName] | 83 return self.indicators.get(indicatorName, None) |
| 40 | 84 |
| 41 def addIndicator(self, indicator): | 85 def addIndicator(self, indicator): |
| 42 self.indicators[indicator.name] = indicator | 86 if indicator: |
| 87 self.indicators[indicator.name] = indicator | |
| 43 | 88 |
| 44 def computeIndicators(self): | 89 def computeIndicators(self): |
| 45 '''Computes the collision course cosine only if the cosine is positive''' | 90 '''Computes the collision course cosine only if the cosine is positive''' |
| 46 collisionCourseDotProducts = {}#[0]*int(self.timeInterval.length()) | 91 collisionCourseDotProducts = {}#[0]*int(self.timeInterval.length()) |
| 47 collisionCourseCosines = {} | 92 collisionCourseAngles = {} |
| 93 velocityAngles = {} | |
| 48 distances = {}#[0]*int(self.timeInterval.length()) | 94 distances = {}#[0]*int(self.timeInterval.length()) |
| 49 speedDifferentials = {} | 95 speedDifferentials = {} |
| 96 interactionInstants = [] | |
| 50 for instant in self.timeInterval: | 97 for instant in self.timeInterval: |
| 51 deltap = self.movingObject1.getPositionAtInstant(instant)-self.movingObject2.getPositionAtInstant(instant) | 98 deltap = self.roadUser1.getPositionAtInstant(instant)-self.roadUser2.getPositionAtInstant(instant) |
| 52 deltav = self.movingObject2.getVelocityAtInstant(instant)-self.movingObject1.getVelocityAtInstant(instant) | 99 v1 = self.roadUser1.getVelocityAtInstant(instant) |
| 100 v2 = self.roadUser2.getVelocityAtInstant(instant) | |
| 101 deltav = v2-v1 | |
| 102 velocityAngles[instant] = arccos(moving.Point.dot(v1, v2)/(v1.norm2()*v2.norm2())) | |
| 53 collisionCourseDotProducts[instant] = moving.Point.dot(deltap, deltav) | 103 collisionCourseDotProducts[instant] = moving.Point.dot(deltap, deltav) |
| 54 distances[instant] = deltap.norm2() # todo compute closest feature distance, if features | 104 distances[instant] = deltap.norm2() |
| 55 speedDifferentials[instant] = deltav.norm2() | 105 speedDifferentials[instant] = deltav.norm2() |
| 56 if collisionCourseDotProducts[instant] > 0: | 106 if collisionCourseDotProducts[instant] > 0: |
| 57 collisionCourseCosines[instant] = arccos(collisionCourseDotProducts[instant]/(distances[instant]*speedDifferentials[instant])) | 107 interactionInstants.append(instant) |
| 58 | 108 collisionCourseAngles[instant] = arccos(collisionCourseDotProducts[instant]/(distances[instant]*speedDifferentials[instant])) |
| 59 # todo shorten the time intervals based on the interaction definition | 109 |
| 60 self.addIndicator(indicators.SeverityIndicator('Collision Course Dot Product', collisionCourseDotProducts)) | 110 if len(interactionInstants) >= 2: |
| 61 self.addIndicator(indicators.SeverityIndicator('Distance', distances)) | 111 self.interactionInterval = moving.TimeInterval(interactionInstants[0], interactionInstants[-1]) |
| 62 self.addIndicator(indicators.SeverityIndicator('Speed Differential', speedDifferentials)) | 112 else: |
| 63 self.addIndicator(indicators.SeverityIndicator('Collision Course Cosine', collisionCourseCosines)) | 113 self.interactionInterval = moving.TimeInterval() |
| 64 | 114 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[0], collisionCourseDotProducts)) |
| 65 # todo test for interaction instants and interval, compute indicators | 115 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[1], collisionCourseAngles)) |
| 116 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[2], distances)) | |
| 117 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[4], velocityAngles)) | |
| 118 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[5], speedDifferentials)) | |
| 119 | |
| 120 # if we have features, compute other indicators | |
| 121 if len(self.roadUser1.features) != 0 and len(self.roadUser2.features) != 0: | |
| 122 minDistance={} | |
| 123 for instant in self.timeInterval: | |
| 124 minDistance[instant] = moving.MovingObject.minDistance(self.roadUser1, self.roadUser2, instant) | |
| 125 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[3], minDistance)) | |
| 126 | |
| 127 def computeCrossingsCollisions(self, predictionParameters, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False, timeInterval = None, nProcesses = 1): | |
| 128 '''Computes all crossing and collision points at each common instant for two road users. ''' | |
| 129 self.collisionPoints={} | |
| 130 self.crossingZones={} | |
| 131 TTCs = {} | |
| 132 | |
| 133 if timeInterval: | |
| 134 commonTimeInterval = timeInterval | |
| 135 else: | |
| 136 commonTimeInterval = self.timeInterval | |
| 137 self.collisionPoints, self.crossingZones = prediction.computeCrossingsCollisions(predictionParameters, self.roadUser1, self.roadUser2, collisionDistanceThreshold, timeHorizon, computeCZ, debug, commonTimeInterval, nProcesses) | |
| 138 for i, cp in self.collisionPoints.iteritems(): | |
| 139 TTCs[i] = prediction.SafetyPoint.computeExpectedIndicator(cp) | |
| 140 # add probability of collision, and probability of successful evasive action | |
| 141 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[7], TTCs)) | |
| 142 | |
| 143 if computeCZ: | |
| 144 pPETs = {} | |
| 145 for i in list(commonTimeInterval)[:-1]: | |
| 146 if len(self.crossingZones[i]) > 0: | |
| 147 pPETs[i] = prediction.SafetyPoint.computeExpectedIndicator(self.crossingZones[i]) | |
| 148 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[9], pPETs)) | |
| 66 | 149 |
| 67 def addVideoFilename(self,videoFilename): | 150 def addVideoFilename(self,videoFilename): |
| 68 self.videoFilename= videoFilename | 151 self.videoFilename= videoFilename |
| 69 | 152 |
| 70 def addInteractionType(self,interactionType): | 153 def addInteractionType(self,interactionType): |
| 71 ''' interaction types: conflict or collision if they are known''' | 154 ''' interaction types: conflict or collision if they are known''' |
| 72 self.interactionType= interactionType | 155 self.interactionType= interactionType |
| 73 | 156 |
| 74 def createInteractions(objects): | 157 def createInteractions(objects, _others = None): |
| 75 '''Create all interactions of two co-existing road users | 158 '''Create all interactions of two co-existing road users''' |
| 76 | 159 if _others != None: |
| 77 todo add test to compute categories?''' | 160 others = _others |
| 161 | |
| 78 interactions = [] | 162 interactions = [] |
| 79 num = 0 | 163 num = 0 |
| 80 for i in xrange(len(objects)): | 164 for i in xrange(len(objects)): |
| 81 for j in xrange(i): | 165 if _others == None: |
| 82 commonTimeInterval = objects[i].commonTimeInterval(objects[j]) | 166 others = objects[:i] |
| 167 for j in xrange(len(others)): | |
| 168 commonTimeInterval = objects[i].commonTimeInterval(others[j]) | |
| 83 if not commonTimeInterval.empty(): | 169 if not commonTimeInterval.empty(): |
| 84 interactions.append(Interaction(num, commonTimeInterval, objects[i].num, objects[j].num, objects[i], objects[j])) | 170 interactions.append(Interaction(num, commonTimeInterval, objects[i].num, others[j].num, objects[i], others[j])) |
| 85 num += 1 | 171 num += 1 |
| 86 return interactions | 172 return interactions |
| 87 | 173 |
| 174 def prototypeCluster(interactions, similarityMatrix, alignmentMatrix, indicatorName, minSimilarity): | |
| 175 '''Finds exemplar indicator time series for all interactions | |
| 176 Returns the prototype indices (in the interaction list) and the label of each indicator (interaction) | |
| 177 | |
| 178 if an indicator profile (time series) is different enough (<minSimilarity), | |
| 179 it will become a new prototype. | |
| 180 Non-prototype interactions will be assigned to an existing prototype''' | |
| 181 | |
| 182 # sort indicators based on length | |
| 183 indices = range(similarityMatrix.shape[0]) | |
| 184 def compare(i, j): | |
| 185 if len(interactions[i].getIndicator(indicatorName)) > len(interactions[j].getIndicator(indicatorName)): | |
| 186 return -1 | |
| 187 elif len(interactions[i].getIndicator(indicatorName)) == len(interactions[j].getIndicator(indicatorName)): | |
| 188 return 0 | |
| 189 else: | |
| 190 return 1 | |
| 191 indices.sort(compare) | |
| 192 # go through all indicators | |
| 193 prototypeIndices = [indices[0]] | |
| 194 for i in indices[1:]: | |
| 195 if similarityMatrix[i][prototypeIndices].max() < minSimilarity: | |
| 196 prototypeIndices.append(i) | |
| 197 | |
| 198 # assignment | |
| 199 labels = [-1]*similarityMatrix.shape[0] | |
| 200 indices = [i for i in range(similarityMatrix.shape[0]) if i not in prototypeIndices] | |
| 201 for i in prototypeIndices: | |
| 202 labels[i] = i | |
| 203 for i in indices: | |
| 204 prototypeIndex = similarityMatrix[i][prototypeIndices].argmax() | |
| 205 labels[i] = prototypeIndices[prototypeIndex] | |
| 206 | |
| 207 return prototypeIndices, labels | |
| 208 | |
| 209 def prototypeMultivariateCluster(interactions, similarityMatrics, indicatorNames, minSimilarities, minClusterSize): | |
| 210 '''Finds exmaple indicator time series (several indicators) for all interactions | |
| 211 | |
| 212 if any interaction indicator time series is different enough (<minSimilarity), | |
| 213 it will become a new prototype. | |
| 214 Non-prototype interactions will be assigned to an existing prototype if all indicators are similar enough''' | |
| 215 pass | |
| 88 | 216 |
| 89 # TODO: | 217 # TODO: |
| 90 #http://stackoverflow.com/questions/3288595/multiprocessing-using-pool-map-on-a-function-defined-in-a-class | 218 #http://stackoverflow.com/questions/3288595/multiprocessing-using-pool-map-on-a-function-defined-in-a-class |
| 91 #http://www.rueckstiess.net/research/snippets/show/ca1d7d90 | 219 #http://www.rueckstiess.net/research/snippets/show/ca1d7d90 |
| 92 def calculateIndicatorPipe(pairs, predParam, timeHorizon=75,collisionDistanceThreshold=1.8): | 220 def calculateIndicatorPipe(pairs, predParam, timeHorizon=75,collisionDistanceThreshold=1.8): |
| 93 collisionPoints, crossingZones = prediction.computeCrossingsCollisions(pairs.movingObject1, pairs.movingObject2, predParam, collisionDistanceThreshold, timeHorizon) | 221 collisionPoints, crossingZones = prediction.computeCrossingsCollisions(pairs.roadUser1, pairs.roadUser2, predParam, collisionDistanceThreshold, timeHorizon) |
| 94 #print pairs.num | 222 #print pairs.num |
| 95 # Ignore empty collision points | 223 # Ignore empty collision points |
| 96 empty = 1 | 224 empty = 1 |
| 97 for i in collisionPoints: | 225 for i in collisionPoints: |
| 98 if(collisionPoints[i] != []): | 226 if(collisionPoints[i] != []): |
| 135 pool.close() | 263 pool.close() |
| 136 else: | 264 else: |
| 137 #prog = Tools.ProgressBar(0, len(self.pairs), 77) #Removed in traffic-intelligenc port | 265 #prog = Tools.ProgressBar(0, len(self.pairs), 77) #Removed in traffic-intelligenc port |
| 138 for j in xrange(len(self.pairs)): | 266 for j in xrange(len(self.pairs)): |
| 139 #prog.updateAmount(j) #Removed in traffic-intelligenc port | 267 #prog.updateAmount(j) #Removed in traffic-intelligenc port |
| 140 collisionPoints, crossingZones = prediction.computeCrossingsCollisions(self.pairs[j].movingObject1, self.pairs[j].movingObject2, predParam, collisionDistanceThreshold, timeHorizon) | 268 collisionPoints, crossingZones = prediction.computeCrossingsCollisions(self.pairs[j].roadUser1, self.pairs[j].roadUser2, predParam, collisionDistanceThreshold, timeHorizon) |
| 141 | 269 |
| 142 # Ignore empty collision points | 270 # Ignore empty collision points |
| 143 empty = 1 | 271 empty = 1 |
| 144 for i in collisionPoints: | 272 for i in collisionPoints: |
| 145 if(collisionPoints[i] != []): | 273 if(collisionPoints[i] != []): |
| 179 for j in self.pairs: | 307 for j in self.pairs: |
| 180 if(j.hasCZ): | 308 if(j.hasCZ): |
| 181 lists.append(j.num) | 309 lists.append(j.num) |
| 182 return lists | 310 return lists |
| 183 | 311 |
| 184 def getCPlist(self,indicatorThreshold=99999): | 312 def getCPlist(self,indicatorThreshold=float('Inf')): |
| 185 lists = [] | 313 lists = [] |
| 186 for j in self.pairs: | 314 for j in self.pairs: |
| 187 if(j.hasCP): | 315 if(j.hasCP): |
| 188 for k in j.CP: | 316 for k in j.CP: |
| 189 if(j.CP[k] != [] and j.CP[k][0].indicator < indicatorThreshold): | 317 if(j.CP[k] != [] and j.CP[k][0].indicator < indicatorThreshold): |
| 190 lists.append([k,j.CP[k][0]]) | 318 lists.append([k,j.CP[k][0]]) |
| 191 return lists | 319 return lists |
| 192 | 320 |
| 193 def getCZlist(self,indicatorThreshold=99999): | 321 def getCZlist(self,indicatorThreshold=float('Inf')): |
| 194 lists = [] | 322 lists = [] |
| 195 for j in self.pairs: | 323 for j in self.pairs: |
| 196 if(j.hasCZ): | 324 if(j.hasCZ): |
| 197 for k in j.CZ: | 325 for k in j.CZ: |
| 198 if(j.CZ[k] != [] and j.CZ[k][0].indicator < indicatorThreshold): | 326 if(j.CZ[k] != [] and j.CZ[k][0].indicator < indicatorThreshold): |
| 227 | 355 |
| 228 | 356 |
| 229 if __name__ == "__main__": | 357 if __name__ == "__main__": |
| 230 import doctest | 358 import doctest |
| 231 import unittest | 359 import unittest |
| 232 #suite = doctest.DocFileSuite('tests/moving.txt') | 360 suite = doctest.DocFileSuite('tests/events.txt') |
| 233 suite = doctest.DocTestSuite() | 361 #suite = doctest.DocTestSuite() |
| 234 unittest.TextTestRunner().run(suite) | 362 unittest.TextTestRunner().run(suite) |
| 235 | 363 |
