Skip to content

Conversation

@enishettyrahul
Copy link

Add vignette as edge attribute.

#fixes #5496

What issue is this PR targeting? If there is no issue that addresses the problem, please open a corresponding issue and link it here.
This to differentiate between toll and vignette costing.

Tasklist

  • Add tests
  • Add #fixes with the issue number that this PR addresses
  • Update the docs with any new request parameters or changes to behavior described
  • Update the changelog
  • If you made changes to the lua files, update the taginfo too
  • If you made changes to a translation file, update transifex too

Requirements / Relations

Rahul Krishna Enishetty [email protected], Mercedes-Benz Tech Innovation GmbH
Provider Information

Licensed under MIT

@enishettyrahul enishettyrahul mentioned this pull request Nov 18, 2025
6 tasks
@enishettyrahul
Copy link
Author

This PR is created to restriction the vignette access, if the user prefers to avoid it.

The Information to be passed via isochrone as an Array.

We can do a soft avoid by providing only a single country for avoidance.
For ex: ["CH"]

We can also do Hard avoid by Providing ["ALL"] as a parameter to exclude_country_vignettes as vehicle costing.

uint64_t modes_ : 12; // Mode(s) this access restriction applies to
uint64_t except_destination_ : 1; // Whether local traffic is exempted from this restriction
uint64_t spare_ : 23;
uint64_t countryIsoCode_ : 16; // Country ISO Code as a numeric value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm torn about whether this is actually necessary at all to store this information. When expanding, we should probably have the begin node's admin index, we'd just need to pass it to DynamicCost::Allowed.

If we decide to store it on the restriction though, it should go into value_ because it's specific to this type of restriction. You can also limit it to 16 bits there to reserve more bits on the value to get more specific (regional, or store provider info in countries where highways are privately owned etc.).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have been interested in the possibility of treating countries in cost profiles for quite some time, but unfortunately the PR at that time got a little out of date 4289. As noted in the issue discussion on this PR, we now have more know how and want to revisit this as soon as we have more capacity available.

We also considered whether to store the country in the value_ or in a new attribute. The reason we decided on a new attribute was that this would allow us to store more complex data in our value_, such as the cost of the vignette or other country-specific information we may want in the future (not only for vignettes), while maintaining good readability in the code. What do you think, should we still move the country to the value_ or keep the countryIsoCode_?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chrstnbwnkl Did you already have the change to check the PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I want to hear other maintainers' thoughts on this as well, this is a non-trivial design decision and I would like to make a decision that will not render us deadlocked in the future.

Maybe you could explain in a little more detail how you are planning to use the country information for types other than vignette? That might help in guiding that decision.

Copy link
Author

@enishettyrahul enishettyrahul Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @chrstnbwnkl

I have changed the code now to use the Value varible in AccessRestriction instead of new CountryIso Variable.

Could you please review the changes for the feature.?

Some changes like in test_elevation.cc are added after calling ./scripts/clang-tidy-only-diff.sh

break;
}
}
return doNotAvoidVignette;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't return early: this will cause timed access restrictions to not be evaluated if there was also a vignette flag but it didn't match the countries provided by the user (crazy edge case but still). Just return false if it matches, otherwise continue with the remaining restrictions.

Also, can you stick to snake_casing here and make it do_not_avoid_vignette?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Now when the country it found out then return is called.

Copy link
Member

@chrstnbwnkl chrstnbwnkl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks mostly good! Just a few nitpicks

break;
case AccessType::kVignette:
writer("value", countryIsoCode());
writer("country_iso", countryIsoCode());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

osm_data = PBFGraphParser::ParseWays(config.get_child("mjolnir"), input_files, ways_bin,
way_nodes_bin, access_bin);
osm_data.pbf_checksum_ = get_pbf_checksum(input_files, tile_dir);
osm_data.pbf_checksum_ = get_pbf_checksum(input_files);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like a merging error

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they appeared after the call of ./scripts/clang-tidy-only-diff.sh

