Skip to content

Commit eb47361

Browse files
authored
feat(lanelet2_extension): add bus_stop_area implementation (#22)
Signed-off-by: Mamoru Sobue <mamoru.sobue@tier4.jp>
1 parent 1d3219a commit eb47361

File tree

5 files changed

+247
-0
lines changed

5 files changed

+247
-0
lines changed

autoware_lanelet2_extension/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ ament_auto_add_library(${PROJECT_NAME}_lib SHARED
1212
lib/landmark.cpp
1313
lib/no_parking_area.cpp
1414
lib/no_stopping_area.cpp
15+
lib/bus_stop_area.cpp
1516
lib/message_conversion.cpp
1617
lib/mgrs_projector.cpp
1718
lib/query.cpp

autoware_lanelet2_extension/include/autoware_lanelet2_extension/regulatory_elements/Forward.hpp

+10
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ class SpeedBump;
3737
class VirtualTrafficLight;
3838
} // namespace format_v1
3939

40+
namespace format_v2
41+
{
42+
class BusStopArea;
43+
} // namespace format_v2
44+
4045
} // namespace lanelet::autoware
4146

4247
namespace lanelet
@@ -54,6 +59,11 @@ using SpeedBumpConstPtr = std::shared_ptr<const lanelet::autoware::SpeedBump>;
5459
using CrosswalkConstPtr = std::shared_ptr<const lanelet::autoware::Crosswalk>;
5560
} // namespace format_v1
5661

62+
namespace format_v2
63+
{
64+
using BusStopAreaConstPtr = std::shared_ptr<const lanelet::autoware::format_v2::BusStopArea>;
65+
} // namespace format_v2
66+
5767
} // namespace lanelet
5868

5969
// NOLINTEND(readability-identifier-naming)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2024 Autoware Foundation. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef AUTOWARE_LANELET2_EXTENSION__REGULATORY_ELEMENTS__BUS_STOP_AREA_HPP_
16+
#define AUTOWARE_LANELET2_EXTENSION__REGULATORY_ELEMENTS__BUS_STOP_AREA_HPP_
17+
18+
// NOLINTBEGIN(readability-identifier-naming)
19+
20+
#include <autoware_lanelet2_extension/regulatory_elements/Forward.hpp>
21+
22+
#include <lanelet2_core/primitives/Lanelet.h>
23+
24+
#include <memory>
25+
26+
namespace lanelet::autoware
27+
{
28+
29+
// TODO(soblin): when updating existing elements from format_v1, prefix this with inline
30+
namespace format_v2
31+
{
32+
class BusStopArea : public lanelet::RegulatoryElement
33+
{
34+
public:
35+
using SharedPtr = std::shared_ptr<BusStopArea>;
36+
static constexpr char RuleName[] = "bus_stop_area";
37+
38+
static SharedPtr make(Id id, const AttributeMap & attributes, const Polygons3d & bus_stop_areas)
39+
{
40+
return SharedPtr{new BusStopArea(id, attributes, bus_stop_areas)};
41+
}
42+
43+
/**
44+
* @brief get the relevant bus stop area
45+
* @return bus stop area
46+
*/
47+
[[nodiscard]] ConstPolygons3d busStopAreas() const;
48+
[[nodiscard]] Polygons3d busStopAreas();
49+
50+
/**
51+
* @brief add a new bus stop are
52+
* @param primitive bus stop area to add
53+
*/
54+
void addBusStopArea(const Polygon3d & primitive);
55+
56+
/**
57+
* @brief remove a bus stop area
58+
* @param primitive the primitive
59+
* @return true if the bus stop area existed and was removed
60+
*/
61+
bool removeBusStopArea(const Polygon3d & primitive);
62+
63+
private:
64+
BusStopArea(Id id, const AttributeMap & attributes, const Polygons3d & bus_stop_area);
65+
66+
// the following lines are required so that lanelet2 can create this object
67+
// when loading a map with this regulatory element
68+
friend class RegisterRegulatoryElement<BusStopArea>;
69+
explicit BusStopArea(const lanelet::RegulatoryElementDataPtr & data);
70+
};
71+
} // namespace format_v2
72+
73+
} // namespace lanelet::autoware
74+
75+
// NOLINTEND(readability-identifier-naming)
76+
77+
#endif // AUTOWARE_LANELET2_EXTENSION__REGULATORY_ELEMENTS__BUS_STOP_AREA_HPP_
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// Copyright 2024 Autoware Foundation. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// NOLINTBEGIN(readability-identifier-naming)
16+
17+
#include "autoware_lanelet2_extension/regulatory_elements/bus_stop_area.hpp"
18+
19+
#include <boost/variant.hpp>
20+
21+
#include <lanelet2_core/primitives/RegulatoryElement.h>
22+
23+
#include <algorithm>
24+
#include <memory>
25+
#include <utility>
26+
#include <vector>
27+
28+
namespace lanelet::autoware
29+
{
30+
namespace
31+
{
32+
template <typename T>
33+
bool findAndErase(const T & primitive, RuleParameters * member)
34+
{
35+
if (member == nullptr) {
36+
return false;
37+
}
38+
auto it = std::find(member->begin(), member->end(), RuleParameter(primitive));
39+
if (it == member->end()) {
40+
return false;
41+
}
42+
member->erase(it);
43+
return true;
44+
}
45+
46+
template <typename T>
47+
Optional<T> tryGetFront(const std::vector<T> & vec)
48+
{
49+
if (vec.empty()) {
50+
return {};
51+
}
52+
return vec.front();
53+
}
54+
55+
template <typename T>
56+
RuleParameters toRuleParameters(const std::vector<T> & primitives)
57+
{
58+
auto cast_func = [](const auto & elem) { return static_cast<RuleParameter>(elem); };
59+
return utils::transform(primitives, cast_func);
60+
}
61+
62+
Polygons3d getPoly(const RuleParameterMap & paramsMap, RoleName role)
63+
{
64+
auto params = paramsMap.find(role);
65+
if (params == paramsMap.end()) {
66+
return {};
67+
}
68+
69+
Polygons3d result;
70+
for (auto & param : params->second) {
71+
auto p = boost::get<Polygon3d>(&param);
72+
if (p != nullptr) {
73+
result.push_back(*p);
74+
}
75+
}
76+
return result;
77+
}
78+
79+
ConstPolygons3d getConstPoly(const RuleParameterMap & params, RoleName role)
80+
{
81+
auto cast_func = [](auto & poly) { return static_cast<ConstPolygon3d>(poly); };
82+
return utils::transform(getPoly(params, role), cast_func);
83+
}
84+
85+
RegulatoryElementDataPtr constructBusStopAreaData(
86+
Id id, const AttributeMap & attributes, const Polygons3d & bus_stop_areas)
87+
{
88+
RuleParameterMap rpm = {{RoleNameString::Refers, toRuleParameters(bus_stop_areas)}};
89+
90+
auto data = std::make_shared<RegulatoryElementData>(id, std::move(rpm), attributes);
91+
data->attributes[AttributeName::Type] = AttributeValueString::RegulatoryElement;
92+
data->attributes[AttributeName::Subtype] = "bus_stop_area";
93+
return data;
94+
}
95+
} // namespace
96+
97+
// TODO(soblin): remove this when format_v2 has been released
98+
namespace format_v2
99+
{
100+
BusStopArea::BusStopArea(const RegulatoryElementDataPtr & data) : RegulatoryElement(data)
101+
{
102+
if (getConstPoly(data->parameters, RoleName::Refers).empty()) {
103+
throw InvalidInputError("no bus stop area defined!");
104+
}
105+
}
106+
107+
BusStopArea::BusStopArea(Id id, const AttributeMap & attributes, const Polygons3d & bus_stop_areas)
108+
: BusStopArea(constructBusStopAreaData(id, attributes, bus_stop_areas))
109+
{
110+
}
111+
112+
ConstPolygons3d BusStopArea::busStopAreas() const
113+
{
114+
return getConstPoly(parameters(), RoleName::Refers);
115+
}
116+
Polygons3d BusStopArea::busStopAreas()
117+
{
118+
return getPoly(parameters(), RoleName::Refers);
119+
}
120+
121+
void BusStopArea::addBusStopArea(const Polygon3d & primitive)
122+
{
123+
parameters()["bus_stop_area"].emplace_back(primitive);
124+
}
125+
126+
bool BusStopArea::removeBusStopArea(const Polygon3d & primitive)
127+
{
128+
return findAndErase(primitive, &parameters().find("bus_stop_area")->second);
129+
}
130+
131+
RegisterRegulatoryElement<BusStopArea> regBusStopArea;
132+
} // namespace format_v2
133+
134+
} // namespace lanelet::autoware
135+
136+
// NOLINTEND(readability-identifier-naming)

