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