Skip to content

Repository files navigation

Unitree G1 Mid-360 · FAST-LIO ROS2 Foxy · Nav2 / Canvas

这是一个面向小型室内环境的三维建图与导航 baseline。它直接使用宇树 G1 官方雷达服务发布的 Mid-360 点云和 IMU,不启动另一套雷达驱动;FAST-LIO 负责建图和实时激光惯性里程计,PCL + OctoMap 把保存的 PCD 转为 Nav2 静态占据地图,Nav2 负责全局规划和局部实时避障。建图仍可使用 Viser,导航使用 Canvas + rosbridge 网页。

Mid-360 官方服务(eth0 / DDS)
  ├─ /utlidar/cloud_livox_mid360 ─┐
  └─ /utlidar/imu_livox_mid360 ───┴─> FAST-LIO
                                      ├─ /cloud_registered(当前注册帧)
                                      ├─ /Laser_map(持续增长的全局地图)
                                      ├─ /Odometry(雷达 IMU 位姿)、/path
                                      └─ maps/fastlio_map.pcd(完整地图)

rt/lowstate(eth0 / Unitree SDK2)──> 官方 mode=6 URDF 腰部链
                                      └─ /Odometry_base(平面导航 base_nav)

/cloud_registered + /Laser_map + /Odometry_base
  └─> Viser 0.0.0.0:8080(远程主机经 wlan0 访问)

当前配置

  • 系统:Ubuntu 20.04 / ROS2 Foxy / aarch64。
  • 雷达:Livox Mid-360,使用宇树官方 LiDAR service DDS 数据。
  • DDS 内部链路:eth0,CycloneDDS 配置默认为 /home/unitree/cyclonedds_ws/cyclonedds_eth0.xml
  • 网页链路:wlan0,Viser 监听 0.0.0.0:8080。当前机器的 Wi-Fi 地址为 http://172.16.12.245:8080,DHCP 变化时以启动脚本打印的地址为准。
  • 输入有效距离:0.5–10.0 mpreprocess.max_range=10.0 会真实丢弃 10 m 外点,mapping.det_range=10.0 同时控制 FAST-LIO 局部地图移动阈值。
  • Mid-360 官方 PointCloud2 字段:x/y/z/intensity/ring/timetime 是单帧内纳秒偏移,已转换为 FAST-LIO 使用的毫秒。
  • 最终 fastlio_map.pcd/Laser_map 使用同一份持续增长的实时建图层;Viser 的 0.10 m 体素和 25 万点上限只影响网页预览,不影响最终 PCD。
  • 世界坐标为 map+Z 由启动静止阶段的重力确定,+X 由官方 Mid360 安装姿态确定为启动时机器人腰部朝前方向。
  • 本机实测 mode_machine=6,自动选择官方 g1_29dof_lock_waist_rev_1_0.urdf;腰 yaw 使用 LowState.motor_state[12].q,roll/pitch 按官方固定关节锁为 0。

参数文件在 fast_lio_mid360_indoor.yamlviser.yamlextrinsic_T=[-0.011,-0.02329,0.04412] 是宇树 LiDAR 文档所给“雷达系中的内置 IMU 位移”的逆变换,不是猜测的机身安装值。

G1 腰部与 Mid360 坐标链

本机采用下面这条动态链。base_link 仍是腰部 pelvis 的真实三维姿态;不伪造腿部、足端或固定 pelvis 高度。二维 AMCL/Nav2 另外使用同原点、仅保留 yaw 的 base_nav,防止人形机器人站立和行走时的 roll/pitch 污染 map→odom

map → odom → base_nav(yaw-only)→ base_link (= pelvis,保留 roll/pitch) → 官方 URDF → MID-360
  └─ waist_yaw_joint      q = motor_state[12].q
     └─ waist_roll_joint  fixed, xyz=(-0.0039635, 0, 0.044)
        └─ waist_pitch_joint fixed
           └─ torso_link
              └─ mid360_link / livox_frame
                 xyz=(0.0002835, 0.00003, 0.428434)
                 rpy=(pi, 0.0511206938, 0)
                 └─ livox_imu xyz=(0.011, 0.02329, -0.04412)

FAST-LIO 仍只用 Mid360 点云与雷达内置 IMU 做紧耦合估计;关节数据不进入滤波器,只在每帧用上面的官方链把 /Odometrylivox_imu 位姿换算成腰部 /Odometry_base,同时发布对应 TF 和 /joint_states。SDK2 与 ROS 2 Foxy 自带的 CycloneDDS ABI 不同,因此 g1_lowstate_udp_bridge 单独在 eth0 读取 rt/lowstate,只通过本机回环 UDP 把关节角交给 ROS 节点。

构建与启动

首次构建:

cd /home/unitree/uinitree_fast_lio_nav2
./build.sh

开始建图:

./run_mapping.sh

开始导航:

./run_navigation.sh

浏览器打开脚本打印的 http://<G1-Wi-Fi-IP>:8080;rosbridge 默认监听 ws://<G1-Wi-Fi-IP>:9090

PCD 地图与 Nav2 导航

导航链路如下:

