Skip to content

Commit

Permalink
Crossing improvements (#57)
Browse files Browse the repository at this point in the history
  • Loading branch information
pablohoch authored Jan 11, 2024
1 parent fdec23d commit 8a84abb
Show file tree
Hide file tree
Showing 20 changed files with 151 additions and 26 deletions.
1 change: 1 addition & 0 deletions include/ppr/common/edge.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct routing_graph_data;
struct routing_graph;

constexpr auto const UNKNOWN_INCLINE = std::numeric_limits<std::int8_t>::min();
constexpr auto const NO_EDGE_INFO = std::numeric_limits<edge_info_idx_t>::max();

// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
struct edge_info {
Expand Down
6 changes: 6 additions & 0 deletions include/ppr/preprocessing/int_graph/int_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ struct int_node {
return elevator_ || entrance_ || cycle_barrier_;
}

inline bool is_crossing_node() const {
return crossing_ != crossing_type::NONE;
}

std::int64_t osm_id_;
merc location_;
crossing_type crossing_ : 3;
Expand All @@ -43,6 +47,8 @@ struct int_node {
uint8_t footway_edges_{};
uint8_t street_edges_{};
std::int16_t level_{}; // stored as level * 10
edge_info_idx_t crossing_edge_info_{NO_EDGE_INFO};

node* rg_foot_node_{};

std::vector<std::unique_ptr<int_edge>> out_edges_;
Expand Down
6 changes: 3 additions & 3 deletions include/ppr/preprocessing/osm/way_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ namespace ppr::preprocessing::osm {
struct way_info {
way_info() = default;
way_info(edge_info_idx_t info, bool sidewalk_left, bool sidewalk_right,
double width, int8_t layer)
: include_(true),
double width, int8_t layer, bool include = true)
: include_(include),
edge_info_(info),
sidewalk_left_(sidewalk_left),
sidewalk_right_(sidewalk_right),
width_(width),
layer_(layer) {}

bool include_{false};
edge_info_idx_t edge_info_{};
edge_info_idx_t edge_info_{NO_EDGE_INFO};
bool sidewalk_left_{false};
bool sidewalk_right_{false};
double width_{0.0};
Expand Down
2 changes: 2 additions & 0 deletions include/ppr/preprocessing/osm_graph/osm_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ struct osm_node {
std::uint8_t street_edges_{};
elevation_t elevation_{NO_ELEVATION_DATA};
std::int16_t level_{}; // stored as level * 10
edge_info_idx_t crossing_edge_info_{NO_EDGE_INFO};

int_node* int_node_{};

std::vector<osm_edge> out_edges_;
Expand Down
6 changes: 5 additions & 1 deletion include/ppr/routing/costs.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "ppr/common/routing_graph.h"
#include "ppr/routing/last_crossing_info.h"
#include "ppr/routing/search_profile.h"

namespace ppr::routing {
Expand All @@ -11,10 +12,13 @@ struct edge_costs {
double duration_penalty_{0};
double accessibility_penalty_{0};
bool allowed_{false};
bool free_crossing_{false};
last_crossing_info new_last_crossing_;
};

edge_costs get_edge_costs(routing_graph_data const& rg, edge const* e,
edge_info const* info, bool fwd,
search_profile const& profile);
search_profile const& profile,
last_crossing_info const* prev_last_crossing);

} // namespace ppr::routing
5 changes: 5 additions & 0 deletions include/ppr/routing/directed_edge.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct directed_edge {
double duration_penalty() const { return costs_.duration_penalty_; }
double accessibility_penalty() const { return costs_.accessibility_penalty_; }
bool allowed() const { return costs_.allowed_; }
bool is_free_crossing() const { return costs_.free_crossing_; }

elevation_diff_t elevation_up() const {
return fwd_ ? edge_->elevation_up_ : edge_->elevation_down_;
Expand Down Expand Up @@ -61,6 +62,10 @@ struct directed_edge {

bool in_area() const { return edge_info_->area_; }

last_crossing_info const& new_last_crossing_info() const {
return costs_.new_last_crossing_;
}

edge const* edge_{};
edge_info const* edge_info_{};
edge_costs costs_;
Expand Down
1 change: 1 addition & 0 deletions include/ppr/routing/label.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "ppr/common/routing_graph.h"
#include "ppr/routing/directed_edge.h"
#include "ppr/routing/last_crossing_info.h"
#include "ppr/routing/search_profile.h"

namespace ppr::routing {
Expand Down
3 changes: 2 additions & 1 deletion include/ppr/routing/labels_to_route.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ route::edge to_route_edge(Label const* label, routing_graph_data const& rg) {
.automatic_door_type_ = ei->automatic_door_type_,
.traffic_signals_sound_ = ei->traffic_signals_sound_,
.traffic_signals_vibration_ = ei->traffic_signals_vibration_,
.is_additional_edge_ = e->info_ == 0};
.is_additional_edge_ = e->info_ == 0,
.free_crossing_ = de.is_free_crossing()};

re.path_.reserve(e->path_.size());
std::copy(begin(e->path_), end(e->path_), std::back_inserter(re.path_));
Expand Down
14 changes: 14 additions & 0 deletions include/ppr/routing/last_crossing_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include "ppr/common/names.h"

namespace ppr::routing {

struct last_crossing_info {
names_idx_t last_street_crossing_name_{};
double last_street_crossing_distance_{};

double last_rail_or_tram_distance_{};
};

} // namespace ppr::routing
14 changes: 9 additions & 5 deletions include/ppr/routing/pareto_dijkstra.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ struct pareto_dijkstra {
if (e == pred->edge_.edge_) {
return;
}
auto de = make_directed_edge(e, fwd);
auto de = make_directed_edge(e, fwd, pred);
if (!de.allowed()) {
return;
}
Expand All @@ -170,11 +170,15 @@ struct pareto_dijkstra {
}
}

directed_edge make_directed_edge(edge const* e, bool fwd) {
directed_edge make_directed_edge(edge const* e, bool fwd,
Label* pred = nullptr) {
auto const* ei = e->info(rg_);
return {e, ei,
get_edge_costs(rg_, e, ei, reverse_search_ ? !fwd : fwd, profile_),
fwd};
return {
e, ei,
get_edge_costs(
rg_, e, ei, reverse_search_ ? !fwd : fwd, profile_,
pred != nullptr ? &pred->edge_.new_last_crossing_info() : nullptr),
fwd};
}

bool add_label_to_node(Label* new_label) {
Expand Down
1 change: 1 addition & 0 deletions include/ppr/routing/route.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct route {
tri_state traffic_signals_sound_{tri_state::UNKNOWN};
tri_state traffic_signals_vibration_{tri_state::UNKNOWN};
bool is_additional_edge_{false};
bool free_crossing_{false};
};

route(std::vector<edge>&& edges, double distance, double duration,
Expand Down
3 changes: 3 additions & 0 deletions include/ppr/routing/search_profile.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ struct search_profile {
bool wheelchair_{};
bool stroller_{};

double max_free_street_crossing_distance_ = 30; // m
double max_free_rail_tram_crossing_distance_ = 15; // m

double round_distance_ = 0;
double round_duration_ = 0;
double round_accessibility_ = 0;
Expand Down
3 changes: 3 additions & 0 deletions src/backend/output/route_response.cc
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ void write_edge(Writer& writer, route::edge const& e) {
writer.String("traffic_signals_vibration");
write_tri_state(writer, e.traffic_signals_vibration_);

writer.String("free_crossing");
writer.Bool(e.free_crossing_);

writer.EndObject();
}

Expand Down
13 changes: 13 additions & 0 deletions src/preprocessing/build_routing_graph.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,19 @@ struct preprocessor {
}
}

if (in->is_crossing_node() && sorted_edges.size() == 2) {
auto [info_idx, info] =
create_edge_info(-in->osm_id_, edge_type::CROSSING, in->crossing_);

if (in->crossing_edge_info_ != NO_EDGE_INFO) {
auto const& cei = ig_.edge_infos_.at(in->crossing_edge_info_);
info->street_type_ = cei.street_type_;
info->name_ = cei.name_;
}

special_edge_info_idx = info_idx;
}

if (special_edge_info_idx) {
connect_edges_at_special_node(in, sorted_edges, *special_edge_info_idx);
} else {
Expand Down
1 change: 1 addition & 0 deletions src/preprocessing/int_graph/int_graph.cc
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ struct int_graph_builder {
in->traffic_signals_vibration_ = on->traffic_signals_vibration_;
in->max_width_ = on->max_width_;
in->level_ = on->level_;
in->crossing_edge_info_ = on->crossing_edge_info_;
on->int_node_ = in;
}
return on->int_node_;
Expand Down
14 changes: 7 additions & 7 deletions src/preprocessing/osm/way_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ way_info get_highway_info(osmium::Way const& way, osmium::TagList const& tags,
auto crossing = get_way_crossing_type(tags);
auto sidewalk_left = false;
auto sidewalk_right = false;
auto include = true;

if (!access_allowed(tags, true)) {
return {};
Expand All @@ -187,7 +188,8 @@ way_info get_highway_info(osmium::Way const& way, osmium::TagList const& tags,
} else if (strcmp(sidewalk, "right") == 0) {
sidewalk_right = true;
} else if (strcmp(sidewalk, "separate") == 0) {
return {};
// keep the information for crossing nodes, but don't create edges
include = false;
} else if (strcmp(sidewalk, "no") != 0 && strcmp(sidewalk, "none") != 0) {
sidewalk_left = true;
sidewalk_right = true;
Expand Down Expand Up @@ -266,7 +268,7 @@ way_info get_highway_info(osmium::Way const& way, osmium::TagList const& tags,
auto const width = get_render_width(type, street);
auto const layer = get_layer(tags);

return {info_idx, sidewalk_left, sidewalk_right, width, layer};
return {info_idx, sidewalk_left, sidewalk_right, width, layer, include};
}

way_info get_railway_info(osmium::Way const& way, osmium::TagList const& tags,
Expand All @@ -277,11 +279,9 @@ way_info get_railway_info(osmium::Way const& way, osmium::TagList const& tags,
auto street = street_type::RAIL;
if (strcmp(railway, "rail") == 0) {
street = street_type::RAIL;
/*
} else if (strcmp(railway, "tram") == 0 ||
strcmp(railway, "light_rail") == 0) {
street = street_type::TRAM;
*/
} else if (strcmp(railway, "tram") == 0 ||
strcmp(railway, "light_rail") == 0) {
street = street_type::TRAM;
} else {
return {};
}
Expand Down
22 changes: 21 additions & 1 deletion src/preprocessing/osm_graph/extractor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,19 @@ struct extract_handler : public osmium::handler::Handler {

void way(osmium::Way const& way) noexcept {
auto info = get_way_info(way, graph_);
if (info.edge_info_ == NO_EDGE_INFO) {
return;
}
auto e_info = &graph_.edge_infos_[info.edge_info_];
if (!info.include_ || e_info->area_) {
if (e_info->area_) {
return;
}

// check if this way can be crossed using a crossing node - we only
// allow streets and rail/tram ways here (both are edge_type::STREET)
auto const can_be_crossed = e_info->type_ == edge_type::STREET;

if (!info.include_ && !can_be_crossed) {
return;
}

Expand All @@ -111,6 +122,15 @@ struct extract_handler : public osmium::handler::Handler {
if (!e_info->area_) {
current_node->exit_ = true;
}
if (can_be_crossed && current_node->crossing_ != crossing_type::NONE) {
if (current_node->crossing_edge_info_ == NO_EDGE_INFO) {
current_node->crossing_edge_info_ = info.edge_info_;
}
}
}

if (!info.include_) {
return;
}

osm_node* last_node = nullptr;
Expand Down
5 changes: 5 additions & 0 deletions src/profiles/parse_search_profile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ void parse_search_profile(search_profile& profile,
get_bool(profile.wheelchair_, root, "wheelchair");
get_bool(profile.stroller_, root, "stroller");

get_double(profile.max_free_street_crossing_distance_, root,
"max_free_street_crossing_distance");
get_double(profile.max_free_rail_tram_crossing_distance_, root,
"max_free_rail_tram_crossing_distance");

get_double(profile.round_distance_, root, "round_distance");
get_double(profile.round_duration_, root, "round_duration");
get_double(profile.round_accessibility_, root, "round_accessibility");
Expand Down
49 changes: 44 additions & 5 deletions src/routing/costs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,19 @@ int32_t get_max_crossing_detour(search_profile const& profile,

edge_costs get_edge_costs(routing_graph_data const& rg, edge const* e,
edge_info const* info, bool fwd,
search_profile const& profile) {
search_profile const& profile,
last_crossing_info const* prev_last_crossing) {
auto const distance = e->distance_;
double duration = distance / profile.walking_speed_;
double accessibility = 0;
double duration_penalty = 0;
double accessibility_penalty = 0;
bool allowed = true;
auto allowed = true;
auto free_crossing = false;

auto new_last_crossing_info = prev_last_crossing != nullptr
? *prev_last_crossing
: last_crossing_info{};

auto const check_allowed = [&](cost_factor const& cf) {
switch (cf.allowed_) {
Expand All @@ -158,7 +164,32 @@ edge_costs get_edge_costs(routing_graph_data const& rg, edge const* e,
auto const& cf = get_crossing_factor(
profile, info->street_type_, info->crossing_type_,
info->is_signals_crossing_with_sound_or_vibration());
add_factor(cf, distance);

if (info->street_type_ == street_type::FOOTWAY ||
info->street_type_ == street_type::NONE) {
free_crossing = true;
} else if (info->is_rail_edge()) {
if (new_last_crossing_info.last_rail_or_tram_distance_ <
profile.max_free_rail_tram_crossing_distance_) {
free_crossing = true;
}
new_last_crossing_info.last_rail_or_tram_distance_ = 0;
} else if (info->name_ != 0) {
if (info->name_ == new_last_crossing_info.last_street_crossing_name_ &&
new_last_crossing_info.last_street_crossing_distance_ <
profile.max_free_street_crossing_distance_) {
free_crossing = true;
}
new_last_crossing_info.last_street_crossing_name_ = info->name_;
new_last_crossing_info.last_street_crossing_distance_ = 0;
}

if (free_crossing) {
check_allowed(cf);
} else {
add_factor(cf, distance);
}

if (info->is_unmarked_crossing()) {
auto const detour = info->marked_crossing_detour_;
if (detour != 0 &&
Expand Down Expand Up @@ -234,8 +265,16 @@ edge_costs get_edge_costs(routing_graph_data const& rg, edge const* e,
allowed = false;
}

return {duration, accessibility, duration_penalty, accessibility_penalty,
allowed};
new_last_crossing_info.last_street_crossing_distance_ += distance;
new_last_crossing_info.last_rail_or_tram_distance_ += distance;

return {.duration_ = duration,
.accessibility_ = accessibility,
.duration_penalty_ = duration_penalty,
.accessibility_penalty_ = accessibility_penalty,
.allowed_ = allowed,
.free_crossing_ = free_crossing,
.new_last_crossing_ = new_last_crossing_info};
}

} // namespace ppr::routing
Loading

0 comments on commit 8a84abb

Please sign in to comment.