wj_716N_lidar_protocol.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. #include "wj_716N_lidar_protocol.h"
  2. #include <iostream>
  3. wj_716N_lidar_protocol::wj_716N_lidar_protocol()
  4. {
  5. memset(&m_sdata, 0, sizeof(m_sdata));
  6. // marker_pub = nh.advertise<sensor_msgs::LaserScan>("scan", 50);
  7. // ros::Time scan_time = ros::Time::now();
  8. // scan.header.stamp = scan_time;
  9. long scan_time=std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
  10. scan.header.stamp.msecs = scan_time;
  11. mp_communication_data_queue = NULL;
  12. freq_scan = 1;
  13. m_u32PreFrameNo = 0;
  14. m_u32ExpectedPackageNo = 0;
  15. m_n32currentDataNo = 0;
  16. total_point = 1081;
  17. scan.header.frame_id = "wj_716N_lidar_frame";
  18. scan.angle_min = -2.35619449;
  19. scan.angle_max = 2.35619449;
  20. scan.angle_increment = 0.017453 / 4;
  21. scan.time_increment = 1 / 15.00000000 / 1440;
  22. scan.range_min = 0;
  23. scan.range_max = 30;
  24. scan.ranges.resize(1081);
  25. scan.intensities.resize(1081);
  26. scan.x.resize(1081);
  27. scan.y.resize(1081);
  28. scan.angle_to_point.resize(1081);
  29. index_start = (config_.min_ang + 2.35619449) / scan.angle_increment;
  30. // adjust angle_max to max_ang config param
  31. index_end = 1081 - ((2.35619449 - config_.max_ang) / scan.angle_increment);
  32. mp_scan_points = pcl::PointCloud<pcl::PointXYZ>::Ptr(new pcl::PointCloud<pcl::PointXYZ>);
  33. mp_thread_analysis = nullptr;
  34. std::cout << "wj_716N_lidar_protocl start success" << std::endl;
  35. }
  36. bool wj_716N_lidar_protocol::setConfig(wj_716_lidarConfig &new_config, uint32_t level)
  37. {
  38. config_ = new_config;
  39. scan.header.frame_id = config_.frame_id;
  40. scan.angle_min = config_.min_ang;
  41. scan.angle_max = config_.max_ang;
  42. scan.range_min = config_.range_min;
  43. scan.range_max = config_.range_max;
  44. freq_scan = config_.frequency_scan;
  45. scan.angle_increment = 0.017453 / 4;
  46. if (freq_scan == 1) //0.25°_15hz
  47. {
  48. scan.time_increment = 1 / 15.00000000 / 1440;
  49. total_point = 1081;
  50. }
  51. else if (freq_scan == 2) //0.25°_25hz
  52. {
  53. scan.time_increment = 1 / 25.00000000 / 1440;
  54. total_point = 1081;
  55. }
  56. // adjust angle_min to min_ang config param
  57. index_start = (config_.min_ang + 2.35619449) / scan.angle_increment;
  58. // adjust angle_max to max_ang config param
  59. index_end = 1081 - ((2.35619449 - config_.max_ang) / scan.angle_increment);
  60. int samples = index_end - index_start;
  61. // scan.ranges.resize(samples);
  62. // scan.intensities.resize(samples);
  63. std::cout << "frame_id:" << scan.header.frame_id << std::endl;
  64. std::cout << "min_ang:" << scan.angle_min << std::endl;
  65. std::cout << "max_ang:" << scan.angle_max << std::endl;
  66. std::cout << "angle_increment:" << scan.angle_increment << std::endl;
  67. std::cout << "time_increment:" << scan.time_increment << std::endl;
  68. std::cout << "range_min:" << scan.range_min << std::endl;
  69. std::cout << "range_max:" << scan.range_max << std::endl;
  70. std::cout << "samples_per_scan:" << samples << std::endl;
  71. return true;
  72. }
  73. // 初始化
  74. Error_manager wj_716N_lidar_protocol::init(Thread_safe_queue<Binary_buf *> *p_communication_data_queue,
  75. Point2D_tool::Polar_coordinates_box polar_coordinates_box,
  76. Point2D_tool::Point2D_box point2D_box,
  77. Point2D_tool::Point2D_transform point2D_transform)
  78. {
  79. if (p_communication_data_queue == NULL)
  80. {
  81. return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
  82. " POINTER IS NULL ");
  83. }
  84. wj_716_lidarConfig t_config;
  85. t_config.min_ang = polar_coordinates_box.angle_min;
  86. t_config.max_ang = polar_coordinates_box.angle_max;
  87. t_config.range_min = polar_coordinates_box.distance_min;
  88. t_config.range_max = polar_coordinates_box.distance_max;
  89. t_config.frequency_scan = 1;
  90. setConfig(t_config, 0);
  91. mp_communication_data_queue = p_communication_data_queue;
  92. m_point2D_box = point2D_box;
  93. std::cout << "box xmin:" << m_point2D_box.x_min << std::endl;
  94. std::cout << "box xmax:" << m_point2D_box.x_max << std::endl;
  95. std::cout << "box ymin:" << m_point2D_box.y_min << std::endl;
  96. std::cout << "box ymax:" << m_point2D_box.y_max << std::endl;
  97. m_point2D_transform = point2D_transform;
  98. //接受线程, 默认开启循环, 在内部的wait_and_pop进行等待
  99. m_condition_analysis.reset(false, true, false);
  100. mp_thread_analysis = new std::thread(&wj_716N_lidar_protocol::thread_analysis, this);
  101. return Error_code::SUCCESS;
  102. }
  103. //反初始化
  104. Error_manager wj_716N_lidar_protocol::uninit()
  105. {
  106. LOG(INFO) << " ---wj_716N_lidar_protocol uninit --- "<< this;
  107. if ( mp_communication_data_queue )
  108. {
  109. //终止队列,防止 wait_and_pop 阻塞线程。
  110. mp_communication_data_queue->termination_queue();
  111. }
  112. //关闭线程
  113. if (mp_thread_analysis)
  114. {
  115. m_condition_analysis.kill_all();
  116. }
  117. //回收线程的资源
  118. if (mp_thread_analysis)
  119. {
  120. mp_thread_analysis->join();
  121. delete mp_thread_analysis;
  122. mp_thread_analysis = NULL;
  123. }
  124. if ( mp_communication_data_queue )
  125. {
  126. //清空队列
  127. mp_communication_data_queue->clear_and_delete();
  128. }
  129. //队列的内存由上级管理, 这里写空就好了.
  130. mp_communication_data_queue = NULL;
  131. return Error_code::SUCCESS;
  132. }
  133. //获取扫描点云
  134. Error_manager wj_716N_lidar_protocol::get_scan_points(pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud_out)
  135. {
  136. if ( p_cloud_out.get() == NULL )
  137. {
  138. return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
  139. " Wj_716_lidar_protocol::get_scan_points POINTER IS NULL ");
  140. }
  141. std::unique_lock<std::mutex> lck(m_scan_mutex);
  142. //将扫描点云追加到p_cloud_out后面, 不要清除p_cloud_out原有的数据
  143. (*p_cloud_out)+=(*mp_scan_points);
  144. return Error_code::SUCCESS;
  145. }
  146. //解析线程函数
  147. void wj_716N_lidar_protocol::thread_analysis()
  148. {
  149. LOG(INFO) << " ---Wj_716_lidar_protocol::thread_analysis start ---" << this;
  150. Error_manager t_error;
  151. //接受雷达消息,包括连接,重连和接受数据
  152. while (m_condition_analysis.is_alive())
  153. {
  154. m_condition_analysis.wait();
  155. if (m_condition_analysis.is_alive())
  156. {
  157. std::this_thread::yield();
  158. if (mp_communication_data_queue == NULL)
  159. {
  160. // m_wanji_lidar_protocol_status = E_FAULT;
  161. }
  162. else
  163. {
  164. Binary_buf *tp_binary_buf = NULL;
  165. bool is_pop = mp_communication_data_queue->wait_and_pop(tp_binary_buf);
  166. if (is_pop == true && tp_binary_buf != NULL)
  167. {
  168. if(dataProcess((unsigned char *)tp_binary_buf->get_buf(), tp_binary_buf->get_length()))
  169. {
  170. t_error = SUCCESS;
  171. }else{
  172. t_error = ERROR;
  173. }
  174. //else 错误不管, 当做无效消息处理
  175. delete(tp_binary_buf);
  176. }
  177. }
  178. }
  179. }
  180. LOG(INFO) << " -Wj_716_lidar_protocol::thread_analysis end :" << this;
  181. return;
  182. }
  183. bool wj_716N_lidar_protocol::dataProcess(unsigned char *data, const int reclen)
  184. {
  185. if (reclen > MAX_LENGTH_DATA_PROCESS)
  186. {
  187. m_sdata.m_u32out = 0;
  188. m_sdata.m_u32in = 0;
  189. return false;
  190. }
  191. if (m_sdata.m_u32in + reclen > MAX_LENGTH_DATA_PROCESS)
  192. {
  193. m_sdata.m_u32out = 0;
  194. m_sdata.m_u32in = 0;
  195. return false;
  196. }
  197. memcpy(&m_sdata.m_acdata[m_sdata.m_u32in], data, reclen * sizeof(char));
  198. m_sdata.m_u32in += reclen;
  199. while (m_sdata.m_u32out < m_sdata.m_u32in)
  200. {
  201. if (m_sdata.m_acdata[m_sdata.m_u32out] == 0xFF && m_sdata.m_acdata[m_sdata.m_u32out + 1] == 0xAA)
  202. {
  203. unsigned l_u32reallen = (m_sdata.m_acdata[m_sdata.m_u32out + 2] << 8) |
  204. (m_sdata.m_acdata[m_sdata.m_u32out + 3] << 0);
  205. l_u32reallen = l_u32reallen + 4;
  206. if (l_u32reallen <= (m_sdata.m_u32in - m_sdata.m_u32out + 1))
  207. {
  208. if (OnRecvProcess(&m_sdata.m_acdata[m_sdata.m_u32out], l_u32reallen))
  209. {
  210. m_sdata.m_u32out += l_u32reallen;
  211. }
  212. else
  213. {
  214. std::cout << "continuous search frame header" << std::endl;
  215. m_sdata.m_u32out++;
  216. }
  217. }
  218. else if (l_u32reallen >= MAX_LENGTH_DATA_PROCESS)
  219. {
  220. m_sdata.m_u32out++;
  221. }
  222. else
  223. {
  224. break;
  225. }
  226. }
  227. else
  228. {
  229. m_sdata.m_u32out++;
  230. }
  231. } //end while(m_sdata.m_u32out < m_sdata.m_u32in)
  232. if (m_sdata.m_u32out >= m_sdata.m_u32in)
  233. {
  234. m_sdata.m_u32out = 0;
  235. m_sdata.m_u32in = 0;
  236. }
  237. else if (m_sdata.m_u32out < m_sdata.m_u32in && m_sdata.m_u32out != 0)
  238. {
  239. movedata(m_sdata);
  240. }
  241. return true;
  242. }
  243. void wj_716N_lidar_protocol::movedata(DataCache &sdata)
  244. {
  245. for (int i = sdata.m_u32out; i < sdata.m_u32in; i++)
  246. {
  247. sdata.m_acdata[i - sdata.m_u32out] = sdata.m_acdata[i];
  248. }
  249. sdata.m_u32in = sdata.m_u32in - sdata.m_u32out;
  250. sdata.m_u32out = 0;
  251. }
  252. bool wj_716N_lidar_protocol::OnRecvProcess(unsigned char *data, int len)
  253. {
  254. if (len > 0)
  255. {
  256. if (checkXor(data, len))
  257. {
  258. protocl(data, len);
  259. }
  260. else
  261. {
  262. return false;
  263. }
  264. }
  265. else
  266. {
  267. return false;
  268. }
  269. return true;
  270. }
  271. bool wj_716N_lidar_protocol::protocl(unsigned char *data, const int len)
  272. {
  273. if ((data[22] == 0x02 && data[23] == 0x02) || (data[22] == 0x02 && data[23] == 0x01)) //command type:0x02 0x01/0X02
  274. {
  275. heartstate = true;
  276. int l_n32TotalPackage = data[80];
  277. int l_n32PackageNo = data[81];
  278. unsigned int l_u32FrameNo = (data[75] << 24) + (data[76] << 16) + (data[77] << 8) + data[78];
  279. int l_n32PointNum = (data[83] << 8) + data[84];
  280. int l_n32Frequency = data[79];
  281. if(l_n32Frequency != freq_scan)
  282. {
  283. std::cout << "The scan frequency "<< l_n32Frequency <<" does not match the one you setted " << freq_scan << " !"<< std::endl;
  284. return false;
  285. }
  286. if(m_u32PreFrameNo != l_u32FrameNo)
  287. {
  288. m_u32PreFrameNo = l_u32FrameNo;
  289. m_u32ExpectedPackageNo = 1;
  290. m_n32currentDataNo = 0;
  291. }
  292. if (l_n32PackageNo == m_u32ExpectedPackageNo && m_u32PreFrameNo == l_u32FrameNo)
  293. {
  294. if(data[82] == 0x00) //Dist
  295. {
  296. for (int j = 0; j < l_n32PointNum; j++)
  297. {
  298. scandata[m_n32currentDataNo] = (((unsigned char)data[85 + j * 2]) << 8) +
  299. ((unsigned char)data[86 + j * 2]);
  300. scandata[m_n32currentDataNo] /= 1000.0;
  301. scanintensity[m_n32currentDataNo] = 0;
  302. if (scandata[m_n32currentDataNo] > scan.range_max || scandata[m_n32currentDataNo] < scan.range_min || scandata[m_n32currentDataNo] == 0)
  303. {
  304. scandata[m_n32currentDataNo] = NAN;
  305. }
  306. m_n32currentDataNo++;
  307. }
  308. m_u32ExpectedPackageNo++;
  309. }
  310. else if(data[82] == 0x01 && m_n32currentDataNo >= total_point) //intensities
  311. {
  312. for (int j = 0; j < l_n32PointNum; j++)
  313. {
  314. scanintensity[m_n32currentDataNo - total_point] = (((unsigned char)data[85 + j * 2]) << 8) +
  315. ((unsigned char)data[86 + j * 2]);
  316. m_n32currentDataNo++;
  317. }
  318. m_u32ExpectedPackageNo++;
  319. }
  320. if(m_u32ExpectedPackageNo - 1 == l_n32TotalPackage)
  321. {
  322. m_read_write_mtx.lock();
  323. mp_scan_points->clear();
  324. for (int i = index_start; i < index_end; i++)
  325. {
  326. scan.ranges[i - index_start] = scandata[i];
  327. //std::cout<<scan.ranges[i - index_start]<<std::endl;
  328. update_data(i-index_start);
  329. if(scandata[i - index_start] == NAN)
  330. {
  331. scan.intensities[i - index_start] = 0;
  332. continue;
  333. }
  334. else
  335. {
  336. scan.intensities[i - index_start] = scanintensity[i];
  337. }
  338. pcl::PointXYZ point;
  339. //判断平面坐标点是否在限制范围
  340. double x = scan.x[i-index_start];
  341. double y = scan.y[i-index_start];
  342. if (Point2D_tool::limit_with_point2D_box(x, y, &m_point2D_box))
  343. {
  344. //平面坐标的转换, 可以进行旋转和平移, 不能缩放
  345. point.x = x * m_point2D_transform.m00 + y * m_point2D_transform.m01 + m_point2D_transform.m02;
  346. point.y = x * m_point2D_transform.m10 + y * m_point2D_transform.m11 + m_point2D_transform.m12;
  347. //添加到最终点云
  348. mp_scan_points->push_back(point);
  349. }
  350. }
  351. scan.header.stamp.msecs=std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
  352. m_read_write_mtx.unlock();
  353. // ros::Time scan_time = ros::Time::now();
  354. // scan.header.stamp = scan_time;
  355. // marker_pub.publish(scan);
  356. }
  357. }
  358. return true;
  359. }
  360. else
  361. {
  362. return false;
  363. }
  364. }
  365. //index点数组下标【0~l_n32PointCount-1】 l_n32PointCount总点数
  366. void wj_716N_lidar_protocol::update_data(int index)
  367. {
  368. if(index>=total_point)
  369. {
  370. return;
  371. }
  372. // std::cout<<"该圈的数据总条数:"<<total_point_number_per_circle<<std::endl;
  373. // std::cout<<"数据点对应的数组下标:"<<index<<std::endl;
  374. // 每个下标对应的弧度
  375. scan.angle_to_point[index] = scan.angle_min+(total_point-1-index)*(scan.angle_max-scan.angle_min)/(total_point-1);
  376. scan.y[index]=scan.ranges[index]*cos(scan.angle_min+(total_point-1-index)*(scan.angle_max-scan.angle_min)/(total_point-1));
  377. scan.x[index]=scan.ranges[index]*sin(scan.angle_min+(total_point-1-index)*(scan.angle_max-scan.angle_min)/(total_point-1));
  378. // scan.angle_to_point[total_point-1-index] = scan.angle_min+(total_point-1-index)*(scan.angle_max-scan.angle_min)/(total_point-1);
  379. // scan.y[total_point-1-index]=scan.ranges[index]*cos(scan.angle_min+(total_point-1-index)*(scan.angle_max-scan.angle_min)/(total_point-1));
  380. // scan.x[total_point-1-index]=scan.ranges[index]*sin(scan.angle_min+(total_point-1-index)*(scan.angle_max-scan.angle_min)/(total_point-1));
  381. // if(index!=540)
  382. // std::cout<<"每个点对应的弧度: "<<scan.angle_to_point[total_point-1-index]<<", 每个点对应的距离: "<<scan.ranges[total_point-1-index]<<", (x,y): ("<<scan.x[total_point-1-index]<<","<<scan.y[total_point-1-index]<<")"<<std::endl;
  383. }
  384. bool wj_716N_lidar_protocol::checkXor(unsigned char *recvbuf, int recvlen)
  385. {
  386. int i = 0;
  387. unsigned char check = 0;
  388. unsigned char *p = recvbuf;
  389. int len;
  390. if (*p == 0xFF)
  391. {
  392. p = p + 2;
  393. len = recvlen - 6;
  394. for (i = 0; i < len; i++)
  395. {
  396. check ^= *p++;
  397. }
  398. p++;
  399. if (check == *p)
  400. {
  401. return true;
  402. }
  403. else
  404. return false;
  405. }
  406. else
  407. {
  408. return false;
  409. }
  410. }