所选 PCD ──PCL 地面 RANSAC + OctoMap 投影──> map.pgm/map.yaml ──> /map
/cloud_registered_body ──base_nav + 地面相对结构高度切片(8 m)──> /scan_localization
/map + /scan_localization + FAST-LIO odom ──Nav2 AMCL(omnidirectional)──> map→odom TF
/map ──static_layer + inflation_layer──> Global Costmap ──NavFn──> 全局路径
/cloud_registered_body ──base_nav + PCL 实时地面/本体过滤──> /cloud_obstacles
  └─ pointcloud_to_laserscan ──> /scan
  └─ obstacle_layer + inflation_layer ──DWB──> Local Costmap / 局部避障
Nav2 /cmd_vel ──安全门 + 限速 + 300 ms watchdog──> Unitree SDK2 G1 LocoClient

网页严格执行以下顺序,未完成的按钮不可用:

  1. 选择 maps/ 下保存的 PCD,设置地面/障碍高度后生成并加载精细二维地图。
  2. 在 Canvas 上按住并拖拽,指定机器人初始位置和朝向;等待官方 Nav2 AMCL 输出稳定。
  3. 人工确认机器人图标与实际环境一致,再开启 G1 运动安全门。
  4. 在 Canvas 上拖拽目标位置和朝向并发送,Nav2 同时执行全局路径与局部避障。
  5. “取消/急停”会取消 action 并立即关闭运动安全门;点云、里程计或导航中的定位超过 1.5 s 未更新也会自动关闭。AMCL 位姿跳变或协方差连续超限同样会取消 action 并关闭运动门。

首次启用真机控制时,先用宇树官方遥控器/应用让 G1 进入可行走的高层站立平衡模式,并由一人手持实体急停;本项目不会自动执行 StandUp 或切换 FSM。启动导航、加载地图和重定位后,先用可移动障碍验证 Local Costmap 能在约 1 秒内出现并消失,再点击“启用 G1 运动安全门”。第一次只发送前方 0.5–1.0 m 的短目标,随时准备按网页“停止/取消导航”和实体急停。运动门打开只允许 /cmd_vel 进入 SDK2,机器人实际速度仍由限速和 300 ms watchdog 约束。

默认地图是 cf.pcd,转换结果位于 maps/generated/cf。当前自动分析结果为:原始范围 x=[-8.651,19.220] my=[-10.332,12.255] mz=[-2.372,5.091] m,地面平面在原点约为 z=-1.272 m;精细地图为 964×7880.03 m/cell,障碍轮廓半径 0.04 m、地面补洞半径 0.15 m。PGM 使用白色可通行、黑色占据、灰色未知,未知格不会被 Nav2 当成自由空间;机器人安全距离仍由 Nav2 inflation layer 独立处理。

需要在真机低速测试前确认的参数:

  • PCD 障碍高度切片:地面以上 0.15–1.80 m,地面带宽 0.15 m
  • 实时障碍物按每帧 PCL RANSAC 地面平面计算,与离线地图统一保留地面以上 0.15–1.80 m,并过滤 pelvis 周围 0.60 m 的机器人本体区域;不再使用会把倾斜地面误认为障碍物的固定 Z 切片。Local Costmap 是机器人周围 8×8 m 的滚动窗口:实时 /scan 最远 4.0 m3.5 m 内标障碍、4.0 m 内射线清障;inf_is_valid=true 使移走物体后的无回波射线能够删除旧障碍,Local Costmap 与网页位图均按最高约 8 Hz 更新,远距离结构只来自静态 Global Costmap。
  • G1 足迹:约 0.62×0.50 m,全局/局部膨胀半径 0.65 m;手臂姿态变化后应按最大包络调整。
  • AMCL 是二维定位,不需要填写 pelvis 高度;pelvis 的真实三维高度和姿态继续由 FAST-LIO 与官方 URDF 在 base_nav→base_link 链中提供。AMCL、Nav2、Costmap 和两路 LaserScan 统一使用 yaw-only base_nav。定位与避障共享实时 PCL RANSAC 地面相对高度过滤,避免上坡地面被固定 Z 切片误认为墙体;/scan_localization 保留 8 m 内结构点供 AMCL 持续匹配,/scan 限制在 4 m 内供 Local Costmap 实时标记和清除障碍。Canvas 默认显示后者,并同时报告 8 m 定位扫描点数和静态地图命中率。
  • 最大命令:vx=0.35 m/svy=0.20 m/syaw=0.50 rad/s;首次测试应在围挡区域进一步降速。

导航与 AMCL 参数在 nav2_foxy_g1.yaml,完整启动文件是 g1_navigation.launch.py。切换 PCD 时 map_server 会装载新 YAML,随后启动一份全新的、未修改的官方 Foxy AMCL 二进制,避免旧粒子和 Foxy lifecycle 重载缺陷进入新地图。初始位姿后会持续调用官方 no-motion update 做扫描匹配,满足至少 5 次输出、近期位姿稳定、协方差和扫描点质量全部合格后才显示 READY;30 秒仍不收敛则拒绝开放运动门。Canvas 导航页提供 RViz 风格的 Displays 图层树、米制网格、平移/滚轮缩放、2D 初始位姿Nav2 Goal、Fixed Frame/位姿/雷达状态栏,以及独立局部雷达窗;拖拽初始位姿时,实时扫描会同步叠加到静态地图上辅助匹配墙角和走廊。

