Skip to content

Commit

Permalink
tracking: tracks an attribute for a path
Browse files Browse the repository at this point in the history
works via labels + entry
dijkstra updates entry tracking with the label tracking

useful to know if a path contains an elevator somewhere
without having to actually reconstruct the whole path
  • Loading branch information
felixguendling committed Jul 20, 2024
1 parent 6cf0a46 commit 6b198c5
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 87 deletions.
4 changes: 1 addition & 3 deletions exe/backend/src/http_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,7 @@ struct http_server::impl {
? 0U
: to_idx(w_.way_osm_idx_[s.way_])},
{"cost", s.cost_},
{"distance", s.dist_},
{"from_node", s.from_node_properties_},
{"to_node", s.to_node_properties_}},
{"distance", s.dist_}},
},
{"geometry", to_line_string(s.polyline_)}};
}) |
Expand Down
2 changes: 1 addition & 1 deletion include/osr/routing/dijkstra.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ struct dijkstra {
cost_[neighbor.get_key()].update(
l, neighbor, static_cast<cost_t>(total), curr)) {
auto next = label{neighbor, static_cast<cost_t>(total)};
next.track(r, way, neighbor.get_node());
next.track(l, r, way, neighbor.get_node());
pq_.push(std::move(next));
}
});
Expand Down
2 changes: 1 addition & 1 deletion include/osr/routing/profiles/bike.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct bike {
constexpr node get_node() const noexcept { return {n_}; }
constexpr cost_t cost() const noexcept { return cost_; }

void track(ways::routing const&, way_idx_t, node_idx_t) {}
void track(label const&, ways::routing const&, way_idx_t, node_idx_t) {}

node_idx_t n_;
level_t lvl_;
Expand Down
4 changes: 1 addition & 3 deletions include/osr/routing/profiles/car.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ struct car {

constexpr node_idx_t get_key() const noexcept { return n_; }

void track(ways::routing const&, way_idx_t, node_idx_t) {}

std::ostream& print(std::ostream& out, ways const& w) const {
return out << "(node=" << w.node_to_osm_[n_] << ", dir=" << to_str(dir_)
<< ", way=" << w.way_osm_idx_[w.r_->node_ways_[n_][way_]]
Expand All @@ -53,7 +51,7 @@ struct car {
constexpr node get_node() const noexcept { return {n_, way_, dir_}; }
constexpr cost_t cost() const noexcept { return cost_; }

void track(ways::routing const&, way_idx_t, node_idx_t) {}
void track(label const&, ways::routing const&, way_idx_t, node_idx_t) {}

node_idx_t n_;
way_pos_t way_;
Expand Down
2 changes: 1 addition & 1 deletion include/osr/routing/profiles/car_parking.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ struct car_parking {

constexpr cost_t cost() const noexcept { return cost_; }

void track(ways::routing const&, way_idx_t, node_idx_t) {}
void track(label const&, ways::routing const&, way_idx_t, node_idx_t) {}

node_idx_t n_;
cost_t cost_;
Expand Down
7 changes: 5 additions & 2 deletions include/osr/routing/profiles/foot.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@ struct foot {
constexpr node get_node() const noexcept { return {n_, lvl_}; }
constexpr cost_t cost() const noexcept { return cost_; }

void track(ways::routing const& r, way_idx_t const w, node_idx_t const n) {
tracking_.track(r, w, n);
void track(label const& l,
ways::routing const& r,
way_idx_t const w,
node_idx_t const n) {
tracking_.track(l.tracking_, r, w, n);
}

node_idx_t n_;
Expand Down
8 changes: 5 additions & 3 deletions include/osr/routing/route.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@ struct path {
std::vector<geo::latlng> polyline_;
level_t from_level_;
level_t to_level_;
node_idx_t from_, to_;
way_idx_t way_;
cost_t cost_{kInfeasible};
distance_t dist_{0};
boost::json::object from_node_properties_{};
boost::json::object to_node_properties_{};
};

cost_t cost_{kInfeasible};
Expand All @@ -56,7 +55,10 @@ std::vector<std::optional<path>> route(
cost_t max,
direction,
double max_match_distance,
bitvec<node_idx_t> const* blocked = nullptr);
bitvec<node_idx_t> const* blocked = nullptr,
std::function<bool(path const&)> const& = [](path const&) {
return false;
});

std::optional<path> route(ways const&,
lookup const&,
Expand Down
12 changes: 9 additions & 3 deletions include/osr/routing/tracking.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,22 @@ namespace osr {

struct elevator_tracking {
void write(path& p) const { p.uses_elevator_ = uses_elevator_; }
void track(ways::routing const& r, way_idx_t, node_idx_t const n) {
uses_elevator_ |= r.node_properties_[n].is_elevator();
void track(elevator_tracking const& l,
ways::routing const& r,
way_idx_t,
node_idx_t const n) {
uses_elevator_ = l.uses_elevator_ || r.node_properties_[n].is_elevator();
}

bool uses_elevator_{false};
};

struct noop_tracking {
void write(path&) const {}
void track(ways::routing const&, way_idx_t, node_idx_t) {}
void track(noop_tracking const&,
ways::routing const&,
way_idx_t,
node_idx_t) {}
};

} // namespace osr
149 changes: 79 additions & 70 deletions src/route.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,22 +112,10 @@ double add_path(ways const& w,
segment.way_ = way;
segment.dist_ = distance;
segment.cost_ = expected_cost;

// when going backwards we have to swap the properties, since we will be
// traversing the way in the opposite direction.
if (dir == direction::kForward) {
segment.from_level_ = r.way_properties_[way].from_level();
segment.to_level_ = r.way_properties_[way].to_level();

segment.from_node_properties_ = from.geojson_properties(w);
segment.to_node_properties_ = to.geojson_properties(w);
} else {
segment.from_level_ = r.way_properties_[way].to_level();
segment.to_level_ = r.way_properties_[way].from_level();

segment.from_node_properties_ = to.geojson_properties(w);
segment.to_node_properties_ = from.geojson_properties(w);
}
segment.from_level_ = r.way_properties_[way].from_level();
segment.to_level_ = r.way_properties_[way].to_level();
segment.from_ = r.way_nodes_[way][from_idx];
segment.to_ = r.way_nodes_[way][to_idx];

for (auto const [osm_idx, coord] :
infinite(reverse(utl::zip(w.way_osm_nodes_[way], w.way_polylines_[way]),
Expand Down Expand Up @@ -183,14 +171,16 @@ path reconstruct(ways const& w,

auto const& start_node =
n.get_node() == start.left_.node_ ? start.left_ : start.right_;
segments.push_back({.polyline_ = start_node.path_,
.from_level_ = start_node.lvl_,
.to_level_ = start_node.lvl_,
.way_ = way_idx_t::invalid(),
.cost_ = kInfeasible,
.dist_ = 0,
.from_node_properties_ = {},
.to_node_properties_ = {}});
segments.push_back(
{.polyline_ = start_node.path_,
.from_level_ = start_node.lvl_,
.to_level_ = start_node.lvl_,
.from_ =
dir == direction::kBackward ? n.get_node() : node_idx_t::invalid(),
.to_ = dir == direction::kForward ? n.get_node() : node_idx_t::invalid(),
.way_ = way_idx_t::invalid(),
.cost_ = kInfeasible,
.dist_ = 0});
std::reverse(begin(segments), end(segments));
auto p = path{.cost_ = cost,
.dist_ = start_node.dist_to_node_ + dist + dest.dist_to_node_,
Expand All @@ -203,7 +193,7 @@ template <typename Profile>
std::optional<std::tuple<node_candidate const*,
way_candidate const*,
typename Profile::node,
cost_t>>
path>>
best_candidate(ways const& w,
dijkstra<Profile>& d,
level_t const lvl,
Expand All @@ -213,7 +203,7 @@ best_candidate(ways const& w,
auto const get_best = [&](way_candidate const& dest,
node_candidate const* x) {
auto best_node = typename Profile::node{};
auto best_cost = std::numeric_limits<cost_t>::max();
auto best_cost = path{.cost_ = std::numeric_limits<cost_t>::max()};
Profile::resolve_all(*w.r_, x->node_, lvl, [&](auto&& node) {
if (!Profile::is_dest_reachable(*w.r_, node, dest.way_,
flip(opposite(dir), x->way_dir_),
Expand All @@ -227,26 +217,26 @@ best_candidate(ways const& w,
}

auto const total_cost = target_cost + x->cost_;
if (total_cost < max && total_cost < best_cost) {
if (total_cost < max && total_cost < best_cost.cost_) {
best_node = node;
best_cost = static_cast<cost_t>(total_cost);
best_cost.cost_ = static_cast<cost_t>(total_cost);
}
});
return std::pair{best_node, best_cost};
};

for (auto const& dest : m) {
auto best_node = typename Profile::node{};
auto best_cost = std::numeric_limits<cost_t>::max();
auto best_cost = path{.cost_ = std::numeric_limits<cost_t>::max()};
auto best = static_cast<node_candidate const*>(nullptr);

for (auto const x : {&dest.left_, &dest.right_}) {
if (x->valid() && x->cost_ < max) {
auto const [x_node, x_cost] = get_best(dest, x);
if (x_cost < max && x_cost < best_cost) {
if (x_cost.cost_ < max && x_cost.cost_ < best_cost.cost_) {
best = x;
best_node = x_node;
best_cost = static_cast<cost_t>(x_cost);
best_cost = x_cost;
}
}
}
Expand Down Expand Up @@ -282,10 +272,9 @@ std::optional<path> route(ways const& w,
for (auto const& start : from_match) {
for (auto const* nc : {&start.left_, &start.right_}) {
if (nc->valid() && nc->cost_ < max) {
Profile::resolve_start_node(*w.r_, start.way_, nc->node_, from.lvl_,
dir, [&](auto const node) {
d.add_start({node, nc->cost_});
});
Profile::resolve_start_node(
*w.r_, start.way_, nc->node_, from.lvl_, dir,
[&](auto const node) { d.add_start({node, nc->cost_}); });
}
}

Expand All @@ -297,24 +286,27 @@ std::optional<path> route(ways const& w,

auto const c = best_candidate(w, d, to.lvl_, to_match, max, dir);
if (c.has_value()) {
auto const [nc, wc, node, cost] = *c;
return reconstruct<Profile>(w, blocked, d, start, *nc, node, cost, dir);
auto const [nc, wc, node, p] = *c;
return reconstruct<Profile>(w, blocked, d, start, *nc, node, p.cost_,
dir);
}
}

return std::nullopt;
}

template <typename Profile>
std::vector<std::optional<path>> route(ways const& w,
lookup const& l,
dijkstra<Profile>& d,
location const& from,
std::vector<location> const& to,
cost_t const max,
direction const dir,
double const max_match_distance,
bitvec<node_idx_t> const* blocked) {
std::vector<std::optional<path>> route(
ways const& w,
lookup const& l,
dijkstra<Profile>& d,
location const& from,
std::vector<location> const& to,
cost_t const max,
direction const dir,
double const max_match_distance,
bitvec<node_idx_t> const* blocked,
std::function<bool(path const&)> const& do_reconstruct) {
auto const from_match =
l.match<Profile>(from, false, dir, max_match_distance, blocked);
auto const to_match = utl::to_vec(to, [&](auto&& x) {
Expand All @@ -332,10 +324,12 @@ std::vector<std::optional<path>> route(ways const& w,
for (auto const& start : from_match) {
for (auto const* nc : {&start.left_, &start.right_}) {
if (nc->valid() && nc->cost_ < max) {
Profile::resolve_start_node(*w.r_, start.way_, nc->node_, from.lvl_,
dir, [&](auto const node) {
d.add_start({node, nc->cost_});
});
Profile::resolve_start_node(
*w.r_, start.way_, nc->node_, from.lvl_, dir, [&](auto const node) {
auto label = typename Profile::label{node, nc->cost_};
label.track(label, *w.r_, start.way_, node.get_node());
d.add_start(label);
});
}
}

Expand All @@ -348,7 +342,14 @@ std::vector<std::optional<path>> route(ways const& w,
} else {
auto const c = best_candidate(w, d, t.lvl_, m, max, dir);
if (c.has_value()) {
r = std::make_optional(path{.cost_ = std::get<3>(*c)});
auto [nc, wc, n, p] = *c;
d.cost_.at(n.get_key()).write(n, p);
if (do_reconstruct(p)) {
p = reconstruct<Profile>(w, blocked, d, start, *nc, n, p.cost_,
dir);
p.uses_elevator_ = true;
}
r = std::make_optional(p);
++found;
}
}
Expand All @@ -371,34 +372,36 @@ dijkstra<Profile>& get_dijkstra() {
return *s.get();
}

std::vector<std::optional<path>> route(ways const& w,
lookup const& l,
search_profile const profile,
location const& from,
std::vector<location> const& to,
cost_t const max,
direction const dir,
double const max_match_distance,
bitvec<node_idx_t> const* blocked) {
std::vector<std::optional<path>> route(
ways const& w,
lookup const& l,
search_profile const profile,
location const& from,
std::vector<location> const& to,
cost_t const max,
direction const dir,
double const max_match_distance,
bitvec<node_idx_t> const* blocked,
std::function<bool(path const&)> const& do_reconstruct) {
switch (profile) {
case search_profile::kFoot:
return route(w, l, get_dijkstra<foot<false>>(), from, to, max, dir,
max_match_distance, blocked);
return route(w, l, get_dijkstra<foot<false, elevator_tracking>>(), from,
to, max, dir, max_match_distance, blocked, do_reconstruct);
case search_profile::kWheelchair:
return route(w, l, get_dijkstra<foot<true>>(), from, to, max, dir,
max_match_distance, blocked);
return route(w, l, get_dijkstra<foot<true, elevator_tracking>>(), from,
to, max, dir, max_match_distance, blocked, do_reconstruct);
case search_profile::kBike:
return route(w, l, get_dijkstra<bike>(), from, to, max, dir,
max_match_distance, blocked);
max_match_distance, blocked, do_reconstruct);
case search_profile::kCar:
return route(w, l, get_dijkstra<car>(), from, to, max, dir,
max_match_distance, blocked);
max_match_distance, blocked, do_reconstruct);
case search_profile::kCarParking:
return route(w, l, get_dijkstra<car_parking<false>>(), from, to, max, dir,
max_match_distance, blocked);
max_match_distance, blocked, do_reconstruct);
case search_profile::kCarParkingWheelchair:
return route(w, l, get_dijkstra<car_parking<true>>(), from, to, max, dir,
max_match_distance, blocked);
max_match_distance, blocked, do_reconstruct);
}
throw utl::fail("not implemented");
}
Expand All @@ -414,8 +417,8 @@ std::optional<path> route(ways const& w,
bitvec<node_idx_t> const* blocked) {
switch (profile) {
case search_profile::kFoot:
return route(w, l, get_dijkstra<foot<false>>(), from, to, max, dir,
max_match_distance, blocked);
return route(w, l, get_dijkstra<foot<false, elevator_tracking>>(), from,
to, max, dir, max_match_distance, blocked);
case search_profile::kWheelchair:
return route(w, l, get_dijkstra<foot<true, elevator_tracking>>(), from,
to, max, dir, max_match_distance, blocked);
Expand All @@ -435,4 +438,10 @@ std::optional<path> route(ways const& w,
throw utl::fail("not implemented");
}

template dijkstra<foot<true, osr::noop_tracking>>&
get_dijkstra<foot<true, osr::noop_tracking>>();

template dijkstra<foot<false, osr::noop_tracking>>&
get_dijkstra<foot<false, osr::noop_tracking>>();

} // namespace osr

0 comments on commit 6b198c5

Please sign in to comment.