Presentation is loading. Please wait.

Presentation is loading. Please wait.

NYC DOT Open Source Routing

Similar presentations


Presentation on theme: "NYC DOT Open Source Routing"— Presentation transcript:

1 NYC DOT Open Source Routing
PgRouting with LION and CSCL

2 Welcome Joseph Miller Professional Services Engineer
Boundless provides geospatial tools and services for managing data and building applications. Middle Tier Development and Integrator of fun projects including: GeoServer, OpenLayers, GeoShape, GeoGig

3 Problem Statement Goals Assets Research/Survey Technologies Architecture Accomplishments...So Far Lessons Learned and Next Steps Future Steps

4 NYC DOT is responsible for over 6,000 miles of roadway and nearly 800 bridges along with the 24/7 operation of the Staten Island Ferry. They have more than 12,000 signalized intersections and over 300,000 streetlights.

5 Inefficiency NYC Truck Permitting
Large Vehicles Require Trip Specific “Overdimensional” permits The permits specify the details of the route Currently a manual, in-person process Route Must Account For Vehicle weight Vehicle Height Road conditions and closures

6 Overdimensional permits apply to trucks over 800 GVW
Specifics depend on routes, axle spacing, and vehicle configuration 100K+ Permits Issued Statewide Every Year

7 Goals Point to Point Routing Visualization Routing Around Barriers
Use designated truck routes Address POI Lat/Long Routing Around Barriers Real/Near-Real-Time Height Restrictions Weight Restrictions Turn Restrictions Blockages Visualization Route Segments Turn-By-Turn Directions

8

9

10 Assets LION/CSCL Topologically Complete (including z-levels)
Street Names Truck Routes POI

11 Survey Criteria Low or No Cost BYOD Flexible Performant
Low Cost of Integration

12 Tech Considered

13 Open Source Routing Machine
BSD License C++ and LUA OpenStreetMap

14 Why It Fit Fast (Contraction Hierarchy Indexing) Fast and easy install Option to switch between cost profiles Cost profiles are customizable using LUA scripts. Supports partial contraction for quick updates when the data changes

15 Contraction Hierarchies
Illustrated very well here: Routing graph preprocessed to “contract” intermediate nodes that are discovered to be parts of shortest paths

16 https://raw. githubusercontent. com/rodo/osrm-profiles/master/truck
speed_profile = { ["motorway"] = 90, ["motorway_link"] = 75, ["trunk"] = 85, ["trunk_link"] = 70, ["primary"] = 65, ["primary_link"] = 60, ["secondary"] = 55, ["secondary_link"] = 50, ["tertiary"] = 40, ["tertiary_link"] = 30, ["unclassified"] = 25, ["residential"] = 25, ["living_street"] = 10, ["service"] = 15, -- ["track"] = 5, ["ferry"] = 5, ["shuttle_train"] = 10, ["default"] = 10 } take_minimum_of_speeds = false obey_oneway = true obey_bollards = true use_restrictions = true ignore_areas = true -- future feature traffic_signal_penalty = 2 u_turn_penalty = 20 function node_function (node) local barrier = node.tags:Find("barrier") local access = Access.find_access_tag(node, access_tags_hierachy) local traffic_signal = node.tags:Find("highway") --flag node if it carries a traffic light if traffic_signal == "traffic_signals" then node.traffic_light = true; end -- parse access and barrier tags if access and access ~= "" then if access_tag_blacklist[access] then node.bollard = true end elseif barrier and barrier ~= "" then if barrier_whitelist[barrier] then return else node.bollard = true end end end

17 Challenges OSM-centric, challenging to use custom model Partial contraction still requires downtime Partial contraction leads to performance degradation

18 Mapzen Turn-by-Turn/Valhalla
MIT License C++ OpenStreetMap

19 Why It Fit Fast and low memory footprint Flexible storage model using THOR route tiles Lots of Costing Models (profiles) and Costing Model Options SIF allows for custom profiles that can be applied at run time with a minimal performance impact

