def osrmGetTimeDistOnePair(startLoc, endLoc): """ A function to get a total time and total distance between two given coordinates Parameters ---------- startLoc: list Start location, the format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt] endLoc: list End location, the format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt] Returns ------- timeSeconds: double time between current shapepoint and previous shapepoint, the first element should be 0 distMeters: double distance between current shapepoint and previous shapepoint, the first element should be 0 """ dicStartLoc = loc2Dict(startLoc) dicEndLoc = loc2Dict(endLoc) timeDistUrl = ('http://router.project-osrm.org/route/v1/driving/%s,%s;%s,%s') % (dicStartLoc['lon'], dicStartLoc['lat'], dicEndLoc['lon'], dicEndLoc['lat']) # OSRM use lon/lat data = [] try: http = urllib3.PoolManager() response = http.request('GET', timeDistUrl) data = json.loads(response.data.decode('utf-8')) timeSeconds = data['routes'][0]['duration'] distMeters = data['routes'][0]['distance'] except: print ("Message: OSRM is currently not available, please try again later.") return [timeSeconds, distMeters]
def osrmGetSnapToRoadLatLon(loc): """ A function to get snapped latlng for one coordinate using OSRM Parameters ---------- loc: list The location to be snapped to road Returns ------- list A snapped locations in the format of [lat, lon], notice that this function will lost the info of altitude of the location. """ dicLoc = loc2Dict(loc) snapToRoadUrl = ('http://router.project-osrm.org/nearest/v1/driving/%s,%s') % (dicLoc['lon'], dicLoc['lat']) # OSRM use lon/lat data = [] try: http = urllib3.PoolManager() response = http.request('GET', snapToRoadUrl) data = json.loads(response.data.decode('utf-8')) snapLoc = [data['waypoints'][0]['location'][1], data['waypoints'][0]['location'][0]] # OSRM use lon/lat except: print ("Message: OSRM is currently not available, please try again later.") return snapLoc
def osrmGetShapepointsTimeDist(startLoc, endLoc): """ A function to get a list of shapepoints from start coordinate to end coordinate, the result of this function is not as detailed as mpqGetShapepointTimeDist, however, it is faster. Parameters ---------- startLoc: list Start location, the format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt] endLoc: list End location, the format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt] Returns ------- path: list of lists A list of coordinates in sequence that shape the route from startLoc to endLoc timeInSeconds: double time between current shapepoint and previous shapepoint, the first element should be 0 distInMeters: double distance between current shapepoint and previous shapepoint, the first element should be 0 """ dicStartLoc = loc2Dict(startLoc) dicEndLoc = loc2Dict(endLoc) shapepointsUrl = ('http://router.project-osrm.org/route/v1/driving/%s,%s;%s,%s?steps=true') % (dicStartLoc['lon'], dicStartLoc['lat'], dicEndLoc['lon'], dicEndLoc['lat']) # OSRM use lon/lat data = [] try: http = urllib3.PoolManager() response = http.request('GET', shapepointsUrl) data = json.loads(response.data.decode('utf-8')) path = [] for i in range(len(data['routes'])): for j in range(len(data['routes'][i]['legs'])): for k in range(len(data['routes'][i]['legs'][j]['steps'])): for m in range(len(data['routes'][i]['legs'][j]['steps'][k]['intersections'])): path.append([data['routes'][i]['legs'][j]['steps'][k]['intersections'][m]['location'][1], data['routes'][i]['legs'][j]['steps'][k]['intersections'][m]['location'][0]]) totalTimeInSecond = data['routes'][0]['duration'] [timeInSeconds, distInMeters] = distributeTimeDist(path, totalTimeInSecond) except: print ("Message: OSRM is currently not available, please try again later.") return [path, timeInSeconds, distInMeters]
def privAddStaticAssignment(initAssignments=None, odID=1, objectID=None, modelFile=None, modelScale=VRV_DEFAULT_CESIUMMODELSCALE, modelMinPxSize=VRV_DEFAULT_CESIUMMODELMINPXSIZE, loc=None, startTimeSec=None, endTimeSec=None): # Replace backslash modelFile = replaceBackslashToSlash(modelFile) # assignment dataframe assignments = initDataframe('Assignments') dicLoc = loc2Dict(loc) assignments = assignments.append( { 'odID': odID, 'objectID': objectID, 'modelFile': modelFile, 'modelScale': modelScale, 'modelMinPxSize': modelMinPxSize, 'startTimeSec': startTimeSec, 'startLat': dicLoc['lat'], 'startLon': dicLoc['lon'], 'startAltMeters': dicLoc['alt'], 'endTimeSec': endTimeSec, 'endLat': dicLoc['lat'], 'endLon': dicLoc['lon'], 'endAltMeters': dicLoc['alt'], 'leafletColor': None, 'leafletWeight': None, 'leafletStyle': None, 'leafletOpacity': None, 'cesiumColor': None, 'cesiumWeight': None, 'cesiumStyle': None, 'cesiumOpacity': None, 'useArrows': None }, ignore_index=True, sort=False) if (type(initAssignments) is pd.core.frame.DataFrame): assignments = pd.concat([initAssignments, assignments], ignore_index=True) return assignments
def orsLocalGetSnapToRoadLatLon(loc, port): """ A function to get snapped latlng for one coordinate using ORS Parameters ---------- loc: list The location to be snapped to road Returns ------- list A snapped location in the format of [lat, lon]. Note that this function will lose the info of altitude of the location. """ # There is no function in ORS that snaps to a road. # Instead, issue a driving request from a location to itself. dicLoc = loc2Dict(loc) # ORS uses [lon, lat] order: snapToRoadUrl = ( 'http://localhost:%s/ors/directions?profile=driving-car&geometry_format=geojson&coordinates=%s,%s|%s,%s&elevation=false' % (port, dicLoc['lon'], dicLoc['lat'], dicLoc['lon'], dicLoc['lat'])) try: http = urllib3.PoolManager() response = http.request('GET', snapToRoadUrl) data = json.loads(response.data.decode('utf-8')) http_status = response.status if (http_status == 200): # OK # ORS uses [lon, lat] order: snapLoc = [ data['routes'][0]['geometry']['coordinates'][0][1], data['routes'][0]['geometry']['coordinates'][0][0] ] return snapLoc else: # Error of some kind http_status_description = responses[http_status] print("Error Code %s: %s" % (http_status, http_status_description)) return except: print("Error: ", sys.exc_info()[1]) raise
def pgrGetSnapToRoadLatLon(gid, loc, databaseName): """ A function to get snapped latlng for one coordinate using pgRouting Parameters ---------- gid: int The gid of the street in pgRouting database loc: list The location to be snapped to road databaseName: string, Require If you are hosting a data provider on your local machine (e.g., pgRouting), you'll need to specify the name of the local database. Returns ------- list A snapped locations in the format of [lat, lon], notice that this function will lost the info of altitude of the location. """ conn = psycopg2.connect( "dbname='%s' user='******' host='%s' password='******'" % (databaseName, config['VRV_SETTING_PGROUTING_USERNAME'], config['VRV_SETTING_PGROUTING_HOST'], config['VRV_SETTING_PGROUTING_PASSWORD'])) cur = conn.cursor() # For maintainability dicLoc = loc2Dict(loc) sqlCommand = " select ST_X(point), ST_Y(point)" sqlCommand += " from (" sqlCommand += " select ST_ClosestPoint(" sqlCommand += " ST_GeomFromEWKT(CONCAT('SRID=4326; LINESTRING(',x1,' ',y1,', ',x2,' ',y2,')'))," sqlCommand += " ST_GeomFromEWKT('SRID=4326;POINT(%s %s)')) as point" % ( dicLoc['lon'], dicLoc['lat']) # Be very careful about lon and lat sqlCommand += " from ways" sqlCommand += " where gid=%s" % (gid) sqlCommand += " ) a;" cur.execute(sqlCommand) row = cur.fetchone() snapLoc = [row[1], row[0]] conn.close() return snapLoc
def mqGetSnapToRoadLatLon(loc, APIkey): """ A function to get snapped latlng for one coordinate using MapQuest Parameters ---------- loc: list The location to be snapped to road APIkey: string, Required Enables us to access to MapQuest server Returns ------- list A snapped locations in the format of [lat, lon], notice that this function will lost the info of altitude of the location. """ dicLoc = loc2Dict(loc) snapToRoadUrl = ( 'http://www.mapquestapi.com/geocoding/v1/batch?key=%s&thumbMaps=false&outFormat=json&location=%s,%s' ) % (APIkey, dicLoc['lat'], dicLoc['lon']) data = [] try: http = urllib3.PoolManager() response = http.request('GET', snapToRoadUrl) data = json.loads(response.data.decode('utf-8')) snapLoc = [ data['results'][0]['locations'][0]['latLng']['lat'], data['results'][0]['locations'][0]['latLng']['lng'] ] except: print( "Message: Unable to connect MapQuest, the most common causes are 1) that your computer isn't connected to the network; 2) an invalid key is provided." ) return snapLoc
def pgrGetNearestStreet(loc, databaseName): """ A function to return the details of the nearest street given a known coordinate Parameters ---------- loc: list The locationi that trying to find the nearest street of databaseName: string, Require If you are hosting a data provider on your local machine (e.g., pgRouting), you'll need to specify the name of the local database. Returns ------- gid: int gid from Ways table, identifier for street sourceVid: int sourceVid from Ways table, identifier for source vertice targetVid: int targetVid from Ways table, identifier for target vertice sourceLat: int sourceLat from Ways table, latitude for source vertice sourceLon: int sourceLon from Ways table, longitude for source vertice targetLat: int targetLat from Ways table, latitude for target vertice targetLon: int targetLon from Ways table, longitude for target vertice cost_s: int cost_s from Ways table, time needs from source to target reverse_cost_s: int reverse_cost_s from Ways table, time needs from target to source one_way: int one_way from Ways table, indicate if it is one way street """ conn = psycopg2.connect("dbname='%s' user='******' host='%s' password='******'" % ( databaseName, VRV_SETTING_PGROUTING_USERNAME, VRV_SETTING_PGROUTING_HOST, VRV_SETTING_PGROUTING_PASSWORD)) cur = conn.cursor() # For maintainability dicLoc = loc2Dict(loc) try: sqlCommand = " select gid, source, target, y1, x1, y2, x2, cost_s, reverse_cost_s, one_way" sqlCommand += " from " sqlCommand += " ways" sqlCommand += " where" sqlCommand += " x1 >= %s - 0.01 and x1 <= %s + 0.01" % (dicLoc['lon'], dicLoc['lon']) # Eliminate most of the ways there sqlCommand += " order by" sqlCommand += " ST_Distance(" sqlCommand += " ST_GeogFromText('SRID=4326; POINT(%s %s)')," % (dicLoc['lon'], dicLoc['lat']) # Be very careful about lon and lat sqlCommand += " ST_GeogFromText(CONCAT('SRID=4326; LINESTRING(',x1,' ',y1,', ',x2,' ',y2,')')))" sqlCommand += " limit 1;" cur.execute(sqlCommand) row = cur.fetchone() street = { "gid" : int(row[0]), "source" : int(row[1]), "target" : int(row[2]), "sourceLoc" : [row[3], row[4]], "targetLoc" : [row[5], row[6]], "cost_s" : row[7], "reverse_cost_s" : row[8], "one_way" : row[9] } except: sqlCommand = " select gid, source, target, y1, x1, y2, x2, length_m, cost_s, reverse_cost_s, one_way" sqlCommand += " from " sqlCommand += " ways" sqlCommand += " order by" sqlCommand += " ST_Distance(" sqlCommand += " ST_GeogFromText('SRID=4326; POINT(%s %s)')," % (dicLoc['lon'], dicLoc['lat']) # Be very careful about lon and lat sqlCommand += " ST_GeogFromText(CONCAT('SRID=4326; LINESTRING(',x1,' ',y1,', ',x2,' ',y2,')')))" sqlCommand += " limit 1;" cur.execute(sqlCommand) row = cur.fetchone() street = { "gid" : int(row[0]), "source" : int(row[1]), "target" : int(row[2]), "sourceLoc" : [row[3], row[4]], "targetLoc" : [row[5], row[6]], "cost_s" : row[7], "reverse_cost_s" : row[8], "one_way" : row[9] } conn.close() return street
def pgrGetTimeDist(fromLocs, toLocs, databaseName): """ This function generated time and distance matrix using pgRouting Parameters ---------- fromLoc: list, Conditional Used in 'one2many' mode. To state the coordinate of the starting node locs: list of lists Used in 'all2all', 'one2many', 'many2one' modes. A list of coordinates, in the format of [[lat1, lon1], [lat2, lon2], ...] toLoc: list, Conditional Used in 'many2one' mode. To state the coordinate of the ending node databaseName: string If you are hosting a data provider on your local machine (e.g., pgRouting), you'll need to specify the name of the local database. Returns ------- timeSecs: dictionary The key of each item in this dictionary is in (coordID1, coordID2) format, the travelling time from first entry to second entry, the units are seconds distMeters: dictionary The key of each item in this dictionary is in (coordID1, coordID2) format, the travelling distance from first entry to second entry, the units are meters """ conn = psycopg2.connect("dbname='%s' user='******' host='%s' password='******'" % ( databaseName, VRV_SETTING_PGROUTING_USERNAME, VRV_SETTING_PGROUTING_HOST, VRV_SETTING_PGROUTING_PASSWORD)) conn.autocommit = True cur = conn.cursor() dummyClassID = 821 # Hard-coded number, no specific meaning # FIXME! For database security reason, we need to testify if class_id = 821 is not used in the original database sqlCommand = " select max(id) from ways_vertices_pgr;" cur.execute(sqlCommand) row = cur.fetchone() newlyInsertVidNum = int(row[0]) + 1 locs = fromLocs.copy() for i in range(len(toLocs)): try: locs.index(toLocs[i]) except ValueError: locs.append(toLocs[i]) startVidList = [] endVidList = [] for i in range(len(fromLocs)): startVidList.append(newlyInsertVidNum + locs.index(fromLocs[i])) for i in range(len(toLocs)): endVidList.append(newlyInsertVidNum + locs.index(toLocs[i])) for i in range(len(locs)): # Add dummy vertices street = pgrGetNearestStreet(locs[i], databaseName) snapLoc = pgrGetSnapToRoadLatLon(street['gid'], locs[i], databaseName) dicSnapLoc = loc2Dict(snapLoc) sqlCommand = " insert into ways_vertices_pgr (id, lon, lat) values (%s, %s, %s);" % ( newlyInsertVidNum + locs.index(locs[i]), dicSnapLoc['lon'], dicSnapLoc['lat']) cur.execute(sqlCommand) # Add four two road segments distSource2Snapped = geoDistance2D(street['sourceLoc'], snapLoc) distSnapped2Target = geoDistance2D(snapLoc, street['targetLoc']) ratio = distSource2Snapped / (distSource2Snapped + distSnapped2Target) dicSourceLoc = loc2Dict(street['sourceLoc']) dicTargetLoc = loc2Dict(street['targetLoc']) sqlCommand = " insert into ways (class_id, source, target, length_m, x1, y1, x2, y2, cost_s, reverse_cost_s) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s);" % ( dummyClassID, street['source'], newlyInsertVidNum + locs.index(locs[i]), distSource2Snapped, dicSourceLoc['lon'], dicSourceLoc['lat'], dicSnapLoc['lon'], dicSnapLoc['lat'], street['cost_s'] * ratio, street['reverse_cost_s'] * ratio) cur.execute(sqlCommand) sqlCommand = " insert into ways (class_id, source, target, length_m, x1, y1, x2, y2, cost_s, reverse_cost_s) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s);" % ( dummyClassID, newlyInsertVidNum + locs.index(locs[i]), street['target'], distSnapped2Target, dicSnapLoc['lon'], dicSnapLoc['lat'], dicTargetLoc['lon'], dicTargetLoc['lat'], street['cost_s'] * (1 - ratio), street['reverse_cost_s'] * (1 - ratio)) cur.execute(sqlCommand) sqlCommand = " select " sqlCommand += " start_vid as start_node, " sqlCommand += " end_vid as end_node, " sqlCommand += " sum(cost) as time, " sqlCommand += " sum(length_m) as distance " sqlCommand += " from (" sqlCommand += " select " sqlCommand += " a.*, " sqlCommand += " b.length_m" sqlCommand += " from pgr_dijkstra(" sqlCommand += " 'select gid as id, source, target, cost_s as cost, reverse_cost_s as reverse_cost from ways', " sqlCommand += " ARRAY%s, " % (startVidList) sqlCommand += " ARRAY%s, " % (endVidList) sqlCommand += " directed := true) a " sqlCommand += " left join " sqlCommand += " ways b " sqlCommand += " on " sqlCommand += " a.edge = b.gid " sqlCommand += " order by " sqlCommand += " a.path_seq" sqlCommand += " ) x " sqlCommand += " group by " sqlCommand += " start_vid, " sqlCommand += " end_vid;" cur.execute(sqlCommand) row = cur.fetchall() for i in range(len(startVidList)): sqlCommand = " delete from ways_vertices_pgr where id = %s;" % (startVidList[i]) cur.execute(sqlCommand) for i in range(len(endVidList)): sqlCommand = " delete from ways_vertices_pgr where id = %s;" % (endVidList[i]) cur.execute(sqlCommand) sqlCommand = " delete from ways where class_id = %s;" % (dummyClassID) cur.execute(sqlCommand) conn.close() rawDist = {} rawTime = {} for i in range(len(row)): rawTime[row[i][0], row[i][1]] = row[i][2] rawDist[row[i][0], row[i][1]] = row[i][3] distMeters = {} timeSecs = {} for i in range(len(fromLocs)): for j in range(len(toLocs)): try: distMeters[i, j] = rawDist[startVidList[i], endVidList[j]] except: distMeters[i, j] = 0 try: timeSecs[i, j] = rawTime[startVidList[i], endVidList[j]] except: timeSecs[i, j] = 0 return [timeSecs, distMeters]
def pgrGetShapepointsTimeDist(startLoc, endLoc, databaseName): """ A function to get a list of shapepoints from start coordinate to end coordinate. Parameters ---------- startLoc: list Start location, the format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt] endLat: float Required, latitude of end coordinate endLon: float Required, longitude of end coordinate databaseName: string, Require If you are hosting a data provider on your local machine (e.g., pgRouting), you'll need to specify the name of the local database. Returns ------- path: list of lists A list of coordinates in sequence that shape the route from startLoc to endLoc timeSecs: list time between current shapepoint and previous shapepoint, the first element should be 0 distMeters: list distance between current shapepoint and previous shapepoint, the first element should be 0 """ conn = psycopg2.connect("dbname='%s' user='******' host='%s' password='******'" % ( databaseName, VRV_SETTING_PGROUTING_USERNAME, VRV_SETTING_PGROUTING_HOST, VRV_SETTING_PGROUTING_PASSWORD)) conn.autocommit = True cur = conn.cursor() # Calculate the distance between snapped location and source/target of closest street for the START coordinate startStreet = pgrGetNearestStreet(startLoc, databaseName) snapStartLoc = pgrGetSnapToRoadLatLon(startStreet['gid'], startLoc, databaseName) dicSnapStartLoc = loc2Dict(snapStartLoc) distSnapStart2Source = geoDistance2D(snapStartLoc, startStreet['sourceLoc']) distSnapStart2Target = geoDistance2D(snapStartLoc, startStreet['targetLoc']) # Calculate the distance between snapped location and source/target of closest street for the END coordinate endStreet = pgrGetNearestStreet(endLoc, databaseName) snapEndLoc = pgrGetSnapToRoadLatLon(endStreet['gid'], endLoc, databaseName) dicSnapEndLoc = loc2Dict(snapEndLoc) distSnapEnd2Source = geoDistance2D(snapEndLoc, endStreet['sourceLoc']) distSnapEnd2Target = geoDistance2D(snapEndLoc, endStreet['targetLoc']) # Find the number of vertices in the pgRouting database sqlCommand = " select count(*) from ways_vertices_pgr;" cur.execute(sqlCommand) row = cur.fetchone() newlyInsertVidNum = int(row[0]) + 1 # Testify and find a dummyClassID to put temp vertices and segments dummyClassID = 821 # Hard-coded number, no specific meaning # FIXME! For database security reason, we need to testify if class_id = 821 is not used in the original database # insert the snapped location for START coordinate, and two segments from the coordinate to source/target of the closest street sqlCommand = " insert into ways_vertices_pgr (id, lon, lat) values (%s, %s, %s);" % ( newlyInsertVidNum, dicSnapStartLoc['lon'], dicSnapStartLoc['lat']) sqlCommand += " insert into ways (class_id, source, target, length_m, x1, y1, x2, y2, cost_s, reverse_cost_s) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s);" % ( dummyClassID, newlyInsertVidNum, startStreet['target'], distSnapStart2Target, dicSnapStartLoc['lon'], dicSnapStartLoc['lat'], startStreet['targetLoc'][1], startStreet['targetLoc'][0], startStreet['cost_s'] * distSnapStart2Target / (distSnapStart2Target + distSnapStart2Source), startStreet['reverse_cost_s'] * distSnapStart2Target / (distSnapStart2Target + distSnapStart2Source)) sqlCommand += " insert into ways (class_id, source, target, length_m, x1, y1, x2, y2, cost_s, reverse_cost_s) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s);" % ( dummyClassID, startStreet['source'], newlyInsertVidNum, distSnapStart2Source, startStreet['sourceLoc'][1], startStreet['sourceLoc'][0], dicSnapStartLoc['lon'], dicSnapStartLoc['lat'], startStreet['cost_s'] * distSnapStart2Source / (distSnapStart2Target + distSnapStart2Source), startStreet['reverse_cost_s'] * distSnapStart2Source / (distSnapStart2Target + distSnapStart2Source)) # insert the snapped location for END coordinate, and two segments from the coordinate to source/target of the closest street sqlCommand += " insert into ways_vertices_pgr (id, lon, lat) values (%s, %s, %s);" % ( newlyInsertVidNum + 1, dicSnapEndLoc['lon'], dicSnapEndLoc['lat']) sqlCommand += " insert into ways (class_id, source, target, length_m, x1, y1, x2, y2, cost_s, reverse_cost_s) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s);" % ( dummyClassID, newlyInsertVidNum + 1, endStreet['target'], distSnapEnd2Target, dicSnapEndLoc['lon'], dicSnapEndLoc['lat'], endStreet['targetLoc'][1], endStreet['targetLoc'][0], endStreet['cost_s'] * distSnapEnd2Target / (distSnapEnd2Target + distSnapEnd2Source), endStreet['reverse_cost_s'] * distSnapEnd2Target / (distSnapEnd2Target + distSnapEnd2Source)) sqlCommand += " insert into ways (class_id, source, target, length_m, x1, y1, x2, y2, cost_s, reverse_cost_s) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s);" % ( dummyClassID, endStreet['source'], newlyInsertVidNum + 1, distSnapEnd2Source, endStreet['sourceLoc'][1], endStreet['sourceLoc'][0], dicSnapEndLoc['lon'], dicSnapEndLoc['lat'], endStreet['cost_s'] * distSnapEnd2Source / (distSnapEnd2Target + distSnapEnd2Source), endStreet['reverse_cost_s'] * distSnapEnd2Source / (distSnapEnd2Target + distSnapEnd2Source)) # Do dijstra algorithm to find shortest path sqlCommand += " select b.gid as gid, b.y1 as lats1, b.x1 as lons1, b.y2 as lats2, b.x2 as lons2, a.cost as secs, b.length_m as dist " sqlCommand += " from " sqlCommand += " pgr_dijkstra(" sqlCommand += " 'select gid as id, source, target, cost_s as cost, reverse_cost_s as reverse_cost from ways'," sqlCommand += " %s," % (newlyInsertVidNum) sqlCommand += " %s," % (newlyInsertVidNum + 1) sqlCommand += " directed := true" sqlCommand += " ) a" sqlCommand += " left join" sqlCommand += " ways b" sqlCommand += " on a.edge = b.gid" sqlCommand += " order by a.path_seq" # Return the shapepoint result from dijstra algorithm cur.execute(sqlCommand) row = cur.fetchall() summary = pd.DataFrame(row, columns=['gid', 'lats1', 'lons1', 'lats2', 'lons2', 'secs', 'dist']) # Delete the temp data sqlCommand = " delete from ways_vertices_pgr where id = (%s);" % (newlyInsertVidNum) sqlCommand += " delete from ways_vertices_pgr where id = (%s);" % (newlyInsertVidNum + 1) sqlCommand += " delete from ways where class_id = %s;" % (dummyClassID) cur.execute(sqlCommand) # The last row is junk info, drop it summary.drop(summary.index[len(summary) - 1], inplace = True) # Sorting the coordinates so that they can be linked to each other lats1 = summary['lats1'].tolist() lons1 = summary['lons1'].tolist() lats2 = summary['lats2'].tolist() lons2 = summary['lons2'].tolist() path = [] path.append(startLoc) for i in range(1, len(lats1)): if (lats1[i] != lats1[i - 1] and lats1[i] != lats2[i - 1]): path.append([lats1[i], lons1[i]]) else: path.append([lats2[i], lons2[i]]) timeSecs = summary['secs'].tolist() distMeters = summary['dist'].tolist() conn.close() return [path, timeSecs, distMeters]
def privGetShapepoints2D( odID=1, objectID=None, modelFile=None, startLoc=None, endLoc=None, startTimeSec=0.0, expDurationSec=None, routeType='euclidean2D', speedMPS=None, leafletColor=config['VRV_DEFAULT_LEAFLETARCCOLOR'], leafletWeight=config['VRV_DEFAULT_LEAFLETARCWEIGHT'], leafletStyle=config['VRV_DEFAULT_LEAFLETARCSTYLE'], leafletOpacity=config['VRV_DEFAULT_LEAFLETARCOPACITY'], leafletCurveType=config['VRV_DEFAULT_ARCCURVETYPE'], leafletCurvature=config['VRV_DEFAULT_ARCCURVATURE'], useArrows=True, modelScale=config['VRV_DEFAULT_CESIUMMODELSCALE'], modelMinPxSize=config['VRV_DEFAULT_CESIUMMODELMINPXSIZE'], cesiumColor=config['VRV_DEFAULT_CESIUMPATHCOLOR'], cesiumWeight=config['VRV_DEFAULT_CESIUMPATHWEIGHT'], cesiumStyle=config['VRV_DEFAULT_CESIUMPATHSTYLE'], cesiumOpacity=config['VRV_DEFAULT_CESIUMPATHOPACITY'], ganttColor=config['VRV_DEFAULT_GANTTCOLOR'], popupText=None, dataProvider=None, dataProviderArgs=None): # Replace backslash modelFile = replaceBackslashToSlash(modelFile) # Ensure leading slash modelFile = addHeadSlash(modelFile) try: dataProvider = dataProvider.lower() except: pass try: routeType = routeType.lower() except: pass if (startLoc != endLoc): extras = {} if (routeType == 'euclidean2d'): [path, time, dist] = _eucGetShapepointsTimeDist(startLoc, endLoc, speedMPS, expDurationSec) elif (routeType == 'manhattan'): [path, time, dist] = _manGetShapepointsTimeDist(startLoc, endLoc, speedMPS, expDurationSec) elif (routeType == 'fastest' and dataProviderDictionary[dataProvider] == 'pgrouting'): databaseName = dataProviderArgs['databaseName'] [path, time, dist] = pgrGetShapepointsTimeDist(startLoc, endLoc, databaseName) elif (routeType == 'fastest' and dataProviderDictionary[dataProvider] == 'osrm-online'): [path, time, dist] = osrmGetShapepointsTimeDist(startLoc, endLoc) elif (routeType in ['fastest', 'shortest', 'pedestrian'] and dataProviderDictionary[dataProvider] == 'mapquest'): APIkey = dataProviderArgs['APIkey'] [path, time, dist] = mqGetShapepointsTimeDist(startLoc, endLoc, routeType, APIkey) elif (routeType in ['fastest', 'pedestrian', 'cycling', 'truck', 'wheelchair'] and dataProviderDictionary[dataProvider] == 'ors-online'): APIkey = dataProviderArgs['APIkey'] if ('requestExtras' in dataProviderArgs.keys()): requestExtras = dataProviderArgs['requestExtras'] else: requestExtras = True [path, extras, time, dist] = orsGetShapepointsTimeDist(startLoc, endLoc, routeType, APIkey, requestExtras) elif (routeType in ['fastest', 'pedestrian', 'cycling', 'truck'] and dataProviderDictionary[dataProvider] == 'ors-local'): port = dataProviderArgs['port'] if ('requestExtras' in dataProviderArgs.keys()): requestExtras = dataProviderArgs['requestExtras'] else: requestExtras = True [path, extras, time, dist] = orsLocalGetShapepointsTimeDist(startLoc, endLoc, routeType, port, requestExtras) else: return # Check if the original point is too far away from the actual start point of the shapepoints from query distOri = geoDistance2D(startLoc, path[0]) if (distOri >= config['VRV_DEFAULT_DISTANCE_ERROR_TOLERANCE'] ): # Go back to 10m after testing print( "Message: The origin point (lat: %s, lon: %s) is %.1f meters away from the road. You might find a gap between the origin point and the route." % (startLoc[0], startLoc[1], distOri)) # Check if the actual end point is too far away from destination point distDes = geoDistance2D(path[-1], endLoc) if (distDes >= config['VRV_DEFAULT_DISTANCE_ERROR_TOLERANCE'] ): # Go back to 10m after testing print( "Message: The destination point (lat: %s, lon: %s) is %.1f meters away from the road. You might find a gap between destination point and the route." % (endLoc[0], endLoc[1], distDes)) # convert distance to accumulated distance accDist = [] accDist.append(0) for i in range(1, len(dist)): accDist.append(accDist[i - 1] + dist[i]) # If `expDurationSec` is provided, override `speedMPS` and datasource, otherwise, if `speedMPS` is provided, override datasource if (expDurationSec != None): [newTime, newDist] = distributeTimeDist(path, expDurationSec) time = newTime dist = newDist elif (speedMPS != None and expDurationSec == None): newExpDurationSec = accDist[len(accDist) - 1] / speedMPS [newTime, newDist] = distributeTimeDist(path, newExpDurationSec) time = newTime dist = newDist # convert time to accumulated time accTime = [] accTime.append(startTimeSec) for i in range(1, len(dist)): accTime.append(accTime[i - 1] + time[i]) # For maintainability, convert locs into dictionary dicPath = locs2Dict(path) # shapepoint dataframe assignments = privInitDataframe('Assignments') # generate assignments for i in range(1, len(path)): if (i - 1) in extras: startElev = extras[i - 1]['elev'] if 'elev' in extras[i - 1] else None wayname = extras[i]['wayname'] if 'wayname' in extras[ i] else None waycategory = extras[i][ 'waycategory'] if 'waycategory' in extras[i] else None surface = extras[i]['surface'] if 'surface' in extras[ i] else None waytype = extras[i]['waytype'] if 'waytype' in extras[ i] else None steepness = extras[i]['steepness'] if 'steepness' in extras[ i] else None tollway = extras[i]['tollway'] if 'tollway' in extras[ i] else None else: startElev = None wayname = None waycategory = None surface = None waytype = None steepness = None tollway = None if i in extras: endElev = extras[i]['elev'] if 'elev' in extras[i] else None else: endElev = None assignments = assignments.append( { 'odID': odID, 'objectID': objectID, 'modelFile': modelFile, 'startTimeSec': accTime[i - 1], 'startLat': dicPath[i - 1]['lat'], 'startLon': dicPath[i - 1]['lon'], 'startAltMeters': dicPath[i - 1]['alt'], 'endTimeSec': accTime[i], 'endLat': dicPath[i]['lat'], 'endLon': dicPath[i]['lon'], 'endAltMeters': dicPath[i]['alt'], 'leafletColor': leafletColor, 'leafletWeight': leafletWeight, 'leafletStyle': leafletStyle, 'leafletCurveType': leafletCurveType, 'leafletCurvature': leafletCurvature, 'useArrows': useArrows, 'leafletOpacity': leafletOpacity, 'modelScale': modelScale, 'modelMinPxSize': modelMinPxSize, 'cesiumColor': stripCesiumColor(cesiumColor), 'cesiumWeight': cesiumWeight, 'cesiumStyle': cesiumStyle, 'cesiumOpacity': cesiumOpacity, 'ganttColor': ganttColor, 'popupText': popupText, 'startElevMeters': startElev, 'endElevMeters': endElev, 'wayname': wayname, 'waycategory': waycategory, 'surface': surface, 'waytype': waytype, 'steepness': steepness, 'tollway': tollway }, ignore_index=True) else: # For maintainability, convert locs into dictionary dicStartLoc = loc2Dict(startLoc) if (dataProviderDictionary[dataProvider] == 'ors-online'): [[lat, lon, elev]] = orsGetElevation([startLoc], dataProviderArgs['APIkey']) else: elev = None assignments = privInitDataframe('Assignments') assignments = assignments.append( { 'odID': odID, 'objectID': objectID, 'modelFile': modelFile, 'startTimeSec': startTimeSec, 'startLat': dicStartLoc['lat'], 'startLon': dicStartLoc['lon'], 'startAltMeters': dicStartLoc['alt'], 'endTimeSec': expDurationSec + startTimeSec if (expDurationSec is not None) else startTimeSec, 'endLat': dicStartLoc['lat'], 'endLon': dicStartLoc['lon'], 'endAltMeters': dicStartLoc['alt'], 'leafletColor': leafletColor, 'leafletWeight': leafletWeight, 'leafletStyle': leafletStyle, 'leafletCurveType': leafletCurveType, 'leafletCurvature': leafletCurvature, 'useArrows': useArrows, 'leafletOpacity': leafletOpacity, 'modelScale': modelScale, 'modelMinPxSize': modelMinPxSize, 'cesiumColor': stripCesiumColor(cesiumColor), 'cesiumWeight': cesiumWeight, 'cesiumStyle': cesiumStyle, 'cesiumOpacity': cesiumOpacity, 'ganttColor': ganttColor, 'popupText': popupText, 'startElevMeters': elev, 'endElevMeters': elev, 'wayname': None, 'waycategory': None, 'surface': None, 'waytype': None, 'steepness': None, 'tollway': None }, ignore_index=True) return assignments
def privGetShapepoints2D(odID=1, objectID=None, modelFile=None, startLoc=None, endLoc=None, startTimeSec=0.0, expDurationSec=None, routeType='euclidean2D', speedMPS=None, leafletColor=VRV_DEFAULT_LEAFLETARCCOLOR, leafletWeight=VRV_DEFAULT_LEAFLETARCWEIGHT, leafletStyle=VRV_DEFAULT_LEAFLETARCSTYLE, leafletOpacity=VRV_DEFAULT_LEAFLETARCOPACITY, useArrows=True, modelScale=VRV_DEFAULT_CESIUMMODELSCALE, modelMinPxSize=VRV_DEFAULT_CESIUMMODELMINPXSIZE, cesiumColor=VRV_DEFAULT_CESIUMPATHCOLOR, cesiumWeight=VRV_DEFAULT_CESIUMPATHWEIGHT, cesiumStyle=VRV_DEFAULT_CESIUMPATHSTYLE, cesiumOpacity=VRV_DEFAULT_CESIUMPATHOPACITY, dataProvider=None, dataProviderArgs=None): # Replace backslash modelFile = replaceBackslashToSlash(modelFile) try: dataProvider = dataProvider.lower() except: pass try: routeType = routeType.lower() except: pass if (startLoc != endLoc): if (routeType == 'euclidean2d'): [path, time, dist] = _eucGetShapepointsTimeDist(startLoc, endLoc, speedMPS, expDurationSec) elif (routeType == 'manhattan'): [path, time, dist] = _manGetShapepointsTimeDist(startLoc, endLoc, speedMPS, expDurationSec) elif (routeType == 'fastest' and dataProviderDictionary[dataProvider] == 'pgrouting'): databaseName = dataProviderArgs['databaseName'] [path, time, dist] = pgrGetShapepointsTimeDist(startLoc, endLoc, databaseName) elif (routeType == 'fastest' and dataProviderDictionary[dataProvider] == 'osrm-online'): [path, time, dist] = osrmGetShapepointsTimeDist(startLoc, endLoc) elif (routeType in ['fastest', 'shortest', 'pedestrian'] and dataProviderDictionary[dataProvider] == 'mapquest'): APIkey = dataProviderArgs['APIkey'] [path, time, dist] = mqGetShapepointsTimeDist(startLoc, endLoc, routeType, APIkey) elif (routeType in ['fastest', 'pedestrian', 'cycling', 'truck'] and dataProviderDictionary[dataProvider] == 'ors-online'): APIkey = dataProviderArgs['APIkey'] [path, time, dist] = orsGetShapepointsTimeDist(startLoc, endLoc, routeType, APIkey) else: return # Check if the original point is too far away from the actual start point of the shapepoints from query distOri = geoDistance2D(startLoc, path[0]) if (distOri >= VRV_DEFAULT_DISTANCE_ERROR_TOLERANCE ): # Go back to 10m after testing print( "Message: The origin point (lat: %s, lon: %s) is %.1f meters away from the road. You might find a gap between the origin point and the route." % (startLoc[0], startLoc[1], distOri)) # Check if the actual end point is too far away from destination point distDes = geoDistance2D(path[-1], endLoc) if (distDes >= VRV_DEFAULT_DISTANCE_ERROR_TOLERANCE ): # Go back to 10m after testing print( "Message: The destination point (lat: %s, lon: %s) is %.1f meters away from the road. You might find a gap between destination point and the route." % (endLoc[0], endLoc[1], distDes)) # convert distance to accumulated distance accDist = [] accDist.append(0) for i in range(1, len(dist)): accDist.append(accDist[i - 1] + dist[i]) # If `expDurationSec` is provided, override `speedMPS` and datasource, otherwise, if `speedMPS` is provided, override datasource if (expDurationSec != None): [newTime, newDist] = distributeTimeDist(path, expDurationSec) time = newTime dist = newDist elif (speedMPS != None and expDurationSec == None): newExpDurationSec = accDist[len(accDist) - 1] / speedMPS [newTime, newDist] = distributeTimeDist(path, newExpDurationSec) time = newTime dist = newDist # convert time to accumulated time accTime = [] accTime.append(startTimeSec) for i in range(1, len(dist)): accTime.append(accTime[i - 1] + time[i]) # For maintainability, convert locs into dictionary dicPath = locs2Dict(path) # shapepoint dataframe assignments = initDataframe('Assignments') # generate assignments for i in range(1, len(path)): assignments = assignments.append( { 'odID': odID, 'objectID': objectID, 'modelFile': modelFile, 'startTimeSec': accTime[i - 1], 'startLat': dicPath[i - 1]['lat'], 'startLon': dicPath[i - 1]['lon'], 'startAltMeters': dicPath[i - 1]['alt'], 'endTimeSec': accTime[i], 'endLat': dicPath[i]['lat'], 'endLon': dicPath[i]['lon'], 'endAltMeters': dicPath[i]['alt'], 'leafletColor': leafletColor, 'leafletWeight': leafletWeight, 'leafletStyle': leafletStyle, 'useArrows': useArrows, 'leafletOpacity': leafletOpacity, 'modelScale': modelScale, 'modelMinPxSize': modelMinPxSize, 'cesiumColor': cesiumColor, 'cesiumWeight': cesiumWeight, 'cesiumStyle': cesiumStyle, 'cesiumOpacity': cesiumOpacity }, ignore_index=True) else: # For maintainability, convert locs into dictionary dicStartLoc = loc2Dict(startLoc) assignments = initDataframe('Assignments') assignments = assignments.append( { 'odID': odID, 'objectID': objectID, 'modelFile': modelFile, 'startTimeSec': startTimeSec, 'startLat': dicStartLoc['lat'], 'startLon': dicStartLoc['lon'], 'startAltMeters': dicStartLoc['alt'], 'endTimeSec': expDurationSec + startTimeSec if (expDurationSec is not None) else startTimeSec, 'endLat': dicStartLoc['lat'], 'endLon': dicStartLoc['lon'], 'endAltMeters': dicStartLoc['alt'], 'leafletColor': leafletColor, 'leafletWeight': leafletWeight, 'leafletStyle': leafletStyle, 'useArrows': useArrows, 'leafletOpacity': leafletOpacity, 'modelScale': modelScale, 'modelMinPxSize': modelMinPxSize, 'cesiumColor': cesiumColor, 'cesiumWeight': cesiumWeight, 'cesiumStyle': cesiumStyle, 'cesiumOpacity': cesiumOpacity }, ignore_index=True) return assignments
def mqGetShapepointsTimeDist(startLoc, endLoc, routeType='fastest', APIkey=None): """ A function to get a list of shapepoints from start coordinate to end coordinate Parameters ---------- startLoc: list, Required Start location, the format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt] endLoc: list, Required End location, the format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt] routeType: string, Optional, default as 'fastest' Route type of MapQuest query APIkey: string, Required Enables us to access to MapQuest server Returns ------- path: list of lists A list of coordinates in sequence that shape the route from startLoc to endLoc time: float time between current shapepoint and previous shapepoint, the first element should be 0 dist: float distance between current shapepoint and previous shapepoint, the first element should be 0 """ try: routeType = routeType.lower() except: pass dicStartLoc = loc2Dict(startLoc) dicEndLoc = loc2Dict(endLoc) shapepointsUrl = ( 'http://www.mapquestapi.com/directions/v2/route?key=%s&from=%s,%s&to=%s,%s&fullShape=true&routeType=%s' ) % (APIkey, dicStartLoc['lat'], dicStartLoc['lon'], dicEndLoc['lat'], dicEndLoc['lon'], routeType) data = [] try: http = urllib3.PoolManager() response = http.request('GET', shapepointsUrl) data = json.loads(response.data.decode('utf-8')) path = [] totalTimeInSeconds = data['route']['time'] maneuverIndexes = data['route']['shape']['maneuverIndexes'] rawShapepoints = data['route']['shape']['shapePoints'] for i in range(int(len(rawShapepoints) / 2)): if (len(path) > 0): if (rawShapepoints[i * 2] != path[-1][0] and rawShapepoints[i * 2 + 1] != path[-1][1]): path.append( [rawShapepoints[i * 2], rawShapepoints[i * 2 + 1]]) else: path.append([rawShapepoints[0], rawShapepoints[1]]) [timeSecs, distMeters] = distributeTimeDist(path, totalTimeInSeconds) except: print( "Message: Unable to connect MapQuest, the most common causes are 1) that your computer isn't connected to the network; 2) an invalid key is provided." ) return [path, timeSecs, distMeters]
def orsGetShapepointsTimeDist(startLoc, endLoc, travelMode='fastest', APIkey=None): """ A function to get a list of shapepoints from start coordinate to end coordinate. Parameters ---------- startLoc: list Start location. The format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt] endLoc: list End location. The format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt] travelMode: string, {fastest} Optional, default as 'fastest'. Choose a travel mode as a parameter for ORS Returns ------- path: list of lists A list of coordinates in sequence that shape the route from startLoc to endLoc timeInSeconds: double FIXME???? time between current shapepoint and previous shapepoint, the first element should be 0 FIXME??? distInMeters: double FIXME??? distance between current shapepoint and previous shapepoint, the first element should be 0 FIXME??? """ dicStartLoc = loc2Dict(startLoc) dicEndLoc = loc2Dict(endLoc) """ The following "profile" options are available in ORS: 'driving-car' ('fastest') 'driving-hgv' ('truck' - fastest) 'cycling-regular' ('cycling') 'cycling-road' 'cycling-mountain' 'cycling-electric' 'foot-walking' 'foot-hiking' 'wheelchair' There is no "shortest" option """ try: travelMode = travelMode.lower() except: pass if (travelMode == 'fastest'): profile = 'driving-car' elif (travelMode == 'pedestrian'): profile = 'foot-walking' elif (travelMode == 'cycling'): profile = 'cycling-road' elif (travelMode == 'truck'): profile = 'driving-hgv' else: print("Error: Invalid travelMode.") return # ORS uses [lon, lat] order: shapepointsUrl = ( 'https://api.openrouteservice.org/v2/directions/%s?api_key=%s&start=%s,%s&end=%s,%s' % (profile, APIkey, dicStartLoc['lon'], dicStartLoc['lat'], dicEndLoc['lon'], dicEndLoc['lat'])) try: http = urllib3.PoolManager() response = http.request('GET', shapepointsUrl) data = json.loads(response.data.decode('utf-8')) http_status = response.status if (http_status == 200): # OK # ORS uses [lon, lat] order: path = [] timeInSeconds = [] distInMeters = [] for i in range(len( data['features'][0]['geometry']['coordinates'])): path.append([ data['features'][0]['geometry']['coordinates'][i][1], data['features'][0]['geometry']['coordinates'][i][0] ]) for i in range(len(data['features'][0]['properties']['segments'])): for j in range( len(data['features'][0]['properties']['segments'][i] ['steps'])): # Find arrival times for each shapepoint location. # ORS gives times for groups of waypoints...we need more granularity. subpathTimeSec = data['features'][0]['properties'][ 'segments'][i]['steps'][j]['duration'] wpStart = data['features'][0]['properties']['segments'][i][ 'steps'][j]['way_points'][0] wpEnd = data['features'][0]['properties']['segments'][i][ 'steps'][j]['way_points'][1] [tmpTimeSec, tmpDistMeters ] = distributeTimeDist(path[wpStart:wpEnd + 1], subpathTimeSec) if (len(timeInSeconds) == 0): timeInSeconds += tmpTimeSec distInMeters += tmpDistMeters else: timeInSeconds += tmpTimeSec[1:] distInMeters += tmpDistMeters[1:] return [path, timeInSeconds, distInMeters] else: # Error of some kind http_status_description = responses[http_status] print("Error Code %s: %s" % (http_status, http_status_description)) return except: print("Error: ", sys.exc_info()[1]) raise
def privAddStaticAssignment( initAssignments=None, odID=1, objectID=None, modelFile=None, modelScale=config['VRV_DEFAULT_CESIUMMODELSCALE'], modelMinPxSize=config['VRV_DEFAULT_CESIUMMODELMINPXSIZE'], loc=None, startTimeSec=None, endTimeSec=None, ganttColor=config['VRV_DEFAULT_GANTTCOLOR'], popupText=None): # Replace backslash modelFile = replaceBackslashToSlash(modelFile) # Ensure leading slash modelFile = addHeadSlash(modelFile) # assignment dataframe assignments = privInitDataframe('Assignments') dicLoc = loc2Dict(loc) assignments = assignments.append( { 'odID': odID, 'objectID': objectID, 'modelFile': modelFile, 'modelScale': modelScale, 'modelMinPxSize': modelMinPxSize, 'startTimeSec': startTimeSec, 'startLat': dicLoc['lat'], 'startLon': dicLoc['lon'], 'startAltMeters': dicLoc['alt'], 'endTimeSec': endTimeSec, 'endLat': dicLoc['lat'], 'endLon': dicLoc['lon'], 'endAltMeters': dicLoc['alt'], 'ganttColor': ganttColor, 'popupText': popupText, 'leafletColor': None, 'leafletWeight': None, 'leafletStyle': None, 'leafletOpacity': None, 'leafletCurveType': None, 'leafletCurvature': None, 'cesiumColor': None, 'cesiumWeight': None, 'cesiumStyle': None, 'cesiumOpacity': None, 'useArrows': None, 'startElevMeters': None, 'endElevMeters': None, 'wayname': None, 'waycategory': None, 'surface': None, 'waytype': None, 'steepness': None, 'tollway': None }, ignore_index=True, sort=False) if (type(initAssignments) is pd.core.frame.DataFrame): assignments = pd.concat([initAssignments, assignments], ignore_index=True) return assignments
def _buildFlightProfile(startLoc, cruiseAltMetersAGL, endLoc, takeoffSpeedMPS, rateOfClimbMPS, cruiseSpeedMPS, landSpeedMPS, rateOfDescentMPS): """ Build a flight profile, by profile, it means it has take_off/cruise/loiter(mission)/landing phase, if we want to construct a customized profile, use _buildFlightPath Parameters ---------- startLoc: list Start location, the format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt]. cruiseAltMetersAGL: float Cruise altitude, meters above sea level. endLoc: list End location, the format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt]. rateOfClimbMPS: float Rate of climb of the aircraft, it is a vertical speed. climbGradientInDegree: float Climb gradient, the unit is degree, horizontal as zero, minimal value as 0, maximum value as 90 (vertical up). cruiseSpeedMPS: float Speed of cruise, in the unit of meters/second. rateOfDescentMPS: float Rate of descent, vertical speed. descentGradientInDegree: float Descent gradient, the unit is degree, horizontal as zero, minimal value as 0, maximum value as 90 (vertical down). Return ------ flight dataframe A dataframe to be interpreted into assignments dataframe """ # Interpret locations into readable dictionary dicStartLoc = loc2Dict(startLoc) dicEndLoc = loc2Dict(endLoc) # Calculate gradients of climbing and landing climbGradientInDegree = math.degrees( math.asin(rateOfClimbMPS / takeoffSpeedMPS)) descentGradientInDegree = math.degrees( math.asin(rateOfDescentMPS / landSpeedMPS)) # calculate the ideal takeoff/landing time/ground distance idealTakeoffTimeSec = (cruiseAltMetersAGL - dicStartLoc['alt']) / rateOfClimbMPS idealTakeoffGroundDistance = (cruiseAltMetersAGL - dicStartLoc['alt']) / math.tan( math.radians(climbGradientInDegree)) idealLandingTimeSec = (cruiseAltMetersAGL - dicEndLoc['alt']) / rateOfDescentMPS idealLandingGroundDistance = (cruiseAltMetersAGL - dicEndLoc['alt']) / math.tan( math.radians(descentGradientInDegree)) # including start and end, takeoffAt and arrivalAt are not included in here markPath = [startLoc, endLoc] # Total ground distance totalGroundDistance = geoDistancePath2D(markPath) # Flight Profile dataframe flight = pd.DataFrame(columns=[ 'lat', 'lon', 'altAGL', 'accuGroundDistance', 'description', 'loiterTime' ]) # For the first location, add one row flight = flight.append( { 'lat': dicStartLoc['lat'], 'lon': dicStartLoc['lon'], 'altAGL': dicStartLoc['alt'], 'accuGroundDistance': 0.0, 'description': "beforeTakeoff", 'loiterTime': 0.0 }, ignore_index=True) # Check if distance is enough for taking off and landing if (totalGroundDistance > idealTakeoffGroundDistance + idealLandingGroundDistance): # if can reach cruise altitude, everything is ideal takeoffMileage = geoMileageInPath2D(markPath, idealTakeoffGroundDistance) landingMileage = geoMileageInPath2D( markPath, totalGroundDistance - idealLandingGroundDistance) # if can cruise, it means we need two locations flight = flight.append( { 'lat': takeoffMileage['loc'][0], 'lon': takeoffMileage['loc'][1], 'altAGL': cruiseAltMetersAGL, 'accuGroundDistance': idealTakeoffGroundDistance, 'description': "takeoffAtAlt", 'loiterTime': 0.0 }, ignore_index=True) flight = flight.append( { 'lat': landingMileage['loc'][0], 'lon': landingMileage['loc'][1], 'altAGL': cruiseAltMetersAGL, 'accuGroundDistance': totalGroundDistance - idealLandingGroundDistance, 'description': "arrivalAtAlt", 'loiterTime': 0.0 }, ignore_index=True) else: # if can not reach cruise altitude, the profile is "triangle", i.e. the takeoffAt position are the same as arrivalAt position deltaAGLTakeoffLanding = dicStartLoc['alt'] - dicEndLoc['alt'] deltaAGLCruiseTakeoff = ( (totalGroundDistance - deltaAGLTakeoffLanding / math.tan(math.radians(descentGradientInDegree))) * (math.tan(math.radians(climbGradientInDegree)) + math.tan(math.radians(descentGradientInDegree)))) deltaAGLCruiseLanding = deltaAGLCruiseTakeoff + deltaAGLTakeoffLanding takeoffGroundDistance = deltaAGLCruiseTakeoff / math.tan( math.radians(climbGradientInDegree)) landingGroundDistance = deltaAGLCruiseLanding / math.tan( math.radians(descentGradientInDegree)) takeoffMileage = geoMileageInPath2D(markPath, takeoffGroundDistance) flight = flight.append( { 'lat': takeoffMileage['loc'][0], 'lon': takeoffMileage['loc'][1], 'altAGL': deltaAGLCruiseTakeoff + dicStartLoc['alt'], 'accuGroundDistance': takeoffGroundDistance, 'description': "takeoffAtAlt and arrivalAtAlt", 'loiterTime': 0.0 }, ignore_index=True) # For the last location, add one row flight = flight.append( { 'lat': dicEndLoc['lat'], 'lon': dicEndLoc['lon'], 'altAGL': dicEndLoc['alt'], 'accuGroundDistance': totalGroundDistance, 'description': "afterArrival", 'loiterTime': 0.0 }, ignore_index=True) # Reorder flight in order flight = flight.sort_values('accuGroundDistance', ascending=True) flight = flight.reset_index(drop=True) # Add the 'groundDistance' column to flight dataframe groundDistance = [0.0] for i in range(1, len(flight)): groundDistance.append( geoDistance2D( (flight.iloc[i]['lat'], flight.iloc[i]['lon']), (flight.iloc[i - 1]['lat'], flight.iloc[i - 1]['lon']))) flight['groundDistance'] = groundDistance # Add the 'flightDistance' column to flight dataframe flightDistance = [0.0] for i in range(1, len(flight)): deltaHeight = flight.iloc[i]['altAGL'] - flight.iloc[i - 1]['altAGL'] groundDistance = flight.iloc[i]['groundDistance'] flightDistance.append( math.sqrt(deltaHeight * deltaHeight + groundDistance * groundDistance)) flight['flightDistance'] = flightDistance # Add the 'accuFlightDistance' column to flight dataframe accuFlightDistance = [0.0] for i in range(1, len(flight)): accuFlightDistance.append(accuFlightDistance[i - 1] + flight.iloc[i]['flightDistance']) flight['accuFlightDistance'] = accuFlightDistance # Add the 'time' column to flight dataframe duration = [0.0] for i in range(1, len(flight)): if (flight.iloc[i]['description'] == "takeoffAtAlt" or flight.iloc[i]['description'] == "takeoffAtAlt and arrivalAtAlt"): speed = takeoffSpeedMPS duration.append(flight.iloc[i]['flightDistance'] / speed) elif (flight.iloc[i]['description'] == "arrivalAtAlt"): speed = cruiseSpeedMPS duration.append(flight.iloc[i]['flightDistance'] / speed) elif (flight.iloc[i]['description'] == "afterArrival"): speed = landSpeedMPS duration.append(flight.iloc[i]['flightDistance'] / speed) flight['timeFromPreviousPosition'] = duration # Add the 'accuTime' column to flight dataframe startTimeSec = [] endTimeSec = [] startTimeSec.append(0.0) endTimeSec.append(flight.iloc[0]['loiterTime']) for i in range(1, len(flight)): startTimeSec.append(endTimeSec[i - 1] + flight.iloc[i]['timeFromPreviousPosition']) endTimeSec.append(endTimeSec[i - 1] + flight.iloc[i]['timeFromPreviousPosition'] + flight.iloc[i]['loiterTime']) flight['pathStartTimeSec'] = startTimeSec flight['pathEndTimeSec'] = endTimeSec return flight
def orsLocalGetShapepointsTimeDist(startLoc, endLoc, travelMode='fastest', port=8081, requestExtras=True): """ A function to get a list of shapepoints from start coordinate to end coordinate. Parameters ---------- startLoc: list Start location. The format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt] endLoc: list End location. The format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt] travelMode: string, {fastest} Optional, default as 'fastest'. Choose a travel mode as a parameter for ORS Returns ------- path: list of lists A list of coordinates in sequence that shape the route from startLoc to endLoc extras: dictionary of dictionaries Describes extra information, such as waynames, waytypes, elevation, etc. timeInSeconds: list time between current shapepoint and previous shapepoint, the first element should be 0 distInMeters: list distance between current shapepoint and previous shapepoint, the first element should be 0 """ dicStartLoc = loc2Dict(startLoc) dicEndLoc = loc2Dict(endLoc) """ The following "profile" options are available in ORS: 'driving-car' ('fastest') 'driving-hgv' ('truck' - fastest) 'cycling-regular' ('cycling') 'cycling-road' 'cycling-mountain' 'cycling-electric' 'foot-walking' 'foot-hiking' 'wheelchair' """ units = 'm' preference = 'fastest' try: travelMode = travelMode.lower() except: pass if (travelMode == 'fastest'): profile = 'driving-car' elif (travelMode == 'shortest'): profile = 'driving-car' preference = 'shortest' elif (travelMode == 'pedestrian'): profile = 'foot-walking' elif (travelMode == 'cycling'): profile = 'cycling-road' elif (travelMode == 'truck'): profile = 'driving-hgv' # elif (travelMode == 'wheelchair'): # profile = 'wheelchair' else: print("Error: Invalid travelMode.") return spUrl = ('http://localhost:%s/ors/directions?profile=%s' % (port, profile)) spUrl += '&coordinates=%s,%s|%s,%s' % (dicStartLoc['lon'], dicStartLoc['lat'], dicEndLoc['lon'], dicEndLoc['lat']) spUrl += '&geometry_format=geojson' if (requestExtras): spUrl += '&extra_info=steepness|surface|waycategory|waytype|tollways' elevation = "true" else: elevation = "false" spUrl += '&elevation=%s' % (elevation) spUrl += '&radiuses=-1|-1' spUrl += '&units=m' spUrl += '&instructions=true' spUrl += '&preference=%s' % (preference) try: http = urllib3.PoolManager() response = http.request('GET', spUrl) data = json.loads(response.data.decode('utf-8')) http_status = response.status if (http_status == 200): # OK # ORS uses [lon, lat] order: path = [] extras = {} timeInSeconds = [] distInMeters = [] for i in range(len(data['routes'][0]['geometry']['coordinates'])): path.append([ data['routes'][0]['geometry']['coordinates'][i][1], data['routes'][0]['geometry']['coordinates'][i][0] ]) if (requestExtras): extras[i] = {} if (len(data['routes'][0]['geometry']['coordinates'][i]) >= 2): extras[i]['elev'] = data['routes'][0]['geometry'][ 'coordinates'][i][2] else: extras[i]['elev'] = None segs = data['routes'][0]['segments'] for i in range(len(segs)): for j in range(len(segs[i]['steps'])): # Find arrival times for each shapepoint location. # ORS gives times for groups of waypoints...we need more granularity. subpathTimeSec = segs[i]['steps'][j]['duration'] wpStart = segs[i]['steps'][j]['way_points'][0] wpEnd = segs[i]['steps'][j]['way_points'][1] [tmpTimeSec, tmpDistMeters ] = distributeTimeDist(path[wpStart:wpEnd + 1], subpathTimeSec) if (len(timeInSeconds) == 0): timeInSeconds += tmpTimeSec distInMeters += tmpDistMeters else: timeInSeconds += tmpTimeSec[1:] distInMeters += tmpDistMeters[1:] if (requestExtras): if (wpStart == 0): extras[0]['wayname'] = segs[i]['steps'][j]['name'] for k in range(wpStart + 1, wpEnd + 1): extras[k]['wayname'] = segs[i]['steps'][j]['name'] if (requestExtras): ex = data['routes'][0]['extras'] if ('waycategory' in ex): for [wpStart, wpEnd, val] in ex['waycategory']['values']: if (wpStart == 0): extras[0]['waycategory'] = bitFieldDecomp( val, orsWaycategoryDict) for i in range(wpStart + 1, wpEnd + 1): extras[i]['waycategory'] = bitFieldDecomp( val, orsWaycategoryDict) if ('surface' in ex): for [wpStart, wpEnd, val] in ex['surface']['values']: if (wpStart == 0): extras[0]['surface'] = orsSurfaceDict[ val] if val in orsSurfaceDict else None for i in range(wpStart + 1, wpEnd + 1): extras[i]['surface'] = orsSurfaceDict[ val] if val in orsSurfaceDict else None if ('waytypes' in ex): for [wpStart, wpEnd, val] in ex['waytypes']['values']: if (wpStart == 0): extras[0]['waytype'] = orsWaytypeDict[ val] if val in orsWaytypeDict else None for i in range(wpStart + 1, wpEnd + 1): extras[i]['waytype'] = orsWaytypeDict[ val] if val in orsWaytypeDict else None if ('steepness' in ex): for [wpStart, wpEnd, val] in ex['steepness']['values']: if (wpStart == 0): extras[0]['steepness'] = val for i in range(wpStart + 1, wpEnd + 1): extras[i]['steepness'] = val if ('tollways' in ex): for [wpStart, wpEnd, val] in ex['tollways']['values']: if (wpStart == 0): extras[0]['tollway'] = bool( val) if type(val) is bool else None for i in range(wpStart + 1, wpEnd + 1): extras[i]['tollway'] = bool( val) if type(val) is bool else None # Just for fun, let's print some other info we got (but didn't save): # print("ascent: {}".format(data['features'][0]['properties']['ascent'])) # print("descent: {}".format(data['features'][0]['properties']['descent'])) return [path, extras, timeInSeconds, distInMeters] else: # Error of some kind http_status_description = responses[http_status] print("Error Code %s: %s" % (http_status, http_status_description)) return except: print("Error: ", sys.exc_info()[1]) raise
def orsGetShapepointsTimeDist(startLoc, endLoc, travelMode='fastest', APIkey=None, requestExtras=True): """ A function to get a list of shapepoints from start coordinate to end coordinate. Parameters ---------- startLoc: list Start location. The format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt] endLoc: list End location. The format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt] travelMode: string, {fastest} Optional, default as 'fastest'. Choose a travel mode as a parameter for ORS Returns ------- path: list of lists A list of coordinates in sequence that shape the route from startLoc to endLoc extras: dictionary of dictionaries Describes extra information, such as waynames, waytypes, elevation, etc. timeInSeconds: list time between current shapepoint and previous shapepoint, the first element should be 0 distInMeters: list distance between current shapepoint and previous shapepoint, the first element should be 0 """ dicStartLoc = loc2Dict(startLoc) dicEndLoc = loc2Dict(endLoc) """ The following "profile" options are available in ORS: 'driving-car' ('fastest') 'driving-hgv' ('truck' - fastest) 'cycling-regular' ('cycling') 'cycling-road' 'cycling-mountain' 'cycling-electric' 'foot-walking' 'foot-hiking' 'wheelchair' There is no "shortest" option """ preference = 'fastest' try: travelMode = travelMode.lower() except: pass if (travelMode == 'fastest'): profile = 'driving-car' elif (travelMode == 'shortest'): profile = 'driving-car' preference = 'shortest' elif (travelMode == 'pedestrian'): profile = 'foot-walking' elif (travelMode == 'cycling'): profile = 'cycling-road' elif (travelMode == 'truck'): profile = 'driving-hgv' elif (travelMode == 'wheelchair'): profile = 'wheelchair' else: print("Error: Invalid travelMode.") return shapepointsUrl = ( 'https://api.openrouteservice.org/v2/directions/%s/geojson' % (profile)) headers = { 'Accept': 'application/json, application/geo+json, application/gpx+xml, img/png; charset=utf-8', 'Authorization': APIkey, 'Content-Type': 'application/json' } try: # ORS uses [lon, lat] order: coordinates = [[dicStartLoc['lon'], dicStartLoc['lat']], [dicEndLoc['lon'], dicEndLoc['lat']]] units = 'm' radiuses = [-1, -1] if (requestExtras): elevation = "true" extra_info = [ "steepness", "surface", "waycategory", "waytype", "tollways" ] else: elevation = "false" extra_info = [] encoded_body = json.dumps({ "coordinates": coordinates, "elevation": elevation, "extra_info": extra_info, "instructions": "true", "preference": preference, "radiuses": radiuses, "units": units }) http = urllib3.PoolManager() response = http.request('POST', shapepointsUrl, headers=headers, body=encoded_body) data = json.loads(response.data.decode('utf-8')) http_status = response.status if (http_status == 200): # OK # ORS uses [lon, lat] order: path = [] extras = {} timeInSeconds = [] distInMeters = [] for i in range(len( data['features'][0]['geometry']['coordinates'])): path.append([ data['features'][0]['geometry']['coordinates'][i][1], data['features'][0]['geometry']['coordinates'][i][0] ]) if (requestExtras): extras[i] = {} if (len(data['features'][0]['geometry']['coordinates'][i]) >= 2): extras[i]['elev'] = data['features'][0]['geometry'][ 'coordinates'][i][2] else: extras[i]['elev'] = None segs = data['features'][0]['properties']['segments'] for i in range(len(segs)): for j in range(len(segs[i]['steps'])): # Find arrival times for each shapepoint location. # ORS gives times for groups of waypoints...we need more granularity. subpathTimeSec = segs[i]['steps'][j]['duration'] wpStart = segs[i]['steps'][j]['way_points'][0] wpEnd = segs[i]['steps'][j]['way_points'][1] [tmpTimeSec, tmpDistMeters ] = distributeTimeDist(path[wpStart:wpEnd + 1], subpathTimeSec) if (len(timeInSeconds) == 0): timeInSeconds += tmpTimeSec distInMeters += tmpDistMeters else: timeInSeconds += tmpTimeSec[1:] distInMeters += tmpDistMeters[1:] if (requestExtras): if (wpStart == 0): extras[0]['wayname'] = segs[i]['steps'][j]['name'] for k in range(wpStart + 1, wpEnd + 1): extras[k]['wayname'] = segs[i]['steps'][j]['name'] if (requestExtras): ex = data['features'][0]['properties']['extras'] if ('waycategory' in ex): for [wpStart, wpEnd, val] in ex['waycategory']['values']: if (wpStart == 0): extras[0]['waycategory'] = bitFieldDecomp( val, orsWaycategoryDict) for i in range(wpStart + 1, wpEnd + 1): extras[i]['waycategory'] = bitFieldDecomp( val, orsWaycategoryDict) if ('surface' in ex): for [wpStart, wpEnd, val] in ex['surface']['values']: if (wpStart == 0): extras[0]['surface'] = orsSurfaceDict[ val] if val in orsSurfaceDict else None for i in range(wpStart + 1, wpEnd + 1): extras[i]['surface'] = orsSurfaceDict[ val] if val in orsSurfaceDict else None if ('waytypes' in ex): for [wpStart, wpEnd, val] in ex['waytypes']['values']: if (wpStart == 0): extras[0]['waytype'] = orsWaytypeDict[ val] if val in orsWaytypeDict else None for i in range(wpStart + 1, wpEnd + 1): extras[i]['waytype'] = orsWaytypeDict[ val] if val in orsWaytypeDict else None if ('steepness' in ex): for [wpStart, wpEnd, val] in ex['steepness']['values']: if (wpStart == 0): extras[0]['steepness'] = val for i in range(wpStart + 1, wpEnd + 1): extras[i]['steepness'] = val if ('tollways' in ex): for [wpStart, wpEnd, val] in ex['tollways']['values']: if (wpStart == 0): extras[0]['tollway'] = bool( val) if type(val) is bool else None for i in range(wpStart + 1, wpEnd + 1): extras[i]['tollway'] = bool( val) if type(val) is bool else None # Just for fun, let's print some other info we got (but didn't save): # print("ascent: {}".format(data['features'][0]['properties']['ascent'])) # print("descent: {}".format(data['features'][0]['properties']['descent'])) return [path, extras, timeInSeconds, distInMeters] else: # Error of some kind http_status_description = responses[http_status] print("Error Code %s: %s" % (http_status, http_status_description)) return except: print("Error: ", sys.exc_info()[1]) raise
def orsGetSnapToRoadLatLon(loc, APIkey): """ A function to get snapped latlng for one coordinate using ORS Parameters ---------- loc: list The location to be snapped to road Returns ------- list A snapped location in the format of [lat, lon]. Note that this function will lose the info of altitude of the location. """ # There is no function in ORS that snaps to a road. # Instead, issue a driving request from a location to itself. dicLoc = loc2Dict(loc) snapToRoadUrl = ( 'https://api.openrouteservice.org/v2/directions/driving-car/geojson') headers = { 'Accept': 'application/json, application/geo+json, application/gpx+xml, img/png; charset=utf-8', 'Authorization': APIkey, 'Content-Type': 'application/json' } try: # ORS uses [lon, lat] order: coordinates = [[dicLoc['lon'], dicLoc['lat']], [dicLoc['lon'], dicLoc['lat']]] radiuses = [-1, -1] elevation = "false" extra_info = [] encoded_body = json.dumps({ "coordinates": coordinates, "elevation": elevation, "extra_info": extra_info, "instructions": "false", "radiuses": radiuses }) http = urllib3.PoolManager() response = http.request('POST', snapToRoadUrl, headers=headers, body=encoded_body) data = json.loads(response.data.decode('utf-8')) http_status = response.status if (http_status == 200): # OK # ORS uses [lon, lat] order: snapLoc = [ data['features'][0]['geometry']['coordinates'][0][1], data['features'][0]['geometry']['coordinates'][0][0] ] return snapLoc else: # Error of some kind http_status_description = responses[http_status] print("Error Code %s: %s" % (http_status, http_status_description)) return except: print("Error: ", sys.exc_info()[1]) raise
def buildNoLoiteringFlight(routeType='square', startLoc=None, cruiseAltMetersAGL=None, endLoc=None, takeoffSpeedMPS=None, rateOfClimbMPS=None, cruiseSpeedMPS=None, landSpeedMPS=None, rateOfDescentMPS=None): """ This function generates a flight profile/path given routeType, origin/destinate location and speed of all phase. The profile it generate does not include loiter (i.e. the loiter column is all zero) Parameters ---------- routeType: string, Optional, default as 'square' Type of flight profile/path, options are 'square', 'triangular', 'trapezoidal', 'straight'. startLoc: list, Required, default as 'None' Start location, the format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt]. cruiseAltMetersAGL: float, Required, default as 'None' Cruise altitude, meters above sea level. endLoc: list, Required, default as 'None' End location, the format is [lat, lon] (altitude, above sea level, set to be 0) or [lat, lon, alt]. rateOfClimbMPS: float, Required, default as 'None' Rate of climb of the aircraft, it is a vertical speed. climbGradientInDegree: float, Required, default as 'None' Climb gradient, the unit is degree, horizontal as zero, minimal value as 0, maximum value as 90 (vertical up). cruiseSpeedMPS: float, Required, default as 'None' Speed of cruise, in the unit of meters/second. rateOfDescentMPS: float, Required, default as 'None' Rate of descent, vertical speed. descentGradientInDegree: float, Required, default as 'None' Descent gradient, the unit is degree, horizontal as zero, minimal value as 0, maximum value as 90 (vertical down). Return ------ flight dataframe A dataframe to be interpreted into assignments dataframe """ try: routeType = routeType.lower() except: pass # Generate flight profile without loitering if (routeType == 'square'): flight = _buildFlightProfile(startLoc=startLoc, cruiseAltMetersAGL=cruiseAltMetersAGL, endLoc=endLoc, takeoffSpeedMPS=takeoffSpeedMPS, rateOfClimbMPS=takeoffSpeedMPS, cruiseSpeedMPS=cruiseSpeedMPS, landSpeedMPS=landSpeedMPS, rateOfDescentMPS=landSpeedMPS) elif (routeType == 'triangular'): dicStartLoc = loc2Dict(startLoc) dicEndLoc = loc2Dict(endLoc) midLoc = [(dicStartLoc['lat'] + dicEndLoc['lat']) / 2, (dicStartLoc['lon'] + dicEndLoc['lon']) / 2, cruiseAltMetersAGL] flight = _buildFlightPath(path=[startLoc, midLoc, endLoc], speedMPS=cruiseSpeedMPS) # There will be only three locations flight.loc[0, 'description'] = "beforeDeparture" flight.loc[1, 'description'] = "takeoffAtAlt and arrivalAtAlt" flight.loc[2, 'description'] = "afterArrival" elif (routeType == 'trapezoidal'): flight = _buildFlightProfile(startLoc=startLoc, cruiseAltMetersAGL=cruiseAltMetersAGL, endLoc=endLoc, takeoffSpeedMPS=takeoffSpeedMPS, rateOfClimbMPS=rateOfClimbMPS, cruiseSpeedMPS=cruiseSpeedMPS, landSpeedMPS=landSpeedMPS, rateOfDescentMPS=rateOfDescentMPS) elif (routeType == 'straight'): flight = _buildFlightPath(path=[startLoc, endLoc], speedMPS=cruiseSpeedMPS) # There will be only two locations flight.loc[0, 'description'] = "beforeDeparture" flight.loc[1, 'description'] = "afterArrival" return flight