Galaxis Codebase  1.0.0
Team Galaxis software stack for the Carolo Cup 2023 - ROS2 based software
RealSenseNode.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <string>
3 #include <cmath>
4 #include <iostream>
5 #include <chrono>
6 #include <thread>
7 
8 #include "RealSenseNode.hpp"
10 #include "utils/logger.hpp"
11 #include <memory>
12 #include <DepthCamera.hpp>
13 #include <utils/settings.hpp>
14 
15 #include <pcl_conversions/pcl_conversions.h>
16 #include <sensor_msgs/msg/point_cloud2.hpp>
17 #include <sensor_msgs/point_cloud2_iterator.hpp>
18 
19 using namespace galaxis::utils;
20 using namespace std::chrono_literals;
21 using std::placeholders::_1;
22 //ros-eloquent-rosbag2-storage-default-plugins // old?
23 
25  try {
26  std::string configPath = "settings/onstartup_realsense.json";
27  auto settingsJsonSPtr = read_json_file(configPath);
28  json& settingsJson = (*settingsJsonSPtr)["settings"];
29 
30  m_debugMode = settingsJson["debug_mode"];
31  m_listenToROSPCL = settingsJson["listen_to_ros_pointcloud"];
32  m_settingsJsonFilename = settingsJson["camera_config_path"];
33  }
34  catch(std::exception& e) {
35  log_error("[RealSenseNode] Failed to read config file. ", e.what());
36  }
37 
38  // init camera
39  m_cam.set_node(this); // required
41 
42  // obstacle publisher
43  rclcpp::QoS qos = galaxis::ros::get_qos_profile(galaxis::ros::QoS_Profile_t::QOS_RELIABLE);
44  galaxis::ros::create_publisher(this, m_obstaclePublisher);
45 
46  if(m_listenToROSPCL) {
47  m_depthSubscriberSPtr = this->create_subscription<sensor_msgs::msg::PointCloud2>("/galaxis/debug/realsense/pointcloud/raw",
48  qos,
49  std::bind(&RealSenseNode::on_ros_pointcloud_callback, this, std::placeholders::_1)
50  );
51  }
52 
53  if(m_debugMode) {
54  if(!m_listenToROSPCL) m_depthPublisherSPtr = this->create_publisher<sensor_msgs::msg::PointCloud2>("/galaxis/debug/realsense/pointcloud/raw", qos);
55  m_debugPclPublisherFiltered = this->create_publisher<sensor_msgs::msg::PointCloud2>("galaxis/debug/realsense/pointcloud/filtered", qos);
56  m_debugPclPublisherResult = this->create_publisher<sensor_msgs::msg::PointCloud2>("galaxis/debug/realsense/pointcloud/objects", qos);
57  }
58 
59  this->enable_parameters(std::bind(&RealSenseNode::new_parameters_callback, this, std::placeholders::_1));
60 
61  std::thread(&RealSenseNode::object_detection_loop, this).detach();
62  // std::thread(&RealSenseNode::pointcloud_publish_loop, this).detach();
63 }
64 
65 void RealSenseNode::on_ros_pointcloud_callback(sensor_msgs::msg::PointCloud2::SharedPtr pclMsg) {
66  auto timePclTupleSPtr = std::make_shared<std::pair<rclcpp::Time, pcl::PointCloud<pcl::PointXYZ>::Ptr>>();
67 
68  pcl::fromROSMsg(*pclMsg, *(timePclTupleSPtr->second));
69  timePclTupleSPtr->first = pclMsg->header.stamp;
70 
71  this->object_detection(timePclTupleSPtr);
72 }
73 
75  while(1) {
76 
77  auto pointCloudRawPair = m_cam.pop_last_grabbed_pcl(true);
78  if(pointCloudRawPair == nullptr) {
79  log_warning("[RealSenseNode] pop_last_grabbed_pcl is nullptr");
80  std::this_thread::sleep_for(std::chrono::milliseconds(5));
81  continue;
82  }
83 
84  this->object_detection(pointCloudRawPair);
85  }
86 }
87 
88 void RealSenseNode::object_detection(std::shared_ptr<std::pair<rclcpp::Time, pcl::PointCloud<pcl::PointXYZ>::Ptr>> pointCloudRawPair) {
89  m_settingsMtx.lock();
90  pclPtrType cloudFiltered(new pclType);
91  m_objectDetector.filter_pcl(pointCloudRawPair->second, cloudFiltered, m_leafSize, m_yMin, m_yMax);
92 
93  std::vector<Object> objectsVec;
94  auto detectedObjectsVecSPtr = m_objectDetector.cluster_data(cloudFiltered, objectsVec, m_clusterTolerance, m_minClusterSize, m_maxClusterSize);
95  m_settingsMtx.unlock();
96 
97  std::unique_ptr<ObstacleListType> msgObstacle = std::make_unique<ObstacleListType>();
98  std_msgs::msg::Header header;
99  header.stamp = pointCloudRawPair->first;
100  msgObstacle->header = header;
101 
102  float sizeX, sizeY, sizeZ;
103  for(uint32_t i = 0; i < objectsVec.size(); i ++){
104  sizeX = std::fabs(objectsVec.at(i).get_max_dimensions().x - objectsVec.at(i).get_min_dimensions().x);
105  sizeY = std::fabs(objectsVec.at(i).get_max_dimensions().y - objectsVec.at(i).get_min_dimensions().y);
106  sizeZ = std::fabs(objectsVec.at(i).get_max_dimensions().z - objectsVec.at(i).get_min_dimensions().z);
107 
108  //TODO: ueberpruefen ob ungefähr rechteck?
109  msgObstacle->obstacles.push_back(ObstacleType());
110  msgObstacle->obstacles.back().pos_x = objectsVec.at(i).get_center_point().x;
111  msgObstacle->obstacles.back().pos_y = objectsVec.at(i).get_center_point().z;
112  msgObstacle->obstacles.back().width = 0.2;
113 
114  if(m_debugMode) {
115  log("object ", std::to_string(objectsVec.at(i).get_center_point().x), " : ", std::to_string(objectsVec.at(i).get_center_point().y), " : ", std::to_string(objectsVec.at(i).get_center_point().z), " | SIZE: ", objectsVec.at(i).size, "\n");
116  log("min Dimensions (x | y | z) ", std::to_string(objectsVec.at(i).get_min_dimensions().x), " | ", std::to_string(objectsVec.at(i).get_min_dimensions().y), " | ", std::to_string(objectsVec.at(i).get_min_dimensions().y), "\n");
117  log("max Dimensions (x | y | z) ", std::to_string(objectsVec.at(i).get_max_dimensions().x), " | ", std::to_string(objectsVec.at(i).get_max_dimensions().y), " | ", std::to_string(objectsVec.at(i).get_max_dimensions().y), "\n");
118  log("object dims (x | y | z): ", sizeX, " | ", sizeY, " | ", sizeZ, "\n");
119  log("SIZE Y: ", std::to_string(objectsVec.at(i).get_max_dimensions().y - objectsVec.at(i).get_min_dimensions().y), "\n");
120  log("SIZE Z: ", std::to_string(objectsVec.at(i).get_max_dimensions().z - objectsVec.at(i).get_min_dimensions().z), "\n");
121  }
122  }
123 
124  if(msgObstacle->obstacles.size() > 0) {
125  m_obstaclePublisher->publish(std::move(msgObstacle));
126  }
127 
128  if(m_debugMode) {
129  // debug publisher
130  std::unique_ptr<sensor_msgs::msg::PointCloud2> pointCloudMsgUPtr = std::make_unique<sensor_msgs::msg::PointCloud2>();
131  if(m_depthPublisherSPtr->get_subscription_count() > 0) {
132  pcl::toROSMsg(*(std::get<1>(*pointCloudRawPair)), *pointCloudMsgUPtr);
133  pointCloudMsgUPtr->header.frame_id = "map";
134  pointCloudMsgUPtr->header.stamp = pointCloudRawPair->first;
135  }
136 
137  std::unique_ptr<sensor_msgs::msg::PointCloud2> pointCloudFilteredMsgUPtr = std::make_unique<sensor_msgs::msg::PointCloud2>();
138  if(m_debugPclPublisherFiltered->get_subscription_count() > 0) {
139  pcl::toROSMsg(*cloudFiltered, *pointCloudFilteredMsgUPtr);
140  pointCloudFilteredMsgUPtr->header.frame_id = "map";
141  pointCloudFilteredMsgUPtr->header.stamp = pointCloudRawPair->first;
142  }
143 
144  std::unique_ptr<sensor_msgs::msg::PointCloud2> pointCloudDetectedObjectsUPtr = std::make_unique<sensor_msgs::msg::PointCloud2>();
145  if(m_debugPclPublisherResult->get_subscription_count() > 0) {
146  pcl::PointCloud<pcl::PointXYZ>::Ptr allObjectsCloudPtr(new pcl::PointCloud<pcl::PointXYZ>);
147  // merge pcls
148  for (auto pclPtr : *detectedObjectsVecSPtr) {
149  *allObjectsCloudPtr += *pclPtr;
150  }
151 
152  pcl::toROSMsg(*allObjectsCloudPtr, *pointCloudDetectedObjectsUPtr);
153  pointCloudDetectedObjectsUPtr->header.frame_id = "map";
154  pointCloudDetectedObjectsUPtr->header.stamp = pointCloudRawPair->first;
155  }
156 
157  if(m_depthPublisherSPtr->get_subscription_count() > 0) {
158  m_depthPublisherSPtr->publish(std::move(pointCloudMsgUPtr));
159  }
160 
161  if(m_debugPclPublisherFiltered->get_subscription_count() > 0) {
162  m_debugPclPublisherFiltered->publish(std::move(pointCloudFilteredMsgUPtr));
163  }
164  if(m_debugPclPublisherResult->get_subscription_count() > 0) {
165  m_debugPclPublisherResult->publish(std::move(pointCloudDetectedObjectsUPtr));
166  }
167  }
168 }
169 
170 // void RealSenseNode::pointcloud_publish_loop(){
171 // while(1) {
172 // auto msg = m_cam.get_last_grabbed_pcl();
173 // if(msg == nullptr) {
174 // log_warning("[RealSenseNode] get_last_grabbed_pcl is nullptr");
175 // continue;
176 // }
177 
178 // std::unique_ptr<sensor_msgs::msg::PointCloud2> pointCloudMsgSPtr = std::make_unique<sensor_msgs::msg::PointCloud2>();
179 // pcl::toROSMsg(*(std::get<1>(*msg)), *pointCloudMsgSPtr);
180 // pointCloudMsgSPtr->header.frame_id = "map";
181 // pointCloudMsgSPtr->header.stamp = std::get<0>(*msg);
182 
183 // m_depthPublisherSPtr->publish(std::move(pointCloudMsgSPtr));
184 // log("[RealSenseNode] pointcloud_publish_loop: Published. :)");
185 // }
186 // }
187 
188 rcl_interfaces::msg::SetParametersResult RealSenseNode::new_parameters_callback(const std::vector<rclcpp::Parameter>& parameters) {
189  log("[RealSenseNode] NEW PARAMETERS");
190 
191  rcl_interfaces::msg::SetParametersResult result;
192  result.successful = true;
193  result.reason = "";
194 
195  m_settingsMtx.lock();
196  for (const auto &param: parameters) {
197  if (param.get_name() == "cluster_extraction.leaf_size") {
198  if(check_parameter<double>(param, result)) {
199  m_leafSize = param.as_double();
200  }
201  }
202  else if (param.get_name() == "cluster_extraction.cluster_tolerance") {
203  if(check_parameter<double>(param, result)) {
204  m_clusterTolerance = param.as_double();
205  }
206  }
207  else if (param.get_name() == "cluster_extraction.cluster_size_min") {
208  if(check_parameter<int>(param, result, 0)) {
209  m_minClusterSize = param.as_int();
210  }
211  }
212  else if (param.get_name() == "cluster_extraction.cluster_size_max") {
213  if(check_parameter<int>(param, result, 0)) {
214  m_maxClusterSize = param.as_int();
215  }
216  }
217  // else if (param.get_name() == "region_of_interest.y_min") {
218  // if(check_parameter<double>(param, result, -10000, 10000)) {
219  // m_yMin = param.as_double();
220  // }
221  // }
222  // else if (param.get_name() == "region_of_interest.y_max") {
223  // if(check_parameter<double>(param, result, -10000, 10000)) {
224  // m_yMax = param.as_double();
225  // }
226  // }
227  else if (param.get_name() == "postprocessing.object_min_size_x") {
228  if(check_parameter<double>(param, result, 0, 100)) {
229  m_objectDetector.m_minSizeX = param.as_double();
230  }
231  }
232  else if (param.get_name() == "postprocessing.object_min_size_y") {
233  if(check_parameter<double>(param, result, 0, 100)) {
234  m_objectDetector.m_minSizeY = param.as_double();
235  }
236  }
237  else if (param.get_name() == "postprocessing.object_min_size_z") {
238  if(check_parameter<double>(param, result, 0, 100)) {
239  m_objectDetector.m_minSizeZ = param.as_double();
240  }
241  }
242  else if (param.get_name() == "postprocessing.object_max_size_x") {
243  if(check_parameter<double>(param, result, 0, 100)) {
244  m_objectDetector.m_maxSizeX = param.as_double();
245  }
246  }
247  else if (param.get_name() == "postprocessing.object_max_size_y") {
248  if(check_parameter<double>(param, result, 0, 100)) {
249  m_objectDetector.m_maxSizeY = param.as_double();
250  }
251  }
252  else if (param.get_name() == "postprocessing.object_max_size_z") {
253  if(check_parameter<double>(param, result, 0, 100)) {
254  m_objectDetector.m_maxSizeZ = param.as_double();
255  }
256  }
257  else if (param.get_name() == "postprocessing.cluster_size_min") {
258  if(check_parameter<int>(param, result, 0, 1000000)) {
260  }
261  }
262  else if (param.get_name() == "postprocessing.cluster_size_max") {
263  if(check_parameter<int>(param, result, 0, 1000000)) {
265  }
266  }
267  else {
268  result.successful = false;
269  result.reason += "[" + param.get_name() + "] UNKNOWN param or NOT IMPLEMENTED; ";
270  }
271  }
272  m_settingsMtx.unlock();
273 
274 
275  if(result.successful == false) {
276  log_warning("[RealSenseNode] Failed to set some parameters. Reasons: ", result.reason);
277  }
278 
279  log("[RealSenseNode] NEW PARAMETERS PROCESSED");
280  return result;
281 }
RealSenseNode::m_cam
Realsense m_cam
Definition: RealSenseNode.hpp:25
RealSenseNode::object_detection
void object_detection(std::shared_ptr< std::pair< rclcpp::Time, pcl::PointCloud< pcl::PointXYZ >::Ptr >> pointCloudRawPair)
Definition: RealSenseNode.cpp:88
EuclideanDetector::m_maxSizeZ
float m_maxSizeZ
Definition: PCLObjectDetector.hpp:73
galaxis::utils::log_error
void log_error(const Args &... args)
Definition: logger.hpp:50
EuclideanDetector::m_minSizeY
float m_minSizeY
Definition: PCLObjectDetector.hpp:68
GalaxisNode::enable_parameters
void enable_parameters(std::function< rcl_interfaces::msg::SetParametersResult(const std::vector< rclcpp::Parameter > &)> callbackFunc)
Definition: GalaxisNode.cpp:69
RealSenseNode::m_depthPublisherSPtr
rclcpp::Publisher< sensor_msgs::msg::PointCloud2 >::SharedPtr m_depthPublisherSPtr
Definition: RealSenseNode.hpp:32
RealSenseNode::m_listenToROSPCL
bool m_listenToROSPCL
Definition: RealSenseNode.hpp:23
EuclideanDetector::m_postProcessingClusterSizeMax
float m_postProcessingClusterSizeMax
Definition: PCLObjectDetector.hpp:76
ObstacleType
messages::msg::Obstacle ObstacleType
Definition: messages.hpp:59
node_ros_pubsub_wrapper.hpp
RealSenseNode::m_leafSize
float m_leafSize
Definition: RealSenseNode.hpp:64
RealSenseNode.hpp
RealSenseNode::m_depthSubscriberSPtr
rclcpp::Subscription< sensor_msgs::msg::PointCloud2 >::SharedPtr m_depthSubscriberSPtr
Definition: RealSenseNode.hpp:37
RealSenseNode::m_minClusterSize
unsigned int m_minClusterSize
Definition: RealSenseNode.hpp:62
json
nlohmann::json json
Definition: AutoPilotNode.hpp:21
settings.hpp
galaxis::utils::log_warning
void log_warning(const Args &... args)
Definition: logger.hpp:41
RealSenseNode::m_clusterTolerance
float m_clusterTolerance
Definition: RealSenseNode.hpp:61
pclPtrType
pcl::PointCloud< pcl::PointXYZ >::Ptr pclPtrType
Definition: PCLObjectDetector.hpp:22
galaxis::utils::read_json_file
shared_ptr< json > read_json_file(std::string path)
Definition: settings.cpp:5
Realsense::set_node
void set_node(rclcpp::Node *ptr)
Definition: DepthCamera.cpp:10
EuclideanDetector::m_minSizeX
float m_minSizeX
Definition: PCLObjectDetector.hpp:67
RealSenseNode::new_parameters_callback
rcl_interfaces::msg::SetParametersResult new_parameters_callback(const std::vector< rclcpp::Parameter > &parameters)
Definition: RealSenseNode.cpp:188
EuclideanDetector::m_postProcessingClusterSizeMin
float m_postProcessingClusterSizeMin
Definition: PCLObjectDetector.hpp:75
RealSenseNode::on_ros_pointcloud_callback
void on_ros_pointcloud_callback(sensor_msgs::msg::PointCloud2::SharedPtr pclMsg)
Definition: RealSenseNode.cpp:65
RealSenseNode::m_debugPclPublisherFiltered
rclcpp::Publisher< sensor_msgs::msg::PointCloud2 >::SharedPtr m_debugPclPublisherFiltered
Definition: RealSenseNode.hpp:33
pclType
pcl::PointCloud< pcl::PointXYZ > pclType
Definition: PCLObjectDetector.hpp:23
RealSenseNode::m_maxClusterSize
unsigned int m_maxClusterSize
Definition: RealSenseNode.hpp:63
RealSenseNode::m_debugMode
bool m_debugMode
Definition: RealSenseNode.hpp:22
RealSenseNode::m_objectDetector
EuclideanDetector m_objectDetector
Definition: RealSenseNode.hpp:39
RealSenseNode::m_debugPclPublisherResult
rclcpp::Publisher< sensor_msgs::msg::PointCloud2 >::SharedPtr m_debugPclPublisherResult
Definition: RealSenseNode.hpp:34
GalaxisNode
Definition: GalaxisNode.hpp:21
RealSenseNode::m_yMax
float m_yMax
Definition: RealSenseNode.hpp:67
RealSenseNode::m_yMin
float m_yMin
Definition: RealSenseNode.hpp:66
EuclideanDetector::cluster_data
std::shared_ptr< std::vector< pcl::PointCloud< pcl::PointXYZ >::Ptr > > cluster_data(pclPtrType p_pclPtr, std::vector< Object > &p_objectsVecRef, float clusterTolerance, int minClusterSize, int maxClusterSize) const
Definition: PCLObjectDetector.cpp:7
EuclideanDetector::m_maxSizeX
float m_maxSizeX
Definition: PCLObjectDetector.hpp:71
EuclideanDetector::m_maxSizeY
float m_maxSizeY
Definition: PCLObjectDetector.hpp:72
RealSenseNode::m_obstaclePublisher
rclcpp::Publisher< ObstacleListType >::SharedPtr m_obstaclePublisher
Definition: RealSenseNode.hpp:29
logger.hpp
PCLObjectDetector::filter_pcl
int filter_pcl(pclPtrType p_pclPtr, pclPtrType p_cloudFiltered, float p_leafsize, float y_min, float y_max)
Definition: PCLObjectDetector.hpp:38
galaxis::utils
Definition: clock.hpp:5
RealSenseNode::RealSenseNode
RealSenseNode()
Definition: RealSenseNode.cpp:24
RealSenseNode::object_detection_loop
void object_detection_loop()
Definition: RealSenseNode.cpp:74
Realsense::init
void init(std::string config)
initializes camera with json settings
Definition: DepthCamera.cpp:14
galaxis::utils::log
void log(const Args &... args)
Definition: logger.hpp:33
EuclideanDetector::m_minSizeZ
float m_minSizeZ
Definition: PCLObjectDetector.hpp:69
RealSenseNode::m_settingsMtx
std::mutex m_settingsMtx
Definition: RealSenseNode.hpp:41
DepthCamera.hpp
Realsense::pop_last_grabbed_pcl
std::shared_ptr< std::pair< rclcpp::Time, pcl::PointCloud< pcl::PointXYZ >::Ptr > > pop_last_grabbed_pcl(bool blocking)
Definition: DepthCamera.cpp:137
RealSenseNode::m_settingsJsonFilename
std::string m_settingsJsonFilename
Definition: RealSenseNode.hpp:26