15 #include "nav2_map_server/vector_object_shapes.hpp"
17 #include <uuid/uuid.h>
24 #include "geometry_msgs/msg/pose_stamped.hpp"
26 #include "nav2_util/occ_grid_utils.hpp"
27 #include "nav2_util/occ_grid_values.hpp"
28 #include "nav2_util/geometry_utils.hpp"
29 #include "nav2_util/raytrace_line_2d.hpp"
30 #include "nav2_util/robot_utils.hpp"
31 #include "nav2_ros_common/tf2_factories.hpp"
33 namespace nav2_map_server
39 : type_(UNKNOWN), node_(node)
52 auto node =
node_.lock();
54 throw std::runtime_error{
"Failed to lock node"};
59 std::string uuid_str = nav2::declare_or_get_parameter<std::string>(
60 node, shape_name +
".uuid");
61 if (uuid_parse(uuid_str.c_str(), out_uuid) != 0) {
64 "[%s] Can not parse UUID string for shape: %s",
65 shape_name.c_str(), uuid_str.c_str());
68 }
catch (
const std::exception &) {
70 uuid_generate(out_uuid);
73 uuid_unparse(out_uuid, uuid_str);
76 "[%s] No UUID is specified for shape. Generating a new one: %s",
77 shape_name.c_str(), uuid_str);
86 const nav2::LifecycleNode::WeakPtr & node)
99 return params_->header.frame_id;
104 return unparseUUID(
params_->uuid.uuid.data());
109 return uuid_compare(
params_->uuid.uuid.data(), uuid) == 0;
119 auto node =
node_.lock();
121 throw std::runtime_error{
"Failed to lock node"};
125 params_ = std::make_shared<nav2_msgs::msg::PolygonObject>();
128 polygon_ = std::make_shared<geometry_msgs::msg::Polygon>();
131 params_->header.frame_id = nav2::declare_or_get_parameter(
132 node, shape_name +
".frame_id", std::string{
"map"});
133 params_->value = nav2::declare_or_get_parameter(
134 node, shape_name +
".value",
static_cast<int>(nav2_util::OCC_GRID_OCCUPIED));
135 params_->closed = nav2::declare_or_get_parameter(
136 node, shape_name +
".closed",
true);
138 std::vector<double> poly_row;
140 poly_row = nav2::declare_or_get_parameter<std::vector<double>>(
141 node, shape_name +
".points");
142 }
catch (
const std::exception & ex) {
145 "[%s] Error while getting polygon parameters: %s",
146 shape_name.c_str(), ex.what());
150 if (poly_row.size() < 6 || poly_row.size() % 2 != 0) {
153 "[%s] Polygon has incorrect points description",
159 geometry_msgs::msg::Point32 point;
161 for (
double val : poly_row) {
166 params_->points.push_back(point);
188 polygon_ = std::make_shared<geometry_msgs::msg::Polygon>();
193 if (uuid_is_null(
params_->uuid.uuid.data())) {
194 uuid_generate(
params_->uuid.uuid.data());
201 const std::string & to_frame,
202 const nav2::TransformBuffer::SharedPtr tf_buffer,
203 const double transform_tolerance)
205 geometry_msgs::msg::PoseStamped from_pose, to_pose;
206 from_pose.header =
params_->header;
207 for (
unsigned int i = 0; i <
params_->points.size(); i++) {
208 from_pose.pose.position.x =
params_->points[i].x;
209 from_pose.pose.position.y =
params_->points[i].y;
210 from_pose.pose.position.z =
params_->points[i].z;
212 nav2_util::transformPoseInTargetFrame(
213 from_pose, to_pose, *tf_buffer, to_frame, transform_tolerance))
215 polygon_->points[i].x = to_pose.pose.position.x;
216 polygon_->points[i].y = to_pose.pose.position.y;
217 polygon_->points[i].z = to_pose.pose.position.z;
228 min_x = std::numeric_limits<double>::max();
229 min_y = std::numeric_limits<double>::max();
230 max_x = std::numeric_limits<double>::lowest();
231 max_y = std::numeric_limits<double>::lowest();
233 for (
auto point :
polygon_->points) {
234 min_x = std::min(min_x,
static_cast<double>(point.x));
235 min_y = std::min(min_y,
static_cast<double>(point.y));
236 max_x = std::max(max_x,
static_cast<double>(point.x));
237 max_y = std::max(max_y,
static_cast<double>(point.y));
243 return nav2_util::geometry_utils::isPointInsidePolygon(px, py,
polygon_->points);
247 nav_msgs::msg::OccupancyGrid::SharedPtr map,
const OverlayType overlay_type)
249 unsigned int mx0, my0, mx1, my1;
251 auto node =
node_.lock();
253 throw std::runtime_error{
"Failed to lock node"};
256 if (!nav2_util::worldToMap(map,
polygon_->points[0].x,
polygon_->points[0].y, mx1, my1)) {
259 "[UUID: %s] Can not convert (%f, %f) point to map",
265 for (
unsigned int i = 1; i <
polygon_->points.size(); i++) {
268 if (!nav2_util::worldToMap(map,
polygon_->points[i].x,
polygon_->points[i].y, mx1, my1)) {
271 "[UUID: %s] Can not convert (%f, %f) point to map",
275 nav2_util::raytraceLine(ma, mx0, my0, mx1, my1, map->info.width);
281 if (
params_->points.size() < 3) {
282 auto node =
node_.lock();
284 throw std::runtime_error{
"Failed to lock node"};
289 "[UUID: %s] Polygon has incorrect number of vertices: %li",
300 const nav2::LifecycleNode::WeakPtr & node)
313 return params_->header.frame_id;
318 return unparseUUID(
params_->uuid.uuid.data());
323 return uuid_compare(
params_->uuid.uuid.data(), uuid) == 0;
333 auto node =
node_.lock();
335 throw std::runtime_error{
"Failed to lock node"};
339 params_ = std::make_shared<nav2_msgs::msg::CircleObject>();
342 center_ = std::make_shared<geometry_msgs::msg::Point32>();
345 params_->header.frame_id = nav2::declare_or_get_parameter(
346 node, shape_name +
".frame_id", std::string{
"map"});
347 params_->value = nav2::declare_or_get_parameter(
348 node, shape_name +
".value",
static_cast<int>(nav2_util::OCC_GRID_OCCUPIED));
349 params_->fill = nav2::declare_or_get_parameter(
350 node, shape_name +
".fill",
true);
352 std::vector<double> center_row;
354 center_row = nav2::declare_or_get_parameter<std::vector<double>>(
355 node, shape_name +
".center");
356 params_->radius = nav2::declare_or_get_parameter<double>(
357 node, shape_name +
".radius");
361 "[%s] Circle has incorrect radius less than zero",
365 }
catch (
const std::exception & ex) {
368 "[%s] Error while getting circle parameters: %s",
369 shape_name.c_str(), ex.what());
373 if (center_row.size() != 2) {
376 "[%s] Circle has incorrect center description",
382 params_->center.x = center_row[0];
383 params_->center.y = center_row[1];
401 center_ = std::make_shared<geometry_msgs::msg::Point32>();
406 if (uuid_is_null(
params_->uuid.uuid.data())) {
407 uuid_generate(
params_->uuid.uuid.data());
414 const std::string & to_frame,
415 const nav2::TransformBuffer::SharedPtr tf_buffer,
416 const double transform_tolerance)
418 geometry_msgs::msg::PoseStamped from_pose, to_pose;
419 from_pose.header =
params_->header;
420 from_pose.pose.position.x =
params_->center.x;
421 from_pose.pose.position.y =
params_->center.y;
422 from_pose.pose.position.z =
params_->center.z;
424 nav2_util::transformPoseInTargetFrame(
425 from_pose, to_pose, *tf_buffer, to_frame, transform_tolerance))
427 center_->x = to_pose.pose.position.x;
428 center_->y = to_pose.pose.position.y;
429 center_->z = to_pose.pose.position.z;
452 nav_msgs::msg::OccupancyGrid::SharedPtr map,
const OverlayType overlay_type)
454 unsigned int mcx, mcy;
464 const int r =
static_cast<int>(std::round(
params_->radius / map->info.resolution));
474 putPoint(mcx + x, mcy + y, map, overlay_type);
475 putPoint(mcx + y, mcy + x, map, overlay_type);
476 putPoint(mcx - x + 1, mcy + y, map, overlay_type);
477 putPoint(mcx + y, mcy - x + 1, map, overlay_type);
478 putPoint(mcx - x + 1, mcy - y + 1, map, overlay_type);
479 putPoint(mcx - y + 1, mcy - x + 1, map, overlay_type);
480 putPoint(mcx + x, mcy - y + 1, map, overlay_type);
481 putPoint(mcx - y + 1, mcy + x, map, overlay_type);
493 putPoint(mcx + x, mcy + y, map, overlay_type);
494 putPoint(mcx - x + 1, mcy + y, map, overlay_type);
495 putPoint(mcx - x + 1, mcy - y + 1, map, overlay_type);
496 putPoint(mcx + x, mcy - y + 1, map, overlay_type);
503 auto node =
node_.lock();
505 throw std::runtime_error{
"Failed to lock node"};
510 "[UUID: %s] Circle has incorrect radius less than zero",
518 nav_msgs::msg::OccupancyGrid::ConstSharedPtr map,
519 unsigned int & mcx,
unsigned int & mcy)
521 auto node =
node_.lock();
523 throw std::runtime_error{
"Failed to lock node"};
527 if (
center_->x < map->info.origin.position.x ||
center_->y < map->info.origin.position.y) {
530 "[UUID: %s] Can not convert (%f, %f) circle center to map",
537 mcx =
static_cast<unsigned int>(
538 std::round((
center_->x - map->info.origin.position.x) / map->info.resolution)) - 1;
539 mcy =
static_cast<unsigned int>(
540 std::round((
center_->y - map->info.origin.position.y) / map->info.resolution)) - 1;
541 if (mcx >= map->info.width || mcy >= map->info.height) {
544 "[UUID: %s] Can not convert (%f, %f) point to map",
553 unsigned int mx,
unsigned int my,
554 nav_msgs::msg::OccupancyGrid::SharedPtr map,
555 const OverlayType overlay_type)
557 processCell(map, my * map->info.width + mx,
params_->value, overlay_type);
bool isUUID(const unsigned char *uuid) const
Checks whether the shape is equal to a given UUID.
int8_t getValue() const
Gets the value of the shape.
bool toFrame(const std::string &to_frame, const nav2::TransformBuffer::SharedPtr tf_buffer, const double transform_tolerance)
Transforms shape coordinates to a new frame.
void putPoint(unsigned int mx, unsigned int my, nav_msgs::msg::OccupancyGrid::SharedPtr map, const OverlayType overlay_type)
Put Circle's point on map.
bool isPointInside(const double px, const double py) const
Is the point inside the shape.
std::string getUUID() const
Gets UUID of the shape.
void getBoundaries(double &min_x, double &min_y, double &max_x, double &max_y)
Gets shape box-boundaries.
std::string getFrameID() const
Gets frame ID of the shape.
bool centerToMap(nav_msgs::msg::OccupancyGrid::ConstSharedPtr map, unsigned int &mcx, unsigned int &mcy)
Converts circle center to map coordinates considering FP-accuracy losing on small values when using c...
bool isFill() const
Whether the shape to be filled or only its borders to be put on map.
nav2_msgs::msg::CircleObject::SharedPtr params_
Input circle parameters (could be in any frame)
bool setParams(const nav2_msgs::msg::CircleObject::SharedPtr params)
Tries to update Circle parameters.
void putBorders(nav_msgs::msg::OccupancyGrid::SharedPtr map, const OverlayType overlay_type)
Puts shape borders on map.
nav2_msgs::msg::CircleObject::SharedPtr getParams() const
Gets Circle parameters.
bool checkConsistency()
Checks that shape is consistent for further operation.
geometry_msgs::msg::Point32::SharedPtr center_
Circle center in the map's frame.
bool obtainParams(const std::string &shape_name)
Supporting routine obtaining ROS-parameters for the given vector object.
Functor class used in raytraceLine algorithm.
std::string getUUID() const
Gets UUID of the shape.
void getBoundaries(double &min_x, double &min_y, double &max_x, double &max_y)
Gets shape box-boundaries.
void putBorders(nav_msgs::msg::OccupancyGrid::SharedPtr map, const OverlayType overlay_type)
Puts shape borders on map.
bool toFrame(const std::string &to_frame, const nav2::TransformBuffer::SharedPtr tf_buffer, const double transform_tolerance)
Transforms shape coordinates to a new frame.
bool isUUID(const unsigned char *uuid) const
Checks whether the shape is equal to a given UUID.
nav2_msgs::msg::PolygonObject::SharedPtr getParams() const
Gets Polygon parameters.
int8_t getValue() const
Gets the value of the shape.
bool setParams(const nav2_msgs::msg::PolygonObject::SharedPtr params)
Tries to update Polygon parameters.
std::string getFrameID() const
Gets frame ID of the shape.
nav2_msgs::msg::PolygonObject::SharedPtr params_
Input polygon parameters (could be in any frame)
bool checkConsistency()
Checks that shape is consistent for further operation.
bool isPointInside(const double px, const double py) const
Is the point inside the shape.
bool isFill() const
Whether the shape to be filled or only its borders to be put on map.
bool obtainParams(const std::string &shape_name)
Supporting routine obtaining ROS-parameters for the given vector object.
geometry_msgs::msg::Polygon::SharedPtr polygon_
Polygon in the map's frame.
Basic class, other vector objects to be inherited from.
bool obtainShapeUUID(const std::string &shape_name, unsigned char *out_uuid)
Supporting routine obtaining shape UUID from ROS-parameters for the given shape object.
ShapeType type_
Type of shape.
ShapeType getType()
Returns type of the shape.
nav2::LifecycleNode::WeakPtr node_
VectorObjectServer node.
virtual ~Shape()
Shape destructor.
Shape(const nav2::LifecycleNode::WeakPtr &node)
Shape basic class constructor.