33 #include "rclcpp/executors.hpp"
34 #include "rclcpp/logging.hpp"
35 #include "rclcpp/node.hpp"
36 #include "rclcpp/publisher.hpp"
37 #include "rclcpp/time.hpp"
38 #include "rclcpp/utilities.hpp"
39 #include "sensor_msgs/msg/point_cloud2.hpp"
40 #include "sensor_msgs/point_cloud2_iterator.hpp"
41 #include "nav2_voxel_grid/voxel_grid.hpp"
42 #include "nav2_msgs/msg/voxel_grid.hpp"
43 #include "nav2_util/execution_timer.hpp"
44 #include "nav2_ros_common/lifecycle_node.hpp"
46 static inline void mapToWorld3D(
47 const unsigned int mx,
48 const unsigned int my,
const unsigned int mz,
49 const double origin_x,
const double origin_y,
const double origin_z,
50 const double x_resolution,
const double y_resolution,
51 const double z_resolution,
52 double & wx,
double & wy,
double & wz)
55 wx = origin_x + (mx + 0.5) * x_resolution;
56 wy = origin_y + (my + 0.5) * y_resolution;
57 wz = origin_z + (mz + 0.5) * z_resolution;
65 nav2_voxel_grid::VoxelStatus status;
67 typedef std::vector<Cell> V_Cell;
69 float g_colors_r[] = {0.0f, 0.0f, 1.0f};
70 float g_colors_g[] = {0.0f, 0.0f, 0.0f};
71 float g_colors_b[] = {0.0f, 1.0f, 0.0f};
72 float g_colors_a[] = {0.0f, 0.5f, 1.0f};
77 rclcpp::Node::SharedPtr g_node;
79 rclcpp::Publisher<sensor_msgs::msg::PointCloud2>::SharedPtr pub_marked;
80 rclcpp::Publisher<sensor_msgs::msg::PointCloud2>::SharedPtr pub_unknown;
89 void pointCloud2Helper(
90 std::unique_ptr<sensor_msgs::msg::PointCloud2> & cloud,
91 uint32_t num_channels,
92 std_msgs::msg::Header header,
95 cloud->header = header;
96 cloud->width = num_channels;
98 cloud->is_dense =
true;
99 cloud->is_bigendian =
false;
100 sensor_msgs::PointCloud2Modifier modifier(*cloud);
102 modifier.setPointCloud2Fields(
103 6,
"x", 1, sensor_msgs::msg::PointField::FLOAT32,
104 "y", 1, sensor_msgs::msg::PointField::FLOAT32,
105 "z", 1, sensor_msgs::msg::PointField::FLOAT32,
106 "r", 1, sensor_msgs::msg::PointField::UINT8,
107 "g", 1, sensor_msgs::msg::PointField::UINT8,
108 "b", 1, sensor_msgs::msg::PointField::UINT8);
110 sensor_msgs::PointCloud2Iterator<float> iter_x(*cloud,
"x");
111 sensor_msgs::PointCloud2Iterator<float> iter_y(*cloud,
"y");
112 sensor_msgs::PointCloud2Iterator<float> iter_z(*cloud,
"z");
114 sensor_msgs::PointCloud2Iterator<uint8_t> iter_r(*cloud,
"r");
115 sensor_msgs::PointCloud2Iterator<uint8_t> iter_g(*cloud,
"g");
116 sensor_msgs::PointCloud2Iterator<uint8_t> iter_b(*cloud,
"b");
118 for (uint32_t i = 0; i < num_channels; ++i) {
119 Cell & c = g_cells[i];
124 *iter_r = g_colors_r[c.status] * 255.0;
125 *iter_g = g_colors_g[c.status] * 255.0;
126 *iter_b = g_colors_b[c.status] * 255.0;
137 void voxelCallback(
const nav2_msgs::msg::VoxelGrid::ConstSharedPtr grid)
139 if (grid->data.empty()) {
140 RCLCPP_ERROR(g_node->get_logger(),
"Received empty voxel grid");
147 RCLCPP_DEBUG(g_node->get_logger(),
"Received voxel grid");
148 const std::string frame_id = grid->header.frame_id;
149 const rclcpp::Time stamp = grid->header.stamp;
150 const uint32_t * data = &grid->data.front();
151 const double x_origin = grid->origin.x;
152 const double y_origin = grid->origin.y;
153 const double z_origin = grid->origin.z;
154 const double x_res = grid->resolutions.x;
155 const double y_res = grid->resolutions.y;
156 const double z_res = grid->resolutions.z;
157 const uint32_t x_size = grid->size_x;
158 const uint32_t y_size = grid->size_y;
159 const uint32_t z_size = grid->size_z;
163 uint32_t num_marked = 0;
164 uint32_t num_unknown = 0;
165 for (uint32_t y_grid = 0; y_grid < y_size; ++y_grid) {
166 for (uint32_t x_grid = 0; x_grid < x_size; ++x_grid) {
167 for (uint32_t z_grid = 0; z_grid < z_size; ++z_grid) {
168 nav2_voxel_grid::VoxelStatus status =
169 nav2_voxel_grid::VoxelGrid::getVoxel(
171 z_grid, x_size, y_size, z_size, data);
172 if (status == nav2_voxel_grid::UNKNOWN) {
176 x_grid, y_grid, z_grid, x_origin, y_origin,
177 z_origin, x_res, y_res, z_res, c.x, c.y, c.z);
179 g_unknown.push_back(c);
182 }
else if (status == nav2_voxel_grid::MARKED) {
186 x_grid, y_grid, z_grid, x_origin, y_origin,
187 z_origin, x_res, y_res, z_res, c.x, c.y, c.z);
189 g_marked.push_back(c);
197 std_msgs::msg::Header pcl_header;
198 pcl_header.frame_id = frame_id;
199 pcl_header.stamp = stamp;
202 auto cloud = std::make_unique<sensor_msgs::msg::PointCloud2>();
203 pointCloud2Helper(cloud, num_marked, pcl_header, g_marked);
204 pub_marked->publish(std::move(cloud));
208 auto cloud = std::make_unique<sensor_msgs::msg::PointCloud2>();
209 pointCloud2Helper(cloud, num_unknown, pcl_header, g_unknown);
210 pub_unknown->publish(std::move(cloud));
215 g_node->get_logger(),
"Published %d points in %f seconds",
219 int main(
int argc,
char ** argv)
221 rclcpp::init(argc, argv);
222 g_node = rclcpp::Node::make_shared(
"costmap_2d_cloud");
224 RCLCPP_DEBUG(g_node->get_logger(),
"Starting up costmap_2d_cloud");
226 pub_marked = g_node->create_publisher<sensor_msgs::msg::PointCloud2>(
228 pub_unknown = g_node->create_publisher<sensor_msgs::msg::PointCloud2>(
230 auto sub = g_node->create_subscription<nav2_msgs::msg::VoxelGrid>(
233 rclcpp::spin(g_node->get_node_base_interface());
A QoS profile for standard reliable topics with a history of 10 messages.
Measures execution time of code between calls to start and end.
void start()
Call just prior to code you want to measure.
double elapsed_time_in_seconds()
Extract the measured time as a floating point number of seconds.
void end()
Call just after the code you want to measure.