ARTICLE DETAIL

资讯详情

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

从零搭建ROS2开发环境:Ubuntu 22.04虚拟机+Humble双语言HelloWorld

从零搭建ROS2开发环境:Ubuntu 22.04虚拟机+Humble双语言HelloWorld 1. 从零开始前的整体思路为什么虚拟机、如何选版本、需要踩平哪些坑先讲个事实我被ROS2环境折腾过太多次了前前后后帮着带过几十个刚入门的同学配环境几乎每次都有人卡在最前面的系统安装上。有的装在物理机上结果把Windows引导搞坏了有的装到一半断电虚了还有的在Ubuntu 24.04上硬装ROS2 Humble最后依赖冲突到心态爆炸。说实话如果你真的想“从零”学会ROS2开发第一步不是装ROS2而是把整个环境方案想清楚——这条路走对了后面全是流水线走错了你会在各种莫名其妙的报错里消耗掉所有热情。这篇内容适合谁我觉得主要是三类人第一类是完全没有Linux经验、连分区和终端是什么都不太清楚的小白第二类是被ROS1和ROS2混杂信息搞晕、不知道该听哪份教程的同学第三类是马上要交课程设计或比赛任务、需要快速跑通一个最小Demo的开发者。如果你是这三类中的任何一种这篇内容能帮你很稳地在3到4小时内走完“Ubuntu虚拟机 ROS2 Humble Python/C双语言HelloWorld VSCode环境配置”整条链路中间每一步我都会告诉你为什么这么做、坑在哪里、以及崩溃时怎么排查。先说方案选型。为什么我坚持推荐虚拟机而不是直接装双系统因为我见过太多人为了“性能好一点”选了双系统结果grub引导出问题、驱动冲突、重装系统才能修复代价特别大。虚拟机确实会损失一部分性能但对于学习阶段跑ROS2节点、小规模仿真、写HelloWorld级别的程序完全够用。更重要的是虚拟机有快照功能装坏了、配错了、依赖炸了一键回滚这对新手来说等于拥有了“后悔药”。等你真的入了门、确认要长跑机器人开发再去折腾物理机也不迟。虚拟机软件我推荐VMware Workstation Pro理由很实在它对个人用户已经免费而且虚拟化兼容性、USB设备透传、3D加速支持都更成熟比VirtualBox在跑Ubuntu桌面环境时明显更流畅。如果你用的是macOS或LinuxFusion和Workstation也不难找但本文按最常见的Windows宿主机来写。接下来是版本选型。ROS2有很多发行版它们的命名是字母序的Foxy、Galactic、Humble、Iron、Jazzy、Kilos……每个版本绑定特定的Ubuntu版本不能乱搭。我选的是Ubuntu 22.04 LTS ROS2 Humble原因有三第一Humble是LTS长期支持版本到2027年才停止维护学习周期内不会过期第二教程生态最完善你踩过的坑网上基本已经有答案第三也是最重要的Humble是目前绝大多数机器人公司和比赛平台在用的版本学完能直接迁移到实际项目。不建议新手去用Ubuntu 24.04 Jazzy因为Jazzy的教程和第三方库适配还不算丰富遇到问题只能自己啃源码招聘和实际项目里也还很少见到。在正式开始之前所有步骤的宏观顺序是这样下载Ubuntu ISO镜像 - 创建VMware虚拟机并安装系统 - 完成系统基础配置换源、输入法、虚拟机增强工具 - 安装ROS2 Humble - 创建ROS2工作空间并分别用Python和C写完Publisher/Subscriber - 安装VSCode并配置C/Python/ROS开发环境 - 测试一切正常后快照保存。这个顺序不是随便排的每一层都建立在上一层稳定运行的基础上强烈建议别跳步。2. Ubuntu 22.04安装实操镜像下载、虚拟机创建与初始化配置2.1 镜像下载别去官网傻等用国内源很多人一上来就跑ubuntu.com下载镜像结果速度慢到怀疑人生。其实Ubuntu镜像在国内有特别成熟的加速渠道我用的是清华开源软件镜像站地址是mirrors.tuna.tsinghua.edu.cn直接在“ubuntu-releases”目录下找22.04版本下载那个64-bit PC (AMD64) desktop image文件名一般是ubuntu-22.04.x-desktop-amd64.iso。阿里云镜像站mirrors.aliyun.com和中科大镜像站mirrors.ustc.edu.cn也都可以哪个顺手用哪个。下载完ISO别急着创建虚拟机先右键该文件点击“属性 - 校验和”或者用命令行算一下MD5/SHA256和官网页面上给出的校验值对比。这一步很多人忽略但如果镜像下载不完整装到一半系统直接崩浪费时间不说还找不出原因。我一般用PowerShell命令是Get-FileHash 文件路径 -Algorithm SHA256十几秒就能算完对比一致再继续干净利落。2.2 创建虚拟机内存、磁盘与虚拟化配置VMware新建虚拟机时选“自定义高级”这样可以精确控制每个参数。虚拟机硬件兼容性保持默认最高的Workstation版本就行。客户机操作系统选“Linux - Ubuntu 64位”之后进入关键硬件配置环节。内存和CPU的分配主要看你的宿主机资源。我自己的经验基准是宿主机有16GB内存就给虚拟机分配8GB有32GB内存就给12GB到16GB。ROS2跑起来后内存占用本来就高日常节点加上VSCode和浏览器4GB内存很容易捉襟见肘。不要贪心一次性把内存全给虚拟机否则宿主机卡死反而拖累开发。CPU方面至少给4核用8核更好编译C功能包时多核并行能省一大半时间。磁盘容量建议直接给80GB超出默认的20GB很多同学不理解为什么。其实Ubuntu系统本身占不到多少但ROS2桌面版安装加缓存会占好几个G后续你再装Gazebo仿真、各种驱动、编译过程中的中间文件20GB很快就满了。关键是VMware的磁盘是动态分配的就像你给项目申请了一个80GB的“预算上限”实际用多少占多少并不会一口气吃掉宿主机80GB空间所以给大点完全不用心疼。有个细节必须检查在“处理器”设置的“虚拟化引擎”里把“虚拟化 Intel VT-x/EPT 或 AMD-V/RVI”勾上。这个选项如果没开Ubuntu里跑一些需要硬件虚拟化的功能会报错而且整体性能会下降很严重。网络模式用默认的NAT就行。桥接和NAT的区别不是新手关注的重点现阶段NAT足够完成软件源访问、apt安装、ROS2多机通信这些所有开发需求。2.3 安装过程与分区建议启动虚拟机后选择“Install Ubuntu”进入安装向导。语言选English别急着选中文因为后边很多软件和命令行工具的报错信息英文搜索起来更精准。接下来键盘布局默认English (US) 即可不影响打字和输入法。分区这步是很多新手最容易害怕的地方但其实在虚拟机里非常安全。如果你完全没概念直接选“Erase disk and install Ubuntu”最省事——注意它擦的只是虚拟机虚拟出来那块盘不会碰你宿主机硬盘放心点就行。如果想稍微掌握一点主动权可以选择“Manual installation”手动分三个区/boot/efiEFI引导分区大小设512MB类型选EFI System Partition/根分区把剩余空间的大部分都给根分区至少60GB格式ext4swap交换分区内存8GB就分8GB内存16GB就分8GB不用太大虚拟机的内存和磁盘其实都不算瓶颈分区的核心目的只是让系统有足够的根空间安软件。剩下的一路Next就行创建一个用户名和密码建议用你将来SSH和sudo时也不会忘记的账号名比如ros2dev然后等待安装完成并重启。重启后进入桌面第一件事不是急着装软件而是先安装VMware Tools增强工具。在VMware窗口菜单栏点击“虚拟机 - 安装VMware Tools”Ubuntu桌面会自动挂载一个光盘镜像里面有个tar.gz包。把它解压到任意位置进目录执行sudo ./vmware-install.pl一路默认回车安装。完成后重启虚拟机你会发现在“查看 - 自动调整大小”之后分辨率能自动跟随窗口变化复制粘贴、文件拖拽也都好使了。这一小步对新手的体验提升极其明显我见过有人在没装Tools的小窗口里硬刷终端刷了一个小时真的没必要。另外强烈建议在装好系统第一步就做一次“虚拟机快照”。右键虚拟机标签 - 快照 - 拍摄快照命名成“Ubuntu-纯净系统”后面不管装ROS2还是配置环境翻车了一键恢复到这个绝对干净的状态比你费半天劲排查依赖问题开心多了。这是整个搭建过程里我最有价值的一个习惯。2.4 系统初始化换源、更新和输入法Ubuntu装完之后apt默认使用的是Ubuntu官方软件源国内访问非常不稳定下载速度可能只有几十KB/s。要换成国内源直接改配置文件/etc/apt/sources.list即可。在Ubuntu 22.04中默认的内容是以deb和deb-src开头的若干行。我习惯先备份再修改sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak sudo sed -i s/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g /etc/apt/sources.list sudo sed -i s/security.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g /etc/apt/sources.list sudo apt update sudo apt upgrade -y这几行命令做的事情就是把官方域名批量替换成清华源域名然后更新软件列表并升级所有现有软件。首次upgrade可能要下载几百MB但速度会比官方源快非常多。升级完成后建议再拍一个快照命名“Ubuntu-基础配置完成”这样你就有了两个高质量回滚点。搜狗输入法的安装很多入门同学都想要但对ROS2开发来说顺手装个中文输入法体验更好。Ubuntu 22.04装搜狗需要先安装fcitx框架sudo apt install fcitx-bin fcitx-table-wubi -y然后到搜狗官网下载对应Ubuntu 22.04的deb包用sudo dpkg -i安装如果缺依赖就执行sudo apt -f install修复。装完在“设置 - 区域与语言 - 输入源”里添加“汉语(智能拼音)”或者fcitx方案重启即可。这里我不建议花太多时间折腾输入法能用系统自带的中文拼音打个字就行核心竞争力是ROS2本身。3. ROS2 Humble安装从换源到跑通talker/listener3.1 安装方式怎么选官方源 vs 一键脚本ROS2的安装方式网上一搜一大把有官方二进制包安装、源码编译安装还有国内社区很火的“鱼香ROS一键安装”。我的态度很明确如果你能跟着步骤一步步来优先用官方二进制包安装。它不是最快的方式但它能让你理解ROS2安装过程中真正发生了哪些事情比如软件源配置、GPG密钥、环境变量source这些基础概念在后续开发中会反复出现。一键脚本的好处是快坏处是你对系统里发生了什么一无所知出问题时无从下手。不过我也理解有些网络环境确实卡在下载上所以本文会给出先用官方步骤、再给替代方案的做法。网上热搜词里频繁出现“鱼香ROS一键安装”这里我补充说明这类脚本本质上是把人肉输入的命令打包成自动化脚本确实方便但你在执行前最好去读一下脚本内容确认它到底往系统里装了什么、改了哪些文件。安全和可控性永远比方便重要至少我在带人入坑时更希望对方对每一步有掌控感。3.2 官方二进制包安装步骤ROS2 Humble官方支持的是Ubuntu 22.04Jammy第一步是确保系统的locale设置是支持UTF-8的否则后面部分工具打印中文或特殊字符时会出乱码sudo apt update sudo apt install locales sudo locale-gen en_US en_US.UTF-8 sudo update-locale LC_ALLen_US.UTF-8 LANGen_US.UTF-8 export LANGen_US.UTF-8然后开启Ubuntu Universe仓库它包含自由开源软件ROS2的很多依赖都在这sudo apt install software-properties-common sudo add-apt-repository universe接着添加ROS2的GPG密钥和软件源。这一步最容易出错的是地址访问慢或超时尤其是官方源raw.githubusercontent.com在国内访问很不稳定。先按官方流程来sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \ -o /usr/share/keyrings/ros-archive-keyring.gpg echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/ros-archive-keyring.gpg] \ http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main | \ sudo tee /etc/apt/sources.list.d/ros2.list /dev/null如果你执行curl时报“Could not resolve host”或卡住不动大概率是网络问题。这时改用国内镜像源将上面的ros.key换成从清华源下载同时把apt源替换为mirrors.tuna.tsinghua.edu.cn/ros2/ubuntu操作如下sudo curl -sSL https://mirrors.tuna.tsinghua.edu.cn/ros2/ros.key \ -o /usr/share/keyrings/ros-archive-keyring.gpg echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/ros-archive-keyring.gpg] \ https://mirrors.tuna.tsinghua.edu.cn/ros2/ubuntu $(lsb_release -cs) main | \ sudo tee /etc/apt/sources.list.d/ros2.list /dev/null之后执行sudo apt update sudo apt install ros-humble-desktop python3-argcomplete -y如果你只是想在服务器上跑不涉及图形界面的ROS2想省空间可以装ros-humble-ros-base但对初学者我强烈建议直接装ros-humble-desktop因为它包含了rqt、RViz2、demo节点等可视化工具学习时观察话题数据流会直观得多。这个安装包比较大快的话10分钟、慢的话半小时取决于网络。假如中间提示依赖冲突不要盲目执行apt --fix-broken install先阅读冲突内容确认是不是Ubuntu版本不对或者是不是之前装过ROS1残留的源把多余源移除再重试。安装完成后还有一个关键动作把ROS2的环境变量写入shell配置文件这样每次打开新终端都能自动加载ROS2命令。官方推荐写的是.bashrcecho source /opt/ros/humble/setup.bash ~/.bashrc source ~/.bashrc这一步至关重要。很多人都栽在这明明装好了ROS2打开终端一敲ros2说command not found就是因为没source环境。source的本质是把ROS2的bin目录加进PATH同时把库路径、消息接口等环境变量加载进来。.bashrc是每次打开新终端都会自动执行的脚本写进去之后以后就不用手动source了。验证安装是否成功在终端敲ros2 run demo_nodes_cpp talker然后另开一个终端窗口ros2 run demo_nodes_py listener如果两个终端窗口里有来有回地在打印“Publishing: Hello World: N”和“I heard: Hello World: N”说明ROS2已经正常工作。这个talker/listener测试的意义很大它证明节点发现、进程间通信、话题机制、消息序列化全链路都是通的。好多人跳过这个验证步骤直接去写代码结果后面报错时根本分不清是自己的代码问题还是环境配置问题白白浪费排查时间。3.3 源码编译与一键脚本什么时候才需要源码编译安装ROS2在绝大多数阶段都不推荐它要求你手动checkout一堆仓库、处理依赖、然后编译半小时以上只适合做二次开发或研究ROS2内部机制的高级玩家。简单带一句如果你将来确实想干这件事官方文档有完整的“Build from source”章节照着做就行。一键脚本安装我前面说过适合网络不畅或赶时间的同学。我在给朋友做装机服务时偶尔会用但装完一定会帮他手动source环境并跑一次talker/listener确认。这里也要提醒一句无论你用什么方式安装切记确认你装的是Humble而不是别的版本很多一键脚本会默认装更新的发行版到时候你跟着Humble教程走命令可以跑但是API对不上那种迷茫感最折磨人。4. 双语言HelloWorld实战Python与C双路开发流程4.1 先搞懂ROS2的最小工程结构工作空间与功能包在写代码之前必须先建立两个概念工作空间Workspace和功能包Package。工作空间本质上是一个目录约定好的结构是src目录下放若干功能包比如你创建一个目录~/ros2_ws/src这个ros2_ws就是工作空间。功能包则是ROS2中组织代码的基本单元一个功能包里可以包含节点、消息定义、启动文件、配置文件等它有自己的package.xml和CMakeLists.txtC或setup.pyPython。你可以把工作空间理解成一个项目仓库功能包就是仓库里的各个模块。写ROS2程序的流程是创建功能包 - 写代码 - 使用colcon build编译工作空间 - source工作空间的环境变量 - 用ros2 run运行节点。注意这里的source和前面source ROS2安装目录的环境变量是同一件事只不过这次是指向你自己的工作空间。4.2 创建ROS2工作空间与Python版Publisher/Subscriber开始之前先建好工作空间mkdir -p ~/ros2_ws/src cd ~/ros2_ws colcon build有同学问为什么现在就要build一个空工作空间其实这一步会生成build、install、log三个目录后续编译功能包时结构更清晰。直接在第4.4节再build也可以但我习惯先跑一次能确认colcon工具是否可用避免写完代码才知道环境有问题。创建Python功能包的命令cd ~/ros2_ws/src ros2 pkg create py_pubsub --build-type ament_python --dependencies rclpy std_msgs这个命令干了三件事创建目录py_pubsub指定用ament_python作为构建类型对应Python包声明依赖rclpyROS2的Python客户端库和std_msgs标准消息定义包括String类型。如果你在命令行看不到ros2 pkg create先执行source /opt/ros/humble/setup.bash或者确认.bashrc写对了。进入包目录写发布者代码。我习惯在py_pubsub/py_pubsub下新建publisher.pyimport rclpy from rclpy.node import Node from std_msgs.msg import String class MinimalPublisher(Node): def __init__(self): super().__init__(minimal_publisher) self.publisher_ self.create_publisher(String, topic, 10) self.timer self.create_timer(0.5, self.timer_callback) self.count 0 def timer_callback(self): msg String() msg.data fHello, ROS2 from Python! {self.count} self.publisher_.publish(msg) self.get_logger().info(fPublishing: {msg.data}) self.count 1 def main(argsNone): rclpy.init(argsargs) node MinimalPublisher() rclpy.spin(node) node.destroy_node() rclpy.shutdown() if __name__ __main__: main()逐行看一下关键点create_publisher(String, topic, 10)创建了一个类型为String、话题名为topic、队列深度10的发布者队列深度表示消息积压缓冲区取值不是越大越好实时性要求高的场景设小一点更合适。create_timer(0.5, self.timer_callback)表示每0.5秒调用一次回调函数。rclpy.spin(node)是事件循环它会一直阻塞等待回调触发直到进程被CtrlC打断。pub计数每轮加1打印日志方便观察。再写订阅者代码import rclpy from rclpy.node import Node from std_msgs.msg import String class MinimalSubscriber(Node): def __init__(self): super().__init__(minimal_subscriber) self.subscription self.create_subscription(String, topic, self.listener_callback, 10) def listener_callback(self, msg): self.get_logger().info(fI heard: {msg.data}) def main(argsNone): rclpy.init(argsargs) node MinimalSubscriber() rclpy.spin(node) node.destroy_node() rclpy.shutdown() if __name__ __main__: main()创建完这两个文件后还需要修改setup.py把入口点注册进去。打开py_pubsub/setup.py找到entry_points字段修改如下entry_points{ console_scripts: [ publisher py_pubsub.publisher:main, subscriber py_pubsub.subscriber:main, ], },这里把命令行命令publisher和subscriber映射到py_pubsub包里的publisher.py和subscriber.py文件的main函数。忘了改这一步你有两个常见报错ros2 run py_pubsub publisher会提示找不到可执行文件。然后回工作空间根目录编译cd ~/ros2_ws colcon build --packages-select py_pubsub source install/setup.bash ros2 run py_pubsub publisher ros2 run py_pubsub subscriber看到两个终端打印互相呼应的Hello WorldPython版HelloWorld就彻底跑通了。4.3 C版HelloWorld每行CMakeLists.txt都不能糊弄C版的创建命令cd ~/ros2_ws/src ros2 pkg create cpp_pubsub --build-type ament_cmake --dependencies rclcpp std_msgs然后往src目录下放两个文件publisher.cpp#include chrono #include functional #include memory #include string #include rclcpp/rclcpp.hpp #include std_msgs/msg/string.hpp using namespace std::chrono_literals; class MinimalPublisher : public rclcpp::Node { public: MinimalPublisher() : Node(minimal_publisher), count_(0) { publisher_ this-create_publisherstd_msgs::msg::String(topic, 10); timer_ this-create_wall_timer(500ms, std::bind(MinimalPublisher::timer_callback, this)); } private: void timer_callback() { auto message std_msgs::msg::String(); message.data Hello, ROS2 from C! std::to_string(count_); RCLCPP_INFO(this-get_logger(), Publishing: %s, message.data.c_str()); publisher_-publish(message); } rclcpp::Publisherstd_msgs::msg::String::SharedPtr publisher_; rclcpp::TimerBase::SharedPtr timer_; size_t count_; }; int main(int argc, char * argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_sharedMinimalPublisher()); rclcpp::shutdown(); return 0; }subscriber.cpp#include functional #include memory #include rclcpp/rclcpp.hpp #include std_msgs/msg/string.hpp class MinimalSubscriber : public rclcpp::Node { public: MinimalSubscriber() : Node(minimal_subscriber) { subscription_ this-create_subscriptionstd_msgs::msg::String( topic, 10, std::bind(MinimalSubscriber::topic_callback, this, std::placeholders::_1)); } private: void topic_callback(const std_msgs::msg::String msg) const { RCLCPP_INFO(this-get_logger(), I heard: %s, msg.data.c_str()); } rclcpp::Subscriptionstd_msgs::msg::String::SharedPtr subscription_; }; int main(int argc, char * argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_sharedMinimalSubscriber()); rclcpp::shutdown(); return 0; }这里有个地方重点说明C代码中create_subscription接受的第三个参数是std::bind绑定的回调函数std::placeholders::_1表示把消息内容作为第一个参数传给topic_callback。这部分很绕新手可以先背下来结构后续深入函数式编程时再理解。写完后真正决定C包能否编译的点在CMakeLists.txt。打开cpp_pubsub/CMakeLists.txt默认生成的模板里需添加如下内容find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) add_executable(publisher src/publisher.cpp) ament_target_dependencies(publisher rclcpp std_msgs) add_executable(subscriber src/subscriber.cpp) ament_target_dependencies(subscriber rclcpp std_msgs) install(TARGETS publisher subscriber DESTINATION lib/${PROJECT_NAME} )每一项的作用我拆开讲add_executable指定要编译的可执行文件名和源文件一个可执行文件对应一个节点ament_target_dependencies负责把指定ROS2包的include路径和链接库传给编译器少了它你写#include rclcpp/rclcpp.hpp时编译器根本找不到头文件install的DESTINATION lib/${PROJECT_NAME}是把编译产物安装到工作空间的install目录里这样ros2 run才能找到可执行文件。很多同学编译时报“target not found”或运行时报“Package not found”90%是install那几行写错或遗漏。编译运行cd ~/ros2_ws colcon build --packages-select cpp_pubsub source install/setup.bash ros2 run cpp_pubsub publisher ros2 run cpp_pubsub subscriber顺利的话两个终端会显示C版本的消息交互。4.4 双语言沟通验证跨语言消息传递的价值上面的步骤分别跑通了Python两个节点和C两个节点但这还不足以体现ROS2跨语言的强大。我们再做一个实验让C的publisher和Python的subscriber通信。先跑一个终端用colcon build重新编译整个工作空间然后source install/setup.bash接着在一个终端运行ros2 run cpp_pubsub publisher在另一个终端运行ros2 run py_pubsub subscriber。你会看到Python订阅者成功收到了C发布者发来的消息。这说明ROS2的通信中间层对语言透明它靠的是DDS数据分发服务做底层通信消息按IDL格式序列化只要消息类型一致Python和C节点无缝互通。这也是ROS2相比ROS1最核心的进步之一——ROS2从设计之初就明确要求不同语言之间必须有完全一致的消息语义而不是靠字符串拼接模板凑合。网上有个热搜词是“ros2和dds”这里多说一句DDS就是ROS2的通信底层。它负责节点发现、消息发布/订阅、QoS策略控制等。你写的create_publisher和create_subscription最终都会映射到DDS的DataWriter和DataReader上。正因为底层是DDSROS2天然支持实时性控制、可靠传输、跨网络通信等高级特性这也是为什么工业机器人领域纷纷转向ROS2。5. VSCode开发环境配置插件、头文件与调试器一次搞定5.1 安装VSCode官网还是apt源在Ubuntu里装VSCode最靠谱的方式是通过微软官方apt源。打开终端依次执行wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor packages.microsoft.gpg sudo install -D -o root -g root -m 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg echo deb [archamd64 signed-by/etc/apt/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main | \ sudo tee /etc/apt/sources.list.d/vscode.list /dev/null sudo apt update sudo apt install code -y如果你不想折腾apt源也可以直接去code.visualstudio.com下载deb包双击安装效果完全一样。装完后在终端敲code就能打开。VSCode比较重要的是它在打开终端时会自带.bashrc加载也就是说我们前面source进.bashrc的ROS2环境变量会自动生效这一点比很多IDE都省心。如果遇到终端里ROS2命令找不到检查一下VSCode是不是以特殊方式启动导致没加载登录shell的配置这个问题在5.4节会详细说。5.2 必装插件清单与配置说明VSCode的插件我只推荐必要且长期有用的装太多反而拖慢启动速度。第一梯队的插件是中文语言包Chinese Language Pack、Python扩展ms-python.python、C/C扩展ms-vscode.cpptools、CMake Tools和ROS2扩展ms-ros.ros2。Python扩展提供语法高亮、代码补全、调试器配合Python解释器使用。C/C扩展这是让VSCode像Visual Studio一样具备智能提示、跳转定义、悬停信息的关键。安装后需要手动配置includePath后面细说。CMake Tools虽然我们用colcon而不是直接cmake但这个插件能帮你在VSCode里直接触发CMake配置和编译查看编译目标。ROS2扩展官方推出的插件能识别ROS2工作空间支持在VSCode里直接选择run目标、查看构建状态。我用下来感觉它对新手不那么必须但对老手提升效率明显。另外我习惯再装一个Material Icon Theme和Error Lens后者能把编译错误直接内联显示在出错的代码行后面省去切换终端翻阅日志的麻烦。5.3 C/C智能提示配置includePath和c_cpp_properties.jsonVSCode打开~/ros2_ws目录后C/C扩展会提示你生成配置文件。按CtrlShiftP输入C/C: Edit Configurations (UI)或者直接编辑.vscode/c_cpp_properties.json。核心配置如下{ configurations: [ { name: ROS2 Humble, includePath: [ ${workspaceFolder}/**, /opt/ros/humble/include/** ], defines: [], compilerPath: /usr/bin/g, cStandard: c17, cppStandard: gnu17, intelliSenseMode: linux-gcc-x64 } ], version: 4 }这里的includePath决定代码补全和头文件跳转的搜索范围。/opt/ros/humble/include是ROS2所有头文件所在目录加进去后你写#include rclcpp/rclcpp.hpp就不会再出现红色波浪线。有一些人问为什么include了还是飘红多半是因为自己功能区里用了workspaceFolder的路径和ROS2路径写反或者漏掉。配置完成后重启VSCode确认#include行不再报错并且Ctrl点击能跳转到头文件内就说明配置成功了。5.4 Python解释器选择和ROS2扩展使用Python端比较简单在VSCode按下CtrlShiftP选择“Python: Select Interpreter”选系统自带Python3/usr/bin/python3。对于ROS2开发不建议开虚拟环境venv因为ROS2的rclpy被装在系统site-packages里虚拟环境默认访问不到。如果你非要隔离环境用virtualenv时记得加--system-site-packages参数否则import rclpy会报ModuleNotFoundError。ROS2扩展安装完后你可以直接在VSCode左侧的“ROS”面板中看到工作空间里的功能包、可执行目标和话题。在ROS2插件设置里指定colcon build和run的默认配置之后在代码里按一下F5还能自动启动调试会话。这个插件的自动补全对C尤其友好它能读取ament_target_dependencies里的依赖并给出正确的头文件路径省去手动维护c_cpp_properties.json的麻烦。不过插件也不是万能的它需要工作空间已经用colcon build成功过一次才能准确解析所以建议先把第4章的HelloWorld完整跑通一遍再配置VSCode。调试配置更简单直接用VSCode自带的launch.json。在“运行和调试”面板中点击“创建launch.json”选择“C (GDB/LLDB)”模板把program字段改成你编译出来的可执行文件绝对路径比如${workspaceFolder}/install/cpp_pubsub/lib/cpp_pubsub/publisher然后设置args为[]。之后你就可以在代码里打断点按F5启动调试在C代码里逐步观察变量的变化。Python调试同理选择“Python Debugger”模板配置module或者program路径即可。5.5 终端集成、Git与常用工作流VSCode的集成终端默认就是bash因为.bashrc里已经有source所以直接能用ros2和colcon命令。我个人的工作流是在VSCode里打开~/ros2_ws修改代码然后在集成终端执行colcon build --packages-select 包名source install/setup.bash再用ros2 run启动节点。这一套东西都配好之后写ROS2代码的体验已经非常接近写普通C/Python工程了。另外强烈建议建好Git仓库因为ROS2开发中试错频率很高代码改来改去很容易回到一个还没法工作的状态。用git init初始化每跑通一个节点就commit一次标注好“Python publisher跑通”“C subscriber跑通”等。这样出了问题随时git diff看改动或者git checkout回滚。VSCode里左侧的源代码管理面板会自动显示变更配合几个基本命令git add .、git commit -m message足够你安全地度过新手期。这个习惯越早建立越好不是挑项目才用而是所有代码都进版本库。6. 常见问题与踩坑排查实录速查速用6.1 虚拟机与系统层问题Q1Ubuntu安装后屏幕分辨率很小、窗口无法放大这是没安装VMware Tools或open-vm-tools的典型症状。Ubuntu 22.04建议直接执行sudo apt install open-vm-tools-desktop -y安装完成后重启。如果还不行检查VMware菜单“查看”里的“自动调整大小”是否选中。Q2虚拟机内apt update很慢或超时大概率是没换源或者源配置错了。按2.4节检查/etc/apt/sources.list确保里面的域名已经被替换为国内镜像。换完源别忘了sudo apt update。如果ping mirrors.tuna.tsinghua.edu.cn都不通请检查宿主机网络和VMware NAT网络设置。Q3虚拟机启动后宿主机变得很卡内存分配过多或CPU分配不足。在VMware设置里降低虚拟机内存到4GB或8GB同时设置宿主机在虚拟机运行时可用的内存上限。另外一个容易被忽略的坑是宿主机硬盘空间不足VMware动态分配磁盘会在宿主机没有足够空间时出现奇怪IO卡顿。Q4在Ubuntu里打开终端中文显示为乱码这是locale配置问题。按3.2节重新生成locale并确认.bashrc或profile里有LANGzh_CN.UTF-8或en_US.UTF-8。如果是搜狗输入法导致fcitx和locale冲突可以重启fcitx或注销重新登录。6.2 ROS2安装与环境变量问题Q5source /opt/ros/humble/setup.bash时提示No such file or directory这说明ROS2没装成功或者装的不是Humble版本。先执行dpkg -l | grep ros查看已装的包如果没有结果回头重新检查3.2节的软件源和安装步骤。另一个可能原因是安装时使用了sudo apt install ros-humble-desktop但因为网络中断没装完这时执行sudo apt --fix-broken install补全依赖。Q6ros2命令找不到command not found确认你已执行source /opt/ros/humble/setup.bash并且该行已经写入~/.bashrc。终端里敲echo $ROS_DISTRO如果输出humble说明环境变量正常。还有一个常见情况你在VSCode里打开了新终端但它没加载.bashrc此时手动执行source ~/.bashrc或者在VSCode设置里把terminal.integrated.defaultProfile.linux改成bash。Q7sudo ros2 run ...报错command not foundsudo会重置PATH和环境变量导致当前用户的ROS2环境不在sudo环境里。尽量避免用sudo运行ROS2命令改用普通用户。如果你确实需要root权限来做设备访问用sudo -E或指定完整路径/opt/ros/humble/bin/ros2。Q8ros2 run时提示duplicate node name这通常是因为你先运行了一个节点没关掉又在另一个终端启动同名节点。用ros2 node list查看当前活跃节点用CtrlC关掉重复的或者在启动命令后加--ros-args --remap __node:new_node_name重映射节点名。6.3 编译与代码问题Q9colcon build找不到自定义包最典型的原因是没source当前工作空间的install/setup.bash。每次build完成后必须source install/setup.bashcolcon才会把新包加入环境。另外检查包名是否和文件夹名一致package.xml里的name字段是否和目录名一致三处不一致时ROS2就找不到它。Q10Python包运行时报ModuleNotFoundError: No module named package_name检查setup.py中的packages字段它需要包含你的包目录名。例如你的代码在py_pubsub/py_pubsub/下那么packages[py_pubsub]。如果功能包中包含子模块还要用setuptools.find_packages()自动发现。改完setup.py后重新colcon build。Q11C包编译报“fatal error: rclcpp/rclcpp.hpp: No such file or directory”这是CMakeLists.txt中ament_target_dependencies没写全导致的。确保add_executable之后紧跟着ament_target_dependencies(可执行文件名 rclcpp std_msgs)。改完后重新colcon build。如果还是不行在终端手动跑cmake --build看具体是哪个include失败。Q12编译通过但ros2 run找不到可执行文件package not found确认你的CMakeLists.txt里有install(TARGETS ... DESTINATION lib/${PROJECT_NAME})并且路径里的PROJECT_NAME和package.xml的name一致。install步骤负责把编译产物复制到install目录没有它ros2 run只能看不能用。如果这行已经存在重新colcon build并source install/setup.bash。Q13colcon build时报Python依赖冲突比如setuptools版本太老Ubuntu 22.04自带setuptools 59.6.0但ament_python在部分版本上需要较新的setuptools。执行pip3 install -U setuptools可以解决但注意如果使用系统Pythonpip安装的包会写进/usr/local/lib/python3.10/dist-packages一般不影响系统。如果更极端考虑在虚拟环境里配置Python开发环境。Q14topic消息收不到talker/listener测试正常但自己的节点不行先分析是不是话题名或消息类型不匹配。用ros2 topic list查看当前所有话题用ros2 topic echo /topic名查看消息内容。如果话题存在但收不到检查QoS策略默认的可靠性和持久性参数下发布者用best_effort而订阅者用reliable会导致不匹配。最简单的方式是两边都设置成相同的QoS或者都用默认的RELIABLE。Q15回调函数不执行程序卡在spin不退出确认你的回调函数是否被正确注册。Python里为定时器注册回调用create_timer订阅消息用create_subscription的回调。如果你在代码里不小心把回调写成了成员函数但没加括号或者std::bind的占位符写错都会导致回调不触发。另外查看日志中是否有“no publisher found”之类的警告说明节点发现在异常状态。6.4 VSCode配置问题Q16C/C 扩展提示“无法打开源文件 std_msgs/msg/string.hpp”检查c_cpp_properties.json的includePath是否包含/opt/ros/humble/include/**并确认该路径下确实存在std_msgs头文件。如果路径正确但依然报错重启VSCode或者执行C/C: Reset IntelliSense Database。Q17Python代码里import rclpy标红但运行不报错这是因为VSCode的Python扩展选了解释器但当时的解释器不是系统Python3。按5.4节重新选择解释器或者在.vscode/settings.json中设置python.defaultInterpreterPath: /usr/bin/python3。标红只代表静态分析找不到模块不代表代码运行一定会失败但为了后续补全和调试体验尽早修正解释器选择。Q18VSCode集成终端打开后没有加载~/.bashrc里的ROS2环境有一种情况是VSCode的集成终端默认使用dash而不是bash。在设置里搜索terminal.integrated.defaultProfile.linux改成bash。还有一种情况是你用code命令启动VSCode时环境变量没继承确保在bash终端里敲code而不是从桌面图标启动。Q19debug时提示“Unable to start debugging. Failed to launch program”检查launch.json中program字段路径是否正确可以用which直接确认可执行文件实际路径。另外确认当前工作空间已经编译并source否则可执行文件不存在自然会启动失败。7. 一些真正的经验和后续建议如果让我给一个最节省时间的建议那就是环境搭建过程中每完成一个里程碑就拍一次快照。装完系统拍一个装完ROS2拍一个跑通双语言HelloWorld再拍一个。很多初学者喜欢一鼓作气全装完再测试结果出了问题不知道是系统坏了还是软件配置坏了只能从头再来。快照就是时间机器它把你从反复重装的无底洞里捞出来。另一个容易被忽视的点是一定要学会看日志。ROS2的命令行工具提供了不少调试手段ros2 node list查看节点、ros2 topic list查看话题、ros2 topic echo查看消息内容、ros2 doctor检查环境健康度。我见过太多人只盯着自己的代码反复改最后发现是环境变量没source或另一个终端里还挂着旧节点。用工具观察系统真实状态比用猜的靠谱一百倍。如果你不知道怎么排查先敲ros2 doctor它会自动检测很多常见配置问题。关于DDS和QoS我建议在你跑通HelloWorld之后可以抽时间看一遍ros2 topic info和ros2 topic pub的用法。简明介绍一下ros2 topic pub /topic std_msgs/msg/String data: hello --rate 2可以在命令行直接往话题发消息无需写任何代码ros2 topic info可以查看话题的类型和QoS配置。学会这些命令行工具后你调试节点的能力会明显上一个台阶。最后说说这个环境的后续扩展方向。等你对Python和C的HelloWorld都熟悉了可以试着用urdf和rviz2建一个简单的机器人模型再跑一套SLAM或导航仿真。ROS2真正强大的地方在于多机通信、跨语言协作和工具生态我的建议是尽早接触rqt_graph和launch文件因为真实项目不会只跑两个节点——当你需要同时启动十几个节点时launch文件会成为你最常用的工具。如果你在这条路上卡住了试试先关掉所有终端重新打开一个再source ~/.bashrc。这个动作解决过我遇到的八成诡异问题——因为环境变量一旦没加载对后面所有的命令都会变得莫名其妙。环境搭建是磨性子的活但也是每个ROS2开发者都必须跨过的第一道门槛。我现在看着当年第一次跑通talker/listener时打印的“Hello World”还是会觉得那一下真的很值。
返回列表