decoder_test.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. #include <gtest/gtest.h>
  2. #include <rs_driver/driver/decoder/decoder_mech.hpp>
  3. #include <rs_driver/msg/point_cloud_msg.hpp>
  4. #include <rs_driver/utility/dbg.hpp>
  5. using namespace robosense::lidar;
  6. typedef PointXYZI PointT;
  7. typedef PointCloudT<PointT> PointCloud;
  8. #pragma pack(push, 1)
  9. struct MyMsopPkt
  10. {
  11. uint8_t id[8];
  12. };
  13. struct MyDifopPkt
  14. {
  15. uint8_t id[8];
  16. uint16_t rpm;
  17. RSFOV fov;
  18. RSCalibrationAngle vert_angle_cali[2];
  19. RSCalibrationAngle horiz_angle_cali[2];
  20. };
  21. #pragma pack(pop)
  22. class MyDecoder : public DecoderMech<PointCloud>
  23. {
  24. public:
  25. MyDecoder(const RSDecoderMechConstParam& const_param,
  26. const RSDecoderParam& param)
  27. : DecoderMech<PointCloud>(const_param, param)
  28. {
  29. }
  30. virtual void decodeDifopPkt(const uint8_t* packet, size_t size)
  31. {
  32. const MyDifopPkt& pkt = *(const MyDifopPkt*)(packet);
  33. this->template decodeDifopCommon<MyDifopPkt>(pkt);
  34. }
  35. virtual bool decodeMsopPkt(const uint8_t* pkt, size_t size)
  36. {
  37. return false;
  38. }
  39. };
  40. static ErrCode errCode = ERRCODE_SUCCESS;
  41. static void errCallback(const Error& err)
  42. {
  43. errCode = err.error_code;
  44. }
  45. TEST(TestDecoder, angles_from_file)
  46. {
  47. RSDecoderMechConstParam const_param;
  48. const_param.base.LASER_NUM = 4;
  49. RSDecoderParam param;
  50. param.config_from_file = true;
  51. param.angle_path = "../rs_driver/test/res/angle.csv";
  52. errCode = ERRCODE_SUCCESS;
  53. MyDecoder decoder(const_param, param);
  54. decoder.regCallback(errCallback, nullptr);
  55. ASSERT_EQ(errCode, ERRCODE_SUCCESS);
  56. ASSERT_TRUE(decoder.angles_ready_);
  57. }
  58. TEST(TestDecoder, angles_from_file_fail)
  59. {
  60. RSDecoderMechConstParam const_param;
  61. const_param.base.LASER_NUM = 4;
  62. RSDecoderParam param;
  63. param.config_from_file = true;
  64. param.angle_path = "../rs_driver/test/res/non_exist.csv";
  65. MyDecoder decoder(const_param, param);
  66. decoder.regCallback(errCallback, nullptr);
  67. ASSERT_FALSE(decoder.angles_ready_);
  68. }
  69. TEST(TestDecoder, processDifopPkt_fail)
  70. {
  71. RSDecoderMechConstParam const_param =
  72. {
  73. sizeof(MyMsopPkt) // msop len
  74. , sizeof(MyDifopPkt) // difop len
  75. , 8 // msop id len
  76. , 8 // difop id len
  77. , {0x55, 0xAA, 0x05, 0x0A, 0x5A, 0xA5, 0x50, 0xA0} // msop id
  78. , {0xA5, 0xFF, 0x00, 0x5A, 0x11, 0x11, 0x55, 0x55} // difop id
  79. };
  80. RSDecoderParam param;
  81. MyDecoder decoder(const_param, param);
  82. decoder.regCallback(errCallback, nullptr);
  83. // wrong difop length
  84. MyDifopPkt pkt = {0};
  85. errCode = ERRCODE_SUCCESS;
  86. decoder.processDifopPkt((const uint8_t*)&pkt, 10);
  87. ASSERT_EQ(errCode, ERRCODE_WRONGPKTLENGTH);
  88. // wrong difop id
  89. errCode = ERRCODE_SUCCESS;
  90. decoder.processDifopPkt((const uint8_t*)&pkt, sizeof(pkt));
  91. ASSERT_EQ(errCode, ERRCODE_WRONGPKTHEADER);
  92. }
  93. TEST(TestDecoder, processDifopPkt)
  94. {
  95. RSDecoderMechConstParam const_param =
  96. {
  97. sizeof(MyMsopPkt) // msop len
  98. , sizeof(MyDifopPkt) // difop len
  99. , 8 // msop id len
  100. , 8 // difop id len
  101. , {0x55, 0xAA, 0x05, 0x0A, 0x5A, 0xA5, 0x50, 0xA0} // msop id
  102. , {0xA5, 0xFF, 0x00, 0x5A, 0x11, 0x11, 0x55, 0x55} // difop id
  103. , {0xFF, 0xEE} // block id
  104. , 2 // laser number
  105. , 1000 // blocks per packet
  106. , 2 // channels per block
  107. };
  108. const_param.BLOCK_DURATION = 55.52f / 1000000;
  109. RSDecoderParam param;
  110. param.config_from_file = false;
  111. MyDecoder decoder(const_param, param);
  112. decoder.regCallback(errCallback, nullptr);
  113. ASSERT_FALSE(decoder.angles_ready_);
  114. //
  115. // angles from difop. no angles in difop
  116. //
  117. uint8_t pkt_no_angles[] =
  118. {
  119. 0xA5, 0xFF, 0x00, 0x5A, 0x11, 0x11, 0x55, 0x55 // difop id
  120. , 0x02, 0x58 // rpm
  121. , 0x23, 0x28 // start angle = 9000
  122. , 0x46, 0x50 // end angle = 18000
  123. , 0xFF, 0xFF, 0xFF // vert angles
  124. , 0xFF, 0xFF, 0xFF
  125. , 0xFF, 0xFF, 0xFF // horiz angles
  126. , 0xFF, 0xFF, 0xFF
  127. };
  128. errCode = ERRCODE_SUCCESS;
  129. decoder.processDifopPkt(pkt_no_angles, sizeof(MyDifopPkt));
  130. errCode = ERRCODE_SUCCESS;
  131. ASSERT_EQ(decoder.rps_, 10);
  132. ASSERT_EQ(decoder.blks_per_frame_, 1801);
  133. ASSERT_EQ(decoder.block_az_diff_, 20);
  134. ASSERT_EQ(decoder.split_blks_per_frame_, 1801);
  135. ASSERT_EQ(decoder.fov_blind_ts_diff_, 0.075); // 0.1 * 3/4
  136. ASSERT_FALSE(decoder.angles_ready_);
  137. ASSERT_EQ(decoder.chan_angles_.vert_angles_.size(), 2);
  138. ASSERT_EQ(decoder.chan_angles_.vert_angles_[0], 0);
  139. ASSERT_EQ(decoder.chan_angles_.horiz_angles_.size(), 2);
  140. ASSERT_EQ(decoder.chan_angles_.horiz_angles_[0], 0);
  141. //
  142. // angles from difop. valid angels in difop.
  143. //
  144. uint8_t pkt[] =
  145. {
  146. 0xA5, 0xFF, 0x00, 0x5A, 0x11, 0x11, 0x55, 0x55 // difop id
  147. , 0x02, 0x58 // rpm
  148. , 0x00, 0x00 // start angle = 0
  149. , 0x8C, 0xA0 // end angle = 36000
  150. , 0x00, 0x00, 0x10 // vert angles
  151. , 0x01, 0x00, 0x20
  152. , 0x00, 0x00, 0x01 // horiz angles
  153. , 0x01, 0x00, 0x02
  154. };
  155. ASSERT_LT(decoder.getPacketDuration() - 55.52/1000, 0.00001);
  156. errCode = ERRCODE_SUCCESS;
  157. decoder.processDifopPkt(pkt, sizeof(MyDifopPkt));
  158. ASSERT_EQ(errCode, ERRCODE_SUCCESS);
  159. ASSERT_EQ(decoder.rps_, 10);
  160. ASSERT_EQ(decoder.fov_blind_ts_diff_, 0.0f); // 0.1 * 3/4
  161. ASSERT_TRUE(decoder.angles_ready_);
  162. ASSERT_EQ(decoder.chan_angles_.vert_angles_.size(), 2);
  163. ASSERT_EQ(decoder.chan_angles_.vert_angles_[0], 16);
  164. ASSERT_EQ(decoder.chan_angles_.horiz_angles_.size(), 2);
  165. ASSERT_EQ(decoder.chan_angles_.horiz_angles_[0], 1);
  166. }
  167. TEST(TestDecoder, processDifopPkt_invalid_rpm)
  168. {
  169. RSDecoderMechConstParam const_param =
  170. {
  171. sizeof(MyMsopPkt) // msop len
  172. , sizeof(MyDifopPkt) // difop len
  173. , 8 // msop id len
  174. , 8 // difop id len
  175. , {0x55, 0xAA, 0x05, 0x0A, 0x5A, 0xA5, 0x50, 0xA0} // msop id
  176. , {0xA5, 0xFF, 0x00, 0x5A, 0x11, 0x11, 0x55, 0x55} // difop id
  177. , {0xFF, 0xEE} // block id
  178. , 32 // laser number
  179. , 12 // blocks per packet
  180. , 32 // channels per block
  181. };
  182. RSDecoderParam param;
  183. MyDecoder decoder(const_param, param);
  184. decoder.regCallback(errCallback, nullptr);
  185. uint8_t pkt[] =
  186. {
  187. 0xA5, 0xFF, 0x00, 0x5A, 0x11, 0x11, 0x55, 0x55 // difop len
  188. , 0x00, 0x00 // rpm = 0
  189. };
  190. errCode = ERRCODE_SUCCESS;
  191. decoder.processDifopPkt(pkt, sizeof(MyDifopPkt));
  192. ASSERT_EQ(errCode, ERRCODE_SUCCESS);
  193. ASSERT_EQ(decoder.rps_, 10);
  194. }
  195. TEST(TestDecoder, processMsopPkt)
  196. {
  197. RSDecoderMechConstParam const_param =
  198. {
  199. sizeof(MyMsopPkt) // msop len
  200. , sizeof(MyDifopPkt) // difop len
  201. , 8 // msop id len
  202. , 8 // difop id len
  203. , {0x55, 0xAA, 0x05, 0x0A, 0x5A, 0xA5, 0x50, 0xA0} // msop id
  204. , {0xA5, 0xFF, 0x00, 0x5A, 0x11, 0x11, 0x55, 0x55} // difop id
  205. };
  206. MyMsopPkt pkt;
  207. RSDecoderParam param;
  208. MyDecoder decoder(const_param, param);
  209. decoder.regCallback(errCallback, nullptr);
  210. // wait_for_difop = true, angles not ready
  211. decoder.param_.wait_for_difop = true;
  212. decoder.angles_ready_ = false;
  213. errCode = ERRCODE_SUCCESS;
  214. decoder.processMsopPkt((const uint8_t*)&pkt, 2);
  215. ASSERT_EQ(errCode, 0);
  216. #if 0
  217. sleep(2);
  218. errCode = ERRCODE_SUCCESS;
  219. decoder.processMsopPkt((const uint8_t*)&pkt, 2);
  220. ASSERT_EQ(errCode, ERRCODE_NODIFOPRECV);
  221. #endif
  222. decoder.param_.wait_for_difop = true;
  223. decoder.angles_ready_ = true;
  224. // wrong msop len
  225. errCode = ERRCODE_SUCCESS;
  226. decoder.processMsopPkt((const uint8_t*)&pkt, 2);
  227. ASSERT_EQ(errCode, ERRCODE_WRONGPKTLENGTH);
  228. decoder.param_.wait_for_difop = false;
  229. // wrong msop header
  230. errCode = ERRCODE_SUCCESS;
  231. decoder.processMsopPkt((const uint8_t*)&pkt, sizeof(pkt));
  232. ASSERT_EQ(errCode, ERRCODE_WRONGPKTHEADER);
  233. // valid msop
  234. uint8_t id[] = {0x55, 0xAA, 0x05, 0x0A, 0x5A, 0xA5, 0x50, 0xA0};
  235. memcpy (pkt.id, id, 8);
  236. errCode = ERRCODE_SUCCESS;
  237. decoder.processMsopPkt((const uint8_t*)&pkt, sizeof(pkt));
  238. ASSERT_EQ(errCode, ERRCODE_SUCCESS);
  239. }
  240. #if 0
  241. TEST(TestDecoder, setPointCloudHeader)
  242. {
  243. // dense_points
  244. RSDecoderMechConstParam const_param = {};
  245. const_param.base.CHANNELS_PER_BLOCK = 2;
  246. RSDecoderParam param;
  247. param.dense_points = true;
  248. MyDecoder decoder(const_param, param, errCallback);
  249. ASSERT_EQ(decoder.point_cloud_seq_, 0);
  250. ASSERT_TRUE(decoder.param_.dense_points);
  251. std::shared_ptr<PointCloud> pt = std::make_shared<PointCloud>();
  252. PointT point;
  253. pt->points.emplace_back(point);
  254. pt->points.emplace_back(point);
  255. // dense_points = true
  256. {
  257. decoder.setPointCloudHeader(pt, 0.5f);
  258. ASSERT_EQ(pt->seq, 0);
  259. ASSERT_EQ(pt->timestamp, 0.5f);
  260. ASSERT_TRUE(pt->is_dense);
  261. ASSERT_EQ(pt->height, 1);
  262. ASSERT_EQ(pt->width, 2);
  263. }
  264. // dense_points = false
  265. decoder.param_.dense_points = false;
  266. {
  267. decoder.setPointCloudHeader(pt, 0.5f);
  268. ASSERT_EQ(pt->seq, 1);
  269. ASSERT_EQ(pt->timestamp, 0.5f);
  270. ASSERT_FALSE(pt->is_dense);
  271. ASSERT_EQ(pt->height, 2);
  272. ASSERT_EQ(pt->width, 1);
  273. }
  274. }
  275. std::shared_ptr<PointCloud> point_cloud_to_get;
  276. std::shared_ptr<PointCloud> getCallback(void)
  277. {
  278. return point_cloud_to_get;
  279. }
  280. bool flag_point_cloud = false;
  281. std::shared_ptr<PointCloud> point_cloud_to_put;
  282. void putCallback(std::shared_ptr<PointCloud> pt)
  283. {
  284. point_cloud_to_put = pt;
  285. flag_point_cloud = true;
  286. }
  287. TEST(TestDecoder, split_by_angle)
  288. {
  289. RSDecoderMechConstParam const_param;
  290. const_param.base.CHANNELS_PER_BLOCK = 2;
  291. RSDecoderParam param;
  292. param.split_frame_mode = SplitFrameMode::SPLIT_BY_ANGLE;
  293. param.split_angle = 0.0f;
  294. MyDecoder decoder(param, errCallback, const_param);
  295. point_cloud_to_get = std::make_shared<PointCloud>();
  296. decoder.regRecvCallback (getCallback, putCallback);
  297. {
  298. // not cross split angle yet.
  299. errCode = ERRCODE_SUCCESS;
  300. flag_point_cloud = false;
  301. decoder.newBlock (35999);
  302. ASSERT_EQ(errCode, ERRCODE_SUCCESS);
  303. ASSERT_FALSE(flag_point_cloud);
  304. // cross split angle. no points in point cloud.
  305. errCode = ERRCODE_SUCCESS;
  306. decoder.newBlock (2);
  307. ASSERT_EQ(errCode, ERRCODE_ZEROPOINTS);
  308. }
  309. // cross split angle. points in point cloud.
  310. {
  311. PointT point;
  312. point_cloud_to_get->points.emplace_back(point);
  313. point_cloud_to_get->points.emplace_back(point);
  314. errCode = ERRCODE_SUCCESS;
  315. flag_point_cloud = false;
  316. decoder.newBlock (1);
  317. ASSERT_EQ(errCode, ERRCODE_SUCCESS);
  318. ASSERT_TRUE(flag_point_cloud);
  319. ASSERT_TRUE(point_cloud_to_put.get() != NULL);
  320. ASSERT_EQ(point_cloud_to_put->height, 2);
  321. ASSERT_EQ(point_cloud_to_put->width, 1);
  322. }
  323. }
  324. TEST(TestDecoder, split_by_fixed_pkts)
  325. {
  326. RSDecoderMechConstParam const_param;
  327. const_param.base.CHANNELS_PER_BLOCK = 2;
  328. RSDecoderParam param;
  329. param.split_frame_mode = SplitFrameMode::SPLIT_BY_FIXED_BLKS;
  330. MyDecoder<PointCloud> decoder(param, errCallback, const_param);
  331. decoder.split_blks_per_frame_ = 2;
  332. point_cloud_to_get = std::make_shared<PointCloud>();
  333. decoder.regRecvCallback (getCallback, putCallback);
  334. PointT point;
  335. point_cloud_to_get->points.emplace_back(point);
  336. point_cloud_to_get->points.emplace_back(point);
  337. {
  338. // blocks < split_blks_per_frame_
  339. errCode = ERRCODE_SUCCESS;
  340. flag_point_cloud = false;
  341. decoder.newBlock (0);
  342. ASSERT_EQ(errCode, ERRCODE_SUCCESS);
  343. ASSERT_FALSE(flag_point_cloud);
  344. }
  345. {
  346. // blocks = split_blks_per_frame_
  347. errCode = ERRCODE_SUCCESS;
  348. flag_point_cloud = false;
  349. decoder.newBlock (0);
  350. ASSERT_EQ(errCode, ERRCODE_SUCCESS);
  351. ASSERT_TRUE(flag_point_cloud);
  352. ASSERT_TRUE(point_cloud_to_put.get() != NULL);
  353. ASSERT_EQ(point_cloud_to_put->height, 2);
  354. ASSERT_EQ(point_cloud_to_put->width, 1);
  355. }
  356. }
  357. TEST(TestDecoder, split_by_custom_blks)
  358. {
  359. RSDecoderMechConstParam const_param;
  360. const_param.base.CHANNELS_PER_BLOCK = 2;
  361. RSDecoderParam param;
  362. param.split_frame_mode = SplitFrameMode::SPLIT_BY_CUSTOM_BLKS;
  363. param.num_blks_split = 2;
  364. MyDecoder<PointCloud> decoder(param, errCallback, const_param);
  365. point_cloud_to_get = std::make_shared<PointCloud>();
  366. decoder.regRecvCallback (getCallback, putCallback);
  367. PointT point;
  368. point_cloud_to_get->points.emplace_back(point);
  369. point_cloud_to_get->points.emplace_back(point);
  370. {
  371. // blocks < num_blks_split
  372. errCode = ERRCODE_SUCCESS;
  373. flag_point_cloud = false;
  374. decoder.newBlock (0);
  375. ASSERT_EQ(errCode, ERRCODE_SUCCESS);
  376. ASSERT_FALSE(flag_point_cloud);
  377. }
  378. {
  379. // blocks = num_blks_split
  380. errCode = ERRCODE_SUCCESS;
  381. flag_point_cloud = false;
  382. decoder.newBlock (0);
  383. ASSERT_EQ(errCode, ERRCODE_SUCCESS);
  384. ASSERT_TRUE(flag_point_cloud);
  385. ASSERT_TRUE(point_cloud_to_put.get() != NULL);
  386. ASSERT_EQ(point_cloud_to_put->height, 2);
  387. ASSERT_EQ(point_cloud_to_put->width, 1);
  388. }
  389. }
  390. #endif