If traffic CSV has an empty 4th column, preserve the weight on an edge while updating the duration.
This commit is contained in:
parent
7702ebde61
commit
b17f40862c
@ -379,3 +379,36 @@ Feature: Weight tests
|
|||||||
| a,d | abcd,abcd | 59.9m | 6.996,0 | 7s,0s |
|
| a,d | abcd,abcd | 59.9m | 6.996,0 | 7s,0s |
|
||||||
| a,e | abcd,ce,ce | 60.1m | 6.005,2.002,0 | 6s,2s,0s |
|
| a,e | abcd,ce,ce | 60.1m | 6.005,2.002,0 | 6s,2s,0s |
|
||||||
| d,e | abcd,ce,ce | 39.9m | 1.991,2.002,0 | 2s,2s,0s |
|
| d,e | abcd,ce,ce | 39.9m | 1.991,2.002,0 | 2s,2s,0s |
|
||||||
|
|
||||||
|
@traffic @speed
|
||||||
|
Scenario: Updating speeds without affecting weights.
|
||||||
|
Given the profile file "testbot" initialized with
|
||||||
|
"""
|
||||||
|
profile.properties.weight_precision = 3
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
a-----------b
|
||||||
|
\ /
|
||||||
|
c----d
|
||||||
|
"""
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed |
|
||||||
|
| ab | living_street | 5 |
|
||||||
|
| acdb | motorway | 100 |
|
||||||
|
|
||||||
|
# Note the comma on the last column - this indicates 'keep existing weight value'
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
1,2,100,
|
||||||
|
1,3,5,
|
||||||
|
3,4,5,
|
||||||
|
4,2,5,
|
||||||
|
"""
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | distance | weights | times |
|
||||||
|
| a,b | acdb,acdb | 78.3m | 11.744,0 | 56.4s,0s |
|
||||||
|
@ -49,9 +49,9 @@ struct Segment final
|
|||||||
|
|
||||||
struct SpeedSource final
|
struct SpeedSource final
|
||||||
{
|
{
|
||||||
SpeedSource() : speed(0), rate(std::numeric_limits<double>::quiet_NaN()) {}
|
SpeedSource() : speed(0), rate() {}
|
||||||
unsigned speed;
|
unsigned speed;
|
||||||
double rate;
|
boost::optional<double> rate;
|
||||||
std::uint8_t source;
|
std::uint8_t source;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,7 +34,9 @@ namespace csv
|
|||||||
SegmentLookupTable readSegmentValues(const std::vector<std::string> &paths)
|
SegmentLookupTable readSegmentValues(const std::vector<std::string> &paths)
|
||||||
{
|
{
|
||||||
CSVFilesParser<Segment, SpeedSource> parser(
|
CSVFilesParser<Segment, SpeedSource> parser(
|
||||||
1, qi::ulong_long >> ',' >> qi::ulong_long, qi::uint_ >> -(',' >> qi::double_));
|
1,
|
||||||
|
qi::ulong_long >> ',' >> qi::ulong_long,
|
||||||
|
qi::uint_ >> -(',' >> (qi::double_ | qi::attr(std::numeric_limits<double>::quiet_NaN()))));
|
||||||
|
|
||||||
// Check consistency of keys in the result lookup table
|
// Check consistency of keys in the result lookup table
|
||||||
auto result = parser(paths);
|
auto result = parser(paths);
|
||||||
|
@ -162,13 +162,28 @@ updateSegmentData(const UpdaterConfig &config,
|
|||||||
// closure to convert SpeedSource value to weight and count fallbacks to durations
|
// closure to convert SpeedSource value to weight and count fallbacks to durations
|
||||||
std::atomic<std::uint32_t> fallbacks_to_duration{0};
|
std::atomic<std::uint32_t> fallbacks_to_duration{0};
|
||||||
auto convertToWeight = [&profile_properties, &fallbacks_to_duration](
|
auto convertToWeight = [&profile_properties, &fallbacks_to_duration](
|
||||||
const SpeedSource &value, double distance_in_meters) {
|
const SegmentWeight &existing_weight, const SpeedSource &value, double distance_in_meters) {
|
||||||
double rate = value.rate;
|
|
||||||
if (!std::isfinite(rate))
|
double rate = std::numeric_limits<double>::quiet_NaN();
|
||||||
{ // use speed value in meters per second as the rate
|
|
||||||
|
// if value.rate is not set, we fall back to duration
|
||||||
|
// this happens when there is no 4th column in the input CSV
|
||||||
|
// if value.rate is set but NaN, we keep the existing weight
|
||||||
|
// this happens when there is an empty 4th column in the input CSV
|
||||||
|
// otherwise, we use the value as the new rate
|
||||||
|
if (!value.rate)
|
||||||
|
{
|
||||||
++fallbacks_to_duration;
|
++fallbacks_to_duration;
|
||||||
rate = value.speed / 3.6;
|
rate = value.speed / 3.6;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rate = *value.rate;
|
||||||
|
if (!std::isfinite(rate))
|
||||||
|
{
|
||||||
|
return existing_weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (rate <= 0.)
|
if (rate <= 0.)
|
||||||
return INVALID_SEGMENT_WEIGHT;
|
return INVALID_SEGMENT_WEIGHT;
|
||||||
@ -231,7 +246,8 @@ updateSegmentData(const UpdaterConfig &config,
|
|||||||
{
|
{
|
||||||
auto segment_length = segment_lengths[segment_offset];
|
auto segment_length = segment_lengths[segment_offset];
|
||||||
auto new_duration = convertToDuration(value->speed, segment_length);
|
auto new_duration = convertToDuration(value->speed, segment_length);
|
||||||
auto new_weight = convertToWeight(*value, segment_length);
|
auto new_weight =
|
||||||
|
convertToWeight(fwd_weights_range[segment_offset], *value, segment_length);
|
||||||
fwd_was_updated = true;
|
fwd_was_updated = true;
|
||||||
|
|
||||||
fwd_weights_range[segment_offset] = new_weight;
|
fwd_weights_range[segment_offset] = new_weight;
|
||||||
@ -270,7 +286,8 @@ updateSegmentData(const UpdaterConfig &config,
|
|||||||
{
|
{
|
||||||
auto segment_length = segment_lengths[segment_offset];
|
auto segment_length = segment_lengths[segment_offset];
|
||||||
auto new_duration = convertToDuration(value->speed, segment_length);
|
auto new_duration = convertToDuration(value->speed, segment_length);
|
||||||
auto new_weight = convertToWeight(*value, segment_length);
|
auto new_weight =
|
||||||
|
convertToWeight(rev_weights_range[segment_offset], *value, segment_length);
|
||||||
rev_was_updated = true;
|
rev_was_updated = true;
|
||||||
|
|
||||||
rev_weights_range[segment_offset] = new_weight;
|
rev_weights_range[segment_offset] = new_weight;
|
||||||
|
Loading…
Reference in New Issue
Block a user