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