// parse from JSON array and set on costing options protobuf.
auto exclude_vignettes_node = rapidjson::get_child_optional(json, "/exclude_country_vignettes");
auto country_vignettes = co->mutable_exclude_country_vignettes();
country_vignettes->Clear();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: is it necessary to clean this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is best to clear, so that only new request is considered always.


struct TestableSample : public valhalla::skadi::sample {
static uint16_t get_tile_index(const PointLL& coord) {
static uint16_t get_tile_index(const valhalla::midgard::PointLL& coord) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we replace all of this with a using namespace ...?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they appeared after the call of ./scripts/clang-tidy-only-diff.sh

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#5488 (comment)
test/elevation_builder.cc does not compile because it gets left out during refactorings because it is not enabled.
Probably caused by #5568, makes sense to just add the using statement in this file.

std::string iso;
iso.push_back(static_cast<char>((countryIsoCode >> 8) & 0xFF));
iso.push_back(static_cast<char>(countryIsoCode & 0xFF));
LOG_INFO("Country ISO: " + iso + " Value in Int: " + std::to_string(countryIsoCode));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove log statement

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

if (restriction.type() == baldr::AccessType::kVignette) {
auto countryIso = ConvertIntToISO(restriction.countryIsoCode());
for (auto v : exclude_country_vignettes_) {
if ((v == countryIso) || (v == "ALL")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

capitalized looks a bit weird here, maybe call it "all" and make it constexpr at the top of the file?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed with use of small or capital letters now.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for mentioning the check for Capitalization.

@enishettyrahul enishettyrahul force-pushed the vignette_as_access_restriction branch 2 times, most recently from 5eedb5a to 5f5e9ec Compare December 9, 2025 15:39
Copy link
Member

@chrstnbwnkl chrstnbwnkl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few things:

  • code style: please don't use camel or pascal case, use snake case, except for compile time constants, which should be kMyConstanst
  • looks like you reverted the update to the date third party lib

r->second.value(), r->second.except_destination());
auto value = r->second.value();
if (r->second.type() == AccessType::kVignette) {
value = CountryISOCodeToValue(boost::to_upper_copy(countryIso));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to_upper_copy is not necessary here because we get that string from the tile's admin data

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

const Admin& admin = graphtile.admins_builder(admin_index);
countryIso = admin.country_iso();
} catch (...) {
LOG_ERROR("admin_index size is greater than admin count in Graphbuilder");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this try catch seems superfluous

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

// Special check for vignette restrictions
if (restriction.type() == baldr::AccessType::kVignette) {
auto countryIso = ConvertIntToISO(restriction.value());
std::transform(countryIso.begin(), countryIso.end(), countryIso.begin(), ::toupper);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, transforming to upper should not be necessary, right?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

bool is_hgv_{false};

// List of country vignettes to exclude
std::vector<std::string> exclude_country_vignettes_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should probably be a std::unordered_set so look ups are fast

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

auto countryIso = ConvertIntToISO(restriction.value());
std::transform(countryIso.begin(), countryIso.end(), countryIso.begin(), ::toupper);
for (auto v : exclude_country_vignettes_) {
if ((v == countryIso) || (v == HardAvoidVignette)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(v == HardAvoidVignette) should be checked before pulling out the iso string

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

@enishettyrahul enishettyrahul force-pushed the vignette_as_access_restriction branch from ea619ca to 4c9a00b Compare December 12, 2025 12:15
Signed-off-by: Rahul Krishna Enishetty <[email protected]>
@enishettyrahul enishettyrahul force-pushed the vignette_as_access_restriction branch from 4c9a00b to 950a37f Compare December 12, 2025 12:29
@enishettyrahul
Copy link
Author

Hallo @chrstnbwnkl ,

Could you please review this ?
Please set all the comments to resolved that you feel are completed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Differentiate between "toll" and "vignette" attributes

5 participants