20 namespace { constexpr float kDefaultManeuverPenalty = 5.0f; // Seconds constexpr float kDefaultDestinationOnlyPenalty = 600.0f; // Seconds constexpr float kDefaultAlleyPenalty = 30.0f; // Seconds constexpr float kDefaultLowClassPenalty = 30.0f; // Seconds constexpr float kDefaultGateCost = 30.0f; // Seconds constexpr float kDefaultGatePenalty = 300.0f; // Seconds constexpr float kDefaultTollBoothCost = 15.0f; // Seconds constexpr float kDefaultTollBoothPenalty = 0.0f; // Seconds constexpr float kDefaultCountryCrossingCost = 600.0f; // Seconds constexpr float kDefaultCountryCrossingPenalty = 0.0f; // Seconds // Default turn costs constexpr float kTCStraight = 0.5f; constexpr float kTCSlight = 0.75f; constexpr float kTCFavorable = 1.0f; constexpr float kTCFavorableSharp = 1.5f; constexpr float kTCCrossing = 2.0f; constexpr float kTCUnfavorable = 2.5f; constexpr float kTCUnfavorableSharp = 3.5f; constexpr float kTCReverse = 5.0f; / Check if access is allowed at the specified node. bool TruckCost::Allowed(const baldr::NodeInfo* node) const { return (node->access() & kTruckAccess); } // Get the cost to traverse the edge in seconds Cost TruckCost::EdgeCost(const DirectedEdge* edge, const uint32_t density) const { float factor = density_factor_[density]; if (edge->truck_route() > 0) { factor *= kTruckRouteFactor; } float sec = 0.0f; if (edge->truck_speed() > 0) sec = (edge->length() * speedfactor_[edge->truck_speed()]); else sec = (edge->length() * speedfactor_[edge->speed()]); return { sec * factor, sec }; }

21 Challenges SIF custom profiles require C++ code Built around OSM data schema, not clear how to add data from custom schemas without transformation

22 GraphHopper https://graphhopper.com/ Apache License V2
Java OpenStreetMap

23 Why It Fit Very fast and low memory footprint in Speedup Mode (Contraction Hierarchy Indexing) Very quick and easy install Option to switch between cost profiles Java API enables custom data models (extend the Reader class) Java API enables on the fly traversal cost and turn restrictions (FlagEncoder classes)

24 protected double getSpeed( OSMWay way ) { String highwayValue = way.getTag("highway"); Integer speed = defaultSpeedMap.get(highwayValue); if (speed == null) throw new IllegalStateException(toString() + ", no speed found for: " + highwayValue + ", tags: " + way); if (highwayValue.equals("track")) { String tt = way.getTag("tracktype"); if (!Helper.isEmpty(tt)) { Integer tInt = trackTypeSpeedMap.get(tt); if (tInt != null) speed = tInt; } } return speed; } restrictions.addAll(Arrays.asList("motorcar", "motor_vehicle", "vehicle", "access")); restrictedValues.add("private"); restrictedValues.add("agricultural"); restrictedValues.add("forestry"); restrictedValues.add("no"); restrictedValues.add("restricted"); restrictedValues.add("delivery"); restrictedValues.add("military"); restrictedValues.add("emergency");

25 Challenges Extending the Reader to read the LION schema would have been taken more time than we had. Use of FlagEncoder dynamically is not compatible with CH Speedup Mode Java codebase/API (for the custom stuff) presents challenge to .NET shop

26 pgRouting http://pgrouting.org/ GPL V2
C++

27 Why It Fit Very simple data schema Right place in the architecture Straightforward to implement custom traversal costs and turn restrictions

28 seq | node | edge | cost | 7 | 6 | | 8 | 7 | | 5 | 8 | | 6 | 11 | | 11 | 13 | | 12 | -1 | 0 (6 rows) SELECT seq, id1 AS node, id2 AS edge, cost FROM pgr_trsp( 'SELECT id, source, target, cost FROM edge_table', , 12, false, false, 'SELECT to_cost, to_edge AS target_id, from_edge || coalesce('','' || via, '''') AS via_path FROM restrictions' );

29 Challenges Slow Spoken language driving directions not included No REST or JavaScript API included

30

31 Technologies PgRouting PostGIS Spring Turn Restricted Shortest Path
Spatial Operators Spatial Indices Spring REST Services Leaflet Basemap Display Vector rendering of routes Click UI

32 Driving Directions API

33 Turn-By-Turn Directions
Based on PostgreSQL functions developed by Stephen Woodbridge Concepts explained: reorder the direction of edge geometry so it flows from start to end compare segment names so we can aggregate multiple adjacent segments with the same name into a single maneuver. compute the turn angles between segments when we are making a turn counting roundabout exits from our entrance point identify a via point check for some degenerate cases like the whole route is on a single segment

34 Columbus Circle is one of only a half dozen traffic circles/roundabouts in NYC. It serves 60K+ vehicles a day.

35 Basic Geocoding Reverse Geocode Forward Geocode
<-> Operator Query for nearest segment St_line_locate_point for percentage Forward Geocode Parse Address using code from JGeocoder ( Use street name and address ranges to find the correct segment and derive percentage

36 Service Wrapper Simple Spring Boot/Spring Web MVC implementation
Direct JDBC calls Easily ported to future ASP.NET/ADO.NET implementation

37 Accomplishments...So Far
Inputs Addresses Truck Route Places Outputs Turn-By-Turn Directions Route Segment Map Display Segment Metadata Topology Connectivity Forward and Reverse Costs Truck Route Identity Route Creation Truck Route Segment Preference Turn Restrictions Height and Weight Restrictions

38

39

40 Accomplishments...So Far
String ddsql = "select (dd).instruction, (dd).geojson,(dd).dist_meters/ as dist_miles from (select imt_drivingDirections(ST_Line_Interpolate_Point(r1.wkb_geometry_ll_simple,"+pct1+"), ST_Line_Interpolate_Point(r2.wkb_geometry_ll_simple,"+pct2+"),eng', 'SELECT seq as gid, source, target, street as name, shape_length/ as distance, (shape_length*.6)::integer as time, wkb_geometry_ll_simple as the_geom FROM pgr_trsp( ''SELECT segmentid::integer as id, source, target, createCostSQL(useTruckRoutes) createReverseCostSQL(useTruckRoutes) ''"+segmentid1+"''::integer, "+pct1+",''"+segmentid2+"''::integer,"+pct2+", true, true, ''SELECT -1::float as to_cost, t_segmentid::integer AS target_id, f_segmentid::text AS via_path FROM turnrestriction'' )as di left JOIN lion pt ON di.id2 = pt.segmentid::integer order by seq') as dd from lion as r1, lion as r2 where r1.segmentid = '"+segmentid1+"' and r2.segmentid = '"+segmentid2+"' ) AS foo;

41 Accomplishments...So Far
private String createCostSQL(boolean useTruckRoutes){ String base =" (case when trafdir=''''A'''' THEN -1 WHEN trafdir='''' '''' THEN -1 WHEN trafdir=''''P'''' THEN -1 WHEN segmentid::integer in(SELECT segmentid FROM physicalrestrictions_populated) THEN -1 "; String basecost = base + "ELSE shape_length END)::float as cost,"; if(useTruckRoutes) basecost = base+"ELSE CASE WHEN segmentid in(SELECT segmentid from all_truck_routes_nyc_lion14a) THEN 0.1 ELSE shape_length END END)::float as cost,"; return basecost; } Accomplishments...So Far

42 Future Steps Truck Class UI to select
Traversal cost/barriers matched to class By weight By Height By Cargo

43 Future Steps Improved Base Segment Traversal Cost Calculations
Speed Limits Historical Traffic Data Web-Based Barrier and Cost Management Map-based barrier creation and editing Visual cues to identify data gaps Potential Height and Weight Restriction Gaps Topology Management

44 Future Steps Route Calculation Performance
Database query optimization Load balanced hardware (pgPool?, Partitioning?) Clean up and transformation of multi-line geometries to single line features Directed Segment Styling (arrows) Integration into the Permitting Process

45


Download ppt "NYC DOT Open Source Routing"

Similar presentations


Ads by Google