|
@@ -16,6 +16,8 @@ WorkflowManager::WorkflowManager(rclcpp::Node *node)
|
|
|
// 初始化旋转管理器
|
|
// 初始化旋转管理器
|
|
|
initializeRotationManager();
|
|
initializeRotationManager();
|
|
|
|
|
|
|
|
|
|
+ initializeSubscriptions(); // 新增
|
|
|
|
|
+
|
|
|
// 创建状态发布者
|
|
// 创建状态发布者
|
|
|
state_publisher_ = node_->create_publisher<std_msgs::msg::String>(
|
|
state_publisher_ = node_->create_publisher<std_msgs::msg::String>(
|
|
|
"wheelchair/state", 10);
|
|
"wheelchair/state", 10);
|
|
@@ -26,6 +28,64 @@ WorkflowManager::WorkflowManager(rclcpp::Node *node)
|
|
|
|
|
|
|
|
RCLCPP_INFO(node_->get_logger(), "工作流管理器已初始化");
|
|
RCLCPP_INFO(node_->get_logger(), "工作流管理器已初始化");
|
|
|
}
|
|
}
|
|
|
|
|
+void WorkflowManager::initializeSubscriptions()
|
|
|
|
|
+{
|
|
|
|
|
+ // 创建基站检测订阅者
|
|
|
|
|
+ station_detected_sub_ = node_->create_subscription<std_msgs::msg::Bool>(
|
|
|
|
|
+ "station/detected", 10,
|
|
|
|
|
+ [this](const std_msgs::msg::Bool::SharedPtr msg)
|
|
|
|
|
+ {
|
|
|
|
|
+ this->stationDetectedCallback(msg);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ RCLCPP_INFO(node_->get_logger(), "基站检测订阅者已初始化");
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void WorkflowManager::stationDetectedCallback(const std_msgs::msg::Bool::SharedPtr msg)
|
|
|
|
|
+{
|
|
|
|
|
+ try
|
|
|
|
|
+ {
|
|
|
|
|
+ bool station_detected = msg->data;
|
|
|
|
|
+ std::string current_state_str = getCurrentState();
|
|
|
|
|
+
|
|
|
|
|
+ RCLCPP_DEBUG(node_->get_logger(),
|
|
|
|
|
+ "收到基站检测信号: %s, 当前状态: %s",
|
|
|
|
|
+ station_detected ? "true" : "false",
|
|
|
|
|
+ current_state_str.c_str());
|
|
|
|
|
+
|
|
|
|
|
+ // 只有在搜索或旋转状态下,且检测到基站时,才考虑状态转移
|
|
|
|
|
+ if (station_detected &&
|
|
|
|
|
+ (current_state_ == WheelchairState::SEARCHING ||
|
|
|
|
|
+ current_state_ == WheelchairState::ROTATING))
|
|
|
|
|
+ {
|
|
|
|
|
+ RCLCPP_INFO(node_->get_logger(),
|
|
|
|
|
+ "搜索中检测到基站,切换到行走状态进行对接");
|
|
|
|
|
+
|
|
|
|
|
+ // 从搜索/旋转状态切换到行走状态
|
|
|
|
|
+ transitionToWalking();
|
|
|
|
|
+
|
|
|
|
|
+ // 发布状态更新
|
|
|
|
|
+ publishState("STATION_DETECTED", "检测到基站,开始移动对接");
|
|
|
|
|
+
|
|
|
|
|
+ // 发布回充状态
|
|
|
|
|
+ publishRechargeStatus("STATION_DETECTED",
|
|
|
|
|
+ "检测到充电基站,开始导航对接");
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (!station_detected)
|
|
|
|
|
+ {
|
|
|
|
|
+ // 基站丢失处理(如果之前正在行走对接,但现在基站丢失)
|
|
|
|
|
+ if (current_state_ == WheelchairState::WALKING)
|
|
|
|
|
+ {
|
|
|
|
|
+ // 可以根据需要处理基站丢失的情况
|
|
|
|
|
+ RCLCPP_DEBUG(node_->get_logger(), "行走对接过程中基站信号丢失");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (const std::exception &e)
|
|
|
|
|
+ {
|
|
|
|
|
+ handleException("处理基站检测回调", e);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
void WorkflowManager::initializeRotationManager()
|
|
void WorkflowManager::initializeRotationManager()
|
|
|
{
|
|
{
|
|
@@ -50,7 +110,7 @@ void WorkflowManager::initializeTransitionTable()
|
|
|
std::map<WheelchairState, bool> ipad_cancel_perms = {
|
|
std::map<WheelchairState, bool> ipad_cancel_perms = {
|
|
|
{WheelchairState::READY, true},
|
|
{WheelchairState::READY, true},
|
|
|
{WheelchairState::WALKING, true},
|
|
{WheelchairState::WALKING, true},
|
|
|
- {WheelchairState::ROTATING, false}, // 旋转中❌
|
|
|
|
|
|
|
+ {WheelchairState::ROTATING, true}, // 旋转中❌
|
|
|
{WheelchairState::SEARCHING, true},
|
|
{WheelchairState::SEARCHING, true},
|
|
|
{WheelchairState::CHARGING, true}};
|
|
{WheelchairState::CHARGING, true}};
|
|
|
transition_table_["ipad_phone_interface_cancel"] = ipad_cancel_perms;
|
|
transition_table_["ipad_phone_interface_cancel"] = ipad_cancel_perms;
|
|
@@ -199,6 +259,14 @@ void WorkflowManager::initializeTransitionTable()
|
|
|
{WheelchairState::CHARGING, false}};
|
|
{WheelchairState::CHARGING, false}};
|
|
|
transition_table_["search_30s_timeout"] = search_timeout_perms;
|
|
transition_table_["search_30s_timeout"] = search_timeout_perms;
|
|
|
|
|
|
|
|
|
|
+ std::map<WheelchairState, bool> station_detected_perms = {
|
|
|
|
|
+ {WheelchairState::READY, false},
|
|
|
|
|
+ {WheelchairState::WALKING, false},
|
|
|
|
|
+ {WheelchairState::ROTATING, true}, // 旋转中✅
|
|
|
|
|
+ {WheelchairState::SEARCHING, true}, // 搜索中✅
|
|
|
|
|
+ {WheelchairState::CHARGING, false}};
|
|
|
|
|
+ transition_table_["station_detected"] = station_detected_perms;
|
|
|
|
|
+
|
|
|
RCLCPP_INFO(node_->get_logger(), "状态转移表已初始化完成");
|
|
RCLCPP_INFO(node_->get_logger(), "状态转移表已初始化完成");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -316,6 +384,11 @@ void WorkflowManager::executeEvent(const std::string &event)
|
|
|
{
|
|
{
|
|
|
handleSearchTimeoutEvent();
|
|
handleSearchTimeoutEvent();
|
|
|
}
|
|
}
|
|
|
|
|
+ else if (event == "station_detected")
|
|
|
|
|
+ {
|
|
|
|
|
+ RCLCPP_INFO(node_->get_logger(), "处理基站检测成功事件");
|
|
|
|
|
+ // 实际上这个事件是通过回调处理的,这里只做日志记录
|
|
|
|
|
+ }
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
RCLCPP_WARN(node_->get_logger(), "未实现的事件处理: %s", event.c_str());
|
|
RCLCPP_WARN(node_->get_logger(), "未实现的事件处理: %s", event.c_str());
|
|
@@ -362,7 +435,11 @@ void WorkflowManager::processStateTransition(const std::string &event)
|
|
|
break;
|
|
break;
|
|
|
case WheelchairState::ROTATING:
|
|
case WheelchairState::ROTATING:
|
|
|
// 旋转中状态下,所有事件默认不处理,可以添加特定逻辑
|
|
// 旋转中状态下,所有事件默认不处理,可以添加特定逻辑
|
|
|
- RCLCPP_DEBUG(node_->get_logger(), "旋转中状态下忽略事件: %s", event.c_str());
|
|
|
|
|
|
|
+ if (event == "station_detected")
|
|
|
|
|
+ {
|
|
|
|
|
+ RCLCPP_INFO(node_->get_logger(), "旋转中检测到基站,转为行走对接");
|
|
|
|
|
+ transitionToWalking();
|
|
|
|
|
+ }
|
|
|
break;
|
|
break;
|
|
|
case WheelchairState::SEARCHING:
|
|
case WheelchairState::SEARCHING:
|
|
|
if (event == "base_station_lost")
|
|
if (event == "base_station_lost")
|
|
@@ -377,6 +454,11 @@ void WorkflowManager::processStateTransition(const std::string &event)
|
|
|
{
|
|
{
|
|
|
transitionToWalking();
|
|
transitionToWalking();
|
|
|
}
|
|
}
|
|
|
|
|
+ else if (event == "station_detected")
|
|
|
|
|
+ {
|
|
|
|
|
+ RCLCPP_INFO(node_->get_logger(), "搜索中检测到基站,转为行走对接");
|
|
|
|
|
+ transitionToWalking();
|
|
|
|
|
+ }
|
|
|
// 搜索超时事件
|
|
// 搜索超时事件
|
|
|
else if (event == "search_30s_timeout")
|
|
else if (event == "search_30s_timeout")
|
|
|
{
|
|
{
|
|
@@ -528,9 +610,8 @@ void WorkflowManager::transitionToWalking()
|
|
|
{
|
|
{
|
|
|
rotation_manager_->stopRotation();
|
|
rotation_manager_->stopRotation();
|
|
|
}
|
|
}
|
|
|
- if (current_state_ == WheelchairState::READY ||
|
|
|
|
|
|
|
+ if (
|
|
|
current_state_ == WheelchairState::SEARCHING ||
|
|
current_state_ == WheelchairState::SEARCHING ||
|
|
|
- current_state_ == WheelchairState::CHARGING ||
|
|
|
|
|
current_state_ == WheelchairState::ROTATING)
|
|
current_state_ == WheelchairState::ROTATING)
|
|
|
{
|
|
{
|
|
|
setState(WheelchairState::WALKING);
|
|
setState(WheelchairState::WALKING);
|
|
@@ -671,7 +752,7 @@ void WorkflowManager::processIpadCancelEvent()
|
|
|
|
|
|
|
|
// 根据当前状态决定是否取消回充
|
|
// 根据当前状态决定是否取消回充
|
|
|
if (current_state_ == WheelchairState::SEARCHING ||
|
|
if (current_state_ == WheelchairState::SEARCHING ||
|
|
|
- current_state_ == WheelchairState::CHARGING)
|
|
|
|
|
|
|
+ current_state_ == WheelchairState::WALKING || current_state_ == WheelchairState::ROTATING)
|
|
|
{
|
|
{
|
|
|
transitionToReady();
|
|
transitionToReady();
|
|
|
RCLCPP_INFO(node_->get_logger(), "iPad自主回充已取消,返回到就绪状态");
|
|
RCLCPP_INFO(node_->get_logger(), "iPad自主回充已取消,返回到就绪状态");
|
|
@@ -1346,10 +1427,14 @@ void WorkflowManager::setState(WheelchairState new_state)
|
|
|
"状态转移: %s -> %s",
|
|
"状态转移: %s -> %s",
|
|
|
old_state.c_str(),
|
|
old_state.c_str(),
|
|
|
getCurrentState().c_str());
|
|
getCurrentState().c_str());
|
|
|
|
|
+ // 增强状态发布:包含时间戳和前后状态
|
|
|
|
|
+ std::stringstream enhanced_state;
|
|
|
|
|
+ enhanced_state << "[" << node_->now().seconds() << "] "
|
|
|
|
|
+ << old_state << " -> " << getCurrentState();
|
|
|
|
|
|
|
|
// 发布状态到ROS话题
|
|
// 发布状态到ROS话题
|
|
|
auto msg = std_msgs::msg::String();
|
|
auto msg = std_msgs::msg::String();
|
|
|
- msg.data = getCurrentState();
|
|
|
|
|
|
|
+ msg.data = enhanced_state.str();
|
|
|
state_publisher_->publish(msg);
|
|
state_publisher_->publish(msg);
|
|
|
|
|
|
|
|
// 调用外部回调
|
|
// 调用外部回调
|