added max_speed to the profiles (#3089)
This commit is contained in:
@@ -173,6 +173,8 @@ class BaseDataFacade
|
||||
|
||||
virtual bool GetContinueStraightDefault() const = 0;
|
||||
|
||||
virtual double GetMapMatchingMaxSpeed() const = 0;
|
||||
|
||||
virtual BearingClassID GetBearingClassID(const NodeID id) const = 0;
|
||||
|
||||
virtual util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const = 0;
|
||||
|
||||
@@ -899,6 +899,11 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
return m_profile_properties.continue_straight_at_waypoint;
|
||||
}
|
||||
|
||||
double GetMapMatchingMaxSpeed() const override final
|
||||
{
|
||||
return m_profile_properties.max_speed_for_map_matching;
|
||||
}
|
||||
|
||||
BearingClassID GetBearingClassID(const NodeID nid) const override final
|
||||
{
|
||||
return m_bearing_class_id_table.at(nid);
|
||||
|
||||
@@ -931,6 +931,11 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
return m_profile_properties->continue_straight_at_waypoint;
|
||||
}
|
||||
|
||||
double GetMapMatchingMaxSpeed() const override final
|
||||
{
|
||||
return m_profile_properties->max_speed_for_map_matching;
|
||||
}
|
||||
|
||||
BearingClassID GetBearingClassID(const NodeID id) const override final
|
||||
{
|
||||
return m_bearing_class_id_table.at(id);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "engine/map_matching/matching_confidence.hpp"
|
||||
#include "engine/map_matching/sub_matching.hpp"
|
||||
|
||||
#include "extractor/profile_properties.hpp"
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
#include "util/for_each_pair.hpp"
|
||||
|
||||
@@ -32,7 +33,6 @@ using HMM = map_matching::HiddenMarkovModel<CandidateLists>;
|
||||
using SubMatchingList = std::vector<map_matching::SubMatching>;
|
||||
|
||||
constexpr static const unsigned MAX_BROKEN_STATES = 10;
|
||||
constexpr static const double MAX_SPEED = 180 / 3.6; // 180km -> m/s
|
||||
static const constexpr double MATCHING_BETA = 10;
|
||||
constexpr static const double MAX_DISTANCE_DELTA = 2000.;
|
||||
|
||||
@@ -46,6 +46,7 @@ class MapMatching final : public BasicRoutingInterface<DataFacadeT, MapMatching<
|
||||
map_matching::EmissionLogProbability default_emission_log_probability;
|
||||
map_matching::TransitionLogProbability transition_log_probability;
|
||||
map_matching::MatchingConfidence confidence;
|
||||
extractor::ProfileProperties m_profile_properties;
|
||||
|
||||
unsigned GetMedianSampleTime(const std::vector<unsigned> ×tamps) const
|
||||
{
|
||||
@@ -98,7 +99,7 @@ class MapMatching final : public BasicRoutingInterface<DataFacadeT, MapMatching<
|
||||
const auto max_distance_delta = [&] {
|
||||
if (use_timestamps)
|
||||
{
|
||||
return median_sample_time * MAX_SPEED;
|
||||
return median_sample_time * facade.GetMapMatchingMaxSpeed();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -172,24 +173,135 @@ class MapMatching final : public BasicRoutingInterface<DataFacadeT, MapMatching<
|
||||
prev_unbroken_timestamps.push_back(initial_timestamp);
|
||||
for (auto t = initial_timestamp + 1; t < candidates_list.size(); ++t)
|
||||
{
|
||||
|
||||
const bool gap_in_trace = [&, use_timestamps]() {
|
||||
// use temporal information if available to determine a split
|
||||
if (use_timestamps)
|
||||
{
|
||||
return trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] >
|
||||
max_broken_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
return t - prev_unbroken_timestamps.back() > MAX_BROKEN_STATES;
|
||||
}
|
||||
}();
|
||||
|
||||
if (!gap_in_trace)
|
||||
{
|
||||
BOOST_ASSERT(!prev_unbroken_timestamps.empty());
|
||||
const std::size_t prev_unbroken_timestamp = prev_unbroken_timestamps.back();
|
||||
|
||||
const auto &prev_viterbi = model.viterbi[prev_unbroken_timestamp];
|
||||
const auto &prev_pruned = model.pruned[prev_unbroken_timestamp];
|
||||
const auto &prev_unbroken_timestamps_list =
|
||||
candidates_list[prev_unbroken_timestamp];
|
||||
const auto &prev_coordinate = trace_coordinates[prev_unbroken_timestamp];
|
||||
|
||||
auto ¤t_viterbi = model.viterbi[t];
|
||||
auto ¤t_pruned = model.pruned[t];
|
||||
auto ¤t_parents = model.parents[t];
|
||||
auto ¤t_lengths = model.path_distances[t];
|
||||
const auto ¤t_timestamps_list = candidates_list[t];
|
||||
const auto ¤t_coordinate = trace_coordinates[t];
|
||||
|
||||
const auto haversine_distance = util::coordinate_calculation::haversineDistance(
|
||||
prev_coordinate, current_coordinate);
|
||||
// assumes minumum of 0.1 m/s
|
||||
const int duration_upper_bound =
|
||||
((haversine_distance + max_distance_delta) * 0.25) * 10;
|
||||
|
||||
// compute d_t for this timestamp and the next one
|
||||
for (const auto s : util::irange<std::size_t>(0UL, prev_viterbi.size()))
|
||||
{
|
||||
if (prev_pruned[s])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto s_prime :
|
||||
util::irange<std::size_t>(0UL, current_viterbi.size()))
|
||||
{
|
||||
const double emission_pr = emission_log_probabilities[t][s_prime];
|
||||
double new_value = prev_viterbi[s] + emission_pr;
|
||||
if (current_viterbi[s_prime] > new_value)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
forward_heap.Clear();
|
||||
reverse_heap.Clear();
|
||||
|
||||
double network_distance;
|
||||
if (facade.GetCoreSize() > 0)
|
||||
{
|
||||
forward_core_heap.Clear();
|
||||
reverse_core_heap.Clear();
|
||||
network_distance = super::GetNetworkDistanceWithCore(
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
forward_core_heap,
|
||||
reverse_core_heap,
|
||||
prev_unbroken_timestamps_list[s].phantom_node,
|
||||
current_timestamps_list[s_prime].phantom_node,
|
||||
duration_upper_bound);
|
||||
}
|
||||
else
|
||||
{
|
||||
network_distance = super::GetNetworkDistance(
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
prev_unbroken_timestamps_list[s].phantom_node,
|
||||
current_timestamps_list[s_prime].phantom_node);
|
||||
}
|
||||
|
||||
// get distance diff between loc1/2 and locs/s_prime
|
||||
const auto d_t = std::abs(network_distance - haversine_distance);
|
||||
|
||||
// very low probability transition -> prune
|
||||
if (d_t >= max_distance_delta)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const double transition_pr = transition_log_probability(d_t);
|
||||
new_value += transition_pr;
|
||||
|
||||
if (new_value > current_viterbi[s_prime])
|
||||
{
|
||||
current_viterbi[s_prime] = new_value;
|
||||
current_parents[s_prime] = std::make_pair(prev_unbroken_timestamp, s);
|
||||
current_lengths[s_prime] = network_distance;
|
||||
current_pruned[s_prime] = false;
|
||||
model.breakage[t] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (model.breakage[t])
|
||||
{
|
||||
// save start of breakage -> we need this as split point
|
||||
if (t < breakage_begin)
|
||||
{
|
||||
breakage_begin = t;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(prev_unbroken_timestamps.size() > 0);
|
||||
// remove both ends of the breakage
|
||||
prev_unbroken_timestamps.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_unbroken_timestamps.push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
// breakage recover has removed all previous good points
|
||||
bool trace_split = prev_unbroken_timestamps.empty();
|
||||
const bool trace_split = prev_unbroken_timestamps.empty();
|
||||
|
||||
// use temporal information if available to determine a split
|
||||
if (use_timestamps)
|
||||
{
|
||||
trace_split =
|
||||
trace_split ||
|
||||
(trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] >
|
||||
max_broken_time);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace_split =
|
||||
trace_split || (t - prev_unbroken_timestamps.back() > MAX_BROKEN_STATES);
|
||||
}
|
||||
|
||||
if (trace_split)
|
||||
if (trace_split || gap_in_trace)
|
||||
{
|
||||
std::size_t split_index = t;
|
||||
if (breakage_begin != map_matching::INVALID_STATE)
|
||||
@@ -213,114 +325,9 @@ class MapMatching final : public BasicRoutingInterface<DataFacadeT, MapMatching<
|
||||
// Important: We potentially go back here!
|
||||
// However since t > new_start >= breakge_begin
|
||||
// we can only reset trace_coordindates.size() times.
|
||||
t = new_start + 1;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(!prev_unbroken_timestamps.empty());
|
||||
const std::size_t prev_unbroken_timestamp = prev_unbroken_timestamps.back();
|
||||
|
||||
const auto &prev_viterbi = model.viterbi[prev_unbroken_timestamp];
|
||||
const auto &prev_pruned = model.pruned[prev_unbroken_timestamp];
|
||||
const auto &prev_unbroken_timestamps_list = candidates_list[prev_unbroken_timestamp];
|
||||
const auto &prev_coordinate = trace_coordinates[prev_unbroken_timestamp];
|
||||
|
||||
auto ¤t_viterbi = model.viterbi[t];
|
||||
auto ¤t_pruned = model.pruned[t];
|
||||
auto ¤t_parents = model.parents[t];
|
||||
auto ¤t_lengths = model.path_distances[t];
|
||||
const auto ¤t_timestamps_list = candidates_list[t];
|
||||
const auto ¤t_coordinate = trace_coordinates[t];
|
||||
|
||||
const auto haversine_distance = util::coordinate_calculation::haversineDistance(
|
||||
prev_coordinate, current_coordinate);
|
||||
// assumes minumum of 0.1 m/s
|
||||
const int duration_uppder_bound =
|
||||
((haversine_distance + max_distance_delta) * 0.25) * 10;
|
||||
|
||||
// compute d_t for this timestamp and the next one
|
||||
for (const auto s : util::irange<std::size_t>(0UL, prev_viterbi.size()))
|
||||
{
|
||||
if (prev_pruned[s])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto s_prime : util::irange<std::size_t>(0UL, current_viterbi.size()))
|
||||
{
|
||||
|
||||
const double emission_pr = emission_log_probabilities[t][s_prime];
|
||||
double new_value = prev_viterbi[s] + emission_pr;
|
||||
if (current_viterbi[s_prime] > new_value)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
forward_heap.Clear();
|
||||
reverse_heap.Clear();
|
||||
|
||||
double network_distance;
|
||||
if (facade.GetCoreSize() > 0)
|
||||
{
|
||||
forward_core_heap.Clear();
|
||||
reverse_core_heap.Clear();
|
||||
network_distance = super::GetNetworkDistanceWithCore(
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
forward_core_heap,
|
||||
reverse_core_heap,
|
||||
prev_unbroken_timestamps_list[s].phantom_node,
|
||||
current_timestamps_list[s_prime].phantom_node,
|
||||
duration_uppder_bound);
|
||||
}
|
||||
else
|
||||
{
|
||||
network_distance = super::GetNetworkDistance(
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
prev_unbroken_timestamps_list[s].phantom_node,
|
||||
current_timestamps_list[s_prime].phantom_node);
|
||||
}
|
||||
|
||||
// get distance diff between loc1/2 and locs/s_prime
|
||||
const auto d_t = std::abs(network_distance - haversine_distance);
|
||||
|
||||
// very low probability transition -> prune
|
||||
if (d_t >= max_distance_delta)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const double transition_pr = transition_log_probability(d_t);
|
||||
new_value += transition_pr;
|
||||
|
||||
if (new_value > current_viterbi[s_prime])
|
||||
{
|
||||
current_viterbi[s_prime] = new_value;
|
||||
current_parents[s_prime] = std::make_pair(prev_unbroken_timestamp, s);
|
||||
current_lengths[s_prime] = network_distance;
|
||||
current_pruned[s_prime] = false;
|
||||
model.breakage[t] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (model.breakage[t])
|
||||
{
|
||||
// save start of breakage -> we need this as split point
|
||||
if (t < breakage_begin)
|
||||
{
|
||||
breakage_begin = t;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(prev_unbroken_timestamps.size() > 0);
|
||||
// remove both ends of the breakage
|
||||
prev_unbroken_timestamps.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_unbroken_timestamps.push_back(t);
|
||||
t = new_start;
|
||||
// note: the head of the loop will call ++t, hence the next
|
||||
// iteration will actually be on new_start+1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,11 +8,14 @@ namespace osrm
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
const constexpr auto DEFAULT_MAX_SPEED = 180 / 3.6; // 180kmph -> m/s
|
||||
|
||||
struct ProfileProperties
|
||||
{
|
||||
ProfileProperties()
|
||||
: traffic_signal_penalty(0), u_turn_penalty(0), continue_straight_at_waypoint(true),
|
||||
use_turn_restrictions(false), left_hand_driving(false)
|
||||
: traffic_signal_penalty(0), u_turn_penalty(0),
|
||||
max_speed_for_map_matching(DEFAULT_MAX_SPEED), continue_straight_at_waypoint(true),
|
||||
use_turn_restrictions(false), left_hand_driving(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -30,10 +33,18 @@ struct ProfileProperties
|
||||
traffic_signal_penalty = boost::numeric_cast<int>(traffic_signal_penalty_ * 10.);
|
||||
}
|
||||
|
||||
double GetMaxSpeedForMapMatching() const { return max_speed_for_map_matching; }
|
||||
|
||||
void SetMaxSpeedForMapMatching(const double max_speed_for_map_matching_)
|
||||
{
|
||||
max_speed_for_map_matching = max_speed_for_map_matching_;
|
||||
}
|
||||
|
||||
//! penalty to cross a traffic light in deci-seconds
|
||||
int traffic_signal_penalty;
|
||||
//! penalty to do a uturn in deci-seconds
|
||||
int u_turn_penalty;
|
||||
double max_speed_for_map_matching;
|
||||
bool continue_straight_at_waypoint;
|
||||
bool use_turn_restrictions;
|
||||
bool left_hand_driving;
|
||||
|
||||
Reference in New Issue
Block a user