ground_region.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. //
  2. // Created by zx on 2021/5/20.
  3. //
  4. #pragma once
  5. #include <thread>
  6. #include <fcntl.h>
  7. #include <algorithm>
  8. #include <opencv2/opencv.hpp>
  9. #include <pcl/point_types.h>
  10. #include <pcl/point_cloud.h>
  11. #include <pcl/common/transforms.h>
  12. #include <pcl/filters/voxel_grid.h>
  13. #include <pcl/filters/crop_hull.h>
  14. #include <pcl/surface/convex_hull.h>
  15. #include <pcl/surface/concave_hull.h>
  16. #include <pcl/segmentation/extract_clusters.h>
  17. #include <pcl/filters/approximate_voxel_grid.h>
  18. #include <pcl/filters/statistical_outlier_removal.h>
  19. #include "tool/point_tool.h"
  20. #include "tool/measure_filter.h"
  21. #include "tool/region_status_checker.h"
  22. #include "tool/thread_condition.h"
  23. #include "tool/common_data.h"
  24. #include "tool/point3D_tool.h"
  25. #include "tool/static_tool.hpp"
  26. #include "tool/memory_box.hpp"
  27. #include "system/system_communication_mq.h"
  28. #include "error_code/error_code.hpp"
  29. #include "match3d/detect_wheel_ceres3d.h"
  30. #include "velodyne_config.pb.h"
  31. #include "message/measure_message.pb.h"
  32. #include "verify/Verify_result.h"
  33. #include "car_pose_detector.h"
  34. #include "chassis_ceres_solver.h"
  35. #include "match3d/WheelFactor.h"
  36. class Ground_region {
  37. public:
  38. // 点云类型,用于外部获取存储的不同的点云
  39. enum Region_cloud_type {
  40. total = 0,
  41. left_front = 1,
  42. left_back = 2,
  43. right_front = 3,
  44. right_back = 4,
  45. filtered = 5,
  46. failure = 6,
  47. trans = 7,
  48. };
  49. // 工作状态
  50. enum Ground_region_status {
  51. E_UNKNOWN = 0, //未知
  52. E_READY = 1, //准备,待机
  53. E_BUSY = 2, //工作正忙
  54. E_FAULT = 10, //故障
  55. };
  56. #define GROUND_REGION_DETECT_CYCLE_MS 500
  57. Ground_region();
  58. ~Ground_region();
  59. // 区域类初始化
  60. Error_manager init(velodyne::Region region, pcl::PointCloud<pcl::PointXYZ>::Ptr left_model,
  61. pcl::PointCloud<pcl::PointXYZ>::Ptr right_model);
  62. // 公有检测函数,根据初始化设置的区域进行裁剪,并识别获得结果
  63. Error_manager detect(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, detect_wheel_ceres3d::Detect_result &result);
  64. // 公有点云更新函数,传入最新点云获得结果
  65. Error_manager update_cloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud);
  66. //外部调用获取当前车轮定位信息, 获取指令时间之后的车轮定位信息, 如果没有就会报错, 不会等待
  67. Error_manager get_current_wheel_information(Common_data::Car_wheel_information *p_car_wheel_information,
  68. std::chrono::system_clock::time_point command_time);
  69. Error_manager get_last_wheel_information(std::vector<Common_data::Car_wheel_information> &car_wheel_information,
  70. std::chrono::system_clock::time_point command_time);
  71. /**
  72. * @description 获取最后一次算法运行结果的plc正向算法结果消息;
  73. * @param p_car_wheel_information 测量结果结果指针;
  74. * @param command_time 时间点,获取该时间点500ms以前到该时间点的算法结果;
  75. * @return 如果没有就会报错, 不会等待;
  76. **/
  77. Error_manager get_last_forward_wheel_information(Common_data::Car_wheel_information *p_car_wheel_information,
  78. std::chrono::system_clock::time_point command_time);
  79. /**
  80. * @description 获取最后一次算法运行结果的plc反向算法结果消息;
  81. * @param p_car_wheel_information 测量结果结果指针;
  82. * @param command_time 时间点,获取该时间点500ms以前到该时间点的算法结果;
  83. * @return 如果没有就会报错, 不会等待;
  84. **/
  85. Error_manager get_last_reverse_wheel_information(Common_data::Car_wheel_information *p_car_wheel_information,
  86. std::chrono::system_clock::time_point command_time);
  87. /**
  88. * @description 获取最后一次算法运行结果的终端算法结果消息;
  89. * @param p_car_wheel_information 测量结果结果指针;
  90. * @param command_time 时间点,获取该时间点500ms以前到该时间点的算法结果;
  91. * @return 如果没有就会报错, 不会等待;
  92. **/
  93. Error_manager get_last_terminal_wheel_information(Common_data::Car_wheel_information *p_car_wheel_information,
  94. std::chrono::system_clock::time_point command_time);
  95. /**
  96. * @description 获取算法最后一次计算时的各种点云,需要指出哪个点云;
  97. * @param out_cloud 点云引用,结果在这个里面,会对输入点云进行一次清除操作;
  98. * @param type 点云种类,根据Region_cloud_type确定;
  99. * @return 无;
  100. **/
  101. void get_region_cloud(pcl::PointCloud<pcl::PointXYZ>::Ptr &out_cloud, const Region_cloud_type &type);
  102. /**
  103. * @brief 获取区域终端号;
  104. * @param 无;
  105. * @return 未初始化调用将返回-1;
  106. **/
  107. int get_terminal_id();
  108. // 获取区域状态
  109. Ground_region_status get_status() { return m_region_status; }
  110. // 获取更新时间
  111. std::chrono::system_clock::time_point get_detect_update_time() { return m_detect_update_time; }
  112. // 获取配置参数
  113. velodyne::Region get_param() { return m_region; }
  114. /**
  115. * @description 检查激光是否在区域中;
  116. * @param lidar_id 雷达id;
  117. * @return 在为true, 不在为false;
  118. **/
  119. bool check_lidar_inside(const int &lidar_id);
  120. private:
  121. /**
  122. * @description 对点云进行裁减滤波,然后通过欧式聚类判断是否存在四块点云,如果存在且可以构成矩形,通过ceres对点云进行车轮参数寻优;
  123. * @param cloud 输入点云;
  124. * @param thresh_z 保留该值以下的点云;
  125. * @param result ceres库寻优结果;
  126. * @return true:成功,false:失败;
  127. **/
  128. bool classify_ceres_detect(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, double thresh_z,
  129. detect_wheel_ceres3d::Detect_result &result, std::string &error);
  130. /**
  131. * @description 算法测量线程函数,在这个线程中不断对点云进行算法检测;
  132. **/
  133. void thread_measure_func();
  134. /**
  135. * @description 欧式聚类,pcl接口二次封装;
  136. * @param sor_cloud 输入点云;
  137. * @param tolerance 聚类距离参数
  138. * @return 各个类的点云,存储在std的vector中;
  139. **/
  140. std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> segmentation(pcl::PointCloud<pcl::PointXYZ>::Ptr &sor_cloud, const float &tolerance);
  141. /**
  142. * @description 判断输入点是否是一个近似的矩形(直角边与坐标轴的夹角 <20°);
  143. * @param points 四个点的坐标信息(如果是三个点会模拟补全);
  144. * @return true:类矩形,false:非矩形;
  145. **/
  146. bool isRect(std::vector<cv::Point2f> &points);
  147. /**
  148. * @description 对坐标经过plc偏移转换过的算法检测结果根据输入的超界限制给出超界判断结果;
  149. * @param measure_result 算法检测的结果;
  150. * @param out_info 超界范围限制信息;
  151. * @return 超界结果,按Range_status进行位组合;
  152. **/
  153. int outOfRangeDetection(Common_data::Car_wheel_information &measure_result, const velodyne::outOfRangeInfo &out_info, detect_wheel_ceres3d::Detect_result &result);
  154. void getMSE(MemoryBox<double> &box, float &value);
  155. /**
  156. * @description 对输入的两个测量结果作对比,给出误差率;
  157. * @param first 测量结果1;
  158. * @param second 测量结果2;
  159. * @return 测量结果平均波动与波动标准的比;
  160. **/
  161. bool CompareCeresResult(detect_wheel_ceres3d::Detect_result &first, detect_wheel_ceres3d::Detect_result &second);
  162. private:
  163. std::chrono::steady_clock::time_point m_last_move_time = std::chrono::steady_clock::now();
  164. velodyne::Region m_region; // 区域配置
  165. detect_wheel_ceres3d *m_detector; // 检测器
  166. Ground_region_status m_region_status; // 区域状态
  167. // 自动检测线程
  168. std::thread *m_measure_thread;
  169. Thread_condition m_measure_condition;
  170. std::mutex m_cloud_collection_mutex; // 点云更新互斥锁, 内存由上级管理
  171. pcl::PointCloud<pcl::PointXYZ>::Ptr mp_cloud_collection; // 扫描点的点云集合, 内存由上级管理
  172. std::chrono::system_clock::time_point m_cloud_collection_time; // 点云更新时间
  173. std::mutex m_detect_failture_cloud_collection_mutex; // 点云检测失败更新互斥锁, 内存由上级管理
  174. pcl::PointCloud<pcl::PointXYZ>::Ptr mp_detect_failture_cloud_collection; // 扫描点的点云检测失败集合, 内存由上级管理
  175. std::chrono::steady_clock::time_point m_detect_failture_cloud_collection_time; // 检测失败的点云更新时间
  176. std::mutex m_filtered_cloud_mutex; // 点云更新互斥锁, 内存由上级管理
  177. pcl::PointCloud<pcl::PointXYZ>::Ptr mp_cloud_filtered; // 区域切除后的点
  178. std::mutex m_detect_z_cloud_mutex; // 点云更新互斥锁, 内存由上级管理
  179. pcl::PointCloud<pcl::PointXYZ>::Ptr mp_cloud_detect_z; // 底盘切除后的点
  180. std::mutex m_car_result_mutex; // 测量结果互斥锁
  181. std::chrono::system_clock::time_point m_detect_update_time; // 定位结果的更新时间.
  182. Common_data::Car_wheel_information m_car_wheel_forward_information; // 车轮的定位结果,
  183. Common_data::Car_wheel_information m_car_wheel_reverse_information; // 车轮的定位结果,
  184. Common_data::Car_wheel_information m_car_wheel_terminal_information; // 车轮的定位结果,
  185. Common_data::Car_information m_car_information;
  186. MemoryBox<double> m_car_cx_box; // 存储的近期车辆轴线坐标
  187. MemoryBox<double> m_car_theta_box; // 存储的近期车辆车身偏转角度
  188. MemoryBox<double> m_car_width_box; // 存储的近期车辆宽度信息
  189. MemoryBox<double> m_car_wheel_base_box; // 存储的近期车辆轴距信息
  190. // 裁剪块
  191. std::vector<pcl::Vertices> m_polygons; //设置动态数组用于保存凸包顶点
  192. pcl::PointCloud<pcl::PointXYZ>::Ptr m_surface_hull; //设置点云用于描述凸包的形状
  193. // 车辆中心优化
  194. WheelsPredictor m_predictor;
  195. int last_range_statu;
  196. #define SaveWheelsData 1
  197. #if SaveWheelsData
  198. int current_index = 0;
  199. #endif
  200. };