task_scheduler.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. /*******************************************************************************************
  2. * @file task_scheduler.c
  3. *
  4. * @brief 任务调度
  5. *
  6. * (c) Copyright 2021, Shandong Huali electromechanical Co., Ltd..
  7. * This is protected by international copyright laws. Knowledge of the
  8. * source code may not be used to write a similar product. This file may
  9. * only be used in accordance with a license and should not be redistributed
  10. * in any way. We appreciate your understanding and fairness.
  11. *
  12. *
  13. * @author Simon
  14. * @date Created: 2021.06.17-T18:25:48+0800
  15. *
  16. *******************************************************************************************/
  17. #include "rtthread.h"
  18. #include "task_scheduler.h"
  19. #include "string.h"
  20. #include "env.h"
  21. #define DBG_TAG "task"
  22. #define DBG_LVL DBG_LOG
  23. #include <rtdbg.h>
  24. enum
  25. {
  26. TASK_TRAJECTORY_EOK = 0,
  27. TASK_TRAJECTORY_EREPEAT = 0x02, /* 接收任务后者指令重复 */
  28. TASK_TRAJECTORY_EFULL = 0x47, /* 任务接续时,小车当前已有两条任务,不接收新的任务 */
  29. TASK_TRAJECTORY_EOVERFLOW = 0x68, /* 接收到WCS的任务节点个数超过RES自身设定的节点个数 */
  30. TASK_TRAJECTORY_EXY = 0x61, /* 校验行驶指令,相邻的两坐标巷道坡道均不一致时错误编码 */
  31. TASK_TRAJECTORY_ELINK = 0x50, /* 任务接续失败,路径起点坐标与上一任务终点坐标不一致 */
  32. TASK_TRAJECTORY_EZ = 0x60, /* 校验行驶指令,相邻的两个坐标位置坐标层数不一致时错误编码 */
  33. TASK_TRAJECTORY_EPASS = 0x62, /* 校验行驶指令,坐标节点位置信息不允许通过时错误编码 */
  34. TASK_TRAJECTORY_ECUR = 0x64, /* 校验行驶指令,当前指令起点坐标与当前小车起点坐标不一致时错误编码 */
  35. };
  36. enum
  37. {
  38. TASK_SET_EOK = 0,
  39. TASK_SET_EDIFF = 0x48, /* 接收到的任务序号与RES内部缓存的任务不匹配 */
  40. TASK_SET_EEXIST = 0x49, /* 接收到的任务还没有执行,又接收到新的任务 */
  41. TASK_SET_EBUSY = 0x6a, /* 小车当前已有任务在执行 */
  42. TASK_SET_ESEG = 0x71, /* 接收到的目的段序号小于上次的目的段序号或大于总的目的段序号) */
  43. TASK_SET_EFINISH = 0x70, /* 当前任务已完成 */
  44. TASK_SET_EEMPTY = 0x72, /* 当前小车没有任务 */
  45. };
  46. typedef struct
  47. {
  48. uint8_t id;
  49. uint8_t cnt;
  50. point_t point[TASK_MAX_POINT];
  51. }task_trajectory_t;
  52. typedef struct
  53. {
  54. uint8_t status;
  55. uint8_t id; /* trajectory id */
  56. uint8_t cur_point_idx; /* form 1-255 */
  57. uint8_t target_point_idx; /* form 1-255 */
  58. }task_t;
  59. static task_trajectory_t task_trajectory_list[TASK_MAX_TRAJECTORY] = {0};
  60. static task_t task_sch = {0};
  61. /**
  62. * @funtion task_current_trajectory
  63. * @brief 获取当前任务路径
  64. * @Author Simon
  65. * @DateTime 2021.06.22-T17:56:13+0800
  66. *
  67. * @return >=0-任务路径序号, <0-无
  68. */
  69. static int task_current_trajectory(void)
  70. {
  71. if(!task_trajectory_list[0].id && !task_trajectory_list[1].id)
  72. {
  73. return -1;
  74. }
  75. else if(!task_trajectory_list[0].id || !task_trajectory_list[1].id)
  76. {
  77. if(!task_trajectory_list[0].id)
  78. {
  79. return 1;
  80. }
  81. else
  82. {
  83. return 0;
  84. }
  85. }
  86. if(task_trajectory_list[0].id > task_trajectory_list[1].id)
  87. {
  88. if(task_trajectory_list[0].id != 255 && task_trajectory_list[1].id != 1)
  89. {
  90. return 1;
  91. }
  92. else
  93. {
  94. return 0;
  95. }
  96. }
  97. else
  98. {
  99. if(task_trajectory_list[1].id != 255 && task_trajectory_list[0].id != 1)
  100. {
  101. return 0;
  102. }
  103. else
  104. {
  105. return 1;
  106. }
  107. }
  108. }
  109. /**
  110. * @funtion task_add_trajectory
  111. * @brief 添加路径
  112. * @Author Simon
  113. * @DateTime 2021.06.22-T17:57:21+0800
  114. *
  115. * @param id 任务序号
  116. * @param cnt 点数
  117. * @param trajectory 路径点表
  118. * @return
  119. * TASK_TRAJECTORY_EOK = 0,
  120. * TASK_TRAJECTORY_EREPEAT = 0x02, 接收任务后者指令重复
  121. * TASK_TRAJECTORY_EFULL = 0x47, 任务接续时,小车当前已有两条任务,不接收新的任务
  122. * TASK_TRAJECTORY_EOVERFLOW = 0x68, 接收到WCS的任务节点个数超过RES自身设定的节点个数
  123. * TASK_TRAJECTORY_EXY = 0x61, 校验行驶指令,相邻的两坐标巷道坡道均不一致时错误编码
  124. * TASK_TRAJECTORY_ELINK = 0x50, 任务接续失败,路径起点坐标与上一任务终点坐标不一致
  125. * TASK_TRAJECTORY_EZ = 0x60, 校验行驶指令,相邻的两个坐标位置坐标层数不一致时错误编码
  126. * TASK_TRAJECTORY_EPASS = 0x62, 校验行驶指令,坐标节点位置信息不允许通过时错误编码
  127. * TASK_TRAJECTORY_ECUR = 0x64, 校验行驶指令,当前指令起点坐标与当前小车起点坐标不一致时错误编码
  128. */
  129. int task_add_trajectory(uint8_t id, uint8_t cnt, point_t *trajectory)
  130. {
  131. uint8_t i;
  132. uint8_t push_idx;
  133. uint8_t point_idx = 0;
  134. if(cnt > TASK_MAX_POINT)
  135. {
  136. return TASK_TRAJECTORY_EOVERFLOW;
  137. }
  138. /* 任务满判断 */
  139. for(push_idx = 0; push_idx < TASK_MAX_TRAJECTORY; push_idx++)
  140. {
  141. if(!task_trajectory_list[push_idx].cnt)
  142. {
  143. break;
  144. }
  145. }
  146. if(push_idx >= TASK_MAX_TRAJECTORY)
  147. {
  148. LOG_W("trajectory full");
  149. return TASK_TRAJECTORY_EFULL;
  150. }
  151. /* 起始点接续判断 */
  152. if(!task_trajectory_list[0].id && !task_trajectory_list[1].id)
  153. {
  154. if(trajectory[0].x != S.xValue || trajectory[0].y != S.yValue)
  155. {
  156. LOG_W("trajectory start point is not at current position");
  157. return TASK_TRAJECTORY_ECUR;
  158. }
  159. }
  160. if(task_trajectory_list[0].id > task_trajectory_list[1].id)
  161. {
  162. if(task_trajectory_list[0].id != 255 && task_trajectory_list[1].id != 1)
  163. {
  164. if(memcmp(&task_trajectory_list[0].point[task_trajectory_list[0].cnt - 1],
  165. &trajectory[0], sizeof(point_t)))
  166. {
  167. LOG_W("points link error");
  168. return TASK_TRAJECTORY_ELINK;
  169. }
  170. }
  171. }
  172. if(task_trajectory_list[1].id > task_trajectory_list[0].id)
  173. {
  174. if(task_trajectory_list[1].id != 255 && task_trajectory_list[0].id != 1)
  175. {
  176. if(memcmp(&task_trajectory_list[1].point[task_trajectory_list[1].cnt - 1],
  177. &trajectory[0], sizeof(point_t)))
  178. {
  179. LOG_W("points link error");
  180. return TASK_TRAJECTORY_ELINK;
  181. }
  182. }
  183. }
  184. /* 起点判断 */ /* 改进起点判断*/
  185. if(S.xValue != trajectory[0].x || S.yValue != trajectory[0].y)
  186. {
  187. LOG_W("start points are no same");
  188. return TASK_TRAJECTORY_ECUR;
  189. }
  190. /* 路径直线判断 */
  191. for(i = 1; i < cnt; i++)
  192. {
  193. if(trajectory[i].z == trajectory[i - 1].z)
  194. {
  195. if(trajectory[i].x != trajectory[i -1].x
  196. && trajectory[i].y != trajectory[i - 1].y)
  197. {
  198. LOG_W("points are not not in line");
  199. return TASK_TRAJECTORY_EXY;
  200. }
  201. }
  202. else
  203. {
  204. LOG_W("points are not in same floor");
  205. return TASK_TRAJECTORY_EZ;
  206. }
  207. }
  208. /* 是否当前层 */
  209. if(trajectory[0].z != S.cValue)
  210. {
  211. LOG_W("points are not in current floor");
  212. return TASK_TRAJECTORY_EPASS;
  213. }
  214. /* 路径重复判断 */
  215. for(i = 0; i < TASK_MAX_TRAJECTORY; i++)
  216. {
  217. if(id == task_trajectory_list[i].id)
  218. {
  219. LOG_W("trajectory repeat");
  220. return TASK_TRAJECTORY_EREPEAT;
  221. }
  222. }
  223. for(i = 0; i < TASK_MAX_TRAJECTORY; i++)
  224. {
  225. if(task_trajectory_list[i].cnt == cnt)
  226. {
  227. if(memcmp(trajectory, task_trajectory_list[i].point, cnt * sizeof(point_t)))
  228. {
  229. LOG_W("trajectory repeat");
  230. return TASK_TRAJECTORY_EREPEAT;
  231. }
  232. }
  233. }
  234. /* 插入路径,无动作:运动作为一个命令,有动作:运动作为一个命令,动作作为一个命令 */
  235. for(i = 0; i < cnt; i++)
  236. {
  237. task_trajectory_list[push_idx].point[point_idx] = trajectory[i];
  238. if(trajectory[i].action)
  239. {
  240. task_trajectory_list[push_idx].point[point_idx].action = 0;
  241. point_idx++;
  242. task_trajectory_list[push_idx].point[point_idx] = trajectory[i];
  243. }
  244. point_idx++;
  245. if(point_idx > TASK_MAX_POINT)
  246. {
  247. task_trajectory_list[push_idx].id = 0;
  248. task_trajectory_list[push_idx].cnt = 0;
  249. LOG_W("points overflow");
  250. return TASK_TRAJECTORY_EOVERFLOW;
  251. }
  252. }
  253. task_trajectory_list[push_idx].id = id;
  254. task_trajectory_list[push_idx].cnt = point_idx;
  255. LOG_I("add trajectory id[%u], points[%u->%u], target[%u, %u, %u]",
  256. id, cnt, point_idx,
  257. task_trajectory_list[push_idx].point[point_idx - 1].x,
  258. task_trajectory_list[push_idx].point[point_idx - 1].y,
  259. task_trajectory_list[push_idx].point[point_idx - 1].z);
  260. return TASK_TRAJECTORY_EOK;
  261. }
  262. /**
  263. * @funtion task_set
  264. * @brief 设置任务
  265. * @Author Simon
  266. * @DateTime 2021.06.22-T17:59:45+0800
  267. *
  268. * @param id 任务序号
  269. * @param target_id 执行节点
  270. * @return
  271. * TASK_SET_EOK = 0,
  272. * TASK_SET_EDIFF = 0x48, 接收到的任务序号与RES内部缓存的任务不匹配
  273. * TASK_SET_EEXIST = 0x49, 接收到的任务还没有执行,又接收到新的任务
  274. * TASK_SET_EBUSY = 0x6a, 小车当前已有任务在执行
  275. * TASK_SET_ESEG = 0x71, 接收到的目的段序号小于上次的目的段序号或大于总的目的段序号)
  276. * TASK_SET_EFINISH = 0x70, 当前任务已完成
  277. * TASK_SET_EEMPTY = 0x72, 当前小车没有任务
  278. */
  279. int task_set(uint8_t id, uint8_t target_id)
  280. {
  281. int cur_traj;
  282. if(id != task_trajectory_list[0].id && id != task_trajectory_list[1].id)
  283. {
  284. return TASK_SET_EDIFF;
  285. }
  286. cur_traj = task_current_trajectory();
  287. if(cur_traj < 0)
  288. {
  289. return TASK_SET_EEMPTY;
  290. }
  291. if(id != task_trajectory_list[cur_traj].id)
  292. {
  293. return TASK_SET_EDIFF;
  294. }
  295. if(task_sch.status == TASK_STATUS_INIT)
  296. {
  297. return TASK_SET_EEXIST;
  298. }
  299. if(task_sch.status == TASK_STATUS_EXE || task_sch.status == TASK_STATUS_PAUSE)
  300. {
  301. return TASK_SET_EBUSY;
  302. }
  303. // if(id == task_sch.id && task_sch.status == TASK_STATUS_DONE && target_id == task_sch.target_point_idx)
  304. // {
  305. // return TASK_SET_EFINISH;
  306. // }
  307. /* 接收到的目的段序号小于上次的目的段序号或大于总的目的段序号 */
  308. if(id == task_sch.id)
  309. {
  310. if(target_id < task_sch.target_point_idx)
  311. {
  312. return TASK_SET_ESEG;
  313. }
  314. }
  315. if(target_id > task_trajectory_list[cur_traj].cnt)
  316. {
  317. return TASK_SET_ESEG;
  318. }
  319. task_sch.target_point_idx = target_id;
  320. task_sch.cur_point_idx = 1;
  321. task_sch.id = id;
  322. task_sch.status = TASK_STATUS_INIT;
  323. return TASK_SET_EOK;
  324. }
  325. /**
  326. * @funtion task_get
  327. * @brief 获取目标
  328. * @Author Simon
  329. * @DateTime 2021.06.22-T18:01:34+0800
  330. *
  331. * @param cur_point 当前坐标
  332. * @param trajectory 输出路径
  333. * @return 路径坐标点数,0-无任务
  334. */
  335. int task_get(point_t cur_point, point_t *trajectory)
  336. {
  337. uint8_t i;
  338. uint8_t idx;
  339. if(task_sch.status == TASK_STATUS_NONE
  340. || task_sch.status == TASK_STATUS_DONE)
  341. {
  342. return 0;
  343. }
  344. for(idx = 0; idx < TASK_MAX_TRAJECTORY; idx++)
  345. {
  346. if(task_trajectory_list[idx].id == task_sch.id)
  347. {
  348. break;
  349. }
  350. }
  351. if(idx >= TASK_MAX_TRAJECTORY)
  352. {
  353. task_sch.status = TASK_STATUS_NONE;
  354. return 0;
  355. }
  356. for(i = 0; i < task_sch.target_point_idx; i++)
  357. {
  358. if(cur_point.x == task_trajectory_list[idx].point[i].x
  359. && cur_point.y == task_trajectory_list[idx].point[i].y)
  360. {
  361. break;
  362. }
  363. }
  364. if(i >= task_sch.target_point_idx)
  365. {
  366. return 0;
  367. }
  368. memcpy(trajectory,
  369. &task_trajectory_list[idx].point[i],
  370. (task_sch.target_point_idx - i) * sizeof(point_t));
  371. return task_sch.target_point_idx - i;
  372. }
  373. /**
  374. * @funtion task_set_status
  375. * @brief 设置任务状态
  376. * @Author Simon
  377. * @DateTime 2021.06.22-T18:02:59+0800
  378. *
  379. * @param status 0:执行中,1:完成,2:暂停
  380. * @param cur_point 当前坐标点
  381. */
  382. void task_set_status(uint8_t status, point_t cur_point)
  383. {
  384. int cur_traj;
  385. uint8_t i;
  386. cur_traj = task_current_trajectory();
  387. if(cur_traj < 0)
  388. {
  389. return;
  390. }
  391. if(task_trajectory_list[cur_traj].id != task_sch.id)
  392. {
  393. return;
  394. }
  395. switch(status)
  396. {
  397. case 0:
  398. task_sch.status = TASK_STATUS_EXE;
  399. break;
  400. case 1:
  401. task_sch.status = TASK_STATUS_DONE;
  402. break;
  403. case 2:
  404. task_sch.status = TASK_STATUS_PAUSE;
  405. break;
  406. default:
  407. break;
  408. }
  409. if(task_sch.status == TASK_STATUS_DONE
  410. && task_trajectory_list[cur_traj].point[task_trajectory_list[cur_traj].cnt - 1].x == cur_point.x
  411. && task_trajectory_list[cur_traj].point[task_trajectory_list[cur_traj].cnt - 1].y == cur_point.y)
  412. {
  413. task_trajectory_list[cur_traj].cnt = 0;
  414. task_trajectory_list[cur_traj].id = 0;
  415. }
  416. else
  417. {
  418. for(i = 0; i < task_trajectory_list[cur_traj].cnt; i++)
  419. {
  420. if(task_trajectory_list[cur_traj].point[i].x == cur_point.x
  421. && task_trajectory_list[cur_traj].point[i].y == cur_point.y)
  422. {
  423. task_sch.cur_point_idx = i + 1;
  424. break;
  425. }
  426. }
  427. if(task_sch.cur_point_idx >= task_trajectory_list[cur_traj].cnt)
  428. {
  429. task_trajectory_list[cur_traj].cnt = 0;
  430. task_trajectory_list[cur_traj].id = 0;
  431. }
  432. }
  433. }
  434. /**
  435. * @funtion task_get_status
  436. * @brief 获取任务状态
  437. * @Author Simon
  438. * @DateTime 2021.06.22-T18:03:41+0800
  439. *
  440. * @return
  441. * TASK_STATUS_NONE, 无任务
  442. * TASK_STATUS_INIT, 任务待命
  443. * TASK_STATUS_EXE, 任务执行中
  444. * TASK_STATUS_PAUSE, 任务暂停
  445. * TASK_STATUS_DONE, 任务完成
  446. */
  447. uint8_t task_get_status(void)
  448. {
  449. return task_sch.status;
  450. }
  451. /**
  452. * @funtion task_get_seg
  453. * @brief 获取当前节点号
  454. * @Author Simon
  455. * @DateTime 2021.06.22-T18:04:44+0800
  456. *
  457. * @return 当前节点号
  458. */
  459. uint8_t task_get_seg(void)
  460. {
  461. if(!task_sch.id)
  462. {
  463. return 0;
  464. }
  465. return task_sch.cur_point_idx;
  466. }
  467. /**
  468. * @funtion task_get_target
  469. * @brief 获取任务终点坐标
  470. * @Author Simon
  471. * @DateTime 2021.06.22-T18:05:15+0800
  472. *
  473. * @return 终点坐标
  474. */
  475. uint32_t task_get_target(void)
  476. {
  477. int idx = task_current_trajectory();
  478. if(idx < 0)
  479. return 0;
  480. return *(uint32_t *)&task_trajectory_list[idx].point[task_trajectory_list[idx].cnt - 1];
  481. }
  482. /**
  483. * @funtion task_cancel
  484. * @brief 撤消任务
  485. * @Author Simon
  486. * @DateTime 2021.06.22-T18:05:53+0800
  487. *
  488. * @param force 1强制撤消, 0非强制
  489. * @return 0-成功,-1-失败
  490. */
  491. int task_cancel(int force)
  492. {
  493. if(task_sch.status != TASK_STATUS_EXE)
  494. {
  495. if(task_sch.status != TASK_STATUS_PAUSE || force)
  496. {
  497. task_sch.id = 0;
  498. task_sch.status = TASK_STATUS_NONE;
  499. task_trajectory_list[0].id = 0;
  500. task_trajectory_list[0].cnt = 0;
  501. task_trajectory_list[1].id = 0;
  502. task_trajectory_list[1].cnt = 0;
  503. return 0;
  504. }
  505. }
  506. return -1;
  507. }
  508. int task_init(void)
  509. {
  510. task_sch.status = TASK_STATUS_NONE;
  511. return 0;
  512. }
  513. INIT_APP_EXPORT(task_init);