rb_lidar.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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 BUF_SIZE 1206
  9. // UDP接收线程
  10. void* udp_listener(void* arg) {
  11. RBLidar* lidar = (RBLidar*)arg;
  12. int sockfd;
  13. struct sockaddr_in server_addr, client_addr;
  14. socklen_t addr_len = sizeof(client_addr);
  15. udp_packet_t udp_packet_temp;
  16. // 创建UDP套接字
  17. sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  18. if (sockfd < 0) {
  19. perror("socket");
  20. return NULL;
  21. }
  22. // 设置服务器地址
  23. memset(&server_addr, 0, sizeof(server_addr));
  24. server_addr.sin_family = AF_INET;
  25. inet_pton(AF_INET, lidar->ip, &server_addr.sin_addr);
  26. server_addr.sin_port = htons(lidar->port);
  27. // 绑定套接字
  28. if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
  29. perror("bind");
  30. close(sockfd);
  31. return NULL;
  32. }
  33. printf("Listening for UDP packets on %s:%d...\n", lidar->ip, lidar->port);
  34. // 接收数据
  35. while (1) {
  36. int len = recvfrom(sockfd, (char *)&udp_packet_temp, BUF_SIZE, 0, (struct sockaddr*)&client_addr, &addr_len);
  37. if (len < 0) {
  38. perror("recvfrom");
  39. continue;
  40. }
  41. // 使用双缓冲机制
  42. pthread_mutex_lock(&lidar->mutex);
  43. // 将接收到的UDP包中的子包存入当前缓冲区
  44. for (int i = 0; i < CONFIG_UDP_BLOCKS; i++) {
  45. sub_packet_t* sub_packet = &udp_packet_temp.sub_packet[i];
  46. // 将子包存入当前缓冲区
  47. memcpy(&lidar->buffer[lidar->current][lidar->valid_count[lidar->current]], sub_packet, sizeof(sub_packet_t));
  48. // 统计有效数据
  49. lidar->valid_count[lidar->current]++;
  50. // 检查azimuth是否为0
  51. if (sub_packet->azimuth == 0) {
  52. // 切换到下一个缓冲区并通知处理线程
  53. lidar->current = (lidar->current + 1) % 2; // 切换缓冲区
  54. lidar->valid_count[lidar->current] = 0;
  55. memcpy(&lidar->buffer[lidar->current][lidar->valid_count[lidar->current]], sub_packet, sizeof(sub_packet_t));
  56. lidar->valid_count[lidar->current]++;
  57. // pthread_cond_signal(&lidar->cond); // 通知处理线程
  58. }
  59. }
  60. pthread_mutex_unlock(&lidar->mutex);
  61. }
  62. close(sockfd);
  63. return NULL;
  64. }
  65. // 组包线程
  66. void* packet_processor(void* arg) {
  67. RBLidar* lidar = (RBLidar*)arg;
  68. // 处理数据
  69. while (1) {
  70. pthread_mutex_lock(&lidar->mutex);
  71. pthread_cond_wait(&lidar->cond, &lidar->mutex); // 等待数据
  72. // 处理当前缓冲区数据
  73. int next_index = (lidar->current + 1) % 2; // 获取上一缓冲区索引
  74. int count = lidar->valid_count[next_index]; // 获取有效数据的数量
  75. // 创建临时缓冲区
  76. sub_packet_t* temp_buffer = (sub_packet_t*)malloc(sizeof(sub_packet_t) * SUBPKT_BUF_COUNT);
  77. int temp_count = 0;
  78. // 处理当前缓冲区中的每个有效子包
  79. for (int i = 0; i < count; i++) {
  80. sub_packet_t* sub_packet = &lidar->buffer[next_index][i];
  81. memcpy(&temp_buffer[temp_count++], sub_packet, sizeof(sub_packet_t));
  82. }
  83. // 调用回调函数
  84. lidar->callback((const char*)temp_buffer, sizeof(sub_packet_t) * temp_count);
  85. // 重置当前缓冲区
  86. memset(lidar->buffer[next_index], 0, sizeof(sub_packet_t) * SUBPKT_BUF_COUNT);
  87. lidar->valid_count[next_index] = 0; // 重置有效数据计数
  88. free(temp_buffer); // 释放临时缓冲区
  89. pthread_mutex_unlock(&lidar->mutex);
  90. }
  91. return NULL;
  92. }
  93. // 创建RBLidar实例
  94. RBLidar* rblidar_create(const char* ip, int port, callback_t callback) {
  95. RBLidar* lidar = (RBLidar*)malloc(sizeof(RBLidar));
  96. lidar->ip = strdup(ip);
  97. lidar->port = port;
  98. lidar->callback = callback;
  99. // 初始化双缓冲区和其他线程同步机制
  100. for (int i = 0; i < 2; i++) {
  101. lidar->buffer[i] = (sub_packet_t*)malloc(sizeof(sub_packet_t) * SUBPKT_BUF_COUNT);
  102. }
  103. lidar->current = 0;
  104. pthread_mutex_init(&lidar->mutex, NULL);
  105. pthread_cond_init(&lidar->cond, NULL);
  106. // 创建接收线程
  107. pthread_t listener_thread;
  108. pthread_create(&listener_thread, NULL, udp_listener, lidar);
  109. pthread_detach(listener_thread); // 让线程在结束时自动回收资源
  110. // 创建组包线程
  111. pthread_t processor_thread;
  112. pthread_create(&processor_thread, NULL, packet_processor, lidar);
  113. pthread_detach(processor_thread);
  114. return lidar;
  115. }
  116. // 释放RBLidar实例
  117. void rblidar_destroy(RBLidar* lidar) {
  118. for (int i = 0; i < 2; i++) {
  119. free(lidar->buffer[i]);
  120. }
  121. pthread_mutex_destroy(&lidar->mutex);
  122. pthread_cond_destroy(&lidar->cond);
  123. free(lidar->ip);
  124. free(lidar);
  125. }