comparison trafficintelligence/moving.py @ 1097:b3f8b26ee838

modification for simulation
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Mon, 18 Feb 2019 17:23:26 -0500
parents 9a32d63bae3f
children 469e36eea158
comparison
equal deleted inserted replaced
1096:9a32d63bae3f 1097:b3f8b26ee838
2 '''Libraries for moving objects, trajectories...''' 2 '''Libraries for moving objects, trajectories...'''
3 3
4 import copy 4 import copy
5 from math import sqrt, atan2, cos, sin 5 from math import sqrt, atan2, cos, sin
6 6
7 from numpy import median, mean, array, arange, zeros, ones, hypot, NaN, std, floor, float32, argwhere, minimum 7 from numpy import median, mean, array, arange, zeros, ones, hypot, NaN, std, floor, ceil, float32, argwhere, minimum
8 from matplotlib.pyplot import plot, text 8 from matplotlib.pyplot import plot, text
9 from scipy.stats import scoreatpercentile 9 from scipy.stats import scoreatpercentile
10 from scipy.spatial.distance import cdist 10 from scipy.spatial.distance import cdist
11 from scipy.signal import savgol_filter 11 from scipy.signal import savgol_filter
12 12
1114 return self.getXCoordinates() 1114 return self.getXCoordinates()
1115 1115
1116 def getLanes(self): 1116 def getLanes(self):
1117 return self.lanes 1117 return self.lanes
1118 1118
1119 def getSCoordAt(self, i):
1120 return self.positions[0][i]
1121
1122 def getYCoordAt(self, i):
1123 return self.positions[1][i]
1124
1125 def getLaneAt(self, i):
1126 return self.positions[2][i]
1127
1119 def addPositionSYL(self, s, y, lane = None): 1128 def addPositionSYL(self, s, y, lane = None):
1120 self.addPositionXY(s,y) 1129 self.addPositionXY(s,y)
1121 self.lanes.append(lane) 1130 self.lanes.append(lane)
1122 1131
1123 def addPosition(self, p): 1132 def addPosition(self, p):
1176 '''Class for moving objects: a spatio-temporal object 1185 '''Class for moving objects: a spatio-temporal object
1177 with a trajectory and a geometry (constant volume over time) 1186 with a trajectory and a geometry (constant volume over time)
1178 and a usertype (e.g. road user) coded as a number (see userTypeNames) 1187 and a usertype (e.g. road user) coded as a number (see userTypeNames)
1179 ''' 1188 '''
1180 1189
1181 def __init__(self, num = None, timeInterval = None, positions = None, velocities = None, geometry = None, userType = userType2Num['unknown'], nObjects = None): 1190 def __init__(self, num = None, timeInterval = None, positions = None, velocities = None, geometry = None, userType = userType2Num['unknown'], nObjects = None, initCurvilinear = False):
1182 super(MovingObject, self).__init__(num, timeInterval) 1191 super(MovingObject, self).__init__(num, timeInterval)
1183 self.positions = positions 1192 if initCurvilinear:
1184 self.velocities = velocities 1193 self.curvilinearPositions = positions
1194 self.curvilinearVelocities = velocities
1195 else:
1196 self.positions = positions
1197 self.velocities = velocities
1185 self.geometry = geometry 1198 self.geometry = geometry
1186 self.userType = userType 1199 self.userType = userType
1187 self.setNObjects(nObjects) # a feature has None for nObjects 1200 self.setNObjects(nObjects) # a feature has None for nObjects
1188 self.features = None 1201 self.features = None
1189 # compute bounding polygon from trajectory 1202 # compute bounding polygon from trajectory
1238 return MovingObject(num = num, timeInterval = timeInterval, positions = positions, velocities = Trajectory([[v.x]*nPoints, [v.y]*nPoints])) 1251 return MovingObject(num = num, timeInterval = timeInterval, positions = positions, velocities = Trajectory([[v.x]*nPoints, [v.y]*nPoints]))
1239 1252
1240 def updatePositions(self): 1253 def updatePositions(self):
1241 inter, self.positions, self.velocities = MovingObject.aggregateTrajectories(self.features, self.getTimeInterval()) 1254 inter, self.positions, self.velocities = MovingObject.aggregateTrajectories(self.features, self.getTimeInterval())
1242 1255
1243 def updateCurvilinearPositions(self, method, changeOfAlignment, nextAlignment_idx, timeStep = None, time = None, 1256 def updateCurvilinearPositions(self, method, changeOfAlignment, nextAlignment_idx, timeStep = None, instant = None, previousAlignmentId = None, maxSpeed = None, acceleration = None):
1244 leaderVehicle = None, previousAlignmentId = None,
1245 maxSpeed = None, acceleration = None):
1246 1257
1247 if method == 'newell': 1258 if method == 'newell':
1248 if time <= self.timeInterval[0] < time + timeStep: 1259 if self.curvilinearPositions is None: # vehicle without positions, all vehicles should have leader (?)
1249 # #si t < instant de creation du vehicule, la position vaut l'espacement dn entre les deux vehicules 1260 if self.leader.curvilinearPositions is not None and self.leader.curvilinearPositions.getSCoordAt(-1) > self.dn and len(self.leader.curvilinearPositions) >=2:
1250 if leaderVehicle is None: 1261 leaderSpeed = self.leader.curvilinearVelocities.getSCoordAt(-1)
1251 self.curvilinearPositions.addPositionSYL( 1262 instantAtX0 = self.tau + instant*timeStep - (self.leader.curvilinearPositions.getSCoordAt(-1)-self.d)/leaderSpeed
1252 -self.dn, 1263 if instantAtX0 < obj.initialHeadway: #obj appears at instant initialHeadway at x=0 with desiredSpeed
1253 0, 1264 instantAtX0 = obj.initialHeadway
1254 nextAlignment_idx) 1265
1266 firstInstant = int(np.ceil(instantAtX0/timeStep))
1267 self.timeInterval = TimeInterval(firstInstant, firstInstant)
1268 freeFlowCoord = (firstInstant*timeStep - instantAtX0)*self.desiredSpeed
1269 # constrainedCoord at firstInstant = xn-1(t = firstInstant*timeStep-self.tn)-self.dn
1270 t = firstInstant*timeStep-self.tn
1271 i = int(floor(t/timeStep))
1272 leaderSpeed = self.leader.getCurvilinearVelocityAtInstant(i)[0]
1273 constrainedCoord = self.leader.getCurvilinearPositionAtInstant(i)[0]+leaderSpeed*(t-i*timeStep)-self.dn
1274 obj.curvilinearPositions = moving.CurvilinearTrajectory([min(freeFlowCoord, constrainedCoord)], [0.], [nextAlignment_idx])# TODO verify initial alignment index
1275 obj.curvilinearVelocities = moving.CurvilinearTrajectory()
1276 for i in range(firstInstant+1, instant+1):
1277 freeFlowCoord = timeStep*self.desiredSpeed + self.curvilinearPositions.getSCoordAt(-1)
1278 #constrainedCoord =
1279
1280 # if instant <= self.timeInterval[0] < instant + timeStep:
1281 # # #si t < instant de creation du vehicule, la position vaut l'espacement dn entre les deux vehicules
1282 # if leaderVehicle is None:
1283 # self.curvilinearPositions.addPositionSYL(
1284 # -self.dn,
1285 # 0,
1286 # nextAlignment_idx)
1287 # else:
1288 # self.curvilinearPositions.addPositionSYL(
1289 # leaderVehicle.curvilinearPositions[0][0] - self.dn,
1290 # 0,
1291 # nextAlignment_idx)
1292 else:
1293 freeFlowCoord = [self.curvilinearPositions[-1][0]+self.desiredSpeed*timeStep, 0, nextAlignment_idx]
1294 if self.leader is None:
1295 self.curvilinearPositions.addPositionSYL(*freeFlowCoord)
1255 else: 1296 else:
1256 self.curvilinearPositions.addPositionSYL( 1297 # if leader coord unknown at t-dn, no movement
1257 leaderVehicle.curvilinearPositions[0][0] - self.dn, 1298 if instant > self.reactionTime:
1258 0, 1299 previousVehicleCurvilinearPositionAtPrecedentInstant = leaderVehicle.curvilinearPositions[-int(round(self.reactionTime))][0] # t-v.reactionTime
1259 nextAlignment_idx)
1260 else:
1261 if leaderVehicle is None:
1262 self.curvilinearPositions.addPositionSYL(self.curvilinearPositions[-1][0]+self.desiredSpeed*timeStep, 0, nextAlignment_idx)
1263 else:
1264 if time > self.reactionTime:
1265 previousVehicleCurvilinearPositionAtPrecedentTime = \
1266 leaderVehicle.curvilinearPositions[-int(round(self.reactionTime))][0] # t-v.reactionTime
1267 else: 1300 else:
1268 previousVehicleCurvilinearPositionAtPrecedentTime = \ 1301 previousVehicleCurvilinearPositionAtPrecedentInstant = \
1269 leaderVehicle.curvilinearPositions[0][0] 1302 leaderVehicle.curvilinearPositions[0][0]
1270 1303
1271 self.curvilinearPositions.addPositionSYL(previousVehicleCurvilinearPositionAtPrecedentTime - self.dn, 0, nextAlignment_idx) 1304 self.curvilinearPositions.addPositionSYL(previousVehicleCurvilinearPositionAtPrecedentInstant - self.dn, 0, nextAlignment_idx)
1272 1305
1273 #mise ajour des vitesses 1306 #mise ajour des vitesses
1274 if changeOfAlignment: 1307 if changeOfAlignment:
1275 self.velocities.addPositionSYL((self.curvilinearPositions[-1][0]-self.curvilinearPositions[-2][0])/timeStep, 1308 self.curvilinearVelocities.addPositionSYL((self.curvilinearPositions[-1][0]-self.curvilinearPositions[-2][0])/timeStep,
1276 (self.curvilinearPositions[-1][1]-self.curvilinearPositions[-2][1])/timeStep, 1309 (self.curvilinearPositions[-1][1]-self.curvilinearPositions[-2][1])/timeStep,
1277 (previousAlignmentId, nextAlignment_idx)) 1310 (previousAlignmentId, nextAlignment_idx))
1278 else: 1311 else:
1279 self.velocities.addPositionSYL((self.curvilinearPositions[-1][0]-self.curvilinearPositions[-2][0])/timeStep, 1312 self.curvilinearVelocities.addPositionSYL((self.curvilinearPositions[-1][0]-self.curvilinearPositions[-2][0])/timeStep,
1280 (self.curvilinearPositions[-1][1]-self.curvilinearPositions[-2][1])/timeStep, 1313 (self.curvilinearPositions[-1][1]-self.curvilinearPositions[-2][1])/timeStep,
1281 None) 1314 None)
1315
1282 @staticmethod 1316 @staticmethod
1283 def concatenate(obj1, obj2, num = None, newFeatureNum = None, computePositions = False): 1317 def concatenate(obj1, obj2, num = None, newFeatureNum = None, computePositions = False):
1284 '''Concatenates two objects, whether overlapping temporally or not 1318 '''Concatenates two objects, whether overlapping temporally or not
1285 1319
1286 Positions will be recomputed only if computePositions is True 1320 Positions will be recomputed only if computePositions is True
1427 if withOrigin and len(instants)>0: 1461 if withOrigin and len(instants)>0:
1428 plot([instants[0]], [coords[0]], 'ro', **kwargs) 1462 plot([instants[0]], [coords[0]], 'ro', **kwargs)
1429 else: 1463 else:
1430 print('Object {} has no curvilinear positions'.format(self.getNum())) 1464 print('Object {} has no curvilinear positions'.format(self.getNum()))
1431 1465
1466 def interpolateCurvilinearPositions(self, t):
1467 '''Linear interpolation of curvilinear positions, t being a float'''
1468 if hasattr(self, 'curvilinearPositions'):
1469 if self.existsAtInstant(t):
1470 i = int(floor(t))
1471 p1 = self.getCurvilinearPositionAtInstant(i)
1472 p2 = self.getCurvilinearPositionAtInstant(i+1)
1473 alpha = t-float(i)
1474 if alpha < 0.5:
1475 lane = p1[2]
1476 else:
1477 lane = p2[2]
1478 return [(1-alpha)*p1[0]+alpha*p2[0], (1-alpha)*p1[1]+alpha*p2[1], lane]
1479 else:
1480 print('Object {} does not exist at {}'.format(self.getNum(), t))
1481 else:
1482 print('Object {} has no curvilinear positions'.format(self.getNum()))
1483
1432 def setUserType(self, userType): 1484 def setUserType(self, userType):
1433 self.userType = userType 1485 self.userType = userType
1434 1486
1435 def getNObjects(self): 1487 def getNObjects(self):
1436 return self.nObjects 1488 return self.nObjects
1514 def getPositionAtInstant(self, i): 1566 def getPositionAtInstant(self, i):
1515 return self.positions[i-self.getFirstInstant()] 1567 return self.positions[i-self.getFirstInstant()]
1516 1568
1517 def getVelocityAtInstant(self, i): 1569 def getVelocityAtInstant(self, i):
1518 return self.velocities[i-self.getFirstInstant()] 1570 return self.velocities[i-self.getFirstInstant()]
1571
1572 def getCurvilinearPositionAt(self, i):
1573 return self.curvilinearPositions[i]
1574
1575 def getCurvilinearVelocityAt(self, i):
1576 return self.curvilinearVelocities[i]
1577
1578 def getCurvilinearPositionAtInstant(self, i):
1579 return self.curvilinearPositions[i-self.getFirstInstant()]
1580
1581 def getCurvilinearVelocityAtInstant(self, i):
1582 return self.curvilinearVelocities[i-self.getFirstInstant()]
1519 1583
1520 def getXCoordinates(self): 1584 def getXCoordinates(self):
1521 return self.positions.getXCoordinates() 1585 return self.positions.getXCoordinates()
1522 1586
1523 def getYCoordinates(self): 1587 def getYCoordinates(self):