1. /joint_states 来自于那里?

我们从这个章节 了解到,robot_state_publisher 会订阅 /joint_states,来计算对应的坐标变化。 那么, /joint_states 来自于那里呢?

根据场景不同,我们总结了以下来源:

来源节点 说明 是否实际连接物理设备
joint_state_publisher 从 URDF 参数中读取所有关节定义,生成模拟的 joint_state(通常给静态或手动控制用) ❌ 无物理设备,只是虚拟 joint 数据
joint_state_publisher_gui 同上,但提供图形界面(滑动条调关节角度)
硬件驱动节点(如 ros2_control / 实际机器人驱动) 从机器人控制器读取真实传感器值,发布真实 joint 状态 ✅ 有物理设备
仿真节点(如 Gazebo / Ignition) 仿真环境中的物理引擎发布 ✅ 虚拟设备(仿真)

1. 1 关于joint_state_publisher

joint_state_publisher 根据 /robot_description 参数中的关节描述, 模拟或手动设置的关节角度 它并不会生成实际的关节状态,而是模拟的 在没有实际硬件时,用于仿真、调试、可视化。真正的关节变化,一定是来自于机器人的传感器。

2. 传感器融合 - robot_localization

robot_localization 是ROS/ROS2 社区里 “开箱即用” 的传感器融合神器。robot_localization 提供:

  • 扩展卡尔曼滤波(EKF)节点
  • 无迹卡尔曼滤波(UKF)节点
节点 作用
ekf_node 基于扩展卡尔曼滤波融合传感器数据(线性化滤波),适合大部分机器人
ukf_node 基于无迹卡尔曼滤波,可处理强非线性情况,但计算量大,适合动态环境或非线性运动模型

它能把 雷达 + 超声波 + 里程计 + IMU数据 全部塞进同一个 EKF/UKF Node 里,吐出一条 平滑、连续、漂移极小 的 /odometry/filtered 里程计,坐标系统一到 odom 或 map。

其主要用于:

  • 融合多源传感器数据,生成一致的机器人位姿(位置 + 姿态)和速度信息。
  • 输出 odometry-like 信息,用于导航和控制。
  • 处理传感器噪声、延迟和不一致问题,使机器人对运动状态的估计更准确。

没有融合之前,每个传感器都有自己的优缺点:

传感器 优点 缺点
IMU 高频率、短时漂移小 长时间积分会累积漂移(位置)
里程计(编码器) 短时间位置精度高 滑轮打滑会导致误差
激光雷达 精度高、可定位 更新频率低、依赖特征
超声波 检测近距离障碍物 精度低、容易受干扰

融合之后:

  • IMU 提供高频姿态更新
  • 里程计提供短期位移约束
  • 雷达/超声波提供环境位置校正

这样就能得到相对稳定、低噪声的 odom 信息,供导航使用。

给出一个关于融合前后的误差的案例:
误差曲线:纯轮式 1 min 漂 1.8 m , 融合后 0.07 m

2.1 robot_localization 通用性

非常通用,但需要配置。

  • 输入数据类型,可以接收:
    • sensor_msgs/Imu
    • nav_msgs/Odometry
    • geometry_msgs/TwistWithCovariance
    • 自定义话题(只要消息类型匹配)
  • 配置灵活,可以指定每个传感器的:
    • Covariance(噪声矩阵)
    • 是否用于位置/姿态/速度融合
    • 更新频率
  • 输出标准化:
    • /odom 或 /odometry/filtered 话题
    • 可以直接作为导航(Nav2 / move_base)输入

所以无论是差速、全向、阿克曼,或者是地面 / 水下 / 空中机器人,只要你提供正确的传感器输入,它都能用。

2.2 配置robot_localization

robot_localization 的核心是 YAML 配置文件,定义传感器输入、噪声矩阵、融合策略等。常见文件名如 ekf.yaml 或 ukf.yaml。

ekf_filter_node:
  ros__parameters:
# ────────────────────── 1. 核心节奏 ──────────────────────
    frequency: 50.0                 # 50Hz 丝滑输出
    sensor_timeout: 0.2             # 丢 0.2s 就纯预测,防卡死
    two_d_mode: true                # 平面车,关 3D!
    print_diagnostics: true         # 出错直接 echo /diagnostics_agg 看

# ────────────────────── 2. 坐标系(一改全活) ──────────────────────
    map_frame:  map                 # 激光建图用
    odom_frame: odom_combined       # 连续 odom(Nav2 吃这根!)
    base_link_frame: base_footprint # 底盘固定名字
    world_frame: odom_combined      # 重要!输出在 odom 系

