aboutsummaryrefslogtreecommitdiffstats
path: root/udp2lcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'udp2lcm.c')
-rw-r--r--udp2lcm.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/udp2lcm.c b/udp2lcm.c
new file mode 100644
index 0000000..ec8aee8
--- /dev/null
+++ b/udp2lcm.c
@@ -0,0 +1,184 @@
1// Encoded in UTF-8
2
3/*
4 * struct path_ctrl_t
5 * {
6 * int8_t cmd;
7 * int8_t speed;
8 * }
9 * 这是与轮控模块通信的数据结构,speed为0-100表示速度
10 * cmd为0停,1前,2左,3右
11 */
12#include "path/path_ctrl_t.h"
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16
17#define MAX_BUFFER_SIZE 1024
18#define PORT 5001
19
20pthread_t udpRecv, udpSend;
21int8_t heartBeat[9] = {0}; // 用于存储需要发送的心跳信息
22// clientIP用于存储手机端IP地址,仅在第一次接收消息后修改
23// 本身就是inet_ntoa(clientAddr.sin_addr),二者内容完全一致
24struct sockaddr_in clientAddr;
25char clientIP[20] = "";
26lcm_t *path_ctrl_lcm;
27
28bool LCMInit();
29void udpSendHandler();
30void udpRecvHandler();
31void parseCmd(const char *buffer, int bytesReceived);
32
33int main() {
34 if (!LCMInit()) {
35 fprintf(stderr, "Error: Failed to initialize LCM\n");
36 return -1;
37 }
38 // 开启udp接收线程
39 pthread_create(&udpRecv, NULL, udpRecvHandler, NULL);
40 return 0;
41}
42
43bool LCMInit() {
44 // TODO: 在这里同意初始化各个LCM变量
45 // ATTENTION:
46 // 是否在这里订阅各个通道、各个通道需要在什么地方订阅,需要慎重考虑
47 if ((path_ctrl_lcm = lcm_create(NULL)) == NULL) {
48 fprintf(stderr, "Error: Failed to create Path Ctrl LCM\n");
49 return false;
50 }
51
52 return true;
53}
54
55void udpRecvHandler() {
56 int socketfd = -1;
57 char buffer[MAX_BUFFER_SIZE];
58 struct sockaddr_in serverAddr;
59 socklen_t addrLen = sizeof(serverAddr);
60 int bytesReceived;
61
62 int retval;
63 struct pollfd fds;
64
65 if ((socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
66 fprintf(stderr, "Error: Failed to create socket\n");
67 return;
68 }
69 memset((char *)&serverAddr, 0, sizeof(serverAddr));
70 memset(buffer, 0, sizeof(buffer));
71 serverAddr.sin_family = AF_INET;
72 serverAddr.sin_port = htons(port);
73 serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
74
75 if (bind(socketfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) ==
76 -1) {
77 fprintf(stderr, "Error: Bind failed\n");
78 close(socketfd);
79 return;
80 }
81
82 bytesReceived = recvfrom(socketfd, buffer, MAX_BUFFER_SIZE, 0,
83 (struct sockaddr *)&clientAddr, &addrLen);
84 if (bytesReceived == -1) {
85 fprintf(stderr, "Error: Failed to receive data\n");
86 close(socketfd);
87 return;
88 }
89 printf("Start message from %s: %s\n", inet_ntoa(clientAddr.sin_addr),
90 buffer);
91 strcpy(clientIP, inet_ntoa(clientAddr.sin_addr));
92
93 // 在接收到第一条消息之后,开启udp发送线程,用于发送心跳信息
94 if (pthread_create(&udpSend, NULL, udpSendHandler, NULL) != 0) {
95 fprintf(stderr, "Error creating udpSend thread\n");
96 close(socketfd);
97 exit(-1);
98 }
99
100 fds.fd = socketfd;
101 fds.events = POLLIN;
102
103 while (true) {
104 retval = poll(&fds, 1, 3000);
105 if (retval == -1) {
106 fprintf(stderr, "Error: select failed\n");
107 break;
108 } else if (retval == 0) {
109 printf("No data within three seconds.\n");
110 speedControl(0, 0);
111 } else {
112 bytesReceived = recvfrom(socketfd, buffer, MAX_BUFFER_SIZE, 0,
113 (struct sockaddr *)&clientAddr, &addrLen);
114 if (bytesReceived == -1) {
115 fprintf(stderr, "Error: Failed to receive data\n");
116 continue;
117 }
118 printf("Massage from client %s: ", clientIP);
119 for (int i = 0; i < bytesReceived; i++) {
120 printf("%02x ", buffer[i]);
121 }
122 printf("\n");
123 parseCmd(buffer, bytesReceived);
124 }
125 }
126}
127
128void udpSendHandler() {
129 // 创建UDP套接字
130 int sockfd = -1;
131 struct sockaddr_in serverAddr;
132 if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
133 fprintf(stderr, "Error: Failed to create socket\n");
134 return;
135 }
136
137 memset((char *)&serverAddr, 0, sizeof(serverAddr));
138 serverAddr.sin_family = AF_INET; // 设置地址族为IPv4
139 serverAddr.sin_port = htons(port); // 设置端口号
140 if (inet_aton(clientIP, &serverAddr.sin_addr) == 0) {
141 fprintf(stderr, "Error: Failed to convert IP address\n");
142 close(sockfd);
143 return;
144 }
145
146 while (true) {
147 sendto(sockfd, (const char *)heartBeat, 9, 0,
148 (struct sockaddr *)&serverAddr, sizeof(serverAddr));
149 printf("Send: Data %02x udpSend successfully!\n", a);
150 sleep(1);
151 }
152}
153
154void parseCmd(const char *buffer, int bytesReceived) {
155 // TODO: 完成本函数的内容
156 if (buffer == NULL || strlen(buffer) != 9) {
157 fprintf(stderr, "Error: Invalid message\n");
158 return;
159 }
160
161 if (buffer[0] == 0) {
162 // 手机端用来与udp2lcm服务器建立连接的初始化消息
163 fprintf(stderr, "Why Init cmd here?\n");
164 } else if (buffer[0] == 1) {
165 // 建图过程中,手机端遥控小车进行移动,命令下发至轮控模块
166 path_ctrl_t path;
167 path.cmd = buffer[1];
168 path.speed = buffer[2];
169 path_ctrl_t_publish(path_ctrl_lcm, "wheel_ctrl", &path);
170 } else if (buffer[0] == 2) {
171 /*
172 * 结束建图,主要有以下几个任务:
173 * - 向轮控模块发送停止命令
174 * - 通知算法模块结束建图(FIXME: 是否接受算法模块的回应?)
175 * - 拉起http服务器进程
176 * - 向手机端通知建图完成
177 * -
178 * 开始通过lcm接受算法给出的实时坐标,存储至heartBeat数组中(对应格式)
179 */
180 } else if (buffer[0] == 3) {
181 // 手机发来的终点坐标,转发给算法模块
182 ;
183 }
184} \ No newline at end of file