diff options
Diffstat (limited to 'udp2lcm/udp2lcm.c')
-rw-r--r-- | udp2lcm/udp2lcm.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/udp2lcm/udp2lcm.c b/udp2lcm/udp2lcm.c new file mode 100644 index 0000000..fdf32c8 --- /dev/null +++ b/udp2lcm/udp2lcm.c | |||
@@ -0,0 +1,118 @@ | |||
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 | |||
13 | #include "udp2lcm.h" | ||
14 | |||
15 | pthread_t udpRecv, udpSend; | ||
16 | int8_t heartBeat[9] = {0}; | ||
17 | pthread_mutex_t heartBeatMutex; | ||
18 | struct sockaddr_in clientAddr; | ||
19 | char clientIP[20] = ""; | ||
20 | lcm_t *lcm; | ||
21 | |||
22 | int main() { | ||
23 | if (!LCMInit()) { | ||
24 | fprintf(stderr, "Error: Failed to initialize LCM\n"); | ||
25 | return -1; | ||
26 | } | ||
27 | // 初始化线程锁 | ||
28 | pthread_mutex_init(&heartBeatMutex, NULL); | ||
29 | // 开启udp接收线程 | ||
30 | pthread_create(&udpRecv, NULL, udpRecvHandler, NULL); | ||
31 | pid_t httpServerPid = -1; | ||
32 | if ((httpServerPid = fork()) == 0) { | ||
33 | // 拉起服务器进程,手机端需要申请的文件/mnt/cf/mapfile/defaultMap.txt | ||
34 | // ATTENTION: 这里的路径需要根据实际存储地图的路径来修改 | ||
35 | chdir("/mnt/cf/mapfile/"); | ||
36 | /* | ||
37 | * execlp使用系统调用exec()执行一个程序 | ||
38 | * 第一个参数是文件名,将在PATH中查找,最后一个参数必须是NULL | ||
39 | * 其他的是传递过去的参数,按一般约定,第一个参数是程序名,不被使用 | ||
40 | * 因而这里出现了两个python | ||
41 | */ | ||
42 | execlp("python", "python", "-m", "http.server", NULL); | ||
43 | } | ||
44 | while (true) { | ||
45 | pause(); | ||
46 | } | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | bool LCMInit() { | ||
51 | if ((lcm = lcm_create("udpm://239.255.76.67:7667?ttl=1")) == NULL) { | ||
52 | fprintf(stderr, "Error: Failed to create Path Ctrl LCM\n"); | ||
53 | return false; | ||
54 | } | ||
55 | return true; | ||
56 | } | ||
57 | |||
58 | void parseCmd(const char *buffer, int bytesReceived) { | ||
59 | if (buffer == NULL) { | ||
60 | fprintf(stderr, "Error: Invalid message\n"); | ||
61 | return; | ||
62 | } | ||
63 | |||
64 | path_ctrl_t path; | ||
65 | robot_control_t robotCtrlData; | ||
66 | pose_t curPos; | ||
67 | if (buffer[0] == 0) { | ||
68 | // 手机端用来与udp2lcm服务器建立连接的初始化消息 | ||
69 | // 也是手机端的心跳 | ||
70 | ; | ||
71 | } else if (buffer[0] == 1) { | ||
72 | // 建图过程中,手机端遥控小车进行移动,命令下发至轮控模块 | ||
73 | path.cmd = buffer[1]; | ||
74 | path.speed = buffer[2]; | ||
75 | path_ctrl_t_publish(lcm, "wheel_ctrl", &path); | ||
76 | } else if (buffer[0] == 2) { | ||
77 | /* | ||
78 | * 结束建图,主要有以下几个任务: | ||
79 | * - 向轮控模块发送停止命令 | ||
80 | * - 通知算法模块结束建图 | ||
81 | * - 拉起http服务器进程(改由main拉起,省的每次拉起浪费资源) | ||
82 | * - 向手机端通知建图完成 | ||
83 | * 开始通过lcm接受算法给出的实时坐标,存储至heartBeat数组中(对应格式) | ||
84 | */ | ||
85 | path.cmd = 0; | ||
86 | path.speed = 0; | ||
87 | path_ctrl_t_publish(lcm, "wheel_ctrl", &path); | ||
88 | |||
89 | robotCtrlInit(&robotCtrlData, 0, 32, 0, 0, 0, 0, 0); | ||
90 | robot_control_t_publish(lcm, "ROBOT_CONTROL", &robotCtrlData); | ||
91 | |||
92 | pose_t_subscribe(lcm, "CURRENTPOSE", poseHandler, NULL); | ||
93 | } else if (buffer[0] == 3) { | ||
94 | // 手机发来的终点坐标,转发给算法模块 | ||
95 | } | ||
96 | } | ||
97 | |||
98 | void poseHandler(const lcm_recv_buf_t *rbuf, const char *channel, | ||
99 | const pose_t *msg, void *userdata) { | ||
100 | int16_t x, y, sita; | ||
101 | x = (int16_t)msg->pos[0]; | ||
102 | y = (int16_t)msg->pos[1]; | ||
103 | sita = (int16_t)msg->pos[2]; | ||
104 | while (sita > 180) | ||
105 | sita -= 360; | ||
106 | while (sita < -180) | ||
107 | sita += 360; | ||
108 | pthread_mutex_lock(&heartBeatMutex); | ||
109 | heartBeat[0] = 0x03; | ||
110 | heartBeat[1] = heartBeat[2] = 0; | ||
111 | heartBeat[3] = x >> 8; | ||
112 | heartBeat[4] = x; | ||
113 | heartBeat[5] = y >> 8; | ||
114 | heartBeat[6] = y; | ||
115 | heartBeat[7] = sita >> 8; | ||
116 | heartBeat[8] = sita; | ||
117 | pthread_mutex_unlock(&heartBeatMutex); | ||
118 | } \ No newline at end of file | ||