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/logging.hpp"
24 #include "rclcpp/parameter_value.hpp"
25 #include "rclcpp/time.hpp"
26 #include "nav2_util/geometry_utils.hpp"
27 #include "angles/angles.h"
28 #include "opennav_docking/types.hpp"
29 #include "opennav_docking_core/charging_dock.hpp"
30 #include "tf2/utils.hpp"
31 
32 namespace utils
33 {
34 
35 using rclcpp::ParameterType::PARAMETER_STRING;
36 using rclcpp::ParameterType::PARAMETER_STRING_ARRAY;
37 using rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY;
38 using nav2_util::geometry_utils::orientationAroundZAxis;
39 using opennav_docking_core::DockDirection;
40 
47 inline bool parseDockFile(
48  const std::string & yaml_filepath,
49  const nav2::LifecycleNode::SharedPtr & node,
50  DockMap & dock_db)
51 {
52  YAML::Node yaml_file;
53  try {
54  yaml_file = YAML::LoadFile(yaml_filepath);
55  } catch (...) {
56  return false;
57  }
58 
59  if (!yaml_file["docks"]) {
60  RCLCPP_ERROR(
61  node->get_logger(),
62  "Dock database (%s) does not contain 'docks'.", yaml_filepath.c_str());
63  return false;
64  }
65 
66  auto yaml_docks = yaml_file["docks"];
67  Dock curr_dock;
68  for (const auto & yaml_dock : yaml_docks) {
69  std::string dock_name = yaml_dock.first.as<std::string>();
70  const YAML::Node & dock_attribs = yaml_dock.second;
71 
72  curr_dock.frame = "map";
73  if (dock_attribs["frame"]) {
74  curr_dock.frame = dock_attribs["frame"].as<std::string>();
75  }
76 
77  if (!dock_attribs["type"]) {
78  RCLCPP_ERROR(
79  node->get_logger(),
80  "Dock database (%s) entries do not contain 'type'.", yaml_filepath.c_str());
81  return false;
82  }
83  curr_dock.type = dock_attribs["type"].as<std::string>();
84 
85  if (!dock_attribs["pose"]) {
86  RCLCPP_ERROR(
87  node->get_logger(),
88  "Dock database (%s) entries do not contain 'pose'.", yaml_filepath.c_str());
89  return false;
90  }
91  std::vector<double> pose_arr = dock_attribs["pose"].as<std::vector<double>>();
92  if (pose_arr.size() != 3u) {
93  RCLCPP_ERROR(
94  node->get_logger(),
95  "Dock database (%s) entries do not contain pose of size 3.", yaml_filepath.c_str());
96  return false;
97  }
98  curr_dock.pose.position.x = pose_arr[0];
99  curr_dock.pose.position.y = pose_arr[1];
100  curr_dock.pose.orientation = orientationAroundZAxis(pose_arr[2]);
101 
102  if (dock_attribs["id"]) {
103  curr_dock.id = dock_attribs["id"].as<std::string>();
104  }
105 
106  // Insert into dock instance database
107  dock_db.emplace(dock_name, curr_dock);
108  }
109 
110  return true;
111 }
112 
119 inline bool parseDockParams(
120  const std::vector<std::string> & docks_param,
121  const nav2::LifecycleNode::SharedPtr & node,
122  DockMap & dock_db)
123 {
124  Dock curr_dock;
125  std::vector<double> pose_arr;
126  for (const auto & dock_name : docks_param) {
127  curr_dock.frame = node->declare_or_get_parameter(dock_name + ".frame", std::string("map"));
128 
129  try {
130  curr_dock.type = node->declare_or_get_parameter<std::string>(dock_name + ".type");
131  } catch (...) {
132  RCLCPP_ERROR(node->get_logger(), "Dock %s has no dock 'type'.", dock_name.c_str());
133  return false;
134  }
135 
136  pose_arr.clear();
137  try {
138  pose_arr = node->declare_or_get_parameter<std::vector<double>>(dock_name + ".pose");
139  if (pose_arr.size() != 3u) {
140  throw std::runtime_error("Dock pose is incorrect size!");
141  }
142  } catch (...) {
143  RCLCPP_ERROR(node->get_logger(), "Dock %s has no valid 'pose'.", dock_name.c_str());
144  return false;
145  }
146 
147  curr_dock.pose.position.x = pose_arr[0];
148  curr_dock.pose.position.y = pose_arr[1];
149  curr_dock.pose.orientation = orientationAroundZAxis(pose_arr[2]);
150 
151  curr_dock.id = node->declare_or_get_parameter(dock_name + ".id", std::string(""));
152 
153  // Insert into dock instance database
154  dock_db.emplace(dock_name, curr_dock);
155  }
156  return true;
157 }
158 
165 inline geometry_msgs::msg::PoseStamped getDockPoseStamped(
166  const Dock * dock, const rclcpp::Time & t)
167 {
168  geometry_msgs::msg::PoseStamped pose;
169  pose.pose = dock->pose;
170  pose.header.frame_id = dock->frame;
171  pose.header.stamp = t;
172  return pose;
173 }
174 
175 inline double l2Norm(const geometry_msgs::msg::Pose & a, const geometry_msgs::msg::Pose & b)
176 {
177  double angle_a = tf2::getYaw(a.orientation);
178  double angle_b = tf2::getYaw(b.orientation);
179  double delta_angle = angles::shortest_angular_distance(angle_a, angle_b);
180  return sqrt(
181  (a.position.x - b.position.x) * (a.position.x - b.position.x) +
182  (a.position.y - b.position.y) * (a.position.y - b.position.y) +
183  delta_angle * delta_angle);
184 }
185 
186 inline DockDirection getDockDirectionFromString(const std::string & direction)
187 {
188  auto upper_direction = direction;
189  std::transform(
190  upper_direction.begin(), upper_direction.end(), upper_direction.begin(), ::toupper);
191 
192  if (upper_direction == "FORWARD") {
193  return DockDirection::FORWARD;
194  } else if (upper_direction == "BACKWARD") {
195  return DockDirection::BACKWARD;
196  } else {
197  return DockDirection::UNKNOWN;
198  }
199 }
200 
201 } // namespace utils
202 
203 #endif // OPENNAV_DOCKING__UTILS_HPP_
Definition: types.hpp:33