Skip to content

Commit

Permalink
Traffic - Speeds in Edge Costing (valhalla#1358)
Browse files Browse the repository at this point in the history
* added speed to the EdgeCost interface, replacing all the derived EdgeCost methods with the new one for traffic influenced routing

* added GetSpeed utility function within GraphTile to choose a speed
  • Loading branch information
kdiluca authored Jun 13, 2018
1 parent 4238a58 commit 32c3513
Show file tree
Hide file tree
Showing 30 changed files with 174 additions and 108 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ We highly encourage running and updating the tests to make sure no regressions h

make check

To run an individual test, `make run-<test name>` from the build directory or `./test/<testname>`

Coverage reports are automatically generated using codecov for each pull request, but you can also build them locally by passing `-DENABLE_COVERAGE=On` and running `make coverage`.

Command Line Tools
Expand Down
4 changes: 3 additions & 1 deletion src/meili/map_matcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ Interpolation InterpolateMeasurement(const MapMatcher& mapmatcher,

// Get the amount of time spent on this segment
auto edge_percent = segment->target - segment->source;
auto route_time = mapmatcher.costing()->EdgeCost(directededge).secs * edge_percent;
auto route_time =
mapmatcher.costing()->EdgeCost(directededge, tile->GetSpeed(directededge)).secs *
edge_percent;

Interpolation interp{projected_point, segment->edgeid, sq_distance,
route_distance, route_time, offset};
Expand Down
15 changes: 10 additions & 5 deletions src/meili/routing.cc
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,8 @@ find_shortest_path(baldr::GraphReader& reader,
// to itself must be 0, so sortcost = cost
sif::Cost cost(label.cost().cost + directededge->length() * edge.percent_along,
label.cost().secs +
costing->EdgeCost(directededge).secs * edge.percent_along);
costing->EdgeCost(directededge, tile->GetSpeed(directededge)).secs *
edge.percent_along);
// We only add the labels if we are under the limits for distance and for time or time
// limit is 0
if (cost.cost < max_dist && (max_time < 0 || cost.secs < max_time)) {
Expand All @@ -450,7 +451,8 @@ find_shortest_path(baldr::GraphReader& reader,
// Get cost - use EdgeCost to get time along the edge. Override
// cost portion to be distance. Add heuristic to get sort cost.
sif::Cost cost(label.cost().cost + directededge->length(),
label.cost().secs + costing->EdgeCost(directededge).secs);
label.cost().secs +
costing->EdgeCost(directededge, tile->GetSpeed(directededge)).secs);
// We only add the labels if we are under the limits for distance and for time or time limit
// is 0
if (cost.cost < max_dist && (max_time < 0 || cost.secs < max_time)) {
Expand Down Expand Up @@ -549,8 +551,10 @@ find_shortest_path(baldr::GraphReader& reader,
// cost portion to be distance. The heuristic cost from a
// destination to itself must be 0
float f = (other_edge.percent_along - origin_edge.percent_along);
sif::Cost cost(label.cost().cost + directededge->length() * f,
label.cost().secs + costing->EdgeCost(directededge).secs * f);
sif::Cost
cost(label.cost().cost + directededge->length() * f,
label.cost().secs +
costing->EdgeCost(directededge, tile->GetSpeed(directededge)).secs * f);
// We only add the labels if we are under the limits for distance and for time or
// time limit is 0
if (cost.cost < max_dist && (max_time < 0 || cost.secs < max_time)) {
Expand All @@ -567,7 +571,8 @@ find_shortest_path(baldr::GraphReader& reader,
// destination to itself must be 0
float f = (1.0f - origin_edge.percent_along);
sif::Cost cost(label.cost().cost + directededge->length() * f,
label.cost().secs + costing->EdgeCost(directededge).secs * f);
label.cost().secs +
costing->EdgeCost(directededge, tile->GetSpeed(directededge)).secs * f);
// We only add the labels if we are under the limits for distance and for time or time
// limit is 0
if (cost.cost < max_dist && (max_time < 0 || cost.secs < max_time)) {
Expand Down
2 changes: 1 addition & 1 deletion src/meili/universal_cost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class UniversalCost : public sif::DynamicCost {
return true;
}

sif::Cost EdgeCost(const baldr::DirectedEdge* edge) const override {
sif::Cost EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const override {
float length = edge->length();
return {length, length};
}
Expand Down
19 changes: 11 additions & 8 deletions src/sif/autocost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,10 @@ class AutoCost : public DynamicCost {
* Get the cost to traverse the specified directed edge. Cost includes
* the time (seconds) to traverse the edge.
* @param edge Pointer to a directed edge.
* @param speed A speed for a road segment/edge.
* @return Returns the cost and time (seconds)
*/
virtual Cost EdgeCost(const baldr::DirectedEdge* edge) const;
virtual Cost EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const;

/**
* Returns the cost to make the transition from the predecessor edge.
Expand Down Expand Up @@ -473,7 +474,7 @@ bool AutoCost::AllowedReverse(const baldr::DirectedEdge* edge,
}

// Get the cost to traverse the edge in seconds
Cost AutoCost::EdgeCost(const DirectedEdge* edge) const {
Cost AutoCost::EdgeCost(const DirectedEdge* edge, const uint32_t speed) const {
float factor = (edge->use() == Use::kFerry) ? ferry_factor_ : density_factor_[edge->density()];

factor += highway_factor_ * kHighwayFactor[static_cast<uint32_t>(edge->classification())] +
Expand All @@ -482,7 +483,7 @@ Cost AutoCost::EdgeCost(const DirectedEdge* edge) const {
factor += toll_factor_;
}

float sec = (edge->length() * speedfactor_[edge->speed()]);
float sec = (edge->length() * speedfactor_[speed]);
return Cost(sec * factor, sec);
}

Expand Down Expand Up @@ -634,12 +635,13 @@ class AutoShorterCost : public AutoCost {
* Returns the cost to traverse the edge and an estimate of the actual time
* (in seconds) to traverse the edge.
* @param edge Pointer to a directed edge.
* @param speed A speed for a road segment/edge.
* @return Returns the cost to traverse the edge.
*/
virtual Cost EdgeCost(const baldr::DirectedEdge* edge) const {
virtual Cost EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const {
float factor = (edge->use() == Use::kFerry) ? ferry_factor_ : 1.0f;
return Cost(edge->length() * adjspeedfactor_[edge->speed()] * factor,
edge->length() * speedfactor_[edge->speed()]);
return Cost(edge->length() * adjspeedfactor_[speed] * factor,
edge->length() * speedfactor_[speed]);
}

/**
Expand Down Expand Up @@ -934,14 +936,15 @@ class HOVCost : public AutoCost {
* Returns the cost to traverse the edge and an estimate of the actual time
* (in seconds) to traverse the edge.
* @param edge Pointer to a directed edge.
* @param speed A speed for a road segment/edge.
* @return Returns the cost to traverse the edge.
*/
virtual Cost EdgeCost(const baldr::DirectedEdge* edge) const {
virtual Cost EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const {
float factor = (edge->use() == Use::kFerry) ? ferry_factor_ : density_factor_[edge->density()];
if ((edge->forwardaccess() & kHOVAccess) && !(edge->forwardaccess() & kAutoAccess)) {
factor *= kHOVFactor;
}
float sec = (edge->length() * speedfactor_[edge->speed()]);
float sec = (edge->length() * speedfactor_[speed]);
return Cost(sec * factor, sec);
}

Expand Down
9 changes: 5 additions & 4 deletions src/sif/bicyclecost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,10 @@ class BicycleCost : public DynamicCost {
* Get the cost to traverse the specified directed edge. Cost includes
* the time (seconds) to traverse the edge.
* @param edge Pointer to a directed edge.
* @param speed A speed for a road segment/edge.
* @return Returns the cost and time (seconds)
*/
virtual Cost EdgeCost(const baldr::DirectedEdge* edge) const;
virtual Cost EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const;

/**
* Returns the cost to make the transition from the predecessor edge.
Expand Down Expand Up @@ -637,7 +638,7 @@ bool BicycleCost::AllowedReverse(const baldr::DirectedEdge* edge,

// Returns the cost to traverse the edge and an estimate of the actual time
// (in seconds) to traverse the edge.
Cost BicycleCost::EdgeCost(const baldr::DirectedEdge* edge) const {
Cost BicycleCost::EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const {
// Stairs/steps - high cost (travel speed = 1kph) so they are generally avoided.
if (edge->use() == Use::kSteps) {
float sec = (edge->length() * speedfactor_[1]);
Expand All @@ -647,7 +648,7 @@ Cost BicycleCost::EdgeCost(const baldr::DirectedEdge* edge) const {
// Ferries are a special case - they use the ferry speed (stored on the edge)
if (edge->use() == Use::kFerry) {
// Compute elapsed time based on speed. Modulate cost with weighting factors.
float sec = (edge->length() * speedfactor_[edge->speed()]);
float sec = (edge->length() * speedfactor_[speed]);
return {sec * ferry_factor_, sec};
}

Expand All @@ -668,7 +669,7 @@ Cost BicycleCost::EdgeCost(const baldr::DirectedEdge* edge) const {
float accommodation_factor = 1.0f;

// Special use cases: cycleway, footway, and path
uint32_t road_speed = static_cast<uint32_t>(edge->speed() + 0.5f);
uint32_t road_speed = static_cast<uint32_t>(speed + 0.5f);
if (edge->use() == Use::kCycleway || edge->use() == Use::kFootway || edge->use() == Use::kPath) {

// Differentiate how segregated the way is from pedestrians
Expand Down
7 changes: 7 additions & 0 deletions src/sif/dynamiccost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ Cost DynamicCost::EdgeCost(const baldr::DirectedEdge* edge,
return {0.0f, 0.0f};
}

// Get the cost to traverse the specified directed edge and gather/pass
// the speed along for use within costing in the PathAlgorithm. Cost
// includes the time (seconds) to traverse the edge.
Cost DynamicCost::EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const {
return {0.0f, 0.0f};
}

// Returns the cost to make the transition from the predecessor edge.
// Defaults to 0. Costing models that wish to include edge transition
// costs (i.e., intersection/turn costs) must override this method.
Expand Down
9 changes: 5 additions & 4 deletions src/sif/motorcyclecost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,10 @@ class MotorcycleCost : public DynamicCost {
* Get the cost to traverse the specified directed edge. Cost includes
* the time (seconds) to traverse the edge.
* @param edge Pointer to a directed edge.
* @param speed A speed for a road segment/edge.
* @return Returns the cost and time (seconds)
*/
virtual Cost EdgeCost(const baldr::DirectedEdge* edge) const;
virtual Cost EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const;

/**
* Returns the cost to make the transition from the predecessor edge.
Expand Down Expand Up @@ -493,10 +494,10 @@ bool MotorcycleCost::Allowed(const baldr::NodeInfo* node) const {
return (node->access() & kMotorcycleAccess);
}

Cost MotorcycleCost::EdgeCost(const baldr::DirectedEdge* edge) const {
Cost MotorcycleCost::EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const {

if (edge->use() == Use::kFerry) {
float sec = (edge->length() * speedfactor_[edge->speed()]);
float sec = (edge->length() * speedfactor_[speed]);
return {sec * ferry_factor_, sec};
}

Expand All @@ -509,7 +510,7 @@ Cost MotorcycleCost::EdgeCost(const baldr::DirectedEdge* edge) const {
factor += kDestinationOnlyFactor;
}

float sec = (edge->length() * speedfactor_[edge->speed()]);
float sec = (edge->length() * speedfactor_[speed]);
return {sec * factor, sec};
}

Expand Down
15 changes: 8 additions & 7 deletions src/sif/motorscootercost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,10 @@ class MotorScooterCost : public DynamicCost {
* Get the cost to traverse the specified directed edge. Cost includes
* the time (seconds) to traverse the edge.
* @param edge Pointer to a directed edge.
* @param speed A speed for a road segment/edge.
* @return Returns the cost and time (seconds)
*/
virtual Cost EdgeCost(const baldr::DirectedEdge* edge) const;
virtual Cost EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const;

/**
* Returns the cost to make the transition from the predecessor edge.
Expand Down Expand Up @@ -494,18 +495,18 @@ bool MotorScooterCost::AllowedReverse(const baldr::DirectedEdge* edge,
return opp_edge->surface() <= kMinimumScooterSurface;
}

Cost MotorScooterCost::EdgeCost(const baldr::DirectedEdge* edge) const {
Cost MotorScooterCost::EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const {

if (edge->use() == Use::kFerry) {
float sec = (edge->length() * speedfactor_[edge->speed()]);
float sec = (edge->length() * speedfactor_[speed]);
return {sec * ferry_factor_, sec};
}

uint32_t scooter_speed = (std::min(top_speed_, edge->speed()) *
kSurfaceSpeedFactors[static_cast<uint32_t>(edge->surface())] *
kGradeBasedSpeedFactor[static_cast<uint32_t>(edge->weighted_grade())]);
uint32_t scooter_speed =
(std::min(top_speed_, speed) * kSurfaceSpeedFactors[static_cast<uint32_t>(edge->surface())] *
kGradeBasedSpeedFactor[static_cast<uint32_t>(edge->weighted_grade())]);

float speed_penalty = (edge->speed() > top_speed_) ? (edge->speed() - top_speed_) * 0.05f : 0.0f;
float speed_penalty = (speed > top_speed_) ? (speed - top_speed_) * 0.05f : 0.0f;
float factor = 1.0f + (density_factor_[edge->density()] - 0.85f) +
(road_factor_ * kRoadClassFactor[static_cast<uint32_t>(edge->classification())]) +
grade_penalty_[static_cast<uint32_t>(edge->weighted_grade())] + speed_penalty;
Expand Down
7 changes: 4 additions & 3 deletions src/sif/pedestriancost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,10 @@ class PedestrianCost : public DynamicCost {
* Get the cost to traverse the specified directed edge. Cost includes
* the time (seconds) to traverse the edge.
* @param edge Pointer to a directed edge.
* @param speed A speed for a road segment/edge.
* @return Returns the cost and time (seconds)
*/
virtual Cost EdgeCost(const baldr::DirectedEdge* edge) const;
virtual Cost EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const;

/**
* Returns the cost to make the transition from the predecessor edge.
Expand Down Expand Up @@ -579,11 +580,11 @@ bool PedestrianCost::AllowedReverse(const baldr::DirectedEdge* edge,

// Returns the cost to traverse the edge and an estimate of the actual time
// (in seconds) to traverse the edge.
Cost PedestrianCost::EdgeCost(const baldr::DirectedEdge* edge) const {
Cost PedestrianCost::EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const {

// Ferries are a special case - they use the ferry speed (stored on the edge)
if (edge->use() == Use::kFerry) {
float sec = edge->length() * (kSecPerHour * 0.001f) / static_cast<float>(edge->speed());
float sec = edge->length() * (kSecPerHour * 0.001f) / static_cast<float>(speed);
return {sec * ferry_factor_, sec};
}

Expand Down
5 changes: 3 additions & 2 deletions src/sif/transitcost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,10 @@ class TransitCost : public DynamicCost {
* Get the cost to traverse the specified directed edge. Cost includes
* the time (seconds) to traverse the edge.
* @param edge Pointer to a directed edge.
* @param speed A speed for a road segment/edge.
* @return Returns the cost and time (seconds)
*/
virtual Cost EdgeCost(const baldr::DirectedEdge* edge) const;
virtual Cost EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const;

/**
* Get the cost to traverse the specified directed edge using a transit
Expand Down Expand Up @@ -569,7 +570,7 @@ bool TransitCost::Allowed(const baldr::NodeInfo* node) const {

// Returns the cost to traverse the edge and an estimate of the actual time
// (in seconds) to traverse the edge.
Cost TransitCost::EdgeCost(const baldr::DirectedEdge* edge) const {
Cost TransitCost::EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const {
LOG_ERROR("Wrong transit edge cost called");
return {0.0f, 0.0f};
}
Expand Down
7 changes: 4 additions & 3 deletions src/sif/truckcost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,10 @@ class TruckCost : public DynamicCost {
* Get the cost to traverse the specified directed edge. Cost includes
* the time (seconds) to traverse the edge.
* @param edge Pointer to a directed edge.
* @param speed A speed for a road segment/edge.
* @return Returns the cost and time (seconds)
*/
virtual Cost EdgeCost(const baldr::DirectedEdge* edge) const;
virtual Cost EdgeCost(const baldr::DirectedEdge* edge, const uint32_t speed) const;

/**
* Returns the cost to make the transition from the predecessor edge.
Expand Down Expand Up @@ -511,7 +512,7 @@ bool TruckCost::Allowed(const baldr::NodeInfo* node) const {
}

// Get the cost to traverse the edge in seconds
Cost TruckCost::EdgeCost(const DirectedEdge* edge) const {
Cost TruckCost::EdgeCost(const DirectedEdge* edge, const uint32_t speed) const {

float factor = density_factor_[edge->density()];

Expand All @@ -523,7 +524,7 @@ Cost TruckCost::EdgeCost(const DirectedEdge* edge) const {
if (edge->truck_speed() > 0) {
sec = (edge->length() * speedfactor_[edge->truck_speed()]);
} else {
sec = (edge->length() * speedfactor_[edge->speed()]);
sec = (edge->length() * speedfactor_[speed]);
}

return {sec * factor, sec};
Expand Down
17 changes: 10 additions & 7 deletions src/thor/astar.cc
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ void AStarPathAlgorithm::ExpandForward(GraphReader& graphreader,
shortcuts |= directededge->shortcut();

// Compute the cost to the end of this edge
Cost newcost = pred.cost() + costing_->EdgeCost(directededge) +
Cost newcost = pred.cost() + costing_->EdgeCost(directededge, tile->GetSpeed(directededge)) +
costing_->TransitionCost(directededge, nodeinfo, pred);

// If this edge is a destination, subtract the partial/remainder cost
Expand Down Expand Up @@ -384,7 +384,8 @@ void AStarPathAlgorithm::SetOrigin(GraphReader& graphreader,

// Get cost
nodeinfo = endtile->node(directededge->endnode());
Cost cost = costing_->EdgeCost(directededge) * (1.0f - edge.percent_along());
Cost cost = costing_->EdgeCost(directededge, tile->GetSpeed(directededge)) *
(1.0f - edge.percent_along());
float dist = astarheuristic_.GetDistance(nodeinfo->latlng());

// We need to penalize this location based on its score (distance in meters from input)
Expand All @@ -407,9 +408,10 @@ void AStarPathAlgorithm::SetOrigin(GraphReader& graphreader,
// a trivial route passes along a single edge, meaning that the
// destination point must be on this edge, and so the distance
// remaining must be zero.
Cost dest_cost =
costing_->EdgeCost(tile->directededge(GraphId(destination_edge.graph_id()))) *
(1.0f - destination_edge.percent_along());
GraphId id(destination_edge.graph_id());
const DirectedEdge* dest_diredge = tile->directededge(id);
Cost dest_cost = costing_->EdgeCost(dest_diredge, tile->GetSpeed(dest_diredge)) *
(1.0f - destination_edge.percent_along());
cost.secs -= p->second.secs;
cost.cost -= dest_cost.cost;
cost.cost += destination_edge.distance();
Expand Down Expand Up @@ -472,8 +474,9 @@ uint32_t AStarPathAlgorithm::SetDestination(GraphReader& graphreader, const odin
// up to the end of the destination edge.
GraphId id(edge.graph_id());
const GraphTile* tile = graphreader.GetGraphTile(id);
destinations_[edge.graph_id()] =
costing_->EdgeCost(tile->directededge(id)) * (1.0f - edge.percent_along());
const DirectedEdge* directededge = tile->directededge(id);
destinations_[edge.graph_id()] = costing_->EdgeCost(directededge, tile->GetSpeed(directededge)) *
(1.0f - edge.percent_along());

// Edge score (penalty) is handled within GetPath. Do not add score here.

Expand Down
Loading

0 comments on commit 32c3513

Please sign in to comment.