add stoppage penalties to table_params. use those to add penalties to table results.

This commit is contained in:
Kevin Kreiser 2019-02-07 10:24:58 -05:00
parent 8b45ff7a18
commit 07f7344d5f
3 changed files with 72 additions and 6 deletions

View File

@ -60,6 +60,8 @@ struct TableParameters : public BaseParameters
std::vector<std::size_t> sources; std::vector<std::size_t> sources;
std::vector<std::size_t> destinations; std::vector<std::size_t> destinations;
double fallback_speed = INVALID_FALLBACK_SPEED; double fallback_speed = INVALID_FALLBACK_SPEED;
double min_stoppage_penalty = INVALID_MINIMUM_STOPAGE_PENALTY;
double max_stoppage_penalty = INVALID_MAXIMUM_STOPAGE_PENALTY;
enum class FallbackCoordinateType enum class FallbackCoordinateType
{ {
@ -108,11 +110,14 @@ struct TableParameters : public BaseParameters
double fallback_speed_, double fallback_speed_,
FallbackCoordinateType fallback_coordinate_type_, FallbackCoordinateType fallback_coordinate_type_,
double scale_factor_, double scale_factor_,
double min_stoppage_penalty_,
double max_stoppage_penalty_,
Args... args_) Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, sources{std::move(sources_)}, : BaseParameters{std::forward<Args>(args_)...}, sources{std::move(sources_)},
destinations{std::move(destinations_)}, fallback_speed{fallback_speed_}, destinations{std::move(destinations_)}, fallback_speed{fallback_speed_},
fallback_coordinate_type{fallback_coordinate_type_}, annotations{annotations_}, fallback_coordinate_type{fallback_coordinate_type_}, annotations{annotations_},
scale_factor{scale_factor_} scale_factor{scale_factor_}, min_stoppage_penalty{min_stoppage_penalty_},
max_stoppage_penalty{max_stoppage_penalty_}
{ {
} }
@ -143,6 +148,10 @@ struct TableParameters : public BaseParameters
if (scale_factor <= 0) if (scale_factor <= 0)
return false; return false;
if (min_stoppage_penalty <= 0 || max_stoppage_penalty <= 0 ||
max_stoppage_penalty > min_stoppage_penalty)
return false;
return true; return true;
} }
}; };

View File

@ -48,7 +48,7 @@ struct osm_way_id
struct duplicated_node struct duplicated_node
{ {
}; };
} } // namespace tag
using OSMNodeID = osrm::Alias<std::uint64_t, tag::osm_node_id>; using OSMNodeID = osrm::Alias<std::uint64_t, tag::osm_node_id>;
static_assert(std::is_pod<OSMNodeID>(), "OSMNodeID is not a valid alias"); static_assert(std::is_pod<OSMNodeID>(), "OSMNodeID is not a valid alias");
using OSMWayID = osrm::Alias<std::uint64_t, tag::osm_way_id>; using OSMWayID = osrm::Alias<std::uint64_t, tag::osm_way_id>;
@ -117,7 +117,13 @@ static const EdgeDuration MAXIMAL_EDGE_DURATION = std::numeric_limits<EdgeDurati
static const EdgeDistance MAXIMAL_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max(); static const EdgeDistance MAXIMAL_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>::max(); static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>::max();
static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max(); static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
static const EdgeDistance INVALID_FALLBACK_SPEED = std::numeric_limits<double>::max(); static const EdgeDistance INVALID_FALLBACK_SPEED = std::numeric_limits<EdgeDistance>::max();
static const EdgeDuration INVALID_MINIMUM_STOPAGE_PENALTY =
std::numeric_limits<EdgeDuration>::max();
static const EdgeDuration INVALID_MAXIMUM_STOPAGE_PENALTY =
std::numeric_limits<EdgeDuration>::max();
constexpr double MINIMAL_ACCEL_DECEL_PENALIZABLE_SPEED = 10;
constexpr double MAXIMAL_ACCEL_DECEL_PENALIZABLE_SPEED = 40;
// FIXME the bitfields we use require a reduced maximal duration, this should be kept consistent // FIXME the bitfields we use require a reduced maximal duration, this should be kept consistent
// within the code base. For now we have to ensure that we don't case 30 bit to -1 and break any // within the code base. For now we have to ensure that we don't case 30 bit to -1 and break any

