Nav2 Navigation Stack - lyrical  lyrical
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 "nav2_ros_common/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 nav2::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 nav2::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  curr_dock.frame = node->declare_or_get_parameter(dock_name + ".frame", std::string("map"));
126 
127  try {
128  curr_dock.type = node->declare_or_get_parameter<std::string>(dock_name + ".type");
129  } catch (...) {
130  RCLCPP_ERROR(node->get_logger(), "Dock %s has no dock 'type'.", dock_name.c_str());
131  return false;
132  }
133 
134  pose_arr.clear();
135  try {
136  pose_arr = node->declare_or_get_parameter<std::vector<double>>(dock_name + ".pose");
137  if (pose_arr.size() != 3u) {
138  throw std::runtime_error("Dock pose is incorrect size!");
139  }
140  } catch (...) {
141  RCLCPP_ERROR(node->get_logger(), "Dock %s has no valid 'pose'.", dock_name.c_str());
142  return false;
143  }
144 
145  curr_dock.pose.position.x = pose_arr[0];
146  curr_dock.pose.position.y = pose_arr[1];
147  curr_dock.pose.orientation = orientationAroundZAxis(pose_arr[2]);
148 
149  curr_dock.id = node->declare_or_get_parameter(dock_name + ".id", std::string(""));
150 
151  // Insert into dock instance database
152  dock_db.emplace(dock_name, curr_dock);
153  }
154  return true;
155 }
156 
163 inline geometry_msgs::msg::PoseStamped getDockPoseStamped(
164  const Dock * dock, const rclcpp::Time & t)
165 {
166  geometry_msgs::msg::PoseStamped pose;
167  pose.pose = dock->pose;
168  pose.header.frame_id = dock->frame;
169  pose.header.stamp = t;
170  return pose;
171 }
172 
173 inline double l2Norm(const geometry_msgs::msg::Pose & a, const geometry_msgs::msg::Pose & b)
174 {
175  double angle_a = tf2::getYaw(a.orientation);
176  double angle_b = tf2::getYaw(b.orientation);
177  double delta_angle = angles::shortest_angular_distance(angle_a, angle_b);
178  return sqrt(
179  (a.position.x - b.position.x) * (a.position.x - b.position.x) +
180  (a.position.y - b.position.y) * (a.position.y - b.position.y) +
181  delta_angle * delta_angle);
182 }
183 
184 inline DockDirection getDockDirectionFromString(const std::string & direction)
185 {
186  auto upper_direction = direction;
187  std::transform(
188  upper_direction.begin(), upper_direction.end(), upper_direction.begin(), ::toupper);
189 
190  if (upper_direction == "FORWARD") {
191  return DockDirection::FORWARD;
192  } else if (upper_direction == "BACKWARD") {
193  return DockDirection::BACKWARD;
194  } else {
195  return DockDirection::UNKNOWN;
196  }
197 }
198 
199 } // namespace utils
200 
201 #endif // OPENNAV_DOCKING__UTILS_HPP_
Definition: types.hpp:33