bcgov / ols-router

BC Advanced Route Planner
https://bcgov.github.io/ols-router/
Apache License 2.0
23 stars 11 forks source link

What is the road segment weighting formula used by the current route planner? #326

Closed mraross closed 1 year ago

mraross commented 2 years ago

On Thu, Aug 26, 2021 at 3:44 PM Ross, Michael RA CITZ:EX Michael.RA.Ross@gov.bc.ca wrote: Hi Chris, What Is the actual formula for calculating road segment weighting from the truck route multiplier, global and local distortions fields, maxSpeed, and segment length?

mraross commented 2 years ago

From: Chris Hodgson chodgson@refractions.net Sent: August 27, 2021 9:58 AM To: Ross, Michael RA CITZ:EX Michael.RA.Ross@gov.bc.ca Cc: Leeming, Graeme CITZ:IN gleeming@refractions.net; Kelsey, Brian CITZ:EX Brian.Kelsey@gov.bc.ca Subject: Re: In the route planner, what is the road segment weighting formula?

[EXTERNAL] This email came from an external source. Only open attachments or links that you are expecting from a known sender.

Please ignore my confusion about a possible bug, I now believe that code is all correct. The global distortion field only applies to trucks, but it can apply different values to truck routes and non-truck routes. I just have to keep the difference between "truck routing" and a "truck route" straight in my head.

Chris

On Fri, Aug 27, 2021 at 9:40 AM Chris Hodgson chodgson@refractions.net wrote: There is an edge-specific multiplier that is multiplied by the distance or time, depending on shortest vs. fastest:

final CostFunction<Integer,Double,Double,Double> costFunction = params.getCriteria() == RoutingCriteria.SHORTEST ? (edgeId, time, dist) -> dist getMultiplier(edgeId) : (edgeId, time, dist) -> time getMultiplier(edgeId);

(That function is using the ternary operator "a ? b : c" which means "if a then b else c")

The multiplier is calculated here:

private double getMultiplier(int edgeId) { double multiplier = 1; if(params.isFollowTruckRoute() && !graph.isTruckRoute(edgeId)) { multiplier = params.getTruckRouteMultiplier(); } if(params.isEnabled(RouteOption.LOCAL_DISTORTION_FIELD)) { multiplier = graph.getLocalDistortion(edgeId, params.getVehicleType()); } if(params.isEnabled(RouteOption.GLOBAL_DISTORTION_FIELD) && params.getVehicleType() == VehicleType.TRUCK) { multiplier *= params.getGlobalDistortionField().lookup(graph.getRoadClass(edgeId), graph.isTruckRoute(edgeId)); } return multiplier; }

So essentially the truck route multiplier, local distortion field, and global distortion field, are all multiplied together as appropriate. Note that the truck route multiplier is applied to increase the cost of roads that are NOT truck routes.

However, looking at it now, I think there might be a bug in that code... or at least a part that I'm not understanding... I don't think the "&& params.getVehicleType() == VehicleType.TRUCK" in the last "if" should be there as there is also a base/non-truck GDF multiplier value that could be applied to non-trucks. Maybe Graeme or someone else can refresh my memory as to how that base GDF is supposed to work, but I would guess that it isn't working right now.

Chris

alixcote commented 1 year ago

Documented in LOC Confluence. Closing.