velodyne_lidar_device.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. #include "velodyne_lidar_device.h"
  2. // 万集雷达封装类构造函数
  3. Velodyne_lidar_device::Velodyne_lidar_device()
  4. {
  5. m_velodyne_lidar_device_status = E_UNKNOWN;
  6. mp_velodyne_lidar_scan_task = NULL;
  7. }
  8. // 万集雷达封装类析构函数
  9. Velodyne_lidar_device::~Velodyne_lidar_device()
  10. {
  11. uninit();
  12. }
  13. void Velodyne_lidar_device::dev_info_config(std::string model, int rpm)
  14. {
  15. double packet_rate; // packet frequency (Hz)
  16. std::string model_full_name;
  17. if ((model == "VLS128"))
  18. {
  19. packet_rate = 6253.9; // 3 firing cycles in a data packet. 3 x 53.3 μs = 0.1599 ms is the accumulation delay per packet.
  20. // 1 packet/0.1599 ms = 6253.9 packets/second
  21. model_full_name = model;
  22. }
  23. else if ((model == "64E_S2") ||
  24. (model == "64E_S2.1")) // generates 1333312 points per second
  25. { // 1 packet holds 384 points
  26. packet_rate = 3472.17; // 1333312 / 384
  27. model_full_name = std::string("HDL-") + model;
  28. }
  29. else if (model == "64E")
  30. {
  31. packet_rate = 2600.0;
  32. model_full_name = std::string("HDL-") + model;
  33. }
  34. else if (model == "64E_S3") // generates 2222220 points per second (half for strongest and half for lastest)
  35. { // 1 packet holds 384 points
  36. packet_rate = 5787.03; // 2222220 / 384
  37. model_full_name = std::string("HDL-") + model;
  38. }
  39. else if (model == "32E")
  40. {
  41. packet_rate = 1808.0;
  42. model_full_name = std::string("HDL-") + model;
  43. }
  44. else if (model == "32C")
  45. {
  46. packet_rate = 1507.0;
  47. model_full_name = std::string("VLP-") + model;
  48. }
  49. else if (model == "VLP16")
  50. {
  51. packet_rate = 754; // 754 Packets/Second for Last or Strongest mode 1508 for dual (VLP-16 User Manual)
  52. model_full_name = "VLP-16";
  53. }
  54. else
  55. {
  56. LOG(WARNING) << "unknown Velodyne LIDAR model: " << model;
  57. packet_rate = 2600.0;
  58. }
  59. std::string deviceName(std::string("Velodyne ") + model_full_name);
  60. LOG(INFO) << deviceName << " rotating at " << rpm << " RPM";
  61. double frequency = (rpm / 60.0); // expected Hz rate
  62. // default number of packets for each scan is a single revolution
  63. // (fractions rounded up)
  64. m_num_packet_per_scan = (int)ceil(packet_rate / frequency);
  65. LOG(INFO) << "publishing " << m_num_packet_per_scan << " packets per scan";
  66. }
  67. // 初始化
  68. Error_manager Velodyne_lidar_device::init(velodyne::velodyneLidarParams params)
  69. {
  70. m_params = params;
  71. Error_manager t_error;
  72. LOG(INFO) << " Velodyne_lidar_device::init " << this;
  73. m_num_packet_inside = 0;
  74. dev_info_config(params.model(), params.rpm());
  75. m_velodyne_lidar_device_status = E_UNKNOWN;
  76. m_velodyne_socket_status = E_UNKNOWN;
  77. m_velodyne_protocol_status = E_UNKNOWN;
  78. m_lidar_id = params.lidar_id();
  79. // 设置雷达内参矩阵
  80. Eigen::AngleAxisd rot_x = Eigen::AngleAxisd(params.calib().r()*M_PI/180.0, Eigen::Vector3d::UnitX());
  81. Eigen::AngleAxisd rot_y = Eigen::AngleAxisd(params.calib().p()*M_PI/180.0, Eigen::Vector3d::UnitY());
  82. Eigen::AngleAxisd rot_z = Eigen::AngleAxisd(params.calib().y()*M_PI/180.0, Eigen::Vector3d::UnitZ());
  83. Eigen::Vector3d trans(params.calib().cx(), params.calib().cy(), params.calib().cz());
  84. m_calib_matrix << rot_x.toRotationMatrix() * rot_y.toRotationMatrix() * rot_z.toRotationMatrix(), trans, 0.0, 0.0, 0.0, 1.0;
  85. // LOG(INFO) <<"lidar "<<m_lidar_id<<",,,\n"<< rot_x.toRotationMatrix()<<"------------------\n"<<rot_y.toRotationMatrix()<<"-----------------\n"<<rot_z.toRotationMatrix()<<"---------------\n"<<m_calib_matrix;
  86. //唤醒队列
  87. m_communication_data_queue.wake_queue();
  88. // //初始化通信协议
  89. // t_error = m_protocol.setup(params.model(), params.calibrationfile(), params.max_range(), params.min_range(), params.min_angle(), params.max_angle()) == true ? SUCCESS : Error_manager(PARAMETER_ERROR, MINOR_ERROR, "protocol parameter error");
  90. // if (t_error != SUCCESS)
  91. // {
  92. // return t_error;
  93. // }
  94. m_velodyne_protocol_status = E_READY;
  95. //初始化雷达通信模块
  96. // std::string t_ip = params.ip();
  97. // int t_port = params.port();
  98. m_cloud_data = new CloudDataMqttAsync;
  99. t_error = m_cloud_data->init() ? SUCCESS : Error_manager(VELODYNE_LIDAR_CONNECT_FAILED, MINOR_ERROR, "socket connect failed");
  100. if (t_error != SUCCESS)
  101. {
  102. // LOG(ERROR) << "Velodyne_lidar_device::init failed: ip = " << t_ip << " : " << t_port;
  103. LOG(ERROR) << "Velodyne_lidar_device::init failed: error = " << t_error.to_string();
  104. return t_error;
  105. }
  106. m_velodyne_socket_status = E_READY;
  107. //启动 内部线程。默认wait。
  108. m_execute_condition.reset(false, false, false);
  109. mp_execute_thread = new std::thread(&Velodyne_lidar_device::execute_thread_fun, this);
  110. m_velodyne_lidar_device_status = E_READY;
  111. return t_error;
  112. }
  113. //反初始化
  114. Error_manager Velodyne_lidar_device::uninit()
  115. {
  116. // //终止队列,防止 wait_and_pop 阻塞线程。
  117. m_communication_data_queue.termination_queue();
  118. m_communication_data_queue.clear();
  119. //关闭线程
  120. //回收线程的资源
  121. if (mp_execute_thread)
  122. {
  123. m_execute_condition.kill_all();
  124. mp_execute_thread->join();
  125. delete mp_execute_thread;
  126. mp_execute_thread = nullptr;
  127. }
  128. delete m_cloud_data;
  129. m_cloud_data = nullptr;
  130. //清空队列
  131. m_communication_data_queue.clear_and_delete();
  132. if (m_velodyne_lidar_device_status != E_FAULT)
  133. {
  134. m_velodyne_lidar_device_status = E_UNKNOWN;
  135. }
  136. return Error_code::SUCCESS;
  137. }
  138. //对外的接口函数,负责接受并处理任务单,
  139. Error_manager Velodyne_lidar_device::execute_task(Task_Base *p_velodyne_lidar_scan_task)
  140. {
  141. LOG(INFO) << " ---Laser_manager::execute_task run--- " << this;
  142. Error_manager t_error;
  143. Error_manager t_result;
  144. //检查指针
  145. if (p_velodyne_lidar_scan_task == nullptr)
  146. {
  147. return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
  148. "Velodyne_lidar_device::execute_task failed, POINTER_IS_NULL");
  149. }
  150. //检查任务类型,
  151. if (p_velodyne_lidar_scan_task->get_task_type() != VELODYNE_LIDAR_SCAN)
  152. {
  153. return Error_manager(Error_code::VELODYNE_LIDAR_DEVICE_TASK_TYPE_ERROR, Error_level::MINOR_ERROR,
  154. " task type error != VELODYNE_LIDAR_SCAN ");
  155. }
  156. //检查接收方的状态
  157. t_error = check_status();
  158. if (t_error != SUCCESS)
  159. {
  160. t_result.compare_and_cover_error(t_error);
  161. }
  162. else
  163. {
  164. //接受任务,并将任务的状态改为TASK_SIGNED已签收
  165. mp_velodyne_lidar_scan_task = (Velodyne_lidar_scan_task *)p_velodyne_lidar_scan_task;
  166. mp_velodyne_lidar_scan_task->set_task_statu(TASK_SIGNED);
  167. //检查消息内容是否正确,
  168. //检查三维点云指针
  169. if (mp_velodyne_lidar_scan_task->get_task_point_cloud().get() == nullptr)
  170. {
  171. t_error.error_manager_reset(Error_code::POINTER_IS_NULL,
  172. Error_level::MINOR_ERROR,
  173. "execute_task mp_task_point_cloud is null");
  174. t_result.compare_and_cover_error(t_error);
  175. }
  176. else if (mp_velodyne_lidar_scan_task->get_task_cloud_lock() == nullptr)
  177. {
  178. t_error.error_manager_reset(Error_code::POINTER_IS_NULL,
  179. Error_level::MINOR_ERROR,
  180. "execute_task mp_task_cloud_lock is null");
  181. t_result.compare_and_cover_error(t_error);
  182. }
  183. else
  184. {
  185. m_velodyne_lidar_device_status = E_BUSY;
  186. //启动雷达管理模块,的核心工作线程
  187. m_execute_condition.notify_all(true);
  188. //通知 thread_work 子线程启动。
  189. //将任务的状态改为 TASK_WORKING 处理中
  190. mp_velodyne_lidar_scan_task->set_task_statu(TASK_WORKING);
  191. }
  192. //return 之前要填充任务单里面的错误码.
  193. if (t_result != Error_code::SUCCESS)
  194. {
  195. //忽略轻微故障
  196. if (t_result.get_error_level() >= Error_level::MINOR_ERROR)
  197. {
  198. //将任务的状态改为 TASK_ERROR 结束错误
  199. mp_velodyne_lidar_scan_task->set_task_statu(TASK_ERROR);
  200. }
  201. //返回错误码
  202. mp_velodyne_lidar_scan_task->compare_and_cover_task_error_manager(t_result);
  203. }
  204. }
  205. return t_result;
  206. }
  207. //检查雷达状态,是否正常运行
  208. Error_manager Velodyne_lidar_device::check_status()
  209. {
  210. updata_status();
  211. if (m_velodyne_lidar_device_status == E_READY)
  212. {
  213. return Error_code::SUCCESS;
  214. }
  215. else if (m_velodyne_lidar_device_status == E_BUSY)
  216. {
  217. return Error_manager(Error_code::VELODYNE_LIDAR_DEVICE_STATUS_BUSY, Error_level::NEGLIGIBLE_ERROR,
  218. " Velodyne_lidar_device::check_status() error ");
  219. }
  220. else
  221. {
  222. return Error_manager(Error_code::VELODYNE_LIDAR_DEVICE_STATUS_ERROR, Error_level::MINOR_ERROR,
  223. " Velodyne_lidar_device::check_status() error ");
  224. }
  225. return Error_code::SUCCESS;
  226. }
  227. //结束任务单,里面会根据任务的故障等级修正雷达管理模块的状态和任务单的状态
  228. Error_manager Velodyne_lidar_device::end_task()
  229. {
  230. m_execute_condition.notify_all(false);
  231. if (m_velodyne_lidar_device_status == E_BUSY)
  232. {
  233. m_velodyne_lidar_device_status = E_READY;
  234. }
  235. //else 状态不变
  236. //在结束任务单时,将雷达任务状态改为 TASK_OVER 已结束
  237. if (mp_velodyne_lidar_scan_task != NULL)
  238. {
  239. //判断任务单的错误等级,
  240. if (mp_velodyne_lidar_scan_task->get_task_error_manager().get_error_level() < Error_level::MINOR_ERROR)
  241. {
  242. //强制改为TASK_OVER,不管它当前在做什么。
  243. mp_velodyne_lidar_scan_task->set_task_statu(TASK_OVER);
  244. }
  245. else
  246. {
  247. //强制改为 TASK_ERROR,不管它当前在做什么。
  248. mp_velodyne_lidar_scan_task->set_task_statu(TASK_ERROR);
  249. }
  250. }
  251. return Error_code::SUCCESS;
  252. }
  253. //取消任务单,由发送方提前取消任务单
  254. Error_manager Velodyne_lidar_device::cancel_task(Task_Base *p_velodyne_lidar_scan_task)
  255. {
  256. if (p_velodyne_lidar_scan_task == mp_velodyne_lidar_scan_task)
  257. {
  258. m_execute_condition.notify_all(false);
  259. if (m_velodyne_lidar_device_status == E_BUSY)
  260. {
  261. m_velodyne_lidar_device_status = E_READY;
  262. }
  263. //else 状态不变
  264. //强制改为 TASK_DEAD,不管它当前在做什么。
  265. mp_velodyne_lidar_scan_task->set_task_statu(TASK_DEAD);
  266. return Error_code::SUCCESS;
  267. }
  268. else
  269. {
  270. return Error_manager(Error_code::PARAMETER_ERROR, Error_level::MINOR_ERROR,
  271. " Velodyne_lidar_device::cancel_task PARAMRTER ERROR ");
  272. }
  273. }
  274. //判断是否为待机,如果已经准备好,则可以执行任务。
  275. bool Velodyne_lidar_device::is_ready()
  276. {
  277. updata_status();
  278. return m_velodyne_lidar_device_status == E_READY;
  279. }
  280. //外部调用获取新的点云, 获取指令时间之后的点云, 如果没有就会等待点云刷新, 直到超时, (内置while)
  281. Error_manager Velodyne_lidar_device::get_new_cloud_and_wait(std::mutex *p_mutex, pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud,
  282. std::chrono::steady_clock::time_point command_time, int timeout_ms)
  283. {
  284. if (p_mutex == NULL || p_cloud.get() == NULL)
  285. {
  286. return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
  287. " POINTER IS NULL ");
  288. }
  289. //判断是否超时
  290. while (std::chrono::steady_clock::now() - command_time < std::chrono::milliseconds(timeout_ms))
  291. {
  292. //获取指令时间之后的点云, 如果没有就会循环
  293. if (m_parse_ring_time > command_time)
  294. {
  295. std::unique_lock<std::mutex> lck(*p_mutex);
  296. {
  297. std::lock_guard<std::mutex> lck(m_cloud_mutex);
  298. m_cloud_data->getCloudData("", p_cloud);
  299. if (p_cloud->empty()) {
  300. return VELODYNE_LIDAR_DEVICE_NO_CLOUD;
  301. }
  302. }
  303. return SUCCESS;
  304. }
  305. //else 等待下一次数据更新
  306. //等1ms
  307. std::this_thread::sleep_for(std::chrono::milliseconds(1));
  308. }
  309. //超时退出就报错
  310. return Error_manager(Error_code::VELODYNE_LIDAR_GET_CLOUD_TIMEOUT, Error_level::MINOR_ERROR,
  311. " Velodyne_lidar_device::get_new_cloud_and_wait error ");
  312. }
  313. //外部调用获取当前点云, 获取指令时间之后的点云, 如果没有就会报错, 不会等待
  314. Error_manager Velodyne_lidar_device::get_current_cloud(std::mutex *p_mutex, pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud,
  315. std::chrono::steady_clock::time_point command_time)
  316. {
  317. if (p_mutex == NULL || p_cloud.get() == NULL)
  318. {
  319. return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
  320. " POINTER IS NULL ");
  321. }
  322. //获取指令时间之后的点云, 如果没有就会报错, 不会等待
  323. if (m_parse_time > command_time)
  324. {
  325. std::unique_lock<std::mutex> lck(*p_mutex);
  326. {
  327. std::lock_guard<std::mutex> lck(m_cloud_mutex);
  328. m_cloud_data->getCloudData("", p_cloud);
  329. if (p_cloud->empty()) {
  330. return VELODYNE_LIDAR_DEVICE_NO_CLOUD;
  331. }
  332. }
  333. return SUCCESS;
  334. }
  335. else
  336. {
  337. return Error_manager(Error_code::VELODYNE_LIDAR_DEVICE_NO_CLOUD, Error_level::MINOR_ERROR,
  338. " Velodyne_lidar_device::get_current_cloud error ");
  339. }
  340. }
  341. //外部调用获取最新的点云, 如果没有就会报错, 不会等待
  342. Error_manager Velodyne_lidar_device::get_last_cloud(std::mutex *p_mutex, pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud,
  343. std::chrono::steady_clock::time_point command_time)
  344. {
  345. if (p_mutex == nullptr || p_cloud.get() == nullptr)
  346. {
  347. return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
  348. " POINTER IS NULL ");
  349. }
  350. if (m_parse_ring_time > command_time - std::chrono::milliseconds(int(60000.0/(m_params.rpm()*0.5))))
  351. {
  352. std::unique_lock<std::mutex> lck(*p_mutex);
  353. {
  354. std::lock_guard<std::mutex> lck(m_cloud_mutex);
  355. m_cloud_data->getCloudData("", p_cloud);
  356. if (p_cloud->empty()) {
  357. return VELODYNE_LIDAR_DEVICE_NO_CLOUD;
  358. }
  359. }
  360. return SUCCESS;
  361. }
  362. else
  363. {
  364. return Error_manager(Error_code::VELODYNE_LIDAR_DEVICE_NO_CLOUD, Error_level::MINOR_ERROR,
  365. " Velodyne_lidar_device::get_current_cloud error ");
  366. }
  367. }
  368. //外部调用获取最新的点云, 获取指令时间往前一个周期内的点云, 如果没有就会报错, 不会等待
  369. //注:函数内部不加锁, 由外部统一加锁.
  370. Error_manager Velodyne_lidar_device::get_last_cloud(pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud,
  371. std::chrono::steady_clock::time_point command_time)
  372. {
  373. if (p_cloud.get() == NULL)
  374. {
  375. return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
  376. " POINTER IS NULL ");
  377. }
  378. if (m_parse_ring_time > command_time - std::chrono::milliseconds(int(60000.0/(m_params.rpm()*0.5))))
  379. {
  380. std::lock_guard<std::mutex> lck(m_cloud_mutex);
  381. m_cloud_data->getCloudData("", p_cloud);
  382. if (p_cloud->empty()) {
  383. return VELODYNE_LIDAR_DEVICE_NO_CLOUD;
  384. }
  385. return SUCCESS;
  386. }
  387. else
  388. {
  389. return Error_manager(Error_code::VELODYNE_LIDAR_DEVICE_NO_CLOUD, Error_level::MINOR_ERROR,
  390. " Velodyne_lidar_device::get_current_cloud error ");
  391. }
  392. }
  393. Velodyne_lidar_device::Velodyne_lidar_device_status Velodyne_lidar_device::get_status()
  394. {
  395. updata_status();
  396. return m_velodyne_lidar_device_status;
  397. }
  398. void Velodyne_lidar_device::updata_status()
  399. {
  400. if (m_velodyne_socket_status == E_FAULT || m_velodyne_protocol_status == E_FAULT)
  401. {
  402. m_velodyne_lidar_device_status = E_FAULT;
  403. }else if (m_velodyne_socket_status == E_DISCONNECT)
  404. {
  405. m_velodyne_lidar_device_status = E_DISCONNECT;
  406. }
  407. else if(m_velodyne_socket_status == E_BUSY || m_velodyne_protocol_status == E_BUSY)
  408. {
  409. m_velodyne_lidar_device_status = E_BUSY;
  410. }
  411. else if (m_velodyne_socket_status == E_READY && m_velodyne_protocol_status == E_READY)
  412. {
  413. if (m_execute_condition.get_pass_ever())
  414. {
  415. m_velodyne_lidar_device_status = E_BUSY;
  416. }
  417. else
  418. {
  419. m_velodyne_lidar_device_status = E_READY;
  420. }
  421. }
  422. else
  423. {
  424. // LOG(WARNING)<<"unknown????? "<<m_velodyne_socket_status<<", "<<m_velodyne_protocol_status;
  425. m_velodyne_lidar_device_status = E_UNKNOWN;
  426. }
  427. }
  428. //mp_laser_manager_thread 线程执行函数,
  429. //thread_work 内部线程负责获取点云结果
  430. void Velodyne_lidar_device::execute_thread_fun()
  431. {
  432. LOG(INFO) << " Velodyne_lidar_device::execute_thread_fun() start " << this;
  433. Error_manager t_error;
  434. //雷达管理的独立线程,负责控制管理所有的雷达。
  435. while (m_execute_condition.is_alive())
  436. {
  437. m_execute_condition.wait();
  438. if (m_execute_condition.is_alive())
  439. {
  440. std::this_thread::yield();
  441. if (mp_velodyne_lidar_scan_task == nullptr)
  442. {
  443. //没有任务就忽略, 直接关闭线程
  444. m_velodyne_lidar_device_status = E_READY;
  445. m_execute_condition.notify_all(false);
  446. }
  447. else
  448. {
  449. if (mp_velodyne_lidar_scan_task->is_over_time())
  450. {
  451. t_error.error_manager_reset(TASK_TIMEOVER, MINOR_ERROR, "Velodyne_lidar_device::get_cloud_thread() TASK_TIMEOVER");
  452. mp_velodyne_lidar_scan_task->compare_and_cover_task_error_manager(t_error);
  453. //故障结束任务
  454. end_task();
  455. }
  456. else
  457. {
  458. //获取这个时间后面的点云.
  459. if (m_parse_ring_time > mp_velodyne_lidar_scan_task->get_command_time())
  460. {
  461. std::mutex *tp_mutex = mp_velodyne_lidar_scan_task->get_task_cloud_lock();
  462. pcl::PointCloud<pcl::PointXYZ>::Ptr tp_cloud = mp_velodyne_lidar_scan_task->get_task_point_cloud();
  463. {
  464. std::unique_lock<std::mutex> lck(*tp_mutex);
  465. {
  466. std::lock_guard<std::mutex> lck(m_cloud_mutex);
  467. // 转换lidar points为pcl点云
  468. m_cloud_data->getCloudData("", tp_cloud);
  469. }
  470. }
  471. mp_velodyne_lidar_scan_task->compare_and_cover_task_error_manager(t_error);
  472. //正常结束任务
  473. end_task();
  474. }
  475. else
  476. {
  477. //等1ms
  478. std::this_thread::sleep_for(std::chrono::milliseconds(1));
  479. }
  480. }
  481. }
  482. }
  483. }
  484. LOG(INFO) << " Velodyne_lidar_device::execute_thread_fun() end :" << this;
  485. return;
  486. }