当前位置:   article > 正文

3d激光雷达开发(lidar使用)

3d激光雷达开发(lidar使用)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        安装好了pcl库之后,下面就是需要想办法采集真实的雷达数据了。和camera不同,3d雷达一般需要单独购买。这方面,camera就强太多了,不仅手机有camera,电脑有camera,就算单独购买,也只要几百块钱。3d雷达则不同,最便宜的3d雷达也要3-4千块,多的可能大几万,这方面大家量力而行。有条件,可以自己购买;没有条件,可以申请单位购买;再不济,那就只能去看一下有没有别人不用的二手lidar了。

1、lidar品牌的选择

        目前这方面,国内也是百花齐放,百家争鸣。不过,还是建议大家购买那些有一定知名度,自己也能负担得起的传感器雷达。对我们自己来说,就是购买了livox品牌的雷达。不为别的,主要是价格负担得起。

2、lidar的选择

        目前来说,lidar的选择,还是来自于自己的需求。好的lidar视场角宽,看得远,但是价格也贵;便宜的lidar视场角一般,价格适中,比如说下面的mid40,视场角为38.4 * 38.4左右,

        而mid70,视场角达到了70.4*70.4左右,

3、使用view工具显示雷达数据,

        等从官方途径购买到了3d雷达之后,接着就是下载view工具,查看图像即可。

        view工具下载地址如下所示,

        https://www.livoxtech.com/cn/downloads

        打开后,链接是这样的,

        

         软件本身是绿色软件,只要把lidar和pc用网线直连在一起,网络配置成192.168.1.*即可。因为lidar默认就是这个网段的ip,pc配置成相同的一个网段后,就可以收到lidar发出来的广播包数据了。忘记说了,livox的雷达需要一个外接12v或者24v的电源,这一块需要准备下。

4、准备livox sdk

        通过view软件确认可以,就可以准备sdk读取lidar数据了。这部分github上面有下载,地址如下,

        https://github.com/Livox-SDK/Livox-SDK

        可以把代码下载下来。

5、编译livox sdk

        和pcl的编译差不多,livox sdk也是依赖于cmake才能完成的。

  

 6、进一步编译livx_sdk.sln

        打开sln工程后,可以看到很多的项目,这里面除了livox_sdk_static是静态库之外,其他都是exe程序。

        编译没有问题的话,就会看到,所有的程序都已经编译成功,

