diff options
Diffstat (limited to 'udp2lcm.c')
-rw-r--r-- | udp2lcm.c | 184 |
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 | |||
20 | pthread_t udpRecv, udpSend; | ||
21 | int8_t heartBeat[9] = {0}; // 用于存储需要发送的心跳信息 | ||
22 | // clientIP用于存储手机端IP地址,仅在第一次接收消息后修改 | ||
23 | // 本身就是inet_ntoa(clientAddr.sin_addr),二者内容完全一致 | ||
24 | struct sockaddr_in clientAddr; | ||
25 | char clientIP[20] = ""; | ||
26 | lcm_t *path_ctrl_lcm; | ||
27 | |||
28 | bool LCMInit(); | ||
29 | void udpSendHandler(); | ||
30 | void udpRecvHandler(); | ||
31 | void parseCmd(const char *buffer, int bytesReceived); | ||
32 | |||
33 | int 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 | |||
43 | bool 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 | |||
55 | void 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 | |||
128 | void 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 | |||
154 | void 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 | ||