workflow.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. // workflow.cpp
  2. #include "wheelchair_state_machine/workflow.hpp"
  3. #include <rclcpp/logging.hpp>
  4. #include <chrono>
  5. using namespace std::chrono_literals;
  6. using std::placeholders::_1;
  7. WorkflowManager::WorkflowManager(rclcpp::Node* node)
  8. : node_(node)
  9. , current_state_(WheelchairState::READY)
  10. {
  11. // 初始化状态转移表
  12. initializeTransitionTable();
  13. // 创建状态发布者
  14. state_publisher_ = node_->create_publisher<std_msgs::msg::String>(
  15. "wheelchair/state", 10);
  16. RCLCPP_INFO(node_->get_logger(), "工作流管理器已初始化");
  17. }
  18. void WorkflowManager::initializeTransitionTable()
  19. {
  20. transition_table_.clear();
  21. // 1. ipad&phone界面启动: 就绪中✅, 其他❌
  22. std::map<WheelchairState, bool> ipad_start_perms = {
  23. {WheelchairState::READY, true},
  24. {WheelchairState::WALKING, false},
  25. {WheelchairState::SEARCHING, false},
  26. {WheelchairState::CHARGING, false}};
  27. transition_table_["ipad_phone_interface_start"] = ipad_start_perms;
  28. // 2. iPad&phone界面取消: 所有状态✅
  29. std::map<WheelchairState, bool> ipad_cancel_perms = {
  30. {WheelchairState::READY, true},
  31. {WheelchairState::WALKING, true},
  32. {WheelchairState::SEARCHING, true},
  33. {WheelchairState::CHARGING, true}};
  34. transition_table_["ipad_phone_interface_cancel"] = ipad_cancel_perms;
  35. // 3. 蓝牙断开: 就绪中❌, 其他✅
  36. std::map<WheelchairState, bool> bluetooth_disconnect_perms = {
  37. {WheelchairState::READY, false},
  38. {WheelchairState::WALKING, true},
  39. {WheelchairState::SEARCHING, true},
  40. {WheelchairState::CHARGING, true}};
  41. transition_table_["bluetooth_disconnected"] = bluetooth_disconnect_perms;
  42. // 4. 蓝牙已连接: 就绪中✅, 其他❌
  43. std::map<WheelchairState, bool> bluetooth_connect_perms = {
  44. {WheelchairState::READY, true},
  45. {WheelchairState::WALKING, false},
  46. {WheelchairState::SEARCHING, false},
  47. {WheelchairState::CHARGING, false}};
  48. transition_table_["bluetooth_connected"] = bluetooth_connect_perms;
  49. // 5. 基站断电: 就绪中❌, 其他✅
  50. std::map<WheelchairState, bool> base_power_off_perms = {
  51. {WheelchairState::READY, false},
  52. {WheelchairState::WALKING, true},
  53. {WheelchairState::SEARCHING, true},
  54. {WheelchairState::CHARGING, true}};
  55. transition_table_["base_station_power_off"] = base_power_off_perms;
  56. // 6. 低电量警告: 就绪中✅, 其他❌
  57. std::map<WheelchairState, bool> low_battery_perms = {
  58. {WheelchairState::READY, true},
  59. {WheelchairState::WALKING, false},
  60. {WheelchairState::SEARCHING, false},
  61. {WheelchairState::CHARGING, false}};
  62. transition_table_["low_battery_warning"] = low_battery_perms;
  63. // 7. 锁车: 就绪中✅, 其他❌
  64. std::map<WheelchairState, bool> lock_vehicle_perms = {
  65. {WheelchairState::READY, true},
  66. {WheelchairState::WALKING, false},
  67. {WheelchairState::SEARCHING, false},
  68. {WheelchairState::CHARGING, false}};
  69. transition_table_["lock_vehicle"] = lock_vehicle_perms;
  70. // 8. 解锁: 行走中✅, 其他❌
  71. std::map<WheelchairState, bool> unlock_vehicle_perms = {
  72. {WheelchairState::READY, false},
  73. {WheelchairState::WALKING, true},
  74. {WheelchairState::SEARCHING, false},
  75. {WheelchairState::CHARGING, false}};
  76. transition_table_["unlock_vehicle"] = unlock_vehicle_perms;
  77. // 9. 摇杆后拉: 搜索中✅, 其他❌
  78. std::map<WheelchairState, bool> joystick_pull_perms = {
  79. {WheelchairState::READY, false},
  80. {WheelchairState::WALKING, false},
  81. {WheelchairState::SEARCHING, true},
  82. {WheelchairState::CHARGING, false}};
  83. transition_table_["joystick_pull_back"] = joystick_pull_perms;
  84. // 10. 摇杆停止: 行走中✅, 搜索中✅, 其他❌
  85. std::map<WheelchairState, bool> joystick_stop_perms = {
  86. {WheelchairState::READY, false},
  87. {WheelchairState::WALKING, true},
  88. {WheelchairState::SEARCHING, true},
  89. {WheelchairState::CHARGING, false}};
  90. transition_table_["joystick_stop"] = joystick_stop_perms;
  91. // 11. 推行启动: 充电中✅, 其他❌
  92. std::map<WheelchairState, bool> push_start_perms = {
  93. {WheelchairState::READY, false},
  94. {WheelchairState::WALKING, false},
  95. {WheelchairState::SEARCHING, false},
  96. {WheelchairState::CHARGING, true}};
  97. transition_table_["push_start"] = push_start_perms;
  98. // 12. 推行关闭: 行走中✅, 搜索中✅, 其他❌
  99. std::map<WheelchairState, bool> push_stop_perms = {
  100. {WheelchairState::READY, false},
  101. {WheelchairState::WALKING, true},
  102. {WheelchairState::SEARCHING, true},
  103. {WheelchairState::CHARGING, false}};
  104. transition_table_["push_stop"] = push_stop_perms;
  105. // 13. 电池-开始充电: 搜索中✅, 充电中✅, 其他❌
  106. std::map<WheelchairState, bool> battery_start_charging_perms = {
  107. {WheelchairState::READY, false},
  108. {WheelchairState::WALKING, false},
  109. {WheelchairState::SEARCHING, true},
  110. {WheelchairState::CHARGING, true}};
  111. transition_table_["battery_start_charging"] = battery_start_charging_perms;
  112. // 14. 电池-断开充电: 充电中✅, 其他❌
  113. std::map<WheelchairState, bool> battery_stop_charging_perms = {
  114. {WheelchairState::READY, false},
  115. {WheelchairState::WALKING, false},
  116. {WheelchairState::SEARCHING, false},
  117. {WheelchairState::CHARGING, true}};
  118. transition_table_["battery_stop_charging"] = battery_stop_charging_perms;
  119. // 15. 电池-电量满: 充电中✅, 其他❌
  120. std::map<WheelchairState, bool> battery_full_perms = {
  121. {WheelchairState::READY, false},
  122. {WheelchairState::WALKING, false},
  123. {WheelchairState::SEARCHING, false},
  124. {WheelchairState::CHARGING, true}};
  125. transition_table_["battery_full"] = battery_full_perms;
  126. // 16. 错误码处理: 所有状态✅
  127. std::map<WheelchairState, bool> error_code_perms = {
  128. {WheelchairState::READY, true},
  129. {WheelchairState::WALKING, true},
  130. {WheelchairState::SEARCHING, true},
  131. {WheelchairState::CHARGING, true}};
  132. transition_table_["error_code_handling"] = error_code_perms;
  133. // 17. 基站检测丢失: 行走中✅, 其他❌
  134. std::map<WheelchairState, bool> base_station_lost_perms = {
  135. {WheelchairState::READY, false},
  136. {WheelchairState::WALKING, true},
  137. {WheelchairState::SEARCHING, false},
  138. {WheelchairState::CHARGING, false}};
  139. transition_table_["base_station_lost"] = base_station_lost_perms;
  140. // 18. 搜索30s超时: 搜索中✅, 其他❌
  141. std::map<WheelchairState, bool> search_timeout_perms = {
  142. {WheelchairState::READY, false},
  143. {WheelchairState::WALKING, false},
  144. {WheelchairState::SEARCHING, true},
  145. {WheelchairState::CHARGING, false}};
  146. transition_table_["search_30s_timeout"] = search_timeout_perms;
  147. RCLCPP_INFO(node_->get_logger(), "状态转移表已初始化完成");
  148. }
  149. bool WorkflowManager::handleEvent(const std::string &event)
  150. {
  151. if (!checkEventPermission(event))
  152. {
  153. RCLCPP_WARN(node_->get_logger(),
  154. "事件 '%s' 在当前状态 '%s' 下不允许执行",
  155. event.c_str(),
  156. getCurrentState().c_str());
  157. return false;
  158. }
  159. executeEvent(event);
  160. return true;
  161. }
  162. bool WorkflowManager::checkEventPermission(const std::string &event)
  163. {
  164. if (transition_table_.find(event) == transition_table_.end())
  165. {
  166. RCLCPP_WARN(node_->get_logger(), "未知事件: %s", event.c_str());
  167. return false;
  168. }
  169. std::map<WheelchairState, bool> state_permissions = transition_table_[event];
  170. if (state_permissions.find(current_state_) != state_permissions.end())
  171. {
  172. return state_permissions[current_state_];
  173. }
  174. return false;
  175. }
  176. void WorkflowManager::executeEvent(const std::string &event)
  177. {
  178. RCLCPP_INFO(node_->get_logger(), "执行事件: %s", event.c_str());
  179. // 根据事件类型执行相应处理
  180. if (event == "ipad_phone_interface_start")
  181. {
  182. processIpadStartEvent();
  183. }
  184. else if (event == "ipad_phone_interface_cancel")
  185. {
  186. processIpadCancelEvent();
  187. }
  188. else if (event == "bluetooth_disconnected")
  189. {
  190. processBluetoothDisconnected();
  191. }
  192. else if (event == "bluetooth_connected")
  193. {
  194. processBluetoothConnected();
  195. }
  196. else if (event == "base_station_power_off")
  197. {
  198. processBaseStationPowerOff();
  199. }
  200. else if (event == "low_battery_warning")
  201. {
  202. // 由外部回调处理
  203. }
  204. else if (event == "lock_vehicle")
  205. {
  206. processLockVehicle();
  207. }
  208. else if (event == "unlock_vehicle")
  209. {
  210. processUnlockVehicle();
  211. }
  212. else if (event == "joystick_pull_back")
  213. {
  214. processJoystickPullBack();
  215. }
  216. else if (event == "joystick_stop")
  217. {
  218. processJoystickStop();
  219. }
  220. else if (event == "push_start")
  221. {
  222. processPushStart();
  223. }
  224. else if (event == "push_stop")
  225. {
  226. processPushStop();
  227. }
  228. else if (event == "battery_start_charging")
  229. {
  230. // 由外部回调处理
  231. }
  232. else if (event == "battery_stop_charging")
  233. {
  234. // 由外部回调处理
  235. }
  236. else if (event == "battery_full")
  237. {
  238. // 由外部回调处理
  239. }
  240. else if (event == "error_code_handling")
  241. {
  242. processErrorCode();
  243. }
  244. else if (event == "base_station_lost")
  245. {
  246. // 由外部回调处理
  247. }
  248. else if (event == "search_30s_timeout")
  249. {
  250. // 由外部回调处理
  251. }
  252. // 根据事件触发状态转移
  253. processStateTransition(event);
  254. // 发布状态更新
  255. publishState(event, "事件已处理");
  256. }
  257. void WorkflowManager::processStateTransition(const std::string &event)
  258. {
  259. // 根据事件检查是否需要状态转移
  260. switch (current_state_)
  261. {
  262. case WheelchairState::READY:
  263. if (event == "low_battery_warning" || event == "ipad_phone_interface_start")
  264. {
  265. transitionToSearching();
  266. }
  267. else if (event == "unlock_vehicle")
  268. {
  269. transitionToWalking();
  270. }
  271. break;
  272. case WheelchairState::WALKING:
  273. if (event == "joystick_stop" || event == "push_stop" || event == "lock_vehicle")
  274. {
  275. transitionToReady();
  276. }
  277. else if (event == "base_station_lost")
  278. {
  279. transitionToSearching();
  280. }
  281. else if (event == "battery_start_charging")
  282. {
  283. transitionToCharging();
  284. }
  285. break;
  286. case WheelchairState::SEARCHING:
  287. if (event == "search_30s_timeout" || event == "base_station_lost")
  288. {
  289. transitionToReady();
  290. }
  291. else if (event == "battery_start_charging")
  292. {
  293. transitionToCharging();
  294. }
  295. else if (event == "joystick_pull_back")
  296. {
  297. transitionToWalking();
  298. }
  299. break;
  300. case WheelchairState::CHARGING:
  301. if (event == "battery_full" ||
  302. event == "battery_stop_charging" ||
  303. event == "base_station_power_off")
  304. {
  305. transitionToReady();
  306. }
  307. else if (event == "push_start")
  308. {
  309. transitionToWalking();
  310. }
  311. break;
  312. }
  313. }
  314. void WorkflowManager::transitionToWalking()
  315. {
  316. if (current_state_ == WheelchairState::READY ||
  317. current_state_ == WheelchairState::SEARCHING ||
  318. current_state_ == WheelchairState::CHARGING)
  319. {
  320. setState(WheelchairState::WALKING);
  321. RCLCPP_INFO(node_->get_logger(), "轮椅开始行走");
  322. publishState("WHEELCHAIR_WALKING");
  323. }
  324. }
  325. void WorkflowManager::transitionToSearching()
  326. {
  327. if (current_state_ == WheelchairState::READY ||
  328. current_state_ == WheelchairState::WALKING)
  329. {
  330. setState(WheelchairState::SEARCHING);
  331. RCLCPP_INFO(node_->get_logger(), "开始搜索充电站");
  332. publishState("SEARCH_CHARGING_STATION_START");
  333. startSearchTimeoutTimer();
  334. }
  335. }
  336. void WorkflowManager::transitionToCharging()
  337. {
  338. if (current_state_ == WheelchairState::SEARCHING ||
  339. current_state_ == WheelchairState::WALKING)
  340. {
  341. setState(WheelchairState::CHARGING);
  342. RCLCPP_INFO(node_->get_logger(), "开始充电");
  343. stopSearchTimeoutTimer();
  344. publishState("CHARGING_START");
  345. }
  346. }
  347. void WorkflowManager::transitionToReady()
  348. {
  349. std::string previous_state = getCurrentState();
  350. setState(WheelchairState::READY);
  351. stopSearchTimeoutTimer();
  352. RCLCPP_INFO(node_->get_logger(), "返回到就绪状态 (前状态: %s)",
  353. previous_state.c_str());
  354. publishState("WHEELCHAIR_READY");
  355. }
  356. // ==================== 事件处理函数实现 ====================
  357. void WorkflowManager::processIpadStartEvent()
  358. {
  359. RCLCPP_INFO(node_->get_logger(), "处理iPad启动事件");
  360. // 发布状态更新
  361. publishState("IPAD_RECHARGE_STARTED", "iPad启动自主回充");
  362. // 如果当前是就绪状态,自动转移到搜索状态
  363. if (current_state_ == WheelchairState::READY)
  364. {
  365. transitionToSearching();
  366. }
  367. else
  368. {
  369. RCLCPP_WARN(node_->get_logger(),
  370. "当前状态 %s 无法启动回充", getCurrentState().c_str());
  371. }
  372. }
  373. void WorkflowManager::processIpadCancelEvent()
  374. {
  375. RCLCPP_INFO(node_->get_logger(), "处理iPad取消事件");
  376. // 发布状态更新
  377. publishState("IPAD_RECHARGE_CANCELLED", "iPad取消自主回充");
  378. // 根据当前状态决定是否取消回充
  379. if (current_state_ == WheelchairState::SEARCHING ||
  380. current_state_ == WheelchairState::CHARGING)
  381. {
  382. transitionToReady();
  383. RCLCPP_INFO(node_->get_logger(), "iPad自主回充已取消,返回到就绪状态");
  384. }
  385. }
  386. void WorkflowManager::processBluetoothDisconnected()
  387. {
  388. RCLCPP_INFO(node_->get_logger(), "处理蓝牙断开事件");
  389. // 发布状态更新
  390. publishState("BLUETOOTH_DISCONNECTED", "蓝牙连接已断开");
  391. // 根据状态处理蓝牙断开
  392. if (current_state_ == WheelchairState::WALKING ||
  393. current_state_ == WheelchairState::SEARCHING ||
  394. current_state_ == WheelchairState::CHARGING)
  395. {
  396. RCLCPP_WARN(node_->get_logger(), "蓝牙断开,返回到就绪状态");
  397. transitionToReady();
  398. }
  399. }
  400. void WorkflowManager::processBluetoothConnected()
  401. {
  402. RCLCPP_INFO(node_->get_logger(), "处理蓝牙连接成功事件");
  403. // 发布状态更新
  404. publishState("BLUETOOTH_CONNECTED", "蓝牙连接成功");
  405. // 蓝牙连接成功通常不需要改变当前状态
  406. // 但可以根据业务需求添加逻辑
  407. }
  408. void WorkflowManager::processBaseStationPowerOff()
  409. {
  410. RCLCPP_INFO(node_->get_logger(), "处理基站断电事件");
  411. // 发布状态更新
  412. publishState("BASE_STATION_POWER_OFF", "充电基站断电");
  413. // 根据状态处理基站断电
  414. if (current_state_ == WheelchairState::SEARCHING)
  415. {
  416. RCLCPP_WARN(node_->get_logger(), "基站断电,停止搜索");
  417. transitionToReady();
  418. }
  419. else if (current_state_ == WheelchairState::CHARGING)
  420. {
  421. RCLCPP_ERROR(node_->get_logger(), "充电中基站断电!");
  422. transitionToReady();
  423. }
  424. }
  425. void WorkflowManager::handleLowBatteryEvent(BatteryState state, float percentage)
  426. {
  427. RCLCPP_INFO(node_->get_logger(), "处理低电量事件: %.1f%%", percentage);
  428. // 发布相应的事件名称
  429. if (state == BatteryState::CRITICAL)
  430. {
  431. triggerEvent("low_battery_warning");
  432. }
  433. else if (state == BatteryState::LOW)
  434. {
  435. triggerEvent("low_battery_warning");
  436. }
  437. // 根据电池状态采取行动
  438. if (state == BatteryState::CRITICAL)
  439. {
  440. RCLCPP_ERROR(node_->get_logger(), "严重低电量! 自动启动回充搜索");
  441. publishState("CRITICAL_BATTERY_EMERGENCY", "自动启动回充");
  442. // 紧急情况下,无论当前状态如何都尝试启动回充
  443. if (current_state_ == WheelchairState::READY)
  444. {
  445. transitionToSearching();
  446. }
  447. else if (current_state_ == WheelchairState::WALKING)
  448. {
  449. // 如果是行走状态,先停止行走再搜索
  450. RCLCPP_WARN(node_->get_logger(), "严重低电量,停止行走并启动回充搜索");
  451. transitionToReady();
  452. // 短暂延迟后启动搜索
  453. // 注意:在实际应用中可能需要异步处理
  454. transitionToSearching();
  455. }
  456. }
  457. else if (state == BatteryState::LOW)
  458. {
  459. RCLCPP_WARN(node_->get_logger(), "低电量警告,建议启动回充");
  460. publishState("LOW_BATTERY_WARNING", "建议启动回充");
  461. // 如果当前是就绪状态,自动启动回充
  462. if (current_state_ == WheelchairState::READY)
  463. {
  464. RCLCPP_INFO(node_->get_logger(), "自动启动回充搜索");
  465. transitionToSearching();
  466. }
  467. }
  468. }
  469. void WorkflowManager::processLockVehicle()
  470. {
  471. RCLCPP_INFO(node_->get_logger(), "处理锁车操作");
  472. // 发布状态更新
  473. publishState("VEHICLE_LOCKED", "轮椅已锁定");
  474. // 根据状态处理锁车
  475. if (current_state_ == WheelchairState::WALKING)
  476. {
  477. RCLCPP_WARN(node_->get_logger(), "行走中锁车,停止运动");
  478. transitionToReady();
  479. }
  480. else if (current_state_ == WheelchairState::SEARCHING)
  481. {
  482. RCLCPP_WARN(node_->get_logger(), "搜索中锁车,取消搜索");
  483. transitionToReady();
  484. }
  485. else if (current_state_ == WheelchairState::CHARGING)
  486. {
  487. RCLCPP_WARN(node_->get_logger(), "充电中锁车,保持充电状态");
  488. // 充电中可以锁车,保持当前状态
  489. }
  490. }
  491. void WorkflowManager::processUnlockVehicle()
  492. {
  493. RCLCPP_INFO(node_->get_logger(), "处理解锁操作");
  494. // 发布状态更新
  495. publishState("VEHICLE_UNLOCKED", "轮椅已解锁");
  496. // 根据状态处理解锁
  497. if (current_state_ == WheelchairState::READY)
  498. {
  499. RCLCPP_INFO(node_->get_logger(), "解锁后准备行走");
  500. transitionToWalking();
  501. }
  502. }
  503. void WorkflowManager::processJoystickPullBack()
  504. {
  505. RCLCPP_INFO(node_->get_logger(), "处理摇杆后拉操作");
  506. // 发布状态更新
  507. publishState("JOYSTICK_PULL_BACK", "摇杆后拉");
  508. // 根据状态处理摇杆后拉
  509. if (current_state_ == WheelchairState::SEARCHING)
  510. {
  511. RCLCPP_INFO(node_->get_logger(), "搜索中摇杆后拉,切换为行走模式");
  512. transitionToWalking();
  513. }
  514. }
  515. void WorkflowManager::processJoystickStop()
  516. {
  517. RCLCPP_INFO(node_->get_logger(), "处理摇杆停止操作");
  518. // 发布状态更新
  519. publishState("JOYSTICK_STOP", "摇杆停止");
  520. // 根据状态处理摇杆停止
  521. if (current_state_ == WheelchairState::WALKING)
  522. {
  523. RCLCPP_INFO(node_->get_logger(), "行走中摇杆停止,返回就绪状态");
  524. transitionToReady();
  525. }
  526. else if (current_state_ == WheelchairState::SEARCHING)
  527. {
  528. RCLCPP_INFO(node_->get_logger(), "搜索中摇杆停止,返回就绪状态");
  529. transitionToReady();
  530. }
  531. }
  532. void WorkflowManager::processPushStart()
  533. {
  534. RCLCPP_INFO(node_->get_logger(), "处理推行启动");
  535. // 发布状态更新
  536. publishState("PUSH_START", "推行模式启动");
  537. // 根据状态处理推行启动
  538. if (current_state_ == WheelchairState::CHARGING)
  539. {
  540. RCLCPP_INFO(node_->get_logger(), "充电中启动推行,切换到行走模式");
  541. transitionToWalking();
  542. }
  543. }
  544. void WorkflowManager::processPushStop()
  545. {
  546. RCLCPP_INFO(node_->get_logger(), "处理推行停止");
  547. // 发布状态更新
  548. publishState("PUSH_STOP", "推行模式停止");
  549. // 根据状态处理推行停止
  550. if (current_state_ == WheelchairState::WALKING)
  551. {
  552. RCLCPP_INFO(node_->get_logger(), "推行中停止,返回就绪状态");
  553. transitionToReady();
  554. }
  555. else if (current_state_ == WheelchairState::SEARCHING)
  556. {
  557. RCLCPP_INFO(node_->get_logger(), "搜索中停止推行,返回就绪状态");
  558. transitionToReady();
  559. }
  560. }
  561. void WorkflowManager::handleChargingStartEvent()
  562. {
  563. RCLCPP_INFO(node_->get_logger(), "处理充电开始事件");
  564. // 触发相应事件
  565. triggerEvent("battery_start_charging");
  566. // 发布状态更新
  567. publishState("BATTERY_START_CHARGING", "开始充电");
  568. // 如果当前在搜索状态,转移到充电状态
  569. if (current_state_ == WheelchairState::SEARCHING)
  570. {
  571. transitionToCharging();
  572. }
  573. else if (current_state_ == WheelchairState::WALKING)
  574. {
  575. RCLCPP_WARN(node_->get_logger(), "行走中开始充电,切换到充电状态");
  576. transitionToCharging();
  577. }
  578. }
  579. void WorkflowManager::handleChargingStopEvent()
  580. {
  581. RCLCPP_INFO(node_->get_logger(), "处理充电停止事件");
  582. // 触发相应事件
  583. triggerEvent("battery_stop_charging");
  584. // 发布状态更新
  585. publishState("BATTERY_STOP_CHARGING", "停止充电");
  586. // 如果当前在充电状态,返回就绪状态
  587. if (current_state_ == WheelchairState::CHARGING)
  588. {
  589. RCLCPP_WARN(node_->get_logger(), "充电停止,返回就绪状态");
  590. transitionToReady();
  591. }
  592. }
  593. void WorkflowManager::handleChargingFullEvent()
  594. {
  595. RCLCPP_INFO(node_->get_logger(), "处理电池充满事件");
  596. // 触发相应事件
  597. triggerEvent("battery_full");
  598. // 发布状态更新
  599. publishState("BATTERY_FULL", "电池已充满");
  600. // 停止充电,返回就绪状态
  601. if (current_state_ == WheelchairState::CHARGING)
  602. {
  603. transitionToReady();
  604. }
  605. }
  606. void WorkflowManager::processErrorCode()
  607. {
  608. RCLCPP_INFO(node_->get_logger(), "处理错误码");
  609. // 发布状态更新
  610. publishState("ERROR_CODE_HANDLING", "处理系统错误码");
  611. // 根据错误码的严重程度处理
  612. // 严重错误可能需要紧急停止并返回就绪状态
  613. bool critical_error = true; // 示例:假设是严重错误
  614. if (critical_error)
  615. {
  616. RCLCPP_ERROR(node_->get_logger(), "检测到严重错误,紧急停止所有操作");
  617. transitionToReady();
  618. }
  619. }
  620. void WorkflowManager::handleBaseStationLostEvent()
  621. {
  622. RCLCPP_INFO(node_->get_logger(), "处理基站丢失事件");
  623. // 触发相应事件
  624. triggerEvent("base_station_lost");
  625. // 发布状态更新
  626. publishState("CHARGING_STATION_LOST", "充电基站丢失");
  627. // 根据状态处理基站丢失
  628. if (current_state_ == WheelchairState::WALKING)
  629. {
  630. // 行走中检测到基站丢失,进入搜索状态
  631. transitionToSearching();
  632. }
  633. else if (current_state_ == WheelchairState::SEARCHING)
  634. {
  635. // 搜索中检测到基站丢失,返回就绪状态
  636. transitionToReady();
  637. }
  638. else if (current_state_ == WheelchairState::CHARGING)
  639. {
  640. RCLCPP_ERROR(node_->get_logger(), "充电中基站丢失,停止充电");
  641. transitionToReady();
  642. }
  643. }
  644. void WorkflowManager::handleSearchTimeoutEvent()
  645. {
  646. RCLCPP_INFO(node_->get_logger(), "处理搜索超时事件");
  647. // 触发相应事件
  648. triggerEvent("search_30s_timeout");
  649. // 发布超时通知
  650. publishState("SEARCH_CHARGING_STATION_TIMEOUT", "搜索充电站超时");
  651. // 根据状态转移表,搜索超时应返回就绪状态
  652. if (current_state_ == WheelchairState::SEARCHING)
  653. {
  654. transitionToReady();
  655. }
  656. }
  657. // ==================== 定时器管理 ====================
  658. void WorkflowManager::startSearchTimeoutTimer()
  659. {
  660. // 如果已经有定时器,先取消
  661. if (search_timeout_timer_)
  662. {
  663. search_timeout_timer_->cancel();
  664. }
  665. // 创建30秒定时器
  666. search_timeout_timer_ = node_->create_wall_timer(
  667. std::chrono::seconds(30),
  668. [this]()
  669. {
  670. this->searchTimeoutCallback();
  671. });
  672. RCLCPP_INFO(node_->get_logger(), "搜索超时定时器已启动");
  673. }
  674. void WorkflowManager::stopSearchTimeoutTimer()
  675. {
  676. if (search_timeout_timer_)
  677. {
  678. search_timeout_timer_->cancel();
  679. search_timeout_timer_.reset();
  680. RCLCPP_INFO(node_->get_logger(), "搜索超时定时器已停止");
  681. }
  682. }
  683. void WorkflowManager::searchTimeoutCallback()
  684. {
  685. if (current_state_ == WheelchairState::SEARCHING)
  686. {
  687. RCLCPP_WARN(node_->get_logger(), "搜索充电站超时30秒");
  688. handleSearchTimeoutEvent();
  689. }
  690. }
  691. // ==================== 辅助函数 ====================
  692. std::string WorkflowManager::getCurrentState() const
  693. {
  694. return stateToString(current_state_);
  695. }
  696. void WorkflowManager::setState(WheelchairState new_state)
  697. {
  698. std::string old_state = getCurrentState();
  699. current_state_ = new_state;
  700. RCLCPP_INFO(node_->get_logger(),
  701. "状态转移: %s -> %s",
  702. old_state.c_str(),
  703. getCurrentState().c_str());
  704. // 发布状态到ROS话题
  705. auto msg = std_msgs::msg::String();
  706. msg.data = getCurrentState();
  707. state_publisher_->publish(msg);
  708. // 调用外部回调
  709. if (state_update_callback_)
  710. {
  711. state_update_callback_(getCurrentState(), "状态已更新");
  712. }
  713. }
  714. std::string WorkflowManager::stateToString(WheelchairState state) const
  715. {
  716. switch (state)
  717. {
  718. case WheelchairState::READY:
  719. return "就绪中";
  720. case WheelchairState::WALKING:
  721. return "行走中";
  722. case WheelchairState::SEARCHING:
  723. return "搜索中";
  724. case WheelchairState::CHARGING:
  725. return "充电中";
  726. default:
  727. return "未知状态";
  728. }
  729. }
  730. void WorkflowManager::publishState(const std::string &state_str, const std::string &message)
  731. {
  732. auto msg = std_msgs::msg::String();
  733. if (message.empty())
  734. {
  735. msg.data = state_str;
  736. }
  737. else
  738. {
  739. msg.data = state_str + ":" + message;
  740. }
  741. state_publisher_->publish(msg);
  742. // 调用外部回调
  743. if (state_update_callback_)
  744. {
  745. state_update_callback_(state_str, message);
  746. }
  747. }
  748. void WorkflowManager::setStateUpdateCallback(StateUpdateCallback callback)
  749. {
  750. state_update_callback_ = callback;
  751. RCLCPP_INFO(node_->get_logger(), "已设置状态更新回调");
  752. }
  753. // ==================== 内部事件触发 ====================
  754. void WorkflowManager::triggerEvent(const std::string &event_name)
  755. {
  756. // 检查事件权限
  757. if (!checkEventPermission(event_name))
  758. {
  759. RCLCPP_WARN(node_->get_logger(),
  760. "内部触发事件 '%s' 在当前状态 '%s' 下不允许执行",
  761. event_name.c_str(),
  762. getCurrentState().c_str());
  763. return;
  764. }
  765. // 执行事件
  766. executeEvent(event_name);
  767. }