rb_lidar.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <arpa/inet.h>
  5. #include <unistd.h>
  6. #include <pthread.h>
  7. #include "rb_lidar.h"
  8. #define BUFFER_SIZE 1024
  9. // UDP接收线程
  10. void *udp_listener(void *arg)
  11. {
  12. RBLidar *lidar = (RBLidar *)arg;
  13. int sockfd;
  14. struct sockaddr_in server_addr, client_addr;
  15. socklen_t addr_len = sizeof(client_addr);
  16. udp_packet_t udp_packet_temp;
  17. uint32_t timestamp_last = 0;
  18. uint32_t timestamp_div = 1;
  19. // 创建UDP套接字
  20. sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  21. if (sockfd < 0)
  22. {
  23. perror("socket");
  24. return NULL;
  25. }
  26. // 设置服务器地址
  27. memset(&server_addr, 0, sizeof(server_addr));
  28. server_addr.sin_family = AF_INET;
  29. inet_pton(AF_INET, lidar->ip, &server_addr.sin_addr);
  30. server_addr.sin_port = htons(lidar->port);
  31. // 绑定套接字
  32. if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
  33. {
  34. perror("bind");
  35. close(sockfd);
  36. return NULL;
  37. }
  38. printf("Listening for UDP packets on %s:%d...\n", lidar->ip, lidar->port);
  39. // 接收数据
  40. while (1)
  41. {
  42. int len = recvfrom(sockfd, (char *)&udp_packet_temp, UDP_BUF_SIZE, 0, (struct sockaddr *)&client_addr, &addr_len);
  43. if (len < 0)
  44. {
  45. perror("recvfrom");
  46. continue;
  47. }
  48. // 使用双缓冲机制
  49. pthread_mutex_lock(&lidar->mutex);
  50. uint32_t timestamp_current = udp_packet_temp.timestamp;
  51. if(timestamp_current == 0)
  52. {
  53. timestamp_current = timestamp_last;
  54. }
  55. else
  56. {
  57. timestamp_div = (timestamp_current - timestamp_last) / CONFIG_UDP_BLOCKS;
  58. timestamp_last = timestamp_current;
  59. }
  60. // 将接收到的UDP包中的子包存入当前缓冲区
  61. for (int i = 0; i < CONFIG_UDP_BLOCKS; i++)
  62. {
  63. sub_packet_t *sub_packet = &udp_packet_temp.sub_packet[i];
  64. // 检查azimuth是否为0
  65. if (sub_packet->azimuth != 0xffff)
  66. {
  67. // 将子包存入当前缓冲区
  68. memcpy(&lidar->buffer[lidar->current][lidar->valid_count[lidar->current]], sub_packet, sizeof(sub_packet_t));
  69. lidar->timestamps[lidar->current][lidar->valid_count[lidar->current]] = timestamp_current + i * timestamp_div;
  70. // lidar->timestamps[lidar->current][lidar->valid_count[lidar->current]] = timestamp_current;
  71. // 统计有效数据
  72. lidar->valid_count[lidar->current]++;
  73. }
  74. // 检查azimuth是否为0
  75. if (sub_packet->azimuth == 0)
  76. {
  77. // 切换到下一个缓冲区并通知处理线程
  78. lidar->current = (lidar->current + 1) % 2; // 切换缓冲区
  79. lidar->valid_count[lidar->current] = 0;
  80. memcpy(&lidar->buffer[lidar->current][lidar->valid_count[lidar->current]], sub_packet, sizeof(sub_packet_t));
  81. lidar->timestamps[lidar->current][lidar->valid_count[lidar->current]] = timestamp_current + i * timestamp_div; // 增加i
  82. lidar->valid_count[lidar->current]++;
  83. pthread_cond_signal(&lidar->cond); // 通知处理线程
  84. }
  85. }
  86. pthread_mutex_unlock(&lidar->mutex);
  87. }
  88. close(sockfd);
  89. return NULL;
  90. }
  91. // 组包线程
  92. void *packet_processor(void *arg)
  93. {
  94. RBLidar *lidar = (RBLidar *)arg;
  95. // 处理数据
  96. while (1)
  97. {
  98. pthread_mutex_lock(&lidar->mutex);
  99. pthread_cond_wait(&lidar->cond, &lidar->mutex); // 等待数据
  100. // 处理当前缓冲区数据
  101. int next_index = (lidar->current + 1) % 2; // 获取上一缓冲区索引
  102. int count = lidar->valid_count[next_index]; // 获取有效数据的数量
  103. // 创建临时缓冲区以存储点数据
  104. point_data_t temp_buffer[BUFFER_SIZE * CONFIG_BLOCK_COUNT]; // 假设 BUFFER_SIZE 足够大
  105. int temp_count = 0;
  106. // 处理当前缓冲区中的每个有效子包
  107. for (int i = 0; i < count - 1; i++)
  108. {
  109. sub_packet_t *sub_packet = &lidar->buffer[next_index][i];
  110. int start_angle = sub_packet->azimuth % 36000;
  111. int end_angle = lidar->buffer[next_index][i + 1].azimuth % 36000; // 获取下一个子包的 azimuth
  112. // 计算角度增量
  113. int div_angle;
  114. if (end_angle >= start_angle)
  115. {
  116. div_angle = (end_angle - start_angle) / CONFIG_BLOCK_COUNT;
  117. }
  118. else
  119. {
  120. div_angle = (36000 - start_angle + end_angle) / CONFIG_BLOCK_COUNT;
  121. }
  122. // 计算时间间隔
  123. uint32_t start_time = lidar->timestamps[next_index][i]; // 从时间戳数组中获取当前子包的时间戳
  124. uint32_t end_time = lidar->timestamps[next_index][i + 1]; // 获取下一个子包的时间戳
  125. uint32_t div_time = (end_time - start_time) / CONFIG_BLOCK_COUNT; // 计算时间间隔make
  126. //printf("Start Time: %u, End Time: %u, Div Time: %u\n", start_time, end_time, div_time);
  127. // 填充点数据
  128. for (int j = 0; j < CONFIG_BLOCK_COUNT; j++) {
  129. point_data_t point_data;
  130. point_data.azimuth = (start_angle + j * div_angle) % 36000;
  131. point_data.dist = sub_packet->point[j].dist_0;
  132. point_data.rssi = sub_packet->point[j].rssi_0;
  133. point_data.timestamp = start_time + j * div_time;
  134. // point_data.timestamp = start_time;
  135. // 将填充的点数据添加到临时缓冲区
  136. temp_buffer[temp_count++] = point_data;
  137. }
  138. }
  139. // 调用回调函数
  140. lidar->callback((void*)temp_buffer, sizeof(point_data_t) * temp_count);
  141. // // 重置当前缓冲区
  142. // memset(lidar->buffer[next_index], 0, sizeof(sub_packet_t) * BUFFER_SIZE);
  143. // lidar->valid_count[next_index] = 0; // 重置有效数据计数
  144. pthread_mutex_unlock(&lidar->mutex);
  145. }
  146. return NULL;
  147. }
  148. // 创建RBLidar实例
  149. RBLidar *rblidar_create(const char *ip, int port, callback_t callback)
  150. {
  151. RBLidar *lidar = (RBLidar *)malloc(sizeof(RBLidar));
  152. lidar->ip = strdup(ip);
  153. lidar->port = port;
  154. lidar->callback = callback;
  155. lidar->current = 0;
  156. pthread_mutex_init(&lidar->mutex, NULL);
  157. pthread_cond_init(&lidar->cond, NULL);
  158. // 创建接收线程
  159. pthread_t listener_thread;
  160. pthread_create(&listener_thread, NULL, udp_listener, lidar);
  161. pthread_detach(listener_thread); // 让线程在结束时自动回收资源
  162. // 创建组包线程
  163. pthread_t processor_thread;
  164. pthread_create(&processor_thread, NULL, packet_processor, lidar);
  165. pthread_detach(processor_thread);
  166. return lidar;
  167. }
  168. // 释放RBLidar实例
  169. void rblidar_destroy(RBLidar *lidar)
  170. {
  171. for (int i = 0; i < 2; i++)
  172. {
  173. free(lidar->buffer[i]);
  174. }
  175. pthread_mutex_destroy(&lidar->mutex);
  176. pthread_cond_destroy(&lidar->cond);
  177. free(lidar->ip);
  178. free(lidar);
  179. }