AutoAPMS
Streamlining behaviors in ROS 2
Loading...
Searching...
No Matches
get_position.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 <Eigen/Geometry>
16#include <type_traits>
17
18#include "auto_apms_behavior_tree_core/node.hpp"
19#include "px4_msgs/msg/vehicle_global_position.hpp"
20#include "px4_msgs/msg/vehicle_local_position.hpp"
21#include "px4_ros2/utils/message_version.hpp"
22
23#define OUTPUT_KEY_LAT "lat"
24#define OUTPUT_KEY_LON "lon"
25#define OUTPUT_KEY_ALT "alt"
26#define OUTPUT_KEY_N "north"
27#define OUTPUT_KEY_E "east"
28#define OUTPUT_KEY_D "down"
29#define OUTPUT_KEY_VEC "vector"
30
31using GlobalPositionMsg = px4_msgs::msg::VehicleGlobalPosition;
32using LocalPositionMsg = px4_msgs::msg::VehicleLocalPosition;
33
34namespace auto_apms_px4
35{
36
37template <class T>
38class GetPosition : public auto_apms_behavior_tree::core::RosSubscriberNode<T>
39{
40 bool first_message_received_ = false;
41 T last_msg_;
42
43public:
44 GetPosition(
45 const std::string & instance_name, const BT::NodeConfig & config,
46 const auto_apms_behavior_tree::core::RosNodeContext & context)
47 : auto_apms_behavior_tree::core::RosSubscriberNode<T>{instance_name, config, context, rclcpp::SensorDataQoS{}}
48 {
49 // Resolve the topic's message version suffix at runtime from the message definition, rather than baking it into
50 // the node manifest at configure time. Since the manifest does not fix a topic, the base class cannot resolve one
51 // at construction and defers creation to this constructor.
52 const std::string base_topic =
53 std::is_same_v<T, GlobalPositionMsg> ? "fmu/out/vehicle_global_position" : "fmu/out/vehicle_local_position";
54 this->createSubscriber(base_topic + px4_ros2::getMessageNameVersion<T>());
55 }
56
57 static BT::PortsList providedPorts()
58 {
59 if constexpr (std::is_same_v<T, GlobalPositionMsg>) {
60 return {
61 BT::OutputPort<Eigen::MatrixXd>(
62 OUTPUT_KEY_VEC, "{pos_vec}",
63 "Current global position vector (latitude [°], longitude [°], altitude AMSL [m])"),
64 BT::OutputPort<double>(OUTPUT_KEY_LAT, "{lat}", "Current latitude in degree [°]"),
65 BT::OutputPort<double>(OUTPUT_KEY_LON, "{lon}", "Current longitude in degree [°]"),
66 BT::OutputPort<double>(OUTPUT_KEY_ALT, "{alt}", "Current altitude in meter (AMSL)")};
67 } else {
68 return {
69 BT::OutputPort<Eigen::MatrixXd>(
70 OUTPUT_KEY_VEC, "{pos_vec}", "Current local position vector (north [m], east [m], down [m])"),
71 BT::OutputPort<double>(OUTPUT_KEY_N, "{north}", "Current north [m] relative to origin"),
72 BT::OutputPort<double>(OUTPUT_KEY_E, "{east}", "Current east [m] relative to origin"),
73 BT::OutputPort<double>(OUTPUT_KEY_D, "{down}", "Current down [m] relative to origin")};
74 }
75 }
76
77 BT::NodeStatus onTick(const std::shared_ptr<T> & last_msg_ptr) final
78 {
79 // Check if a new message was received
80 if (last_msg_ptr) {
81 first_message_received_ = true;
82 last_msg_ = *last_msg_ptr;
83 }
84
85 if (!first_message_received_) return BT::NodeStatus::FAILURE;
86
87 if constexpr (std::is_same_v<T, GlobalPositionMsg>) {
88 Eigen::MatrixXd mat(1, 3);
89 mat(0, 0) = last_msg_.lat;
90 mat(0, 1) = last_msg_.lon;
91 mat(0, 2) = last_msg_.alt;
92 this->setOutput(OUTPUT_KEY_LAT, mat(0, 0));
93 this->setOutput(OUTPUT_KEY_LON, mat(0, 1));
94 this->setOutput(OUTPUT_KEY_ALT, mat(0, 2));
95 this->setOutput(OUTPUT_KEY_VEC, mat);
96 } else {
97 Eigen::MatrixXd mat(1, 3);
98 mat(0, 0) = last_msg_.x;
99 mat(0, 1) = last_msg_.y;
100 mat(0, 2) = last_msg_.z;
101 this->setOutput(OUTPUT_KEY_N, mat(0, 0));
102 this->setOutput(OUTPUT_KEY_E, mat(0, 1));
103 this->setOutput(OUTPUT_KEY_D, mat(0, 2));
104 this->setOutput(OUTPUT_KEY_VEC, mat);
105 }
106
107 return BT::NodeStatus::SUCCESS;
108 }
109};
110
111} // namespace auto_apms_px4
112
113AUTO_APMS_BEHAVIOR_TREE_REGISTER_NODE(auto_apms_px4::GetPosition<GlobalPositionMsg>)
114AUTO_APMS_BEHAVIOR_TREE_REGISTER_NODE(auto_apms_px4::GetPosition<LocalPositionMsg>)
RosSubscriberNode(const std::string &instance_name, const Config &config, Context context, const rclcpp::QoS &qos={10})
#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.