comparison trafficintelligence/moving.py @ 1177:aa88acf06876

rewrote object concatenation method, cleaner
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Thu, 24 Mar 2022 16:07:51 -0400
parents b55adb13f262
children 2039df59c47b
comparison
equal deleted inserted replaced
1176:5874ece33637 1177:aa88acf06876
748 else: 748 else:
749 return False 749 return False
750 750
751 def append(self,other): 751 def append(self,other):
752 '''adds positions of other to the trajectory (in-place modification)''' 752 '''adds positions of other to the trajectory (in-place modification)'''
753 for p in other: 753 for i in range(2):
754 self.addPosition(p) 754 self.positions[i] += other.positions[i]
755 755
756 def setPositionXY(self, i, x, y): 756 def setPositionXY(self, i, x, y):
757 if i < self.__len__(): 757 if i < self.__len__():
758 self.positions[0][i] = x 758 self.positions[0][i] = x
759 self.positions[1][i] = y 759 self.positions[1][i] = y
765 self.positions[0].append(x) 765 self.positions[0].append(x)
766 self.positions[1].append(y) 766 self.positions[1].append(y)
767 767
768 def addPosition(self, p): 768 def addPosition(self, p):
769 self.addPositionXY(p.x, p.y) 769 self.addPositionXY(p.x, p.y)
770 770
771 def duplicateLastPosition(self): 771 def duplicateLastPosition(self):
772 self.positions[0].append(self.positions[0][-1]) 772 self.positions[0].append(self.positions[0][-1])
773 self.positions[1].append(self.positions[1][-1]) 773 self.positions[1].append(self.positions[1][-1])
774 774
775 @staticmethod 775 @staticmethod
1172 self.positions[1][inter.first:inter.last+1], 1172 self.positions[1][inter.first:inter.last+1],
1173 self.lanes[inter.first:inter.last+1]) 1173 self.lanes[inter.first:inter.last+1])
1174 else: 1174 else:
1175 return None 1175 return None
1176 1176
1177 def append(self, other):
1178 Trajectory.append(self, other)
1179 self.lanes.append(other.getLanes())
1180
1177 def addPositionSYL(self, s, y, lane = None): 1181 def addPositionSYL(self, s, y, lane = None):
1178 self.addPositionXY(s,y) 1182 self.addPositionXY(s,y)
1179 self.lanes.append(lane) 1183 self.lanes.append(lane)
1180 1184
1181 def addPosition(self, p): 1185 def addPosition(self, p):
1310 1314
1311 def updatePositions(self): 1315 def updatePositions(self):
1312 inter, self.positions, self.velocities = MovingObject.aggregateTrajectories(self.features, self.getTimeInterval()) 1316 inter, self.positions, self.velocities = MovingObject.aggregateTrajectories(self.features, self.getTimeInterval())
1313 1317
1314 @staticmethod 1318 @staticmethod
1315 def concatenate(obj1, obj2, num = None, newFeatureNum = None, minFeatureLength = 5): 1319 def concatenate(obj1, obj2, num = None, newFeatureNum = None):
1316 '''Concatenates two objects, whether overlapping temporally or not 1320 '''Concatenates two objects, whether overlapping temporally or not
1317 1321
1318 Positions will be recomputed features are merged 1322 Positions will be recomputed if features are merged
1319 Otherwise, only featureNumbers and/or features will be merged 1323 Otherwise, only featureNumbers and/or features will be merged'''
1320 minFeatureLength enforces a minimum length to avoid small features
1321 (and smaller velocities that are not saved)'''
1322 if num is None: 1324 if num is None:
1323 newNum = obj1.getNum() 1325 newNum = obj1.getNum()
1324 else: 1326 else:
1325 newNum = num 1327 newNum = num
1326 commonTimeInterval = obj1.commonTimeInterval(obj2) 1328 commonTimeInterval = obj1.commonTimeInterval(obj2)
1327 if commonTimeInterval.empty(): 1329 emptyInterval = TimeInterval(min(obj1.getLastInstant(),obj2.getLastInstant()), max(obj1.getFirstInstant(),obj2.getFirstInstant()))
1328 #print('The two objects\' time intervals do not overlap: obj1 {} and obj2 {}'.format(obj1.getTimeInterval(), obj2.getTimeInterval())) 1330 if commonTimeInterval.empty() and emptyInterval.length() >= 3:
1329 emptyInterval = TimeInterval(min(obj1.getLastInstant(),obj2.getLastInstant()), max(obj1.getFirstInstant(),obj2.getFirstInstant())) 1331 if newFeatureNum is None:
1330 if obj1.existsAtInstant(emptyInterval.last): 1332 print('Not merging objects {} and {}, missing new feature number'.format(obj1.getNum(),obj2.getNum()))
1331 firstObject = obj2 1333 return None, None
1332 secondObject = obj1
1333 else: 1334 else:
1334 firstObject = obj1 1335 if obj1.existsAtInstant(emptyInterval.last):
1335 secondObject = obj2 1336 firstObject = obj2
1336 v = (secondObject.getPositionAtInstant(emptyInterval.last)-firstObject.getPositionAtInstant(emptyInterval.first)).divide(emptyInterval.length()-1) 1337 secondObject = obj1
1337 positions = copy.deepcopy(firstObject.getPositions()) 1338 else:
1338 velocities = copy.deepcopy(firstObject.getPositions()) 1339 firstObject = obj1
1339 featurePositions = Trajectory() 1340 secondObject = obj2
1340 featureVelocities = Trajectory() 1341 v = (secondObject.getPositionAtInstant(emptyInterval.last)-firstObject.getPositionAtInstant(emptyInterval.first)).divide(emptyInterval.length()-1)
1341 p = firstObject.getPositionAtInstant(emptyInterval.first)+v 1342 positions = copy.deepcopy(firstObject.getPositions())
1342 for t in range(emptyInterval.first+1, emptyInterval.last+1): 1343 velocities = copy.deepcopy(firstObject.getPositions())
1343 positions.addPosition(p) 1344 featurePositions = Trajectory()
1344 velocities.addPosition(v) 1345 featureVelocities = Trajectory()
1345 featurePositions.addPosition(p) 1346 p = firstObject.getPositionAtInstant(emptyInterval.first)
1346 featureVelocities.addPosition(v) 1347 # init new feature with position at last instant of 1st obj
1347 p=p+v 1348 featurePositions.addPosition(p)
1348 for t in secondObject.getTimeInterval(): 1349 featureVelocities.addPosition(v)
1349 p = secondObject.getPositionAtInstant(t) 1350 for t in range(emptyInterval.first+1, emptyInterval.last):
1350 v = secondObject.getVelocityAtInstant(t) 1351 p=p+v
1351 positions.addPosition(p) 1352 positions.addPosition(p)
1352 velocities.addPosition(v) 1353 velocities.addPosition(v)
1353 if featurePositions.length() < minFeatureLength:
1354 featurePositions.addPosition(p) 1354 featurePositions.addPosition(p)
1355 featureVelocities.addPosition(v) 1355 featureVelocities.addPosition(v)
1356 newObject = MovingObject(newNum, TimeInterval(firstObject.getFirstInstant(), secondObject.getLastInstant()), positions, velocities, nObjects = 1) 1356 # last position to feature
1357 if hasattr(obj1, 'featureNumbers') and hasattr(obj2, 'featureNumbers'): 1357 p = secondObject.getPositionAtInstant(emptyInterval.last)
1358 if newFeatureNum is not None: 1358 v = secondObject.getVelocityAtInstant(emptyInterval.last)
1359 featurePositions.addPosition(p)
1360 featureVelocities.addPosition(v)
1361 # copy second trajectory
1362 positions.append(secondObject.getPositions())
1363 velocities.append(secondObject.getVelocities())
1364 newObject = MovingObject(newNum, TimeInterval(firstObject.getFirstInstant(), secondObject.getLastInstant()), positions, velocities, nObjects = 1)
1365 newFeature = MovingObject(newFeatureNum, emptyInterval, featurePositions, featureVelocities)
1366 if hasattr(obj1, 'featureNumbers') and hasattr(obj2, 'featureNumbers'):
1359 newObject.featureNumbers = obj1.featureNumbers+obj2.featureNumbers+[newFeatureNum] 1367 newObject.featureNumbers = obj1.featureNumbers+obj2.featureNumbers+[newFeatureNum]
1360 else: 1368 if obj1.hasFeatures() and obj2.hasFeatures():
1361 print('Issue, new created feature has no num id') 1369 newObject.features = obj1.getFeatures()+obj2.getFeatures()+[newFeature]
1362 if obj1.hasFeatures() and obj2.hasFeatures():
1363 newObject.features = obj1.getFeatures()+obj2.getFeatures()+[MovingObject(newFeatureNum, TimeInterval(emptyInterval.first+1, emptyInterval.first+featurePositions.length()), featurePositions, featureVelocities)]
1364 newObject.updatePositions()
1365 else: # time intervals overlap 1370 else: # time intervals overlap
1366 newTimeInterval = TimeInterval.union(obj1.getTimeInterval(), obj2.getTimeInterval()) 1371 newTimeInterval = TimeInterval.union(obj1.getTimeInterval(), obj2.getTimeInterval())
1367 newObject = MovingObject(newNum, newTimeInterval, nObjects = 1) # hypothesis is that it's the same object being reunited 1372 newObject = MovingObject(newNum, newTimeInterval, nObjects = 1) # hypothesis is that it's the same object being reunited
1373 newFeature = None
1368 if hasattr(obj1, 'featureNumbers') and hasattr(obj2, 'featureNumbers'): 1374 if hasattr(obj1, 'featureNumbers') and hasattr(obj2, 'featureNumbers'):
1369 newObject.featureNumbers = obj1.featureNumbers+obj2.featureNumbers 1375 newObject.featureNumbers = obj1.featureNumbers+obj2.featureNumbers
1370 if obj1.hasFeatures() and obj2.hasFeatures(): 1376 if obj1.hasFeatures() and obj2.hasFeatures():
1371 newObject.features = obj1.getFeatures()+obj2.getFeatures() 1377 newObject.features = obj1.getFeatures()+obj2.getFeatures()
1372 newObject.updatePositions() 1378 newObject.updatePositions()
1374 print('Cannot update object positions without features') 1380 print('Cannot update object positions without features')
1375 # user type 1381 # user type
1376 if obj1.getUserType() != obj2.getUserType(): 1382 if obj1.getUserType() != obj2.getUserType():
1377 print('The two moving objects have different user types: obj1 {} obj2 {}'.format(userTypeNames[obj1.getUserType()], userTypeNames[obj2.getUserType()])) 1383 print('The two moving objects have different user types: obj1 {} obj2 {}'.format(userTypeNames[obj1.getUserType()], userTypeNames[obj2.getUserType()]))
1378 newObject.setUserType(obj1.getUserType()) 1384 newObject.setUserType(obj1.getUserType())
1379 return newObject 1385 return newObject, newFeature
1380 1386
1381 def getObjectInTimeInterval(self, inter): 1387 def getObjectInTimeInterval(self, inter):
1382 '''Returns a new object extracted from self, 1388 '''Returns a new object extracted from self,
1383 restricted to time interval inter''' 1389 restricted to time interval inter'''
1384 intersection = TimeInterval.intersection(inter, self.getTimeInterval()) 1390 intersection = TimeInterval.intersection(inter, self.getTimeInterval())