osrm-backend
osrm-backend copied to clipboard
How to use angle in map-matching.
Hi team,I think angle is an important factor in map matching, how can I use it in osrm. I found transition_probability only rely on const auto d_t = std::abs(network_distance - haversine_distance); but I think the angle between pre-current phantom node and trace coordinates should also be taken into, i modified it slightly(the commented part of the code), want to hear team opinion. I tested about 100 angle-related cases, and the accuracy rate has greatly improved.
// include/engine/map_matching/hidden_markov_model.hpp
struct TransitionAngleLogProbability
{
double sigma_z;
double log_sigma_z;
TransitionAngleLogProbability(const double sigma_z) : sigma_z(sigma_z), log_sigma_z(std::log(sigma_z))
{
}
double operator()(const double distance) const
{
return -0.5 * (log_2_pi + (distance / sigma_z) * (distance / sigma_z)) - log_sigma_z;
}
};
// src/engine/routing_algorithms/map_matching.cpp:222
// 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;
}
double network_distance =
getNetworkDistance(engine_working_data,
facade,
forward_heap,
reverse_heap,
prev_unbroken_timestamps_list[s].phantom_node,
current_timestamps_list[s_prime].phantom_node,
weight_upper_bound);
// 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;
// calculate angle transition probability
// const PhantomNodeWithDistance &pre_phantom_node = prev_unbroken_timestamps_list[s];
// const PhantomNodeWithDistance ¤t_phantom_node = current_timestamps_list[s_prime];
//
// FixedLongitude translate_longitude =
// prev_coordinate.lon - pre_phantom_node.phantom_node.location.lon;
// FixedLatitude translate_latitude =
// prev_coordinate.lat - pre_phantom_node.phantom_node.location.lat;
//
// double transition_angle = util::coordinate_calculation::computeAngle(
// util::Coordinate(current_phantom_node.phantom_node.location.lon + translate_longitude,
// current_phantom_node.phantom_node.location.lat + translate_latitude),
// prev_coordinate, current_coordinate);
//
// // norm angle to
// transition_angle = transition_angle > 180 ? 360 - transition_angle : transition_angle;
//
// const double transition_angle_pr = transition_angle_log_probability(transition_angle);
// new_value += transition_angle_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;
}
}
}