Mercurial > hg > nsaunier > traffic-intelligence
comparison trafficintelligence/events.py @ 1267:ad60e5adf084
cleaned interaction categorization and added stationary category
| author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
|---|---|
| date | Wed, 29 May 2024 09:52:42 -0400 |
| parents | ebb18043616e |
| children | ca70a79688ae |
comparison
equal
deleted
inserted
replaced
| 1266:ebb18043616e | 1267:ad60e5adf084 |
|---|---|
| 194 cvutils.displayTrajectories(videoFilename, [self.roadUser1, self.roadUser2], homography = homography, firstFrameNum = firstFrameNum, lastFrameNumArg = lastFrameNum, undistort = undistort, intrinsicCameraMatrix = intrinsicCameraMatrix, distortionCoefficients = distortionCoefficients, undistortedImageMultiplication = undistortedImageMultiplication) | 194 cvutils.displayTrajectories(videoFilename, [self.roadUser1, self.roadUser2], homography = homography, firstFrameNum = firstFrameNum, lastFrameNumArg = lastFrameNum, undistort = undistort, intrinsicCameraMatrix = intrinsicCameraMatrix, distortionCoefficients = distortionCoefficients, undistortedImageMultiplication = undistortedImageMultiplication) |
| 195 else: | 195 else: |
| 196 print('Please set the interaction road user attributes roadUser1 and roadUser1 through the method setRoadUsers') | 196 print('Please set the interaction road user attributes roadUser1 and roadUser1 through the method setRoadUsers') |
| 197 | 197 |
| 198 def computeIndicators(self): | 198 def computeIndicators(self): |
| 199 '''Computes the collision course cosine only if the cosine is positive''' | 199 '''Computes all cinematic indicators but the expensive safety indicators (TTC, PET)''' |
| 200 collisionCourseDotProducts = {} | 200 collisionCourseDotProducts = {} |
| 201 collisionCourseAngles = {} | 201 collisionCourseAngles = {} |
| 202 velocityAngles = {} | 202 velocityAngles = {} |
| 203 distances = {} | 203 distances = {} |
| 204 speedDifferentials = {} | 204 speedDifferentials = {} |
| 231 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[3], minDistances, mostSevereIsMax = False)) | 231 self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[3], minDistances, mostSevereIsMax = False)) |
| 232 | 232 |
| 233 def categorize(self, velocityAngleTolerance, parallelAngleTolerance, headonCollisionCourseAngleTolerance = None, speedThreshold = 0.): | 233 def categorize(self, velocityAngleTolerance, parallelAngleTolerance, headonCollisionCourseAngleTolerance = None, speedThreshold = 0.): |
| 234 '''Computes the interaction category by instant | 234 '''Computes the interaction category by instant |
| 235 all 3 angle arguments in radian | 235 all 3 angle arguments in radian |
| 236 velocityAngleTolerance: indicates the angle threshold for rear and head on (180-velocityAngleTolerance), as well as the maximum collision course angle for head on (if headonCollisionCourseAngleTolerance is None) | 236 velocityAngleTolerance: indicates the angle threshold for rear and head on (180-velocityAngleTolerance), |
| 237 parallelAngleTolerance: indicates the angle between velocity vector (average for parallel) and position vector | 237 as well as the maximum collision course angle for head on (if headonCollisionCourseAngleTolerance is None) |
| 238 parallelAngleTolerance: indicates the tolerance on the expected 90 deg angle | |
| 239 between velocity vector (average for parallel) and position vector for a parallel interaction | |
| 240 speedThreshold defines stationary users: a stationary interaction is between one moving and | |
| 241 one stationary user, and their distance decreases | |
| 238 | 242 |
| 239 an instant may not be categorized if it matches the side definition (angle) | 243 an instant may not be categorized if it matches the side definition (angle) |
| 240 but the distance is growing (at least one user is probably past the point of trajectory crossing)''' | 244 but the distance is growing (at least one user is probably past the point of trajectory crossing)''' |
| 241 parallelAngleToleranceCosine = np.cos(parallelAngleTolerance) | 245 minParallelAngleCosine = np.cos(np.pi/2+parallelAngleTolerance) |
| 246 maxParallelAngleCosine = np.cos(np.pi/2-parallelAngleTolerance) | |
| 242 if headonCollisionCourseAngleTolerance is None: | 247 if headonCollisionCourseAngleTolerance is None: |
| 243 headonCollisionCourseAngleTolerance = velocityAngleTolerance | 248 headonCollisionCourseAngleTolerance = velocityAngleTolerance |
| 244 speedThreshold2 = speedThreshold**2 | 249 speedThreshold2 = speedThreshold**2 |
| 245 | 250 |
| 246 self.categories = {} | 251 self.categories = {} |
| 247 collisionCourseDotProducts = self.getIndicator(Interaction.indicatorNames[0]) | 252 collisionCourseDotProducts = self.getIndicator(Interaction.indicatorNames[0]) |
| 248 collisionCourseAngles = self.getIndicator(Interaction.indicatorNames[1]) | 253 collisionCourseAngles = self.getIndicator(Interaction.indicatorNames[1]) |
| 249 distances = self.getIndicator(Interaction.indicatorNames[2]) | 254 distances = self.getIndicator(Interaction.indicatorNames[2]) |
| 250 velocityAngles = self.getIndicator(Interaction.indicatorNames[4]) | 255 velocityAngles = self.getIndicator(Interaction.indicatorNames[4]) |
| 251 for instant in self.timeInterval: | 256 for instant in self.timeInterval: |
| 252 if instant in velocityAngles: | 257 stationaryUser1 = self.roadUser1.getVelocityAtInstant(instant).norm2Squared() <= speedThreshold2 |
| 258 stationaryUser2 = self.roadUser2.getVelocityAtInstant(instant).norm2Squared() <= speedThreshold2 | |
| 259 if stationaryUser1 != stationaryUser2 and collisionCourseDotProducts[instant] > 0: # only one is not moving and is getting closer | |
| 260 self.categories[instant] = Interaction.categories["stationary"] | |
| 261 # true stationary would be all the times (parked, difficult without semantic knowledge of the scene | |
| 262 # alternatively, one could get the previous or next non zero velocity to identify user orientation | |
| 263 elif velocityAngles.existsAtInstant(instant): | |
| 253 if velocityAngles[instant] < velocityAngleTolerance: # parallel or rear end | 264 if velocityAngles[instant] < velocityAngleTolerance: # parallel or rear end |
| 254 midVelocity = self.roadUser1.getVelocityAtInstant(instant) + self.roadUser2.getVelocityAtInstant(instant) | 265 midVelocity = self.roadUser1.getVelocityAtInstant(instant) + self.roadUser2.getVelocityAtInstant(instant) |
| 255 deltap = self.roadUser1.getPositionAtInstant(instant)-self.roadUser2.getPositionAtInstant(instant) | 266 deltap = self.roadUser1.getPositionAtInstant(instant)-self.roadUser2.getPositionAtInstant(instant) |
| 256 if abs(moving.Point.dot(midVelocity, deltap)/(midVelocity.norm2()*distances[instant])) < parallelAngleToleranceCosine: | 267 if minParallelAngleCosine < abs(moving.Point.dot(midVelocity, deltap)/(midVelocity.norm2()*distances[instant])) < maxParallelAngleCosine: |
| 257 self.categories[instant] = Interaction.categories["parallel"] | 268 self.categories[instant] = Interaction.categories["parallel"] |
| 258 else: | 269 else: |
| 259 self.categories[instant] = Interaction.categories["rearend"] | 270 self.categories[instant] = Interaction.categories["rearend"] |
| 260 elif velocityAngles[instant] > np.pi - velocityAngleTolerance and collisionCourseAngles[instant] < headonCollisionCourseAngleTolerance: # head on | 271 elif velocityAngles[instant] > np.pi - velocityAngleTolerance and collisionCourseAngles[instant] < headonCollisionCourseAngleTolerance: # head on |
| 261 self.categories[instant] = Interaction.categories["headon"] | 272 self.categories[instant] = Interaction.categories["headon"] |
| 262 elif collisionCourseDotProducts[instant] > 0: | 273 elif collisionCourseDotProducts[instant] > 0: |
| 263 self.categories[instant] = Interaction.categories["side"] | 274 self.categories[instant] = Interaction.categories["side"] |
| 264 # true stationary is when object does not move for the whole period of the interaction, otherwise get last (or next) velocity vector for user orientation | 275 # true stationary is when object does not move for the whole period of the interaction, otherwise get last (or next) velocity vector for user orientation |
| 265 # if instant not in self.categories: # if it's none of the other categories (could be with almost stationary vehicle) and only one speed is 0 | 276 # leaving is not a good interaction category (issue in Etienne's 2022 paper): |
| 266 # stationaryUser1 = self.roadUser1.getVelocityAtInstant(instant).norm2Squared() <= speedThreshold2 | 277 # means we are past the situation in which users are approaching |
| 267 # stationaryUser2 = self.roadUser2.getVelocityAtInstant(instant).norm2Squared() <= speedThreshold2 | |
| 268 # if stationaryUser1 != stationaryUser2 and collisionCourseDotProducts[instant] > 0: # only one is not moving | |
| 269 # self.categories[instant] = Interaction.categories["stationary"] | |
| 270 # leaving is not a good interaction category (issue in Etienne's 2022 paper): means we are past the situation in which users are approaching | |
| 271 # could try to predict what happened before, but it's not observed | 278 # could try to predict what happened before, but it's not observed |
| 272 | 279 |
| 273 | 280 |
| 274 def computeCrossingsCollisions(self, predictionParameters, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False, timeInterval = None): | 281 def computeCrossingsCollisions(self, predictionParameters, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False, timeInterval = None): |
| 275 '''Computes all crossing and collision points at each common instant for two road users. ''' | 282 '''Computes all crossing and collision points at each common instant for two road users. ''' |
