Skip to content

Commit 6e6e601

Browse files
authored
feat(static_centerline_optimizer): static centerline optimizer with GUI (#6717)
feat: add GUI for static centerline optimizer Signed-off-by: Takayuki Murooka <takayuki5168@gmail.com>
1 parent 8f67bc9 commit 6e6e601

File tree

5 files changed

+285
-1
lines changed

5 files changed

+285
-1
lines changed

planning/static_centerline_optimizer/include/static_centerline_optimizer/static_centerline_optimizer_node.hpp

+18
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#include "static_centerline_optimizer/type_alias.hpp"
2323
#include "vehicle_info_util/vehicle_info_util.hpp"
2424

25+
#include "std_msgs/msg/bool.hpp"
26+
#include "std_msgs/msg/int32.hpp"
27+
2528
#include <memory>
2629
#include <string>
2730
#include <vector>
@@ -67,13 +70,28 @@ class StaticCenterlineOptimizerNode : public rclcpp::Node
6770
HADMapBin::ConstSharedPtr map_bin_ptr_{nullptr};
6871
std::shared_ptr<RouteHandler> route_handler_ptr_{nullptr};
6972

73+
int traj_start_index_{0};
74+
int traj_end_index_{0};
75+
struct MetaDataToSaveMap
76+
{
77+
std::vector<TrajectoryPoint> optimized_traj_points{};
78+
std::vector<lanelet::Id> route_lane_ids{};
79+
};
80+
std::optional<MetaDataToSaveMap> meta_data_to_save_map_{std::nullopt};
81+
7082
// publisher
7183
rclcpp::Publisher<HADMapBin>::SharedPtr pub_map_bin_{nullptr};
7284
rclcpp::Publisher<PathWithLaneId>::SharedPtr pub_raw_path_with_lane_id_{nullptr};
7385
rclcpp::Publisher<Path>::SharedPtr pub_raw_path_{nullptr};
7486
rclcpp::Publisher<MarkerArray>::SharedPtr pub_debug_unsafe_footprints_{nullptr};
87+
rclcpp::Publisher<Trajectory>::SharedPtr pub_whole_optimized_centerline_{nullptr};
7588
rclcpp::Publisher<Trajectory>::SharedPtr pub_optimized_centerline_{nullptr};
7689

90+
// subscriber
91+
rclcpp::Subscription<std_msgs::msg::Int32>::SharedPtr sub_traj_start_index_;
92+
rclcpp::Subscription<std_msgs::msg::Int32>::SharedPtr sub_traj_end_index_;
93+
rclcpp::Subscription<std_msgs::msg::Bool>::SharedPtr sub_save_map_;
94+
7795
// service
7896
rclcpp::Service<LoadMap>::SharedPtr srv_load_map_;
7997
rclcpp::Service<PlanRoute>::SharedPtr srv_plan_route_;

planning/static_centerline_optimizer/launch/static_centerline_optimizer.launch.xml

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
<node pkg="static_centerline_optimizer" exec="main" name="static_centerline_optimizer">
5757
<remap from="lanelet2_map_topic" to="$(var lanelet2_map_topic)"/>
5858
<remap from="input_centerline" to="~/input_centerline"/>
59+
<remap from="output_whole_centerline" to="~/output_whole_centerline"/>
5960
<remap from="output_centerline" to="~/output_centerline"/>
6061
<remap from="debug/raw_centerline" to="~/debug/raw_centerline"/>
6162
<remap from="debug/unsafe_footprints" to="~/debug/unsafe_footprints"/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
#!/bin/env python3
2+
3+
# Copyright 2024 TIER IV, Inc.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
18+
import sys
19+
import time
20+
21+
from PyQt5 import QtCore
22+
from PyQt5.QtWidgets import QApplication
23+
from PyQt5.QtWidgets import QGridLayout
24+
from PyQt5.QtWidgets import QMainWindow
25+
from PyQt5.QtWidgets import QPushButton
26+
from PyQt5.QtWidgets import QSizePolicy
27+
from PyQt5.QtWidgets import QSlider
28+
from PyQt5.QtWidgets import QWidget
29+
from autoware_auto_planning_msgs.msg import Trajectory
30+
import rclpy
31+
from rclpy.node import Node
32+
from rclpy.qos import QoSDurabilityPolicy
33+
from rclpy.qos import QoSProfile
34+
from std_msgs.msg import Bool
35+
from std_msgs.msg import Int32
36+
37+
38+
class CenterlineUpdaterWidget(QMainWindow):
39+
def __init__(self):
40+
super(self.__class__, self).__init__()
41+
self.setupUI()
42+
43+
def setupUI(self):
44+
self.setObjectName("MainWindow")
45+
self.resize(480, 120)
46+
self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
47+
48+
central_widget = QWidget(self)
49+
central_widget.setObjectName("central_widget")
50+
51+
self.grid_layout = QGridLayout(central_widget)
52+
self.grid_layout.setContentsMargins(10, 10, 10, 10)
53+
self.grid_layout.setObjectName("grid_layout")
54+
55+
# button to update the trajectory's start and end index
56+
self.update_button = QPushButton("update slider")
57+
self.update_button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
58+
self.update_button.clicked.connect(self.onUpdateButton)
59+
60+
# button to reset the trajectory's start and end index
61+
self.reset_button = QPushButton("reset")
62+
self.reset_button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
63+
self.reset_button.clicked.connect(self.onResetButton)
64+
65+
# button to save map
66+
self.save_map_button = QPushButton("save map")
67+
self.save_map_button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
68+
69+
# slide of the trajectory's start and end index
70+
self.traj_start_index_slider = QSlider(QtCore.Qt.Horizontal)
71+
self.traj_end_index_slider = QSlider(QtCore.Qt.Horizontal)
72+
self.min_traj_start_index = 0
73+
self.max_traj_end_index = None
74+
75+
# set layout
76+
self.grid_layout.addWidget(self.update_button, 1, 0, 1, -1)
77+
self.grid_layout.addWidget(self.reset_button, 2, 0, 1, -1)
78+
self.grid_layout.addWidget(self.save_map_button, 3, 0, 1, -1)
79+
self.grid_layout.addWidget(self.traj_start_index_slider, 4, 0, 1, -1)
80+
self.grid_layout.addWidget(self.traj_end_index_slider, 5, 0, 1, -1)
81+
self.setCentralWidget(central_widget)
82+
83+
def initWithEndIndex(self, max_traj_end_index):
84+
self.max_traj_end_index = max_traj_end_index
85+
86+
# initialize slider
87+
self.displayed_min_traj_start_index = self.min_traj_start_index
88+
self.displayed_max_traj_end_index = self.max_traj_end_index
89+
self.initializeSlider()
90+
91+
def initializeSlider(self, move_value_to_end=True):
92+
self.traj_start_index_slider.setMinimum(0)
93+
self.traj_end_index_slider.setMinimum(0)
94+
self.traj_start_index_slider.setMaximum(
95+
self.displayed_max_traj_end_index - self.displayed_min_traj_start_index
96+
)
97+
self.traj_end_index_slider.setMaximum(
98+
self.displayed_max_traj_end_index - self.displayed_min_traj_start_index
99+
)
100+
101+
if move_value_to_end:
102+
self.traj_start_index_slider.setValue(0)
103+
self.traj_end_index_slider.setValue(self.traj_end_index_slider.maximum())
104+
105+
def onResetButton(self, event):
106+
current_traj_start_index = self.displayed_min_traj_start_index
107+
current_traj_end_index = self.displayed_max_traj_end_index
108+
109+
self.displayed_min_traj_start_index = self.min_traj_start_index
110+
self.displayed_max_traj_end_index = self.max_traj_end_index
111+
112+
self.initializeSlider(False)
113+
self.traj_start_index_slider.setValue(current_traj_start_index)
114+
if (
115+
current_traj_start_index == self.min_traj_start_index
116+
and current_traj_end_index == self.max_traj_end_index
117+
):
118+
self.traj_end_index_slider.setValue(self.displayed_max_traj_end_index)
119+
else:
120+
self.traj_end_index_slider.setValue(
121+
current_traj_start_index + self.traj_end_index_slider.value()
122+
)
123+
124+
def onUpdateButton(self, event):
125+
current_traj_start_index = self.getCurrentStartIndex()
126+
current_traj_end_index = self.getCurrentEndIndex()
127+
128+
self.displayed_min_traj_start_index = current_traj_start_index
129+
self.displayed_max_traj_end_index = current_traj_end_index
130+
131+
self.initializeSlider()
132+
133+
def getCurrentStartIndex(self):
134+
return self.displayed_min_traj_start_index + self.traj_start_index_slider.value()
135+
136+
def getCurrentEndIndex(self):
137+
return self.displayed_min_traj_start_index + self.traj_end_index_slider.value()
138+
139+
140+
class CenterlineUpdaterHelper(Node):
141+
def __init__(self):
142+
super().__init__("centerline_updater_helper")
143+
# Qt
144+
self.widget = CenterlineUpdaterWidget()
145+
self.widget.show()
146+
self.widget.save_map_button.clicked.connect(self.onSaveMapButtonPushed)
147+
self.widget.traj_start_index_slider.valueChanged.connect(self.onStartIndexChanged)
148+
self.widget.traj_end_index_slider.valueChanged.connect(self.onEndIndexChanged)
149+
150+
# ROS
151+
self.pub_save_map = self.create_publisher(Bool, "~/save_map", 1)
152+
self.pub_traj_start_index = self.create_publisher(Int32, "~/traj_start_index", 1)
153+
self.pub_traj_end_index = self.create_publisher(Int32, "~/traj_end_index", 1)
154+
155+
transient_local_qos = QoSProfile(depth=1, durability=QoSDurabilityPolicy.TRANSIENT_LOCAL)
156+
self.sub_whole_centerline = self.create_subscription(
157+
Trajectory,
158+
"/static_centerline_optimizer/output_whole_centerline",
159+
self.onWholeCenterline,
160+
transient_local_qos,
161+
)
162+
163+
while self.widget.max_traj_end_index is None:
164+
rclpy.spin_once(self, timeout_sec=0.01)
165+
time.sleep(0.1)
166+
167+
def onWholeCenterline(self, whole_centerline):
168+
self.widget.initWithEndIndex(len(whole_centerline.points) - 1)
169+
170+
def onSaveMapButtonPushed(self, event):
171+
msg = Bool()
172+
msg.data = True
173+
self.pub_save_map.publish(msg)
174+
175+
def onStartIndexChanged(self, event):
176+
msg = Int32()
177+
msg.data = self.widget.getCurrentStartIndex()
178+
self.pub_traj_start_index.publish(msg)
179+
180+
def onEndIndexChanged(self, event):
181+
msg = Int32()
182+
msg.data = self.widget.getCurrentEndIndex()
183+
self.pub_traj_end_index.publish(msg)
184+
185+
186+
def main(args=None):
187+
app = QApplication(sys.argv)
188+
189+
rclpy.init(args=args)
190+
node = CenterlineUpdaterHelper()
191+
192+
while True:
193+
app.processEvents()
194+
rclpy.spin_once(node, timeout_sec=0.01)
195+
196+
197+
if __name__ == "__main__":
198+
main()
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
#!/bin/bash
22

3-
ros2 launch static_centerline_optimizer static_centerline_optimizer.launch.xml run_background:=false lanelet2_input_file_path:="$HOME/AutonomousDrivingScenarios/map/sample_map/lanelet2_map.osm" start_lanelet_id:=125 end_lanelet_id:=132 vehicle_model:=lexus
3+
ros2 launch static_centerline_optimizer static_centerline_optimizer.launch.xml run_background:=false lanelet2_input_file_path:="$HOME/autoware_map/sample_map/lanelet2_map.osm" start_lanelet_id:=125 end_lanelet_id:=132 vehicle_model:=lexus

planning/static_centerline_optimizer/src/static_centerline_optimizer_node.cpp

+67
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,14 @@
2626
#include "static_centerline_optimizer/type_alias.hpp"
2727
#include "static_centerline_optimizer/utils.hpp"
2828
#include "tier4_autoware_utils/geometry/geometry.hpp"
29+
#include "tier4_autoware_utils/ros/parameter.hpp"
2930

3031
#include <mission_planner/mission_planner_plugin.hpp>
3132
#include <pluginlib/class_loader.hpp>
3233
#include <tier4_autoware_utils/ros/marker_helper.hpp>
3334

35+
#include "std_msgs/msg/bool.hpp"
36+
#include "std_msgs/msg/int32.hpp"
3437
#include <tier4_map_msgs/msg/map_projector_info.hpp>
3538

3639
#include <boost/geometry/algorithms/correct.hpp>
@@ -41,6 +44,7 @@
4144
#include <lanelet2_io/Io.h>
4245
#include <lanelet2_projection/UTM.h>
4346

47+
#include <chrono>
4448
#include <fstream>
4549
#include <limits>
4650
#include <memory>
@@ -202,6 +206,14 @@ std::vector<lanelet::Id> check_lanelet_connection(
202206

203207
return unconnected_lane_ids;
204208
}
209+
210+
std_msgs::msg::Header createHeader(const rclcpp::Time & now)
211+
{
212+
std_msgs::msg::Header header;
213+
header.frame_id = "map";
214+
header.stamp = now;
215+
return header;
216+
}
205217
} // namespace
206218

