19 #include "std_msgs/msg/color_rgba.hpp"
20 #include "visualization_msgs/msg/marker_array.hpp"
21 #include "visualization_msgs/msg/marker.hpp"
22 #include "geometry_msgs/msg/vector3.hpp"
23 #include "nav2_util/geometry_utils.hpp"
24 #include "nav2_msgs/msg/route.hpp"
25 #include "nav2_route/types.hpp"
26 #include "nav2_costmap_2d/costmap_2d.hpp"
27 #include "nav2_util/line_iterator.hpp"
29 #ifndef NAV2_ROUTE__UTILS_HPP_
30 #define NAV2_ROUTE__UTILS_HPP_
44 inline geometry_msgs::msg::PoseStamped toMsg(
const float x,
const float y)
46 geometry_msgs::msg::PoseStamped pose;
47 pose.pose.position.x = x;
48 pose.pose.position.y = y;
59 inline visualization_msgs::msg::MarkerArray::UniquePtr toMsg(
60 const nav2_route::Graph & graph,
const std::string & frame,
const rclcpp::Time & now)
62 auto msg = std::make_unique<visualization_msgs::msg::MarkerArray>();
64 visualization_msgs::msg::Marker nodes_marker;
65 nodes_marker.header.frame_id = frame;
66 nodes_marker.header.stamp = now;
67 nodes_marker.action = 0;
68 nodes_marker.ns =
"route_graph_nodes";
69 nodes_marker.type = visualization_msgs::msg::Marker::SPHERE_LIST;
70 nodes_marker.scale.x = 0.1;
71 nodes_marker.scale.y = 0.1;
72 nodes_marker.scale.z = 0.1;
73 nodes_marker.color.r = 1.0;
74 nodes_marker.color.a = 1.0;
75 nodes_marker.points.reserve(graph.size());
77 visualization_msgs::msg::Marker edges_marker;
78 edges_marker.header.frame_id = frame;
79 edges_marker.header.stamp = now;
80 edges_marker.action = 0;
81 edges_marker.ns =
"route_graph_edges";
82 edges_marker.type = visualization_msgs::msg::Marker::LINE_LIST;
83 edges_marker.scale.x = 0.05;
84 edges_marker.color.g = 1.0;
85 edges_marker.color.a = 0.5;
86 constexpr
size_t points_per_edge = 2;
88 constexpr
size_t likely_min_edges_per_node = 2;
89 edges_marker.points.reserve(graph.size() * points_per_edge * likely_min_edges_per_node);
91 geometry_msgs::msg::Point node_pos;
92 geometry_msgs::msg::Point edge_start;
93 geometry_msgs::msg::Point edge_end;
95 visualization_msgs::msg::Marker node_id_marker;
96 node_id_marker.header.frame_id = frame;
97 node_id_marker.header.stamp = now;
98 node_id_marker.action = 0;
99 node_id_marker.ns =
"route_graph_node_ids";
100 node_id_marker.type = visualization_msgs::msg::Marker::TEXT_VIEW_FACING;
101 node_id_marker.scale.x = 0.1;
102 node_id_marker.scale.y = 0.1;
103 node_id_marker.scale.z = 0.1;
104 node_id_marker.color.a = 1.0;
105 node_id_marker.color.r = 1.0;
107 visualization_msgs::msg::Marker edge_id_marker;
108 edge_id_marker.header.frame_id = frame;
109 edge_id_marker.header.stamp = now;
110 edge_id_marker.action = 0;
111 edge_id_marker.ns =
"route_graph_edge_ids";
112 edge_id_marker.type = visualization_msgs::msg::Marker::TEXT_VIEW_FACING;
113 edge_id_marker.scale.x = 0.1;
114 edge_id_marker.scale.y = 0.1;
115 edge_id_marker.scale.z = 0.1;
116 edge_id_marker.color.a = 1.0;
117 edge_id_marker.color.g = 1.0;
119 for (
const auto & node : graph) {
120 node_pos.x = node.coords.x;
121 node_pos.y = node.coords.y;
122 nodes_marker.points.push_back(node_pos);
126 node_id_marker.pose.position.x = node.coords.x + 0.07;
127 node_id_marker.pose.position.y = node.coords.y;
128 node_id_marker.text = std::to_string(node.nodeid);
129 msg->markers.push_back(node_id_marker);
131 for (
const auto & neighbor : node.neighbors) {
132 edge_start.x = node.coords.x;
133 edge_start.y = node.coords.y;
134 edge_end.x = neighbor.end->coords.x;
135 edge_end.y = neighbor.end->coords.y;
136 edges_marker.points.push_back(edge_start);
137 edges_marker.points.push_back(edge_end);
140 float y_offset = 0.0;
141 if (node.nodeid > neighbor.end->nodeid) {
146 const float x_offset = 0.07;
150 edge_id_marker.pose.position.x =
151 node.coords.x + ((neighbor.end->coords.x - node.coords.x) / 2.0) + x_offset;
152 edge_id_marker.pose.position.y =
153 node.coords.y + ((neighbor.end->coords.y - node.coords.y) / 2.0) + y_offset;
154 edge_id_marker.text = std::to_string(neighbor.edgeid);
155 msg->markers.push_back(edge_id_marker);
159 msg->markers.push_back(edges_marker);
160 msg->markers.push_back(nodes_marker);
171 inline nav2_msgs::msg::Route toMsg(
172 const nav2_route::Route & route,
const std::string & frame,
const rclcpp::Time & now)
174 nav2_msgs::msg::Route msg;
175 msg.header.frame_id = frame;
176 msg.header.stamp = now;
177 msg.route_cost = route.route_cost;
179 nav2_msgs::msg::RouteNode route_node;
180 nav2_msgs::msg::RouteEdge route_edge;
181 route_node.nodeid = route.start_node->nodeid;
182 route_node.position.x = route.start_node->coords.x;
183 route_node.position.y = route.start_node->coords.y;
184 msg.nodes.push_back(route_node);
187 for (
unsigned int i = 0; i != route.edges.size(); i++) {
188 route_edge.edgeid = route.edges[i]->edgeid;
189 route_edge.start.x = route.edges[i]->start->coords.x;
190 route_edge.start.y = route.edges[i]->start->coords.y;
191 route_edge.end.x = route.edges[i]->end->coords.x;
192 route_edge.end.y = route.edges[i]->end->coords.y;
193 msg.edges.push_back(route_edge);
195 route_node.nodeid = route.edges[i]->end->nodeid;
196 route_node.position.x = route.edges[i]->end->coords.x;
197 route_node.position.y = route.edges[i]->end->coords.y;
198 msg.nodes.push_back(route_node);
212 inline float normalizedDot(
213 const float v1x,
const float v1y,
214 const float v2x,
const float v2y)
216 const float mag1 = std::hypotf(v1x, v1y);
217 const float mag2 = std::hypotf(v2x, v2y);
218 if (mag1 < 1e-6 || mag2 < 1e-6) {
221 return (v1x / mag1) * (v2x / mag2) + (v1y / mag1) * (v2y / mag2);
231 inline Coordinates findClosestPoint(
232 const geometry_msgs::msg::PoseStamped & pose,
233 const Coordinates & start,
const Coordinates & end)
236 const float vx = end.x - start.x;
237 const float vy = end.y - start.y;
238 const float ux = start.x - pose.pose.position.x;
239 const float uy = start.y - pose.pose.position.y;
240 const float uv = vx * ux + vy * uy;
241 const float vv = vx * vx + vy * vy;
248 const float t = -uv / vv;
249 if (t > 0.0 && t < 1.0) {
250 pt.x = (1.0 - t) * start.x + t * end.x;
251 pt.y = (1.0 - t) * start.y + t * end.y;
252 }
else if (t <= 0.0) {
261 inline float distance(
const Coordinates & coords,
const geometry_msgs::msg::PoseStamped & pose)
263 return hypotf(coords.x - pose.pose.position.x, coords.y - pose.pose.position.y);
An ordered set of nodes and edges corresponding to the planned route.