Server status. Good job, friend!

服务器当前已运行48天4小时24分钟,负载平均值较低。计划在周一因预防性断电而关闭。

Will be shutdown in prior to power outage on Monday.

### 解决方案分析 在 ROS 的 `ActionServer` 实现中,如果执行回调 (`executeCallback`) 未能正确设置目标的状态为目标完成或终止状态,则可能会导致客户端无法正常接收最终的结果。这种行为通常是因为回调函数内部逻辑错误或者未调用适当的 API 来更新目标状态。 以下是针对此问题的具体解决方案: #### 1. **确认回调函数中的状态更新** 确保在 `executeCallback` 函数中显式地设置了目标的终端状态。ROS 提供了多种方法来标记目标已完成或失败,例如: - 调用 `setSucceeded()` 方法表示目标成功完成。 - 调用 `setAborted()` 方法表示目标因某种原因被中断。 - 调用 `setPreempted()` 方法表示目标被抢占。 这些方法会自动将目标状态更改为相应的终端状态,并通知客户端[^1]。 ```cpp void executeCB(const actionlib_tutorials::FibonacciGoalConstPtr& goal) { // ... 执行任务 ... if (/* 成功条件 */) { as_->setSucceeded(result); } else if (/* 中断条件 */) { as_->setAborted(); } else if (/* 抢占条件 */) { as_->setPreempted(); } } ``` #### 2. **检查定时器发布状态的功能** 从引用内容可以看出,`publishStatus` 是一个周期性发布的功能,用于向客户端发送当前的目标状态列表。如果某些目标长时间停留在非终端状态(如 `ACTIVE`),可能是由于以下原因之一: - 定时器频率过低,导致状态更新不及时。 - 回调函数中未正确处理异常情况,使得目标状态卡住。 可以通过增加调试日志的方式验证状态更新是否按预期工作。例如,在每次循环中打印当前状态列表的内容[^1]。 ```cpp template<class ActionSpec> void ActionServer<ActionSpec>::publishStatus() { boost::recursive_mutex::scoped_lock lock(this->lock_); actionlib_msgs::GoalStatusArray status_array; status_array.header.stamp = ros::Time::now(); for (auto it = this->status_list_.begin(); it != this->status_list_.end(); ++it) { ROS_INFO_STREAM("Current Goal Status: " << (*it).status_.goal_id.id << ", State: " << (*it).status_.status); // 发布状态... } status_pub_.publish(status_array); } ``` #### 3. **引入超时机制** 为了避免目标无限期处于活动状态,可以在服务器端实现超时检测逻辑。当某个目标超过预设时间仍未进入终端状态时,强制将其置为失败状态。 修改后的代码可能如下所示: ```cpp for (auto it = this->status_list_.begin(); it != this->status_list_.end();) { auto current_time = ros::Time::now(); if ((*it).start_time_ + timeout_duration_ < current_time && !(*it).is_terminal_state_) { ROS_WARN_STREAM("Timeout detected for goal ID: " << (*it).status_.goal_id.id); as_->setAborted((*it).result_, "Execution timed out"); it = this->status_list_.erase(it); } else { ++it; } } ``` 此处假设每个目标都有一个记录其启动时间的字段 `start_time_` 和判断是否已到达终端状态的标志位 `is_terminal_state_`[^1]。 --- ### 示例代码修正 基于以上分析,提供一段完整的修复示例代码片段: ```cpp #include <actionlib/server/simple_action_server.h> typedef actionlib::SimpleActionServer<actionlib_tutorials::FibonacciAction> FibonacciServer; void executeCB(const actionlib_tutorials::FibonacciGoalConstPtr& goal, FibonacciServer* as) { bool success = true; try { // Simulate doing some work. feedback.sequence.clear(); for(int i=0;i<=goal->order;i++) { if(as->isPreemptRequested() || !ros::ok()) { ROS_INFO("%s: Preempted", action_name.c_str()); as->setPreempted(); success = false; break; } feedback.sequence.push_back(i); as->publishFeedback(feedback); ros::Duration(0.1).sleep(); } if(success){ result.sequence = feedback.sequence; ROS_INFO("%s: Succeeded", action_name.c_str()); as->setSucceeded(result); } } catch (...) { ROS_ERROR("Exception occurred during execution."); as->setAborted(); } } int main(int argc, char** argv) { ros::init(argc, argv, "fibonacci_server_node"); FibonacciServer fibonacci_as(node_handle, "fibonacci", boost::bind(&executeCB, _1, &fibonacci_as), false); fibonacci_as.start(); ros::spin(); return 0; } ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值