Skip to content

Latest commit

 

History

32 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NavForge

NavForge is a ROS2 navigation deployment framework built around Nav2, providing reusable configurations, dependencies and launch workflows for mobile robots.

NavForge 面向仿真与真实移动机器人提供可复用的 ROS 2 Humble 2D 导航部署能力。框架通过 profile、mode 和 params 组合构建导航系统;自研节点负责话题与 frame 规范化,点云转激光、SLAM、AMCL 和 Nav2 等能力通过依赖包按需启用。

ROS 2 包名遵循小写命名约定:

  • navforge:话题与 TF 规范化节点
  • navforge_bringup:统一入口和模块化 launch 工作流
  • navforge_config:机器人 profile、部署 mode、算法参数、地图与 RViz 配置

功能模式

mode 用途 定位 模块
mapping SLAM 建图与地图保存 slam_toolbox static_tf + laserscan + interface + slam
nav 已保存地图上的全局导航 AMCL static_tf + laserscan + interface + amcl + nav2
local_nav 不维护全局地图的短程导航 连续 odom static_tf + laserscan + nav2

每种模式在 modes/templates/ 中提供组合模板,实际启动文件按机器人添加尾缀: mapping_l1nav_l1local_nav_l1,以及 mapping_quadrovernav_quadroverlocal_nav_quadrover

快速开始

./scripts/install_deps.sh
./scripts/build.sh
source install/setup.bash

先启动仿真或真机驱动,再 launch 对应 mode。

架构

外部环境(仿真 / 真机)
    ├── 传感器 / 定位话题
    │       ↓ params 中写明的 input_topic
    │   laserscan + interface
    │       ↓ /scan、/odom 与动态 TF
    │   slam / amcl / nav2
    │
    └── static_tf(按配置补齐真机缺失的固定坐标变换)

TF 分工

