Laser.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*
  2. * laser雷达核心模块,主要是负责管理所有的雷达设备,按需采集三维点。
  3. * 由上层下发任务单,雷达模块按照任务指示,进行相应的雷达扫描。
  4. * 转换和拼接为标准参考系的三维坐标点云。
  5. * 然后通过任务单返回上层。
  6. */
  7. #ifndef __LASER__HH__
  8. #define __LASER__HH__
  9. #include "Point2D.h"
  10. #include "Point3D.h"
  11. #include "LogFiles.h"
  12. #include <glog/logging.h>
  13. #include "laser_parameter.pb.h"
  14. #include "laser_task_command.h"
  15. #include "../error_code/error_code.h"
  16. #include "../tool/binary_buf.h"
  17. #include "../tool/thread_safe_queue.h"
  18. #include "../tool/thread_condition.h"
  19. //雷达工作状态,基类三线程的状态
  20. //connect_laser 和 disconnect_laser 中要切换状态 LASER_DISCONNECT <===> LASER_READY
  21. //start_scan 和 stop_scan 和 end_task 中要切换状态 LASER_READY <===> LASER_BUSY
  22. enum Laser_statu
  23. {
  24. //默认值 LASER_DISCONNECT =0
  25. LASER_DISCONNECT =0, //雷达断连
  26. LASER_READY =1, //雷达正常待机,空闲
  27. LASER_BUSY =2, //雷达正在工作,正忙
  28. LASER_FAULT =3, //雷达错误
  29. };
  30. //雷达变换矩阵的数组长度,默认为12个参数, size = 3 * ( 3 + 1 ) ,旋转加平移,没有缩放
  31. #define LASER_MATRIX_ARRAY_SIZE 12
  32. //雷达的基类,不能直接使用,必须子类继承
  33. class Laser_base
  34. {
  35. public:
  36. Laser_base() = delete;
  37. Laser_base(const Laser_base& other) = delete;
  38. //唯一的构造函数,按照设备名称和雷达参数来创建实例。
  39. //input:id: 雷达设备的id,(唯一索引)
  40. //input:laser_param:雷达的参数,
  41. //注:利用protobuf创建 laser_parameter 类,然后从文件读取参数
  42. Laser_base(int laser_id,Laser_proto::laser_parameter laser_param);
  43. //析构函数
  44. ~Laser_base();
  45. //雷达链接设备,为3个线程添加线程执行函数。
  46. virtual Error_manager connect_laser();
  47. //雷达断开链接,释放3个线程
  48. virtual Error_manager disconnect_laser();
  49. //对外的接口函数,负责接受并处理任务单,
  50. //input:p_laser_task 雷达任务单,基类的指针,指向子类的实例,(多态)
  51. //注:这个函数为虚函数,实际的处理任务的代码由子类重载并实现。
  52. virtual Error_manager execute_task(Task_Base* p_laser_task);
  53. //检查雷达状态,是否正常运行
  54. virtual Error_manager check_status();
  55. //雷达的启动接口函数, 让雷达进行扫描,一般需要子类重载,不同的雷达开始方式不同。
  56. virtual Error_manager start_scan();
  57. //雷达的停止接口函数, 让雷达停止扫描,一般需要子类重载,不同的雷达结束方式不同。
  58. virtual Error_manager stop_scan();
  59. //结束任务单,stop之后,要检查线程状态和数据结果,然后才能 end_task
  60. virtual Error_manager end_task();
  61. //取消任务单,由发送方提前取消任务单
  62. virtual Error_manager cancel_task();
  63. public:
  64. //设置保存文件的路径,并打开文件,
  65. Error_manager set_open_save_path(std::string save_path,bool is_save=true);
  66. //关闭保存文件,推出前一定要执行
  67. Error_manager close_save_path();
  68. //判断雷达状态是否为待机,如果已经准备好,则可以执行任务。
  69. //子类重载 is_ready(),里面增加livox sdk后台线程状态的判断。
  70. virtual bool is_ready();
  71. //获取雷达id
  72. int get_laser_id();
  73. //设置变换矩阵,用作三维点的坐标变换,
  74. Error_manager set_laser_matrix(double* p_matrix, int size);
  75. protected:
  76. //接受二进制消息的功能函数,并将其存入 m_queue_laser_data, 每次只转化一个CBinaryData,
  77. // 纯虚函数,必须由子类重载,
  78. virtual Error_manager receive_buf_to_queue() = 0;
  79. //线程执行函数,将二进制消息存入队列缓存,
  80. void thread_receive();
  81. //将二进制消息转化为三维点云的功能函数,并将其存入 任务单 , 每次只转化一个CBinaryData,
  82. // 纯虚函数,必须由子类重载,
  83. virtual Error_manager transform_buf_to_points()=0;
  84. //线程执行函数,转化并处理三维点云。
  85. void thread_transform();
  86. //公开发布雷达信息的功能函数,
  87. Error_manager publish_laser_to_message();
  88. //线程执行函数,公开发布雷达的相关信息,用作上位机的监视。
  89. static void thread_publish(Laser_base* p_laser);
  90. //获取雷达状态
  91. Laser_statu get_laser_statu();
  92. protected:
  93. //初始化变换矩阵,设置默认值
  94. Error_manager init_laser_matrix();
  95. //三维点的坐标变换的功能函数,从雷达自己的坐标系,转化到公共坐标系,(目前以plc为公共坐标系)
  96. virtual CPoint3D transform_by_matrix(CPoint3D point);
  97. protected:
  98. //为了保证多线程的数据安全,修改共享数据必须加锁。 atomic 和 安全队列 可以不加锁进行读写
  99. //建议:判断标志位使用 atomic, 容器要封装并使用 安全容器,
  100. // std::mutex m_laser_lock; //雷达数据锁
  101. std::atomic<int> m_laser_id; //雷达设备id
  102. Laser_proto::laser_parameter m_laser_param; //雷达的配置参数
  103. //雷达变换矩阵,三维点的坐标变换的矩阵,从雷达自己的坐标系,转化到公共坐标系,(目前以plc为公共坐标系)
  104. //必须在set_laser_matrix之后,才能使用。(connect时,从雷达的配置参数导入)
  105. double mp_laser_matrix[LASER_MATRIX_ARRAY_SIZE]; //雷达变换矩阵
  106. //雷达扫描事件的标志位,受start和stop控制,然后其他线程判断m_scan_flag标准位,来进行启停。
  107. std::atomic<bool> m_laser_scan_flag; //雷达扫描的使能标志位
  108. //雷达状态和任务状态同步,m_scan_flag停止之后,还要等任务执行完成,才会切回 ready。
  109. std::atomic<Laser_statu> m_laser_statu; //雷达工作状态,基类三线程的状态
  110. //注:m_laser_statu是基类的三线程的状态,和livox sdk后台线程状态没有任何关系。
  111. //子类重载 is_ready(),里面增加livox sdk后台线程状态的判断。
  112. std::atomic<int> m_points_count; //雷达采集点的计数
  113. Thread_safe_queue<Binary_buf*> m_queue_laser_data; //二进制缓存的队列容器
  114. Binary_buf m_last_data; //上一个二进制缓存,用作数据拼接
  115. std::atomic<bool> m_save_flag; //雷达保存文件的使能标志位
  116. std::string m_save_path; //雷达保存文件的保存路径
  117. CLogFile m_binary_log_tool; //二进制缓存的日志工具
  118. CLogFile m_points_log_tool; //三维点云的日志工具
  119. //线程指针的内存管理,由Connect和Disconnect进行分配和释放。
  120. std::thread* mp_thread_receive; //接受缓存的线程指针
  121. Thread_condition m_condition_receive; //接受缓存的条件变量
  122. std::thread* mp_thread_transform; //转化数据的线程指针
  123. Thread_condition m_condition_transform; //转化数据的条件变量
  124. std::thread* mp_thread_publish; //发布信息的线程指针
  125. Thread_condition m_condition_publish; //发布信息的条件变量
  126. //任务单的指针,实际内存由应用层管理,
  127. //接受任务后,指向新的任务单
  128. Laser_task * mp_laser_task; //任务单的指针
  129. };
  130. //雷达的注册类,
  131. //雷达模块可能有多个不同的雷达,这些雷达需要制定不同的子类,从laser基类继承。
  132. //使用类的多态,从基类操作不同的子类。
  133. //雷达的注册器为单例模式,没有任何成员变量。
  134. //里面定义了 static std::map<std::string, CreateLaserFunc>* g_map 注册表,作为永久的内存。
  135. //然后提供了注册函数和访问函数,来操作这段静态变量(唯一,永久)
  136. class LaserRegistory
  137. {
  138. typedef Laser_base* (*CreateLaserFunc)(int id, Laser_proto::laser_parameter laser_param);
  139. public:
  140. LaserRegistory(std::string name, CreateLaserFunc pFun) {
  141. AddCreator(name, pFun);
  142. }
  143. static Laser_base* CreateLaser(std::string name, int id,Laser_proto::laser_parameter laser_param) {
  144. if (GetFuncMap().count(name) == 0)
  145. return 0;
  146. return GetFuncMap()[name](id,laser_param);
  147. }
  148. private:
  149. static std::map<std::string, CreateLaserFunc>& GetFuncMap() {
  150. static std::map<std::string, CreateLaserFunc>* g_map = new std::map<std::string, CreateLaserFunc>;
  151. return *g_map;
  152. }
  153. void AddCreator(std::string name, CreateLaserFunc pFun) {
  154. GetFuncMap()[name] = pFun;
  155. }
  156. };
  157. #define RegisterLaser(NAME) \
  158. static Laser_base* Create_##NAME##_Laser(int id, Laser_proto::laser_parameter param) \
  159. { \
  160. return new C##NAME##Laser(id,param); \
  161. } \
  162. LaserRegistory g_##NAME##_Laser(#NAME,Create_##NAME##_Laser);
  163. #endif