PX4 ROS 2 Interface Library
Library to interface with PX4 from a companion computer using ROS 2
Loading...
Searching...
No Matches
node_with_mode.hpp
1/****************************************************************************
2 * Copyright (c) 2024 PX4 Development Team.
3 * SPDX-License-Identifier: BSD-3-Clause
4 ****************************************************************************/
5
6#pragma once
7
8#include <px4_ros2/components/mode.hpp>
9#include <px4_ros2/components/wait_for_fmu.hpp>
10#include <rclcpp/rclcpp.hpp>
11#include <tuple>
12#include <utility>
13
14namespace px4_ros2 {
32template <typename ModeT>
33class NodeWithMode : public rclcpp::Node {
34 static_assert(std::is_base_of_v<ModeBase, ModeT>,
35 "Template type ModeT must be derived from px4_ros2::ModeBase");
36
37 public:
38 explicit NodeWithMode(const std::string& node_name, bool enable_debug_output = false)
39 : Node(node_name)
40 {
41 if (enable_debug_output) {
42 auto ret =
43 rcutils_logging_set_logger_level(get_logger().get_name(), RCUTILS_LOG_SEVERITY_DEBUG);
44
45 if (ret != RCUTILS_RET_OK) {
46 RCLCPP_ERROR(get_logger(), "Error setting severity: %s", rcutils_get_error_string().str);
47 rcutils_reset_error();
48 }
49 }
50
51 _mode = std::make_unique<ModeT>(*this);
52
53 if (!_mode->doRegister()) {
54 throw Exception("Registration failed");
55 }
56 }
57
58 ModeT& getMode() const { return *_mode; }
59
60 private:
61 std::unique_ptr<ModeT> _mode;
62};
63
88template <typename ModeExecutorT, typename OwnedModeT, typename... OtherModesT>
89class NodeWithModeExecutor : public rclcpp::Node {
90 static_assert(std::is_base_of_v<ModeExecutorBase, ModeExecutorT>,
91 "Template type ModeExecutorT must be derived from px4_ros2::ModeExecutorBase");
92 static_assert(
93 (std::is_base_of_v<ModeBase, OwnedModeT> && ... && std::is_base_of_v<ModeBase, OtherModesT>),
94 "Template types OwnedModeT and OtherModesT must be derived from px4_ros2::ModeBase");
95
96 public:
97 explicit NodeWithModeExecutor(std::string node_name, bool enable_debug_output = false)
98 : Node(node_name)
99 {
100 if (enable_debug_output) {
101 auto ret =
102 rcutils_logging_set_logger_level(get_logger().get_name(), RCUTILS_LOG_SEVERITY_DEBUG);
103
104 if (ret != RCUTILS_RET_OK) {
105 RCLCPP_ERROR(get_logger(), "Error setting severity: %s", rcutils_get_error_string().str);
106 rcutils_reset_error();
107 }
108 }
109
110 _owned_mode = std::make_unique<OwnedModeT>(*this);
111 _other_modes = std::make_tuple(std::make_unique<OtherModesT>(*this)...);
112 _mode_executor = createModeExecutor(std::index_sequence_for<OtherModesT...>{});
113
114 if (!_mode_executor->doRegister() || !std::apply(
115 [](const auto&... mode) {
116 // *INDENT-OFF*
117 return (mode->doRegister() && ...);
118 // *INDENT-ON*
119 },
120 _other_modes)) {
121 throw Exception("Registration failed");
122 }
123 }
124
125 template <typename ModeT = OwnedModeT>
126 ModeT& getMode() const
127 {
128 if constexpr (std::is_same_v<ModeT, OwnedModeT>) {
129 return *_owned_mode;
130 } else {
131 return *std::get<ModeT>(_other_modes);
132 }
133 }
134
135 private:
136 template <std::size_t... Idx>
137 auto createModeExecutor(std::index_sequence<Idx...>)
138 {
139 if constexpr (sizeof...(Idx) == 0) {
140 return std::make_unique<ModeExecutorT>(*_owned_mode);
141 } else {
142 return std::make_unique<ModeExecutorT>(*_owned_mode, *std::get<Idx>(_other_modes)...);
143 }
144 }
145
146 std::unique_ptr<ModeExecutorT> _mode_executor;
147 std::unique_ptr<OwnedModeT> _owned_mode;
148 std::tuple<std::unique_ptr<OtherModesT>...> _other_modes;
149};
150
152} // namespace px4_ros2
Definition exception.hpp:14
A ROS2 node which instantiates a mode executor and its owned mode, and handles their registration wit...
Definition node_with_mode.hpp:89
A ROS2 node which instantiates a control mode and handles its registration with PX4.
Definition node_with_mode.hpp:33