Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
docking_panel.hpp
1 // Copyright (c) 2024 Alberto J. Tudela Roldán
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 NAV2_RVIZ_PLUGINS__DOCKING_PANEL_HPP_
16 #define NAV2_RVIZ_PLUGINS__DOCKING_PANEL_HPP_
17 
18 // QT
19 #include <QtWidgets>
20 #include <QBasicTimer>
21 #include <QStateMachine>
22 #include <QState>
23 #include <QSignalTransition>
24 
25 #include <memory>
26 #include <string>
27 
28 // ROS
29 #include "nav2_lifecycle_manager/lifecycle_manager_client.hpp"
30 #include "rclcpp/executors/single_threaded_executor.hpp"
31 #include "rclcpp/node.hpp"
32 #include "rclcpp_action/rclcpp_action.hpp"
33 #include "rviz_common/panel.hpp"
34 #include "rviz_common/ros_integration/ros_node_abstraction_iface.hpp"
35 #include "sensor_msgs/msg/battery_state.hpp"
36 #include "nav2_msgs/action/dock_robot.hpp"
37 #include "nav2_msgs/action/undock_robot.hpp"
38 
39 class QLineEdit;
40 class QPushButton;
41 
42 namespace nav2_rviz_plugins
43 {
44 
45 class InitialDockThread;
46 
48 class DockingPanel : public rviz_common::Panel
49 {
50  Q_OBJECT
51 
52 public:
53  explicit DockingPanel(QWidget * parent = 0);
54  virtual ~DockingPanel();
55 
56  void onInitialize() override;
57 
59  void load(const rviz_common::Config & config) override;
60  void save(rviz_common::Config config) const override;
61 
62 private Q_SLOTS:
63  void startThread();
64  void onDockingButtonPressed();
65  void onUndockingButtonPressed();
66  void onCancelDocking();
67  void onCancelUndocking();
68  void dockIdCheckbox();
69 
70 private:
71  using Dock = nav2_msgs::action::DockRobot;
72  using Undock = nav2_msgs::action::UndockRobot;
73  using DockGoalHandle = rclcpp_action::ClientGoalHandle<Dock>;
74  using UndockGoalHandle = rclcpp_action::ClientGoalHandle<Undock>;
75 
76  // The (non-spinning) client node used to invoke the action client
77  void timerEvent(QTimerEvent * event) override;
78 
79  // Create label string from feedback msg
80  static inline QString getDockFeedbackLabel(Dock::Feedback msg = Dock::Feedback());
81 
82  // Create label string from status msg
83  template<typename T>
84  static inline std::string toLabel(T & msg);
85 
86  // Round off double to the specified precision and convert to string
87  static inline std::string toString(double val, int precision = 0);
88 
89  // Convert the dock state and error code to string
90  static inline std::string dockStateToString(int16_t state);
91  static inline std::string dockErrorToString(int16_t error_code);
92 
93  // The (non-spinning) client node used to invoke the action client
94  rclcpp::Node::SharedPtr client_node_; // nosemgrep
95  rclcpp::executors::SingleThreadedExecutor::SharedPtr executor_;
96 
97  // The Node pointer that we need to keep alive for the duration of this plugin.
98  std::shared_ptr<rviz_common::ros_integration::RosNodeAbstractionIface> node_ptr_;
99 
100  // Timeout value when waiting for action servers to respond
101  std::chrono::milliseconds server_timeout_;
102 
103  // A timer used to check on the completion status of the action
104  QBasicTimer action_timer_;
105 
106  // The Dock and Undock action client
107  nav2::ActionClient<Dock>::SharedPtr dock_client_;
108  nav2::ActionClient<Undock>::SharedPtr undock_client_;
109 
110  // Docking / Undocking action feedback subscribers
111  nav2::Subscription<Dock::Impl::FeedbackMessage>::SharedPtr docking_feedback_sub_;
112  nav2::Subscription<Undock::Impl::FeedbackMessage>::SharedPtr undocking_feedback_sub_;
113  nav2::Subscription<Dock::Impl::GoalStatusMessage>::SharedPtr docking_goal_status_sub_;
114  nav2::Subscription<Undock::Impl::GoalStatusMessage>::SharedPtr undocking_goal_status_sub_;
115 
116  // Goal related state
117  DockGoalHandle::SharedPtr dock_goal_handle_;
118  UndockGoalHandle::SharedPtr undock_goal_handle_;
119 
120  // Flags to indicate if the plugins have been loaded
121  bool plugins_loaded_ = false;
122  bool server_failed_ = false;
123 
124  QVBoxLayout * main_layout_{nullptr};
125  QHBoxLayout * info_layout_{nullptr};
126  QVBoxLayout * feedback_layout_{nullptr};
127  QHBoxLayout * dock_id_layout_{nullptr};
128  QHBoxLayout * dock_type_layout_{nullptr};
129  QHBoxLayout * dock_pose_layout_{nullptr};
130  QHBoxLayout * nav_stage_layout_{nullptr};
131 
132  QComboBox * dock_type_{nullptr};
133  QPushButton * docking_button_{nullptr};
134  QPushButton * undocking_button_{nullptr};
135  QCheckBox * use_dock_id_checkbox_{nullptr};
136  QCheckBox * nav_to_staging_checkbox_{nullptr};
137 
138  QLabel * docking_goal_status_indicator_{nullptr};
139  QLabel * docking_feedback_indicator_{nullptr};
140  QLabel * docking_result_indicator_{nullptr};
141 
142  QLineEdit * dock_id_{nullptr};
143  QLineEdit * dock_pose_x_{nullptr};
144  QLineEdit * dock_pose_y_{nullptr};
145  QLineEdit * dock_pose_yaw_{nullptr};
146 
147  // The current state of the docking and undocking actions
148  bool docking_in_progress_ = false;
149  bool undocking_in_progress_ = false;
150  bool use_dock_id_ = false;
151 
152  QStateMachine state_machine_;
153  InitialDockThread * initial_thread_;
154 
155  QState * pre_initial_{nullptr};
156  QState * idle_{nullptr};
157  QState * docking_{nullptr};
158  QState * undocking_{nullptr};
159  QState * canceled_docking_{nullptr};
160  QState * canceled_undocking_{nullptr};
161 };
162 
163 class InitialDockThread : public QThread
164 {
165  Q_OBJECT
166 
167 public:
168  explicit InitialDockThread(
169  nav2::ActionClient<nav2_msgs::action::DockRobot>::SharedPtr & dock_client,
170  nav2::ActionClient<nav2_msgs::action::UndockRobot>::SharedPtr & undock_client)
171  : dock_client_(dock_client), undock_client_(undock_client)
172  {}
173 
174  void run() override
175  {
176  while (!dock_active_) {
177  dock_active_ = dock_client_->wait_for_action_server(std::chrono::seconds(1));
178  }
179 
180  while (!undock_active_) {
181  undock_active_ = undock_client_->wait_for_action_server(std::chrono::seconds(1));
182  }
183 
184  if (dock_active_) {
185  emit dockingActive();
186  } else {
187  emit dockingInactive();
188  }
189 
190  if (undock_active_) {
191  emit undockingActive();
192  } else {
193  emit undockingInactive();
194  }
195  }
196 
197 signals:
198  void dockingActive();
199  void dockingInactive();
200  void undockingActive();
201  void undockingInactive();
202 
203 private:
204  nav2::ActionClient<nav2_msgs::action::DockRobot>::SharedPtr dock_client_;
205  nav2::ActionClient<nav2_msgs::action::UndockRobot>::SharedPtr undock_client_;
206  bool dock_active_ = false;
207  bool undock_active_ = false;
208 };
209 
210 } // namespace nav2_rviz_plugins
211 
212 #endif // NAV2_RVIZ_PLUGINS__DOCKING_PANEL_HPP_
Panel to interface to the docking server.
void load(const rviz_common::Config &config) override
Load and save configuration data.
Definition: types.hpp:33