diff --git a/RoadLogicSuite/Internal/MapConversion/mantle_barrier_converter.cpp b/RoadLogicSuite/Internal/MapConversion/mantle_barrier_converter.cpp index d14198dfacb619d41c833b850b8944c5435a6adc..63d0745838fc3358f4f7cf02a019496dd17e9e8f 100644 --- a/RoadLogicSuite/Internal/MapConversion/mantle_barrier_converter.cpp +++ b/RoadLogicSuite/Internal/MapConversion/mantle_barrier_converter.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2023, ANSYS, Inc. + * Copyright (C) 2023-2025, ANSYS, Inc. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -31,12 +31,15 @@ std::unique_ptr<map_api::LaneBoundary> MantleBarrierConverter::Convert(const std const auto height = math_utils::Lerp(barrier.height_start, barrier.height_end, s_percent); const auto width = math_utils::Lerp(barrier.width_start, barrier.width_end, s_percent); const auto position = - converter.ConvertRoadPositionToInertialCoordinates({.road = road_id, .s_offset = s, .t_offset = t}).value(); - points.push_back({ - .position = {position.x, position.y, position.z + z_offset}, - .width = width, - .height = height, - }); + converter.ConvertRoadPositionToInertialCoordinates({.road = road_id, .s_offset = s, .t_offset = t}); + if (position.has_value()) + { + points.push_back({ + .position = {position.value().x, position.value().y, position.value().z + z_offset}, + .width = width, + .height = height, + }); + } } const auto position = converter.ConvertRoadPositionToInertialCoordinates( {.road = road_id, .s_offset = barrier.s_end, .t_offset = barrier.t_end}); @@ -49,11 +52,6 @@ std::unique_ptr<map_api::LaneBoundary> MantleBarrierConverter::Convert(const std .height = barrier.height_end, }); } - else - { - std::cout << "WARNING: Invalid s_end value of road barrier with road id " << road_id - << " is discarded in conversion!" << std::endl; - } if (config.downsampling) { @@ -62,4 +60,4 @@ std::unique_ptr<map_api::LaneBoundary> MantleBarrierConverter::Convert(const std return std::make_unique<map_api::LaneBoundary>(map_api::LaneBoundary{ .id = id_provider.GetNewId(), .boundary_line = points, .type = utils::ConvertRoadBarrierType(barrier.name)}); } -} // namespace road_logic_suite::map_conversion \ No newline at end of file +} // namespace road_logic_suite::map_conversion diff --git a/RoadLogicSuite/Internal/MapConversion/mantle_barrier_converter_test.cpp b/RoadLogicSuite/Internal/MapConversion/mantle_barrier_converter_test.cpp index ca604220c7d1c498ffe7ef6604ec572b6e9bf50e..3138f957e0944a756e443a72575733216fa40f3b 100644 --- a/RoadLogicSuite/Internal/MapConversion/mantle_barrier_converter_test.cpp +++ b/RoadLogicSuite/Internal/MapConversion/mantle_barrier_converter_test.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2023, ANSYS, Inc. + * Copyright (C) 2023-2025, ANSYS, Inc. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -147,8 +147,7 @@ TEST(MantleBarrierConverterTest, GivenBarrierWithGuardRailType_WhenConverting_Th ASSERT_EQ(result->type, map_api::LaneBoundary::Type::kGuardRail); } -TEST(MantleBarrierConverterTest, - GivenBarrierWithInvalidSEnd_WhenConverting_ThenInvalidPointIsDiscardedAndWarningMessageIsPrinted) +TEST(MantleBarrierConverterTest, GivenBarrierWithInvalidSEnd_WhenConverting_ThenInvalidPointIsDiscarded) { // arrange road_logic_suite::map_conversion::MantleIdProvider id_provider{}; @@ -179,11 +178,7 @@ TEST(MantleBarrierConverterTest, .sampling_distance = units::length::meter_t(50.0), }; - testing::internal::CaptureStdout(); - const auto expected_boundary_line_size = 2; - const auto expected_warning_output = - "WARNING: Invalid s_end value of road barrier with road id 0 is discarded in conversion!\n"; // act const auto result = road_logic_suite::map_conversion::MantleBarrierConverter::Convert( @@ -193,9 +188,6 @@ TEST(MantleBarrierConverterTest, ASSERT_EQ(result->boundary_line.size(), expected_boundary_line_size); EXPECT_NEAR(result->boundary_line[0].position.x(), 2, kAbsError); EXPECT_NEAR(result->boundary_line[1].position.x(), 52, kAbsError); - - std::string console_output = testing::internal::GetCapturedStdout(); - EXPECT_EQ(console_output, expected_warning_output); } -} // namespace \ No newline at end of file +} // namespace diff --git a/RoadLogicSuite/Internal/MapConversion/mantle_map_converter.cpp b/RoadLogicSuite/Internal/MapConversion/mantle_map_converter.cpp index cb3b07557d044a3e541513a85f4e83c92882ae6f..241ee49c2af50b58fffe4f824007065029fc79d8 100644 --- a/RoadLogicSuite/Internal/MapConversion/mantle_map_converter.cpp +++ b/RoadLogicSuite/Internal/MapConversion/mantle_map_converter.cpp @@ -317,6 +317,13 @@ MantleMapConverter::CreateLaneBoundariesForLane(const CoordinateConverter& coord for (const auto& road_barrier : lane.road_barriers) { + if (road_barrier.s_end > road.length) + { + std::cout + << "[RoadLogicSuite: Barrier Conversion] WARNING: The s_end of the road barrier is larger than the " + "road length (ID: " + << road.id << "). Points outside the range will be discarded during conversion!" << std::endl; + } physical_boundaries.push_back( MantleBarrierConverter::Convert(road.id, road_barrier, coordinate_converter, config_, id_provider_)); } diff --git a/RoadLogicSuite/Internal/MapConversion/mantle_map_converter_test.cpp b/RoadLogicSuite/Internal/MapConversion/mantle_map_converter_test.cpp index abb636dbcf3f8d41de9ef065dcd4341a3e881b4e..17e7cb7025902812f9127e386e69b59cf51945ae 100644 --- a/RoadLogicSuite/Internal/MapConversion/mantle_map_converter_test.cpp +++ b/RoadLogicSuite/Internal/MapConversion/mantle_map_converter_test.cpp @@ -1100,4 +1100,32 @@ TEST(MantleConverterTest, expected_logical_lane_right_boundary_start_position_y); } +TEST(MantleConverterTest, GivenDataStorageWithBarrierOutOfRange_WhenConverting_ThenOutputWarning) +{ + // The road length is 100 meters. A barrier with s_end at 150 meters exceeds the valid range. + auto data_storage = CreateStraightOneWayRoad(); + const units::length::meter_t s0(0); + const road_logic_suite::RoadBarrier barrier{.s_start = units::length::meter_t(2), + .s_end = units::length::meter_t(150), + .t_start = units::length::meter_t(0), + .t_end = units::length::meter_t(0.04)}; + data_storage.roads["0"].lane_sections.Find(s0)->second.center_lane.road_barriers.push_back(barrier); + + // The warning message is printed twice because the barrier lies on the centerline, which includes both the left and + // right centerlines. + const auto expected_warning_output = + "[RoadLogicSuite: Barrier Conversion] WARNING: The s_end of the road barrier is larger than the road length " + "(ID: 0). Points outside the range will be discarded during conversion!\n[RoadLogicSuite: Barrier Conversion] " + "WARNING: The s_end of the road barrier is larger than the road length (ID: 0). Points outside the range will " + "be discarded during conversion!\n"; + + road_logic_suite::MapConverterConfig converter_config{}; + road_logic_suite::map_conversion::MantleMapConverter converter(converter_config); + + testing::internal::CaptureStdout(); + EXPECT_NO_THROW(converter.Convert(data_storage)); + std::string console_output = testing::internal::GetCapturedStdout(); + EXPECT_EQ(console_output, expected_warning_output); +} + } // namespace diff --git a/RoadLogicSuite/Tests/Data/Maps/simple_road_with_invalid_barrier.xodr b/RoadLogicSuite/Tests/Data/Maps/simple_road_with_invalid_barrier.xodr index 056f259a45c9a74e9bbb7c8ac9bf336602cc6400..6a88359ea7c08e9be60c6e5e9949767c44673c5e 100644 --- a/RoadLogicSuite/Tests/Data/Maps/simple_road_with_invalid_barrier.xodr +++ b/RoadLogicSuite/Tests/Data/Maps/simple_road_with_invalid_barrier.xodr @@ -1,51 +1,63 @@ <?xml version="1.0" encoding="utf-8"?> <OpenDRIVE> - <header name="myroad" revMajor="1" revMinor="5" date="2023-03-09 13:17:27.535810" north="0.0" south="0.0" east="0.0" west="0.0"/> + <header name="myroad" revMajor="1" revMinor="5" date="2023-03-09 13:17:27.535810" north="0.0" + south="0.0" east="0.0" west="0.0" /> <road rule="RHT" id="0" junction="-1" length="1000"> - <link/> + <link /> <planView> <geometry s="0" x="0" y="0" hdg="0" length="1000"> - <line/> + <line /> </geometry> </planView> - <elevationProfile/> - <lateralProfile/> + <elevationProfile /> + <lateralProfile /> <lanes> <laneSection s="0"> <left> <lane id="2" type="driving" level="false"> - <link/> - <width a="3" b="0" c="0" d="0" sOffset="0"/> - <roadMark sOffset="0" type="solid" weight="standard" color="standard" height="0.02" width="0.2"/> + <link /> + <width a="3" b="0" c="0" d="0" sOffset="0" /> + <roadMark sOffset="0" type="solid" weight="standard" color="standard" + height="0.02" width="0.2" /> </lane> <lane id="1" type="driving" level="false"> - <link/> - <width a="3" b="0" c="0" d="0" sOffset="0"/> - <roadMark sOffset="0" type="broken" weight="standard" color="standard" height="0.02" width="0.2"/> + <link /> + <width a="3" b="0" c="0" d="0" sOffset="0" /> + <roadMark sOffset="0" type="broken" weight="standard" color="standard" + height="0.02" width="0.2" /> </lane> </left> <center> <lane id="0" type="none" level="false"> - <roadMark sOffset="0" type="solid" weight="standard" color="standard" height="0.02" width="0.2"/> + <roadMark sOffset="0" type="solid" weight="standard" color="standard" + height="0.02" width="0.2" /> </lane> </center> <right> <lane id="-1" type="driving" level="false"> - <link/> - <width a="3" b="0" c="0" d="0" sOffset="0"/> - <roadMark sOffset="0" type="broken" weight="standard" color="standard" height="0.02" width="0.2"/> + <link /> + <width a="3" b="0" c="0" d="0" sOffset="0" /> + <roadMark sOffset="0" type="broken" weight="standard" color="standard" + height="0.02" width="0.2" /> </lane> <lane id="-2" type="driving" level="false"> - <link/> - <width a="3" b="0" c="0" d="0" sOffset="0"/> - <roadMark sOffset="0" type="solid" weight="standard" color="standard" height="0.02" width="0.2"/> + <link /> + <width a="3" b="0" c="0" d="0" sOffset="0" /> + <roadMark sOffset="0" type="solid" weight="standard" color="standard" + height="0.02" width="0.2" /> </lane> </right> </laneSection> </lanes> <objects> - <object type="barrier" name="guardRail" id="0" s="9.7037600280e-09" t="-8e+00" zOffset="0.5929"> - <repeat s="9.7037600280e-09" length="1000" distance="0.0000000000e+00" tStart="-8e+00" tEnd="-7.90e+00" widthStart="3.5000000000e-01" widthEnd="3.5000000000e-01" heightStart="3.0000000000e-01" heightEnd="3.0000000000e-01" zOffsetStart="5.9285838688e-01" zOffsetEnd="6.2342519426e-01" /> - </objects> + <object type="barrier" name="guardRail" id="0" s="9.7037600280e-09" t="-8e+00" + zOffset="0.5929"> + <repeat s="9.7037600280e-09" length="1000" distance="0.0000000000e+00" + tStart="-8e+00" + tEnd="-7.90e+00" widthStart="3.5000000000e-01" widthEnd="3.5000000000e-01" + heightStart="3.0000000000e-01" heightEnd="3.0000000000e-01" + zOffsetStart="5.9285838688e-01" zOffsetEnd="6.2342519426e-01" /> + </object> + </objects> </road> </OpenDRIVE> diff --git a/RoadLogicSuite/Tests/MantleMapConvertIntegrationTest/road_with_invalid_barrier_integration_test.cpp b/RoadLogicSuite/Tests/MantleMapConvertIntegrationTest/road_with_invalid_barrier_integration_test.cpp index 3e11afa7fc547d33d463840e2c89e21d6d1421b6..99abf3ec56f0c7ccc5f45a49a0344ce184cf5a1a 100644 --- a/RoadLogicSuite/Tests/MantleMapConvertIntegrationTest/road_with_invalid_barrier_integration_test.cpp +++ b/RoadLogicSuite/Tests/MantleMapConvertIntegrationTest/road_with_invalid_barrier_integration_test.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024, ANSYS, Inc. + * Copyright (C) 2024-2025, ANSYS, Inc. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -35,4 +35,16 @@ TEST_F(MapConvertIntegrationTestFixture, GivenMapWithInvalidBarrier_WhenParsingM EXPECT_EQ(lane_minus_2_barrier_last_point_x_position, expected_lane_minus_2_barrier_last_point_x_position); } -} // namespace road_logic_suite::test \ No newline at end of file +TEST_F(MapConvertIntegrationTestFixture, GivenMapWithInvalidBarrier_WhenParsingMap_ThenOutputWarning) +{ + const auto expected_warning_output = + "[RoadLogicSuite: Barrier Conversion] WARNING: The s_end of the road barrier is larger than the road length " + "(ID: 0). Points outside the range will be discarded during conversion!\n"; + + testing::internal::CaptureStdout(); + EXPECT_NO_THROW(GetMap(GetResolvedMapPathInternal("simple_road_with_invalid_barrier.xodr"), 1.0, 0.01, false)); + std::string console_output = testing::internal::GetCapturedStdout(); + EXPECT_EQ(console_output, expected_warning_output); +} + +} // namespace road_logic_suite::test