lds.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  1. //
  2. // The MIT License (MIT)
  3. //
  4. // Copyright (c) 2019 Livox. All rights reserved.
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. // SOFTWARE.
  23. //
  24. #include "lds.h"
  25. #include <math.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <time.h>
  29. #include <chrono>
  30. namespace livox_ros {
  31. /** Common function --------------------------------------------------------- */
  32. bool IsFilePathValid(const char *path_str) {
  33. int str_len = strlen(path_str);
  34. if ((str_len > kPathStrMinSize) && (str_len < kPathStrMaxSize)) {
  35. return true;
  36. } else {
  37. return false;
  38. }
  39. }
  40. /** Replace nonstardard function "timegm" with mktime.
  41. * For a portable version of timegm, set the TZ environment variable to UTC,
  42. * call mktime and restore the value of TZ.
  43. * "localtime" and "timegm" are nonstandard GNU extensions that are also present
  44. * on the BSDs. Avoid their use!!!
  45. */
  46. time_t replace_timegm(struct tm *tm) {
  47. time_t ret;
  48. char *tz;
  49. tz = getenv("TZ");
  50. setenv("TZ", "", 1);
  51. tzset();
  52. ret = mktime(tm);
  53. if (tz)
  54. setenv("TZ", tz, 1);
  55. else
  56. unsetenv("TZ");
  57. tzset();
  58. return ret;
  59. }
  60. uint64_t RawLdsStampToNs(LdsStamp &timestamp, uint8_t timestamp_type) {
  61. if (timestamp_type == kTimestampTypePps) {
  62. return timestamp.stamp;
  63. } else if (timestamp_type == kTimestampTypeNoSync) {
  64. return timestamp.stamp;
  65. } else if (timestamp_type == kTimestampTypePtp) {
  66. return timestamp.stamp;
  67. } else if (timestamp_type == kTimestampTypePpsGps) {
  68. struct tm time_utc;
  69. time_utc.tm_isdst = 0;
  70. time_utc.tm_year = timestamp.stamp_bytes[0] + 100; // map 2000 to 1990
  71. time_utc.tm_mon = timestamp.stamp_bytes[1] - 1; // map 1~12 to 0~11
  72. time_utc.tm_mday = timestamp.stamp_bytes[2];
  73. time_utc.tm_hour = timestamp.stamp_bytes[3];
  74. time_utc.tm_min = 0;
  75. time_utc.tm_sec = 0;
  76. // uint64_t time_epoch = mktime(&time_utc);
  77. uint64_t time_epoch = timegm(&time_utc); // no timezone
  78. time_epoch = time_epoch * 1000000 + timestamp.stamp_word.high; // to us
  79. time_epoch = time_epoch * 1000; // to ns
  80. return time_epoch;
  81. } else {
  82. printf("Timestamp type[%d] invalid.\n", timestamp_type);
  83. return 0;
  84. }
  85. }
  86. uint64_t GetStoragePacketTimestamp(StoragePacket *packet, uint8_t data_src) {
  87. LivoxEthPacket *raw_packet =
  88. reinterpret_cast<LivoxEthPacket *>(packet->raw_data);
  89. LdsStamp timestamp;
  90. memcpy(timestamp.stamp_bytes, raw_packet->timestamp, sizeof(timestamp));
  91. if (raw_packet->timestamp_type == kTimestampTypePps) {
  92. if (data_src != kSourceLvxFile) {
  93. return (timestamp.stamp + packet->time_rcv);
  94. } else {
  95. return timestamp.stamp;
  96. }
  97. } else if (raw_packet->timestamp_type == kTimestampTypeNoSync) {
  98. return timestamp.stamp;
  99. } else if (raw_packet->timestamp_type == kTimestampTypePtp) {
  100. return timestamp.stamp;
  101. } else if (raw_packet->timestamp_type == kTimestampTypePpsGps) {
  102. struct tm time_utc;
  103. time_utc.tm_isdst = 0;
  104. time_utc.tm_year = raw_packet->timestamp[0] + 100; // map 2000 to 1990
  105. time_utc.tm_mon = raw_packet->timestamp[1] - 1; // map 1~12 to 0~11
  106. time_utc.tm_mday = raw_packet->timestamp[2];
  107. time_utc.tm_hour = raw_packet->timestamp[3];
  108. time_utc.tm_min = 0;
  109. time_utc.tm_sec = 0;
  110. // uint64_t time_epoch = mktime(&time_utc);
  111. uint64_t time_epoch = timegm(&time_utc); // no timezone
  112. time_epoch = time_epoch * 1000000 + timestamp.stamp_word.high; // to us
  113. time_epoch = time_epoch * 1000; // to ns
  114. return time_epoch;
  115. } else {
  116. printf("Timestamp type[%d] invalid.\n", raw_packet->timestamp_type);
  117. return 0;
  118. }
  119. }
  120. uint32_t CalculatePacketQueueSize(uint32_t interval_ms, uint8_t product_type,
  121. uint8_t data_type) {
  122. uint32_t queue_size =
  123. (interval_ms * GetPacketNumPerSec(product_type, data_type)) / 1000;
  124. queue_size = queue_size * 2;
  125. if (queue_size < kMinEthPacketQueueSize) {
  126. queue_size = kMinEthPacketQueueSize;
  127. } else if (queue_size > kMaxEthPacketQueueSize) {
  128. queue_size = kMaxEthPacketQueueSize;
  129. }
  130. return queue_size;
  131. }
  132. void ParseCommandlineInputBdCode(const char *cammandline_str,
  133. std::vector<std::string> &bd_code_list) {
  134. char *strs = new char[strlen(cammandline_str) + 1];
  135. strcpy(strs, cammandline_str);
  136. std::string pattern = "&";
  137. char *bd_str = strtok(strs, pattern.c_str());
  138. std::string invalid_bd = "000000000";
  139. while (bd_str != NULL) {
  140. printf("Commandline input bd:%s\n", bd_str);
  141. if ((kBdCodeSize == strlen(bd_str)) &&
  142. (NULL == strstr(bd_str, invalid_bd.c_str()))) {
  143. bd_code_list.push_back(bd_str);
  144. } else {
  145. printf("Invalid bd:%s!\n", bd_str);
  146. }
  147. bd_str = strtok(NULL, pattern.c_str());
  148. }
  149. delete[] strs;
  150. }
  151. void EulerAnglesToRotationMatrix(EulerAngle euler, RotationMatrix matrix) {
  152. double cos_roll = cos(static_cast<double>(euler[0]));
  153. double cos_pitch = cos(static_cast<double>(euler[1]));
  154. double cos_yaw = cos(static_cast<double>(euler[2]));
  155. double sin_roll = sin(static_cast<double>(euler[0]));
  156. double sin_pitch = sin(static_cast<double>(euler[1]));
  157. double sin_yaw = sin(static_cast<double>(euler[2]));
  158. matrix[0][0] = cos_pitch * cos_yaw;
  159. matrix[0][1] = sin_roll * sin_pitch * cos_yaw - cos_roll * sin_yaw;
  160. matrix[0][2] = cos_roll * sin_pitch * cos_yaw + sin_roll * sin_yaw;
  161. matrix[1][0] = cos_pitch * sin_yaw;
  162. matrix[1][1] = sin_roll * sin_pitch * sin_yaw + cos_roll * cos_yaw;
  163. matrix[1][2] = cos_roll * sin_pitch * sin_yaw - sin_roll * cos_yaw;
  164. matrix[2][0] = -sin_pitch;
  165. matrix[2][1] = sin_roll * cos_pitch;
  166. matrix[2][2] = cos_roll * cos_pitch;
  167. /*
  168. float rotate[3][3] = {
  169. {
  170. std::cos(info.pitch) * std::cos(info.yaw),
  171. std::sin(info.roll) * std::sin(info.pitch) * std::cos(info.yaw) -
  172. std::cos(info.roll) * std::sin(info.yaw), std::cos(info.roll) *
  173. std::sin(info.pitch) * std::cos(info.yaw) + std::sin(info.roll) *
  174. std::sin(info.yaw) },
  175. {
  176. std::cos(info.pitch) * std::sin(info.yaw),
  177. std::sin(info.roll) * std::sin(info.pitch) * std::sin(info.yaw) +
  178. std::cos(info.roll) * std::cos(info.yaw), std::cos(info.roll) *
  179. std::sin(info.pitch) * std::sin(info.yaw) - std::sin(info.roll) *
  180. std::cos(info.yaw) },
  181. {
  182. -std::sin(info.pitch),
  183. std::sin(info.roll) * std::cos(info.pitch),
  184. std::cos(info.roll) * std::cos(info.pitch)
  185. }
  186. };
  187. */
  188. }
  189. void PointExtrisincCompensation(PointXyz *dst_point, const PointXyz &src_point,
  190. ExtrinsicParameter &extrinsic) {
  191. dst_point->x = src_point.x * extrinsic.rotation[0][0] +
  192. src_point.y * extrinsic.rotation[0][1] +
  193. src_point.z * extrinsic.rotation[0][2] + extrinsic.trans[0];
  194. dst_point->y = src_point.x * extrinsic.rotation[1][0] +
  195. src_point.y * extrinsic.rotation[1][1] +
  196. src_point.z * extrinsic.rotation[1][2] + extrinsic.trans[1];
  197. dst_point->z = src_point.x * extrinsic.rotation[2][0] +
  198. src_point.y * extrinsic.rotation[2][1] +
  199. src_point.z * extrinsic.rotation[2][2] + extrinsic.trans[2];
  200. }
  201. /** Livox point procees for different raw data format
  202. * --------------------------------------------*/
  203. uint8_t *LivoxPointToPxyzrtl(uint8_t *point_buf, LivoxEthPacket *eth_packet,
  204. ExtrinsicParameter &extrinsic, uint32_t line_num) {
  205. LivoxPointXyzrtl *dst_point = (LivoxPointXyzrtl *)point_buf;
  206. uint32_t points_per_packet = GetPointsPerPacket(eth_packet->data_type);
  207. LivoxPoint *raw_point = reinterpret_cast<LivoxPoint *>(eth_packet->data);
  208. while (points_per_packet) {
  209. RawPointConvert((LivoxPointXyzr *)dst_point, raw_point);
  210. if (extrinsic.enable && IsTripleFloatNoneZero(raw_point->x,
  211. raw_point->y, raw_point->z)) {
  212. PointXyz src_point = *((PointXyz *)dst_point);
  213. PointExtrisincCompensation((PointXyz *)dst_point, src_point, extrinsic);
  214. }
  215. dst_point->tag = 0;
  216. dst_point->line = 0;
  217. ++raw_point;
  218. ++dst_point;
  219. --points_per_packet;
  220. }
  221. return (uint8_t *)dst_point;
  222. }
  223. static uint8_t *LivoxRawPointToPxyzrtl(uint8_t *point_buf, LivoxEthPacket *eth_packet,
  224. ExtrinsicParameter &extrinsic, uint32_t line_num) {
  225. LivoxPointXyzrtl *dst_point = (LivoxPointXyzrtl *)point_buf;
  226. uint32_t points_per_packet = GetPointsPerPacket(eth_packet->data_type);
  227. LivoxRawPoint *raw_point =
  228. reinterpret_cast<LivoxRawPoint *>(eth_packet->data);
  229. while (points_per_packet) {
  230. RawPointConvert((LivoxPointXyzr *)dst_point, raw_point);
  231. if (extrinsic.enable && IsTripleIntNoneZero(raw_point->x,
  232. raw_point->y, raw_point->z)) {
  233. PointXyz src_point = *((PointXyz *)dst_point);
  234. PointExtrisincCompensation((PointXyz *)dst_point, src_point, extrinsic);
  235. }
  236. dst_point->tag = 0;
  237. dst_point->line = 0;
  238. ++raw_point;
  239. ++dst_point;
  240. --points_per_packet;
  241. }
  242. return (uint8_t *)dst_point;
  243. }
  244. static uint8_t *LivoxSpherPointToPxyzrtl(uint8_t *point_buf, \
  245. LivoxEthPacket *eth_packet, ExtrinsicParameter &extrinsic, \
  246. uint32_t line_num) {
  247. LivoxPointXyzrtl *dst_point = (LivoxPointXyzrtl *)point_buf;
  248. uint32_t points_per_packet = GetPointsPerPacket(eth_packet->data_type);
  249. LivoxSpherPoint *raw_point =
  250. reinterpret_cast<LivoxSpherPoint *>(eth_packet->data);
  251. while (points_per_packet) {
  252. RawPointConvert((LivoxPointXyzr *)dst_point, raw_point);
  253. if (extrinsic.enable && raw_point->depth) {
  254. PointXyz src_point = *((PointXyz *)dst_point);
  255. PointExtrisincCompensation((PointXyz *)dst_point, src_point, extrinsic);
  256. }
  257. dst_point->tag = 0;
  258. dst_point->line = 0;
  259. ++raw_point;
  260. ++dst_point;
  261. --points_per_packet;
  262. }
  263. return (uint8_t *)dst_point;
  264. }
  265. static uint8_t *LivoxExtendRawPointToPxyzrtl(uint8_t *point_buf, \
  266. LivoxEthPacket *eth_packet, ExtrinsicParameter &extrinsic, \
  267. uint32_t line_num) {
  268. LivoxPointXyzrtl *dst_point = (LivoxPointXyzrtl *)point_buf;
  269. uint32_t points_per_packet = GetPointsPerPacket(eth_packet->data_type);
  270. LivoxExtendRawPoint *raw_point =
  271. reinterpret_cast<LivoxExtendRawPoint *>(eth_packet->data);
  272. uint8_t line_id = 0;
  273. while (points_per_packet) {
  274. RawPointConvert((LivoxPointXyzr *)dst_point, (LivoxRawPoint *)raw_point);
  275. if (extrinsic.enable && IsTripleIntNoneZero(raw_point->x,
  276. raw_point->y, raw_point->z)) {
  277. PointXyz src_point = *((PointXyz *)dst_point);
  278. PointExtrisincCompensation((PointXyz *)dst_point, src_point, extrinsic);
  279. }
  280. dst_point->tag = raw_point->tag;
  281. if (line_num > 1) {
  282. dst_point->line = line_id % line_num;
  283. } else {
  284. dst_point->line = 0;
  285. }
  286. ++raw_point;
  287. ++dst_point;
  288. ++line_id;
  289. --points_per_packet;
  290. }
  291. return (uint8_t *)dst_point;
  292. }
  293. static uint8_t *LivoxExtendSpherPointToPxyzrtl(uint8_t *point_buf, \
  294. LivoxEthPacket *eth_packet, ExtrinsicParameter &extrinsic, \
  295. uint32_t line_num) {
  296. LivoxPointXyzrtl *dst_point = (LivoxPointXyzrtl *)point_buf;
  297. uint32_t points_per_packet = GetPointsPerPacket(eth_packet->data_type);
  298. LivoxExtendSpherPoint *raw_point =
  299. reinterpret_cast<LivoxExtendSpherPoint *>(eth_packet->data);
  300. uint8_t line_id = 0;
  301. while (points_per_packet) {
  302. RawPointConvert((LivoxPointXyzr *)dst_point, (LivoxSpherPoint *)raw_point);
  303. if (extrinsic.enable && raw_point->depth) {
  304. PointXyz src_point = *((PointXyz *)dst_point);
  305. PointExtrisincCompensation((PointXyz *)dst_point, src_point, extrinsic);
  306. }
  307. dst_point->tag = raw_point->tag;
  308. if (line_num > 1) {
  309. dst_point->line = line_id % line_num;
  310. } else {
  311. dst_point->line = 0;
  312. }
  313. ++raw_point;
  314. ++dst_point;
  315. ++line_id;
  316. --points_per_packet;
  317. }
  318. return (uint8_t *)dst_point;
  319. }
  320. static uint8_t *LivoxDualExtendRawPointToPxyzrtl(uint8_t *point_buf, \
  321. LivoxEthPacket *eth_packet, ExtrinsicParameter &extrinsic, \
  322. uint32_t line_num) {
  323. LivoxPointXyzrtl *dst_point = (LivoxPointXyzrtl *)point_buf;
  324. uint32_t points_per_packet = GetPointsPerPacket(eth_packet->data_type);
  325. LivoxExtendRawPoint *raw_point =
  326. reinterpret_cast<LivoxExtendRawPoint *>(eth_packet->data);
  327. /* LivoxDualExtendRawPoint = 2*LivoxExtendRawPoint */
  328. points_per_packet = points_per_packet * 2;
  329. uint8_t line_id = 0;
  330. while (points_per_packet) {
  331. RawPointConvert((LivoxPointXyzr *)dst_point, (LivoxRawPoint *)raw_point);
  332. if (extrinsic.enable && IsTripleIntNoneZero(raw_point->x,
  333. raw_point->y, raw_point->z)) {
  334. PointXyz src_point = *((PointXyz *)dst_point);
  335. PointExtrisincCompensation((PointXyz *)dst_point, src_point, extrinsic);
  336. }
  337. dst_point->tag = raw_point->tag;
  338. if (line_num > 1) {
  339. dst_point->line = (line_id / 2) % line_num;
  340. } else {
  341. dst_point->line = 0;
  342. }
  343. ++raw_point;
  344. ++dst_point;
  345. ++line_id;
  346. --points_per_packet;
  347. }
  348. return (uint8_t *)dst_point;
  349. }
  350. static uint8_t *LivoxDualExtendSpherPointToPxyzrtl(uint8_t *point_buf, \
  351. LivoxEthPacket *eth_packet, ExtrinsicParameter &extrinsic, \
  352. uint32_t line_num) {
  353. LivoxPointXyzrtl *dst_point = (LivoxPointXyzrtl *)point_buf;
  354. uint32_t points_per_packet = GetPointsPerPacket(eth_packet->data_type);
  355. LivoxDualExtendSpherPoint *raw_point =
  356. reinterpret_cast<LivoxDualExtendSpherPoint *>(eth_packet->data);
  357. uint8_t line_id = 0;
  358. while (points_per_packet) {
  359. RawPointConvert((LivoxPointXyzr *)dst_point,
  360. (LivoxPointXyzr *)(dst_point + 1),
  361. (LivoxDualExtendSpherPoint *)raw_point);
  362. if (extrinsic.enable && raw_point->depth1) {
  363. PointXyz src_point = *((PointXyz *)dst_point);
  364. PointExtrisincCompensation((PointXyz *)dst_point, src_point, extrinsic);
  365. }
  366. dst_point->tag = raw_point->tag1;
  367. if (line_num > 1) {
  368. dst_point->line = line_id % line_num;
  369. } else {
  370. dst_point->line = 0;
  371. }
  372. ++dst_point;
  373. if (extrinsic.enable && raw_point->depth2) {
  374. PointXyz src_point = *((PointXyz *)dst_point);
  375. PointExtrisincCompensation((PointXyz *)dst_point, src_point, extrinsic);
  376. }
  377. dst_point->tag = raw_point->tag2;
  378. if (line_num > 1) {
  379. dst_point->line = line_id % line_num;
  380. } else {
  381. dst_point->line = 0;
  382. }
  383. ++dst_point;
  384. ++raw_point; /* only increase one */
  385. ++line_id;
  386. --points_per_packet;
  387. }
  388. return (uint8_t *)dst_point;
  389. }
  390. static uint8_t *LivoxTripleExtendRawPointToPxyzrtl(uint8_t *point_buf, \
  391. LivoxEthPacket *eth_packet, ExtrinsicParameter &extrinsic, \
  392. uint32_t line_num) {
  393. LivoxPointXyzrtl *dst_point = (LivoxPointXyzrtl *)point_buf;
  394. uint32_t points_per_packet = GetPointsPerPacket(eth_packet->data_type);
  395. LivoxExtendRawPoint *raw_point =
  396. reinterpret_cast<LivoxExtendRawPoint *>(eth_packet->data);
  397. /* LivoxTripleExtendRawPoint = 3*LivoxExtendRawPoint, echo_num */
  398. points_per_packet = points_per_packet * 3;
  399. uint8_t line_id = 0;
  400. while (points_per_packet) {
  401. RawPointConvert((LivoxPointXyzr *)dst_point, (LivoxRawPoint *)raw_point);
  402. if (extrinsic.enable && IsTripleIntNoneZero(raw_point->x,
  403. raw_point->y, raw_point->z)) {
  404. PointXyz src_point = *((PointXyz *)dst_point);
  405. PointExtrisincCompensation((PointXyz *)dst_point, src_point, extrinsic);
  406. }
  407. dst_point->tag = raw_point->tag;
  408. if (line_num > 1) {
  409. dst_point->line = (line_id / 3) % line_num;
  410. } else {
  411. dst_point->line = 0;
  412. }
  413. ++raw_point;
  414. ++dst_point;
  415. ++line_id;
  416. --points_per_packet;
  417. }
  418. return (uint8_t *)dst_point;
  419. }
  420. static uint8_t *LivoxTripleExtendSpherPointToPxyzrtl(uint8_t *point_buf, \
  421. LivoxEthPacket *eth_packet, ExtrinsicParameter &extrinsic, \
  422. uint32_t line_num) {
  423. LivoxPointXyzrtl *dst_point = (LivoxPointXyzrtl *)point_buf;
  424. uint32_t points_per_packet = GetPointsPerPacket(eth_packet->data_type);
  425. LivoxTripleExtendSpherPoint *raw_point =
  426. reinterpret_cast<LivoxTripleExtendSpherPoint *>(eth_packet->data);
  427. uint8_t line_id = 0;
  428. while (points_per_packet) {
  429. RawPointConvert((LivoxPointXyzr *)dst_point,
  430. (LivoxPointXyzr *)(dst_point + 1),
  431. (LivoxPointXyzr *)(dst_point + 2),
  432. (LivoxTripleExtendSpherPoint *)raw_point);
  433. if (extrinsic.enable && raw_point->depth1) {
  434. PointXyz src_point = *((PointXyz *)dst_point);
  435. PointExtrisincCompensation((PointXyz *)dst_point, src_point, extrinsic);
  436. }
  437. dst_point->tag = raw_point->tag1;
  438. if (line_num > 1) {
  439. dst_point->line = line_id % line_num;
  440. } else {
  441. dst_point->line = 0;
  442. }
  443. ++dst_point;
  444. if (extrinsic.enable && raw_point->depth2) {
  445. PointXyz src_point = *((PointXyz *)dst_point);
  446. PointExtrisincCompensation((PointXyz *)dst_point, src_point, extrinsic);
  447. }
  448. dst_point->tag = raw_point->tag2;
  449. if (line_num > 1) {
  450. dst_point->line = line_id % line_num;
  451. } else {
  452. dst_point->line = 0;
  453. }
  454. ++dst_point;
  455. if (extrinsic.enable && raw_point->depth3) {
  456. PointXyz src_point = *((PointXyz *)dst_point);
  457. PointExtrisincCompensation((PointXyz *)dst_point, src_point, extrinsic);
  458. }
  459. dst_point->tag = raw_point->tag3;
  460. if (line_num > 1) {
  461. dst_point->line = line_id % line_num;
  462. } else {
  463. dst_point->line = 0;
  464. }
  465. ++dst_point;
  466. ++raw_point; /* only increase one */
  467. ++line_id;
  468. --points_per_packet;
  469. }
  470. return (uint8_t *)dst_point;
  471. }
  472. uint8_t *LivoxImuDataProcess(uint8_t *point_buf, LivoxEthPacket *eth_packet) {
  473. memcpy(point_buf, eth_packet->data, sizeof(LivoxImuPoint));
  474. return point_buf;
  475. }
  476. const PointConvertHandler to_pxyzi_handler_table[kMaxPointDataType] = {
  477. LivoxRawPointToPxyzrtl,
  478. LivoxSpherPointToPxyzrtl,
  479. LivoxExtendRawPointToPxyzrtl,
  480. LivoxExtendSpherPointToPxyzrtl,
  481. LivoxDualExtendRawPointToPxyzrtl,
  482. LivoxDualExtendSpherPointToPxyzrtl,
  483. nullptr,
  484. LivoxTripleExtendRawPointToPxyzrtl,
  485. LivoxTripleExtendSpherPointToPxyzrtl
  486. };
  487. PointConvertHandler GetConvertHandler(uint8_t data_type) {
  488. if (data_type < kMaxPointDataType)
  489. return to_pxyzi_handler_table[data_type];
  490. else
  491. return nullptr;
  492. }
  493. void ZeroPointDataOfStoragePacket(StoragePacket* storage_packet) {
  494. LivoxEthPacket *raw_packet =
  495. reinterpret_cast<LivoxEthPacket *>(storage_packet->raw_data);
  496. uint32_t point_length = GetPointLen(raw_packet->data_type);
  497. memset(raw_packet->data, 0, point_length * storage_packet->point_num);
  498. }
  499. #if 0
  500. static void PointCloudConvert(LivoxPoint *p_dpoint, LivoxRawPoint *p_raw_point) {
  501. p_dpoint->x = p_raw_point->x/1000.0f;
  502. p_dpoint->y = p_raw_point->y/1000.0f;
  503. p_dpoint->z = p_raw_point->z/1000.0f;
  504. p_dpoint->reflectivity = p_raw_point->reflectivity;
  505. }
  506. #endif
  507. /* Member function --------------------------------------------------------- */
  508. Lds::Lds(uint32_t buffer_time_ms, uint8_t data_src) : \
  509. lidar_count_(kMaxSourceLidar), semaphore_(0), \
  510. buffer_time_ms_(buffer_time_ms), data_src_(data_src), request_exit_(false) {
  511. ResetLds(data_src_);
  512. };
  513. Lds::~Lds() {
  514. lidar_count_ = 0;
  515. ResetLds(0);
  516. };
  517. void Lds::ResetLidar(LidarDevice *lidar, uint8_t data_src) {
  518. DeInitQueue(&lidar->data);
  519. DeInitQueue(&lidar->imu_data);
  520. memset(lidar, 0, sizeof(LidarDevice));
  521. /** unallocated state */
  522. lidar->handle = kMaxSourceLidar;
  523. lidar->data_src = data_src;
  524. lidar->data_is_pubulished = false;
  525. lidar->connect_state = kConnectStateOff;
  526. lidar->raw_data_type = 0xFF;
  527. }
  528. void Lds::SetLidarDataSrc(LidarDevice *lidar, uint8_t data_src) {
  529. lidar->data_src = data_src;
  530. }
  531. void Lds::ResetLds(uint8_t data_src) {
  532. lidar_count_ = kMaxSourceLidar;
  533. for (uint32_t i = 0; i < kMaxSourceLidar; i++) {
  534. ResetLidar(&lidars_[i], data_src);
  535. }
  536. }
  537. void Lds::RequestExit() {
  538. request_exit_ = true;
  539. }
  540. bool Lds::IsAllQueueEmpty() {
  541. for (int i = 0; i < lidar_count_; i++) {
  542. if (!QueueIsEmpty(&lidars_[i].data)) {
  543. return false;
  544. }
  545. }
  546. return true;
  547. }
  548. bool Lds::IsAllQueueReadStop() {
  549. for (int i = 0; i < lidar_count_; i++) {
  550. uint32_t data_size = QueueUsedSize(&lidars_[i].data);
  551. if (data_size && (data_size > lidars_[i].onetime_publish_packets)) {
  552. return false;
  553. }
  554. }
  555. return true;
  556. }
  557. uint8_t Lds::GetDeviceType(uint8_t handle) {
  558. if (handle < kMaxSourceLidar) {
  559. return lidars_[handle].info.type;
  560. } else {
  561. return kDeviceTypeHub;
  562. }
  563. }
  564. void Lds::UpdateLidarInfoByEthPacket(LidarDevice *p_lidar,
  565. LivoxEthPacket* eth_packet) {
  566. if (p_lidar->raw_data_type != eth_packet->data_type) {
  567. p_lidar->raw_data_type = eth_packet->data_type;
  568. p_lidar->packet_interval = GetPacketInterval(p_lidar->info.type,
  569. eth_packet->data_type);
  570. p_lidar->timestamp_type = eth_packet->timestamp_type;
  571. p_lidar->packet_interval_max = p_lidar->packet_interval * 1.8f;
  572. p_lidar->onetime_publish_packets =
  573. GetPacketNumPerSec(p_lidar->info.type,
  574. p_lidar->raw_data_type) * buffer_time_ms_ / 1000;
  575. printf("Lidar[%d][%s] DataType[%d] timestamp_type[%d] PacketInterval[%d] "
  576. "PublishPackets[%d]\n", p_lidar->handle, p_lidar->info.broadcast_code,
  577. p_lidar->raw_data_type, p_lidar->timestamp_type,
  578. p_lidar->packet_interval, p_lidar->onetime_publish_packets);
  579. }
  580. }
  581. void Lds::StorageRawPacket(uint8_t handle, LivoxEthPacket* eth_packet)
  582. {
  583. LidarDevice *p_lidar = &lidars_[handle];
  584. LidarPacketStatistic *packet_statistic = &p_lidar->statistic_info;
  585. LdsStamp cur_timestamp;
  586. uint64_t timestamp;
  587. memcpy(cur_timestamp.stamp_bytes, eth_packet->timestamp,
  588. sizeof(cur_timestamp));
  589. timestamp = RawLdsStampToNs(cur_timestamp, eth_packet->timestamp_type);
  590. if (timestamp >= kRosTimeMax)
  591. {
  592. printf("Raw EthPacket time out of range Lidar[%d]\n", handle);
  593. return;
  594. }
  595. if (kImu != eth_packet->data_type)
  596. {
  597. UpdateLidarInfoByEthPacket(p_lidar, eth_packet);
  598. if (eth_packet->timestamp_type == kTimestampTypePps)
  599. {
  600. /** Whether a new sync frame */
  601. if ((cur_timestamp.stamp < packet_statistic->last_timestamp) &&
  602. (cur_timestamp.stamp < kPacketTimeGap))
  603. {
  604. auto cur_time = std::chrono::high_resolution_clock::now();
  605. int64_t sync_time = cur_time.time_since_epoch().count();
  606. /** used receive time as timebase */
  607. packet_statistic->timebase = sync_time;
  608. }
  609. }
  610. packet_statistic->last_timestamp = cur_timestamp.stamp;
  611. LidarDataQueue *p_queue = &p_lidar->data;
  612. if (nullptr == p_queue->storage_packet)
  613. {
  614. uint32_t queue_size = CalculatePacketQueueSize(
  615. buffer_time_ms_, p_lidar->info.type, eth_packet->data_type);
  616. InitQueue(p_queue, queue_size);
  617. printf("Lidar[%d][%s] storage queue size : %d %d\n", p_lidar->handle,
  618. p_lidar->info.broadcast_code, queue_size, p_queue->size);
  619. }
  620. if (!QueueIsFull(p_queue))
  621. {
  622. QueuePushAny(p_queue, (uint8_t *) eth_packet,
  623. GetEthPacketLen(eth_packet->data_type),
  624. packet_statistic->timebase,
  625. GetPointsPerPacket(eth_packet->data_type));
  626. if (QueueUsedSize(p_queue) > p_lidar->onetime_publish_packets)
  627. {
  628. if (semaphore_.GetCount() <= 0)
  629. {
  630. semaphore_.Signal();
  631. }
  632. }
  633. }
  634. }
  635. else //imu data
  636. {
  637. if (eth_packet->timestamp_type == kTimestampTypePps)
  638. {
  639. /** Whether a new sync frame */
  640. if ((cur_timestamp.stamp < packet_statistic->last_imu_timestamp) &&
  641. (cur_timestamp.stamp < kPacketTimeGap))
  642. {
  643. auto cur_time = std::chrono::high_resolution_clock::now();
  644. int64_t sync_time = cur_time.time_since_epoch().count();
  645. /** used receive time as timebase */
  646. packet_statistic->imu_timebase = sync_time;
  647. }
  648. }
  649. packet_statistic->last_imu_timestamp = cur_timestamp.stamp;
  650. LidarDataQueue *p_queue = &p_lidar->imu_data;
  651. if (nullptr == p_queue->storage_packet)
  652. {
  653. uint32_t queue_size = 256; /* fixed imu data queue size */
  654. InitQueue(p_queue, queue_size);
  655. printf("Lidar[%d][%s] imu storage queue size : %d %d\n", p_lidar->handle,
  656. p_lidar->info.broadcast_code, queue_size, p_queue->size);
  657. }
  658. if (!QueueIsFull(p_queue))
  659. {
  660. QueuePushAny(p_queue, (uint8_t *) eth_packet,
  661. GetEthPacketLen(eth_packet->data_type),
  662. packet_statistic->imu_timebase,
  663. GetPointsPerPacket(eth_packet->data_type));
  664. }
  665. }
  666. }
  667. void Lds::PrepareExit(void) {}
  668. } // namespace livox_ros