207219
StaticCenterlineOptimizerNode::StaticCenterlineOptimizerNode(
@@ -213,13 +225,62 @@ StaticCenterlineOptimizerNode::StaticCenterlineOptimizerNode(
213225
pub_raw_path_with_lane_id_ =
214226
create_publisher<PathWithLaneId>("input_centerline", create_transient_local_qos());
215227
pub_raw_path_ = create_publisher<Path>("debug/raw_centerline", create_transient_local_qos());
228+
pub_whole_optimized_centerline_ =
229+
create_publisher<Trajectory>("output_whole_centerline", create_transient_local_qos());
216230
pub_optimized_centerline_ =
217231
create_publisher<Trajectory>("output_centerline", create_transient_local_qos());
218232

219233
// debug publishers
220234
pub_debug_unsafe_footprints_ =
221235
create_publisher<MarkerArray>("debug/unsafe_footprints", create_transient_local_qos());
222236

237+
// subscribers
238+
sub_traj_start_index_ = create_subscription<std_msgs::msg::Int32>(
239+
"/centerline_updater_helper/traj_start_index", rclcpp::QoS{1},
240+
[this](const std_msgs::msg::Int32 & msg) {
241+
if (!meta_data_to_save_map_ || traj_end_index_ + 1 < msg.data) {
242+
return;
243+
}
244+
traj_start_index_ = msg.data;
245+
246+
const auto & d = meta_data_to_save_map_;
247+
const auto selected_optimized_traj_points = std::vector<TrajectoryPoint>(
248+
d->optimized_traj_points.begin() + traj_start_index_,
249+
d->optimized_traj_points.begin() + traj_end_index_ + 1);
250+
251+
pub_optimized_centerline_->publish(motion_utils::convertToTrajectory(
252+
selected_optimized_traj_points, createHeader(this->now())));
253+
});
254+
sub_traj_end_index_ = create_subscription<std_msgs::msg::Int32>(
255+
"/centerline_updater_helper/traj_end_index", rclcpp::QoS{1},
256+
[this](const std_msgs::msg::Int32 & msg) {
257+
if (!meta_data_to_save_map_ || msg.data + 1 < traj_start_index_) {
258+
return;
259+
}
260+
traj_end_index_ = msg.data;
261+
262+
const auto & d = meta_data_to_save_map_;
263+
const auto selected_optimized_traj_points = std::vector<TrajectoryPoint>(
264+
d->optimized_traj_points.begin() + traj_start_index_,
265+
d->optimized_traj_points.begin() + traj_end_index_ + 1);
266+
267+
pub_optimized_centerline_->publish(motion_utils::convertToTrajectory(
268+
selected_optimized_traj_points, createHeader(this->now())));
269+
});
270+
sub_save_map_ = create_subscription<std_msgs::msg::Bool>(
271+
"/centerline_updater_helper/save_map", rclcpp::QoS{1}, [this](const std_msgs::msg::Bool & msg) {
272+
const auto lanelet2_output_file_path =
273+
tier4_autoware_utils::getOrDeclareParameter<std::string>(
274+
*this, "lanelet2_output_file_path");
275+
if (!meta_data_to_save_map_ || msg.data) {
276+
const auto & d = meta_data_to_save_map_;
277+
const auto selected_optimized_traj_points = std::vector<TrajectoryPoint>(
278+
d->optimized_traj_points.begin() + traj_start_index_,
279+
d->optimized_traj_points.begin() + traj_end_index_ + 1);
280+
save_map(lanelet2_output_file_path, d->route_lane_ids, selected_optimized_traj_points);
281+
}
282+
});
283+
223284
// services
224285
callback_group_ = create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
225286
srv_load_map_ = create_service<LoadMap>(
@@ -258,7 +319,11 @@ void StaticCenterlineOptimizerNode::run()
258319
load_map(lanelet2_input_file_path);
259320
const auto route_lane_ids = plan_route(start_lanelet_id, end_lanelet_id);
260321
const auto optimized_traj_points = plan_path(route_lane_ids);
322+
traj_start_index_ = 0;
323+
traj_end_index_ = optimized_traj_points.size() - 1;
261324
save_map(lanelet2_output_file_path, route_lane_ids, optimized_traj_points);
325+
326+
meta_data_to_save_map_ = MetaDataToSaveMap{optimized_traj_points, route_lane_ids};
262327
}
263328

264329
void StaticCenterlineOptimizerNode::load_map(const std::string & lanelet2_input_file_path)
@@ -450,6 +515,8 @@ std::vector<TrajectoryPoint> StaticCenterlineOptimizerNode::plan_path(
450515

451516
// smooth trajectory and road collision avoidance
452517
const auto optimized_traj_points = optimize_trajectory(raw_path);
518+
pub_whole_optimized_centerline_->publish(
519+
motion_utils::convertToTrajectory(optimized_traj_points, raw_path.header));
453520
pub_optimized_centerline_->publish(
454521
motion_utils::convertToTrajectory(optimized_traj_points, raw_path.header));
455522
RCLCPP_INFO(

0 commit comments

Comments
 (0)