Skip to content

Commit

Permalink
osr_footpaths: add missing footpaths (#707)
Browse files Browse the repository at this point in the history
* osr_footpaths: add missing footpaths

* update osr (ramp support)

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* formatting
  • Loading branch information
felixguendling authored Jan 22, 2025
1 parent 34f8b95 commit e7c6663
Show file tree
Hide file tree
Showing 16 changed files with 172 additions and 73 deletions.
4 changes: 2 additions & 2 deletions .pkg
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
[osr]
url=git@github.com:motis-project/osr.git
branch=master
commit=478bed28978461f0728c311899cc6bb22f0dd591
commit=650e05c5dc59598f84a5e9bae2db75d5cc3433b8
[utl]
url=git@github.com:motis-project/utl.git
branch=master
commit=368fdcb8326ced5bb151b60c09a07c2e5f09bf55
commit=07fb33df7b79b73e84e0d2c69c6ee445221f6e32
[adr]
url=git@github.com:triptix-tech/adr.git
branch=master
Expand Down
7 changes: 4 additions & 3 deletions .pkg.lock
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
1084193615955229448
16722610972019258869
cista 6362f3ad8c3133a0abf64e5d8c9ea3e21f531ee8
zlib-ng 68ab3e2d80253ec5dc3c83691d9ff70477b32cd3
boost 930f38eb0365ceb7853273e03da4d9e7787abfb9
googletest 7b64fca6ea0833628d6f86255a81424365f7cc0c
lz4 c4765545ebb14b0a56c663e21923166923f8280e
mimalloc e2f4fe647e8aff4603a7d5119b8639fd1a47c8a6
libressl 24acd9e710fbe842e863572da9d738715fbc74b8
docs 75dc89a53e9c2d78574fc0ffda698e69f1682ed2
fmt dc10f83be70ac2873d5f8d1ce317596f1fd318a2
utl 368fdcb8326ced5bb151b60c09a07c2e5f09bf55
utl 07fb33df7b79b73e84e0d2c69c6ee445221f6e32
res b759b93316afeb529b6cb5b2548b24c41e382fb0
date ce88cc33b5551f66655614eeebb7c5b7189025fb
yaml-cpp 1d8ca1f35eb3a9c9142462b28282a848e5d29a91
Expand Down Expand Up @@ -43,7 +44,7 @@ sol2 40c7cbc7c5cfed1e8c7f1bbe6fcbe23d7a67fc75
variant 5aa73631dc969087c77433a5cdef246303051f69
tiles ab6c4b13544570f893c2d64434c613d8fd7d2ceb
rtree.c 6ed73a7dc4f1184f2b5b2acd8ac1c2b28a273057
osr 478bed28978461f0728c311899cc6bb22f0dd591
osr 650e05c5dc59598f84a5e9bae2db75d5cc3433b8
reflect-cpp c54fe66de4650b60c23aadd4a06d9db4ffeda22f
FTXUI dd6a5d371fd7a3e2937bb579955003c54b727233
tg 20c0f298b8ce58de29a790290f44dca7c4ecc364
Expand Down
4 changes: 3 additions & 1 deletion include/motis/compute_footpaths.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ elevator_footpath_map_t compute_footpaths(osr::ways const&,
osr::lookup const&,
osr::platforms const&,
nigiri::timetable&,
bool update_coordinates);
bool update_coordinates,
bool extend_missing,
std::chrono::seconds max_duration);

} // namespace motis
2 changes: 2 additions & 0 deletions include/motis/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ struct config {
unsigned update_interval_{60};
unsigned http_timeout_{10};
bool incremental_rt_update_{false};
bool use_osm_stop_coordinates_{false};
bool extend_missing_footpaths_{false};
std::uint16_t max_footpath_length_{15};
std::optional<std::string> default_timezone_{};
std::map<std::string, dataset> datasets_{};
Expand Down
2 changes: 1 addition & 1 deletion include/motis/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ struct data {
friend std::ostream& operator<<(std::ostream&, data const&);

void load_osr();
void load_tt();
void load_tt(std::filesystem::path const&);
void load_shapes();
void load_railviz();
void load_geocoder();
Expand Down
2 changes: 1 addition & 1 deletion include/motis/hashes.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ using meta_entry_t = std::pair<std::string, std::uint64_t>;
using meta_t = std::map<std::string, std::uint64_t>;

constexpr auto const osr_version = []() {
return meta_entry_t{"osr_bin_ver", 8U};
return meta_entry_t{"osr_bin_ver", 9U};
};
constexpr auto const adr_version = []() {
return meta_entry_t{"adr_bin_ver", 4U};
Expand Down
7 changes: 6 additions & 1 deletion openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1649,7 +1649,12 @@ components:
foot:
type: number
description: |
optional; missing if no path was found with the foot profile
optional; missing if no path was found (timetable / osr)
footpath duration in minutes for the foot profile
footRouted:
type: number
description: |
optional; missing if no path was found with foot routing
footpath duration in minutes for the foot profile
wheelchair:
type: number
Expand Down
136 changes: 89 additions & 47 deletions src/compute_footpaths.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
#include "cista/mmap.h"
#include "cista/serialization.h"

#include "utl/concat.h"
#include "utl/erase_if.h"
#include "utl/parallel_for.h"
#include "utl/sorted_diff.h"

#include "osr/routing/profiles/foot.h"
#include "osr/routing/route.h"
Expand Down Expand Up @@ -47,12 +50,15 @@ vector_map<n::location_idx_t, osr::match_t> lookup_locations(
return ret;
}

elevator_footpath_map_t compute_footpaths(osr::ways const& w,
osr::lookup const& lookup,
osr::platforms const& pl,
nigiri::timetable& tt,
bool const update_coordinates) {
fmt::println(std::clog, " -> creating matches");
elevator_footpath_map_t compute_footpaths(
osr::ways const& w,
osr::lookup const& lookup,
osr::platforms const& pl,
nigiri::timetable& tt,
bool const update_coordinates,
bool const extend_missing,
std::chrono::seconds const max_duration) {
fmt::println(std::clog, "creating matches");
auto const matches = get_matches(tt, pl, w);

fmt::println(std::clog, " -> creating r-tree");
Expand All @@ -67,10 +73,7 @@ elevator_footpath_map_t compute_footpaths(osr::ways const& w,
tt.locations_.coordinates_[i] = *center;
}
}

if (!tt.location_routes_[i].empty()) {
t.add(tt.locations_.coordinates_[i], i);
}
t.add(tt.locations_.coordinates_[i], i);
}
return t;
}();
Expand Down Expand Up @@ -102,52 +105,91 @@ elevator_footpath_map_t compute_footpaths(osr::ways const& w,
auto const wheelchair_candidates = lookup_locations(
w, lookup, pl, tt, matches, osr::search_profile::kWheelchair);

auto m = std::mutex{};
struct state {
std::vector<n::footpath> sorted_tt_fps_;
std::vector<n::footpath> missing_;
std::vector<n::location_idx_t> neighbors_;
std::vector<osr::location> neighbors_loc_;
std::vector<osr::match_t> neighbor_candidates_;
};

for (auto const mode :
{osr::search_profile::kFoot, osr::search_profile::kWheelchair}) {
auto const& candidates = mode == osr::search_profile::kFoot
? foot_candidates
: wheelchair_candidates;
utl::parallel_for_run(tt.n_locations(), [&](auto const i) {
auto const l = n::location_idx_t{i};
auto& footpaths =
(mode == osr::search_profile::kFoot ? footpaths_out_foot[l]
: footpaths_out_wheelchair[l]);
auto neighbors = std::vector<n::location_idx_t>{};
loc_rtree.in_radius(tt.locations_.coordinates_[l], kMaxDistance,
[&](n::location_idx_t const x) {
if (x != l) {
neighbors.emplace_back(x);
}
});
auto const results = osr::route(
w, mode, get_loc(tt, w, pl, matches, l),
utl::to_vec(neighbors,
[&](auto&& x) { return get_loc(tt, w, pl, matches, x); }),
candidates[l],
utl::to_vec(neighbors, [&](auto&& x) { return candidates[x]; }),
kMaxDuration, osr::direction::kForward, nullptr, nullptr,
[](osr::path const& p) { return p.uses_elevator_; });
for (auto const [n, r] : utl::zip(neighbors, results)) {
if (r.has_value()) {
auto lock = std::scoped_lock{m};
auto const duration = n::duration_t{r->cost_ / 60U};
if (duration < n::footpath::kMaxDuration) {
footpaths.emplace_back(n::footpath{n, duration});
utl::parallel_for_run_threadlocal<state>(
tt.n_locations(), [&](state& s, auto const i) {
cista::for_each_field(s, [](auto& f) { f.clear(); });

auto const l = n::location_idx_t{i};
auto& footpaths = (mode == osr::search_profile::kFoot
? footpaths_out_foot[l]
: footpaths_out_wheelchair[l]);
loc_rtree.in_radius(tt.locations_.coordinates_[l], kMaxDistance,
[&](n::location_idx_t const x) {
if (x != l) {
s.neighbors_.emplace_back(x);
}
});
auto const results = osr::route(
w, mode, get_loc(tt, w, pl, matches, l),
utl::transform_to(
s.neighbors_, s.neighbors_loc_,
[&](auto&& x) { return get_loc(tt, w, pl, matches, x); }),
candidates[l],
utl::transform_to(s.neighbors_, s.neighbor_candidates_,
[&](auto&& x) { return candidates[x]; }),
kMaxDuration, osr::direction::kForward, nullptr, nullptr,
[](osr::path const& p) { return p.uses_elevator_; });
for (auto const [n, r] : utl::zip(s.neighbors_, results)) {
if (r.has_value()) {
auto const duration = n::duration_t{r->cost_ / 60U};
footpaths.emplace_back(n::footpath{n, duration});
for (auto const& seg : r->segments_) {
add_if_elevator(seg.from_, l, n);
add_if_elevator(seg.from_, n, l);
}
}
}
for (auto const& s : r->segments_) {
add_if_elevator(s.from_, l, n);
add_if_elevator(s.from_, n, l);

if (extend_missing && mode == osr::search_profile::kFoot) {
auto const& tt_fps = tt.locations_.footpaths_out_[0].at(l);
s.sorted_tt_fps_.resize(tt_fps.size());
std::copy(begin(tt_fps), end(tt_fps), begin(s.sorted_tt_fps_));
utl::sort(s.sorted_tt_fps_);
utl::sort(footpaths);

utl::sorted_diff(
s.sorted_tt_fps_, footpaths,
[](auto&& a, auto&& b) { return a.target() < b.target(); },
[](auto&& a, auto&& b) { return a.target() == b.target(); },
utl::overloaded{
[](n::footpath, n::footpath) { assert(false); },
[&](utl::op const op, n::footpath const x) {
if (op == utl::op::kDel) {
auto const duration =
n::duration_t{static_cast<int>(std::ceil(
(geo::distance(
tt.locations_.coordinates_[l],
tt.locations_.coordinates_[x.target()]) /
0.7) /
60.0))};
s.missing_.emplace_back(x.target(), duration);
}
}});

utl::concat(footpaths, s.missing_);
}
}
}

utl::sort(footpaths_out_foot[l]);
utl::sort(footpaths_out_wheelchair[l]);
utl::erase_if(footpaths, [&](n::footpath fp) {
return fp.duration() > max_duration;
});
utl::sort(footpaths);

pt->update_monotonic(
(mode == osr::search_profile::kFoot ? 0U : tt.n_locations()) + i);
});
pt->update_monotonic(
(mode == osr::search_profile::kFoot ? 0U : tt.n_locations()) + i);
});
}

fmt::println(std::clog, " -> create ingoing footpaths");
Expand Down
6 changes: 3 additions & 3 deletions src/data.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ data::data(std::filesystem::path p, config const& c)

auto tt = std::async(std::launch::async, [&]() {
if (c.timetable_) {
load_tt();
load_tt(config_.osr_footpath_ ? "tt_ext.bin" : "tt.bin");
if (c.timetable_->with_shapes_) {
load_shapes();
}
Expand Down Expand Up @@ -189,9 +189,9 @@ void data::load_osr() {
pl_->build_rtree(*w_);
}

void data::load_tt() {
void data::load_tt(fs::path const& p) {
tags_ = tag_lookup::read(path_ / "tags.bin");
tt_ = n::timetable::read(path_ / "tt.bin");
tt_ = n::timetable::read(path_ / p);
tt_->locations_.resolve_timezones();
location_rtee_ = std::make_unique<point_rtree<n::location_idx_t>>(
create_location_rtree(*tt_));
Expand Down
13 changes: 8 additions & 5 deletions src/endpoints/footpaths.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,16 @@ api::footpaths_response footpaths::operator()(

auto footpaths = hash_map<n::location_idx_t, api::Footpath>{};

for (auto const fp : tt_.locations_.footpaths_out_[0][l]) {
if (tt_.location_routes_[fp.target()].empty()) {
continue;
}
for (auto const fp : tt_.locations_.footpaths_out_[0].at(l)) {
footpaths[fp.target()].default_ = fp.duration().count();
}

if (!tt_.locations_.footpaths_out_[1].empty()) {
for (auto const fp : tt_.locations_.footpaths_out_[1].at(l)) {
footpaths[fp.target()].foot_ = fp.duration().count();
}
}

auto const loc = get_loc(tt_, w_, pl_, matches_, l);
for (auto const mode :
{osr::search_profile::kFoot, osr::search_profile::kWheelchair}) {
Expand All @@ -57,7 +60,7 @@ api::footpaths_response footpaths::operator()(
std::ceil(r->cost_ * kTransferTimeMultiplier / 60U);
if (duration < n::footpath::kMaxDuration.count()) {
switch (mode) {
case osr::search_profile::kFoot: fp.foot_ = duration; break;
case osr::search_profile::kFoot: fp.footRouted_ = duration; break;
case osr::search_profile::kWheelchair:
fp.wheelchair_ = duration;
fp.wheelchairUsesElevator_ = r->uses_elevator_;
Expand Down
17 changes: 10 additions & 7 deletions src/import.cc
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ data import(config const& c, fs::path const& data_path, bool const write) {
}
},
[&]() {
d.load_tt();
d.load_tt("tt.bin");
if (c.timetable_->with_shapes_) {
d.load_shapes();
}
Expand Down Expand Up @@ -367,19 +367,22 @@ data import(config const& c, fs::path const& data_path, bool const write) {

auto osr_footpath = task{
"osr_footpath",
[&]() { return c.osr_footpath_; },
[&]() { return d.tt_ && d.w_ && d.l_ && d.pl_; },
[&]() { return c.osr_footpath_ && c.timetable_; },
[&]() { return d.tt_ && d.tags_ && d.w_ && d.l_ && d.pl_; },
[&]() {
auto const elevator_footpath_map =
compute_footpaths(*d.w_, *d.l_, *d.pl_, *d.tt_, true);
auto const elevator_footpath_map = compute_footpaths(
*d.w_, *d.l_, *d.pl_, *d.tt_,
c.timetable_->use_osm_stop_coordinates_,
c.timetable_->extend_missing_footpaths_,
std::chrono::seconds{c.timetable_->max_footpath_length_ * 60U});

if (write) {
cista::write(data_path / "elevator_footpath_map.bin",
elevator_footpath_map);
d.tt_->write(data_path / "tt.bin");
d.tt_->write(data_path / "tt_ext.bin");
}
},
[&]() {},
[&]() { d.load_tt("tt_ext.bin"); },
{tt_hash, osm_hash, osr_version(), osr_footpath_version(), n_version()}};

auto matches =
Expand Down
2 changes: 2 additions & 0 deletions test/config_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ osm: europe-latest.osm.pbf
update_interval: 60
http_timeout: 10
incremental_rt_update: false
use_osm_stop_coordinates: false
extend_missing_footpaths: false
max_footpath_length: 15
datasets:
de:
Expand Down
2 changes: 2 additions & 0 deletions test/routing_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ TEST(motis, routing) {
config::timetable{
.first_day_ = "2019-05-01",
.num_days_ = 2,
.use_osm_stop_coordinates_ = true,
.extend_missing_footpaths_ = false,
.datasets_ = {{"test", {.path_ = std::string{kGTFS}}}}},
.gbfs_ = {{.feeds_ = {{"CAB", {.url_ = "./test/resources/gbfs"}}}}},
.street_routing_ = true,
Expand Down
Loading

0 comments on commit e7c6663

Please sign in to comment.