Mercurial > hg > nsaunier > traffic-intelligence
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()) |
