Skip to content

Commit 3d1593c

Browse files
committed
perf: performance tuning
1 parent 758b425 commit 3d1593c

File tree

7 files changed

+219
-81
lines changed

7 files changed

+219
-81
lines changed

perception/probabilistic_occupancy_grid_map/include/probabilistic_occupancy_grid_map/pointcloud_based_occupancy_grid_map/occupancy_grid_map_base.hpp

+7
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,18 @@ class OccupancyGridMapInterface : public nav2_costmap_2d::Costmap2D
8383

8484
virtual void initRosParam(rclcpp::Node & node) = 0;
8585

86+
void setHeightLimit(const double min_height, const double max_height);
87+
88+
double min_height_ = -std::numeric_limits<double>::infinity();
89+
double max_height_ = std::numeric_limits<double>::infinity();
90+
8691
private:
8792
bool worldToMap(double wx, double wy, unsigned int & mx, unsigned int & my) const;
8893

8994
rclcpp::Logger logger_{rclcpp::get_logger("pointcloud_based_occupancy_grid_map")};
9095
rclcpp::Clock clock_{RCL_ROS_TIME};
96+
97+
double resolution_inv_;
9198
};
9299

93100
} // namespace costmap_2d

perception/probabilistic_occupancy_grid_map/include/probabilistic_occupancy_grid_map/pointcloud_based_occupancy_grid_map/pointcloud_based_occupancy_grid_map_node.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class PointcloudBasedOccupancyGridMapNode : public rclcpp::Node
5555
{
5656
public:
5757
explicit PointcloudBasedOccupancyGridMapNode(const rclcpp::NodeOptions & node_options);
58+
~PointcloudBasedOccupancyGridMapNode();
5859

5960
private:
6061
void onPointcloudWithObstacleAndRaw(

perception/probabilistic_occupancy_grid_map/src/pointcloud_based_occupancy_grid_map/occupancy_grid_map_base.cpp

+10-3
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,18 @@ OccupancyGridMapInterface::OccupancyGridMapInterface(
7777
const unsigned int cells_size_x, const unsigned int cells_size_y, const float resolution)
7878
: Costmap2D(cells_size_x, cells_size_y, resolution, 0.f, 0.f, occupancy_cost_value::NO_INFORMATION)
7979
{
80+
resolution_inv_ = 1.0 / resolution_;
8081
}
8182

82-
bool OccupancyGridMapInterface::worldToMap(
83+
inline bool OccupancyGridMapInterface::worldToMap(
8384
double wx, double wy, unsigned int & mx, unsigned int & my) const
8485
{
8586
if (wx < origin_x_ || wy < origin_y_) {
8687
return false;
8788
}
8889

89-
mx = static_cast<int>(std::floor((wx - origin_x_) / resolution_));
90-
my = static_cast<int>(std::floor((wy - origin_y_) / resolution_));
90+
mx = static_cast<int>(std::floor((wx - origin_x_) * resolution_inv_));
91+
my = static_cast<int>(std::floor((wy - origin_y_) * resolution_inv_));
9192

9293
if (mx < size_x_ && my < size_y_) {
9394
return true;
@@ -229,4 +230,10 @@ void OccupancyGridMapInterface::raytrace(
229230
raytraceLine(marker, x0, y0, x1, y1, cell_raytrace_range);
230231
}
231232

233+
void OccupancyGridMapInterface::setHeightLimit(const double min_height, const double max_height)
234+
{
235+
min_height_ = min_height;
236+
max_height_ = max_height;
237+
}
238+
232239
} // namespace costmap_2d

perception/probabilistic_occupancy_grid_map/src/pointcloud_based_occupancy_grid_map/occupancy_grid_map_fixed.cpp

+79-29
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,12 @@ void OccupancyGridMapFixedBlindSpot::updateWithPointCloud(
6060
constexpr double angle_increment = autoware::universe_utils::deg2rad(0.1);
6161
const size_t angle_bin_size = ((max_angle - min_angle) / angle_increment) + size_t(1 /*margin*/);
6262

63-
// Transform from base_link to map frame
64-
PointCloud2 map_raw_pointcloud, map_obstacle_pointcloud; // point cloud in map frame
65-
utils::transformPointcloud(raw_pointcloud, robot_pose, map_raw_pointcloud);
66-
utils::transformPointcloud(obstacle_pointcloud, robot_pose, map_obstacle_pointcloud);
63+
// Transform Matrix from base_link to map frame
64+
Eigen::Matrix4f matmap = utils::getTransformMatrix(robot_pose);
6765

68-
// Transform from map frame to scan frame
69-
PointCloud2 scan_raw_pointcloud, scan_obstacle_pointcloud; // point cloud in scan frame
7066
const auto scan2map_pose = utils::getInversePose(scan_origin); // scan -> map transform pose
71-
utils::transformPointcloud(map_raw_pointcloud, scan2map_pose, scan_raw_pointcloud);
72-
utils::transformPointcloud(map_obstacle_pointcloud, scan2map_pose, scan_obstacle_pointcloud);
67+
// Transform Matrix from map frame to scan frame
68+
Eigen::Matrix4f matscan = utils::getTransformMatrix(scan2map_pose);
7369

7470
// Create angle bins and sort by distance
7571
struct BinInfo
@@ -83,40 +79,94 @@ void OccupancyGridMapFixedBlindSpot::updateWithPointCloud(
8379
double wx;
8480
double wy;
8581
};
86-
std::vector</*angle bin*/ std::vector<BinInfo>> obstacle_pointcloud_angle_bins;
87-
std::vector</*angle bin*/ std::vector<BinInfo>> raw_pointcloud_angle_bins;
88-
obstacle_pointcloud_angle_bins.resize(angle_bin_size);
89-
raw_pointcloud_angle_bins.resize(angle_bin_size);
90-
for (PointCloud2ConstIterator<float> iter_x(scan_raw_pointcloud, "x"),
91-
iter_y(scan_raw_pointcloud, "y"), iter_wx(map_raw_pointcloud, "x"),
92-
iter_wy(map_raw_pointcloud, "y");
93-
iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_wx, ++iter_wy) {
94-
const double angle = atan2(*iter_y, *iter_x);
95-
const int angle_bin_index = (angle - min_angle) / angle_increment;
82+
std::vector</*angle bin*/ std::vector<BinInfo>> obstacle_pointcloud_angle_bins(angle_bin_size);
83+
std::vector</*angle bin*/ std::vector<BinInfo>> raw_pointcloud_angle_bins(angle_bin_size);
84+
const int x_offset_raw = raw_pointcloud.fields[pcl::getFieldIndex(raw_pointcloud, "x")].offset;
85+
const int y_offset_raw = raw_pointcloud.fields[pcl::getFieldIndex(raw_pointcloud, "y")].offset;
86+
const int z_offset_raw = raw_pointcloud.fields[pcl::getFieldIndex(raw_pointcloud, "z")].offset;
87+
const int x_offset_obstacle =
88+
obstacle_pointcloud.fields[pcl::getFieldIndex(obstacle_pointcloud, "x")].offset;
89+
const int y_offset_obstacle =
90+
obstacle_pointcloud.fields[pcl::getFieldIndex(obstacle_pointcloud, "y")].offset;
91+
const int z_offset_obstacle =
92+
obstacle_pointcloud.fields[pcl::getFieldIndex(obstacle_pointcloud, "z")].offset;
93+
const size_t raw_pointcloud_size = raw_pointcloud.width * raw_pointcloud.height;
94+
const size_t obstacle_pointcloud_size = obstacle_pointcloud.width * obstacle_pointcloud.height;
95+
96+
const size_t raw_reserve_size = raw_pointcloud_size / angle_bin_size;
97+
const size_t obstacle_reserve_size = obstacle_pointcloud_size / angle_bin_size;
98+
for (auto & raw_pointcloud_angle_bin : raw_pointcloud_angle_bins) {
99+
raw_pointcloud_angle_bin.reserve(raw_reserve_size);
100+
}
101+
for (auto & obstacle_pointcloud_angle_bin : obstacle_pointcloud_angle_bins) {
102+
obstacle_pointcloud_angle_bin.reserve(obstacle_reserve_size);
103+
}
104+
size_t global_offset = 0;
105+
const auto angle_increment_inv = 1.0 / angle_increment;
106+
for (size_t i = 0; i < raw_pointcloud_size; ++i) {
107+
Eigen::Vector4f pt(
108+
*reinterpret_cast<const float *>(&raw_pointcloud.data[global_offset + x_offset_raw]),
109+
*reinterpret_cast<const float *>(&raw_pointcloud.data[global_offset + y_offset_raw]),
110+
*reinterpret_cast<const float *>(&raw_pointcloud.data[global_offset + z_offset_raw]), 1);
111+
// Exclude invalid points
112+
if (!std::isfinite(pt[0]) || !std::isfinite(pt[1]) || !std::isfinite(pt[2])) {
113+
global_offset += raw_pointcloud.point_step;
114+
continue;
115+
}
116+
// Apply height filter
117+
if (pt[2] < min_height_ || max_height_ < pt[2]) {
118+
global_offset += raw_pointcloud.point_step;
119+
continue;
120+
}
121+
// Calculate transformed points
122+
Eigen::Vector4f pt_map(matmap * pt);
123+
Eigen::Vector4f pt_scan(matscan * pt_map);
124+
const double angle = atan2(pt_scan[1], pt_scan[0]);
125+
const int angle_bin_index = (angle - min_angle) * angle_increment_inv;
96126
raw_pointcloud_angle_bins.at(angle_bin_index)
97-
.push_back(BinInfo(std::hypot(*iter_y, *iter_x), *iter_wx, *iter_wy));
127+
.emplace_back(
128+
std::sqrt(pt_scan[1] * pt_scan[1] + pt_scan[0] * pt_scan[0]), pt_map[0], pt_map[1]);
129+
global_offset += raw_pointcloud.point_step;
98130
}
99131
for (auto & raw_pointcloud_angle_bin : raw_pointcloud_angle_bins) {
100132
std::sort(raw_pointcloud_angle_bin.begin(), raw_pointcloud_angle_bin.end(), [](auto a, auto b) {
101133
return a.range < b.range;
102134
});
103135
}
104-
// create and sort bin for obstacle pointcloud
105-
for (PointCloud2ConstIterator<float> iter_x(scan_obstacle_pointcloud, "x"),
106-
iter_y(scan_obstacle_pointcloud, "y"), iter_wx(map_obstacle_pointcloud, "x"),
107-
iter_wy(map_obstacle_pointcloud, "y");
108-
iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_wx, ++iter_wy) {
109-
const double angle = atan2(*iter_y, *iter_x);
110-
const int angle_bin_index = (angle - min_angle) / angle_increment;
111-
const double range = std::hypot(*iter_y, *iter_x);
136+
global_offset = 0;
137+
for (size_t i = 0; i < obstacle_pointcloud_size; ++i) {
138+
Eigen::Vector4f pt(
139+
*reinterpret_cast<const float *>(
140+
&obstacle_pointcloud.data[global_offset + x_offset_obstacle]),
141+
*reinterpret_cast<const float *>(
142+
&obstacle_pointcloud.data[global_offset + y_offset_obstacle]),
143+
*reinterpret_cast<const float *>(
144+
&obstacle_pointcloud.data[global_offset + z_offset_obstacle]),
145+
1);
146+
// Exclude invalid points
147+
if (!std::isfinite(pt[0]) || !std::isfinite(pt[1]) || !std::isfinite(pt[2])) {
148+
global_offset += obstacle_pointcloud.point_step;
149+
continue;
150+
}
151+
// Apply height filter
152+
if (pt[2] < min_height_ || max_height_ < pt[2]) {
153+
global_offset += obstacle_pointcloud.point_step;
154+
continue;
155+
}
156+
// Calculate transformed points
157+
Eigen::Vector4f pt_map(matmap * pt);
158+
Eigen::Vector4f pt_scan(matscan * pt_map);
159+
const double angle = atan2(pt_scan[1], pt_scan[0]);
160+
const int angle_bin_index = (angle - min_angle) * angle_increment_inv;
161+
const double range = std::sqrt(pt_scan[1] * pt_scan[1] + pt_scan[0] * pt_scan[0]);
112162
// Ignore obstacle points exceed the range of the raw points
113163
if (raw_pointcloud_angle_bins.at(angle_bin_index).empty()) {
114164
continue; // No raw point in this angle bin
115165
} else if (range > raw_pointcloud_angle_bins.at(angle_bin_index).back().range) {
116166
continue; // Obstacle point exceeds the range of the raw points
117167
}
118-
obstacle_pointcloud_angle_bins.at(angle_bin_index)
119-
.push_back(BinInfo(range, *iter_wx, *iter_wy));
168+
obstacle_pointcloud_angle_bins.at(angle_bin_index).emplace_back(range, pt_map[0], pt_map[1]);
169+
global_offset += obstacle_pointcloud.point_step;
120170
}
121171
for (auto & obstacle_pointcloud_angle_bin : obstacle_pointcloud_angle_bins) {
122172
std::sort(

perception/probabilistic_occupancy_grid_map/src/pointcloud_based_occupancy_grid_map/occupancy_grid_map_projective.cpp

+84-29
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,12 @@ void OccupancyGridMapProjectiveBlindSpot::updateWithPointCloud(
6363

6464
// Transform from base_link to map frame
6565
PointCloud2 map_raw_pointcloud, map_obstacle_pointcloud; // point cloud in map frame
66-
utils::transformPointcloud(raw_pointcloud, robot_pose, map_raw_pointcloud);
67-
utils::transformPointcloud(obstacle_pointcloud, robot_pose, map_obstacle_pointcloud);
66+
Eigen::Matrix4f matmap = utils::getTransformMatrix(robot_pose);
6867

6968
// Transform from map frame to scan frame
7069
PointCloud2 scan_raw_pointcloud, scan_obstacle_pointcloud; // point cloud in scan frame
7170
const auto scan2map_pose = utils::getInversePose(scan_origin); // scan -> map transform pose
72-
utils::transformPointcloud(map_raw_pointcloud, scan2map_pose, scan_raw_pointcloud);
73-
utils::transformPointcloud(map_obstacle_pointcloud, scan2map_pose, scan_obstacle_pointcloud);
71+
Eigen::Matrix4f matscan = utils::getTransformMatrix(scan2map_pose);
7472

7573
// Create angle bins and sort points by range
7674
struct BinInfo3D
@@ -97,36 +95,92 @@ void OccupancyGridMapProjectiveBlindSpot::updateWithPointCloud(
9795
double projected_wy;
9896
};
9997

100-
std::vector</*angle bin*/ std::vector<BinInfo3D>> obstacle_pointcloud_angle_bins;
101-
std::vector</*angle bin*/ std::vector<BinInfo3D>> raw_pointcloud_angle_bins;
102-
obstacle_pointcloud_angle_bins.resize(angle_bin_size);
103-
raw_pointcloud_angle_bins.resize(angle_bin_size);
104-
for (PointCloud2ConstIterator<float> iter_x(scan_raw_pointcloud, "x"),
105-
iter_y(scan_raw_pointcloud, "y"), iter_wx(map_raw_pointcloud, "x"),
106-
iter_wy(map_raw_pointcloud, "y"), iter_wz(map_raw_pointcloud, "z");
107-
iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_wx, ++iter_wy, ++iter_wz) {
108-
const double angle = atan2(*iter_y, *iter_x);
109-
const int angle_bin_index = (angle - min_angle) / angle_increment;
98+
std::vector</*angle bin*/ std::vector<BinInfo3D>> obstacle_pointcloud_angle_bins(angle_bin_size);
99+
std::vector</*angle bin*/ std::vector<BinInfo3D>> raw_pointcloud_angle_bins(angle_bin_size);
100+
const int x_offset_raw = raw_pointcloud.fields[pcl::getFieldIndex(raw_pointcloud, "x")].offset;
101+
const int y_offset_raw = raw_pointcloud.fields[pcl::getFieldIndex(raw_pointcloud, "y")].offset;
102+
const int z_offset_raw = raw_pointcloud.fields[pcl::getFieldIndex(raw_pointcloud, "z")].offset;
103+
const int x_offset_obstacle =
104+
obstacle_pointcloud.fields[pcl::getFieldIndex(obstacle_pointcloud, "x")].offset;
105+
const int y_offset_obstacle =
106+
obstacle_pointcloud.fields[pcl::getFieldIndex(obstacle_pointcloud, "y")].offset;
107+
const int z_offset_obstacle =
108+
obstacle_pointcloud.fields[pcl::getFieldIndex(obstacle_pointcloud, "z")].offset;
109+
const size_t raw_pointcloud_size = raw_pointcloud.width * raw_pointcloud.height;
110+
const size_t obstacle_pointcloud_size = obstacle_pointcloud.width * obstacle_pointcloud.height;
111+
112+
const size_t raw_reserve_size = raw_pointcloud_size / angle_bin_size;
113+
const size_t obstacle_reserve_size = obstacle_pointcloud_size / angle_bin_size;
114+
for (auto & raw_pointcloud_angle_bin : raw_pointcloud_angle_bins) {
115+
raw_pointcloud_angle_bin.reserve(raw_reserve_size);
116+
}
117+
for (auto & obstacle_pointcloud_angle_bin : obstacle_pointcloud_angle_bins) {
118+
obstacle_pointcloud_angle_bin.reserve(obstacle_reserve_size);
119+
}
120+
size_t global_offset = 0;
121+
const auto angle_increment_inv = 1.0 / angle_increment;
122+
123+
for (size_t i = 0; i < raw_pointcloud_size; i++) {
124+
Eigen::Vector4f pt(
125+
*reinterpret_cast<const float *>(&raw_pointcloud.data[global_offset + x_offset_raw]),
126+
*reinterpret_cast<const float *>(&raw_pointcloud.data[global_offset + y_offset_raw]),
127+
*reinterpret_cast<const float *>(&raw_pointcloud.data[global_offset + z_offset_raw]), 1);
128+
// Exclude invalid points
129+
if (!std::isfinite(pt[0]) || !std::isfinite(pt[1]) || !std::isfinite(pt[2])) {
130+
global_offset += raw_pointcloud.point_step;
131+
continue;
132+
}
133+
// Apply height filter
134+
if (pt[2] < min_height_ || max_height_ < pt[2]) {
135+
global_offset += raw_pointcloud.point_step;
136+
continue;
137+
}
138+
// Calculate transformed points
139+
Eigen::Vector4f pt_map(matmap * pt);
140+
Eigen::Vector4f pt_scan(matscan * pt_map);
141+
const double angle = atan2(pt_scan[1], pt_scan[0]);
142+
const int angle_bin_index = (angle - min_angle) * angle_increment_inv;
110143
raw_pointcloud_angle_bins.at(angle_bin_index)
111-
.emplace_back(std::hypot(*iter_y, *iter_x), *iter_wx, *iter_wy, *iter_wz);
144+
.emplace_back(
145+
std::sqrt(pt_scan[1] * pt_scan[1] + pt_scan[0] * pt_scan[0]), pt_map[0], pt_map[1],
146+
pt_map[2]);
147+
global_offset += raw_pointcloud.point_step;
112148
}
113149
for (auto & raw_pointcloud_angle_bin : raw_pointcloud_angle_bins) {
114150
std::sort(raw_pointcloud_angle_bin.begin(), raw_pointcloud_angle_bin.end(), [](auto a, auto b) {
115151
return a.range < b.range;
116152
});
117153
}
118-
// Create obstacle angle bins and sort points by range
119-
for (PointCloud2ConstIterator<float> iter_x(scan_obstacle_pointcloud, "x"),
120-
iter_y(scan_obstacle_pointcloud, "y"), iter_z(scan_obstacle_pointcloud, "z"),
121-
iter_wx(map_obstacle_pointcloud, "x"), iter_wy(map_obstacle_pointcloud, "y"),
122-
iter_wz(map_obstacle_pointcloud, "z");
123-
iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z, ++iter_wx, ++iter_wy, ++iter_wz) {
154+
155+
global_offset = 0;
156+
for (size_t i = 0; i < obstacle_pointcloud_size; i++) {
157+
Eigen::Vector4f pt(
158+
*reinterpret_cast<const float *>(
159+
&obstacle_pointcloud.data[global_offset + x_offset_obstacle]),
160+
*reinterpret_cast<const float *>(
161+
&obstacle_pointcloud.data[global_offset + y_offset_obstacle]),
162+
*reinterpret_cast<const float *>(
163+
&obstacle_pointcloud.data[global_offset + z_offset_obstacle]),
164+
1);
165+
// Exclude invalid points
166+
if (!std::isfinite(pt[0]) || !std::isfinite(pt[1]) || !std::isfinite(pt[2])) {
167+
global_offset += obstacle_pointcloud.point_step;
168+
continue;
169+
}
170+
// Apply height filter
171+
if (pt[2] < min_height_ || max_height_ < pt[2]) {
172+
global_offset += obstacle_pointcloud.point_step;
173+
continue;
174+
}
175+
// Calculate transformed points
176+
Eigen::Vector4f pt_map(matmap * pt);
177+
Eigen::Vector4f pt_scan(matscan * pt_map);
124178
const double scan_z = scan_origin.position.z - robot_pose.position.z;
125-
const double obstacle_z = (*iter_wz) - robot_pose.position.z;
179+
const double obstacle_z = (pt_map[2]) - robot_pose.position.z;
126180
const double dz = scan_z - obstacle_z;
127-
const double angle = atan2(*iter_y, *iter_x);
128-
const int angle_bin_index = (angle - min_angle) / angle_increment;
129-
const double range = std::hypot(*iter_x, *iter_y);
181+
const double angle = atan2(pt_scan[1], pt_scan[0]);
182+
const int angle_bin_index = (angle - min_angle) * angle_increment_inv;
183+
const double range = std::sqrt(pt_scan[1] * pt_scan[1] + pt_scan[0] * pt_scan[0]);
130184
// Ignore obstacle points exceed the range of the raw points
131185
if (raw_pointcloud_angle_bins.at(angle_bin_index).empty()) {
132186
continue; // No raw point in this angle bin
@@ -136,17 +190,18 @@ void OccupancyGridMapProjectiveBlindSpot::updateWithPointCloud(
136190
if (dz > projection_dz_threshold_) {
137191
const double ratio = obstacle_z / dz;
138192
const double projection_length = range * ratio;
139-
const double projected_wx = (*iter_wx) + ((*iter_wx) - scan_origin.position.x) * ratio;
140-
const double projected_wy = (*iter_wy) + ((*iter_wy) - scan_origin.position.y) * ratio;
193+
const double projected_wx = (pt_map[0]) + ((pt_map[0]) - scan_origin.position.x) * ratio;
194+
const double projected_wy = (pt_map[1]) + ((pt_map[1]) - scan_origin.position.y) * ratio;
141195
obstacle_pointcloud_angle_bins.at(angle_bin_index)
142196
.emplace_back(
143-
range, *iter_wx, *iter_wy, *iter_wz, projection_length, projected_wx, projected_wy);
197+
range, pt_map[0], pt_map[1], pt_map[2], projection_length, projected_wx, projected_wy);
144198
} else {
145199
obstacle_pointcloud_angle_bins.at(angle_bin_index)
146200
.emplace_back(
147-
range, *iter_wx, *iter_wy, *iter_wz, std::numeric_limits<double>::infinity(),
201+
range, pt_map[0], pt_map[1], pt_map[2], std::numeric_limits<double>::infinity(),
148202
std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity());
149203
}
204+
global_offset += obstacle_pointcloud.point_step;
150205
}
151206
for (auto & obstacle_pointcloud_angle_bin : obstacle_pointcloud_angle_bins) {
152207
std::sort(

0 commit comments

Comments
 (0)