39 #include "nav2_costmap_2d/costmap_2d_publisher.hpp"
40 #include "nav2_costmap_2d/costmap_layer.hpp"
46 #include "nav2_costmap_2d/cost_values.hpp"
51 char * Costmap2DPublisher::cost_translation_table_ = NULL;
54 const nav2::LifecycleNode::WeakPtr & parent,
56 std::string global_frame,
57 std::string topic_name,
58 bool always_send_full_costmap,
61 global_frame_(global_frame),
62 topic_name_(topic_name),
63 always_send_full_costmap_(always_send_full_costmap),
66 auto node = parent.lock();
67 clock_ = node->get_clock();
68 logger_ = node->get_logger();
70 auto matched_callback = [
this](rclcpp::MatchedInfo & status) {
71 if (status.total_count_change > 0) {
72 republish_costmap_ =
true;
75 costmap_pub_ = node->create_publisher<nav_msgs::msg::OccupancyGrid>(
78 costmap_raw_pub_ = node->create_publisher<nav2_msgs::msg::Costmap>(
81 costmap_update_pub_ = node->create_publisher<map_msgs::msg::OccupancyGridUpdate>(
83 costmap_raw_update_pub_ = node->create_publisher<nav2_msgs::msg::CostmapUpdate>(
87 costmap_service_ = node->create_service<nav2_msgs::srv::GetCostmap>(
88 std::string(
"get_") + topic_name,
90 &Costmap2DPublisher::costmap_service_callback,
this,
91 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
93 if (cost_translation_table_ == NULL) {
94 cost_translation_table_ =
new char[256];
97 cost_translation_table_[0] = 0;
98 cost_translation_table_[253] = 99;
99 cost_translation_table_[254] = 100;
100 cost_translation_table_[255] = -1;
104 for (
int i = 1; i < 253; i++) {
105 cost_translation_table_[i] =
static_cast<char>(1 + (97 * (i - 1)) / 251);
116 void Costmap2DPublisher::updateGridParams()
126 void Costmap2DPublisher::prepareGrid()
128 std::unique_lock<Costmap2D::mutex_t> lock(*(costmap_->getMutex()));
130 grid_ = std::make_unique<nav_msgs::msg::OccupancyGrid>();
132 grid_->header.frame_id = global_frame_;
133 grid_->header.stamp = clock_->now();
135 grid_->info.resolution = grid_resolution_;
137 grid_->info.width = grid_width_;
138 grid_->info.height = grid_height_;
142 grid_->info.origin.position.x = wx - grid_resolution_ / 2;
143 grid_->info.origin.position.y = wy - grid_resolution_ / 2;
144 grid_->info.origin.position.z = map_vis_z_;
145 grid_->info.origin.orientation.w = 1.0;
147 grid_->data.resize(grid_->info.width * grid_->info.height);
149 unsigned char * data = costmap_->
getCharMap();
151 data, data + grid_->data.size(), grid_->data.begin(),
152 [](
unsigned char c) {return cost_translation_table_[c];});
155 void Costmap2DPublisher::prepareCostmap()
157 std::unique_lock<Costmap2D::mutex_t> lock(*(costmap_->getMutex()));
160 costmap_raw_ = std::make_unique<nav2_msgs::msg::Costmap>();
162 costmap_raw_->header.frame_id = global_frame_;
163 costmap_raw_->header.stamp = clock_->now();
165 costmap_raw_->metadata.layer =
"master";
166 costmap_raw_->metadata.resolution = resolution;
173 costmap_raw_->metadata.origin.position.x = wx - resolution / 2;
174 costmap_raw_->metadata.origin.position.y = wy - resolution / 2;
175 costmap_raw_->metadata.origin.position.z = 0.0;
176 costmap_raw_->metadata.origin.orientation.w = 1.0;
178 costmap_raw_->data.resize(costmap_raw_->metadata.size_x * costmap_raw_->metadata.size_y);
180 unsigned char * data = costmap_->
getCharMap();
181 memcpy(costmap_raw_->data.data(), data, costmap_raw_->data.size());
184 std::unique_ptr<map_msgs::msg::OccupancyGridUpdate> Costmap2DPublisher::createGridUpdateMsg()
186 auto update = std::make_unique<map_msgs::msg::OccupancyGridUpdate>();
188 update->header.stamp = clock_->now();
189 update->header.frame_id = global_frame_;
192 update->width = xn_ - x0_;
193 update->height = yn_ - y0_;
194 update->data.resize(update->width * update->height);
196 unsigned char * costmap_data = costmap_->
getCharMap();
198 for (std::uint32_t y = y0_; y < yn_; y++) {
199 std::uint32_t row_start = y * map_width + x0_;
201 costmap_data + row_start, costmap_data + row_start + update->width,
202 update->data.begin() + i,
203 [](
unsigned char c) {return cost_translation_table_[c];});
209 std::unique_ptr<nav2_msgs::msg::CostmapUpdate> Costmap2DPublisher::createCostmapUpdateMsg()
211 auto msg = std::make_unique<nav2_msgs::msg::CostmapUpdate>();
213 msg->header.stamp = clock_->now();
214 msg->header.frame_id = global_frame_;
217 msg->size_x = xn_ - x0_;
218 msg->size_y = yn_ - y0_;
219 msg->data.resize(msg->size_x * msg->size_y);
221 unsigned char * costmap_data = costmap_->
getCharMap();
224 for (std::uint32_t y = y0_; y < yn_; y++) {
225 std::uint32_t row_start = y * map_width + x0_;
226 std::copy_n(costmap_data + row_start, msg->size_x, msg->data.begin() + i);
234 auto const costmap_layer =
dynamic_cast<CostmapLayer *
>(costmap_);
235 if (costmap_layer !=
nullptr && !costmap_layer->isEnabled()) {
239 const bool republish = republish_costmap_.exchange(
false);
241 if (always_send_full_costmap_ || grid_resolution_ != resolution ||
246 !costmap_published_once_ || republish)
249 if (costmap_pub_->get_subscription_count() > 0 || !costmap_published_once_) {
251 costmap_pub_->publish(std::move(grid_));
253 if (costmap_raw_pub_->get_subscription_count() > 0 || !costmap_published_once_) {
255 costmap_raw_pub_->publish(std::move(costmap_raw_));
257 costmap_published_once_ =
true;
258 }
else if (x0_ < xn_) {
260 std::unique_lock<Costmap2D::mutex_t> lock(*(costmap_->getMutex()));
261 if (costmap_update_pub_->get_subscription_count() > 0) {
262 costmap_update_pub_->publish(createGridUpdateMsg());
264 if (costmap_raw_update_pub_->get_subscription_count() > 0) {
265 costmap_raw_update_pub_->publish(createCostmapUpdateMsg());
275 Costmap2DPublisher::costmap_service_callback(
276 const std::shared_ptr<rmw_request_id_t>,
277 const std::shared_ptr<nav2_msgs::srv::GetCostmap::Request>,
278 const std::shared_ptr<nav2_msgs::srv::GetCostmap::Response> response)
280 RCLCPP_DEBUG(logger_,
"Received costmap service request");
283 tf2::Quaternion quaternion;
284 quaternion.setRPY(0.0, 0.0, 0.0);
286 std::unique_lock<Costmap2D::mutex_t> lock(*(costmap_->getMutex()));
290 auto data_length = size_x * size_y;
291 unsigned char * data = costmap_->
getCharMap();
292 auto current_time = clock_->now();
294 response->map.header.stamp = current_time;
295 response->map.header.frame_id = global_frame_;
296 response->map.metadata.size_x = size_x;
297 response->map.metadata.size_y = size_y;
298 response->map.metadata.resolution = costmap_->
getResolution();
299 response->map.metadata.layer =
"master";
300 response->map.metadata.map_load_time = current_time;
301 response->map.metadata.update_time = current_time;
302 response->map.metadata.origin.position.x = costmap_->
getOriginX();
303 response->map.metadata.origin.position.y = costmap_->
getOriginY();
304 response->map.metadata.origin.position.z = 0.0;
305 response->map.metadata.origin.orientation = tf2::toMsg(quaternion);
306 response->map.data.resize(data_length);
307 response->map.data.assign(data, data + data_length);
A QoS profile for latched, reliable topics with a history of 1 messages.
~Costmap2DPublisher()
Destructor.
Costmap2DPublisher(const nav2::LifecycleNode::WeakPtr &parent, Costmap2D *costmap, std::string global_frame, std::string topic_name, bool always_send_full_costmap=false, double map_vis_z=0.0)
Constructor for the Costmap2DPublisher.
void publishCostmap()
Publishes the visualization data over ROS.
A 2D costmap provides a mapping between points in the world and their associated "costs".
void mapToWorld(unsigned int mx, unsigned int my, double &wx, double &wy) const
Convert from map coordinates to world coordinates.
unsigned char * getCharMap() const
Will return a pointer to the underlying unsigned char array used as the costmap.
double getResolution() const
Accessor for the resolution of the costmap.
unsigned int getSizeInCellsX() const
Accessor for the x size of the costmap in cells.
double getOriginY() const
Accessor for the y origin of the costmap.
unsigned int getSizeInCellsY() const
Accessor for the y size of the costmap in cells.
double getOriginX() const
Accessor for the x origin of the costmap.
A costmap layer base class for costmap plugin layers. Rather than just a layer, this object also cont...