-
Notifications
You must be signed in to change notification settings - Fork 661
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unify Time Tracking in all the Algorithms #2278
Conversation
…es that we could maybe move later
t.tm_hour < 0 || t.tm_hour > 23 || t.tm_min < 0 || t.tm_min > 59) { | ||
t.tm_year = 0; | ||
// If parsing failed zero 0 the struct | ||
if (ss.fail()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gknisely you can more easily test for failure by checking the failbit on the stream
|
||
// we weren't able to use this string as a date and you'd like to know about it | ||
if (can_throw && in.fail()) | ||
throw std::invalid_argument("Date string is invalid: " + date); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gknisely if the caller says you can throw then we throw when they pass an invalid date format. the default is to NOT throw which is how the code was previously working. currently only the new code ive written for time tracking asks this to throw. i dont like it but i dont want to go through the exorcise right now of making all the places that call this catch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kevinkreiser That works, but can we create an issue for this with examples of the bad input so that we can update and create tests. Thank you.
…. add increment and decrement operator tests
@@ -851,5 +851,10 @@ AABB2<PointLL> GraphReader::GetMinimumBoundingBox(const AABB2<PointLL>& bb) { | |||
return min_bb; | |||
} | |||
|
|||
int GraphReader::GetTimezone(const baldr::GraphId& node, const GraphTile*& tile) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was a helper funciton in the timedependent algorithms but since all of them need to use it i figured we can move it to the graphreader where we have other helpers
@@ -2,26 +2,27 @@ file(GLOB headers ${VALHALLA_SOURCE_DIR}/valhalla/thor/*.h) | |||
|
|||
set(sources | |||
astar.cc | |||
attributes_controller.cc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i went to insert the new source file and saw this wasnt alphabetially sorted, so i did that
if (closest_ni != nullptr && origin.has_date_time() && origin.date_time() == "current") { | ||
origin.set_date_time( | ||
DateTime::iso_date_time(DateTime::get_tz_db().from_index(closest_ni->timezone()))); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i gutted all the time setting stuff from all the algorithms becuse the new struct handles all that for you
@@ -43,7 +43,6 @@ BidirectionalAStar::BidirectionalAStar() : PathAlgorithm() { | |||
|
|||
// Destructor | |||
BidirectionalAStar::~BidirectionalAStar() { | |||
Clear(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was pointless, but the class isnt final so i left the destructor
@@ -113,7 +112,8 @@ bool BidirectionalAStar::ExpandForward(GraphReader& graphreader, | |||
const GraphId& node, | |||
BDEdgeLabel& pred, | |||
const uint32_t pred_idx, | |||
const bool from_transition) { | |||
const bool from_transition, | |||
const TimeInfo& time_info) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all the algorithms pass this struct around to compute time offsets at every expansion. instead of having the guts of that computation in the algorithm, its all in the TimeInfo struct nicely encapsulated
@@ -228,7 +234,8 @@ inline bool BidirectionalAStar::ExpandForwardInner(GraphReader& graphreader, | |||
return true; // This is an edge we _could_ have expanded, so return true | |||
} | |||
|
|||
const uint64_t localtime = 0; // Bidirectional is not yet time-aware | |||
// TODO: actually use time_info |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we're not actually to the point yet where bidirectional makes time aware expansion choices. coming soon
…so use it from the tests
Ok I've brought this branch back up to speed in both senses of the word. I've made use of the caching of timezones and I've gotten master merged back into it. I've added extensive testing of the new little struct and done benchmarking using a file of Master completed the routes in:
Where as this branch completed the routes in:
A difference of just 9 milliseconds which is well within the margin of error over the course of almost 14k route requests. |
const date::time_zone* origin_tz, | ||
const date::time_zone* dest_tz, | ||
std::unordered_map<const date::time_zone*, std::vector<date::sys_info>>* cache = nullptr); | ||
using tz_sys_info_cache_t = std::unordered_map<const date::time_zone*, std::vector<date::sys_info>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i couldnt stand looking at this detail so i type aliased it away
* @return the initialized TimeInfo | ||
*/ | ||
static TimeInfo | ||
make(valhalla::Location& location, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all of the algorithms now start off by calling this function. it sets all the time information that we need to track over the course of the expansion, see the members above.
* @param next_tz_index the timezone index at the new location | ||
* @return a new TimeInfo object reflecting the offset | ||
*/ | ||
inline TimeInfo forward(float seconds_offset, int next_tz_index) const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this method and its sister method below are in charge of updating the timeinfo object to reflect the passage of time as expansion proceeds. so after you traverse an edge you provide the amount of time that passed during that traversal to this function so it can update its members to reflect that time change.
namespace valhalla { | ||
namespace baldr { | ||
// A structure for tracking time information as the route progresses | ||
struct TimeInfo { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the main point of this struct is to provide a one stop shop for 2 things:
- convenient encapsulation that allows any routing algorithm (graph expansion) to track time
- parameter pack that we can, in the future, send directly to costing to do the right thign with respect to time-based speed look up (second of week for historical speed and seconds from now for real time speed)
test/gurka/test_time_tracking.cc
Outdated
const gurka::ways ways = {{"AB", {{"highway", "trunk"}}}}; | ||
const auto layout = gurka::detail::map_to_coordinates(ascii_map, 100); | ||
auto map = gurka::buildtiles(layout, ways, {}, {}, "test/data/gurka_time_tracking_make", | ||
{{"mjlonir.timezone", "/path/to/timezone.sqlite"}}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mjlonir? :)
} | ||
} | ||
} | ||
std::vector<double> expected = {0, 17.1429, 34.2857, 176.789, 220.289, 244.289, 268.289}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the big step between 34s to 176s? Is it because of a huge turncost when turning south?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i want to say its because its right hand driving an you make a left onto a lower class road from the ramp but... what i really did here was run this exact test on master and captured the output. this was basically a regression test
valhalla/baldr/time_info.h
Outdated
sw += tz_diff; | ||
} | ||
|
||
// wrap the week second if it went past the end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could the seconds_of_week
go past the beginning? I.e, become <0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not in this function, but it could in the function below which checks the other direction
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@purew pointed out that tz_diff is signed. so actually hes right! technically it should all be signed and get wrapped in either direction in both functions. this is important in the forward direction when you drive west over a timezone but are routing near midnight on sunday
uint64_t seconds_from_now : 43; | ||
|
||
// the sign bit for seconds_from_now | ||
uint64_t negative_seconds_from_now : 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be named something to signify it's a boolean, like is_negative_...
or has_negative_...
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM Great with all the unification! 🍰
Just had a few comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GR8!
So I've now also tested timedep routes and the main difference is that now that we are using the timezone cache, running the 14k routes from above finishes in |
Issue
This PR seeks to unify the way we track time during any given algorithms expansion in the graph. At the moment we use a bunch of the same patterns in all the different algorithms, and it would be great to encapsulate that into a single set of functionality that all the different code paths can re-use.
The eventual goal of this is to do bidirectional a* with time dependence but that functionality will be a completely separate PR. this is just the first steps
Tasklist