ros三大通信方式总结

ROS 中的三种通信方式(Topic、Service、Action),包括它们使用的通信文件、代码示例、区别和使用场景。


1. Topic(话题)

  • 通信方式: 单向通信,类似于广播。
  • 通信文件: .msg 文件。
  • 工作原理:
    • 发布者(Publisher)发布消息到 Topic。
    • 订阅者(Subscriber)从 Topic 接收消息。
  • 特点:
    • 单向传输,没有返回值。
    • 适合持续的数据流(如传感器数据)。
  • 代码示例:
    # Publisher
    import rospy
    from std_msgs.msg import String
    
    rospy.init_node('publisher_node')
    pub = rospy.Publisher('chatter', String, queue_size=10)
    rate = rospy.Rate(1)  # 1Hz
    while not rospy.is_shutdown():
        pub.publish("Hello, World!")
        rate.sleep()
    
    # Subscriber
    def callback(msg):
        rospy.loginfo("I heard: %s", msg.data)
    
    rospy.init_node('subscriber_node')
    rospy.Subscriber('chatter', String, callback)
    rospy.spin()
    
  • 使用场景:
    • 传感器数据(如激光雷达、摄像头数据)。
    • 机器人状态信息(如位置、速度)。
    • 任何需要持续传输数据的场景。

2. Service(服务)

  • 通信方式: 双向通信,类似于函数调用。
  • 通信文件: .srv 文件。
  • 工作原理:
    • 客户端(Client)发送请求。
    • 服务器(Server)处理请求并返回响应。
  • 特点:
    • 一次性请求/响应。
    • 适合短时间任务调用。
  • 代码示例:
    # Server
    import rospy
    from example_srv.srv import AddTwoInts, AddTwoIntsResponse
    
    def handle_add(req):
        return AddTwoIntsResponse(req.a + req.b)
    
    rospy.init_node('add_two_ints_server')
    rospy.Service('add_two_ints', AddTwoInts, handle_add)
    rospy.spin()
    
    # Client
    import rospy
    from example_srv.srv import AddTwoInts, AddTwoIntsRequest
    
    rospy.init_node('add_two_ints_client')
    rospy.wait_for_service('add_two_ints')
    add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
    req = AddTwoIntsRequest(a=1, b=2)
    resp = add_two_ints(req)
    rospy.loginfo("Sum: %d", resp.sum)
    
  • 使用场景:
    • 执行简单任务(如加法计算)。
    • 调用某个功能(如开关设备)。
    • 任何需要请求-响应模式的场景。

3. Action(动作)

  • 通信方式: 双向通信 + 实时反馈。
  • 通信文件: .action 文件。
  • 工作原理:
    • 客户端(Client)发送目标(Goal)。
    • 服务器(Server)执行任务,并实时发送反馈(Feedback)。
    • 任务完成后,服务器返回结果(Result)。
  • 特点:
    • 支持长时间任务。
    • 支持任务取消和实时反馈。
  • 代码示例:
    # Action Server
    import rospy
    import actionlib
    from example_action.msg import FibonacciAction, FibonacciFeedback, FibonacciResult
    
    def execute_cb(goal):
        feedback = FibonacciFeedback()
        result = FibonacciResult()
        sequence = [0, 1]
        for i in range(1, goal.order):
            sequence.append(sequence[i] + sequence[i-1])
            feedback.sequence = sequence
            server.publish_feedback(feedback)
        result.sequence = sequence
        server.set_succeeded(result)
    
    rospy.init_node('fibonacci_server')
    server = actionlib.SimpleActionServer('fibonacci', FibonacciAction, execute_cb, False)
    server.start()
    rospy.spin()
    
    # Action Client
    import rospy
    import actionlib
    from example_action.msg import FibonacciAction, FibonacciGoal
    
    def feedback_cb(feedback):
        rospy.loginfo("Feedback: %s", feedback.sequence)
    
    rospy.init_node('fibonacci_client')
    client = actionlib.SimpleActionClient('fibonacci', FibonacciAction)
    client.wait_for_server()
    goal = FibonacciGoal(order=10)
    client.send_goal(goal, feedback_cb=feedback_cb)
    client.wait_for_result()
    rospy.loginfo("Result: %s", client.get_result())
    
  • 使用场景:
    • 长时间任务(如导航、路径规划)。
    • 需要实时反馈的任务(如机器人移动中的位置反馈)。
    • 支持任务取消的场景。

对比总结

特性Topic (msg)Service (srv)Action (action)
通信模式单向(发布/订阅)双向(请求/响应)双向(Goal/Result) + 反馈(Feedback)
实时性持续数据流一次性请求/响应长时间任务 + 实时反馈
是否支持反馈不支持不支持支持
是否支持取消不支持不支持支持
适用场景传感器数据、状态信息简单任务调用复杂任务(如导航、抓取)

通俗解释

  • Topic:就像广播电台,发布者不断发送消息,订阅者只能听,不能回复。
  • Service:就像打电话,客户端打电话给服务器,服务器接电话并回复。
  • Action:就像点外卖,客户端下单(Goal),商家实时更新配送进度(Feedback),最后送到家(Result)。如果不想等了,还可以取消订单(Cancel)。