时间戳边界

宇树 LiDAR DDS 消息采用设备/发布端时间,本机实测其绝对时间约比 ROS 主机慢 7.4–7.5 s,但点云与内置 IMU 保留共同的源时间供 FAST-LIO 做帧内去畸变和紧耦合融合。导航不能直接使用这条旧时间链,因此本项目只在 FAST-LIO 输出边界把 /Odometry_baseodom→base_nav/cloud_nav 和后续两路 LaserScan 重打为 ROS 当前时间;不会改写 FAST-LIO 输入消息。/Odometry_base.twist 由连续 yaw-only 导航位姿差分并低通生成,不再向 DWB 固定报告零速度。

单台 Mid-360 与其内置 IMU不需要为了 FAST-LIO 先增加 GPS 时钟盒。若以后需要多雷达、多相机或绝对 UTC 的亚毫秒硬同步,Mid-360 官方协议支持 IEEE 1588v2 PTP/gPTP,也支持 GPS/PPS;这属于传感器硬同步的升级项,不能代替 IMU 零偏、外参、重力初始化和振动隔离标定。

脚本会强制 ROS2/CycloneDDS 在 eth0 接收宇树数据,同时打印 Wi-Fi Viser URL。在同一 Wi-Fi 局域网内的远程电脑浏览器打开该 URL。端口已经监听所有 IPv4 接口;如果系统以后启用 UFW,还需允许 8080/tcp

可覆盖启动参数,例如:

./run_mapping.sh viser_port:=8081 map_output:=/home/unitree/maps/room.pcd

Viser 与 RViz 的对应关系

Viser 不拼接点云,也不修改 FAST-LIO 位姿:

  • 黄色“当前帧”对应 RViz 的 /cloud_registered
  • 彩色“全局地图”对应 RViz 的 /Laser_map,在建图过程中持续扩展。
  • 机器人坐标轴和轨迹来自腰部 /Odometry_base
  • 实时网页层以 2 Hz 渲染,使用 0.10 m 体素并限制在 25 万点;这些限制只节省 Jetson 到远程浏览器之间的 Wi-Fi/WebSocket 带宽。
  • 点击“保存实时建图层并渐进显示最终 PCD”会把 /Laser_map 的完整底层点云保存下来,随后每批加载 5 万点,直到同一页面显示最终地图的全部点。
  • 点击“返回实时全局地图”可重新查看正在增长的轻量实时层。

停止建图时按一次 Ctrl-C。FAST-LIO 也会把完整地图写到:

/home/unitree/uinitree_fast_lio_nav2/maps/fastlio_map.pcd

也可从命令行在线保存:

source /opt/ros/foxy/setup.bash
source install/setup.bash
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export CYCLONEDDS_URI=/home/unitree/cyclonedds_ws/cyclonedds_eth0.xml
ros2 service call /map_save std_srvs/srv/Trigger '{}'

默认不会再把每一个 10 Hz 注册帧重复追加到最终 PCD。若科研时确实需要保留逐帧高密度档案,可将 pcd_save.registered_frames_archive 改为 true;此模式会快速增加内存和文件大小,不用于 Viser 的常规最终地图。

数据检查

如果 FAST-LIO 没有输出,先确认宇树官方服务:

source /opt/ros/foxy/setup.bash
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export CYCLONEDDS_URI=/home/unitree/cyclonedds_ws/cyclonedds_eth0.xml
ros2 topic list -t | grep utlidar
ros2 topic hz /utlidar/cloud_livox_mid360
ros2 topic hz /utlidar/imu_livox_mid360

正常情况下,Mid-360 点云约 10 Hz,IMU 约 200 Hz。网页打不开时检查 ip -4 addr show wlan0、远程主机是否在同一 Wi-Fi,以及 ss -ltn | grep 8080

算法边界

当前 baseline 使用 Mid-360 点云和雷达内置 IMU,由 FAST-LIO 输出 /Odometry,再经官方腰部/Mid360 URDF 链生成 /Odometry_base。腰关节只用于刚体坐标换算,不作为 FAST-LIO 观测;腿部、足端接触和足端里程计暂不参与。

FAST-LIO 本身是紧耦合激光惯性里程计和增量 scan-to-map,不包含回环检测或全局位姿图优化。因此重访区域可能仍有累计漂移。若后续需要回环,应在保持本 baseline 前端的基础上另接回环/图优化后端,并让 Viser显示后端校正后的地图;当前实现不会用网页端的累计逻辑伪装成闭环。

上游来源

src/livox_ros_driver2 仅保留为该 ROS2 FAST-LIO 上游源码的 CustomMsg 编译依赖。本 baseline 的 launch 不会启动 Livox driver,运行数据来自宇树官方服务。

About

宇树人形机器人完成推车和实机部署!完成slam建图和高层规划底层执行,实现高精度的导航系统

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages