Formula Student Autonomous Systems
The code for the main driverless system
Loading...
Searching...
No Matches
ransac.cpp
Go to the documentation of this file.
2
3#include <Eigen/Dense>
4#include <random>
5
6RANSAC::RANSAC(const double epsilon, const int n_tries) : epsilon(epsilon), n_tries(n_tries) {}
7
8void RANSAC::ground_removal(const sensor_msgs::msg::PointCloud2::SharedPtr& trimmed_point_cloud,
9 sensor_msgs::msg::PointCloud2::SharedPtr& ground_removed_cloud,
10 GroundGrid& ground_grid) const {
11 const auto& cloud_data = trimmed_point_cloud->data;
12 const size_t num_points = trimmed_point_cloud->width * trimmed_point_cloud->height;
13 if (num_points < 3) {
14 return;
15 }
16
17 ground_removed_cloud->header = trimmed_point_cloud->header;
18 ground_removed_cloud->height = 1;
19 ground_removed_cloud->is_bigendian = trimmed_point_cloud->is_bigendian;
20 ground_removed_cloud->is_dense = true;
21 ground_removed_cloud->fields = trimmed_point_cloud->fields;
22 ground_removed_cloud->point_step = trimmed_point_cloud->point_step;
23 ground_removed_cloud->width = 0;
24 ground_removed_cloud->data.resize(num_points * trimmed_point_cloud->point_step);
25
26 std::mt19937 rng(std::random_device{}());
27 std::uniform_int_distribution<size_t> dist(0, num_points - 1);
28
29 double best_a = 0, best_b = 0, best_c = 0, best_d = 0;
30 size_t best_inliers = 0;
31
32 for (int i = 0; i < n_tries; ++i) {
33 // Select 3 random points
34 size_t idx1 = dist(rng), idx2 = dist(rng), idx3 = dist(rng);
35 if (idx1 == idx2 || idx1 == idx3 || idx2 == idx3) {
36 i--;
37 continue;
38 }
39
40 Eigen::Vector3f p1 = *reinterpret_cast<const Eigen::Vector3f*>(&cloud_data[LidarPoint::PointX(idx1)]);
41 Eigen::Vector3f p2 = *reinterpret_cast<const Eigen::Vector3f*>(&cloud_data[LidarPoint::PointX(idx2)]);
42 Eigen::Vector3f p3 = *reinterpret_cast<const Eigen::Vector3f*>(&cloud_data[LidarPoint::PointX(idx3)]);
43
44 Eigen::Vector3f v1 = p2 - p1;
45 Eigen::Vector3f v2 = p3 - p1;
46 Eigen::Vector3f n = v1.cross(v2);
47
48 if (n.norm() < 1e-6) {
49 continue;
50 }
51 n.normalize();
52 double a = n.x(), b = n.y(), c = n.z();
53 double d = -n.dot(p1);
54
55 size_t inliers = 0;
56 for (size_t j = 0; j < num_points; ++j) {
57 float x = *reinterpret_cast<const float*>(&cloud_data[LidarPoint::PointX(j)]);
58 float y = *reinterpret_cast<const float*>(&cloud_data[LidarPoint::PointY(j)]);
59 float z = *reinterpret_cast<const float*>(&cloud_data[LidarPoint::PointZ(j)]);
60 double dist = std::abs(a * x + b * y + c * z + d);
61 if (dist < epsilon) {
62 inliers++;
63 }
64 }
65
66 if (inliers > best_inliers) {
67 best_inliers = inliers;
68 best_a = a;
69 best_b = b;
70 best_c = c;
71 best_d = d;
72 }
73 }
74
75 // Classify points based on the best plane
76 for (size_t i = 0; i < num_points; ++i) {
77 float x = *reinterpret_cast<const float*>(&cloud_data[LidarPoint::PointX(i)]);
78 float y = *reinterpret_cast<const float*>(&cloud_data[LidarPoint::PointY(i)]);
79 float z = *reinterpret_cast<const float*>(&cloud_data[LidarPoint::PointZ(i)]);
80 double dist = std::abs(best_a * x + best_b * y + best_c * z + best_d);
81 if (dist < epsilon) {
82 // Ground point, update ground grid
83 ground_grid.set_ground_height(x, y, z);
84 } else {
85 // Non-ground
86 size_t write_idx = ground_removed_cloud->width++;
87 std::memcpy(&ground_removed_cloud->data[write_idx * trimmed_point_cloud->point_step],
88 &cloud_data[i * trimmed_point_cloud->point_step],
89 trimmed_point_cloud->point_step);
90 }
91 }
92
93 ground_removed_cloud->data.resize(ground_removed_cloud->width * trimmed_point_cloud->point_step);
94 ground_removed_cloud->row_step = ground_removed_cloud->width * trimmed_point_cloud->point_step;
95}
Class to represent a ground height grid for ground proximity checks.
void set_ground_height(const float x, const float y, const float height)
Set the ground height at a specific (x, y) location.
double epsilon
Epsilon threshold for ground removal.
Definition ransac.hpp:43
void ground_removal(const sensor_msgs::msg::PointCloud2::SharedPtr &trimmed_point_cloud, sensor_msgs::msg::PointCloud2::SharedPtr &ground_removed_point_cloud, GroundGrid &ground_grid) const override
Perform ground removal using the RANSAC algorithm.
Definition ransac.cpp:8
int n_tries
Number of RANSAC iterations.
Definition ransac.hpp:44
RANSAC()=default
Default constructor.
constexpr size_t PointZ(size_t idx)
constexpr size_t PointX(size_t idx)
constexpr size_t PointY(size_t idx)