View File

@ -17,6 +17,31 @@
#include <boost/assert.hpp> #include <boost/assert.hpp>
namespace
{
// where does this speed lie with respect to the min/max penalizable speeds
inline double stoppage_penalty(double speed, double min_penalty, double penalty_range)
{
// You're so slow already you don't get a penalty
if (speed < MINIMAL_ACCEL_DECEL_PENALIZABLE_SPEED)
return 0;
// Find where it is on the scale
constexpr auto max =
MAXIMAL_ACCEL_DECEL_PENALIZABLE_SPEED - MINIMAL_ACCEL_DECEL_PENALIZABLE_SPEED;
auto ratio = (speed - MINIMAL_ACCEL_DECEL_PENALIZABLE_SPEED) / max;
// You're faster than the max so you get the max
if (ratio >= 1)
return min_penalty + penalty_range;
// You're in between so you get a linear combination
return min_penalty + ratio * penalty_range;
}
} // namespace
namespace osrm namespace osrm
{ {
namespace engine namespace engine
@ -96,6 +121,7 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
} }
std::vector<api::TableAPI::TableCellRef> estimated_pairs; std::vector<api::TableAPI::TableCellRef> estimated_pairs;
const auto stoppage_penalty_range = params.max_stoppage_penalty - params.min_stoppage_penalty;
// Scan table for null results - if any exist, replace with distance estimates // Scan table for null results - if any exist, replace with distance estimates
if (params.fallback_speed != INVALID_FALLBACK_SPEED || params.scale_factor != 1) if (params.fallback_speed != INVALID_FALLBACK_SPEED || params.scale_factor != 1)
@ -106,6 +132,30 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
{ {
const auto &table_index = row * num_destinations + column; const auto &table_index = row * num_destinations + column;
BOOST_ASSERT(table_index < result_tables_pair.first.size()); BOOST_ASSERT(table_index < result_tables_pair.first.size());
// Add decel/accel penalty to account for stoppage at the start/end of trip
if (stoppage_penalty_range >= 0 &&
result_tables_pair.first[table_index] != MAXIMAL_EDGE_DURATION)
{
const auto &source =
snapped_phantoms[params.sources.empty() ? row : params.sources[row]];
const auto &destination =
snapped_phantoms[params.destinations.empty() ? column
: params.destinations[column]];
// TODO: if phantom node is actual node, will the distance/duration be 0?
auto source_penalty =
stoppage_penalty(source.forward_distance / source.forward_duration,
params.min_stoppage_penalty,
stoppage_penalty_range);
auto dest_penalty = stoppage_penalty(destination.forward_distance /
destination.forward_duration,
params.min_stoppage_penalty,
stoppage_penalty_range);
result_tables_pair.first[table_index] += source_penalty + dest_penalty;
}
// Estimate null results based on fallback_speed (if valid) and distance
if (params.fallback_speed != INVALID_FALLBACK_SPEED && params.fallback_speed > 0 && if (params.fallback_speed != INVALID_FALLBACK_SPEED && params.fallback_speed > 0 &&
result_tables_pair.first[table_index] == MAXIMAL_EDGE_DURATION) result_tables_pair.first[table_index] == MAXIMAL_EDGE_DURATION)
{ {
@ -132,6 +182,7 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
estimated_pairs.emplace_back(row, column); estimated_pairs.emplace_back(row, column);
} }
// Apply a scale factor to non-null result if requested
if (params.scale_factor > 0 && params.scale_factor != 1 && if (params.scale_factor > 0 && params.scale_factor != 1 &&
result_tables_pair.first[table_index] != MAXIMAL_EDGE_DURATION && result_tables_pair.first[table_index] != MAXIMAL_EDGE_DURATION &&
result_tables_pair.first[table_index] != 0) result_tables_pair.first[table_index] != 0)
@ -158,6 +209,6 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
return Status::Ok; return Status::Ok;
} }
} } // namespace plugins
} } // namespace engine
} } // namespace osrm