wj_716N_lidar_protocol.cpp 15 KB

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