Repository navigation
feat: time tracking in Bidirectional A* - #5640
Conversation
| kReverseTTHeuristicFactor, | ||
| forward_time_info, costing_, arrive_by) | ||
| : TimeInfo::invalid()); | ||
| } |
There was a problem hiding this comment.
on the "forward" expansion simply make a regular timeinfo object, and on the other one either
- make a regular one if invariant
- make in invalid one
- or make one based on a heuristic
| offset_time = time_info.forward(seconds_offset, static_cast<int>(nodeinfo->timezone())); | ||
| } else { | ||
| offset_time = time_info.reverse(seconds_offset, static_cast<int>(nodeinfo->timezone())); | ||
| } |
There was a problem hiding this comment.
This actually doesn't change at all, only the offset seconds may be 0 if the time isn't valid in the first place.
| | `admin_crossings` | When present and `true`, the successful route summary will include the two keys `admins` and `admin_crossings`. `admins` is an array of administrative regions the route lies within. `admin_crossings` is an array of objects that contain `from_admin_index` and `to_admin_index`, which are indices into the `admins` array. They also contain `from_shape_index` and `to_shape_index`, which are start and end indices of the edge along which an administrative boundary is crossed. | | ||
| | `turn_lanes` | When present and `true`, each maneuver in the route response can include a `lanes` array describing lane-level guidance. The lanes array details possible `directions`, as well as which lanes are `valid` or `active` for following the maneuver. | ||
| | `turn_lanes` | When present and `true`, each maneuver in the route response can include a `lanes` array describing lane-level guidance. The lanes array details possible `directions`, as well as which lanes are `valid` or `active` for following the maneuver. | | ||
| | `reverse_time_tracking` | Which time tracking strategy to use on the non-time aware expansion in the bidirectional routing algorithm: `invalid` will assume no time, `heuristic` will try a best guess based on the bee line distance between origin and destination. Default `heuristic` | |
There was a problem hiding this comment.
As long as we don't have a battle tested heuristic, users should be able to opt out of it and choose the more conservative method.
There was a problem hiding this comment.
should we mark it BETA? IMO ideally we'd remove this at some point when we either have a good feeling with a simpler heuristic or, less likely, make a more sophisticated one.
| heuristic = 0; | ||
| invalid = 1; |
There was a problem hiding this comment.
did you do this on purpose to make the default (unset) value be new behavior? once upon a time i would be against this to avoid breaking existing users but honestly i feel like sometimes we have to move forward.
also nit: invalid seems a strange word choice, why not disabled or none or something along those lines
There was a problem hiding this comment.
Well both options are new behavior. If someone wants old behavior, they can set date_time type to invariant.
Good point about naming, will change it to something more fitting.
| nodeinfo = endtile->node(directededge->endnode()); | ||
| return time_info.forward(seconds, static_cast<int>(nodeinfo->timezone())); | ||
| } else { | ||
| // in case of depart_at, we want the start node of our correlated edge |
There was a problem hiding this comment.
Not sure we need differentiate which node we take, unless we do better guessing based on the percent_along. TBH I'm ok with leaving a comment and simply take the first or last node no matter if fwd/rev
There was a problem hiding this comment.
I think you might be right, using percent along would be the best we could do probably.
| : distance_meters / (fixed_speed_ * midgard::kKPHtoMetersPerSec) * factor * | ||
| 0.85; // if fixed speed, the factor should be lowered |
There was a problem hiding this comment.
can you comment why it's lower? somehow I don't quite get it
There was a problem hiding this comment.
a vehicle likely won't travel much at top speed, so the actual time will differ from the ideal time both in distance traveled and speed. If fixed speed is set, we know the exact speed and just have to correct the estimate based on bee-line vs real distance, so the difference (what we're trying to correct for using the factor) won't be as large. I can leave a comment above that line.
nilsnolde
left a comment
There was a problem hiding this comment.
looks like a good start! just a few suggestions, and pls some docstrings :)
…to cb-bidir-route-time
| second_of_week = 28800; // arbitrary time to land us within the constrained time window | ||
| } else if (initial_flow_mask & kFreeFlowMask) { | ||
| second_of_week = 0; // ... or within the free flow window | ||
| } |
There was a problem hiding this comment.
this was necessary to keep getting free flow/constrained speeds. This is because of the change in GraphTile::GetSpeed: before, passing an invalid time and the respective mask would give you the one you wanted, faded with live speed. Now you can only fade them with live speed if the time is valid, so it would use that time to see in which time window you are (either free flow or constrained), so you could only get either one or the other. So we just set it to a value here to make the time fall into the window we want.
| EXPECT_NEAR(edges[1]["speeds_faded"]["predicted_flow"].GetInt(), | ||
| current * multiplier_inverse + predicted * multiplier, 1); | ||
| EXPECT_NEAR(edges[1]["speeds_faded"]["no_flow"].GetInt(), | ||
| current * multiplier_inverse + base * multiplier, 1); |
There was a problem hiding this comment.
The only thing that changed here are the multipliers, which I am pretty sure is due to meili/trace_attributes being non-time aware: before, it would always use live speeds, regardless of the date time, but now it will just fall back to constrained/free_flow if available.
|
@janusz-anue Just a heads-up: I had to tweak the logic for getting faded/non-faded speed attributes a little to not break that functionality. Would appreciate it if you could have a quick look at some point! The only change that made this necessary is that we'd now require a valid time to get live speeds: valhalla/valhalla/baldr/graphtile.h Lines 665 to 667 in bd81efc |
nilsnolde
left a comment
There was a problem hiding this comment.
looks good, other than possibly having spotted a bug. but I might have a knot in my brain as well..
| | `admin_crossings` | When present and `true`, the successful route summary will include the two keys `admins` and `admin_crossings`. `admins` is an array of administrative regions the route lies within. `admin_crossings` is an array of objects that contain `from_admin_index` and `to_admin_index`, which are indices into the `admins` array. They also contain `from_shape_index` and `to_shape_index`, which are start and end indices of the edge along which an administrative boundary is crossed. | | ||
| | `turn_lanes` | When present and `true`, each maneuver in the route response can include a `lanes` array describing lane-level guidance. The lanes array details possible `directions`, as well as which lanes are `valid` or `active` for following the maneuver. | ||
| | `turn_lanes` | When present and `true`, each maneuver in the route response can include a `lanes` array describing lane-level guidance. The lanes array details possible `directions`, as well as which lanes are `valid` or `active` for following the maneuver. | | ||
| | `reverse_time_tracking` | Which time tracking strategy to use on the non-time aware expansion in the bidirectional routing algorithm: `disabled` will assume no time, `heuristic` will try a best guess based on the bee line distance between origin and destination. Default `heuristic` | |
There was a problem hiding this comment.
I asked about labeling it maybe BETA but maybe you didn't see that: #5640 (comment). WDYT?
| } | ||
|
|
||
| enum ReverseTimeTracking { | ||
| heuristic = 0; |
There was a problem hiding this comment.
maybe prefix the members with rtt_ or so. a very annoying thing in pbf is that enum members are children of the parent, i.e. this is Options::disabled etc, where disabled is a bit generic for the whole Options object
| nodeinfo = tile->node(opp_edge->endnode()); | ||
| } | ||
|
|
||
| return arrive_by ? time_info.forward(seconds, static_cast<int>(nodeinfo->timezone())) |
There was a problem hiding this comment.
shouldn't this be the other way around? if we're on arrive_by, the time_info here is somewhere in the future (at the destination) and we want to go back in time to propose an origin date_time, no?
| } | ||
|
|
||
| TEST_F(MatrixTrafficTest, TDMatrixWithLiveTraffic) { | ||
| TEST_F(MatrixTrafficTest, DISABLED_TDMatrixWithLiveTraffic) { |
There was a problem hiding this comment.
Currently rewriting these because the ones testing CostMatrix are not working as expected anymore: we used to test live traffic with type set to "current" and would also get the current live speed on the reverse branch, but now we won't, so CostMatrix does not find the optimal path for that particular scenario.
| if (arrive_by) { | ||
| reverse_time_info = TimeInfo::make(destination, graphreader, &tz_cache_); | ||
| forward_time_info = | ||
| reverse_time_tracking == Options_ReverseTimeTracking_heuristic |
There was a problem hiding this comment.
personally I prefer Options::heuristic notation, I find these really hard to read.
…to cb-bidir-route-time
…to cb-bidir-route-time
| second_of_week = 0; | ||
| } | ||
| if (initial_flow_mask == kConstrainedFlowMask) { | ||
| second_of_week = 28800; // arbitrary time to land us within the constrained time window |
There was a problem hiding this comment.
make this a constant (or see if there is one)
| {"DE", {{"highway", "primary"}, {"maxspeed", "100"}}}, | ||
| {"EF", {{"highway", "primary"}, {"maxspeed", "100"}}}, | ||
| {"FG", {{"highway", "primary"}, {"maxspeed", "100"}}}, | ||
| }; |
There was a problem hiding this comment.
see if I can somehow snoop on what the algorithm is actually doing to make sure time is forwarded/reversed correctly.
kevinkreiser
left a comment
There was a problem hiding this comment.
maybe a constant for the constrained week time and maybe see if refactoring the testing to see inside about what its doing with the time tracking is possible but dont let it stop you from merging
…to cb-bidir-route-time
|
I couldn't find an easy way to really snoop on what the algorithm's doing, but I modified the fake costing class so that we record time info objects passed to EdgeCost only when an edge is first reached to make sure we're not looking at time info passed via recosting. |
I wasn't happy with the refactoring I did over in #5638, so I tried again. This time I decided to just go for it and try to find a simple heuristic for estimating the time of arrival/departure on the "far-end" tree.
What this PR does:
arrive_byordepart_at/current)invalid, the more conservative option; assumes no time on this expansion, just like inCostMatrixheuristic, uses a simple calculation based on costing's top_speed/fixed_speed parameters, the bee-line distance between the path edge snapped locations closest to origin/destination and a constant factorWhat this PR doesn't include:
The Factor
It's impossible to come up with something perfect of course, and maybe we can have an array of factors based on e.g. the flow mask or the rough bee line distance. I wrote a little program in Python that went over hundreds of routes in the de_benchmark_routes.txt, trying out factors in the range
[1.0,5.0]. I usedscipy.optimize.minimize_scalarto try to minimize the average difference between the estimation and the actual time, once with plain OSM and once with tiles built from a commercial provider, loaded with predicted speeds, and ran this for auto and truck.I landed somewhere in the range of 1.49 - 1.89, but note that this was using inter-city routes in a not so small country (Germany). I assume the ideal factor will be higher for larger distances, so for now my first estimate is 2.1.