【unitree】go2 ros开发指南+slam规划
go2 ros开发学习过程
个人github仓库,欢迎star:
https://github.com/huaianxizhilang/unitree_ros_dev_demo
b站demo视频:(csdn越来越废了,视频链接也给封禁了,后面不想用csdn了)
b站go2开发demo视频
1 基础环境配置
如下这里记得换成humble

编译cyclone dds(如果使用Humble,此步骤可跳过,这里我使用的是humble,所以跳过。但是按照B站教程还是得编译
先去bashrc将这个source注释掉,后面再打开
换成humble

设置网络配置,这个是我之前设置的本机地址,unitree的地址为192.168.123.161
登陆发现,此时的网口号
如下改成humble和自己的网口信息

在bashrc里面添加这个source文件这样,不用每次source
上面都做好了之后,按照官方教程处理,无法处理,得不到toplic
将防火墙关闭了不行
在其他博客里面看到了这个,于是远程ssh到unitree go2上面,然后可以看到

此时在unitree本地机子上面是有的 。
注意这里 unitree上面的环境变量,不小心添上去的,后续要学会自己删除。

不知道是不是这个原因,再使用wifi连接下看看,按照这个来搞还是不行
最后参考这个时间点的博客,参考这个搞出来到,就是这个2个原因,记得setup.bash url后面不要带上空格,本地网要写对。同时ros2 topic list --no-daemon


2 实际开发过程
下面均为原课程编号
1.2.4 toptic数据及rivz2可视化
unitree l1雷达可视化
如下显示L1 雷达数据
ros2 topic echo /utlidar/cloud --no-arr --no-daemon
rviz2 教程具体看rviz2视频
1.2.5 编译测试例程
按照如下编译,会有报错

参考doubao将这个ut_errror.hpp文件润色了下,但是还是会报std warning,告警信息
#pragma once
#include <cstdint>
#include "rclcpp/rclcpp.hpp" // 确保包含RCLCPP头文件(RCLCPP_ERROR依赖)
// 定义错误码和对应的描述
#define UT_DECL_ERR(name, code, desc) \
const int32_t name = code; \
const constexpr char* name##_DESC = desc;
UT_DECL_ERR(UT_ROBOT_SUCCESS, 0, "success.")
UT_DECL_ERR(UT_ROBOT_TASK_TIMEOUT, -1, "task timeout.")
UT_DECL_ERR(UT_ROBOT_TASK_UNKNOWN_ERROR, -2, "task unknown error.")
// 修正后的错误打印宏(确保反斜杠后无空格,仅换行)
#define UT_PRINT_ERR(code, error) \
if ((code) == (error)) { \
RCLCPP_ERROR(this->get_logger(), "%s", error##_DESC); \
}
代办:./install/unitree_ros2_example/bin/read_motion_state sport_model
1.3.1 1.3.2 机器狗helloworld
过滤request话题,寻找需要发布的运动信息
ros2 topic list | grep -i request
四足狗运动的话题 /api/sport/request
查看接口格式:ros2 toptic info /api/sport/request
查看具体如何定义:ros2 interface show unitree_api/msg/Request
创建功能包:
ros2 pkg create go2_helloworld --build-type ament_cmake --dependencies rclcpp unitree_api
c++类
编写代码:
编写的时候报错,原因是找不到路径:
将路径写到里面就会包含了。
写好了一些代码,编译的时候没文件,需要在cmakelist里面添加相应的依赖和编译项

写好程序之后,编译,source 源文件,然后运行话题,就可以,注意如果没有连接go2端口,开机会爆如下的错:
代办:需要看下为什么,代码这样写,c++代码
python类
使用如下命令创建包:(记得结尾加上 node-name)
ros2 pkg create helloworld_py --build-type ament_python --dependencies rclpy unitree_api --node-name hello
写完之后编译,colcon build --packages-select helloworld_py
然后source源文件,source install/setup.bash ,然后ros2 run helloworld_py hello
代办:这里需要再执行下
2.1.1 高层状态获取
代办:这里需要再执行下
查看 sportmodestate ,这里可以看到不同频率的sportmodestate
ros2 topic list | grep -i sportmodestate
ros2 topic hz /lf/sportmodestate (低频)
ros2 topic hz /mf/sportmodestate(中频)
ros2 topic hz /sportmodestate(高频)
ros2 topic type /sportmodestate (看消息类型)
ros2 interface show unitree_go/msg/SportModeState (接口定义的具体数据结构)
ros2 topic echo /sportmodestate --no-arr (查看数据)
具体官方代码实现:
example/src/src/read_motion_state.cpp
如果需要执行的话,直接按照官方文档编译后在终端运行
./install/unitree_ros2_example/bin/read_motion_state
2.1.2 低层状态获取[INFO] [1762252280.016273967] [rviz]: Message Filter dropping message: frame ‘base_link’ at time 1762252245.246 for reason 'discarding message because the queue is full
代办:这里需要再执行下
ros2 topic list | grep -i lowstate
ros2 topic type /lowstate (看消息类型)
ros2 topic type /lf/lowstate (看消息类型)
ros2 topic hz /lowstate (低频)
ros2 topic hz /lf/lowstate (看消息类型)
ros2 interface show unitree_go/msg/LowState (接口定义的具体数据结构)
具体官方代码实现:
example/src/src/read_low_state.cpp
如果需要执行的话,直接按照官方文档编译后在终端运行
2.1.3 遥控器状态获取
代办:这里需要再执行下
ros2 topic list | grep -i wireless
ros2 topic type /wirelesscontroller (看消息类型)
剩下和之前的一样,有官方例子
2.2.1 运动控制
代办:这里需要再执行下
ros2 topic list | grep -i request
四足狗运动的话题 /api/sport/request
查看接口格式:ros2 toptic info /api/sport/request
查看具体如何定义:ros2 interface show unitree_api/msg/Request
剩下和之前的一样,有官方例子
可以 直接使用rqt 来进行发布,写上对应的toptic和角度 ,然后沟上就会自动发布话题
高层运动控制的完整例程位于:example/src/sport_mode_ctrl.cpp(这里我没找到)
2.2.2 电机控制
代办:这里需要再执行下
ros2 topic type /lowcmd (看消息类型)
运行地层控制服务之前,需确保app上面sport服务关闭

机器人架空之后,就可以按照下面的源码来进行处理
example/src/src/low_level_ctrl.cpp
恢复,时候,摆到阻尼状态,再到app恢复
3.1.1 键盘控制
这里由于控制比较简单,所以不写c++,写python程序
ros2 pkg create go2_teleop_ctrl_keyboard --build-type ament_python --dependencies rclpy unitree_api --node-name go2_teleop_ctrl_keyboard
python脚本里面,里面多了个子线程步骤,因为需要主线程等待操作
然后编译
ros2 run go2_teleop_ctrl_keyboard go2_teleop_ctrl_keyboard运行
代办:但是直接使用视频中的程序,停止之后无法恢复平衡站立

3.2.1 Twist消息转换
这个只能实现比较基础的转换,比如线速度和角速度转换
ros2 pkg create go2_twist_bridge --build-type ament_cmake --dependencies rclcpp geometry_msgs unitree_api --node-name twist_bridge
ros2 pkg create go2_twist_bridge_py --build-type ament_python --dependencies rclpy geometry_msgs unitree_api --node-name twist_bridge
在写这个代码之前,需要将/home/xzl/Project/unitree/unitree_ros2/example/src/include/nlohmann (我的unitree_ros2)目录下的这个include这个目录复制到当前功能包include目录下

python版本编写时候,注意导包不要忘记.
剩余流程差不多

注意使用ros2 原生的这种,使用按键不一样,同时这个速度会非常快,很容易撞倒
3.3.2 机器人模型可视化
注意的是这里为什么不用官方的,因为官方的下载下来之后,都是用的ros1,不适配ros2,所以必须要改造成ros2的。
https://github.com/unitreerobotics/unitree_ros/tree/master
按照教程将cmake和package写好之后,编译,source setup.bash

这里有个注意点,包名和官方的urdf要同统一,不然后续所有的urdf都要改
此时如果机器狗没开会报错:
如果机器狗开了,在终端执行就会这样
按照视频做到这三项,但是此时模型不完全对
另外要注意如果有如下错,可能是没source 环境setup.bash
注意上面只解决了go2本体的可视化,但是radar的扫描不显示,因为urdf官方中用的radar,但是ros topic话题中这个radar数据用的base是 utlidar_lidar

此时可以手动坐标系转换在shell3中加上这个,重映射
ros2 run tf2_ros static_transform_publisher --frame-id radar --child-frame-id utlidar_lidar

这里Launch文件为什么需要添加这个额外的参数控制,因为后续这个joint需要其他程序动态发布

3.4.2## 3.4 机器人驱动包 c++ 机器人驱动包 c++
五大功能:

上面的需求中,里程计和里程计相关的坐标变换,从sportmodel四足狗发布的话题里面取,关节状态从lowstate话题里面取,然后转换发布出去
这里补充一点:代码如果没有这个补充参数,发布的时候关节会不停地抖动,此时我们通过godriver重新发布了一个,就不应该使用默认的如下代码红框发布的这个了(就是之前课程讲的四个足半趴状态),所以这里要将其关了

创建对应的包
ros2 pkg create go2_driver --build-type ament_cmake --dependencies rclcpp unitree_go sensor_msgs tf2 tf2_ros geometry_msgs nav_msgs --node-name driver
ros2 pkg create go2_driver_py --build-type ament_python --dependencies rclpy unitree_go sensor_msgs tf2_ros geometry_msgs nav_msgs --node-name driver
这里可以自己添加rviz配置,这样每次不用自己手动修改rviz配置,可以在riviz目录下面创建display.rviz
另外launch文件中增加了条件,所以可以使用
ros2 launch go2_driver driver.launch.py use_rviz:=false来不启动rviz
此时想保存rviz配置,报错

那为什么将rviz2中的Fixed Frame 设置为 odom后,会报以下错误,但是将Fixed Frame 设置为base后雷达点云又显示正常,
【INFO】 【1752416695.855021906】 【rviz】: Message Filter dropping message: frame ‘utlidar_lidar’ at time 1740213107.629 for reason ‘the timestamp on the message is earlier than all the data in the transform cache’
doubao解释:
这个问题的核心原因是 不同坐标系(odom 和 base)的 TF 变换缓存中,时间戳与雷达点云时间戳不匹配,具体分析如下:
1. 为什么 Fixed Frame 设为 base 时正常?
base是机器人的基坐标系(通常与机器人底盘刚性连接),而激光雷达的坐标系utlidar_lidar与base之间的变换通常是 静态 TF(通过static_transform_publisher发布,比如base → radar → utlidar_lidar的固定关系)。- 静态 TF 的特点是:一旦发布,会被 TF 缓存长期保存(默认缓存时间较长),且时间戳通常会被强制设为当前时间(如果加了
--use-current-time参数)。 - 因此,当
Fixed Frame为base时,RViz 只需要base到utlidar_lidar的静态 TF 变换,而这个变换的时间戳始终是“有效”的(与点云时间戳的偏差较小,或静态 TF 被长期缓存),所以点云能正常显示。
2. 为什么 Fixed Frame 设为 odom 时出错?
odom是里程计坐标系,它与base之间的变换是 动态 TF(由里程计节点实时发布,比如odom → base的变换,随机器人运动不断更新)。- 动态 TF 的时间戳是 实时更新的(与机器人运动同步),且 TF 缓存默认只保留最近一段时间的数据(比如几秒到十几秒)。
- 当雷达点云的时间戳 远早于
odom → base动态 TF 的时间戳 时(比如点云时间戳是 1740213107,而odom到base的 TF 时间戳已经是 1752416695),RViz 无法在 TF 缓存中找到“点云时间戳对应的odom → base → utlidar_lidar完整变换链”,因此会报错并丢弃点云。
根本原因总结
- 雷达点云的时间戳 严重滞后于系统当前时间(从报错看,点云时间戳 1740213107 比 RViz 运行时间 1752416695 早了很久,可能是雷达内部时钟未同步或驱动时间戳设置错误)。
- 当
Fixed Frame为odom时,必须依赖 动态更新的odom → base变换,而这个变换的时间戳是“最新的”,与滞后的点云时间戳无法匹配。 - 当
Fixed Frame为base时,仅依赖 静态的base → utlidar_lidar变换,静态 TF 时间戳通常被强制为当前时间,因此即使点云滞后,也能找到匹配的变换。
解决方法(针对真实环境)
1. 优先解决雷达时间戳滞后问题
- 检查雷达驱动时间戳:确保雷达点云的
header.stamp使用 系统当前时间(而非雷达内部时钟,可能未同步)。
在雷达驱动代码中强制覆盖时间戳:// 发布点云前,用ROS节点的当前时间更新时间戳 cloud_msg.header.stamp = this->now(); // this 是当前ROS节点 pointcloud_pub->publish(cloud_msg); - 确保系统时间同步:通过 NTP 同步所有设备(雷达、机器人主控、上位机)的系统时间,避免时间戳偏差过大(具体操作见前文)。
2. 优化动态 TF 的缓存策略
- 增加动态 TF(
odom → base)的发布频率,确保 TF 缓存中始终有“较新”的变换数据。 - 在 RViz 中调大
TF Cache Time(例如设为 60s),允许缓存更早的动态 TF 变换,适应轻微的时间戳滞后。
操作:RViz →Displays→Global Options→TF Cache Time→ 改为 60.0。
3. 验证 TF 变换链的完整性
通过 ros2 topic echo /tf 检查:
odom → base的变换是否存在,且时间戳是否为 当前时间(与系统时间date对比,偏差应小于 1s)。base → radar → utlidar_lidar的静态变换是否存在,时间戳是否正常(建议加--use-current-time参数)。
通过以上步骤,先解决雷达时间戳滞后问题,再确保 TF 变换链的时间戳匹配,即可在 Fixed Frame 设为 odom 时正常显示点云。
这里我没使用上面的解决步骤来解决rviz的可视化,使用unitree官方的其他话题来显示点云信息。
具体配置如下:



搞好之后保存到这里,重新编译就可以,后面就不用单独再开rviz了
代办:
但是时间长了之后还是会报错,说帧数饱满了

[INFO] [1762252280.016273967] [rviz]: Message Filter dropping message: frame ‘base_link’ at time 1762252245.246 for reason 'discarding message because the queue is full
ros2 launch go2_driver driver.launch.py 启动即可同步相应姿态数据
3.4.3 机器人驱动包 python
未看呢,后续更新
4 通信例程
为了实现topic,service,action三种级别代码的编写

未看呢,后续更新
5 go2_ros2_sdk 非官方sdk开发使用
依赖安装好了,直接编译会报错:

将源代码文件,红框这里改成4个空格子,保持一致

按照文档连接报错:
原因是foxglove_bridge没装,ros-humble-slam-toolbox/ros-humble-nav2-bringup,这里出现这种原因就是
rosdep install --from-paths src --ignore-src -r -y 这个命令当时没在src上级目录执行安装
此时可以进行webrtc开发
其他博客,发现要使用cyclonedds进行开发,需升级,具体见其他博客社区legion1581作者,2024/11/21 20:03:14发言,需启用二次开发才行

代办:这个社区里面有foxglove和另外一款可视化工具非常不错。
社区讲解的如何保存地图:
具体建图步骤可以看这个
https://www.hiascend.com/document/detail/zh/Atlas200IDKA2DeveloperKit/23.0.RC2/Application%20Cases/oanvadg/inoaadg_0016.html
https://github.com/SteveMacenski/slam_toolbox
这里可以添加插件

成功建图

更多推荐

所有评论(0)