35 #include "dwb_core/publisher.hpp"
43 #include "sensor_msgs/point_cloud2_iterator.hpp"
44 #include "nav_2d_utils/conversions.hpp"
45 #include "sensor_msgs/msg/point_cloud2.hpp"
46 #include "visualization_msgs/msg/marker_array.hpp"
47 #include "visualization_msgs/msg/marker.hpp"
55 DWBPublisher::DWBPublisher(
56 const nav2::LifecycleNode::WeakPtr & parent,
57 const std::string & plugin_name)
59 plugin_name_(plugin_name)
61 auto node = node_.lock();
62 clock_ = node->get_clock();
66 DWBPublisher::on_configure()
68 auto node = node_.lock();
70 throw std::runtime_error{
"Failed to lock node"};
73 publish_evaluation_ = node->declare_or_get_parameter(
74 plugin_name_ +
".publish_evaluation",
true);
75 publish_local_plan_ = node->declare_or_get_parameter(
76 plugin_name_ +
".publish_local_plan",
true);
77 publish_trajectories_ = node->declare_or_get_parameter(
78 plugin_name_ +
".publish_trajectories",
true);
79 publish_cost_grid_pc_ = node->declare_or_get_parameter(
80 plugin_name_ +
".publish_cost_grid_pc",
false);
81 double marker_lifetime = node->declare_or_get_parameter(
82 plugin_name_ +
".marker_lifetime", 0.1);
83 marker_lifetime_ = rclcpp::Duration::from_seconds(marker_lifetime);
85 eval_pub_ = node->create_publisher<dwb_msgs::msg::LocalPlanEvaluation>(
"evaluation");
86 local_pub_ = node->create_publisher<nav_msgs::msg::Path>(
"local_plan");
87 marker_pub_ = node->create_publisher<visualization_msgs::msg::MarkerArray>(
"marker");
88 cost_grid_pc_pub_ = node->create_publisher<sensor_msgs::msg::PointCloud2>(
"cost_cloud");
90 return nav2::CallbackReturn::SUCCESS;
94 DWBPublisher::on_activate()
96 eval_pub_->on_activate();
97 local_pub_->on_activate();
98 marker_pub_->on_activate();
99 cost_grid_pc_pub_->on_activate();
101 return nav2::CallbackReturn::SUCCESS;
105 DWBPublisher::on_deactivate()
107 eval_pub_->on_deactivate();
108 local_pub_->on_deactivate();
109 marker_pub_->on_deactivate();
110 cost_grid_pc_pub_->on_deactivate();
112 return nav2::CallbackReturn::SUCCESS;
116 DWBPublisher::on_cleanup()
121 cost_grid_pc_pub_.reset();
123 return nav2::CallbackReturn::SUCCESS;
127 DWBPublisher::publishEvaluation(std::shared_ptr<dwb_msgs::msg::LocalPlanEvaluation> results)
130 if (publish_evaluation_ && eval_pub_->get_subscription_count() > 0) {
131 auto msg = std::make_unique<dwb_msgs::msg::LocalPlanEvaluation>(*results);
132 eval_pub_->publish(std::move(msg));
134 publishTrajectories(*results);
139 DWBPublisher::publishTrajectories(
const dwb_msgs::msg::LocalPlanEvaluation & results)
141 if (marker_pub_->get_subscription_count() < 1) {
return;}
143 if (!publish_trajectories_) {
return;}
144 auto ma = std::make_unique<visualization_msgs::msg::MarkerArray>();
145 visualization_msgs::msg::Marker m;
147 if (results.twists.size() == 0) {
return;}
149 geometry_msgs::msg::Point pt;
151 m.header = results.header;
152 m.type = m.LINE_STRIP;
153 m.pose.orientation.w = 1;
156 m.lifetime = marker_lifetime_;
158 double best_cost = results.twists[results.best_index].total;
159 double worst_cost = results.twists[results.worst_index].total;
160 double denominator = worst_cost - best_cost;
162 if (std::fabs(denominator) < 1e-9) {
166 unsigned currentValidId = 0;
167 unsigned currentInvalidId = 0;
168 string validNamespace(
"ValidTrajectories");
169 string invalidNamespace(
"InvalidTrajectories");
170 for (
unsigned int i = 0; i < results.twists.size(); i++) {
171 const dwb_msgs::msg::TrajectoryScore & twist = results.twists[i];
172 double displayLevel = (twist.total - best_cost) / denominator;
173 if (twist.total >= 0) {
174 m.color.r = displayLevel;
175 m.color.g = 1.0 - displayLevel;
178 m.ns = validNamespace;
179 m.id = currentValidId;
186 m.ns = invalidNamespace;
187 m.id = currentInvalidId;
191 for (
unsigned int j = 0; j < twist.traj.poses.size(); ++j) {
192 pt.x = twist.traj.poses[j].position.x;
193 pt.y = twist.traj.poses[j].position.y;
195 m.points.push_back(pt);
197 ma->markers.push_back(m);
199 marker_pub_->publish(std::move(ma));
203 DWBPublisher::publishLocalPlan(
204 const std_msgs::msg::Header & header,
205 const dwb_msgs::msg::Trajectory2D & traj)
207 if (!publish_local_plan_) {
return;}
210 std::make_unique<nav_msgs::msg::Path>(
211 nav_2d_utils::posesToPath(
212 traj.poses, header.frame_id,
215 if (local_pub_->get_subscription_count() > 0) {
216 local_pub_->publish(std::move(path));
221 DWBPublisher::publishCostGrid(
222 const std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap_ros,
223 const std::vector<TrajectoryCritic::Ptr> critics)
225 if (cost_grid_pc_pub_->get_subscription_count() < 1) {
return;}
227 if (!publish_cost_grid_pc_) {
return;}
229 auto cost_grid_pc = std::make_unique<sensor_msgs::msg::PointCloud2>();
230 cost_grid_pc->header.frame_id = costmap_ros->getGlobalFrameID();
231 cost_grid_pc->header.stamp = clock_->now();
234 double x_coord, y_coord;
238 std::vector<std::pair<std::string, std::vector<float>>> cost_channels;
239 std::vector<float> total_cost(size_x * size_y, 0.0);
241 for (TrajectoryCritic::Ptr critic : critics) {
242 unsigned int channel_index = cost_channels.size();
243 critic->addCriticVisualization(cost_channels);
244 if (channel_index == cost_channels.size()) {
248 double scale = critic->getScale();
249 for (
unsigned int i = 0; i < size_x * size_y; i++) {
250 total_cost[i] += cost_channels[channel_index].second[i] * scale;
254 cost_channels.push_back(std::make_pair(
"total_cost", total_cost));
256 cost_grid_pc->width = size_x * size_y;
257 cost_grid_pc->height = 1;
258 cost_grid_pc->fields.resize(3 + cost_channels.size());
259 cost_grid_pc->is_dense =
true;
260 cost_grid_pc->is_bigendian =
false;
263 for (
size_t i = 0; i < cost_grid_pc->fields.size(); ++i, offset += 4) {
264 cost_grid_pc->fields[i].offset = offset;
265 cost_grid_pc->fields[i].count = 1;
266 cost_grid_pc->fields[i].datatype = sensor_msgs::msg::PointField::FLOAT32;
268 cost_grid_pc->fields[i].name = cost_channels[i - 3].first;
272 cost_grid_pc->fields[0].name =
"x";
273 cost_grid_pc->fields[1].name =
"y";
274 cost_grid_pc->fields[2].name =
"z";
276 cost_grid_pc->point_step = offset;
277 cost_grid_pc->row_step = cost_grid_pc->point_step * cost_grid_pc->width;
278 cost_grid_pc->data.resize(cost_grid_pc->row_step * cost_grid_pc->height);
280 std::vector<sensor_msgs::PointCloud2Iterator<float>> cost_grid_pc_iter;
282 for (
size_t i = 0; i < cost_grid_pc->fields.size(); ++i) {
283 sensor_msgs::PointCloud2Iterator<float> iter(*cost_grid_pc, cost_grid_pc->fields[i].name);
284 cost_grid_pc_iter.push_back(iter);
288 for (
unsigned int cy = 0; cy < size_y; cy++) {
289 for (
unsigned int cx = 0; cx < size_x; cx++) {
290 costmap->
mapToWorld(cx, cy, x_coord, y_coord);
291 *cost_grid_pc_iter[0] = x_coord;
292 *cost_grid_pc_iter[1] = y_coord;
293 *cost_grid_pc_iter[2] = 0.0;
295 for (
size_t i = 3; i < cost_grid_pc_iter.size(); ++i) {
296 *cost_grid_pc_iter[i] = cost_channels[i - 3].second[j];
297 ++cost_grid_pc_iter[i];
299 ++cost_grid_pc_iter[0];
300 ++cost_grid_pc_iter[1];
301 ++cost_grid_pc_iter[2];
306 cost_grid_pc_pub_->publish(std::move(cost_grid_pc));
310 DWBPublisher::publishLocalPlan(
const nav_msgs::msg::Path plan)
312 publishGenericPlan(plan, *local_pub_, publish_local_plan_);
316 DWBPublisher::publishGenericPlan(
317 const nav_msgs::msg::Path plan,
318 rclcpp::Publisher<nav_msgs::msg::Path> & pub,
bool flag)
320 if (pub.get_subscription_count() < 1) {
return;}
322 auto path = std::make_unique<nav_msgs::msg::Path>(plan);
323 pub.publish(std::move(path));
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 int getSizeInCellsX() const
Accessor for the x size of the costmap in cells.
unsigned int getSizeInCellsY() const
Accessor for the y size of the costmap in cells.