尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

ROS机器人操作系统入门:从核心概念到Python实战Topic与Service通信

ROS机器人操作系统入门:从核心概念到Python实战Topic与Service通信 在机器人技术快速发展的今天无论是学术研究还是工业应用一个稳定、高效且易于扩展的机器人软件开发框架至关重要。ROSRobot Operating System作为业界事实上的标准为开发者提供了构建复杂机器人应用的强大工具箱。然而对于许多初学者而言ROS庞大的生态、复杂的节点通信机制以及繁琐的环境配置常常是入门路上的第一道门槛。本文旨在提供一个从零开始的保姆级教程不仅详细拆解ROS的核心通信原理更会手把手带你完成环境搭建并通过Python代码实战Topic和Service两种核心通信模式最终让你能独立开发一个简单的智能机器人应用为后续探索SLAM、导航、机械臂控制等具身智能领域打下坚实基础。1. ROS核心概念与架构解析在动手写代码之前理解ROS的基本思想和架构是至关重要的。这能帮助你在后续开发中清晰地知道每个组件的作用和它们之间的协作关系。1.1 ROS是什么不是什么首先需要明确ROS不是一个传统意义上的操作系统如Windows、Linux。它不执行底层的硬件驱动、进程调度或内存管理。相反ROS是一个运行在现有操作系统通常是Ubuntu Linux之上的元操作系统或中间件框架。你可以把它想象成一个为机器人软件开发量身定制的“软件总线”和“工具集”。它提供了一系列标准化的服务例如硬件抽象用统一的接口控制不同的传感器如摄像头、激光雷达和执行器如电机。底层设备控制管理电机、舵机等硬件。进程间消息传递让不同功能模块进程能够轻松地通信。包管理方便地发布、查找、安装和复用机器人软件组件。常用功能实现提供了大量现成的算法库如坐标变换TF、定位、地图构建、路径规划等。因此ROS的核心价值在于标准化和复用性。它定义了一套通信机制和接口规范让全球的机器人开发者能够基于同一套“语言”进行开发极大地加速了机器人软件的迭代和创新。1.2 ROS的核心架构节点、主题、服务、消息ROS采用了一种分布式、松耦合的进程节点网络架构。理解以下几个核心概念是掌握ROS的关键节点NodeROS中的基本执行单元。一个节点就是一个可执行文件它负责完成某个具体的功能例如读取传感器数据、进行路径规划、控制电机转动等。一个复杂的机器人系统通常由数十个甚至上百个节点协同工作。主题TopicROS中最常用的一种异步通信机制。它基于发布/订阅Publish/Subscribe模型。发布者Publisher节点可以向一个特定的主题发布消息。订阅者Subscriber节点可以订阅它感兴趣的主题从而接收该主题上的所有消息。主题通信是单向且多对多的。一个主题可以有多个发布者和多个订阅者。数据流是持续不断的就像广播电台一样。服务ServiceROS中另一种同步通信机制。它基于客户端/服务器Client/Server模型适用于请求/响应式的交互。服务端Server提供一个具名的服务并等待客户端的请求。客户端Client向服务端发送一个请求然后等待并接收服务端的响应。服务通信是双向、同步且一对一的。客户端发出请求后会阻塞直到收到响应或超时。消息Message节点之间通过主题或服务传递的数据具有严格定义的数据结构。消息类型可以是简单的整数、浮点数也可以是复杂的嵌套结构如包含位置、姿态信息的激光扫描数据。.msg文件用于定义主题消息.srv文件用于定义服务消息。Topic vs Service 如何选择使用Topic当需要持续、单向地流式传输数据时例如传感器数据流摄像头图像、激光雷达点云、机器人状态位置、速度广播。使用Service当需要执行一个具体的、一次性的操作并获取结果时例如请求计算一个路径、触发一次拍照、查询某个状态。1.3 ROS的版本与发行版ROS目前有两个主要版本ROS 1通常简称ROS和 ROS 2。ROS 2是对ROS 1的彻底重构解决了ROS 1在实时性、安全性、跨平台等方面的诸多限制是未来的发展方向。但对于初学者从经典的ROS 1入手学习核心概念更为合适因为其生态更成熟资料更丰富。ROS采用发行版Distribution的形式发布类似于Ubuntu的发行版。每个发行版对应一个Ubuntu LTS版本。常见的ROS 1发行版有ROS Noetic Ninjemys最后一个ROS 1 LTS版本支持到2025年5月。对应Ubuntu 20.04。这是目前最推荐初学者使用的版本生态完善兼容性好。ROS Melodic Morenia上一个LTS版本对应 Ubuntu 18.04。ROS Kinetic Kame更早的LTS版本对应 Ubuntu 16.04。本文后续所有教程将基于 ROS Noetic 和 Ubuntu 20.04 进行。如果你使用的是其他系统可以考虑使用虚拟机如VirtualBox或Windows的WSL2来安装Ubuntu 20.04。2. 环境搭建从零安装ROS Noetic环境搭建是第一步也是最容易出错的一步。我们将采用官方推荐的方式并介绍国内可用的镜像源以加速下载。2.1 系统准备与配置操作系统确保你使用的是Ubuntu 20.04 Desktop版本。可以在终端中通过lsb_release -a命令查看。配置软件源为了加快安装包的下载速度建议将Ubuntu的软件源和ROS的软件源替换为国内镜像如清华、中科大。打开“软件和更新”在“Ubuntu软件”标签页选择“下载自”-“其他站点”-选择 mirrors.tuna.tsinghua.edu.cn。或者通过命令行修改源列表备份原文件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 install curl build-essential2.2 安装ROS Noetic遵循官方安装步骤但使用国内镜像源。设置ROS软件源sudo sh -c echo deb http://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu/ $(lsb_release -sc) main /etc/apt/sources.list.d/ros-latest.list设置密钥sudo apt install curl curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add -如果遇到网络问题可以尝试使用中科大的密钥服务器sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654更新软件包索引并安装ROSsudo apt update sudo apt install ros-noetic-desktop-fullros-noetic-desktop-full包含了ROS核心库、图形化工具如Rviz、Gazebo以及许多常用的机器人算法包。安装过程较长请耐心等待。2.3 环境配置与验证安装完成后需要让系统知道ROS命令的位置。初始化 rosdeprosdep是ROS的一个工具用于安装系统依赖。sudo rosdep init rosdep update注意sudo rosdep init只需要执行一次。如果失败可能是网络问题可以多试几次或搜索相关解决方案。设置环境变量每次打开新的终端窗口都需要让系统知道ROS的路径。最方便的方法是将配置命令添加到shell的启动文件中。echo source /opt/ros/noetic/setup.bash ~/.bashrc source ~/.bashrc这行命令将ROS的环境设置脚本添加到你的.bashrc文件中这样每次启动终端都会自动生效。安装构建工具ROS使用catkin作为构建系统。需要安装相关工具。sudo apt install python3-rosinstall python3-rosinstall-generator python3-wstool build-essential sudo apt install python3-catkin-tools python3-osrf-pycommon验证安装打开一个新的终端窗口运行以下命令roscore如果看到类似下面的输出并且没有报错说明ROS核心Master已经成功启动。... logging to /home/yourname/.ros/log/... started core service [/rosout]在另一个终端中输入rosnode list应该能看到正在运行的节点如/rosout。这证明你的ROS环境已经搭建成功最后按CtrlC停止roscore。3. 创建你的第一个ROS工作空间与包在ROS中我们所有的代码都组织在“工作空间”和“包”里。这是ROS项目管理的标准方式。3.1 创建Catkin工作空间Catkin是ROS的官方构建系统。工作空间是一个存放项目源码、编译文件和安装文件的目录。# 1. 创建并进入工作空间目录 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/ # 2. 初始化工作空间。这会在src目录下生成CMakeLists.txt的符号链接。 catkin init # 3. 构建工作空间。第一次构建会配置很多环境。 catkin build # 或者使用传统的catkin_make命令catkin_make # 4. 将工作空间的设置脚本加入环境变量同样添加到.bashrc echo source ~/catkin_ws/devel/setup.bash ~/.bashrc source ~/.bashrc构建成功后工作空间内会生成build,devel,logs等目录。devel目录下的setup.bash就是你这个工作空间的环境设置脚本。3.2 创建ROS功能包包Package是ROS中组织代码的基本单元。一个包可以包含节点、库、配置文件等。# 进入src目录 cd ~/catkin_ws/src # 使用catkin_create_pkg命令创建包 # 语法catkin_create_pkg package_name [depend1] [depend2] ... # 我们创建一个名为my_first_robot的包它依赖roscpp和rospyC和Python的ROS客户端库以及std_msgs标准消息类型 catkin_create_pkg my_first_robot rospy roscpp std_msgs命令执行后会在src目录下生成一个名为my_first_robot的文件夹其结构如下my_first_robot/ ├── CMakeLists.txt # 包的编译规则 ├── package.xml # 包的描述信息和依赖声明 └── src/ # 存放源代码的目录package.xml文件非常重要它定义了包的元数据名称、版本、作者、许可证和依赖关系。CMakeLists.txt则告诉系统如何编译你的代码。4. 实战Topic通信发布与订阅我们将创建一个经典的“Talker-Listener”示例。一个节点发布者周期性地向一个主题发布字符串消息另一个节点订阅者订阅该主题并打印接收到的消息。4.1 创建发布者节点Python在my_first_robot包下创建scripts文件夹来存放Python脚本这是一种常见约定。mkdir -p ~/catkin_ws/src/my_first_robot/scripts cd ~/catkin_ws/src/my_first_robot/scripts创建发布者脚本talker.py#!/usr/bin/env python3 # -*- coding: utf-8 -*- import rospy from std_msgs.msg import String def talker(): # 初始化ROS节点节点名为talkeranonymousTrue确保节点名称唯一避免重复 rospy.init_node(talker, anonymousTrue) # 创建一个Publisher发布到名为chatter的Topic消息类型为String队列长度10 pub rospy.Publisher(chatter, String, queue_size10) # 设置发布频率1Hz (每秒1次) rate rospy.Rate(1) # 设置一个计数器 count 0 # 在ROS没有被关闭的情况下循环 while not rospy.is_shutdown(): # 准备要发布的消息内容 hello_str Hello ROS! This is message #%d % count rospy.loginfo(hello_str) # 在ROS日志和终端打印消息 # 发布消息 pub.publish(hello_str) # 按照设定的频率休眠 rate.sleep() count 1 if __name__ __main__: try: talker() except rospy.ROSInterruptException: pass关键代码解释rospy.init_node(): 注册节点到ROS Master。rospy.Publisher(): 创建发布者对象。queue_size是一个重要的参数它定义了发布者缓存未发送消息的队列大小。如果发布速度过快超过队列大小旧消息会被丢弃。rospy.Rate(): 用于控制循环频率。rospy.loginfo(): ROS提供的日志打印函数比print更好因为它有日志级别info, warn, error等。pub.publish(): 发布消息到主题。rospy.is_shutdown(): 检查ROS是否被关闭例如按下了CtrlC。4.2 创建订阅者节点Python在同一个scripts目录下创建订阅者脚本listener.py#!/usr/bin/env python3 # -*- coding: utf-8 -*- import rospy from std_msgs.msg import String def callback(data): # 当收到消息时这个回调函数会被调用 # data就是收到的消息对象 rospy.loginfo(rospy.get_caller_id() I heard: %s, data.data) def listener(): # 初始化节点名为listener rospy.init_node(listener, anonymousTrue) # 创建一个Subscriber订阅名为chatter的Topic消息类型为String # 当有新消息到达时调用callback函数处理 rospy.Subscriber(chatter, String, callback) # rospy.spin() 使Python程序保持运行直到节点被显式关闭 # 它会循环等待并在收到消息时触发回调函数 rospy.spin() if __name__ __main__: listener()关键代码解释rospy.Subscriber(): 创建订阅者对象。最重要的参数是回调函数callback每当有消息到达时ROS就会自动调用这个函数并将消息作为参数传入。rospy.spin(): 这是一个阻塞调用它让节点保持活动状态并等待回调。对于只做订阅的节点这是必需的。对于既有发布又有订阅的节点通常使用循环while not rospy.is_shutdown()。4.3 赋予脚本执行权限并测试Python脚本需要可执行权限才能被ROS直接运行。cd ~/catkin_ws/src/my_first_robot/scripts chmod x talker.py listener.py现在让我们来测试这个Topic通信系统终端1启动ROS Masterroscore终端2运行发布者节点cd ~/catkin_ws source devel/setup.bash # 如果已经添加到.bashrc新终端会自动执行 rosrun my_first_robot talker.py你应该能看到终端每秒打印一次 “Hello ROS! This is message #X”。终端3运行订阅者节点cd ~/catkin_ws source devel/setup.bash rosrun my_first_robot listener.py你应该能看到订阅者节点打印出它从talker那里听到的每一条消息。使用命令行工具观察再开一个终端rosnode list: 查看所有运行中的节点应看到/talker,/listener,/rosout。rostopic list: 查看所有活跃的主题应看到/chatter,/rosout,/rosout_agg。rostopic echo /chatter: 实时打印/chatter主题上发布的所有消息。rostopic hz /chatter: 查看/chatter主题的消息发布频率应接近1Hz。通过这个简单的例子你已经成功实现了ROS中最基础的异步通信。可以尝试修改发布频率、消息内容或者创建多个订阅者来加深理解。5. 实战Service通信请求与响应Service通信是同步的适合执行一次性的任务。我们创建一个简单的加法服务客户端发送两个整数服务端计算它们的和并返回结果。5.1 定义服务类型首先我们需要定义服务的数据结构。在ROS中服务类型在.srv文件中定义。在my_first_robot包下创建srv目录mkdir -p ~/catkin_ws/src/my_first_robot/srv创建AddTwoInts.srv文件cd ~/catkin_ws/src/my_first_robot/srv touch AddTwoInts.srv编辑该文件内容如下# 请求部分客户端发送给服务端 int64 a int64 b --- # 响应部分服务端返回给客户端 int64 sum文件用三个短横线---分隔请求和响应两部分。5.2 配置包以编译服务定义为了让ROS系统识别我们自定义的服务类型需要修改package.xml和CMakeLists.txt。修改package.xml确保有以下行catkin_create_pkg应该已经添加了build_dependmessage_generation/build_depend exec_dependmessage_runtime/exec_depend修改CMakeLists.txt这是关键步骤。找到find_package(...)部分确保包含message_generationfind_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation # 添加这一行 )找到add_service_files(...)部分取消注释并添加你的.srv文件add_service_files( FILES AddTwoInts.srv )找到generate_messages(...)部分确保它存在通常已存在generate_messages( DEPENDENCIES std_msgs )找到catkin_package(...)部分确保包含message_runtimecatkin_package( CATKIN_DEPONDE message_generation message_runtime # 确保有message_runtime )编译工作空间以生成服务代码cd ~/catkin_ws catkin build my_first_robot # 或者 catkin_make source devel/setup.bash编译成功后ROS会自动为AddTwoInts.srv生成Python或其他语言的代码这样我们就可以在脚本中导入my_first_robot.srv模块了。5.3 创建服务端节点Python在scripts目录下创建add_two_ints_server.py#!/usr/bin/env python3 # -*- coding: utf-8 -*- from my_first_robot.srv import AddTwoInts, AddTwoIntsResponse import rospy def handle_add_two_ints(req): # 这个函数在收到服务请求时被调用 # req 是一个 AddTwoIntsRequest 对象包含 a 和 b 字段 print(Returning [%s %s %s] % (req.a, req.b, (req.a req.b))) # 返回一个 AddTwoIntsResponse 对象设置 sum 字段 return AddTwoIntsResponse(req.a req.b) def add_two_ints_server(): # 初始化节点 rospy.init_node(add_two_ints_server) # 创建一个Service名称为add_two_ints类型为AddTwoInts处理函数为handle_add_two_ints s rospy.Service(add_two_ints, AddTwoInts, handle_add_two_ints) print(Ready to add two ints.) # 保持节点运行等待服务请求 rospy.spin() if __name__ __main__: add_two_ints_server()5.4 创建客户端节点Python在scripts目录下创建add_two_ints_client.py#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys import rospy from my_first_robot.srv import AddTwoInts def add_two_ints_client(x, y): # 等待名为add_two_ints的服务变得可用 rospy.wait_for_service(add_two_ints) try: # 创建一个服务调用的“句柄”可以像调用函数一样使用它 add_two_ints rospy.ServiceProxy(add_two_ints, AddTwoInts) # 调用服务传入请求参数resp1 是响应对象 resp1 add_two_ints(x, y) return resp1.sum except rospy.ServiceException as e: print(Service call failed: %s % e) if __name__ __main__: # 允许从命令行传入两个整数参数 if len(sys.argv) 3: a int(sys.argv[1]) b int(sys.argv[2]) else: # 如果没有提供参数使用默认值 print(Usage: %s [a b] % sys.argv[0]) print(Using default values 5 and 3) a 5 b 3 print(Requesting %s %s % (a, b)) result add_two_ints_client(a, b) print(%s %s %s % (a, b, result))5.5 测试Service通信赋予脚本执行权限并测试cd ~/catkin_ws/src/my_first_robot/scripts chmod x add_two_ints_server.py add_two_ints_client.py终端1启动ROS Masterroscore终端2启动服务端cd ~/catkin_ws source devel/setup.bash rosrun my_first_robot add_two_ints_server.py你会看到输出 “Ready to add two ints.”。终端3启动客户端cd ~/catkin_ws source devel/setup.bash rosrun my_first_robot add_two_ints_client.py 10 20客户端会打印 “Requesting 10 20”然后调用服务。服务端会打印 “Returning [10 20 30]”客户端最终打印 “10 20 30”。使用命令行工具观察rosservice list: 查看所有可用服务应看到/add_two_ints。rosservice type /add_two_ints: 查看该服务的类型应显示my_first_robot/AddTwoInts。rosservice call /add_two_ints “a: 5 b: 7”: 直接通过命令行调用服务你会看到返回结果sum: 12。至此你已经成功掌握了ROS最核心的两种通信机制异步的Topic和同步的Service。这是构建任何复杂机器人应用的基石。6. 常见问题与深度排错指南在学习和使用ROS的过程中你几乎一定会遇到各种问题。下面是一些最常见的问题及其解决方案。6.1 环境与路径问题问题现象可能原因解决方案roscore或rosrun命令未找到ROS环境变量未正确设置1. 检查~/.bashrc文件末尾是否有source /opt/ros/noetic/setup.bash和source ~/catkin_ws/devel/setup.bash。2. 执行source ~/.bashrc或重新打开终端。rosrun找不到自己创建的包工作空间未编译或环境未更新1. 确保在catkin_ws目录下执行了catkin build或catkin_make且无报错。2. 确保执行了source devel/setup.bash。3. 使用rospack find my_first_robot检查包路径是否能被找到。运行Python脚本报ImportErrorPython模块路径问题或脚本权限问题1. 确保脚本有可执行权限 (chmod x your_script.py)。2. 确保脚本首行有#!/usr/bin/env python3。3. 如果是导入自定义消息/服务确保已编译工作空间并source devel/setup.bash。6.2 编译与包配置问题问题现象可能原因解决方案catkin_make编译失败提示找不到依赖package.xml中依赖声明不全1. 检查package.xml中的depend或build_depend/exec_depend标签确保包含了所有用到的ROS包如roscpp,rospy,std_msgs,message_generation等。2. 运行rosdep install --from-paths src --ignore-src -r -y安装系统依赖。自定义消息/服务编译后Python中仍无法导入CMakeLists.txt配置错误或未重新source1. 仔细检查CMakeLists.txt中find_package,add_service_files,generate_messages,catkin_package几个部分的配置确保与上文一致。2. 删除build和devel文件夹重新catkin_make。3.务必在新的终端或source devel/setup.bash。6.3 运行时通信问题问题现象可能原因解决方案节点启动后立刻退出脚本执行完毕常见于没有rospy.spin()或循环的订阅者对于订阅者或服务端确保在代码末尾有rospy.spin()来保持节点运行。对于发布者使用while not rospy.is_shutdown():循环。发布者/订阅者无法通信1.roscore未运行。2. Topic名称拼写不一致。3. 消息类型不匹配。1. 首先运行roscore。2. 使用rostopic list确认Topic是否存在使用rostopic info /topic_name查看其类型和发布/订阅者。3. 检查发布和订阅代码中的Topic名称和消息类型是否完全一致大小写敏感。服务调用失败或超时1. 服务端未启动。2. 服务名称错误。3. 请求/响应类型不匹配。1. 使用rosservice list确认服务是否存在。2. 检查客户端和服务端的服务名称、.srv文件定义是否一致。3. 使用rosservice call手动测试服务是否正常工作。6.4 网络与多机通信问题进阶当你在多台机器上部署ROS节点时需要设置ROS环境变量以实现通信。所有机器必须在同一网络且能互相ping通。指定ROS Master在一台机器假设IP为192.168.1.100上运行roscore这台机器就是Master。配置其他机器的环境变量export ROS_MASTER_URIhttp://192.168.1.100:11311 export ROS_IP本机IP地址 # 例如 192.168.1.101将这些行添加到其他机器的~/.bashrc中。这样其他机器上的节点就会连接到指定的Master进行通信。7. 工程实践与进阶学习建议掌握了基础通信后你可以开始构建更真实的机器人应用。以下是一些工程实践建议和后续学习方向。7.1 项目组织最佳实践清晰的包结构一个包只负责一个相对独立的功能模块。例如robot_driver包负责底层硬件驱动robot_navigation包负责导航算法robot_perception包负责传感器数据处理。使用Launch文件手动在多个终端启动节点非常繁琐。ROS Launch文件.launch可以一次性启动多个节点并设置参数。这是管理复杂机器人系统的标准方式。参数服务器使用rosparam将可配置参数如机器人尺寸、控制器增益、算法阈值存储在参数服务器中而不是硬编码在代码里。这样可以在Launch文件中动态修改便于调试和部署。善用ROS工具rqt_graph可视化显示节点和主题之间的连接关系是调试通信问题的神器。rviz3D可视化工具可以显示传感器数据点云、图像、机器人模型、路径规划结果等。rosbag记录和回放ROS Topic数据用于算法调试和离线分析。7.2 从Demo到真实机器人仿真先行在将代码部署到真实机器人前强烈建议在仿真环境中测试。Gazebo是ROS官方集成的强大物理仿真器可以模拟机器人、传感器和环境。理解TFTransformTF是ROS中管理坐标系变换的库。机器人各个部件底盘、激光雷达、摄像头、机械臂关节都有自己的坐标系。TF维护着这些坐标系之间的树状变换关系对于传感器融合、导航、机械臂运动学计算至关重要。学习导航栈ROS提供了完整的move_base导航框架集成了全局/局部路径规划、代价地图、恢复行为等。理解并配置导航栈是让机器人实现自主移动的关键。探索感知与SLAM学习如何使用OpenCV和PCL点云库处理图像和3D点云数据。掌握gmapping,cartographer或RTAB-Map等SLAM算法让机器人能构建环境地图并同时定位自身。7.3 学习路线图建议巩固基础反复练习本文的Topic和Service通信理解其本质区别。尝试创建自定义复杂消息类型。掌握工具链熟练使用roslaunch,rviz,rqt,rosbag等核心工具。深入仿真在Gazebo中加载一个现成的机器人模型如TurtleBot3尝试用键盘或代码控制它运动并添加虚拟传感器。学习导航为仿真机器人配置move_base实现从A点到B点的自主导航。连接真实硬件如果你有实体机器人如树莓派电机驱动板学习如何编写驱动节点将ROS命令转换为电机控制信号并将传感器数据发布为ROS Topic。迈向ROS 2当对ROS 1的核心概念有扎实理解后开始学习ROS 2。关注其改进的通信机制DDS、生命周期节点、安全特性等。ROS的学习曲线前期可能较陡峭但一旦你理解了其分布式、节点化的设计哲学并熟练使用其强大的工具链开发机器人软件将变得高效且充满乐趣。从今天这个简单的“Hello ROS”开始一步步构建你想象中的智能机器人吧。如果在实践中遇到具体问题ROS社区和丰富的在线文档wiki.ros.org是你最好的朋友。
返回列表