7、雷达数据读取

        所有sdk的示例代码中,可以重点关注lidar_sample、lidar_sample_cc这两个项目。前者是c语言,后者是cpp语言,就是这点区别,其他部分基本都是一样的。这里以lidar_sample举例,看一下官方提供的示例代码是这样的,

  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 <stdio.h>
  25. #include <stdlib.h>
  26. #ifdef WIN32
  27. #include <windows.h>
  28. #else
  29. #include <unistd.h>
  30. #endif
  31. #include <string.h>
  32. #include "livox_sdk.h"
  33. typedef enum {
  34. kDeviceStateDisconnect = 0,
  35. kDeviceStateConnect = 1,
  36. kDeviceStateSampling = 2,
  37. } DeviceState;
  38. typedef struct {
  39. uint8_t handle;
  40. DeviceState device_state;
  41. DeviceInfo info;
  42. } DeviceItem;
  43. DeviceItem devices[kMaxLidarCount];
  44. uint32_t data_recveive_count[kMaxLidarCount];
  45. /** Connect all the broadcast device. */
  46. int lidar_count = 0;
  47. char broadcast_code_list[kMaxLidarCount][kBroadcastCodeSize];
  48. /** Connect the broadcast device in list, please input the broadcast code and modify the BROADCAST_CODE_LIST_SIZE. */
  49. /*#define BROADCAST_CODE_LIST_SIZE 3
  50. int lidar_count = BROADCAST_CODE_LIST_SIZE;
  51. char broadcast_code_list[kMaxLidarCount][kBroadcastCodeSize] = {
  52. "000000000000002",
  53. "000000000000003",
  54. "000000000000004"
  55. };*/
  56. /** Receiving error message from Livox Lidar. */
  57. void OnLidarErrorStatusCallback(livox_status status, uint8_t handle, ErrorMessage *message) {
  58. static uint32_t error_message_count = 0;
  59. if (message != NULL) {
  60. ++error_message_count;
  61. if (0 == (error_message_count % 100)) {
  62. printf("handle: %u\n", handle);
  63. printf("temp_status : %u\n", message->lidar_error_code.temp_status);
  64. printf("volt_status : %u\n", message->lidar_error_code.volt_status);
  65. printf("motor_status : %u\n", message->lidar_error_code.motor_status);
  66. printf("dirty_warn : %u\n", message->lidar_error_code.dirty_warn);
  67. printf("firmware_err : %u\n", message->lidar_error_code.firmware_err);
  68. printf("pps_status : %u\n", message->lidar_error_code.device_status);
  69. printf("fan_status : %u\n", message->lidar_error_code.fan_status);
  70. printf("self_heating : %u\n", message->lidar_error_code.self_heating);
  71. printf("ptp_status : %u\n", message->lidar_error_code.ptp_status);
  72. printf("time_sync_status : %u\n", message->lidar_error_code.time_sync_status);
  73. printf("system_status : %u\n", message->lidar_error_code.system_status);
  74. }
  75. }
  76. }
  77. /** Receiving point cloud data from Livox LiDAR. */
  78. void GetLidarData(uint8_t handle, LivoxEthPacket *data, uint32_t data_num, void *client_data) {
  79. if (data) {
  80. data_recveive_count[handle] ++ ;
  81. if (data_recveive_count[handle] % 100 == 0) {
  82. /** Parsing the timestamp and the point cloud data. */
  83. uint64_t cur_timestamp = *((uint64_t *)(data->timestamp));
  84. if(data ->data_type == kCartesian) {
  85. LivoxRawPoint *p_point_data = (LivoxRawPoint *)data->data;
  86. }else if ( data ->data_type == kSpherical) {
  87. LivoxSpherPoint *p_point_data = (LivoxSpherPoint *)data->data;
  88. }else if ( data ->data_type == kExtendCartesian) {
  89. LivoxExtendRawPoint *p_point_data = (LivoxExtendRawPoint *)data->data;
  90. }else if ( data ->data_type == kExtendSpherical) {
  91. LivoxExtendSpherPoint *p_point_data = (LivoxExtendSpherPoint *)data->data;
  92. }else if ( data ->data_type == kDualExtendCartesian) {
  93. LivoxDualExtendRawPoint *p_point_data = (LivoxDualExtendRawPoint *)data->data;
  94. }else if ( data ->data_type == kDualExtendSpherical) {
  95. LivoxDualExtendSpherPoint *p_point_data = (LivoxDualExtendSpherPoint *)data->data;
  96. }else if ( data ->data_type == kImu) {
  97. LivoxImuPoint *p_point_data = (LivoxImuPoint *)data->data;
  98. }else if ( data ->data_type == kTripleExtendCartesian) {
  99. LivoxTripleExtendRawPoint *p_point_data = (LivoxTripleExtendRawPoint *)data->data;
  100. }else if ( data ->data_type == kTripleExtendSpherical) {
  101. LivoxTripleExtendSpherPoint *p_point_data = (LivoxTripleExtendSpherPoint *)data->data;
  102. }
  103. printf("data_type %d packet num %d\n", data->data_type, data_recveive_count[handle]);
  104. }
  105. }
  106. }
  107. /** Callback function of starting sampling. */
  108. void OnSampleCallback(livox_status status, uint8_t handle, uint8_t response, void *data) {
  109. printf("OnSampleCallback statue %d handle %d response %d \n", status, handle, response);
  110. if (status == kStatusSuccess) {
  111. if (response != 0) {
  112. devices[handle].device_state = kDeviceStateConnect;
  113. }
  114. } else if (status == kStatusTimeout) {
  115. devices[handle].device_state = kDeviceStateConnect;
  116. }
  117. }
  118. /** Callback function of stopping sampling. */
  119. void OnStopSampleCallback(livox_status status, uint8_t handle, uint8_t response, void *data) {
  120. }
  121. /** Query the firmware version of Livox LiDAR. */
  122. void OnDeviceInformation(livox_status status, uint8_t handle, DeviceInformationResponse *ack, void *data) {
  123. if (status != kStatusSuccess) {
  124. printf("Device Query Informations Failed %d\n", status);
  125. }
  126. if (ack) {
  127. printf("firm ver: %d.%d.%d.%d\n",
  128. ack->firmware_version[0],
  129. ack->firmware_version[1],
  130. ack->firmware_version[2],
  131. ack->firmware_version[3]);
  132. }
  133. }
  134. void LidarConnect(const DeviceInfo *info) {
  135. uint8_t handle = info->handle;
  136. QueryDeviceInformation(handle, OnDeviceInformation, NULL);
  137. if (devices[handle].device_state == kDeviceStateDisconnect) {
  138. devices[handle].device_state = kDeviceStateConnect;
  139. devices[handle].info = *info;
  140. }
  141. }
  142. void LidarDisConnect(const DeviceInfo *info) {
  143. uint8_t handle = info->handle;
  144. devices[handle].device_state = kDeviceStateDisconnect;
  145. }
  146. void LidarStateChange(const DeviceInfo *info) {
  147. uint8_t handle = info->handle;
  148. devices[handle].info = *info;
  149. }
  150. /** Callback function of changing of device state. */
  151. void OnDeviceInfoChange(const DeviceInfo *info, DeviceEvent type) {
  152. if (info == NULL) {
  153. return;
  154. }
  155. uint8_t handle = info->handle;
  156. if (handle >= kMaxLidarCount) {
  157. return;
  158. }
  159. if (type == kEventConnect) {
  160. LidarConnect(info);
  161. printf("[WARNING] Lidar sn: [%s] Connect!!!\n", info->broadcast_code);
  162. } else if (type == kEventDisconnect) {
  163. LidarDisConnect(info);
  164. printf("[WARNING] Lidar sn: [%s] Disconnect!!!\n", info->broadcast_code);
  165. } else if (type == kEventStateChange) {
  166. LidarStateChange(info);
  167. printf("[WARNING] Lidar sn: [%s] StateChange!!!\n", info->broadcast_code);
  168. }
  169. if (devices[handle].device_state == kDeviceStateConnect) {
  170. printf("Device Working State %d\n", devices[handle].info.state);
  171. if (devices[handle].info.state == kLidarStateInit) {
  172. printf("Device State Change Progress %u\n", devices[handle].info.status.progress);
  173. } else {
  174. printf("Device State Error Code 0X%08x\n", devices[handle].info.status.status_code.error_code);
  175. }
  176. printf("Device feature %d\n", devices[handle].info.feature);
  177. SetErrorMessageCallback(handle, OnLidarErrorStatusCallback);
  178. if (devices[handle].info.state == kLidarStateNormal) {
  179. LidarStartSampling(handle, OnSampleCallback, NULL);
  180. devices[handle].device_state = kDeviceStateSampling;
  181. }
  182. }
  183. }
  184. /** Callback function when broadcast message received.
  185. * You need to add listening device broadcast code and set the point cloud data callback in this function.
  186. */
  187. void OnDeviceBroadcast(const BroadcastDeviceInfo *info) {
  188. if (info == NULL || info->dev_type == kDeviceTypeHub) {
  189. return;
  190. }
  191. printf("Receive Broadcast Code %s\n", info->broadcast_code);
  192. if (lidar_count > 0) {
  193. bool found = false;
  194. int i = 0;
  195. for (i = 0; i < lidar_count; ++i) {
  196. if (strncmp(info->broadcast_code, broadcast_code_list[i], kBroadcastCodeSize) == 0) {
  197. found = true;
  198. break;
  199. }
  200. }
  201. if (!found) {
  202. return;
  203. }
  204. }
  205. bool result = false;
  206. uint8_t handle = 0;
  207. result = AddLidarToConnect(info->broadcast_code, &handle);
  208. if (result == kStatusSuccess) {
  209. /** Set the point cloud data for a specific Livox LiDAR. */
  210. SetDataCallback(handle, GetLidarData, NULL);
  211. devices[handle].handle = handle;
  212. devices[handle].device_state = kDeviceStateDisconnect;
  213. }
  214. }
  215. int main(int argc, const char *argv[]) {
  216. printf("Livox SDK initializing.\n");
  217. /** Initialize Livox-SDK. */
  218. if (!Init()) {
  219. return -1;
  220. }
  221. printf("Livox SDK has been initialized.\n");
  222. LivoxSdkVersion _sdkversion;
  223. GetLivoxSdkVersion(&_sdkversion);
  224. printf("Livox SDK version %d.%d.%d .\n", _sdkversion.major, _sdkversion.minor, _sdkversion.patch);
  225. memset(devices, 0, sizeof(devices));
  226. memset(data_recveive_count, 0, sizeof(data_recveive_count));
  227. /** Set the callback function receiving broadcast message from Livox LiDAR. */
  228. SetBroadcastCallback(OnDeviceBroadcast);
  229. /** Set the callback function called when device state change,
  230. * which means connection/disconnection and changing of LiDAR state.
  231. */
  232. SetDeviceStateUpdateCallback(OnDeviceInfoChange);
  233. /** Start the device discovering routine. */
  234. if (!Start()) {
  235. Uninit();
  236. return -1;
  237. }
  238. printf("Start discovering device.\n");
  239. #ifdef WIN32
  240. Sleep(30000);
  241. #else
  242. sleep(30);
  243. #endif
  244. int i = 0;
  245. for (i = 0; i < kMaxLidarCount; ++i) {
  246. if (devices[i].device_state == kDeviceStateSampling) {
  247. /** Stop the sampling of Livox LiDAR. */
  248. LidarStopSampling(devices[i].handle, OnStopSampleCallback, NULL);
  249. }
  250. }
  251. /** Uninitialize Livox-SDK. */
  252. Uninit();
  253. }

         如果用户需要自己读取数据,只需要修改一下上面这段代码,然后合入到自己的项目当中,略作调整即可。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/481593
推荐阅读
相关标签
  

闽ICP备14008679号