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