autoware_lanelet2_extension/test/src/test_regulatory_elements.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
// NOLINTBEGIN(readability-identifier-naming)
1616

1717
#include "autoware_lanelet2_extension/regulatory_elements/autoware_traffic_light.hpp"
18+
#include "autoware_lanelet2_extension/regulatory_elements/bus_stop_area.hpp"
1819

1920
#include <boost/optional/optional_io.hpp>
2021

@@ -29,6 +30,7 @@ using lanelet::LineString3d;
2930
using lanelet::LineStringOrPolygon3d;
3031
using lanelet::Point3d;
3132
using lanelet::Points3d;
33+
using lanelet::Polygon3d;
3234
using lanelet::utils::getId;
3335

3436
namespace
@@ -138,6 +140,27 @@ TEST(TestSuite, TrafficLightWorksAsExpected) // NOLINT for gtest
138140
EXPECT_EQ(1ul, tl->lightBulbs().size());
139141
}
140142

143+
TEST(TestSuite, BusStopAreInstantiation) // NOLINT for gtest
144+
{
145+
/*
146+
p4 <---- p3
147+
| ^
148+
| |
149+
V |
150+
p1 ----> p2
151+
*/
152+
const Point3d p1{getId(), 0, 0, 0};
153+
const Point3d p2{getId(), 3, 0, 0};
154+
const Point3d p3{getId(), 3, 3, 0};
155+
const Point3d p4{getId(), 0, 3, 0};
156+
const Polygon3d polygon{LineString3d{getId(), Points3d{p1, p2, p3, p4}}};
157+
auto bus_stop_area_reg_elem = lanelet::autoware::format_v2::BusStopArea::make(
158+
getId(), lanelet::AttributeMap(), convertToVector(polygon));
159+
EXPECT_EQ(bus_stop_area_reg_elem->busStopAreas().size(), 1);
160+
EXPECT_NO_THROW(bus_stop_area_reg_elem->busStopAreas().at(0));
161+
const auto bus_stop_area = bus_stop_area_reg_elem->busStopAreas().at(0);
162+
}
163+
141164
int main(int argc, char ** argv)
142165
{
143166
testing::InitGoogleTest(&argc, argv);

0 commit comments

Comments
 (0)