使用launch文件启动ROS服务返回IMU值为0问题求助
问题根因
- 启动时序不匹配:launch启动时两个节点同时运行,服务端节点刚启动还没收到
/thrbot/imu话题的第一帧数据,存储IMU数值的全局变量还保持初始化的0值,此时客户端已经完成服务调用,自然返回0。手动执行rosrun时一般会先启动服务端等待数据接收完成后再启动客户端,所以数值正常。 - 服务端回调逻辑缺陷:你编写的服务处理函数
get_val声明了bool返回类型,但没有显式返回值,属于未定义行为,会导致服务调用状态异常。 - 客户端无等待逻辑:客户端启动后直接调用服务,既没有等待服务端完成注册,也没有等待IMU数据完成首次接收。
解决方案
你可以任选以下一种方案快速修复,也可以组合使用提升稳定性:
方案1:修改客户端添加等待逻辑(推荐)
修改客户端代码,增加服务等待和数据延迟逻辑,示例如下:
#include "ros/ros.h" #include "ros_services/ImuValue.h" #include <cstdlib> int main(int argc, char **argv) { ros::init(argc,argv,"imu_client_node"); ros::NodeHandle n; ros::ServiceClient client = n.serviceClient<ros_services::ImuValue>("imu_status_server"); // 等待服务注册完成,最长等待5秒 if(!ros::service::waitForService("imu_status_server", ros::Duration(5.0))){ ROS_ERROR("等待IMU服务超时"); return 1; } ros_services::ImuValue srv; // 等待1秒保证服务端拿到第一帧IMU数据 ros::Duration(1.0).sleep(); if(client.call(srv)){ std::cout << "Got accel x: " << srv.response.current_x_orientation_s << std::endl; }else{ ROS_ERROR("调用IMU服务失败"); return 1; } return 0; }
方案2:修改launch文件添加启动延迟(无需改代码)
直接给客户端节点加启动延迟,让服务端先运行2秒再启动客户端,修改后的launch文件如下:
<?xml version="1.0"?> <launch> <node name="ImuServerService" pkg="ros_services" type="ImuServerService" output="screen"> </node> <node name="ImuClientService" pkg="ros_services" type="ImuClientService" output="screen" launch-prefix="sleep 2 && "/> </launch>
方案3:优化服务端逻辑(提升健壮性)
给服务端增加数据接收标记,未收到IMU数据时直接返回服务调用失败,引导客户端重试,修改点如下:
// 新增全局标记位 bool imu_received = false; bool get_val(imu_service::ImuValue::Request &req, imu_service::ImuValue::Response &res) { if(!imu_received){ ROS_WARN("IMU数据未就绪,服务调用失败"); return false; } ROS_INFO("sending back response"); res.current_x_orientation_s = get_imu_orientation_x; // 必须显式返回true表示服务处理成功 return true; } void imuCallback(const sensor_msgs::ImuConstPtr& msg) { current_x_orientation_s= msg->orientation.x; get_imu_orientation_x=current_x_orientation_s; // 标记数据已接收 imu_received = true; }
内容的提问来源于stack exchange,提问作者Bob9710
相关产品推荐
相关产品推荐

