15 #ifndef OPENNAV_DOCKING__UTILS_HPP_
16 #define OPENNAV_DOCKING__UTILS_HPP_
21 #include "yaml-cpp/yaml.h"
22 #include "rclcpp_lifecycle/lifecycle_node.hpp"
23 #include "rclcpp/rclcpp.hpp"
24 #include "nav2_util/geometry_utils.hpp"
25 #include "angles/angles.h"
26 #include "opennav_docking/types.hpp"
27 #include "opennav_docking_core/charging_dock.hpp"
28 #include "tf2/utils.hpp"
33 using rclcpp::ParameterType::PARAMETER_STRING;
34 using rclcpp::ParameterType::PARAMETER_STRING_ARRAY;
35 using rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY;
36 using nav2_util::geometry_utils::orientationAroundZAxis;
37 using opennav_docking_core::DockDirection;
45 inline bool parseDockFile(
46 const std::string & yaml_filepath,
47 const rclcpp_lifecycle::LifecycleNode::SharedPtr & node,
52 yaml_file = YAML::LoadFile(yaml_filepath);
57 if (!yaml_file[
"docks"]) {
60 "Dock database (%s) does not contain 'docks'.", yaml_filepath.c_str());
64 auto yaml_docks = yaml_file[
"docks"];
66 for (
const auto & yaml_dock : yaml_docks) {
67 std::string dock_name = yaml_dock.first.as<std::string>();
68 const YAML::Node & dock_attribs = yaml_dock.second;
70 curr_dock.frame =
"map";
71 if (dock_attribs[
"frame"]) {
72 curr_dock.frame = dock_attribs[
"frame"].as<std::string>();
75 if (!dock_attribs[
"type"]) {
78 "Dock database (%s) entries do not contain 'type'.", yaml_filepath.c_str());
81 curr_dock.type = dock_attribs[
"type"].as<std::string>();
83 if (!dock_attribs[
"pose"]) {
86 "Dock database (%s) entries do not contain 'pose'.", yaml_filepath.c_str());
89 std::vector<double> pose_arr = dock_attribs[
"pose"].as<std::vector<double>>();
90 if (pose_arr.size() != 3u) {
93 "Dock database (%s) entries do not contain pose of size 3.", yaml_filepath.c_str());
96 curr_dock.pose.position.x = pose_arr[0];
97 curr_dock.pose.position.y = pose_arr[1];
98 curr_dock.pose.orientation = orientationAroundZAxis(pose_arr[2]);
100 if (dock_attribs[
"id"]) {
101 curr_dock.id = dock_attribs[
"id"].as<std::string>();
105 dock_db.emplace(dock_name, curr_dock);
117 inline bool parseDockParams(
118 const std::vector<std::string> & docks_param,
119 const rclcpp_lifecycle::LifecycleNode::SharedPtr & node,
123 std::vector<double> pose_arr;
124 for (
const auto & dock_name : docks_param) {
125 if (!node->has_parameter(dock_name +
".frame")) {
126 node->declare_parameter(dock_name +
".frame",
"map");
128 node->get_parameter(dock_name +
".frame", curr_dock.frame);
130 if (!node->has_parameter(dock_name +
".type")) {
131 node->declare_parameter(dock_name +
".type", PARAMETER_STRING);
133 if (!node->get_parameter(dock_name +
".type", curr_dock.type)) {
134 RCLCPP_ERROR(node->get_logger(),
"Dock %s has no dock 'type'.", dock_name.c_str());
139 if (!node->has_parameter(dock_name +
".pose")) {
140 node->declare_parameter(dock_name +
".pose", PARAMETER_DOUBLE_ARRAY);
142 if (!node->get_parameter(dock_name +
".pose", pose_arr) || pose_arr.size() != 3u) {
143 RCLCPP_ERROR(node->get_logger(),
"Dock %s has no valid 'pose'.", dock_name.c_str());
146 curr_dock.pose.position.x = pose_arr[0];
147 curr_dock.pose.position.y = pose_arr[1];
148 curr_dock.pose.orientation = orientationAroundZAxis(pose_arr[2]);
150 if (!node->has_parameter(dock_name +
".id")) {
151 node->declare_parameter(dock_name +
".id",
"");
153 node->get_parameter(dock_name +
".id", curr_dock.id);
156 dock_db.emplace(dock_name, curr_dock);
167 inline geometry_msgs::msg::PoseStamped getDockPoseStamped(
168 const Dock * dock,
const rclcpp::Time & t)
170 geometry_msgs::msg::PoseStamped pose;
171 pose.pose = dock->pose;
172 pose.header.frame_id = dock->frame;
173 pose.header.stamp = t;
177 inline double l2Norm(
const geometry_msgs::msg::Pose & a,
const geometry_msgs::msg::Pose & b)
179 double angle_a = tf2::getYaw(a.orientation);
180 double angle_b = tf2::getYaw(b.orientation);
181 double delta_angle = angles::shortest_angular_distance(angle_a, angle_b);
183 (a.position.x - b.position.x) * (a.position.x - b.position.x) +
184 (a.position.y - b.position.y) * (a.position.y - b.position.y) +
185 delta_angle * delta_angle);
188 inline DockDirection getDockDirectionFromString(
const std::string & direction)
190 auto upper_direction = direction;
192 upper_direction.begin(), upper_direction.end(), upper_direction.begin(), ::toupper);
194 if (upper_direction ==
"FORWARD") {
195 return DockDirection::FORWARD;
196 }
else if (upper_direction ==
"BACKWARD") {
197 return DockDirection::BACKWARD;
199 return DockDirection::UNKNOWN;