在进行ros通信时,需要首先定义消息文件,即.msg .srv .action文件,里面储存着消息的格式,在实际开发中需要我们设计消息的结构体,部署到项目代码中


一、自定义消息开发的通用注意事项

1. 语义清晰性
  • 字段命名:避免歧义,直接表达意图(如 target_pose 而非 goalobstacle_distance 而非 distance)。
  • 单位统一:明确标注单位(如 metersradiansseconds),避免混合单位导致计算错误。
  • 状态枚举:使用 uint8 + 常量定义状态(如 SUCCESS=0, FAILURE=1),而非纯数字。
2. 数据结构优化
  • 复用标准消息:优先使用 geometry_msgsstd_msgs 等ROS内置类型(如 PointQuaternion)。
  • 避免冗余数据
    # 反面案例:重复传输坐标系信息
    x = float32  # 在 map 坐标系下
    y = float32  # 在 map 坐标系下
    frame_id = string  # 冗余,header 中已包含
    
    # 优化方案:使用 PoseStamped
    header = Header
    pose = Pose
    
  • 数组长度控制:若数据量过大(如点云),使用分片(chunked)或压缩格式(如 sensor_msgs/CompressedImage)。
3. 兼容性与版本管理
  • 字段增删规则:仅允许向后兼容的修改(新增字段必须带默认值,禁止删除或修改现有字段)。
  • 语义版本号:遵循 MAJOR.MINOR.PATCH,破坏性变更需升级 MAJOR 版本(如 PathV1.msgPathV2.msg)。
  • 弃用策略:通过文档标注弃用字段,逐步迁移而非强制删除。
4. 性能与效率
  • 零拷贝设计:在C++中使用 const&shared_ptr 避免数据复制。
  • 紧凑数据布局:避免嵌套过深的消息结构(如多层 Array 嵌套)。
  • 二进制兼容性:确保消息序列化后在不同平台(x86/ARM)解析一致。
5. 可扩展性
  • 预留扩展字段:添加 metadata(如 string json_metadata)存储自定义参数。
  • 位掩码标记:使用 uint8 flags + 位运算表示多个布尔状态(如 FLAG_EMERGENCY=0x01)。
6. 文档与测试
  • 必含注释:每个字段需说明用途、单位、取值范围(如 # Range: [0.0, 1.0])。
  • 示例消息:在文档中提供典型场景的 .msg 文件示例。
  • 兼容性测试:验证新旧版本消息的序列化/反序列化兼容性。

二、典型机器人业务与优秀消息设计案例

1. 导航与路径规划
  • 典型消息nav_msgs/Path
    • 结构Header + geometry_msgs/PoseStamped[] poses
    • 优点
      • 复用 PoseStamped 包含时间戳和坐标系
      • 路径点序列清晰,支持插值算法
    • 扩展设计:可添加 velocity_profile 数组表示速度建议。
2. 机械臂控制
  • 典型消息trajectory_msgs/JointTrajectory
    • 结构Header + string[] joint_names + JointTrajectoryPoint[] points
    • 优点
      • 动态绑定关节名与轨迹点,支持不同机械臂
      • 每个轨迹点包含位置、速度、加速度、时间戳
    • 扩展设计:添加 torque_profile 表示力矩约束。
3. SLAM与地图构建
  • 典型消息nav_msgs/OccupancyGrid
    • 结构Header + MapMetaData + int8[] data
    • 优点
      • 使用一维数组存储二维栅格地图,内存紧凑
      • MapMetaData 包含分辨率、原点,支持坐标转换
    • 扩展设计:添加 probability 字段表示置信度。
4. 多传感器融合
  • 典型消息sensor_msgs/PointCloud2
    • 结构Header + uint32 height/width + PointField[] fields + uint8[] data
    • 优点
      • 支持灵活的点云格式(XYZ、RGB、强度等)
      • 通过 fields 动态描述数据布局,兼容不同激光雷达
    • 扩展设计:结合 CompressedImage 实现压缩传输。
5. 任务调度与状态监控
  • 典型消息actionlib_msgs/GoalStatus
    • 结构uint8 status + string text + GoalID goal_id
    • 优点
      • 状态码标准化(SUCCEEDEDABORTED
      • 通过 text 提供人类可读的调试信息

三、优秀设计的核心原则总结

设计维度优秀实践反面案例
字段命名target_joint_anglesdata_array
数据结构使用 PoseStamped 替代独立 x, y, theta重复定义坐标系
性能优化分片传输点云(chunked单消息传输10万个点
兼容性新增 optional_field 并设置默认值删除旧字段 required_field
文档提供字段取值范围(如 # Range: [0, 100]无注释或仅写“速度值”

四、最佳实践工具链

  1. 消息验证工具:使用 rosmsg 检查消息结构,或自定义脚本验证数据合法性。
  2. IDL转换工具:通过 rosidl 生成不同语言的消息代码,或转换为 Protobuf/JSON。
  3. 性能分析:用 rostopic bw 监控消息带宽,用 rqt_plot 可视化实时数据。

通过以上设计原则和典型案例,开发者可以构建高鲁棒性、高效且易维护的ROS消息接口,满足复杂机器人系统的长期需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值