# ────────────────────── 3. 轮式里程计(防打滑) ──────────────────────
    odom0: /odom                    # 默认话题
    odom0_config: [true, true, false,      # X Y
                   false,false,false,      # roll pitch
                   true, true, false,      # yaw
                   true, true, false,      # VX VY
                   false,false,false]      # 加速度不用
    odom0_queue_size: 10
    odom0_differential: false       # 是绝对位姿
    odom0_nodelay: true

# ────────────────────── 4. IMU(零速修正+防侧滑) ──────────────────────
    imu0: /imu/data_raw             # 轮趣原始 IMU
    imu0_config: [false,false,false,
                  true, true, true,        # 角速度全开
                  false,false,false,
                  true, true, true,        # 线加速度全开
                  false,false,false]
    imu0_queue_size: 10
    imu0_differential: false        # 绝对角速度
    imu0_remove_gravitational_acceleration: true   # 自动去重力
    imu0_nodelay: true

# ────────────────────── 5. 激光 Cartographer(全局定位) ──────────────────────
    pose0: /cartographer/odom       # carto 吐的 odom
    pose0_config: [true, true, false,
                   false,false,false,
                   true, true, false,
                   true, true, false,
                   false,false,false]
    pose0_queue_size: 5
    pose0_differential: false
    pose0_relative: false

# ────────────────────── 6. 超声波墙距(室内神器) ──────────────────────
    pose1: /sonar_pose              # 你自己写的节点
    pose1_config: [true, true, false,
                   false,false,false,
                   false,false,false,
                   false,false,false,
                   false,false,false]
    pose1_queue_size: 5

# ────────────────────── 7. 控制输入(急转弯更准) ──────────────────────
    use_control: true
    control_timeout: 0.1
    control_config: [true, false, false, false, false, true]  # 只控 X 和 yaw

# ────────────────────── 8. 噪声(复制粘贴,永不调参) ──────────────────────
    process_noise_covariance: [0.08,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                               0,0.08,0,0,0,0,0,0,0,0,0,0,0,0,0,
                               0,0,1e3,0,0,0,0,0,0,0,0,0,0,0,0,
                               0,0,0,0.03,0,0,0,0,0,0,0,0,0,0,0,
                               0,0,0,0,0.03,0,0,0,0,0,0,0,0,0,0,
                               0,0,0,0,0,0.08,0,0,0,0,0,0,0,0,0,
                               0,0,0,0,0,0,0.03,0,0,0,0,0,0,0,0,
                               0,0,0,0,0,0,0,0.03,0,0,0,0,0,0,0,
                               0,0,0,0,0,0,0,0,1e3,0,0,0,0,0,0,
                               0,0,0,0,0,0,0,0,0,0.02,0,0,0,0,0,
                               0,0,0,0,0,0,0,0,0,0,0.02,0,0,0,0,
                               0,0,0,0,0,0,0,0,0,0,0,0.04,0,0,0,
                               0,0,0,0,0,0,0,0,0,0,0,0,0.01,0,0,
                               0,0,0,0,0,0,0,0,0,0,0,0,0,0.01,0,
                               0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.02]

# ────────────────────── 9. 初始误差(1e-9 秒收敛) ──────────────────────
    initial_estimate_covariance: [1e-9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                  0,1e-9,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                  0,0,1e-9,0,0,0,0,0,0,0,0,0,0,0,0,
                                  0,0,0,1e-9,0,0,0,0,0,0,0,0,0,0,0,
                                  0,0,0,0,1e-9,0,0,0,0,0,0,0,0,0,0,
                                  0,0,0,0,0,1e-9,0,0,0,0,0,0,0,0,0,
                                  0,0,0,0,0,0,1e-9,0,0,0,0,0,0,0,0,
                                  0,0,0,0,0,0,0,1e-9,0,0,0,0,0,0,0,
                                  0,0,0,0,0,0,0,0,1e-9,0,0,0,0,0,0,
                                  0,0,0,0,0,0,0,0,0,1e-9,0,0,0,0,0,
                                  0,0,0,0,0,0,0,0,0,0,1e-9,0,0,0,0,
                                  0,0,0,0,0,0,0,0,0,0,0,1e-9,0,0,0,
                                  0,0,0,0,0,0,0,0,0,0,0,0,1e-9,0,0,
                                  0,0,0,0,0,0,0,0,0,0,0,0,0,1e-9,0,
                                  0,0,0,0,0,0,0,0,0,0,0,0,0,0,1e-9]
Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