ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ROS 1 Noetic实战入门:从Ubuntu安装到手写发布订阅节点

ROS 1 Noetic实战入门:从Ubuntu安装到手写发布订阅节点 很多朋友私信问我ROS怎么入门我太懂这种心情了——当年自己装第一个ROS环境光是装依赖就折腾了两天最后还不知道装成功没有。这篇是ROS快速入门的第一篇目标很纯粹从零开始在Ubuntu上装好ROS 1 Noetic跑通小乌龟例程亲手写一个发布/订阅节点把ROS最核心的通信机制真正搞明白。这篇内容我尽量按“别人踩过的坑就是你的捷径”的思路来写所有命令你都可以直接复制粘贴所有坑我都提前标出来。不管你是准备做机械臂、做小车导航还是纯粹想搞懂ROS这个东西到底是怎么跑起来的这篇都适用。1. 别急着敲命令先搞清楚ROS到底是个啥1.1 ROS不是操作系统而是一套“机器人通信框架”很多人第一次听到“ROS”这个名字下意识以为它是个系统像Windows或者Ubuntu那样装完就能用。实际上ROS是运行在Linux之上的一个软件框架它的核心作用是把机器人开发里的各种模块——摄像头驱动、激光雷达驱动、导航算法、机械臂控制——连接起来让它们能互相通信。你可以把ROS理解成一个公司里的“后勤协调系统”各部门各干各的活摄像头负责看、电机负责动、算法负责想但它们怎么知道彼此干了啥这就需要一个统一的沟通规则。ROS就干这个事它规定了通信的格式、通信的渠道、通信的时序让每个模块只需要关心自己的活并通过标准接口和别人对接。这种设计带来的最直接好处是“复用”。别人写好的激光雷达驱动你拿过来直接用别人调好的路径规划包不需要动源码就能接到你的小车上。这也是为什么ROS能在机器人领域快速普及它本质上解决的是“重复造轮子”的问题。1.2 版本到底怎么选ROS 1 Noetic还是ROS 2 Humble这是新手问得最多的问题。我的建议非常直接学习入门用ROS 1 Noetic别一上来就碰ROS 2。原因有三点ROS 1的教程资料最全你踩过的坑几乎都有人踩过搜索引擎一搜全是对应的解决方案。ROS 1的核心概念节点、话题、服务在ROS 2里依然延续先把这套通信模型吃透再学ROS 2的DDS机制会轻松很多。学校、老项目、工业现场大量存量代码都基于ROS 1你会用ROS 1至少能看懂大多数开源机器人项目。版本和Ubuntu系统的对应关系非常严格不能随便配。ROS 1 Noetic对应Ubuntu 20.04ROS 2 Humble对应Ubuntu 22.04ROS 2 Foxy对应Ubuntu 20.04。这里多说一句不少人问我Ubuntu 24.04能不能装ROS目前ROS 2 Jazzy支持24.04但ROS 1在24.04上基本告别了。如果你要学ROS 1老老实实装Ubuntu 20.04。ROS版本对应Ubuntu版本支持状态适合谁ROS 1 NoeticUbuntu 20.04停止维护但资料极多入门学习、老项目维护ROS 2 FoxyUbuntu 20.04已停止维护过渡期学习ROS 2 HumbleUbuntu 22.04长期支持新项目开发、深入学习2. 安装环境选型虚拟机、双系统还是Docker2.1 三种方案实测对比硬件条件允许的话我推荐双系统性能最好但如果你手头只有一台Windows电脑又想快速把ROS跑起来虚拟机完全够用。我自己的学习经历就是从VMware虚拟机开始的小乌龟、Gazebo仿真、RVIZ可视化全都能跑只是偶尔会有点卡。三种方案的对比我直接给结论双系统性能最好适合长期搞机器人开发但安装时需要分区、引导配置对新手不太友好万一搞砸了还可能影响原有系统。虚拟机VMware/VirtualBox推荐Vware性能和稳定性都更好。分配4核CPU、4GB内存、60GB硬盘就可以流畅运行ROS 1 Noetic。优点是随时快照装坏了回滚就行。Docker适合有Linux基础的开发者镜像拉下来就能用但不适合图形界面交互多的场景小乌龟这种GUI程序要额外配置显示转发。2.2 Ubuntu 20.04安装后的关键设置如果你已经在虚拟机里装好了Ubuntu 20.04建议先做三件事再装ROS第一更换软件源。默认源在国外下载速度会让你怀疑人生。打开“软件和更新”把下载服务器换成清华源或阿里源然后在终端执行sudo apt update刷新索引。第二确认系统语言。最好保持英文环境如果已经是中文也没关系但终端里的报错信息如果你看不懂英文建议临时用export LANGen_US切换到英文看报错排查问题会方便很多。第三确认网络连接稳定。ROS安装过程要下载大量依赖包断网会导致安装到一半失败尤其是rosdep步骤对网络要求比较高。2.3 一键安装脚本和手动安装怎么选ROS安装有两种路径手动按官方步骤来或者用社区的一键安装脚本。我的态度很明确新手直接用一键脚本省下的时间用来学核心概念性价比最高。手动安装步骤本身不复杂无非是添加ROS软件源、添加密钥、apt install安装、初始化rosdep、配置环境变量。但问题出在细节上国内网络访问ROS官方源经常超时密钥添加可能失败rosdep初始化依赖外网这些会让新手卡得死去活来。一键脚本本质上是把这些步骤自动化了它还是用官方源安装但会自动换源、自动处理密钥、自动配置环境全程只需要几分钟。社区里用得比较多的是“鱼香ROS一键安装”这个脚本做得比较省心命令一行就能跑完。它的原理并不神秘检测系统版本、配置软件源为国内镜像、安装ROS本体、初始化rosdep、写入环境变量。你如果会手动安装再看这个脚本会觉得它就是把那些命令串起来而已。3. 安装完成后的头等大事环境配置和验证3.1 为什么每次打开终端都要source安装成功后你会看到提示要执行source /opt/ros/noetic/setup.bash。这行命令的作用是把ROS相关的环境变量加载到当前终端里比如roscore、rosrun这些命令的路径。如果你不source终端根本找不到这些命令一输入就会报command not found。为了避免每次开终端都要手动敲最好把这行命令写进~/.bashrc文件里这样每次打开终端就会自动加载。输入以下命令echo source /opt/ros/noetic/setup.bash ~/.bashrc source ~/.bashrc有人说“我明明source了还是找不到命令”大概率是.bashrc文件里重复写了两行或者后写的覆盖了先写的。打开~/.bashrc检查一下确保只有一行ROS的环境变量配置。3.2 运行小乌龟例程验证安装环境配置好之后最直接的验证方法是跑小乌龟模拟器。打开三个终端分别执行roscorerosrun turtlesim turtlesim_noderosrun turtlesim turtle_teleop_key第三个终端里可以用方向键控制小乌龟移动。如果乌龟能动说明ROS安装成功、节点通信正常。我第一次跑通这个例程的时候虽然只是一个简单的小窗口但那种“通了”的感觉确实很爽。这里额外提一句roscore是ROS 1的“启动总开关”它负责启动Master节点所有其他节点都要依赖它才能通信。如果你运行rosrun时报错Couldnt find master说明roscore没起来。3.3 常用命令速查先背熟这几个命令作用示例roscore启动ROS Masterroscorerosrun 包名 节点名运行功能包里的节点rosrun turtlesim turtlesim_noderoslaunch 包名 launch文件批量启动多个节点roslaunch turtle_tf turtle_tf_demo.launchrosnode list查看当前所有节点rosnode listrostopic list查看当前所有话题rostopic listrostopic echo 话题名查看话题上发布的数据rostopic echo /turtle1/cmd_velrqt_graph图形化显示节点通信关系rqt_graph4. ROS核心通信机制节点、话题、服务4.1 节点和Master谁在说话谁在管联系ROS里运行的一个个程序叫“节点”每个节点只负责一件事。比如小乌龟例程里turtlesim_node负责显示画面和处理运动turtle_teleop_key负责读取键盘输入。它们之间怎么联系靠Master。Master的作用类似于“电话号码簿”每个节点启动时向Master注册自己告诉Master“我叫什么名字、我能提供什么服务、我想订阅什么数据”。当一个节点想给另一个节点发数据时先问Master对方在哪然后两者直接建立连接。roscore启动的就是这个Master。这个设计最大的好处是解耦。发布数据的节点不需要知道谁在接收接收数据的节点也不关心谁在发布。你后续写复杂系统时加一个传感器驱动只需要发布数据导航模块自动就能收到不用改导航的代码。4.2 话题Topic广播电台模型话题是ROS最常用的通信方式适合持续、单向的数据流比如激光雷达不断扫描数据、摄像头持续输出图像、速度指令不断发给底盘。这种“一直发、多人收”的模式我常拿广播电台来类比电台不管谁在听只管按时广播听众打开收音机就能收到不用跟电台建立专门的通话。举个例子小乌龟例程里键盘控制节点把速度消息发布到/turtle1/cmd_vel这个话题上龟仿真节点订阅这个话题读到消息就更新乌龟的位置。你在终端里输入rostopic echo /turtle1/cmd_vel然后去第三个终端按方向键就能看到源源不断的数据流。数据格式是Twist类型包含线速度和角速度。话题的关键特点是订阅和发布完全异步。发布者按自己的节奏发订阅者按自己的节奏收两边不用互相等待。这种机制特别适合传感器数据这种实时性要求高的场景。4.3 服务Service打电话模式话题适合持续的数据流但有些交互是“请求-应答”型。比如你让小乌龟重置位置、你调用某个节点去计算一个结果、你请求摄像头拍一张照片并返回图片数据这种场景用服务。服务是典型的“打电话”模式发起方拿起电话拨号对方接通后说话然后挂断。整个对话是同步的请求方必须等接收方处理完才能继续。服务由三部分组成服务名称、请求数据格式、响应数据格式。小乌龟例程里自带一个演示服务。新开一个终端执行rosservice call /spawn 2.0 2.0 1.0 turtle2这行命令的意思是在(2.0, 2.0)位置、方向角1.0弧度处生成一只名字叫turtle2的新乌龟。如果你执行成功画面上会出现第二只乌龟。这就是服务通信客户端发送一个请求服务端执行操作并返回结果。4.4 用rqt_graph直观理解通信关系光看文字可能还是有点抽象这里推荐大家用rqt_graph。在终端输入rqt_graph会弹出一个图形界面里面用圆形表示节点用箭头表示话题或服务的通信方向。等小乌龟例程跑着的时候打开看你能清楚看到键盘节点和乌龟仿真节点之间的连线。这个工具我建议新手多看看它能把ROS的通信关系可视化对于理解整个系统的数据流非常有帮助。5. 从零手写一个发布/订阅节点5.1 创建catkin工作空间小乌龟只是验证环境真正的学习从自己写节点开始。ROS 1用catkin构建系统管理代码第一件事是创建工作空间。这个工作空间就是你的代码基地后面所有功能包都放在里面。mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src catkin_init_workspace cd ~/catkin_ws catkin_make执行catkin_make后会出现build和devel两个文件夹这说明编译系统正常了。然后source一下工作空间的setup文件echo source ~/catkin_ws/devel/setup.bash ~/.bashrc source ~/.bashrc这一步很重要很多人写完代码一编译就“找不到包”原因就是没source工作空间的环境变量。注意顺序先source ROS本体环境再source工作空间环境后者会覆盖前者的部分路径设置。5.2 创建功能包并编写代码一个功能包是ROS中代码组织的基本单位。创建功能包的命令是cd ~/catkin_ws/src catkin_create_pkg beginner_tutorials roscpp rospy std_msgs这行命令创建名为beginner_tutorials的功能包同时声明依赖roscppC客户端库、rospyPython客户端库、std_msgs标准消息类型。依赖声明会直接写入功能包的package.xml和CMakeLists.txt编译时按这些依赖配置头文件和库路径。然后我们写一个最简单的发布者节点。在beginner_tutorials的src文件夹下创建talker.cpp文件#include ros/ros.h #include std_msgs/String.h #include sstream int main(int argc, char **argv) { ros::init(argc, argv, talker); ros::NodeHandle n; ros::Publisher chatter_pub n.advertisestd_msgs::String(chatter, 1000); ros::Rate loop_rate(10); int count 0; while (ros::ok()) { std_msgs::String msg; std::stringstream ss; ss hello world count; msg.data ss.str(); chatter_pub.publish(msg); ros::spinOnce(); loop_rate.sleep(); count; } return 0; }这段代码的逻辑很简单初始化节点在chatter话题上发布字符串消息每秒发10条。n.advertise的第二个参数1000是消息队列长度如果订阅者处理不过来消息会先在队列里排队避免丢失。订阅者写在同一个目录下文件名listener.cpp#include ros/ros.h #include std_msgs/String.h void chatterCallback(const std_msgs::String::ConstPtr msg) { ROS_INFO(I heard: [%s], msg-data.c_str()); } int main(int argc, char **argv) { ros::init(argc, argv, listener); ros::NodeHandle n; ros::Subscriber sub n.subscribe(chatter, 1000, chatterCallback); ros::spin(); return 0; }回调函数chatterCallback是订阅者的核心每收到一条消息就打印一次内容。ros::spin()的含义是让程序进入等待状态把控制权交给ROS一旦有消息到达就触发回调。5.3 修改CMakeLists.txt编译配置代码写完了但CMakeLists.txt还不知道要编译这两个文件。找到功能包里的CMakeLists.txt取消注释并修改以下几行add_executable(talker src/talker.cpp) target_link_libraries(talker ${catkin_LIBRARIES}) add_executable(listener src/listener.cpp) target_link_libraries(listener ${catkin_LIBRARIES})没有这几行catkin_make会编译通过但不会生成可执行文件运行时提示找不到程序。然后回到工作空间根目录编译cd ~/catkin_ws catkin_make编译完成后运行验证。开三个终端分别启动roscore、talker、listenerroscoresource ~/catkin_ws/devel/setup.bash rosrun beginner_tutorials talkersource ~/catkin_ws/devel/setup.bash rosrun beginner_tutorials listener如果listener终端持续打印I heard: hello world ...说明你自己的第一个通信节点跑通了。这一步走通之后ROS的大门就算真正打开了。6. 新手最容易踩的坑问题排查实录6.1 环境变量没生效天天“command not found”症状是rosrun、roscore这些命令输入后提示找不到。排查思路是先检查/opt/ros/noetic/bin目录下有没有这些可执行文件如果有就说明ROS本体装成功了问题出在环境变量没加载。执行echo $ROS_DISTRO看看输出是不是noetic如果是空白的说明环境变量没生效。这时候重新执行一次source /opt/ros/noetic/setup.bash再把那行写进~/.bashrc。6.2 rosdep初始化卡死或超时rosdep是ROS的依赖管理工具用于在编译功能包时自动安装依赖库。但官方源在国外初始化经常卡住。一键安装脚本通常已经处理了这个问题它的做法是修改rosdep的源地址为国内镜像。如果你已经安装完了ROS只是后面编译自己的功能包时遇到依赖问题可以检查/etc/ros/rosdep/sources.list.d/目录下的源配置是不是国内可用源。6.3 “Package not found”但包明明存在编译或者在rosrun时提示找不到功能包通常有几种原因工作空间没编译成功、没source工作空间的setup文件、包名拼写错误。先用rospack find 包名测试一下ROS能不能找到这个包如果找不到八成是环境变量问题。重新执行catkin_make并source后一般能解决。6.4 VM虚拟机跑ROS特别卡风扇狂转小乌龟还好一跑Gazebo就卡得动不了这个我在虚拟机里深有体会。建议给虚拟机至少分配4GB内存和2GB显存如果用的是VMware可以在虚拟机设置里调整显存大小关闭Ubuntu的动画效果。不过如果是复杂的Gazebo仿真还是建议实体机装双系统硬件性能决定体验上限。6.5 软件源更新时报错仓库没有Release文件安装ROS时如果提示E: 仓库 http://packages.ros.org/ros/ubuntu focal Release 没有Release文件说明软件源配置有问题。检查/etc/apt/sources.list.d/ros-latest.list文件里的地址是否正确并确认Ubuntu版本代号是否写对了。Ubuntu 20.04的代号是focal这个必须严格对应。最后分享一点我的体会讲了这么多其实ROS入门最大的障碍不是技术而是“信息过载”。网上的教程五花八门版本混杂今天跟着一篇装Halfzone明天又看到一篇让装ROS 2折腾两周连环境都没搞定热情就没了。我自己的建议是认准一套方案死磕到底先把小乌龟跑通再模仿着写一个发布订阅节点后面的一切都会顺畅起来。这篇是基础篇的第一篇按照这个流程走完你已经有能力看懂大多数ROS基础教程了。下一篇我会接着写launch文件的使用、常用传感器仿真、RVIZ可视化等内容一步步把整个机器人开发链路串起来。
返回列表