模式 odom→base_link map→odom
mapping interface 或机器人里程计 slam_toolbox
nav interface 或机器人里程计 AMCL
local_nav interface 或机器人里程计 无(全链路使用 odom

map→odom 只能由一个模块发布:slam_toolbox 与 AMCL 不可同时运行。 传感器等固定 frame 由机器人驱动、robot_state_publisherstatic_tf 发布, 同一变换只能保留一个发布源。

配置分层

层级 职责
profiles/*.yaml footprint、frames
modes/templates/*.yaml mappingnavlocal_nav 三种组合模板
modes/*_{l1,quadrover}.yaml 机器人实际使用的模块、params、RViz 与地图路径
params/*.yaml 话题、frame、算法参数
launch use_sim_time 可覆盖 mode 默认时钟;Quadrover 为 true,L1 为 false

params 一览

文件 用于
laserscan_{l1,quadrover}.yaml 点云→/scan
cloud_filter_l1.yaml L1 机身与上装点云剔除
interface_mapping_{l1,quadrover}.yaml 建图里程计接口
interface_nav_{l1,quadrover}.yaml 全局/局部导航里程计接口
slam_mapping_{l1,quadrover}.yaml slam_toolbox建图
amcl_nav_{l1,quadrover}.yaml nav的AMCL + map_server
nav2_nav_{l1,quadrover}.yaml 已保存地图导航
nav2_local_nav_{l1,quadrover}.yaml 滚动局部导航
static_tf_{l1,quadrover}.yaml 各机器人缺失的静态TF
robot_localization_l1.yaml L1 Local/Global EKF 完整示例
rtk_adapter_l1.yaml L1 Unicore 双天线标准消息适配

L1 使用 _l1 参数文件。其中 nav2_nav_l1.yaml 使用 MPPI Omni 控制器、 SmacPlanner2D、全向 AMCL 运动模型配套的室外 costmap;slam_mapping_l1.yaml 为实时建图调整扫描节流、队列与回环检测。 nav2_local_nav_l1.yaml 不订阅静态地图,使用 odom 下固定 20 m × 20 m 滚动全局 costmap,供长时间运行的短程避障导航使用。

params/templates/ 按 launch 模块提供完整、带注释的配置基线。模板不会被 mode 自动加载;可以复制到 params/ 后修改,也可以直接使用相对路径,例如 params_file:=templates/laserscan.yaml。完整清单和使用说明见 params/templates/README.md

仿真与真机差异:修改 interface_*.yaml 中的 input_topic

自体点云剔除

L1 mode 默认在生成 /scan 前启动 cloud_filter

/livox/lidar → cloud_filter → /livox/lidar_filtered
                              → pointcloud_to_laserscan → /scan

节点按点云时间戳查询 filter_frame(默认 base_link)的 TF,并剔除落在任一 三维包围盒内的点。输出仍保留输入点云的 frame 和全部字段,后续 pointcloud_to_laserscan 会按自身配置转换到 base_link。TF 不可用或点云 缺少有效的 x/y/z 字段时整帧丢弃并输出节流告警,避免使用坐标系错误的数据。

编辑 params/cloud_filter_l1.yamlbox_names,并为每个名称配置 boxes.<name>.min_x/max_x/min_y/max_y/min_z/max_z。ROS 2 参数不支持配置示例 中那种字典数组,因此采用名称列表加嵌套参数:

box_names: [robot_body, rear_payload]
boxes:
  rear_payload:
    min_x: -0.65
    max_x: -0.25
    min_y: -0.30
    max_y: 0.30
    min_z: 0.25
    max_z: 0.90

包围盒边界均以 filter_frame 为准,真机部署前应根据实际机身、腿部运动包络和 上装尺寸测量,并用 RViz 同时观察原始点云与 /livox/lidar_filtered,确认不会 误删紧邻机器狗的真实障碍物。模块也可单独启动:

ros2 launch navforge_bringup cloud_filter.launch.py \
  params_file:=cloud_filter_l1.yaml

Robot Localization

robot_localization.launch.py 可以从一个 params 文件启动 Local EKF 和 Global EKF。当前没有 mode 引用该模块,需单独启动:

ros2 launch navforge_bringup robot_localization.launch.py \
  params_file:=robot_localization_l1.yaml

示例数据流如下:

L1 LIO → /slam_odom + odom→base_link
/slam_odom + 绝对全局观测 → ekf_global → /odometry/global + map→odom

编辑 params/robot_localization_l1.yaml 中各节点的 enabledremappingsros__parameters 即可选择节点、替换真机话题并调整融合维度。配置数组顺序为 x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az; L1 示例保留全向运动所需的 vxvy

L1 的 LIO 已完成 LiDAR/IMU 紧耦合并负责 odom→base_link,因此示例默认关闭 ekf_local。由于暂未选择绝对全局观测,ekf_global 也默认关闭。配置全局 观测后,仍需确保它与 SLAM、AMCL 不会同时发布 map→odom。RTK/NavSat 数据转换与融合策略将在确定接收机输出、航向定义和质量状态后单独设计。

Unicore RTK Adapter

rtk_adapter 将 L1 的 Unicore 派生自定义消息转换为 ROS 标准类型:

/uni_best_nav → /rtk/fix     sensor_msgs/msg/NavSatFix
/uni_heading  → /rtk/heading sensor_msgs/msg/Imu(仅绝对 ENU yaw)
状态与拒绝原因 → /rtk/status diagnostic_msgs/msg/DiagnosticArray

节点会从 ROS graph 自动发现两个输入话题的实际消息类型,因此 NavForge 不需要 编译依赖厂商接口包;运行环境仍必须安装并 source 对应消息接口包。也可在 params 中填写 package/msg/Type 显式指定。当前没有 mode 自动启动该模块, 可独立验证:

ros2 launch navforge_bringup rtk_adapter.launch.py \
  params_file:=rtk_adapter_l1.yaml

L1 默认只接受 solution_status=0 且类型为 50 的 RTK Fixed 位置和航向。 无效解只写入 /rtk/status,不会把零经纬度或零航向送入定位链路。航向从 “真北为零、顺时针为正”转换为 ROS ENU,并通过 heading_mounting_yaw_deg 补偿双天线基线相对 base_link +X 的安装角。 rtk_primary_link 必须通过静态 TF 正确连接到 base_link。RTK 与 Global EKF 的融合仍保持独立,待确定门限和 TF 所有权后再接入 mode。hor_spdtrk_gndver_spd 暂不输出:其 ENU 速度还需要随全局 frame 对齐,且当前 厂商消息未提供可用速度标准差,避免在此阶段生成看似完整但协方差不可信的速度。

静态 TF 配置

所有 mode 默认都会启动 static_tf 模块。编辑对应机器人的 params/static_tf_<robot>.yamltransforms 数组即可补齐任意多个固定变换;未配置 transforms 时节点不会发布 TF。

static_tf_publisher:
  ros__parameters:
    # parent child x y z roll pitch yaw
    # 平移单位:米;旋转单位:弧度
    transforms:
      - "base_link lidar_link 0.20 0.0 0.30 0.0 0.0 0.0"
      - "base_link imu_link 0.00 0.0 0.10 0.0 0.0 1.5708"

每个 child frame 只能配置一次。不要配置已由机器人驱动、 robot_state_publisher、SLAM 或 AMCL 发布的变换,否则 TF 会产生冲突。

地图文件

src/navforge_config/maps/gitignore,本地存放,不入库。

./scripts/save_map.sh
# 默认保存:src/navforge_config/maps/<当前 profile>/map.yaml + map.pgm
用途 格式 默认路径
建图保存 .yaml + .pgm maps/<profile>/map
已知地图导航 .yaml + .pgm maps/example/map
L1 建图 / 已知地图 同上 maps/l1/map

建图类 mode 不配置保存路径。save_map.sh 会从正在运行的 topic_relay_odom 读取 profile;无法读取时回退为 quadrover。也可以显式指定 profile、目录和文件名:

./scripts/save_map.sh --profile l1
./scripts/save_map.sh --output-dir /data/maps --map-name campus
# 兼容旧位置参数:MAP_NAME OUTPUT_DIR
./scripts/save_map.sh campus /data/maps

启动命令

# Quadrover 建图
ros2 launch navforge_bringup navforge.launch.py mode:=mapping_quadrover

# Quadrover 已保存地图导航
ros2 launch navforge_bringup navforge.launch.py mode:=nav_quadrover

# Quadrover 局部导航
ros2 launch navforge_bringup navforge.launch.py mode:=local_nav_quadrover

# 覆盖 mode 中的地图路径
ros2 launch navforge_bringup navforge.launch.py \
  mode:=nav_quadrover map:=maps/quadrover/map

可选参数:use_rviz:=falseprofile:=...use_sim_time:=...。未显式指定时 使用 mode 中的默认值;Quadrover mode 使用仿真时钟,L1 mode 使用 l1/系统时钟。

L1 机器狗真机

部署前必须确认

默认配置假设机器狗驱动提供:

接口 默认值 要求
Livox 原始点云 /livox/lidar sensor_msgs/PointCloud2,有效时间戳和 frame,包含 x/y/z
LIO 里程计 /slam_odom nav_msgs/Odometry,并提供连续的 odom→base_link
速度指令 /cmd_vel 支持 linear.xlinear.yangular.z,停止时三个分量必须为 0
TF SLAM/AMCL 为 map→odom→base_link;局部导航为 odom→base_link 只能有一个发布源;传感器固定 TF 必须完整

按实际驱动修改 cloud_filter_l1.yamllaserscan_l1.yamlinterface_*_l1.yaml,测量包含载荷后的机身外廓并同步修改 profiles/l1.yamlnav2_nav_l1.yamlnav2_local_nav_l1.yaml 中的 footprint。 在 static_tf_l1.yaml 中只补充驱动或 URDF 未发布的固定变换。 当前L1 LIO自身发布odom→base_link,因此interface_*_l1.yaml已将 publish_tf设为none;只有更换为不发布TF的里程计源时才应调整所有权。

本仓库使用 2D costmap。室外坡地、台阶和负障碍不能仅凭投影后的 /scan 判断可通行性;送入本工具前必须完成地面分割/地形过滤,并保留独立急停与真机限速。

启动

# 室外建图
ros2 launch navforge_bringup navforge.launch.py \
  mode:=mapping_l1 use_sim_time:=false

# 保存地图上的AMCL导航
ros2 launch navforge_bringup navforge.launch.py \
  mode:=nav_l1 use_sim_time:=false map:=maps/l1/map

# 不维护全局地图的长时间短程导航
# 目标使用 odom frame,推荐单段距离 5-8 m
ros2 launch navforge_bringup navforge.launch.py \
  mode:=local_nav_l1 use_sim_time:=false

首次上车应架空或低速测试横移方向和急停,再从空旷区域开始。默认速度上限为 前进 0.4 m/s、后退 0.2 m/s、横移 0.2 m/s、转动 0.6 rad/s; 目标容差为 0.10 m / 0.10 rad。L1 驱动接受的最小非零速度为前后 0.05 m/s、横移 0.10 m/s、转动 0.02 rad/s,对应配置在 nav2_nav_l1.yamlnav2_local_nav_l1.yaml中的 VelocityDeadbandCritic.deadband_velocitiesvelocity_smoother.deadband_velocity

整体导航速度主要由 FollowPath 下的 vx_maxvx_minvy_maxwz_max 决定;velocity_smoothermax_velocitymin_velocity 是发布到真机前的最终 硬限制。调整速度时应同步修改这两组值,并优先保持两处限制一致。 先校准里程计、TF、footprint 和时间同步,再调整 MPPI critic 权重;不要通过继续 缩小目标容差掩盖定位漂移。

建图

  1. 启动 mapping,遥控覆盖环境
  2. ./scripts/save_map.sh 保存栅格地图;默认输出到当前 profile 的 map.yamlmap.pgm

全局导航

  1. 使用mapping_<robot>生成地图并保存
  2. 启动nav_<robot>
  3. RViz 2D Pose Estimate 设置初始位姿
  4. 发送 Nav2 Goal

局部导航

  1. 启动local_nav_<robot>
  2. 确认机器人提供连续的odom→base_link
  3. odom坐标系内发送短程目标;长任务由上层拆分为多个局部目标

脚本

脚本 作用
install_deps.sh 安装 apt 依赖
build.sh colcon 编译
save_map.sh 保存栅格地图,支持自定义 profile、目录和文件名

常见问题

/scan 无数据

pointcloud_to_laserscan 懒订阅:打开 RViz 或 ros2 topic hz /scan 触发。

RViz LaserScan 不显示

/scan 为 Best Effort。使用 mode 对应的 rviz_config,或手动将 Reliability 改为 Best Effort。

RViz未弹出

修改 launch 后需重新 colcon buildsource install/setup.bash

AMCL 不定位

必须先 2D Pose Estimate,等待 AMCL 发布 map→odom 后再发 Goal。

Goal 到达精度

在对应的nav2_nav_<robot>.yamlnav2_local_nav_<robot>.yaml中调整 xy_goal_tolerance(米)与yaw_goal_tolerance(弧度)。 L1 使用precise_goal_checker;实际精度上限首先取决于传感器标定、 时间同步、里程计和全局定位质量。

/loc/gazebo 误用

/loc/gazebomap→base_link真值,不能作为AMCL的odom输入;Quadrover导航 应使用/odom/wheel(见interface_nav_quadrover.yaml)。

仓库结构

NavForge/
├── scripts/              # install / build / save_map
├── src/
│   ├── navforge/          # C++ nodes and shared headers
│   ├── navforge_bringup/  # launch entrypoint and module launch files
│   └── navforge_config/   # profiles / modes / params / maps / rviz
├── AGENTS.md
└── README.md

About

A ROS2 navigation deployment framework built around Nav2, providing reusable configurations, dependencies and launch workflows for mobile robots

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages