Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
selector.cpp
1 // Copyright (c) 2024 Neobotix GmbH
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 #include "nav2_rviz_plugins/selector.hpp"
16 #include "nav2_rviz_plugins/utils.hpp"
17 #include "rviz_common/display_context.hpp"
18 #include "rclcpp/rate.hpp"
19 
20 using namespace std::chrono_literals;
21 
22 namespace nav2_rviz_plugins
23 {
24 Selector::Selector(QWidget * parent)
25 : Panel(parent)
26 {
27  client_node_ = std::make_shared<rclcpp::Node>("nav2_rviz_selector_node"); // nosemgrep
28  rclcpp::QoS qos(rclcpp::KeepLast(1));
29  qos.transient_local().reliable();
30 
31  pub_controller_ =
32  client_node_->create_publisher<std_msgs::msg::String>("controller_selector", qos);
33  pub_planner_ = client_node_->create_publisher<std_msgs::msg::String>("planner_selector", qos);
34  pub_goal_checker_ =
35  client_node_->create_publisher<std_msgs::msg::String>("goal_checker_selector", qos);
36  pub_smoother_ = client_node_->create_publisher<std_msgs::msg::String>("smoother_selector", qos);
37  pub_progress_checker_ =
38  client_node_->create_publisher<std_msgs::msg::String>("progress_checker_selector", qos);
39  pub_path_handler_ =
40  client_node_->create_publisher<std_msgs::msg::String>("path_handler_selector", qos);
41 
42  main_layout_ = new QVBoxLayout;
43  row_1_label_layout_ = new QHBoxLayout;
44  row_2_label_layout_ = new QHBoxLayout;
45  row_3_label_layout_ = new QHBoxLayout;
46  row_1_layout_ = new QHBoxLayout;
47  row_2_layout_ = new QHBoxLayout;
48  row_3_layout_ = new QHBoxLayout;
49  controller_ = new QComboBox;
50  planner_ = new QComboBox;
51  goal_checker_ = new QComboBox;
52  smoother_ = new QComboBox;
53  progress_checker_ = new QComboBox;
54  path_handler_ = new QComboBox;
55 
56  main_layout_->setContentsMargins(10, 10, 10, 10);
57 
58  row_1_label_layout_->addWidget(new QLabel("Controller"));
59  row_1_layout_->addWidget(controller_);
60  row_1_label_layout_->addWidget(new QLabel("Planner"));
61  row_1_layout_->addWidget(planner_);
62  row_2_label_layout_->addWidget(new QLabel("Goal Checker"));
63  row_2_layout_->addWidget(goal_checker_);
64  row_2_label_layout_->addWidget(new QLabel("Smoother"));
65  row_2_layout_->addWidget(smoother_);
66  row_3_label_layout_->addWidget(new QLabel("Progress Checker"));
67  row_3_layout_->addWidget(progress_checker_);
68  row_3_label_layout_->addWidget(new QLabel("Path Handler"));
69  row_3_layout_->addWidget(path_handler_);
70 
71  main_layout_->addLayout(row_1_label_layout_);
72  main_layout_->addLayout(row_1_layout_);
73  main_layout_->addLayout(row_2_label_layout_);
74  main_layout_->addLayout(row_2_layout_);
75  main_layout_->addLayout(row_3_label_layout_);
76  main_layout_->addLayout(row_3_layout_);
77 
78  setLayout(main_layout_);
79  loadPlugins();
80 
81  connect(
82  controller_, QOverload<int>::of(&QComboBox::activated), this,
83  &Selector::setController);
84 
85  connect(
86  planner_, QOverload<int>::of(&QComboBox::activated), this,
87  &Selector::setPlanner);
88 
89  connect(
90  goal_checker_, QOverload<int>::of(&QComboBox::activated), this,
91  &Selector::setGoalChecker);
92 
93  connect(
94  smoother_, QOverload<int>::of(&QComboBox::activated), this,
95  &Selector::setSmoother);
96 
97  connect(
98  progress_checker_, QOverload<int>::of(&QComboBox::activated), this,
99  &Selector::setProgressChecker);
100 
101  connect(
102  path_handler_, QOverload<int>::of(&QComboBox::activated), this,
103  &Selector::setPathHandler);
104 }
105 
106 Selector::~Selector()
107 {
108  if (load_plugins_thread_.joinable()) {
109  load_plugins_thread_.join();
110  }
111 }
112 
113 // Publish the selected controller or planner
114 void Selector::setSelection(
115  QComboBox * combo_box,
116  rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher) // nosemgrep
117 {
118  // If "default" option is selected, it gets removed and the next item is selected
119  if (combo_box->findText("Default") != -1) {
120  combo_box->removeItem(0);
121  }
122 
123  // if there are no plugins available, return
124  if (combo_box->count() == 0) {
125  return;
126  }
127 
128  auto msg = std::make_unique<std_msgs::msg::String>();
129  msg->data = combo_box->currentText().toStdString();
130 
131  publisher->publish(std::move(msg));
132 }
133 
134 // Call setSelection() for controller
135 void Selector::setController()
136 {
137  setSelection(controller_, pub_controller_);
138 }
139 
140 // Call setSelection() for planner
141 void Selector::setPlanner()
142 {
143  setSelection(planner_, pub_planner_);
144 }
145 
146 // Call setSelection() for goal checker
147 void Selector::setGoalChecker()
148 {
149  setSelection(goal_checker_, pub_goal_checker_);
150 }
151 
152 // Call setSelection() for smoother
153 void Selector::setSmoother()
154 {
155  setSelection(smoother_, pub_smoother_);
156 }
157 
158 void Selector::setProgressChecker()
159 {
160  setSelection(progress_checker_, pub_progress_checker_);
161 }
162 
163 void Selector::setPathHandler()
164 {
165  setSelection(path_handler_, pub_path_handler_);
166 }
167 
168 void
169 Selector::loadPlugins()
170 {
171  load_plugins_thread_ = std::thread(
172  [this]() {
173  rclcpp::Rate rate(0.2);
174  while (rclcpp::ok() && !plugins_loaded_) {
175  RCLCPP_INFO(client_node_->get_logger(), "Trying to load plugins...");
176  nav2_rviz_plugins::pluginLoader(
177  client_node_, server_failed_, "controller_server", "controller_plugins", controller_);
178  nav2_rviz_plugins::pluginLoader(
179  client_node_, server_failed_, "planner_server", "planner_plugins", planner_);
180  nav2_rviz_plugins::pluginLoader(
181  client_node_, server_failed_, "controller_server", "goal_checker_plugins",
182  goal_checker_);
183  nav2_rviz_plugins::pluginLoader(
184  client_node_, server_failed_, "smoother_server", "smoother_plugins", smoother_);
185  nav2_rviz_plugins::pluginLoader(
186  client_node_, server_failed_, "controller_server", "progress_checker_plugins",
187  progress_checker_);
188  nav2_rviz_plugins::pluginLoader(
189  client_node_, server_failed_, "controller_server", "path_handler_plugins",
190  path_handler_);
191  if (controller_->count() > 0 &&
192  planner_->count() > 0 &&
193  goal_checker_->count() > 0 &&
194  smoother_->count() > 0 &&
195  progress_checker_->count() > 0 &&
196  path_handler_->count() > 0)
197  {
198  plugins_loaded_ = true;
199  } else {
200  RCLCPP_INFO(client_node_->get_logger(), "Failed to load plugins. Retrying...");
201  }
202  rate.sleep();
203  }
204  });
205 }
206 
207 } // namespace nav2_rviz_plugins
208 #include "pluginlib/class_list_macros.hpp"
209 PLUGINLIB_EXPORT_CLASS(nav2_rviz_plugins::Selector, rviz_common::Panel)