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