command.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * Copyright (c) 2019, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-08-26 sogwms The first version
  9. */
  10. #include <command.h>
  11. #define DBG_SECTION_NAME "command"
  12. #define DBG_LEVEL DBG_LOG
  13. #include <rtdbg.h>
  14. // Thread
  15. #define THREAD_PRIORITY ((RT_THREAD_PRIORITY_MAX / 3) + 1)
  16. #define THREAD_STACK_SIZE 512
  17. #define THREAD_TIMESLICE 10
  18. static rt_thread_t cmd_tid = RT_NULL;
  19. //
  20. struct command_info
  21. {
  22. rt_uint16_t cmd;
  23. };
  24. typedef struct command_info *command_info_t;
  25. // Message Queue
  26. struct command_msg
  27. {
  28. struct command_info info;
  29. void *param;
  30. rt_uint16_t size;
  31. };
  32. #define MAX_MSGS 32
  33. static rt_mq_t cmd_mq = RT_NULL;
  34. // Target
  35. chassis_t g_chas;
  36. static rt_err_t command_handle_get(struct command_msg *msg)
  37. {
  38. switch (msg->info.cmd)
  39. {
  40. case COMMAND_GET_WHEEL0_PID:
  41. case COMMAND_GET_WHEEL1_PID:
  42. case COMMAND_GET_WHEEL2_PID:
  43. case COMMAND_GET_WHEEL3_PID:
  44. if (msg->size == sizeof(struct cmd_pid))
  45. {
  46. struct cmd_pid *ppid = msg->param;
  47. struct controller_param parameter;
  48. controller_get_param(g_chas->c_wheels[msg->info.cmd - COMMAND_GET_WHEEL0_PID]->w_controller, &parameter);
  49. ppid->kp = parameter.data.pid.kp;
  50. ppid->ki = parameter.data.pid.ki;
  51. ppid->kd = parameter.data.pid.kd;
  52. }
  53. else
  54. {
  55. return RT_ERROR;
  56. }
  57. break;
  58. case COMMAND_GET_WHEELS_PID:
  59. if (msg->size >= 2 * sizeof(struct cmd_pid))
  60. {
  61. struct cmd_pid *ppid = msg->param;
  62. struct controller_param parameter;
  63. for (int i = 0; (i < g_chas->c_kinematics->total_wheels) && (i < (msg->size / sizeof(struct cmd_pid))); i++)
  64. {
  65. controller_get_param(g_chas->c_wheels[i]->w_controller, &parameter);
  66. ppid[i].id = COMMAND_GET_WHEEL0_PID + i;
  67. ppid[i].kp = parameter.data.pid.kp;
  68. ppid[i].ki = parameter.data.pid.ki;
  69. ppid[i].kd = parameter.data.pid.kd;
  70. }
  71. }
  72. else
  73. {
  74. return RT_ERROR;
  75. }
  76. break;
  77. default: return RT_ERROR;
  78. }
  79. return RT_EOK;
  80. }
  81. rt_err_t command_handle(rt_uint16_t cmd, void *param, rt_uint16_t size)
  82. {
  83. struct command_msg msg = {
  84. .param = param,
  85. .size = size,
  86. .info = {
  87. .cmd = cmd,
  88. }
  89. };
  90. if (cmd > COMMAND_GET_START && cmd < COMMAND_GET_END)
  91. {
  92. return command_handle_get(&msg);
  93. }
  94. return rt_mq_send(cmd_mq, &msg, sizeof(struct command_msg));
  95. }
  96. rt_err_t command_send(command_sender_t sender, rt_uint16_t cmd, void *param, rt_uint16_t size)
  97. {
  98. if (sender->send != RT_NULL)
  99. {
  100. return sender->send(cmd, param, size);
  101. }
  102. return RT_ERROR;
  103. }
  104. static void command_thread_entry(void *param)
  105. {
  106. struct command_msg msg;
  107. while (1)
  108. {
  109. rt_mq_recv(cmd_mq, &msg, sizeof(struct command_msg), RT_WAITING_FOREVER);
  110. if (g_chas == RT_NULL)
  111. {
  112. LOG_D("The target is NULL");
  113. continue;
  114. }
  115. switch (msg.info.cmd)
  116. {
  117. case COMMAND_SET_WHEELS_PID:
  118. if (msg.size >= 2 * sizeof(struct cmd_pid))
  119. {
  120. struct cmd_pid *ppid = msg.param;
  121. struct controller_param parameter;
  122. for (int i = 0; i < g_chas->c_kinematics->total_wheels; i++)
  123. {
  124. parameter.data.pid.kp = ppid[i].kp;
  125. parameter.data.pid.ki = ppid[i].ki;
  126. parameter.data.pid.kd = ppid[i].kd;
  127. controller_set_param(g_chas->c_wheels[ppid[i].id]->w_controller, &parameter);
  128. }
  129. }
  130. break;
  131. case COMMAND_SET_WHEEL0_PID:
  132. case COMMAND_SET_WHEEL1_PID:
  133. case COMMAND_SET_WHEEL2_PID:
  134. case COMMAND_SET_WHEEL3_PID:
  135. if (msg.size == sizeof(struct cmd_pid))
  136. {
  137. if (g_chas->c_kinematics->total_wheels > msg.info.cmd - COMMAND_SET_WHEEL0_PID)
  138. {
  139. struct cmd_pid *ppid = msg.param;
  140. struct controller_param parameter = {
  141. .data.pid.kp = ppid->kp,
  142. .data.pid.ki = ppid->ki,
  143. .data.pid.kd = ppid->kd
  144. };
  145. controller_set_param(g_chas->c_wheels[msg.info.cmd - COMMAND_SET_WHEEL0_PID]->w_controller, &parameter);
  146. }
  147. }
  148. break;
  149. case COMMAND_SET_CHASSIS_STOP:
  150. chassis_move(g_chas, 0.0f);
  151. break;
  152. case COMMAND_SET_CHASSIS_FORWARD:
  153. chassis_straight(g_chas, CHASSIS_VELOCITY_LINEAR_MAXIMUM / 2.0f);
  154. break;
  155. case COMMAND_SET_CHASSIS_BACKWARD:
  156. chassis_straight(g_chas, -CHASSIS_VELOCITY_LINEAR_MAXIMUM / 2.0f);
  157. break;
  158. case COMMAND_SET_CHASSIS_ROTATE_LEFT:
  159. chassis_rotate(g_chas, CHASSIS_VELOCITY_ANGULAR_MAXIMUM / 2.0f);
  160. break;
  161. case COMMAND_SET_CHASSIS_ROTATE_RIGHT:
  162. chassis_rotate(g_chas, -CHASSIS_VELOCITY_ANGULAR_MAXIMUM / 2.0f);
  163. break;
  164. case COMMAND_SET_CHASSIS_MOVE_LEFT:
  165. chassis_move(g_chas, CHASSIS_VELOCITY_LINEAR_MAXIMUM / 2.0f);
  166. break;
  167. case COMMAND_SET_CHASSIS_MOVE_RIGHT:
  168. chassis_move(g_chas, -CHASSIS_VELOCITY_LINEAR_MAXIMUM / 2.0f);
  169. break;
  170. case COMMAND_SET_CHASSIS_FORWARD_WITH_PARAM:
  171. case COMMAND_SET_CHASSIS_BACKWARD_WITH_PARAM:
  172. case COMMAND_SET_CHASSIS_ROTATE_LEFT_WITH_PARAM:
  173. case COMMAND_SET_CHASSIS_ROTATE_RIGHT_WITH_PARAM:
  174. case COMMAND_SET_CHASSIS_MOVE_LEFT_WITH_PARAM:
  175. case COMMAND_SET_CHASSIS_MOVE_RIGHT_WITH_PARAM:
  176. if (msg.size == sizeof(struct cmd_velocity))
  177. {
  178. struct cmd_velocity *target_velocity = (struct cmd_velocity *)msg.param;
  179. rt_err_t (*p_fun)(chassis_t chas, float data);
  180. float tmp;
  181. if (msg.info.cmd == COMMAND_SET_CHASSIS_FORWARD_WITH_PARAM)
  182. {
  183. tmp = target_velocity->data.linear_x;
  184. p_fun = chassis_straight;
  185. }
  186. else if (msg.info.cmd == COMMAND_SET_CHASSIS_BACKWARD_WITH_PARAM)
  187. {
  188. tmp = -target_velocity->data.linear_x;
  189. p_fun = chassis_straight;
  190. }
  191. else if (msg.info.cmd == COMMAND_SET_CHASSIS_ROTATE_LEFT_WITH_PARAM)
  192. {
  193. tmp = target_velocity->data.angular_z;
  194. p_fun = chassis_rotate;
  195. }
  196. else if (msg.info.cmd == COMMAND_SET_CHASSIS_ROTATE_RIGHT_WITH_PARAM)
  197. {
  198. tmp = -target_velocity->data.angular_z;
  199. p_fun = chassis_rotate;
  200. }
  201. else if (msg.info.cmd == COMMAND_SET_CHASSIS_MOVE_LEFT_WITH_PARAM)
  202. {
  203. tmp = target_velocity->data.linear_y;
  204. p_fun = chassis_move;
  205. }
  206. else
  207. {
  208. tmp = -target_velocity->data.linear_y;
  209. p_fun = chassis_move;
  210. }
  211. p_fun(g_chas, tmp);
  212. }
  213. break;
  214. case COMMAND_SET_CHASSIS_VELOCITY_LINEAR_X:
  215. case COMMAND_SET_CHASSIS_VELOCITY_LINEAR_Y:
  216. case COMMAND_SET_CHASSIS_VELOCITY_ANGULAR_Z:
  217. if (msg.size == sizeof(struct cmd_velocity))
  218. {
  219. struct cmd_velocity *target_velocity = (struct cmd_velocity *)msg.param;
  220. rt_err_t (*p_fun)(chassis_t chas, float data);
  221. float tmp;
  222. if (msg.info.cmd == COMMAND_SET_CHASSIS_VELOCITY_LINEAR_X)
  223. {
  224. tmp = target_velocity->data.linear_x;
  225. p_fun = chassis_set_velocity_x;
  226. }
  227. else if (msg.info.cmd == COMMAND_SET_CHASSIS_VELOCITY_LINEAR_Y)
  228. {
  229. tmp = target_velocity->data.linear_y;
  230. p_fun = chassis_set_velocity_y;
  231. }
  232. else
  233. {
  234. tmp = target_velocity->data.angular_z;
  235. p_fun = chassis_set_velocity_z;
  236. }
  237. p_fun(g_chas, tmp);
  238. }
  239. break;
  240. default:
  241. break;
  242. }
  243. }
  244. }
  245. rt_err_t command_init(chassis_t chas)
  246. {
  247. cmd_mq = rt_mq_create("command", sizeof(struct command_msg), MAX_MSGS, RT_IPC_FLAG_FIFO);
  248. if (cmd_mq == RT_NULL)
  249. {
  250. LOG_E("Failed to creat meassage queue");
  251. return RT_ERROR;
  252. }
  253. cmd_tid = rt_thread_create("command",
  254. command_thread_entry, RT_NULL,
  255. THREAD_STACK_SIZE,
  256. THREAD_PRIORITY, THREAD_TIMESLICE);
  257. if (cmd_tid == RT_NULL)
  258. {
  259. LOG_E("Failed to creat thread");
  260. return RT_ERROR;
  261. }
  262. g_chas = chas;
  263. rt_thread_startup(cmd_tid);
  264. return RT_EOK;
  265. }