PX4 ROS 2 Interface Library
Library to interface with PX4 from a companion computer using ROS 2
mode_executor.hpp
1 /****************************************************************************
2  * Copyright (c) 2023 PX4 Development Team.
3  * SPDX-License-Identifier: BSD-3-Clause
4  ****************************************************************************/
5 
6 #pragma once
7 
8 #include "mode.hpp"
9 #include "overrides.hpp"
10 
11 #include <rclcpp/rclcpp.hpp>
12 #include <px4_msgs/msg/vehicle_status.hpp>
13 #include <px4_msgs/msg/vehicle_command.hpp>
14 #include <px4_msgs/msg/vehicle_command_ack.hpp>
15 #include <px4_msgs/msg/mode_completed.hpp>
16 
17 #include <functional>
18 
19 class Registration;
20 
21 namespace px4_ros2
22 {
31 {
32 public:
33  using CompletedCallback = std::function<void (Result)>;
34 
35  struct Settings
36  {
37  enum class Activation
38  {
42  };
44  };
45 
46  enum class DeactivateReason
47  {
48  FailsafeActivated,
49  Other
50  };
51 
52  ModeExecutorBase(
53  rclcpp::Node & node, const Settings & settings, ModeBase & owned_mode,
54  const std::string & topic_namespace_prefix = "");
55  ModeExecutorBase(const ModeExecutorBase &) = delete;
56  virtual ~ModeExecutorBase() = default;
57 
62  bool doRegister();
63 
64 
68  virtual void onActivate() = 0;
69 
73  virtual void onDeactivate(DeactivateReason reason) = 0;
74 
79  virtual void onFailsafeDeferred() {}
80 
85  uint32_t command, float param1 = NAN, float param2 = NAN, float param3 = NAN,
86  float param4 = NAN,
87  float param5 = NAN, float param6 = NAN, float param7 = NAN);
88 
94  void scheduleMode(ModeBase::ModeID mode_id, const CompletedCallback & on_completed);
95 
96  void takeoff(const CompletedCallback & on_completed, float altitude = NAN, float heading = NAN);
97  void land(const CompletedCallback & on_completed);
98  void rtl(const CompletedCallback & on_completed);
99 
100  void arm(const CompletedCallback & on_completed);
101  void waitReadyToArm(const CompletedCallback & on_completed);
102  void waitUntilDisarmed(const CompletedCallback & on_completed);
103 
104  bool isInCharge() const {return _is_in_charge;}
105 
106  bool isArmed() const {return _is_armed;}
107 
108  ModeBase & ownedMode() {return _owned_mode;}
109 
110  int id() const;
111 
112  rclcpp::Node & node() {return _node;}
113 
114  ConfigOverrides & configOverrides() {return _config_overrides;}
115 
128  bool deferFailsafesSync(bool enabled, int timeout_s = 0);
129 
130 private:
131  class ScheduledMode
132  {
133 public:
134  ScheduledMode(rclcpp::Node & node, const std::string & topic_namespace_prefix);
135 
136  bool active() const {return _mode_id != ModeBase::kModeIDInvalid;}
137  void activate(ModeBase::ModeID mode_id, const CompletedCallback & on_completed);
138  void cancel();
139  ModeBase::ModeID modeId() const {return _mode_id;}
140 
141 private:
142  void reset() {_mode_id = ModeBase::kModeIDInvalid;}
143 
144  ModeBase::ModeID _mode_id{ModeBase::kModeIDInvalid};
145  CompletedCallback _on_completed_callback;
146  rclcpp::Subscription<px4_msgs::msg::ModeCompleted>::SharedPtr _mode_completed_sub;
147  };
148 
149  class WaitForVehicleStatusCondition
150  {
151 public:
152  using RunCheckCallback =
153  std::function<bool (const px4_msgs::msg::VehicleStatus::UniquePtr & msg)>;
154  WaitForVehicleStatusCondition() = default;
155 
156  bool active() const {return _on_completed_callback != nullptr;}
157  void update(const px4_msgs::msg::VehicleStatus::UniquePtr & msg);
158 
159  void activate(
160  const RunCheckCallback & run_check_callback,
161  const CompletedCallback & on_completed);
162  void cancel();
163 
164 private:
165  CompletedCallback _on_completed_callback;
166  RunCheckCallback _run_check_callback;
167  };
168 
169  void onRegistered();
170 
171  void callOnActivate();
172  void callOnDeactivate(DeactivateReason reason);
173 
174  void vehicleStatusUpdated(const px4_msgs::msg::VehicleStatus::UniquePtr & msg);
175 
176  void scheduleMode(
177  ModeBase::ModeID mode_id, const px4_msgs::msg::VehicleCommand & cmd,
178  const ModeExecutorBase::CompletedCallback & on_completed);
179 
180  rclcpp::Node & _node;
181  const std::string _topic_namespace_prefix;
182  const Settings _settings;
183  ModeBase & _owned_mode;
184 
185  std::shared_ptr<Registration> _registration;
186 
187  rclcpp::Subscription<px4_msgs::msg::VehicleStatus>::SharedPtr _vehicle_status_sub;
188  rclcpp::Publisher<px4_msgs::msg::VehicleCommand>::SharedPtr _vehicle_command_pub;
189  rclcpp::Subscription<px4_msgs::msg::VehicleCommandAck>::SharedPtr _vehicle_command_ack_sub;
190 
191  ScheduledMode _current_scheduled_mode;
192  WaitForVehicleStatusCondition _current_wait_vehicle_status;
193 
194  bool _is_in_charge{false};
195  bool _is_armed{false};
196  bool _was_never_activated{true};
197  ModeBase::ModeID _prev_nav_state{ModeBase::kModeIDInvalid};
198  uint8_t _prev_failsafe_defer_state{px4_msgs::msg::VehicleStatus::FAILSAFE_DEFER_STATE_DISABLED};
199 
200  ConfigOverrides _config_overrides;
201 };
202 
204 } // namespace px4_ros2
uint8_t ModeID
Mode ID, corresponds to nav_state.
Definition: mode.hpp:72
Base class for a mode executor.
Definition: mode_executor.hpp:31
virtual void onDeactivate(DeactivateReason reason)=0
bool deferFailsafesSync(bool enabled, int timeout_s=0)
Result sendCommandSync(uint32_t command, float param1=NAN, float param2=NAN, float param3=NAN, float param4=NAN, float param5=NAN, float param6=NAN, float param7=NAN)
void scheduleMode(ModeBase::ModeID mode_id, const CompletedCallback &on_completed)
virtual void onFailsafeDeferred()
Definition: mode_executor.hpp:79
virtual void onActivate()=0
Result
Definition: mode.hpp:30
Definition: mode_executor.hpp:36
Activation
Definition: mode_executor.hpp:38
@ ActivateAlways
Allow the executor to always be activated (so it can arm the vehicle)
@ ActivateOnlyWhenArmed
Only activate the executor when armed (and selected)
@ ActivateImmediately
Activate the mode and executor immediately after registration. Only use this for fully autonomous exe...