AutoAPMS
Streamlining behaviors in ROS 2
Loading...
Searching...
No Matches
get_mode_nav_state.cpp
1// Copyright 2024 Robin Müller
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#include <cstdint>
16#include <map>
17#include <memory>
18#include <string>
19
20#include "auto_apms_behavior_tree_core/node.hpp"
21#include "auto_apms_px4_interfaces/msg/registered_mode.hpp"
22#include "px4_msgs/msg/vehicle_status.hpp"
23
24#define INPUT_KEY_MODE_NAME "mode_name"
25#define OUTPUT_KEY_NAV_STATE "nav_state"
26
27namespace auto_apms_px4
28{
29
47class GetModeNavState
48: public auto_apms_behavior_tree::core::RosSubscriberNode<auto_apms_px4_interfaces::msg::RegisteredMode>
49{
51 static std::map<std::string, uint8_t> standardModes()
52 {
53 using VehicleStatus = px4_msgs::msg::VehicleStatus;
54 return {
55 {"Manual", VehicleStatus::NAVIGATION_STATE_MANUAL},
56 {"Altitude", VehicleStatus::NAVIGATION_STATE_ALTCTL},
57 {"Position", VehicleStatus::NAVIGATION_STATE_POSCTL},
58 {"Mission", VehicleStatus::NAVIGATION_STATE_AUTO_MISSION},
59 {"Hold", VehicleStatus::NAVIGATION_STATE_AUTO_LOITER},
60 {"RTL", VehicleStatus::NAVIGATION_STATE_AUTO_RTL},
61 {"Acro", VehicleStatus::NAVIGATION_STATE_ACRO},
62 {"Descend", VehicleStatus::NAVIGATION_STATE_DESCEND},
63 {"Termination", VehicleStatus::NAVIGATION_STATE_TERMINATION},
64 {"Offboard", VehicleStatus::NAVIGATION_STATE_OFFBOARD},
65 {"Stabilized", VehicleStatus::NAVIGATION_STATE_STAB},
66 {"Takeoff", VehicleStatus::NAVIGATION_STATE_AUTO_TAKEOFF},
67 {"Land", VehicleStatus::NAVIGATION_STATE_AUTO_LAND},
68 {"FollowTarget", VehicleStatus::NAVIGATION_STATE_AUTO_FOLLOW_TARGET},
69 {"PrecisionLand", VehicleStatus::NAVIGATION_STATE_AUTO_PRECLAND},
70 {"Orbit", VehicleStatus::NAVIGATION_STATE_ORBIT},
71 {"VtolTakeoff", VehicleStatus::NAVIGATION_STATE_AUTO_VTOL_TAKEOFF},
72 };
73 }
74
75 // Seeded with the builtin modes; announcements from custom mode components are merged in on tick.
76 std::map<std::string, uint8_t> known_modes_ = standardModes();
77
78public:
79 GetModeNavState(
80 const std::string & instance_name, const BT::NodeConfig & config,
82 : RosSubscriberNode{instance_name, config, context, rclcpp::QoS(10).transient_local()}
83 {
84 }
85
86 static BT::PortsList providedPorts()
87 {
88 return providedBasicPorts({
89 BT::InputPort<std::string>(INPUT_KEY_MODE_NAME, "Name of the registered PX4 mode to resolve."),
90 BT::OutputPort<int>(OUTPUT_KEY_NAV_STATE, "Resolved PX4 navigation state (mode id) of the named mode."),
91 });
92 }
93
94 BT::NodeStatus onTick(const std::shared_ptr<auto_apms_px4_interfaces::msg::RegisteredMode> & last_msg_ptr) final
95 {
96 // Accumulate the latest announcement (each mode component publishes its own mapping on the shared topic).
97 if (last_msg_ptr) known_modes_[last_msg_ptr->name] = last_msg_ptr->nav_state;
98
99 const BT::Expected<std::string> expected_mode_name = getInput<std::string>(INPUT_KEY_MODE_NAME);
100 if (!expected_mode_name) {
101 RCLCPP_ERROR(
102 logger_, "%s - Missing required input '%s': %s", context_.getFullyQualifiedTreeNodeName(this).c_str(),
103 INPUT_KEY_MODE_NAME, expected_mode_name.error().c_str());
104 return BT::NodeStatus::FAILURE;
105 }
106
107 const auto it = known_modes_.find(expected_mode_name.value());
108 if (it == known_modes_.end()) {
109 // Not a builtin mode and not announced (yet) - retry to keep waiting for a custom mode to register.
110 return BT::NodeStatus::FAILURE;
111 }
112
113 setOutput(OUTPUT_KEY_NAV_STATE, static_cast<int>(it->second));
114 return BT::NodeStatus::SUCCESS;
115 }
116};
117
118} // namespace auto_apms_px4
119
Additional parameters specific to ROS 2 determined at runtime by TreeBuilder.
Generic behavior tree node wrapper for a ROS 2 subscriber.
RosSubscriberNode(const std::string &instance_name, const Config &config, Context context, const rclcpp::QoS &qos={10})
Resolves a PX4 mode's name to its nav_state (mode id).
#define AUTO_APMS_BEHAVIOR_TREE_REGISTER_NODE(type)
Macro for registering a behavior tree node plugin.
Definition node.hpp:50
Implementation of PX4 mode peers offered by px4_ros2_cpp enabling integration with AutoAPMS.