Skip to content

Commit

Permalink
Merge pull request #911 from valhalla/pedestrian_astar
Browse files Browse the repository at this point in the history
Pedestrian A* fix
  • Loading branch information
dnesbitt61 committed Aug 28, 2017
2 parents 7fc0c54 + 998effd commit 8b0fb8d
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 14 deletions.
3 changes: 2 additions & 1 deletion src/sif/dynamiccost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ namespace sif {

DynamicCost::DynamicCost(const boost::property_tree::ptree& pt,
const TravelMode mode)
: allow_transit_connections_(false),
: pass_(0),
allow_transit_connections_(false),
allow_destination_only_(true),
travel_mode_(mode) {
// Parse property tree to get hierarchy limits
Expand Down
22 changes: 20 additions & 2 deletions src/sif/pedestriancost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ class PedestrianCost : public DynamicCost {

virtual ~PedestrianCost();

/**
* Does the costing method allow multiple passes (with relaxed hierarchy
* limits).
* @return Returns true if the costing model allows multiple passes.
*/
virtual bool AllowMultiPass() const;

/**
* This method overrides the max_distance with the max_distance_mm per segment
* distance. An example is a pure walking route may have a max distance of
Expand Down Expand Up @@ -444,6 +451,11 @@ PedestrianCost::PedestrianCost(const boost::property_tree::ptree& pt)
PedestrianCost::~PedestrianCost() {
}

// Allow multiple passes when ferries are on initial path.
bool PedestrianCost::AllowMultiPass() const {
return true;
}

// This method overrides the max_distance with the max_distance_mm per segment
// distance. An example is a pure walking route may have a max distance of
// 10000 meters (10km) but for a multi-modal route a lower limit of 5000
Expand Down Expand Up @@ -643,8 +655,14 @@ Cost PedestrianCost::TransitionCostReverse(
// assume the maximum speed is used to the destination such that the time
// estimate is less than the least possible time along roads.
float PedestrianCost::AStarCostFactor() const {
// Use the factor to favor walkways/paths if < 1.0f
return (walkway_factor_ < 1.0f) ? walkway_factor_ * speedfactor_ : speedfactor_;
// On first pass use the walking speed plus a small factor to account for
// favoring walkways, on the second pass use the the maximum ferry speed.
if (pass_ == 0) {
float speed = kDefaultSpeedFoot * std::min(walkway_factor_, sidewalk_factor_);
return (kSecPerHour * 0.001f) / static_cast<float>(speed);
} else {
return (kSecPerHour * 0.001f) / static_cast<float>(kMaxFerrySpeedKph);
}
}

// Returns the current travel type.
Expand Down
8 changes: 8 additions & 0 deletions src/thor/astar.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ void AStarPathAlgorithm::Clear() {

// Clear the edge status flags
edgestatus_.reset();

// Set the ferry flag to false
has_ferry_ = false;
}

// Initialize prior to finding best path
Expand Down Expand Up @@ -468,6 +471,11 @@ std::vector<PathInfo> AStarPathAlgorithm::FormPath(const uint32_t dest) {
const EdgeLabel& edgelabel = edgelabels_[edgelabel_index];
path.emplace_back(edgelabel.mode(), edgelabel.cost().secs,
edgelabel.edgeid(), 0);

// Check if this is a ferry
if (edgelabel.use() == Use::kFerry) {
has_ferry_ = true;
}
}

// Reverse the list and return
Expand Down
13 changes: 13 additions & 0 deletions src/thor/bidirectional_astar.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ void BidirectionalAStar::Clear() {
adjacencylist_reverse_.reset();
edgestatus_forward_.reset();
edgestatus_reverse_.reset();

// Set the ferry flag to false
has_ferry_ = false;
}

// Initialize the A* heuristic and adjacency lists for both the forward
Expand Down Expand Up @@ -670,6 +673,11 @@ std::vector<PathInfo> BidirectionalAStar::FormPath(GraphReader& graphreader) {
const BDEdgeLabel& edgelabel = edgelabels_forward_[edgelabel_index];
path.emplace_back(edgelabel.mode(), edgelabel.cost().secs,
edgelabel.edgeid(), 0);

// Check if this is a ferry
if (edgelabel.use() == Use::kFerry) {
has_ferry_ = true;
}
}

// Reverse the list
Expand Down Expand Up @@ -715,6 +723,11 @@ std::vector<PathInfo> BidirectionalAStar::FormPath(GraphReader& graphreader) {
secs += tc;
path.emplace_back(edgelabel.mode(), secs, oppedge, 0);

// Check if this is a ferry
if (edgelabel.use() == Use::kFerry) {
has_ferry_ = true;
}

// Update edgelabel_index and transition cost to apply at next iteration
edgelabel_index = predidx;
tc = edgelabel.transition_secs();
Expand Down
8 changes: 8 additions & 0 deletions src/thor/multimodal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ void MultiModalPathAlgorithm::Clear() {

// Clear the edge status flags
edgestatus_.reset();

// Set the ferry flag to false
has_ferry_ = false;
}


Expand Down Expand Up @@ -800,6 +803,11 @@ std::vector<PathInfo> MultiModalPathAlgorithm::FormPath(const uint32_t dest) {
const MMEdgeLabel& edgelabel = edgelabels_[edgelabel_index];
path.emplace_back(edgelabel.mode(), edgelabel.cost().secs,
edgelabel.edgeid(), edgelabel.tripid());

// Check if this is a ferry
if (edgelabel.use() == Use::kFerry) {
has_ferry_ = true;
}
}

// Reverse the list and return
Expand Down
12 changes: 8 additions & 4 deletions src/thor/route_action.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,21 @@ namespace valhalla {
}

std::vector<thor::PathInfo> thor_worker_t::get_path(PathAlgorithm* path_algorithm, baldr::PathLocation& origin,
baldr::PathLocation& destination) {
baldr::PathLocation& destination, const std::string& costing) {
// Find the path. If bidirectional A* disable use of destination only
// edges on the first pass. If there is a failure, we allow them on the
// second pass.
valhalla::sif::cost_ptr_t cost = mode_costing[static_cast<uint32_t>(mode)];
if (path_algorithm == &bidir_astar) {
cost->set_allow_destination_only(false);
}
cost->set_pass(0);
auto path = path_algorithm->GetBestPath(origin, destination, reader,
mode_costing, mode);

// If path is not found try again with relaxed limits (if allowed)
if (path.empty()) {
if (path.empty() ||
(costing == "pedestrian" && path_algorithm->has_ferry())) {
if (cost->AllowMultiPass()) {
// 2nd pass. Less aggressive hierarchy transitioning, and retry with more candidate edges(filterd by heading in loki).

Expand All @@ -73,6 +76,7 @@ namespace valhalla {
destination.edges.insert(destination.edges.end(), destination.filtered_edges.begin(), destination.filtered_edges.end());

path_algorithm->Clear();
cost->set_pass(1);
bool using_astar = (path_algorithm == &astar);
float relax_factor = using_astar ? 16.0f : 8.0f;
float expansion_within_factor = using_astar ? 4.0f : 2.0f;
Expand Down Expand Up @@ -113,7 +117,7 @@ namespace valhalla {
}

// Get best path and keep it
auto temp_path = get_path(path_algorithm, *origin, *destination);
auto temp_path = get_path(path_algorithm, *origin, *destination, costing);
temp_path.swap(path);

// Merge through legs by updating the time and splicing the lists
Expand Down Expand Up @@ -178,7 +182,7 @@ namespace valhalla {
}

// Get best path and keep it
auto temp_path = get_path(path_algorithm, *origin, *destination);
auto temp_path = get_path(path_algorithm, *origin, *destination, costing);

// Merge through legs by updating the time and splicing the lists
if(!path.empty()) {
Expand Down
10 changes: 7 additions & 3 deletions src/valhalla_run_route.cc
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,19 @@ TripPath PathTest(GraphReader& reader, PathLocation& origin,
const std::shared_ptr<DynamicCost>* mode_costing,
const TravelMode mode, PathStatistics& data,
bool multi_run, uint32_t iterations,
bool using_astar, bool match_test) {
bool using_astar, bool match_test,
const std::string& routetype) {
auto t1 = std::chrono::high_resolution_clock::now();
std::vector<PathInfo> pathedges;
pathedges = pathalgorithm->GetBestPath(origin, dest, reader, mode_costing, mode);
cost_ptr_t cost = mode_costing[static_cast<uint32_t>(mode)];
cost->set_pass(0);
data.incPasses();
if (pathedges.size() == 0) {
if (pathedges.size() == 0 ||
(routetype == "pedestrian" && pathalgorithm->has_ferry())) {
if (cost->AllowMultiPass()) {
LOG_INFO("Try again with relaxed hierarchy limits");
cost->set_pass(1);
pathalgorithm->Clear();
float relax_factor = (using_astar) ? 16.0f : 8.0f;
float expansion_within_factor = (using_astar) ? 4.0f : 2.0f;
Expand Down Expand Up @@ -705,7 +709,7 @@ int main(int argc, char *argv[]) {
try {
trip_path = PathTest(reader, path_location[i], path_location[i + 1],
pathalgorithm, mode_costing, mode, data, multi_run,
iterations, using_astar, match_test);
iterations, using_astar, match_test, routetype);
} catch (std::runtime_error& rte) {
LOG_ERROR("trip_path not found");
}
Expand Down
3 changes: 3 additions & 0 deletions valhalla/baldr/graphconstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ constexpr uint32_t kMaxDensity = 15;
// clamped to this maximum value.
constexpr uint32_t kMaxSpeedKph = 140; // ~85 MPH

// Maximum ferry speed
constexpr uint32_t kMaxFerrySpeedKph = 40; // 21 knots

// Road class or importance of an edge
enum class RoadClass : uint8_t {
kMotorway = 0,
Expand Down
19 changes: 19 additions & 0 deletions valhalla/sif/dynamiccost.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ class DynamicCost {
*/
virtual bool AllowMultiPass() const;

/**
* Get the pass number.
* @return Returns the pass through the algorithm.
*/
uint32_t pass() const {
return pass_;
}

/**
* Set the pass number.
* @param pass Pass number (incremental).
*/
void set_pass(const uint32_t pass) {
pass_ = pass;
}

/**
* Returns the maximum transfer distance between stops that you are willing
* to travel for this mode. It is the max distance you are willing to
Expand Down Expand Up @@ -409,6 +425,9 @@ class DynamicCost {
}

protected:
// Algorithm pass
uint32_t pass_;

// Flag indicating whether transit connections are allowed.
bool allow_transit_connections_;

Expand Down
8 changes: 6 additions & 2 deletions valhalla/sif/hierarchylimits.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,14 @@ struct HierarchyLimits {

/**
* Relax hierarchy limits to try to find a route when initial attempt fails.
* Do not relax limits if they are unlimited (bicycle and pedestrian for
* example).
*/
void Relax(const float factor, const float expansion_within_factor) {
max_up_transitions *= factor;
expansion_within_dist *= expansion_within_factor;
if (max_up_transitions != kUnlimitedTransitions) {
max_up_transitions *= factor;
expansion_within_dist *= expansion_within_factor;
}
}
};

Expand Down
13 changes: 12 additions & 1 deletion valhalla/thor/pathalgorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class PathAlgorithm {
* Constructor
*/
PathAlgorithm()
: interrupt(nullptr) {
: interrupt(nullptr),
has_ferry_(false) {
}

/**
Expand Down Expand Up @@ -68,9 +69,19 @@ class PathAlgorithm {
interrupt = interrupt_callback;
}

/**
* Does the path include a ferry?
* @return Returns true if the path includes a ferry.
*/
bool has_ferry() const {
return has_ferry_;
}

protected:
const std::function<void()>* interrupt;

bool has_ferry_; // Indicates whether the path has a ferry

/**
* Check for path completion along the same edge. Edge ID in question
* is along both an origin and destination and origin shows up at the
Expand Down
2 changes: 1 addition & 1 deletion valhalla/thor/worker.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class thor_worker_t : public service_worker_t{
protected:

std::vector<thor::PathInfo> get_path(PathAlgorithm* path_algorithm, baldr::PathLocation& origin,
baldr::PathLocation& destination);
baldr::PathLocation& destination, const std::string& costing);
void log_admin(odin::TripPath&);
valhalla::sif::cost_ptr_t get_costing(
const boost::property_tree::ptree& request, const std::string& costing);
Expand Down

0 comments on commit 8b0fb8d

Please sign in to comment.