-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpit_detection.cpp
More file actions
120 lines (100 loc) · 3.69 KB
/
pit_detection.cpp
File metadata and controls
120 lines (100 loc) · 3.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/point_cloud2.hpp>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <vector>
#include <string>
#include <cmath>
#include <std_msgs/msg/string.hpp>
using namespace std;
class Pitpoint : public rclcpp::Node {
public:
enum ObstacleEnum {
OBSTACLE,
PIT,
SAFE
};
struct ObstacleInfo {
float x;
float y;
float z;
float distance;
};
Pitpoint() : Node("pit_point") {
point_cloud_sub = this->create_subscription<sensor_msgs::msg::PointCloud2>(
"/camera/camera/depth/color/points", 10,
std::bind(&Pitpoint::processPointCloud, this, std::placeholders::_1)
);
direction_publisher = this->create_publisher<std_msgs::msg::String>("/pit_direction", 10);
}
private:
static constexpr float SAFE_DISTANCE = 3.0;
static constexpr float HORY_DIST = 0.75;
static constexpr float REAL_HEIGHT = 0.8;
rclcpp::Subscription<sensor_msgs::msg::PointCloud2>::SharedPtr point_cloud_sub;
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr direction_publisher;
void preProcessPointCloud(pcl::PointCloud<pcl::PointXYZRGB>::Ptr& cloud) {
pcl::StatisticalOutlierRemoval<pcl::PointXYZRGB> sor;
sor.setInputCloud(cloud);
sor.setMeanK(50);
sor.setStddevMulThresh(1.0);
sor.filter(*cloud);
}
vector<ObstacleInfo> filterPointCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Ptr& cloud) {
vector<ObstacleInfo> filteredPointCloud;
for (const auto& point : cloud->points) {
float distance = sqrt((point.x * point.x) + (point.y * point.y) + (point.z * point.z));
if (point.z < SAFE_DISTANCE) {
filteredPointCloud.push_back({point.x, point.y, point.z, distance});
}
}
return filteredPointCloud;
}
vector<ObstacleInfo> pitFilterPointCloud(vector<ObstacleInfo>& cloud) {
vector<ObstacleInfo> pits;
for (const auto& point : cloud) {
if (point.y > REAL_HEIGHT && abs(point.x) < HORY_DIST) {
pits.push_back({point.x, point.y, point.z, point.distance});
}
}
return pits;
}
string getDirection(const vector<ObstacleInfo>& pits) {
string direction;
float sum_x = 0;
for (const auto& pit : pits) {
RCLCPP_WARN(this->get_logger(), "Distance=%.2f, Height=%.2f, X_Direction=%.2f", pit.z, pit.y, pit.x);
sum_x += pit.x;
}
if (!pits.empty()) {
if (sum_x >= 0) {
direction = "Front_Right";
} else {
direction = "Front_Left";
}
} else {
direction = "Empty";
}
return direction;
}
void processPointCloud(const sensor_msgs::msg::PointCloud2::SharedPtr msg) {
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::fromROSMsg(*msg, *cloud);
auto message = std_msgs::msg::String();
preProcessPointCloud(cloud);
vector<ObstacleInfo> filteredPointCloud = filterPointCloud(cloud);
vector<ObstacleInfo> pits = pitFilterPointCloud(filteredPointCloud);
string direction = getDirection(pits);
message.data = direction;
direction_publisher->publish(message);
RCLCPP_WARN(this->get_logger(), "Publishing direction: %s", direction.c_str());
}
};
int main(int argc, char* argv[]) {
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<Pitpoint>());
rclcpp::shutdown();
return 0;
}