Nav2 Navigation Stack - kilted  kilted
ROS 2 Navigation Stack
utils.hpp
1 // Copyright (c) 2024 Open Navigation LLC
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 #ifndef OPENNAV_DOCKING__UTILS_HPP_
16 #define OPENNAV_DOCKING__UTILS_HPP_
17 
18 #include <string>
19 #include <vector>
20 
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"
29 
30 namespace utils
31 {
32 
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;
38 
45 inline bool parseDockFile(
46  const std::string & yaml_filepath,
47  const rclcpp_lifecycle::LifecycleNode::SharedPtr & node,
48  DockMap & dock_db)
49 {
50  YAML::Node yaml_file;
51  try {
52  yaml_file = YAML::LoadFile(yaml_filepath);
53  } catch (...) {
54  return false;
55  }
56 
57  if (!yaml_file["docks"]) {
58  RCLCPP_ERROR(
59  node->get_logger(),
60  "Dock database (%s) does not contain 'docks'.", yaml_filepath.c_str());
61  return false;
62  }
63 
64  auto yaml_docks = yaml_file["docks"];
65  Dock curr_dock;
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;
69 
70  curr_dock.frame = "map";
71  if (dock_attribs["frame"]) {
72  curr_dock.frame = dock_attribs["frame"].as<std::string>();
73  }
74 
75  if (!dock_attribs["type"]) {
76  RCLCPP_ERROR(
77  node->get_logger(),
78  "Dock database (%s) entries do not contain 'type'.", yaml_filepath.c_str());
79  return false;
80  }
81  curr_dock.type = dock_attribs["type"].as<std::string>();
82 
83  if (!dock_attribs["pose"]) {
84  RCLCPP_ERROR(
85  node->get_logger(),
86  "Dock database (%s) entries do not contain 'pose'.", yaml_filepath.c_str());
87  return false;
88  }
89  std::vector<double> pose_arr = dock_attribs["pose"].as<std::vector<double>>();
90  if (pose_arr.size() != 3u) {
91  RCLCPP_ERROR(
92  node->get_logger(),
93  "Dock database (%s) entries do not contain pose of size 3.", yaml_filepath.c_str());
94  return false;
95  }
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]);
99 
100  if (dock_attribs["id"]) {
101  curr_dock.id = dock_attribs["id"].as<std::string>();
102  }
103 
104  // Insert into dock instance database
105  dock_db.emplace(dock_name, curr_dock);
106  }
107 
108  return true;
109 }
110 
117 inline bool parseDockParams(
118  const std::vector<std::string> & docks_param,
119  const rclcpp_lifecycle::LifecycleNode::SharedPtr & node,
120  DockMap & dock_db)
121 {
122  Dock curr_dock;
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");
127  }
128  node->get_parameter(dock_name + ".frame", curr_dock.frame);
129 
130  if (!node->has_parameter(dock_name + ".type")) {
131  node->declare_parameter(dock_name + ".type", PARAMETER_STRING);
132  }
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());
135  return false;
136  }
137 
138  pose_arr.clear();
139  if (!node->has_parameter(dock_name + ".pose")) {
140  node->declare_parameter(dock_name + ".pose", PARAMETER_DOUBLE_ARRAY);
141  }
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());
144  return false;
145  }
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]);
149 
150  if (!node->has_parameter(dock_name + ".id")) {
151  node->declare_parameter(dock_name + ".id", "");
152  }
153  node->get_parameter(dock_name + ".id", curr_dock.id);
154 
155  // Insert into dock instance database
156  dock_db.emplace(dock_name, curr_dock);
157  }
158  return true;
159 }
160 
167 inline geometry_msgs::msg::PoseStamped getDockPoseStamped(
168  const Dock * dock, const rclcpp::Time & t)
169 {
170  geometry_msgs::msg::PoseStamped pose;
171  pose.pose = dock->pose;
172  pose.header.frame_id = dock->frame;
173  pose.header.stamp = t;
174  return pose;
175 }
176 
177 inline double l2Norm(const geometry_msgs::msg::Pose & a, const geometry_msgs::msg::Pose & b)
178 {
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);
182  return sqrt(
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);
186 }
187 
188 inline DockDirection getDockDirectionFromString(const std::string & direction)
189 {
190  auto upper_direction = direction;
191  std::transform(
192  upper_direction.begin(), upper_direction.end(), upper_direction.begin(), ::toupper);
193 
194  if (upper_direction == "FORWARD") {
195  return DockDirection::FORWARD;
196  } else if (upper_direction == "BACKWARD") {
197  return DockDirection::BACKWARD;
198  } else {
199  return DockDirection::UNKNOWN;
200  }
201 }
202 
203 } // namespace utils
204 
205 #endif // OPENNAV_DOCKING__UTILS_HPP_
Definition: types.hpp:33