Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(lanelet2_map_validator): add validator to check whether intersection lanelets have valid turn_direction tags #186

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@
}
]
},
{
"id": "vm-03-02",
"validators": [
{
"name": "mapping.intersection.turn_direction_tagging"
}
]
},
{
"id": "vm-03-08",
"validators": [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# turn_direction_tagging

## Validator name

mapping.intersection.turn_direction_tagging

## Feature

This validator checks whether lanelets inside the `intersection_area` polygon have a `turn_direction` tag and it is set to "straight", "left", or "right".

The validator will output the following issues with the corresponding primitive ID.

| Issue Code | Message | Severity | Primitive | Description | Approach |
| ------------------------------------- | ---------------------------------------------------- | -------- | --------- | ------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Intersection.TurnDirectionTagging-001 | "This lanelet is missing a turn_direction tag." | Error | Lanelet | Lanelets at intersections must have a `turn_direction` tag but this lanelet doesn't have it. | Set a `turn_direction` tag to the lanelet with a value of `straight`, `left` or `right`. This tells the vehicle whether to use the blinkers or not at intersections. |
| Intersection.TurnDirectionTagging-002 | "Invalid turn_direction tag <INVALID_TAG> is found." | Error | Lanelet | The `turn_direction` tag of this lanelet is set to <INVALID_TAG> while it has to be `straight`, `left` or `right`. | Fix the tag value to `straight`, `left` or `right`. |

## Related source codes

- turn_direction_tagging.cpp
- turn_direction_tagging.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2025 Autoware Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef LANELET2_MAP_VALIDATOR__VALIDATORS__INTERSECTION__TURN_DIRECTION_TAGGING_HPP_ // NOLINT
#define LANELET2_MAP_VALIDATOR__VALIDATORS__INTERSECTION__TURN_DIRECTION_TAGGING_HPP_ // NOLINT

#include <lanelet2_validation/Validation.h>
#include <lanelet2_validation/ValidatorFactory.h>

namespace lanelet::autoware::validation
{
class IntersectionTurnDirectionTaggingValidator : public lanelet::validation::MapValidator
{
public:
constexpr static const char * name() { return "mapping.intersection.turn_direction_tagging"; }

lanelet::validation::Issues operator()(const lanelet::LaneletMap & map) override;

private:
lanelet::validation::Issues checkTurnDirectionTagging(const lanelet::LaneletMap & map);
bool lanelet_is_within_intersection_area2d(
const lanelet::BasicPolygon2d & intersection_area2d, const lanelet::ConstLanelet & lanelet);
};
} // namespace lanelet::autoware::validation

// clang-format off
#endif // LANELET2_MAP_VALIDATOR__VALIDATORS__INTERSECTION__TURN_DIRECTION_TAGGING_HPP_ // NOLINT
// clang-format on
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright 2025 Autoware Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "lanelet2_map_validator/validators/intersection/turn_direction_tagging.hpp"

#include "lanelet2_map_validator/utils.hpp"

#include <boost/geometry/geometry.hpp>

#include <lanelet2_core/LaneletMap.h>
#include <lanelet2_core/geometry/Polygon.h>
#include <lanelet2_core/primitives/BoundingBox.h>
#include <lanelet2_core/primitives/Polygon.h>

#include <set>
#include <string>

namespace lanelet::autoware::validation
{
namespace
{
lanelet::validation::RegisterMapValidator<IntersectionTurnDirectionTaggingValidator> reg;
}

lanelet::validation::Issues IntersectionTurnDirectionTaggingValidator::operator()(
const lanelet::LaneletMap & map)
{
lanelet::validation::Issues issues;

lanelet::autoware::validation::appendIssues(issues, checkTurnDirectionTagging(map));

return issues;
}

lanelet::validation::Issues IntersectionTurnDirectionTaggingValidator::checkTurnDirectionTagging(
const lanelet::LaneletMap & map)
{
lanelet::validation::Issues issues;
const std::set<std::string> direction_set = {"left", "straight", "right"};

for (const lanelet::ConstPolygon3d & polygon3d : map.polygonLayer) {
if (
!polygon3d.hasAttribute(lanelet::AttributeName::Type) ||
polygon3d.attribute(lanelet::AttributeName::Type).value() != "intersection_area") {
continue;
}

lanelet::BasicPolygon2d intersection_area2d = lanelet::traits::toBasicPolygon2d(polygon3d);
lanelet::BoundingBox2d bbox2d = lanelet::geometry::boundingBox2d(intersection_area2d);
lanelet::ConstLanelets nearby_lanelets = map.laneletLayer.search(bbox2d);

for (const auto & lane : nearby_lanelets) {
// Skip lanelets that are not roads and not inside the intersection_area
if (
!lane.hasAttribute(lanelet::AttributeName::Subtype) ||
lane.attribute(lanelet::AttributeName::Subtype).value() !=
lanelet::AttributeValueString::Road) {
continue;
}
if (!lanelet_is_within_intersection_area2d(intersection_area2d, lane)) {
continue;
}

if (!lane.hasAttribute("turn_direction")) {
issues.emplace_back(
lanelet::validation::Severity::Error, lanelet::validation::Primitive::Lanelet, lane.id(),
append_issue_code_prefix(
this->name(), 1, "This lanelet is missing a turn_direction tag."));
continue;
}

std::string turn_direction = lane.attribute("turn_direction").value();
if (direction_set.find(turn_direction) == direction_set.end()) {
issues.emplace_back(
lanelet::validation::Severity::Error, lanelet::validation::Primitive::Lanelet, lane.id(),
append_issue_code_prefix(
this->name(), 2, "Invalid turn_direction tag \"" + turn_direction + "\" is found."));
}
}
}

return issues;
}

bool IntersectionTurnDirectionTaggingValidator::lanelet_is_within_intersection_area2d(
const lanelet::BasicPolygon2d & intersection_area2d, const lanelet::ConstLanelet & lanelet)
{
for (const auto & left_point : lanelet.leftBound2d()) {
if (!boost::geometry::covered_by(left_point.basicPoint(), intersection_area2d)) {
return false;
}
}
for (const auto & right_point : lanelet.rightBound2d()) {
if (!boost::geometry::covered_by(right_point.basicPoint(), intersection_area2d)) {
return false;
}
}
return true;
}

} // namespace lanelet::autoware::validation
Loading
Loading