原文:
zh.annas-archive.org/md5/edf77da8c3973e5e777cd87524a170a5译者:飞龙
前言
为什么会有关于使用 ROS 学习机器人的新书?嗯,编程只是与机器人一起工作的很小一部分。如果你想真正擅长机器人技术,你还需要在其他领域具备技能:机电一体化、机器人仿真、自主导航和机器学习/强化学习。这四个主题中的每一个都是你在获得完整机器人技能的道路上需要掌握的构建模块。本书分为四个部分,每个部分都致力于这些构建模块之一。
第一部分,物理机器人组装和测试,侧重于机电一体化,并描述机器人的每个硬件部分,提供如何测试其配备的每个传感器和执行器的实际演示。本书的这一部分应帮助你理解移动机器人是如何工作的。
第二部分,使用 Gazebo 进行机器人仿真,涉及机器人仿真。在这里,我们介绍了 ROS 并开发了一个两轮机器人仿真,它模拟了实际机器人的物理特性和行为。我们将探讨数字孪生的概念,这是一个虚拟机器人,它是物理机器人的孪生兄弟。这是开发机器人应用的基本部分,因为它减少了与测试真实硬件相关的成本。数字孪生使我们能够加快开发过程,并将物理机器人的测试留到开发的高级阶段。
第三部分,使用 SLAM 进行自主导航,专注于机器人导航,这是移动机器人最常见的任务。最先进的算法和技术以实用的方式解释,首先是模拟,然后是使用物理机器人。
第四部分,使用机器学习实现自适应机器人行为,专注于机器学习和强化学习,这是机器人研究和实际机器人应用中最活跃的领域。通过使用这项技术,机器人能够从纯自动化的状态——即每个可能的行为或答案都被编码——过渡到灵活的行为机器,机器人能够通过学习数据以智能的方式对环境需求做出反应。这些数据可以来自机器人的先前经验,也可以从类似机器人的经验中收集。
要构建一个最先进的机器人应用,你首先需要掌握并组合这四个构建模块。结果将是我们通常所说的智能机器人。这就是你的任务——这就是你的挑战。
本书面向的对象
如果你是一名希望使用 ROS 构建 AI 机器人工程师,那么这本书就是为你准备的。希望开发自己的 ROS 机器人项目的技术人员和爱好者也会发现这本书是一个有用的资源。
本书涵盖的内容
第一章,组装机器人,提供了关于本书所有内容所基于的移动机器人的关键概念和实际组装指南。考虑到非常实用的方法,我们深入探讨了 GoPiGo3 的特性,使其成为学习机器人的理想且经济实惠的平台。通过完成 GoPiGo3 的组装,您将获得操作机器人典型组件所需的第一个手动技能。要购买 GoPiGo3 套件,您可以访问 www.dexterindustries.com/gopigo3/,并使用优惠券代码 BRJAPON@PACKT 获得折扣 10%。
第二章,GoPiGo3 的单元测试,为您提供了对 GoPiGo3 工作原理的实用见解。我们通过介绍 JupyterLab 环境,一个友好的界面,它采用由人类可读段落后跟 Python 代码片段组成的笔记本结构来实现这一点。您将为每个测试程序产生两个版本:JupyterLab 笔记本和纯 Python 脚本。使用这些编程工具,您将单独测试每个传感器/执行器,并检查其是否正常工作,同时了解背后的技术。
第三章,ROS 入门,解释了 ROS 的基本概念。它使用易于理解的语言介绍框架,避免使用非常技术性的描述。这是因为我们的主要目标是向您展示 ROS 在概念上的确切含义。在接下来的章节中,将提供深入的技术描述,以便您最终能够将 ROS 集成到您的项目中。
第四章,创建虚拟双轮 ROS 机器人,描述了如何构建一个简单的双轮机器人,它是 GoPiGo3 的数字孪生。该模型以统一机器人描述格式(URDF)编写,并通过 RViz 进行检查,RViz 是一个 ROS 工具,它提供了一个可配置的图形用户界面(GUI),允许用户显示他们所需的具体信息。RViz 可用于全局机器人可视化,以及在构建模型时调试特定功能。
第五章,使用 Gazebo 模拟机器人行为,教您如何将您的机器人数字定义(URDF 文件)插入到 Gazebo 的模拟环境中,Gazebo 是一个具有能够模拟真实行为的物理引擎。您还将了解如何检查和测试数字机器人,以确保其行为在现实中表现得很好。
第六章,ROS 命令和工具编程,向您介绍与 ROS 的命令行交互,并解释 ROS 命令的类型。我们将探讨 ROS 中最常用的通信模式,包括发布-订阅模型。为了处理您所有的 ROS 数据,您将了解 rqt,它简化了开发和调试应用程序的过程。此外,还介绍了 ROS 参数,以让您了解它们在高级别管理机器人配置方面的强大功能。
第七章,机器人控制和仿真,教您如何使用 GoPiGo3 设置真实机器人的 ROS 环境。我们将从使用笔记本电脑键盘的按键进行远程控制开始,然后过渡到更技术性的使用 ROS 主题的方法。本章将引导您从基于键盘和主题的手动控制到内部编程逻辑,以便您的机器人能够自主执行任务。
第八章,使用 Gazebo 进行虚拟 SLAM 和导航,通过实际方法和 GoPiGo3 的数字孪生探索同时定位与建图(SLAM)技术。您将了解为什么在正确导航之前需要 SLAM。仿真将在 Gazebo 中运行,这是具有物理引擎的 ROS 原生仿真工具,可以提供逼真的结果。
第九章,机器人导航中的 SLAM,将重点转向物理 GoPiGo3 机器人。本章突出了在真实环境中面对机器人任务时出现的许多细节和实际问题。仿真是一个好的开始,但通过在实际场景中执行任务来验证您的机器人按预期工作,才是真正的证明。本章是您深入了解机器人导航的起点,如果您想在这个领域继续发展,这将对您的知识库至关重要。
第十章,在机器人学中应用机器学习,旨在对机器人学中的机器学习主题进行温和的介绍,更倾向于直观理解而非复杂的数学公式,并侧重于理解该领域常用的概念。本章中使用的实际示例将涉及 GoPiGo3 的 Pi 摄像头识别物体。
第十一章,使用 OpenAI Gym 进行机器学习,基于简单场景提供了强化学习的理论背景。这一章节让你更好地理解在经典强化训练任务中幕后发生了什么。我们将继续使用实际例子来探索所提出的概念,并使用开源环境 OpenAI Gym,它使我们能够轻松测试来自训练代理、甚至是在 ROS 中驾驶机器人的不同算法。
第十二章,通过强化学习实现目标,在计算机视觉对象识别方面更进一步,表明 GoPiGo3 不仅能感知事物,还能采取步骤实现目标。我们的机器人在模拟的每一步都需要决定执行什么动作以实现目标。执行每个动作后,机器人将获得关于其做出的决策好坏的反馈,形式为奖励。经过一些训练后,奖励的激励将加强并巩固良好的决策。
要充分利用本书
本书采用实践方法来处理事物,并鼓励你使用物理机器人来实践你所学的知识。我们选择 GoPiGo3 (www.dexterindustries.com/gopigo3/),因为它具有模块化、适中的成本,并且基于 Raspberry Pi。你可以在全球范围内的在线商店购买 Raspberry Pi 板。在购买套件中的任何组件之前,我们建议你首先阅读第一章,组装机器人,以获取所有你需要购买的组件的基本信息。要购买 GoPiGo3 套件,你可以访问www.dexterindustries.com/gopigo3/,并使用优惠券代码BRJAPON@PACKT获得 10%的折扣。
为了充分利用本书,需要具备一些 Python 和/或 C++编程知识,以及熟悉如 Raspberry Pi 这样的单板计算机。
最后,你需要一台装有 Ubuntu 16.04 Xenial Xerus 或 Ubuntu 18.04 Bionic Beaver 的笔记本电脑。本书的代码已在这两个操作系统上进行了测试。如果你必须从头开始,我们建议你使用 Ubuntu 18.04,因为它是由 Canonical 提供的最新长期支持(LTS)版本,并将支持到 2023 年 4 月。
你需要的所有安装说明都包含在每个章节开头的技术要求部分。
下载示例代码文件
你可以从www.packt.com上的账户下载本书的示例代码文件。如果你在其他地方购买了本书,你可以访问www.packtpub.com/support并注册,以便将文件直接通过电子邮件发送给你。
您可以通过以下步骤下载代码文件:
-
在www.packt.com登录或注册。
-
选择“支持”标签。
-
点击“代码下载”。
-
在“搜索”框中输入书名,并遵循屏幕上的说明。
文件下载后,请确保使用最新版本解压缩或提取文件夹。
-
Windows 上的 WinRAR/7-Zip
-
Mac 上的 Zipeg/iZip/UnRarX
-
Linux 上的 7-Zip/PeaZip
书籍的代码包也托管在 GitHub 上,地址为github.com/PacktPublishing/Hands-On-ROS-for-Robotics-Programming。如果代码有更新,它将在现有的 GitHub 仓库中更新。
我们还有其他来自我们丰富图书和视频目录的代码包,可在github.com/PacktPublishing/找到。查看它们吧!
下载彩色图像
我们还提供了一份包含本书中使用的截图/图表彩色图像的 PDF 文件。您可以从这里下载:www.packtpub.com/sites/default/files/downloads/9781838551308_ColorImages.pdf。
代码实战
访问以下链接查看代码运行的视频:
使用的约定
本书使用了多种文本约定。
CodeInText:表示文本中的代码单词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 昵称。以下是一个示例:“似乎只有最后一行被执行,即my_gopigo.left()。”
代码块设置如下:
msg_range.header.frame_id = "distance"
msg_range.radiation_type = Range.INFRARED
msg_range.min_range = 0.02
msg_range.max_range = 3.0
当我们希望您注意代码块中的特定部分时,相关的行或项目将以粗体显示:
std_msgs/Header header
uint8 radiation_type
float32 field_of_view
float32 min_range
任何命令行输入或输出都如下所示:
$ cd./Chapter2_Unit_Tests/drivingAround
$ python <name_of_script.py>
粗体:表示新术语、重要单词或屏幕上看到的单词。例如,菜单或对话框中的单词在文本中如下所示。以下是一个示例:“通过点击“检查生命体征”来检查生命体征。”
警告或重要提示如下所示。
小贴士和技巧如下所示。
联系我们
欢迎读者反馈。
一般反馈:如果您对本书的任何方面有疑问,请在邮件主题中提及书名,并通过customercare@packtpub.com给我们发邮件。
勘误表:尽管我们已经尽最大努力确保内容的准确性,但错误仍然可能发生。如果您在本书中发现错误,我们将非常感激您向我们报告。请访问www.packtpub.com/support/errata,选择您的书,点击“勘误表提交表单”链接,并输入详细信息。
盗版: 如果您在互联网上以任何形式发现我们作品的非法副本,如果您能提供位置地址或网站名称,我们将不胜感激。请通过copyright@packt.com与我们联系,并附上材料的链接。
如果您有兴趣成为作者: 如果您在某个领域有专业知识,并且您有兴趣撰写或为书籍做出贡献,请访问 authors.packtpub.com。
评论
请留下评论。一旦您阅读并使用过这本书,为何不在购买它的网站上留下评论呢?潜在读者可以查看并使用您的客观意见来做出购买决定,我们 Packt 可以了解您对我们产品的看法,我们的作者也可以看到他们对书籍的反馈。谢谢!
如需更多关于 Packt 的信息,请访问 packt.com。
第一部分:物理机器人组装和测试
本节主要描述和设置将与本书一起使用的硬件。机械部件,包括传感器和执行器、微控制器和嵌入式计算机,是任何移动机器人的核心硬件特性。将包括运行 GoPiGo3 与 ROS 所需的软件的安装说明。
本节包含以下章节:
-
第一章,组装机器人
-
第二章,GoPiGo3 单元测试
-
第三章,ROS 入门
第一章:组装机器人
本章将为您提供关于本书内容所基于的移动机器人的各种实用组装指南。考虑到非常实用的方法,我们将深入探讨 GoPiGo3 的特点以及它为何是一个理想的机器人学习平台。
首先,我们将关注硬件,并讨论每个机器人所组成的组件,包括机械部件和嵌入式系统、传感器和电机。
在完成 GoPiGo3 组装部分后,您将获得手动技能,以便您可以开始操作机器人中的典型组件。您还将被推动采用在组装机器人时应用部分验证测试的系统化方法,也称为单元测试。
在本章的第一部分介绍了 GoPiGo3 机器人之后,我们将深入解释这些概念,包括嵌入式控制器、GoPiGo3 板和嵌入式计算机 Raspberry Pi。
接下来,我们将描述机器人将使用的传感器和执行器,我们将它们分为我们所说的机电。
最后,我们将为您提供一些有用的指南,以便组装机器人变得简单直接。然后,我们将使用易于启动的软件 DexterOS 测试 GoPiGo3 机器人。尽管我们将在本书的后面部分采用 Ubuntu 作为运行 ROS 的操作系统,但我们建议您从 DexterOS 开始,这样您可以在避免特定软件编程任务的同时熟悉硬件,这些任务将在后面的章节中留出。
在本章中,我们将涵盖以下主题:
-
理解 GoPiGo3 机器人
-
熟悉嵌入式硬件——GoPiGo3 板和 Raspberry Pi
-
深入了解机电——电机、传感器和 2D 摄像头
-
整合所有内容
-
在 DexterOS 下使用 Bloxter(可视化编程)进行硬件测试
理解 GoPiGo3 机器人
GoPiGo3 是由 Dexter Industries 制造的基于 Raspberry Pi 的机器人车。它旨在用作学习机器人技术和编程的教育套件,这两者都是互补的视角,清楚地表明了您应该获得的知识,以成为一名机器人工程师。我们将通过让 Modular Robotics 工程总监 Nicole Parrot 用自己的话来解释这一点来解释这意味着什么:
“GoPiGo 起源于 2014 年初的一次 Kickstarter 活动,当时 Raspberry Pi 还相对较新。最初的用户是爱好者,但很快教师和编程俱乐部志愿者开始将他们的 GoPiGo 分享给学生。这导致了对电路板的各种修改,以使其成为教室适用的机器人。它坚固耐用,功能齐全,并且仍然基于 Raspberry Pi!最新的版本自 2017 年以来一直存在,是一个稳定的平台。”
基于 Raspberry Pi 的机器人课堂中提供了许多优势。它可以使用多种编程语言进行编程,它可以在不使用蓝牙的情况下独立于学校 Wi-Fi,并且它可以直接在板上执行高级应用,如计算机视觉和数据收集。配备 DexterOS 的 GoPiGo 预装了所有科学库。配备 Raspbian for Robots 的 GoPiGo 允许用户安装项目所需的任何库和工具。它包含两个 Python 库:easygopigo3.py 和 gopigo3.py。这两个库都提供了对机器人的高级控制和低级控制,这取决于用户的技能水平。
GoPiGo 已经成为寻求简单、文档齐全的 Raspberry Pi 机器人的大学、研究人员和工程师的首选。
准备好深入机器人学了吗?让我们开始吧!
机器人学视角
从机器人学的角度来看,你将学习如何与基本部件协同工作:
-
电机,它允许机器人从一个点移动到另一个点。在 GoPiGo3 中,我们有内置编码器的直流电机,它们提供精确的运动。这是从 GoPiGo2 升级的主要改进之一,在那里编码器位于电机外部,并且不太准确。
-
传感器,它们从环境中获取信息,例如近物距离、亮度、加速度等。
-
控制器——即 GoPiGo3 红色主板——负责与传感器和执行器的物理接口。这是 GoPiGo3 与物理世界交互的实时组件。
-
一块单板计算机(SBC)Raspberry Pi 3B+,它提供处理能力。因此,它运行在一个操作系统下,通常是基于 Linux 的发行版,从软件角度来看提供了广泛的灵活性。
大多数教育套件仅停留在 3 级控制器;它们不包括 4 级单板计算机。控制器中的软件是一个小的程序(只有一个),它嵌入在板上。每次你想修改机器人的代码时,你必须完全替换现有的程序,并使用 USB 端口上的串行连接从外部计算机中刷新新版本。
这里的一个经典例子是 Arduino 控制的机器人。在这里,Arduino 板扮演着我们的 GoPiGo3 板的角色,如果你曾经使用过它,你一定会记得你需要如何通过 USB 线将新程序从笔记本电脑上的 Arduino IDE 传输到机器人。
编程视角
从编程的角度来看,GoPiGo3 允许你通过学习一个视觉编程语言 Bloxter(Google Blockly 的开源分支,专门为 GoPiGo3 开发)来轻松入门。当涉及到学习编写软件程序的基本概念时,这是一个非常舒适的先决条件。
但如果您正在阅读这本书,我们确信您已经知道如何使用许多可用的语言之一进行编程,即 C、C++、Java、JavaScript 或 Python。Dexter Industries 提供了各种开源库(github.com/DexterInd/GoPiGo3/tree/master/Software),您可以使用这些库来编程 GoPiGo3。以下是一些例子:
-
C
-
C#
-
Go
-
Java
-
Node.js(JavaScript)
-
Python
-
Scratch
无论如何,在本章的第一部分,我们鼓励您只使用 Bloxter 来强调机器人视角,并熟悉您手中的硬件。之后,您可以使用您选择的任何语言,因为有许多可用的 GoPiGo3应用程序编程接口(API)可供选择。
在这本书中,我们将重点关注 Python 作为 ROS(机器人操作系统)编程的主要语言。Python 语言易于学习,同时仍然非常强大,在机器人和计算机科学领域占主导地位。在阅读了第二章中的 Python 示例,“GoPiGo3 单元测试”之后,我们将开始学习机器人操作系统(ROS),它不是一个实际的编程语言,而是为机器人提供开发应用框架的开发应用程序。因此,我们将向您展示如何通过包装器来适应您的 Python 程序,以便它们也可以在 ROS 中作为构建高级功能的部分运行。
当您发现 GoPiGo3 的 Python 代码基础被 ROS 包装后,它能做更多的事情时,您将欣赏这种跳转到 ROS 的附加价值。这个软件升级为 GoPiGo3 提供了一个工具包,使学生、创造者和工程师能够理解机器人是如何工作的。此外,您应该知道 ROS 在专业环境中被广泛使用。
机器人套件和资源
从高层次来看,我们可以将机器人的硬件分为两组:
-
机电学:这指的是允许它与物理世界交互的传感器和执行器。
-
嵌入式硬件:允许它从传感器获取信号,将其转换为数字信号,并提供处理逻辑并向执行器发送命令的电子板。在这里,我们通常有两种类型的电子板:
-
控制器,它作为与传感器和执行器的物理接口——即 GoPiGo3 板。控制器处理来自机电设备的模拟和数字信号,将它们转换为 CPU 可以处理的数字信号。
-
计算机,它为我们提供了实现智能逻辑的手段。在大多数机器人中,这是一个 SBC(单板计算机)。在 GoPiGo3 的情况下,这是一个运行 Linux 操作系统发行版的 Raspberry Pi,例如 Raspbian 或 Ubuntu。
-
尽管您可以直接通过树莓派的通用输入/输出(GPIO)引脚将数字设备连接到树莓派,但从功能角度来看,最好通过控制器——即 GoPiGo3 板——将所有传感器和执行器进行接口——也就是说,保持与物理世界的接口在控制器层面,并在计算机层面进行处理和计算。
如果您是经常使用树莓派的用户并且拥有该板,您只需要购买 GoPiGo3 机器人基础套件(www.dexterindustries.com/product/gopigo3-robot-base-kit/)。该套件包括以下内容:
-
GoPiGo3 板(红色板)
-
底盘(框架、轮子、硬件)
-
电机
-
编码器
-
电源电池组和电缆
-
组装用的螺丝刀
以下图片展示了所有包含的部件:
https://github.com/OpenDocCN/freelearn-python-zh/raw/master/docs/hsn-ros-rbt-prog/img/),该套件包括树莓派 3 及其配件,以及一个配备伺服电机的可转向距离传感器,使其能够覆盖 180°的视野。此传感器套件由以下组成:
-
距离传感器([
www.dexterindustries.com/product/distance-sensor/](https://www.dexterindustries.com/product/distance-sensor/)) -
伺服包([https://www.dexterindustries.com/product/servo-package/](https://www.dexterindustries.com/product/servo-package/))
以下图片展示了组装完成的初学者入门套件最终的外观。通过添加树莓派和可转向的距离传感器,使用机器人基础套件也能得到相同的结果:
https://github.com/OpenDocCN/freelearn-python-zh/raw/master/docs/hsn-ros-rbt-prog/img/)提供了控制器所期望的一般功能:
-
与传感器和执行器进行实时通信。
-
通过串行外设接口(SPI)进行输入/输出(I/O)接口,该接口将传感器的数据传输到 Raspberry Pi,并且也可能接收对执行器的命令(也来自 Raspberry Pi,在它的 CPU 中运行控制循环的每一步逻辑之后)。
-
在板上加载的单个程序称为固件。由于该软件的目标是在计算机实现逻辑的同时实现通信协议,因此除非你决定在可用新版本时升级它,否则不需要对其进行更改。
让我们简要解释一下我们在前面的项目符号列表中提到的输入/输出接口协议。SPI 是一个用于在微控制器和外部设备之间发送数据的总线,在我们的例子中是传感器。它使用独立的时钟和数据线,以及一个选择线来选择要与之通信的设备。生成时钟的连接端称为主设备,在我们的例子中是 Raspberry Pi,而另一端称为从设备,即 GoPiGo3 板。这样,两个板就同步了,比异步串行通信更快,后者是通用板(如 Arduino)中的典型通信协议。
你可以在learn.sparkfun.com/tutorials/serial-peripheral-interface-spi的简单教程中了解更多关于 SPI 协议的信息。通过 SPI 与 Raspberry Pi 进行通信是通过引脚接口进行的,这可以在以下图像的顶部部分看到。只需要 40 个 GPIO 引脚中的 5 个用于此类接口:
图片来源:Dexter Industries: https://32414320wji53mwwch1u68ce-wpengine.netdna-ssl.com/wp-content/uploads/2014/07/GoPiGo3-Bottom_annotated-600x441.jpg
为了与设备接口,该板提供了以下功能(板的俯视图可以在下一张图中看到):
-
两个 I2C 端口——两个 Grove 端口通过电平转换芯片连接到 Raspberry Pi 的 I2C 总线
-
一个串行端口——一个 Grove 端口通过电平转换芯片连接到 Raspberry Pi 的串行引脚
-
两个模拟-数字端口——两个连接到 GoPiGo3 微控制器的 Grove 端口
-
两个 PWM 类型伺服电机的伺服端口:
图片来源:Dexter Industries: https://32414320wji53mwwch1u68ce-wpengine.netdna-ssl.com/wp-content/uploads/2014/07/GoPiGo3-Top-768x565.jpg
让我们解释这些新概念:
-
串行端口:这是我们之前在讨论 SPI 时提到的互补通信协议。虽然后者是同步的(需要五个接口引脚),但串行端口是异步的——也就是说,没有时钟信号需要跟随,只需要两个引脚:Tx用于数据传输和Rx用于数据接收。在 GoPiGo3 中,此端口通过一个电平转换芯片直接连接到 Raspberry Pi 的串行引脚。
-
I2C 端口:正如其名称所示,它使用 I2C 通信协议。就像 SPI 一样,它是一个同步协议,比异步串行更快。I2C 使用两条线,SDA用于数据,SCL用于时钟信号。第三和第四条线是用于电源供应的:VIN为 5V 和GND接地——即 0V 参考。SDA是双向的,因此任何连接的设备都可以发送或接收数据。在这两个端口中,你将连接距离传感器和线跟随传感器。
-
模拟-数字:这些端口可以连接到模拟、数字或 I2C Grove 设备。我们将连接到一个模拟-数字端口,即 IMU 传感器。我们将在稍后详细讨论这一点。
-
伺服端口,连接 PWM 伺服电机:这些端口比配备编码器的电机便宜且易于控制,同时提供足够的精度来控制它们将支持的方位。在 GoPiGo3 中,我们可以将距离传感器或 Pi 摄像头连接到伺服电机。脉冲宽度调制(PWM)技术指的是通过改变电压供应的占空比来在连续范围内进行控制,从而产生从 0V 到 5V 的等效输出:0V 是 0%占空比,而 100%对应于在整个周期内施加 5V。通过在周期中应用低于 100%的百分比 5V,你可以获得对位置的连续控制,范围从 0 到 180°的电机轴旋转。有关此内容的解释和一些有用的图表,请访问
www.jameco.com/jameco/workshop/howitworks/how-servo-motors-work.html。
Raspberry Pi 3B+
Raspberry Pi 在教育领域和工业领域都有最大的社区,这使得它成为开发机器人或物联网(IoT)设备嵌入式软件的最佳单板计算机选择。以下图像显示了 Raspberry Pi 3B+,这是为 GoPiGo3 供电的最常见型号:
图片来源:https://en.wikipedia.org/wiki/File:Raspberry_Pi_3_B%2B_(39906369025).png, 许可证 CC BY-SA 2.0
Raspberry Pi 3B+ 的主要特性如下:
-
由四个 Cortex-A53 1.4 GHz 组成的 中央处理单元(CPU)。
-
图形处理单元(GPU)是 250 MHz 的 Broadcom VideoCore IV。
-
同步动态随机存取存储器(SDRAM)为 1 GB,与 GPU 共享。
-
板载存储通过 MicroSDHC 插槽提供。您可以选择任何适合您需求的 micro SD 卡大小。无论如何,一般建议使用 16 GB 容量的 10 级 micro SD 卡——10 表示它能够以 10 Mb/second 的速度写入。
让我们回顾一下这些组件的功能:
-
CPU 提供了运行各种算法的计算能力。这正是我们机器人智能所在之处。
-
GPU 的任务是处理计算机图形和图像处理。在我们的案例中,它将主要致力于处理 Pi 相机的图像并提供计算机视觉功能。
-
SDRAM 有 1 GB 易失性存储,与 GPU 共享,因此这是您分配给 GPU 的内存量(默认情况下,它最多占用 64 Mb)。RAM 是程序加载并执行的地方。
-
板载 microSD 卡是包含操作系统以及所有已安装软件的持久存储。
Raspberry Pi 运行操作系统,通常是基于 Linux 的发行版,如 Debian 或 Ubuntu。
虽然基于 Debian 的 Raspbian 是 Raspberry Pi 基金会的官方发行版,但我们将使用由 Canonical 支持的 Ubuntu,因为这是 Open Robotics (www.openrobotics.org) 每年提供 ROS 版本的平台,与 Ubuntu 的年度版本同步。
为什么机器人需要 CPU?
除了这本书的目标是让您获得一些 ROS 的实际操作经验——为此,您需要 Linux 操作系统来安装软件——如果您真的想创建一个智能机器人,您需要运行计算密集型算法的处理能力,这正是 Raspberry Pi 等 CPU 所提供的。
为什么这个计算是必要的?因为一个智能机器人必须将环境信息与当前任务的逻辑相结合,才能成功完成它。让我们以将一个物体从当前位置移动到目标位置为例。为此,激光距离传感器、3D 相机和/或 GPS 等设备为机器人提供环境信息。这些数据源必须结合起来,以便机器人能够在环境中定位自己。通过提供目标位置,它还必须计算将物体携带到那里的最佳路径,这被称为路径规划。在执行这样的路径规划时,它必须检测路径上可能出现的障碍物并避开它们,同时不失目标。因此,任务的每一步都涉及到在机器人的 CPU 中执行一个算法。
这就是您将学会使用 ROS 解决的大量实际场景之一,ROS 目前是机器人应用开发的事实标准。
深入了解机电一体化
如 GoPiGo 官方文档www.dexterindustries.com/GoPiGo/learning/technical-specifications-for-the-gopigo-raspberry-pi-robotics-kit/所述,GoPiGo3 机器人的规格如下:
-
工作电压:7V-12V
-
外部接口:
-
I2C 端口:两个连接到 Raspberry Pi I2C 总线的 Grove 端口,通过一个电平转换芯片
-
串行端口:一个连接到 Raspberry Pi 串行引脚的 Grove 端口,通过一个电平转换芯片
-
模拟数字端口:两个连接到 GoPiGo3 微控制器的 Grove 端口
-
-
编码器:两个每转六脉冲计数的磁性编码器(通过 120:1 的齿轮减速,每轮旋转总共 720 个脉冲)
-
车轮直径:66.5 毫米
-
车轮间距:117 毫米
-
更多信息:设计信息可在官方 GitHub 仓库
github.com/DexterInd/GoPiGo3找到
这只是对我们之前在标题为GoPiGo3 板的章节中解释的内容的总结。在本节中,我们将专注于描述连接到 GoPiGo3 板的设备。
最有用的传感器
我们将要安装到 GoPiGo3 上的传感器是我们完成机器人顶级任务(即低成本的运动规划导航)所需的传感器。以下是一些传感器:
-
距离传感器
-
跟踪线
-
惯性测量单元(IMU)传感器
-
2D 相机
在使用循线传感器的情况下,由于机器人将跟随地板上标记的路径(通常是黑色),可以跳过运动规划部分,导航将变得容易得多。如果路径上有障碍物,你必须应用一个算法来绕过障碍物并返回路径——也就是说,将循线传感器再次放置在黑线上方。
现在,我们应该花时间了解每个传感器提供的信息。在这本书的后面部分,你将遇到这样的导航问题以及可以用来实现它的算法。
距离传感器
简单的距离传感器使我们能够测量其前方物体的距离。它有一个小激光器,用于测量到物体的距离。传感器使用飞行时间方法进行非常快速和精确的距离读取。产品页面可在www.dexterindustries.com/product/distance-sensor/查看:
图片来源:Dexter Industries:https://shop.dexterindustries.com/media/catalog/product/cache/4/image/1800x2400/9df78eab33525d08d6e5fb8d27136e95/d/e/dexter-industries-raspberry-pi-robot-distance-sensor-for-robots-front-of-sensor-1.jpg
你可以将距离传感器连接到任意的两个 I2C 端口之一。请注意,GoPiGo3 软件库不会要求你指定使用哪个端口。这将被自动检测。
你可以将传感器安装到伺服包上,以扫描大约 180°的宽角度。伺服电机可以连接到伺服端口 1 或伺服端口 2。产品页面可在www.dexterindustries.com/product/servo-package/查看:
图片来源:Modular Robotics:https://www.dexterindustries.com/wp-content/uploads/2019/09/GoPiGo3-Molded-Servo-Frontal-300x200.jpg
在第二章“GoPiGo3 单元测试”中,有一个你可以用你的机器人运行的特定测试,以检查这个单元是否正常工作。
循线传感器
GoPiGo3 的循线传感器由六对 LED 光电晶体管组成。当你将传感器放在面前读取字母时,LED 发射器是每对中最右边的一部分。这可以在以下照片中看到,这是一张有电源的传感器的图片,尽管你此时还看不到 LED 的光束:
为什么在图片中看不到它们?因为 LED 发出红外光,人眼无法检测到;然而,手机摄像头可以揭示它(默认情况下,这些摄像头的光学系统不包括红外滤光片)。所以,如果您后来发现线跟踪器工作不正常,您必须首先检查硬件。为此,只需用智能手机的相机应用程序拍照即可。
在下面的图像中,传感器视图被有意模糊处理,以便您可以看到光线并确认光线是从 LED 光敏晶体管的右侧发出的。接收部分,即光敏晶体管,是检测是否有从 LED 发射器反射的光线的组件。该组件的产品页面可在www.dexterindustries.com/product/line-follower-sensor/查看:
现在,您已经可以理解线跟踪传感器的原理了:
-
如果光线因为地板是白色的而反射,光敏晶体管就会接收到反射的光束,并在数据传感器流中提供这一信息。
-
如果传感器位于黑色表面上,光敏晶体管不会接收到任何反射光线,并让机器人知道。
反射会使传感器电子报告的信号接近 1(白色表面),而吸收则提供接近 0 的值(黑色表面)。但是,如果传感器离地板很远或者没有面向它呢?好吧,从传感器的角度来看,吸收等同于没有反射。因此,报告的信号接近零。这一特性使得 GoPiGo3 不仅能跟随地面上的黑色路径,还能沿着边缘行走,避免可能损坏机器人的凹坑。
由于您有六对,您将拥有六个信号,每个信号报告 0 或 1。这六个数字将使我们能够推断出机器人在黑色线上的中心位置有多好。传感器的规格如下:
-
带有 Grove 连接器的 I2C 传感器。
-
六个模拟传感器,每个传感器根据从地板接收到的光线量给出 0 到 1 之间的值,其中 0 表示黑色,1 表示白色。
-
传感器可以以高达 120 Hz 的频率轮询。
-
一个简单的库(
di-sensors.readthedocs.io/en/master/api-basic.html#easylinefollower)和一个驱动级库(di-sensors.readthedocs.io/en/master/api-advanced.html#linefollower)可用,并且完全有文档记录。简单的库提供了为您做繁重工作的方法。
以下是从发射器-接收器底部的视图。这个面必须比地板高出几毫米,以确保 LED 发射的正确反射:
图片来源:Modular Robotics:https://shop.dexterindustries.com/media/catalog/product/cache/4/thumbnail/1800x2400/9df78eab33525d08d6e5fb8d27136e95/l/i/linefollower_bottom.jpg
以下图片显示了线跟踪传感器正确安装在 GoPiGo3 上——即在地板上方:
图片来源:Modular Robotics:http://www.dexterindustries.com/wp-content/uploads/2019/03/linefollowerinaction.jpg
有关如何组装和校准传感器的说明,请访问 www.dexterindustries.com/GoPiGo/line-follower-v2-black-board-getting-started/。对于连接,你可以使用线跟踪传感器上可用的两个 I2C 连接器中的任何一个。请记住,其中一个将被距离传感器使用。
如果你使用 Raspbian For Robots (www.dexterindustries.com/raspberry-pi-robot-software/),线跟踪器也可以连接到 AD 端口之一。它适用于更高级的使用,并且为此配置编写的代码略有不同。
为了介绍机器人技术,我们将通过将传感器连接到 I2C 端口并使用更友好的 DexterOS (www.dexterindustries.com/dexteros/) 来简化操作。在 第二章 GoPiGo3 的单元测试 中,我们将介绍你可以运行的具体测试,以检查该单元是否正常工作。
IMU 传感器
IMU 传感器使我们能够测量机器人的方向,以及在其移动过程中获得其位置的估计。Dexter Industries IMU 的产品页面可以在 www.dexterindustries.com/product/imu-sensor/ 查看。传感器的相应方面可以在以下图片中看到:
图片来源:Dexter Industries:https://shop.dexterindustries.com/media/catalog/product/cache/4/thumbnail/1800x2400/9df78eab33525d08d6e5fb8d27136e95/i/m/imu-sensor_mount2-800x800.jpg
在以下图片中,你可以看到它安装在 GoPiGo3 上。要连接到机器人,你只需将其插入 GoPiGo 板上的 AD1 或 AD2 即可:
图片来源:Dexter Industries:https://shop.dexterindustries.com/media/catalog/product/cache/4/thumbnail/1800x2400/9df78eab33525d08d6e5fb8d27136e95/i/m/imu-sensor_gpg3_3.jpg
此 IMU 有九个 自由度(DOF),以及温度测量功能。让我们来谈谈 IMU 的每个传感器以及它们提供的数据类型:
-
让我们从更简单的一个开始,即温度。这提供了环境室温,可以与其它传感器结合使用,例如,通过在 GoPiGo3 覆盖的表面多个位置进行测量,创建一个房间的温度图。
-
加速度计是一个绝对传感器,因为它的值始终参照为零加速度(静止物体)。它为三个轴——X, Y, 和 Z——提供值:
-
它适合测量机器人的倾斜度(一个余弦值为垂直加速度除以重力值=9.81 m/s²的角度)和自由落体状态,这相当于一个 90°的斜坡,是一个垂直墙面(传感器持续检测重力,即 9.81 m/s²,如果物体保持在水平面上)。
-
加速度计在测量速度方面并不准确,因为传感器没有直接提供这个值。我们可以通过在时间上对加速度信号进行积分来获得它,这会产生累积误差(漂移),主要来自传感器噪声(电子)和测量误差本身。这就是陀螺仪发挥作用以提供准确速度测量的地方。
-
陀螺仪是一个差分传感器,它相对于任意参考提供了三个旋转(X, Y, 和 Z 轴)。它们实际上提供的是旋转速度。这意味着它们在测量旋转速度方面很准确,但不适合测量角位置(你必须对速度信号进行时间积分,积累测量误差和传感器噪声,从而产生漂移)。
-
一个六自由度 IMU 将是一个结合了加速度计(三个自由度)和陀螺仪(三个自由度)的设备:
-
加速度计可以准确地测量相对于垂直的倾斜度。它在中等/长期测量中没有漂移,但短期测量不准确。
-
陀螺仪可以准确地测量旋转速度,但它们有漂移。这意味着它们不适合中等/长期测量。
通过结合加速度计和陀螺仪的六个值,可以获得一个改进的测量方向。这通过以下图中的欧拉角——α, β, γ——来表示:
图片来源:https://commons.wikimedia.org/wiki/File:Euler_angles_zxz_int%2Baxes.png,许可协议 CC BY-SA 4.0
比欧拉角更常用的方法是 Tait-Bryan 版本或导航角,即偏航-俯仰-横滚角,其定义如下:
图片来源:https://es.m.wikipedia.org/wiki/Archivo:Flight_dynamics_with_text.png,许可协议 CC BY-SA 3.0
这些角度是通过应用一个特殊的滤波器,称为互补滤波器,到传感器的信号中获得的。它的工作原理如下:
-
对于加速度计的信号,它表现为低通滤波器,因为我们信任它的中/长期测量。
-
对于陀螺仪的信号,它表现为高通滤波器,因为我们信任它的短期测量。
从数学上讲,互补滤波器表示如下:
在这里,A 和 B 的和必须为 1。这些常数由传感器的校准确定,典型值包括 A = 0.98,B = 0.02。互补滤波器提供与卡尔曼滤波器非常相似的结果,卡尔曼滤波器是最佳线性(无偏)估计器(BLE),但计算量更大。
现在,我们有三个旋转(关于 X、Y、Z 轴),但它们还不是绝对角度:
-
多亏了加速度计,相对于垂直方向的姿态是一个绝对参考,但对于水平平面上的姿态,我们缺少这样的参考,因为陀螺仪是一个差分传感器。
-
这就是磁力计似乎给我们提供地球磁场(三个轴 X、Y、Z)的方向。
因此,使用我们的 6 + 3 = 9 个自由度 IMU,我们有了机器人的绝对姿态,以重力场和磁场矢量作为参考。在第二章,GoPiGo3 的单元测试中,我们将介绍你可以用你的机器人运行的一个特定测试来检查这个单元是否正常工作。
Pi 相机
Pi 相机是一个定制的 2D 相机,具有相机串行接口(CSI)。下面的图像显示了两个物理组件——即相机的电子板和带状电缆:
图片来源:https://commons.wikimedia.org/wiki/File:Raspberry_Pi_Camera_Module_v2_with_ribbon.jpg, 许可证 CC BY-SA 4.0
在下面的图像中,我们可以看到如何将带子连接到 Raspberry Pi 的 CSI 端口:
图片来源:https://www.flickr.com/photos/nez/9398354549/in/photostream by Andrew,许可证:CC BY-SA 2.0
Pi 相机能够提供高达 30 帧每秒(FPS)的 HD 分辨率(1920 x 1080 像素)。你可以在picamera.readthedocs.io/en/release-1.12/fov.html的文档中找到可能的配置。在第二章,GoPiGo3 的单元测试中,我们将介绍你可以用你的机器人运行的一个特定测试来检查这个单元是否正常工作。
将所有这些放在一起
现在您已经熟悉了硬件,是时候将所有部件组装起来,连接它们,并进行快速测试以检查 GoPiGo3 是否正常工作。组装过程在官方文档中有详细的步骤说明,包括大量的图表和照片;您可以在www.dexterindustries.com/GoPiGo/get-started-with-the-gopigo3-raspberry-pi-robot/1-assemble-gopigo3/找到这份文档。
或者,您可以使用edu.workbencheducation.com/上的 Workbench 培训环境,并免费注册一个个人账户,在注册进度的同时完成相同的组装过程。如果您这样做,请按照制造商官方文档中的两个组装阶段进行操作:
-
GoPiGo3 组装阶段 1:
edu.workbencheducation.com/cwists/preview/26659-build-your-gopigo3-stage-1x -
GoPiGo3 组装阶段 2:
edu.workbencheducation.com/cwists/preview/26655-build-your-gopigo3-stage-2x
请注意,每个电机的电缆必须插入同一侧的连接器。如果您反方向操作,那么当您使用 GoPiGo3 API 库命令前进时,机器人会向后移动,反之亦然。如果您遇到这种情况,您只需交换连接器,使其正常工作。
要安装 Pi 相机,请按照www.dexterindustries.com/GoPiGo/get-started-with-the-gopigo3-raspberry-pi-robot/4-attach-the-camera-and-distance-sensor-to-the-raspberry-pi-robot上的说明进行。这些说明扩展了 Raspberry Pi 部分。
组装好基础套件后,您可以继续安装传感器:
-
对于循线传感器,您可以按照
www.dexterindustries.com/GoPiGo/line-follower-v2-black-board-getting-started/上的说明进行操作。 -
要安装距离传感器,您可以观看
www.youtube.com/watch?v=R7BlvxPCll4上的视频。这个视频展示了如何将 Pi 相机安装在 Sero 套件顶部,但您也可以安装距离传感器。 -
对于 IMU 传感器,将其插入一个模拟-数字 Grove 连接器(AD1 或 AD2)中,并确保其方向正确,如以下图片所示(参见X、Y和Z轴的方向)。
以下图片显示了连接了三个传感器的 GoPiGo3:
注意,IMU 传感器的Z轴应指向前方,X轴应指向左轮,因此Y轴应沿着垂直轴向上。当正确校准并放置在水平表面上时,两个角度,俯仰和横滚,将为零,如果Z指向磁南,偏航角度也将为零。
快速硬件测试
为了快速测试并专注于手头的硬件,我们将使用 DexterOS,这是 Dexter Industries 创建的基于 Raspbian 的发行版,允许用户快速开始。操作系统的详细信息可在www.dexterindustries.com/dexteros/找到。Dexter Industries 通过提供一个简单的网络环境,简化了界面,无需处理完整的 Linux 桌面。
你可以通过连接到名为 GoPiGo 的 Wi-Fi 接入点来访问它(不需要密码)。这样,你将直接通过你的笔记本电脑连接到机器人。在安装之前,让我们回顾一下我们可用的资源。
资源
在与机器人一起工作时,你将至少管理以下三个网站/仓库:
-
在 GitHub 上托管由 Dexter Industries 提供的官方库。具体如下:
-
GoPiGo3 官方库:
github.com/DexterInd/GoPiGo3。这个仓库不仅包含多种语言的 API(Python、Scratch、C、JavaScript、Go 等),还包含示例和完整的项目,其中一些我们将在下一章中使用,以扩展到 ROS。 -
DI 传感器库:
github.com/DexterInd/DI_Sensors。这个仓库涵盖了 Dexter Industries 提供的所有传感器,不仅限于 GoPiGo3 中使用的传感器。它为 Python、Scratch、C#和 Node.js 提供了 API。 -
基于 Web 的学习平台:
edu.workbencheducation.com/。如果你是从零开始,这是一个针对 GoPiGo3 的指导培训网站。
-
开始使用 DexterOS
在完成“整合一切”部分的第 1 步和第 2 步后,你应该通过www.dexterindustries.com/dexteros/get-dexteros-operating-system-for-raspberry-pi-robotics/中的步骤,在那里你可以下载操作系统的映像文件,并按照说明使用 Etcher 应用程序([www.balena.io/etcher/](https://www.balena.io/etcher/))烧录微 SD 卡。按照以下步骤开始使用 DexterOS:
-
一旦你将卡插入 Raspberry Pi 的插槽中,打开 GoPiGo 板并连接到它创建的 Wi-Fi 网络(其 SSID 为 GoPiGo,无需密码)。
-
之后,前往http://mygopigo.com或
http://10.10.10.10以访问机器人的环境,首页看起来如下。你可以在edu.workbencheducation.com/cwists/preview/26657x找到逐步操作流程:
请注意,如果你保持笔记本电脑的互联网连接(有线),那么你应该连接到机器人的 IP 地址http://10.10.10.10。如果你需要帮助,你可以访问 DexterOS 论坛forum.dexterindustries.com/c/DexterOS。
从这一点开始,正如你在首页上看到的那样,你可以做以下事情:
-
DRIVE:通过基本控制面板在所有方向上移动机器人。
-
LEARN:通过在 Bloxter 中遵循引导教程——我们选择的语言之一——或使用 Jupyter Lab 笔记本的 Python。
-
使用 Bloxter 编写代码:基于 Google 的开源 Blockly 的可视化编程语言(
github.com/google/blockly)。 -
使用 Python 编写代码:我们将用它来开发我们的机器人训练。
接下来,我们将开始使用 Bloxter 进行编码。
使用 Bloxter 进行编码
在可用的编程语言中,Bloxter为你提供了在不涉及编写代码的复杂性下学习机器人的机会。使用可视化界面,你可以排列和连接模块,并快速开发基本的程序来控制 GoPiGo3。让我们开始吧:
- 通过在首页上点击“LEARN”,然后点击“Bloxter 中的课程”,你可以访问可用的课程,如下面的截图所示:
- 选择你喜欢的,考虑到它们是按难度递增排序的:
在开始第二章,GoPiGo3 单元测试之前,建议你完成 Bloxter 部分的 LEARN 部分。课程易于跟随,并且它们会教你比仅仅阅读文档更多的关于 GoPiGo3 的知识。
校准机器人
按照以下步骤校准机器人:
- 返回主页面,点击
mygopigo.com/,然后在首页右上角的图标上点击。会出现一个帮助屏幕,包含两个按钮,一个用于校准,另一个用于检查电池状态,如下面的截图所示:
- 点击“检查生命体征”来检查生命体征:
- 现在,点击前面的按钮,测试你机器人的精度并进行校准。你会看到以下屏幕:
-
调整尺寸,使其与你的机器人尺寸相匹配:
-
轮径: 在地面上标记 2 米的距离,然后点击驱动 2m按钮。如果 GoPiGo3 刚好到达终点线,66.5 毫米是合适的。如果没有到达,你应该稍微增加直径;如果超过了终点线,你应该减少它。再次测试。通过试错,你会找到最适合你自己的机器人的直径。
-
车轮之间的距离: 这个过程非常相似,唯一的区别是,在这种情况下,当你按下旋转一周时,机器人将围绕自身旋转。如果 GoPiGo3 完成 360°的完整旋转,117 毫米是合适的。如果没有完成旋转,你应该减少距离;如果旋转超过 360°,你应该增加它。再次测试。通过试错,你将能够调整这个距离,就像调整轮径一样。
-
驾驶机器人
要驾驶机器人,请按照以下步骤操作:
-
关闭帮助窗口,并在主页上选择DRIVE项。
-
通过点击此按钮,你可以访问一个面板,其中包含用于移动机器人前后和旋转左右的控制按钮。继续检查 GoPiGo3 是否按预期移动。
-
每当你需要停止运动时,请按键盘上的空格键:
接下来,我们将检查传感器。
检查传感器
按照以下步骤检查传感器:
-
返回主页并点击Code in Bloxter。
-
在屏幕的右侧,你会看到一个滑动窗口,你可以在这里指定连接到每个传感器的端口。在我们的示例中,我们设置了以下配置:
-
将距离传感器插入 I2C-1,GoPiGo3 左侧的 I2C 接口
-
循线传感器连接到 I2C-2,GoPiGo3 右侧的 I2C 接口
-
IMU传感器连接到 AD1(左侧)
-
-
一旦你在 DexterOS 中选择了一个端口,你将能够为出现的每个下拉菜单进行选择,这些都是关于来自传感器的实时数据,如下面的截图所示:
-
检查所有三个——即距离传感器、循线传感器和 IMU——以提供读数。在距离传感器中,你可能会得到一个错误未知的消息。不要担心,传感器并没有损坏,只是软件的一个错误。在我们下一章使用 Python 时,你肯定会获得良好的读数。
-
最后,让我们看看更复杂的传感器——IMU 的数据。在将其连接到 AD1 后,当您选择“惯性测量单元”或“惯性测量单元(数据)”时,窗口会提示您——将机器人空转 3 秒钟以校准其方向。这样,我们通过结合地球的重力和磁场来获得绝对方向参考。然后,如果我们从下拉列表中选择“惯性测量单元”,我们将看到实时报告的欧拉角度。如果它们已经正确校准,我们应该找到以下内容:
-
当 GoPiGo3 在水平表面上并且面向东方时,欧拉航向(偏航、俯仰和滚转)的三个角度都是零。在这种情况下,Z轴(在传感器上涂有颜色)指向南方。
-
在这个位置,如果你用手围绕Z轴旋转 GoPiGo3 超过 90°,那么滚转角度将是 90°,X轴将指向向上(指向天顶)。
-
回到原始位置,如果你用手围绕X轴旋转 GoPiGo3 +90°,俯仰角度将是 90°,Y轴将指向南方。
-
GoPiGo3 中 IMU 的物理位置可以在以下图片中看到:
在下一章中,我们将学习如何使用 Pi Camera,当我们使用 Python 编程机器人时。
关闭机器人
要完成您与 GoPiGo3 的第一段旅程,只需长时间按住 GoPiGo 红色板上的黑色按钮。几秒钟后,红色 LED 将停止闪烁,这意味着关闭过程已完成。
摘要
在本章中,我们通过了解套件中传感器和电机的物理原理,熟悉了 GoPiGo3 硬件。我们通过运行一些快速测试来检查它们是否正常工作,以便我们可以开始编程任务。
在下一章中,我们将学习如何使用 Python 编程 GoPiGo3,同时为它的每个主要组件执行一些单元测试:伺服电机、距离传感器、线跟踪器、IMU 和 Pi Camera。
问题
- 机器人是否必须配备像 Raspberry Pi 这样的计算机?
A) 是的,因为计算机为控制板供电。
B) 不,因为计算机只需要在屏幕上可视化软件代码。如果已经将程序烧录到控制器中,它可能可以独立工作。
C) 并非真的;你可以编写一个小程序来控制机器人,并将其烧录到控制器的芯片上。每次你给机器人供电时,它都会在无限循环中执行程序。
- GoPiGo3 的距离传感器发射什么类型的辐射?
A) 激光
B) 红外线
C) 超声波
- 为什么你看不到线跟踪传感器发出的光?
A) 因为传感器必须先通过软件命令预先激活
B) 它不发射光,而是一个磁场
C) 它在可见光范围内不发射任何东西
- GoPiGo 红板上的串行端口有什么用途?
A) 为了让我们能够以与 Arduino 板相同的方式编程它,在那里您使用串行端口将程序烧录到微控制器的芯片上。
B) 为了从传感器同步传输数据到板。
C) 为了从 Raspberry Pi 访问 GPIO 的串行引脚。
- IMU 传感器是否提供机器人的绝对方向?
A) 是的,因为这是将加速度计和陀螺仪放在一起的目标。
B) 只有当 IMU 包含磁力计。
C) 只有在具有六个自由度的 IMU 传感器的情况下。
进一步阅读
您可以通过阅读制造商提供的详尽官方文档来了解更多关于 GoPiGo3 的功能:
-
Dexter Industries GoPiGo3 文档:
gopigo3.readthedocs.io -
Dexter Industries DI-Sensors 文档:
di-sensors.readthedocs.io -
Pi 相机文档:
picamera.readthedocs.io/
第二章:GoPiGo3 的单元测试
在完成硬件组装后,在本章中,您将通过 JupyterLab 环境熟悉 GoPiGo3 的工作方式,这是一个友好的界面,它采用由人类可读段落和 Python 代码片段组成的笔记本结构。您将为每个测试程序产生两个版本:JupyterLab 笔记本和纯 Python 脚本。
使用这些编程工具,您将单独测试每个传感器/执行器,并检查它们是否正常工作,同时了解每个技术背后的知识。
我们将涵盖以下主题:
-
在 Jupyterlab 友好的环境中开始 Python 编程
-
测试机器人感知:距离传感器、循线传感器和 2D
-
测试机器人动作:电机和编码器
如果您遵循实际练习,您将了解不同的包(传感器、电机等)如何构建整个机器人,传感器测量了什么,以及如何系统地测试传感器和执行器。
技术要求
第一部分的代码,Python 和 Jupyterlab 入门,包含在 GoPiGo3 制造商提供的自定义操作系统 DexterOS 的图像中。在第一章组装机器人中,我们解释了如何获取此图像并将其烧录到 SD 卡中。这已在快速硬件测试部分和DexterOS 入门子部分的入门部分中解释。
本章的代码位于本书的 GitHub 仓库中,位于github.com/PacktPublishing/Hands-On-ROS-for-Robotics-Programming/tree/master/Chapter2_Unit_Tests.在单元测试传感器和驱动器部分的开始,我们解释了如何在 Raspberry Pi 上本地克隆代码。
在 Jupyterlab 友好的环境中开始 Python 编程
JupyterLab 是 Python 社区中的一个非常全面的工具,因为它允许您编写程序,就像在学校课堂上解决数学问题一样。也就是说,您编写标题,然后是问题陈述和初始数据。在此声明之后,您编写一个段落来解释您将要执行的操作,然后编写执行该操作的 Python 行(代码单元格)。对于每个操作,您重复相同的步骤:
-
一个人类可读的段落解释下一个操作,该段落使用众所周知的 markdown 语法 格式化。
commonmark.org/help/ -
包含执行操作的 Python 代码行的代码单元格。
-
对每个执行单个操作的代码片段重复步骤 1 和 2。最后一个将提供问题的解决方案。
这里有一个自解释的示例,用于读取 GoPiGo3 的距离传感器:
接下来,我们将解释如何为 GoPiGo3 启动 JupyterLab。
启动 GoPiGo3 的 JupyterLab
在 DexterOS 中,你有两个课程解释了 Jupyter 笔记本和用 Python 控制机器人:
- 你可以通过访问
http://mygopigo.com或http://10.10.10.10来访问它们,然后点击 LEARN,然后点击 Python 中的课程:
然后启动 JupyterLab 环境,在窗口的左侧你会看到两个文件:
-
-
1_Moving_Around.ipynb是一个 Jupyter 笔记本,逐步解释了如何让机器人前进和旋转。按照笔记本中的说明执行命令。 -
2_The_Environment.ipynb是另一个例子,解释了如何处理 JupyterLab:运行一个单元、停止执行等等。如果你在前一个笔记本中遇到了困难,请按照这个笔记本操作,然后返回到第一个笔记本。
-
- 现在我们尝试
1_Moving_Around.ipynb。以下命令使机器人前进 10 厘米:
my_gopigo.drive_cm(10)
- 如果你更喜欢用英寸工作,使用这个命令:
my_gopigo.drive_inches(10)
- 如果你同时在同一个代码单元中执行这两个命令,你会在执行第二个命令之前注意到一个小间隙:
my_gopigo.drive_cm(10)
my_gopigo.drive_inches(10)
现在我们用机器人进行一次物理测试:
- 在起点在地面上做一个标记,向前开 10 厘米,向后开 10 厘米,看看运动有多精确:
# Forward
my_gopigo.drive_cm(10)
my_gopigo.drive_inches(10)
# Backward
my_gopigo.drive_cm(-10)
my_gopigo.drive_inches(-10)
你应该会发现它准确地回到了起点。我们用千分尺测量的误差(测量了三次)分别是 +1.29 毫米、-0.76 毫米和 +2.16 毫米。正数表示在倒车时它通过了起点,而负数表示它没有到达起点。
- 如果你将距离相加(10 厘米 + 10 英寸 = 35.4 厘米)并放入一个向前命令中,然后发出另一个命令以相同的距离后退,我们测量的误差是(我们再次进行了三次测量)-0.01 毫米、-1.40 毫米和 -0.72 毫米:
# Forward
my_gopigo.drive_cm(+35.4)
# Backward
my_gopigo.drive_cm(-35.4)
你可以看到,使用两个命令引入的暂停引入了一个大约 1 毫米的错误。仅使用一个命令向前和一个命令向后可以显著减少错误。
- 我们可以对转向进行类似的测试:
# Turn clockwise (right)
my_gopigo.turn_degrees(90)
# Turn counterclockwise (left)
my_gopigo.turn_degrees(-90)
- 其他有用的命令如下:
my_gopigo.forward()
my_gopigo.backward()
my_gopigo.right()
my_gopigo.left()
- 要停止机器人,使用这个命令:
my_gopigo.stop()
- 非常重要的是要注意,软件流程可能与机器人物理不兼容。尝试这个序列并观察 GoPiGo3 的表现:
my_gopigo.forward()
my_gopigo.backward()
my_gopigo.right()
my_gopigo.left()
似乎只有最后一行被执行,即 my_gopigo.left()。实际上发生的情况是,命令执行得非常快(每次几毫秒),机器人的惯性不允许 GoPiGo 有足够的时间向前、向后或向右移动。移除最后一行来检查它:现在你看到的唯一实际执行的命令是 my_gopigo.right()。
在为机器人编程时,最具挑战性的问题之一是理解其动力学,因为可能看起来像是软件错误的东西,可能是机器人意外物理反应。因此,在开发软件之前,您必须确保您理解问题的物理原理,包括其质量(惯性)、摩擦力、电机上的最大负载、电源限制和电池水平。来自物理世界的变量列表可能是无限的,您应该应用您的力学和电学知识来成功开发功能软件。
对于这个简单案例的一个可能解决方案是在序列中指定您想要它移动的距离或角度:
my_gopigo.drive_cm(-10) # Forward
my_gopigo.drive_cm(10) # Backward
my_gopigo.turn_degrees(90) # Right (clockwise)
my_gopigo.turn_degrees(-90) # Left (counterclockwise)
要在 DexterOS 中保存您的作品,您必须从 ~/.lessons_python 文件夹中进行。这个文件夹属于 pi:users,而 DexterOS 用户是 jupyter(在终端中输入 $ whoami 命令或在提示符中查看)。在树中向上移动一级,并创建一个您想要的任何名称的文件夹。然后使用文件 | 另存为… 在该位置保存您的更改。
硬件测试
要在 LEARN 环境之外访问 DexterOS 中的这些笔记本,请导航到 mygopigo.com 或 http://10.10.10.10,然后点击 Python 中的代码。JupyterLab 将启动:
在屏幕左侧的文件管理器视图中,您将找到这两个笔记本:
- 其中一个是
First Ride Around.ipynb,它提供了一个用于通过视觉面板控制机器人的小部件:
- 另一个笔记本是
Hardware Testing.ipynb,它为电池、LED 灯和编码器运行特定的测试。以下小节中讨论了我们对 GoPiGo3 行为的预期。
测试电池、LED 灯和电机/编码器
打开笔记本并逐个检查每个单元,以了解其功能。
电池水平
以下命令读取并显示当前电池电压*.* 对于 GoPiGo3 正常工作,这个值应该高于 9 V。当电池电量不足时,您将失去与机器人的 Wi-Fi 连接,您必须充电或更换新电池:
print("Battery voltage : ", GPG.get_voltage_battery() )
OUTPUT ===> Battery voltage : 9.114
接下来,我们将查看硬件信息和电压水平。
硬件信息和当前电压水平
下一个命令块将打印制造商信息、硬件和固件版本以及电池水平。以下与输出相关:
-
电池电压 与之前相同。测量给出略有不同的值,9.294V,这是正常的。
-
5V 电压 是通过 GPIO 向 Raspberry Pi 提供电源的电压。GoPiGo 红色电路板有一个电源调节器,将 9V 的原始输入转换为稳定的 5V。如果电池充电良好,这个值应该非常接近 5V,如所示:
print("Manufacturer : ", GPG.get_manufacturer() )
print("Board : ", GPG.get_board() )
print("Serial Number : ", GPG.get_id() )
print("Hardware version: ", GPG.get_version_hardware())
print("Firmware version: ", GPG.get_version_firmware())
print("Battery voltage : ", GPG.get_voltage_battery() )
print("5v voltage : ", GPG.get_voltage_5v() )
OUTPUT ===>
Manufacturer : Dexter Industries
Board : GoPiGo3
Serial Number : F92DD433514E343732202020FF112535
Hardware version: 3.x.x
Firmware version: 1.0.0
Battery voltage : 9.294
5v voltage : 4.893
接下来,我们将检查 LED 灯和闪烁灯。
LED 灯和闪烁灯
板上顶部有两个 LED 灯,模拟 GoPiGo3 的眼睛。通过运行以下代码块,它们将改变颜色:
colors = [ (255,0,0), (255,255,0), (255,255,255), (0,255,0), (0,255,255), (0,0,255), (0,0,0)]
for color in colors:
GPG.set_eye_color(color)
GPG.open_eyes()
time.sleep(0.5)
闪烁灯是位于前面红色板下方的两个小红灯。以下代码使它们闪烁 5 次:
for i in range(5):
GPG.led_on("left")
GPG.led_on("right")
time.sleep(0.5)
GPG.led_off("left")
GPG.led_off("right")
time.sleep(0.5)
视觉检查,并注意控制台不会显示任何消息。
电机和编码器测试
下一个单元格将运行大约 5 秒,并将报告编码器读数:
GPG.set_motor_dps(GPG.MOTOR_LEFT | GPG.MOTOR_RIGHT, 100)
start = time.time()
lapse = 0
while lapse < 5:
lapse = time.time() - start
time.sleep(0.5)
print("LEFT: {} RIGHT:{}".format(GPG.get_motor_status(GPG.MOTOR_LEFT),GPG.get_motor_status(GPG.MOTOR_RIGHT)))
passed_test = GPG.get_motor_status(GPG.MOTOR_LEFT)[0]==0 and GPG.get_motor_status(GPG.MOTOR_RIGHT)[0]==0
GPG.set_motor_dps(GPG.MOTOR_LEFT | GPG.MOTOR_RIGHT, 0)
if passed_test:
print("Test passed.")
else:
print("Test failed.")
这些是结果:
LEFT: [0, 26, 3095, 101] RIGHT:[0, 26, 4806, 101]
LEFT: [0, 26, 3146, 101] RIGHT:[0, 28, 4856, 101]
LEFT: [0, 26, 3196, 101] RIGHT:[0, 28, 4906, 101]
LEFT: [0, 26, 3246, 101] RIGHT:[0, 26, 4957, 96]
LEFT: [0, 26, 3296, 101] RIGHT:[0, 26, 5007, 101]
LEFT: [0, 26, 3347, 101] RIGHT:[0, 28, 5057, 101]
LEFT: [0, 24, 3397, 105] RIGHT:[0, 26, 5107, 96]
LEFT: [0, 21, 3447, 96] RIGHT:[0, 26, 5158, 101]
LEFT: [0, 26, 3497, 101] RIGHT:[0, 21, 5208, 101]
LEFT: [0, 28, 3547, 96] RIGHT:[0, 28, 5258, 96]
LEFT: [0, 33, 3598, 101] RIGHT:[0, 33, 5308, 101]
Test passed.
我们应该看到最后的消息,告诉我们测试是否通过。目前不必担心理解这些数字:这是一个 GoPiGo3 自我检查并报告是否通过或失败的内测。
如果成功,你可以继续进行以下测试。GoPiGo3 将向前行驶 10 厘米,最后的输出值应该大约是 10。如果这个测试失败,你可以通过点击顶部红色的停止按钮来停止机器人:
GPG.reset_encoders()
#GPG.set_speed(GPG.DEFAULT_SPEED)
GPG.drive_cm(10)
encoders_read = round(GPG.read_encoders_average())
print("Drove {:.2f} cm".format(encoders_read))
if encoders_read == 10:
print("Test passed.")
else:
print("Test failed.")
如果一切顺利,你将获得以下消息:
Drove 10.00 cm Test passed.
再次,如果这个测试失败,你可以通过按顶部红色的停止按钮来停止机器人。在这些基本测试之后,我们对 GoPiGo3 的硬件和软件有了足够的了解,可以执行单元测试,这是本章的主要目标。
传感器和驱动单元测试
在本节中,我们将通过使用 Jupyter Notebooks 在 Python 中运行一些简单的脚本。从你的笔记本电脑中的终端,克隆书籍仓库并进入Chapter2_Unit_Tests文件夹以访问本章的文件:
$ git clone https://github.com/PacktPublishing/Hands-On-ROS-for-Robotics-Programming
$ cd Hands-On-ROS-for-Robotics-Programming/Chapter2_Unit_Tests
为了完整性,我们在lessons_GettingStarted文件夹中包含了上一节使用的笔记本。
使用传感器和电机快速入门
要进入机器人的 Python 环境,打开红色板,并从你的笔记本电脑连接到GoPiGo Wi-Fi 网络。然后,在浏览器中访问以下 URL:
http://10.10.10.10/python
在 JupyterLab 中,关注左侧,那里显示了文件存储。要运行任何示例,你必须手动上传到你想在机器人存储中放置的位置。创建一个名为Chapter2_Unit_Tests的文件夹并上传所需的文件。我们将在每个练习的开始处指出我们将使用哪个文件。
驱动绕行
本小节中的文件位于仓库的./Chapter2_Unit_Tests/drivingAround文件夹中。你可以逐个上传它们。之后,在 JupyterLab 中通过打开启动器标签页启动一个 shell 会话:
- 从标签页中选择终端图标,如图所示:
- 通过更改到它们的目录来从终端执行脚本:
$ cd./Chapter2_Unit_Tests/drivingAround
$ python <name_of_script.py>
第一个脚本是1-easyMotors.py,它执行一个非常简单的序列:
-
电机向前移动 1 秒。
-
电机停止 1 秒。
-
驱动机器人 50 厘米然后停止。
-
向右转 1 秒。
-
向左转 1 秒。
-
停止。
您可以在以下代码列表中看到脚本的第一个部分,它显示了前进 1 秒然后停止 1 秒的命令:
# import the time library for the sleep function
import time
# import the GoPiGo3 drivers
from easygopigo3 import EasyGoPiGo3
# Create an instance of the GoPiGo3 class.
# GPG will be the GoPiGo3 object.
gpg = EasyGoPiGo3()
print("Move the motors forward freely for 1 second.")
gpg.forward()
time.sleep(1)
gpg.stop()
print("Stop the motors for 1 second.")
time.sleep(1)
第二部分如下所示,它包括前进 50 厘米,然后向右转 1 秒,然后向左转 1 秒的命令:
print("Drive the motors 50 cm and then stop.")
gpg.drive_cm(50, True)
time.sleep(1)
print("Turn right 1 second.")
gpg.right()
time.sleep(1)
print("Turn left 1 second.")
gpg.left()
time.sleep(1)
print("Stop!")
gpg.stop()
print("Done!")
下一个脚本是 2-driveSquare.py,它做了它所说的:它在地板上画一个正方形。如果我们使用一个for循环,在每次驱动 30 厘米后进行 90 度旋转,我们得到一个行数非常少的程序:
from easygopigo3 import EasyGoPiGo3
gpg = EasyGoPiGo3()
length = 30
for i in range(4):
gpg.drive_cm(length) # drive forward for length cm
gpg.turn_degrees(90) # rotate 90 degrees to the right
3-circularMoves.py Python 脚本使 GoPiGo3 在一个方向上走半圆,然后在相反方向上走,返回起点:
from easygopigo3 import EasyGoPiGo3
gpg = EasyGoPiGo3()
gpg.orbit(180, 50) # draw half a circle
gpg.turn_degrees(180) # rotate the GoPiGo3 around
gpg.orbit(-180, 50) # return on the initial path
gpg.turn_degrees(180) # and put it in the initial position
程序 4-drawEight.py 将弧线和直线路径结合起来,在地板上绘制一个 8 形状:
from easygopigo3 import EasyGoPiGo3
gpg = EasyGoPiGo3()
radius = 30
gpg.orbit(-270, radius) # to rotate to the left
gpg.drive_cm(radius * 2) # move forward
gpg.orbit(270, radius) # to rotate to the right
gpg.drive_cm(radius * 2) # move forward
最后,程序 5-accelerateForward.py 展示了如何加速机器人。这个序列相当简单:
-
设置初始速度和结束速度。
-
通过将它们之间的间隔除以 20 来计算步长。
-
运行一个循环,每次迭代增加步进值。
-
每 0.1 秒执行一次迭代。
-
2 秒后,GoPiGo3 将达到最大速度并停止:
from easygopigo3 import EasyGoPiGo3
from time import time, sleep
gpg = EasyGoPiGo3()
# setting speed to lowest value and calculating the step increase in speed
current_speed = 50
end_speed = 400 step = (end_speed - current_speed) / 20
gpg.set_speed(current_speed) # start moving the robot at an ever increasing speed
gpg.forward()
while current_speed <= end_speed:
sleep(0.1)
gpg.set_speed(current_speed)
current_speed += step # and then stop it
gpg.stop()
现在我们来测试我们为机器人配备的所有传感器。
距离传感器
为了与传感器通信,我们将使用 DI-sensors Python 库 github.com/DexterInd/DI_Sensors。
首先,我们需要修改端口连接。这就是我们现在要回顾的内容。
检查端口连接
以下图表在连接传感器到 GoPiGo3 端口时应非常有帮助,以确保硬件正确布线:
图片来源:Dexter Industries: https://gopigo3.readthedocs.io/en/master/_images/gpg3_ports.jpg
从上一章,你应该记得每个端口的用途:
-
AD1和AD2是通用输入/输出端口。
-
SERVO1和SERVO2是伺服控制器端口。
-
I2C端口是您连接I2C 启用设备的地方。
-
串行端口是您可以连接UART 启用设备的地方。
根据这个描述,检查传感器是否按照我们在第一章中描述的方式连接:
-
距离传感器应该插入到I2C-1,GoPiGo3 左侧的 I2C 端口。
-
伺服包应该连接到SERVO1。
-
线跟踪器应该插入到I2C-2,GoPiGo3 右侧的 I2C 端口。
-
IMU传感器应该连接到AD1(在左侧)。
距离传感器单元测试
尽管您已经将距离传感器连接到I2C-1端口,但请注意,GoPiGo3 软件库不会要求您在脚本中指定您使用的是两个端口中的哪一个。它将自动检测。
测试文件位于存储库的 ./Chapter2_Unit_Tests/DI-distance 文件夹中。您可以逐个上传到 DexterOS:
-
di-distance_cm.py -
di-distance-easygopigo_mm.py
然后,通过打开启动器窗口并从中选择终端图标,在 JupyterLab 中打开一个 shell 会话。通过移动到它们的位置来在终端中执行脚本:
$ cd./Chapter2_Unit_Tests/DI-distance
$ python <script.py>
第一个脚本是di-distance_cm.py。它以固定的时间速率读取数据:
# import the modules
from di_sensors.easy_distance_sensor import EasyDistanceSensor
from time import sleep
# instantiate the distance object
my_sensor = EasyDistanceSensor()
# and read the sensor iteratively
while True:
read_distance = my_sensor.read()
print("distance from object: {} cm".format(read_distance))
sleep(0.1)
发布间隔为 0.1 秒,如sleep(0.1)行中指定。距离传感器 API 的详细说明可在di-sensors.readthedocs.io/en/master/api-basic.html#easydistancesensor找到。my_sensor.read()方法提供厘米距离,但如果你更喜欢使用其他单位,还有另外两种方法:
-
my_sensor.read_mm()用于毫米。 -
my_sensor.read_inch()用于英寸。
第二个脚本di-distance-easygopigo_mm.py按照github.com/DexterInd/GoPiGo3导入 GoPiGo3 库,这隐式地包含了传感器库github.com/DexterInd/DI_Sensors。你可以看到它使用相同的类方法来读取数据。在这种情况下,使用的是读取毫米距离的函数:
# import the GoPiGo3 drivers
import time
import easygopigo3 as easy
# This example shows how to read values from the Distance Sensor
# Create an instance of the GoPiGo3 class.
# GPG will be the GoPiGo3 object.
gpg = easy.EasyGoPiGo3()
# Create an instance of the Distance Sensor class.
# I2C1 and I2C2 are just labels used for identifyng the port on the GoPiGo3 board.
# But technically, I2C1 and I2C2 are the same thing, so we don't have to pass any port to the constructor.
my_distance_sensor = gpg.init_distance_sensor()
while True:
# Directly print the values of the sensor.
print("Distance Sensor Reading (mm): " + str(my_distance_sensor.read_mm()))
为了完整性,我们已将这两个库包含在本章的文件夹中:
-
easysensors.py用于传感器 -
easygopigo3.py用于机器人
如果你检查后者,你将在文件开头看到这条import行:
import easysensors
...
try:
from di_sensors import easy_distance_sensor
这样,我们可以将所需的 DI 传感器集成到你的机器人中,以增加其感知能力。让我们通过一个例子来更好地理解 Dexter Industries 提供的库。
GoPiGo3 API 库
机器人的主要类是GoPiGo3,你可以在以下图中看到类结构。easysensors库被EasyGoPiGo3类(继承)导入,因此可以访问所有传感器方法。类结构在以下图中展示:
图片来源:Dexter Industries:https://gopigo3.readthedocs.io/en/master/_images/inheritance-e4cb3d2ae1367b2d98aab1a112a1c8e1b7cd9e47.png
一个包含该类所有功能的总结表格可在gopigo3.readthedocs.io/en/master/api-basic/structure.html#functions-short-list找到。API 库的详细内容可在gopigo3.readthedocs.io/en/master/api-basic/easygopigo3.html找到。
因此,使用easygopigo3.py库,你可以创建你的机器人实例并初始化所需的传感器。例如,距离传感器通过以下类方法进行初始化:
easygopigo3.EasyGoPiGo3.init_distance_sensor([port])
在我们的脚本中,这是通过三行实现的:
import easygopigo3 as easy
gpg = easy.EasyGoPiGo3()
my_distance_sensor = gpg.init_distance_sensor()
在第一行,您导入easygopigo3库。在第二行,您实例化一个机器人对象,在第三行,您初始化距离传感器。然后,您就可以从传感器获取数据了:
my_distance_sensor.read_mm()
简而言之,如果您使用easygopigo3.py库,顶层对象是机器人本身。另一方面,如果您在一个不涉及 GoPiGo 的自定义项目中使用传感器,顶层对象尚未创建,除非您已经有了相应的库。如果没有,您需要定义一个表示该实体(例如气象站)的类,并导入 DI 传感器库。这是下一小节的主题。
DI 传感器 API 库
每种传感器类型都有自己的类和方法。在./Chapter2_Unit_Tests/DI-distance/di-distance_cm.py脚本中,我们使用了 DI-sensors 库。类结构在以下屏幕截图中有显示,并在di-sensors.readthedocs.io/en/master/structure.html#library-structure中进行了说明:
图片由 Dexter Industries 提供:https://di-sensors.readthedocs.io/en/master/_images/inheritance-a8243413ad98ddae26cdf121c775ad137c7f2e30.png
所有 DI 传感器的总结表格方法显示在di-sensors.readthedocs.io/en/master/structure.html#functions-short-list。您将找到每个传感器的两种使用方法:
-
简单方法——以
easy前缀开头——是为了快速使用,并提供顶层功能。您可以在前一个图例的右侧看到语法。 -
没有带
easy前缀的高级方法是供开发者使用的,并提供低级控制。
距离传感器由以下类管理:
di_sensors.easy_distance_sensor.EasyDistanceSensor([…])
在我们的脚本中,传感器初始化如下::
from di_sensors.easy_distance_sensor import EasyDistanceSensor
my_sensor = EasyDistanceSensor()
前面的行描述如下:
-
在第一行,您导入距离传感器的类。请注意,您只需要从
di_sensors.easy_distance_sensor导入EasyDistanceSensor类。 -
在第二行,您使用
Easy类实例化距离传感器对象。
然后,您就可以从传感器获取数据了:
read_distance = my_sensor.read()
与不使用easy选项的情况进行比较。语法类似,唯一的区别是去除了_easy和Easy前缀:
from di_sensors.distance_sensor import DistanceSensor my_sensor = DistanceSensor()
read_distance = my_sensor.read()
同样的方案将适用于我们稍后要介绍的其他传感器,特别是线跟踪器和 IMU。
伺服包
伺服包由一个脉冲宽度调制(PWM)伺服电机组成。它通过施加产生电机轴在 180°幅度范围内的成比例旋转的电压进行开环控制。在下面的图像中有一个小杆,使我们能够可视化旋转。在我们的 GoPiGo3 组装中,我们将看到旋转距离传感器:
图片来源:Dexter Industries:https://www.dexterindustries.com/wp-content/uploads/2017/06/GoPiGo3-Servo-Assembly-11-600x338.jpg
伺服包是描述在 距离传感器单元测试 部分的 GoPiGo3 API 库的一部分。它的 API 方法在 gopigo3.readthedocs.io/en/master/api-basic/sensors.html#servo 中详细说明。
接下来,我们将执行一些单元测试来检查它是否能够正确旋转。由于我们已经将距离传感器与伺服包一起安装,我们可以通过旋转伺服来测量 180º 视场内的障碍物距离。在测试中,我们还将校准机器人能够覆盖的实际视场。
伺服包单元测试
测试包括将距离传感器相对于伺服电机轴放置在一个角度位置,这个位置覆盖了 GoPiGo3 的整个前方视图,从左到右。所有的解释和代码都在位于 ./Chapter2_Unit_Tests/DI-servo_package/servoCalibration.ipynb 的 Jupyter 笔记本中:
- 首先,我们从
EasyGoPiGo3类创建伺服对象。为此,我们需要导入库并实例化GoPiGo3:
import easygopigo3 as easy
my_gpg3 = easy.EasyGoPiGo3()
- 然后,我们初始化伺服:
servo = my_gpg3.init_servo()
- 我们检查我们是否能够完全旋转伺服。你应该已经卸下传感器以防止与机器人底盘碰撞:
servo.rotate_servo(0) # This is 0º position
servo.rotate_servo(180) # This is 180º position
- 然后,将伺服移动到区间的中间,90º,并将传感器安装好,使其朝向前方:
servo.rotate_servo(90)
- 调整角度,使传感器正好朝向前方。在我们的例子中,这个角度是 95°。你应该找出你自己的角度:
servo.rotate_servo(95)
- 一旦我们检查了参考位置,让我们设置实际限制。为此,找到防止机器人底盘干扰传感器的角度。在我们的例子中,这些角度是 30º 和 160º。同样,你应该找出你自己的角度:
servo.rotate_servo(30)
servo.rotate_servo(160)
这样,我们就完成了带有距离传感器的伺服包的设置。
对于高级用户,还有一个 API 库,gopigo3,它提供了对硬件的低级访问,以便您能够完全控制它。尽管本书的范围不包括低级编程,但您提供了一个 Python 脚本,Servo.py,简要说明了其方法的使用。此脚本以 计数 而不是 旋转角度 来设置旋转。我们执行一个循环,当计数从 1000 到 2001 时。
这样,您就可以访问伺服电机的全部分辨率,并且应该对它能够提供的旋转步长的大小有一个概念。
跟踪线
如第一章所述,跟踪线由六个发射器-接收器对组成,用于感应地板上的六个对齐点,以确定机器人相对于它将跟随的黑线的偏离程度。
线路跟随器也是 GoPiGo3 API 库的一部分。其方法在di-sensors.readthedocs.io/en/master/api-basic.html#easylinefollower中有详细说明。我们将进行的单元测试包括验证传感器能否告知机器人位于黑色线哪一侧。
线路跟随器单元测试
测试用的 Jupyter 笔记本是./CH2-uniTests/di-lineFollower/lineFollower_libraries.ipynb。这个笔记本还展示了简单的库,di_sensors.easy_line_follower,以及高级版本,di_sensors.line_follower,的实际应用。
当传感器报告中心时,这是因为机器人在黑色线路上很好地居中,如下一张图片所示。这意味着两个外部发射器-接收器对报告白色,而它们之间的对报告黑色:
当传感器报告左侧时,这意味着线路稍微在机器人左侧,如下一张照片所示。这意味着最左侧的对报告黑色,中间的对黑色,其余的对白色:
如果机器人完全偏离了线路,所有对都会报告白色,线路跟随器总体上也会报告白色。反之亦然:如果所有对都报告黑色,可能是因为黑色线条太宽或者机器人被放置在了一个暗色的表面上。
不惯性测量单元(IMU)
使用提供的惯性测量单元(IMU),我们有以下传感器:
-
磁力计,三轴
-
惯性测量单元(IMU),三轴
-
加速度计,三轴
如前一章所述,有了这三个传感器——一旦完成校准设置——就可以获得机器人在 3D 空间中的绝对方向,用欧拉角来量化。此外,我们还有温度,因为 DI IMU 配备了温度传感器。
IMU 单元测试
测试用的 Jupyter 笔记本是./Chapter2_Unit_Tests/DI-IMU/IMU_reading.ipynb。相应的 DI 传感器 API 库在di-sensors.readthedocs.io/en/master/examples/imu.html上有文档说明。
在运行笔记本时,你可以检查报告的欧拉角是否正确。
Raspberry Pi
Pi 是任何机器人不可或缺的感知设备。考虑到大约 80%的人类大脑处理的感觉数据来自视觉。在本节中,我们只将测试 Pi 是否能够拍照以检查其是否正常工作。在*第十章,在机器人学中应用机器学习*,我们将使用相机捕获的图像上的对象识别算法。因此,机器人将表现出更智能的行为,能够识别颜色、形状、面孔等等。
Pi 单元测试
测试的 Jupyter 笔记本位于 ./Chapter2_Unit_Tests/PiCamera/Taking_Photos.ipynb。这个简单的例子拍摄照片并创建直方图,即显示图像中每种颜色的数量和每种颜色的数量的图表。
因此,让我们拍摄一张颜色较少的照片,以便更容易理解直方图的信息。以下是用 GoPiGo3 拍摄的照片,具有我们需要的特征:
这可以通过以下代码片段实现:
- 首先,我们拍照。然后将其转换为 JPG 图像格式并保存,最后在屏幕上显示结果:
with picamera.PiCamera() as camera:
camera.resolution = (640, 480)
camera.capture(output, format = 'rgb', use_video_port = True)
img = Image.fromarray(output)
img.save("../photo.jpg")
plt.imshow(output)
- 最后,我们用这个简单的命令绘制直方图:
img = Image.open("../photo.jpg")
histogram = img.histogram()
plt.plot(histogram)
这是结果:
你可能会看到颜色集中在三个点上。x 轴的刻度从 0(黑色)到 768(白色)。这个区间是通过考虑 24 位 RGB 像素值可以高达 768 来解释的。让我们看看每根垂直线代表什么:
-
在 x = 0 的线上表示的是黑色区域。
-
在 x = 525 的线上表示的是更闪亮的区域,即灯泡。
-
最后,很容易推断出 x = 250 对应的是显示器周围的较亮区域,看起来有灰色调。
通过这次最后的测试,我们验证了我们的机器人所有的传感器和驱动器都工作正常,我们准备进入下一步,构建功能行为。
GoPiGo3 项目
在 Github 上托管的官方 GoPiGo3 软件提供了几个有趣的项目。github.com/DexterInd/GoPiGo3。在这个阶段,我们建议你克隆仓库并将其中的一些项目上传到运行 DexterOS 的机器人。项目位于仓库的这个文件夹中:github.com/DexterInd/GoPiGo3/tree/master/Projects。
你可以尝试,例如,位于 github.com/DexterInd/GoPiGo3/tree/master/Projects/BasicRobotControl 的 基本机器人控制 项目。你拥有使用连接到机器人的无线键盘的按键来完全控制驱动器、LED 和闪烁灯的方法:
[key w ] : Move the GoPiGo3 forward
[key s ] : Move the GoPiGo3 backward
[key a ] : Turn the GoPiGo3 to the left
[key d ] : Turn the GoPiGo3 to the right
[key <SPACE> ] : Stop the GoPiGo3 from moving
[key <F1> ] : Drive forward for 10 centimeters
[key <F2> ] : Drive forward for 10 inches
[key <F3> ] : Drive forward for 360 degrees (aka 1 wheel rotation)
[key 1 ] : Turn ON/OFF left blinker of the GoPiGo3
[key 2 ] : Turn ON/OFF right blinker of the GoPiGo3
[key 3 ] : Turn ON/OFF both blinkers of the GoPiGo3
[key 8 ] : Turn ON/OFF left eye of the GoPiGo3
[key 9 ] : Turn ON/OFF right eye of the GoPiGo3
[key 0 ] : Turn ON/OFF both eyes of the GoPiGo3
[key <INSERT>] : Change the eyes' color on the go
[key <ESC> ] : Exit
到目前为止,你可能认为我们用来将新文件放入机器人的方法很繁琐。我们使用了 DexterOS,这样你就可以快速开始,无需处理 Linux 问题。
从下一章开始,我们将在你的笔记本电脑上使用 Ubuntu 16.04 和 GoPiGo3 内部的完整 Linux 桌面,Ubuntu 18.04。这将使机器人能够连接到互联网,并允许你直接将仓库克隆到机器人中。
摘要
在本章中,我们通过运行允许我们测试机器人传感器和执行器的简单程序,熟悉了 GoPiGo3 的 Python 环境。我们按照正式的单元测试方法逐一检查了它们。这实现了两个目标:开始 Python 编程和功能验证您的机器人硬件。
接下来,我们将把机器人放到下一章,我们将讨论 ROS 的核心软件概念,这是我们稍后用来编程 GoPiGo3 的。
问题
- 如果你有这个 Python 命令序列,GoPiGo3 会做什么?
my_gopigo.drive_cm(10)
my_gopigo.turn_degrees(90)
A) 它将向前行驶 10 厘米,然后向右转 90 度
B) 它将向前行驶 10 厘米,然后向左转 90 度
C) 它将转 90 度
- GoPiGo3 正常工作所需的电池电量是多少?
A) 略高于 9V 就足够了。
B) 5V,与 Raspberry Pi 所需的电压相同。
C) 没有最小值。如果电压低,机器人将缓慢行驶。
- 哪组命令将使 GoPiGo3 绘制直径为 60 厘米的直角圆弧?
A) gpg.orbit(90, 60) B) gpg.orbit(90, 30) C) gpg.orbit(180, 30)
- 线跟踪器的六个传感器信号中哪一种组合不对应于 GoPiGo3 位于黑色线右侧?(w: 白色,b: 黑色)
A) b-b-b-b-w
B) w-b-b-b-w
C) b-b-b-w-w
- 如果有一个图像直方图,它由在x = 0 和x = 768 处的两条等高垂直线组成,且x的颜色范围是从 0 到 768,那么图像中存在哪些颜色?
A) 灰色,因为它是以相等比例混合黑色和白色所得的结果。
B) 图像的一半是黑色,另一半是白色。
C) 不可能得到这样的直方图。
进一步阅读
要深入了解 GoPiGo3 的技术细节,您可以在以下官方指南中找到非常详细的信息:
-
Dexter Industries GoPiGo3 文档:
gopigo3.readthedocs.io -
Dexter Industries DI-Sensors 文档:
di-sensors.readthedocs.io -
Pi 相机文档:
picamera.readthedocs.io/
第三章:ROS 入门
机器人操作系统(ROS)是一个开源软件。其开发始于 Willow Garage,一个技术孵化器和机器人研究实验室。其起源可以追溯到 2000 年中叶斯坦福大学的几个项目,当时研究人员每次都必须为每个项目构建软件时,都会发现自己是在重新发明轮子。
2007 年,Willow Garage 率先推出了 ROS。主要目标是重用现有代码,并使快速原型化新机器人设计成为可能,专注于高级功能并最大限度地减少编辑代码的需求。如果您对 ROS 如何成为机器人应用程序开发的事实上的标准感兴趣,可以查看一个交互式页面www.ros.org/history。
ROS 旨在开发需要不同设备相互通信以创建灵活和可扩展环境的应用程序。本章将解释 ROS 的基本概念。它将使用通俗易懂的语言介绍框架,同时避免过于技术性的描述。这是因为我们的首要目标是干净利落地向你展示 ROS 在概念上的含义。在接下来的章节中,我们将有机会涵盖技术描述;这些描述在任何情况下你都需要,以便能够在项目中使用 ROS。
在本章的第一部分,我们将介绍 ROS 在底层是如何工作的,以及为什么它不应仅仅被视为一种特定用途的编程语言,而应被视为开发机器人应用程序的框架。您将深入了解 ROS 图的核心概念和节点之间的异步通信。
在第二部分,您将逐步引导配置笔记本电脑上的 ROS 环境。
在第三部分,通过一个实际练习的引导,你将学习如何使用命令行在节点之间交换简单的消息。
最后,我们将为您概述许多由开源社区贡献的可用 ROS 包。
在本章中,我们将涵盖以下主题:
-
ROS 基本概念和 ROS 图
-
配置您的 ROS 开发环境
-
ROS 节点之间的通信:消息和主题
-
使用 ROS 的公开可用包
技术要求
本章的实践方面要求您能够访问带有以下两种 Ubuntu 版本之一的台式计算机或笔记本电脑:
-
Ubuntu 16.04 Xenial
-
Ubuntu 18.04 Bionic
长期支持(LTS)Ubuntu 版本由 Canonical 维护长达 5 年。此外,这类版本在偶数年发布。因此,2016 年发布的 Ubuntu 16.04 将会维护到 2021 年,而 2018 年发布的 Ubuntu 18.04 将会维护到 2023 年。我们不会考虑奇数年版本,即 Ubuntu 17 或 Ubuntu 19,因为它们是开发版本,不是 LTS 版本。
Open Robotics 每年都会发布一个新的 ROS 版本,与每个 Ubuntu 版本同步。对应关系如下:
-
在 Ubuntu 16.04 Xenial 下运行的 ROS Kinetic
-
在 Ubuntu 18.04 Bionic 下运行的 ROS Melodic
到本书写作时,最常用的版本是 ROS Kinetic。以下章节中提供的实际例子适用于 Ubuntu 16.04 和 Ubuntu 18.04。因此,它们也适用于 ROS Kinetic 和 ROS Melodic。
当我们不区分 Ubuntu 或 ROS 版本时,你应该假设它们适用于这两个版本。如果根据版本的不同,命令或要运行的脚本有所不同,我们将明确指出。
本章的代码可以在本书仓库的 Chapter3_ROS_basics 中找到,该仓库托管在 GitHub 上,网址为 github.com/PacktPublishing/Hands-On-ROS-for-Robotics-Programming/tree/master/Chapter3_ROS_basics。在 设置 ROS 软件包 部分中,你将学习如何下载代码并将其与你的 ROS 安装一起使用。
ROS 基本概念
在早期,斯坦福大学机器人学的研究人员发现,为机器人原型设计软件是一项繁重的编程任务,因为他们必须为每个项目从头开始编码。曾经有一段时间,C++ 和 Python 等编程语言被用作机器人的一般编程语言,而这一事实要求人们付出巨大的努力来构建每一块软件,以提供机器人级别的功能,例如导航或操作。
这不仅是一个代码可重用性的问题,而且也是一个机器人工作方式的问题。在过程式编程中,程序的典型流程是按顺序执行一个步骤接着另一个步骤,如下面的图所示:
这个程序执行的任务是将多个图像合并成一个,这一点很容易推断。从我们的机器人角度来看,这种工作流程的主要缺点是,如果某些步骤未能执行,那么流程就无法继续,因此无法提供其结果,即合并后的图像。如果我们用机器人的类比,这意味着一个类人机器人如果其一只手臂(例如,肘关节的驱动电机损坏)不能正常工作,那么它可能无法完成其任务。类人机器人当然应该能够用另一只手臂完成任务。这正是 ROS 所做的!
让我们看看以下 ROS 图的例子。
ROS 图
这个图对于 ROS 来说,就像工作流程图对于过程式编程来说一样:
在前面的图中,每个圆圈——称为节点——代表一个独立的程序(这可以用 Python、Java、C++、Ruby、Node.js 或 ROS 已实现的任何其他编程语言编写)。它们之间的连接——称为边缘——代表信息的交换。箭头方向的意义是显而易见的:数据发射器是箭头开始的节点,接收节点是箭头指向的节点。出现在边缘上方的单词是 ROS 所说的主题,它们构成了节点之间交换信息的通道。当一个节点需要使用主题的信息时,它会通过订阅它来这样做,这个操作会在图中从数据提供者(此类主题的数据)到订阅节点添加一个新的箭头。
那么,从机器人的角度来看,这个图做了什么?记住,GoPiGo3 是一个经典的差速驱动机器人,其中每个轮子都可以独立转动,传感器——例如,距离传感器——在移动时为机器人提供有关障碍物距离的信息:
图片来源:Dexter Industries https://32414320wji53mwwch1u68ce-wpengine.netdna-ssl.com/wp-content/uploads/2017/05/GPG3_FullServoDistanceGoogly_1-800x800.jpg
因此,你可能已经猜到了,在前面的 ROS 图中,L_servo节点是控制左伺服电机的程序(通过旋转该轮子),而R_servo节点对右轮做同样的操作。
sensor节点是那个从距离传感器读取数据并通过连接到它的边缘(即使用/sharp_data主题)使它们对control节点可用的节点。
在control节点中运行着决定如果 GoPiGo3 遇到障碍物时应该做什么的程序。例如,它可以旋转机器人直到找到一个没有障碍物的方向。旋转意味着control节点向L_servo和R_Servo节点发送相反的命令。
这些信号是通过图中的相应边缘流动的:/speed_left主题或左舵机,以及/speed_right用于另一个。在 ROS 语言中,我们说control节点在/speed_left主题中发布左舵机的命令。
roscore
roscore是必须启动的第一个节点,以便 ROS 环境可以运行。这允许每个节点通过订阅它发布的主题来找到任何其他节点。roscore 还管理 ROS 参数的数据库——定义机器人配置的值。因此,如果 roscore 进程崩溃,主节点失败,机器人将停止工作。您可以猜测,这个单点故障对于像 ROS 这样的分布式计算框架来说是一个明显的限制。因此,ROS2 解决了这个问题,运行中的软件不再需要主节点。节点之间的通信依赖于DDS(数据分发服务)架构,适用于实时系统。
您能看出编写机器人程序与编写软件应用程序的不同之处吗?在机器人领域,您关注应用程序的顶层功能,并集成其他人编写的预制软件组件。
请注意,并非所有机器人领域的软件都遵循这种方法。实际上,在其众多用途中,我们选择 ROS 是因为其哲学与本书所采用的实践学习方法论非常契合。
这些软件组件,由代码块组成的节点群组,构成了我们所说的ROS 软件包。几个相关的节点构成了一个 ROS 软件包,提供特定的功能,例如,使用摄像头进行物体识别。
工作空间和 catkin
在 ROS 中,工作空间是一个用于构建和运行您软件的独立环境。您可以使用不同的工作空间来管理不同的项目。工作空间将包含您项目所需的全部 ROS 软件包。
在物理上,它是在您的家目录中的一个文件夹,其中包含您应用程序的所有特定文件,这样部署这个工作空间到另一个预装了 ROS 的机器上时可以正常工作,并且与原始计算机上的表现相同。
catkin 与工作空间的概念紧密相连,它是 ROS 的构建系统,结合了 CMake 宏和 Python 脚本,在 CMake 的正常工作流程之上提供功能。在此阶段,您只需知道这是一个工具,每次您在工作空间中包含新的软件包时都会用来构建软件。您可以在wiki.ros.org/catkin/conceptual_overview找到 catkin 的深入概念解释。
配置您的 ROS 开发环境
在本节中,我们将指导您如何安装和配置您在笔记本电脑上舒适地使用 ROS 所需的工具。简而言之,在开始本章的实践练习之前,您需要完成以下步骤:
-
请确保您的计算机运行Ubuntu 16.04或Ubuntu 18.04。这两个都是 LTS 版本,在撰写本书时拥有最广泛的 ROS 软件包集合。
-
在您的笔记本电脑上安装和设置 ROS。您还将获得在 Raspberry Pi、GoPiGO3 机器人的 CPU 上安装 ROS 的指南。然而,在本书的第二部分,您只需要笔记本电脑,因为我们将会处理一个机器人的虚拟模型。物理机器人的包含留待本书的第三部分。
-
对于 集成开发环境(IDE),我们将使用 RoboWare Studio,它基于微软的通用 IDE Visual Studio Code。我们将在下面的 安装 RoboWare Studio 部分提供设置说明。
因此,假设您的笔记本电脑具备所需的操作系统,我们现在继续进行配置的第二步。
安装 ROS
如果您使用的是 Ubuntu 16.04,您需要安装 ROS 的 Kinetic 发行版。另一方面,如果您有 Ubuntu 18.04,要安装的 ROS 版本称为 Melodic。请记住,这些选择在 技术要求 部分中已有详细解释。
在安装软件之前,请确保您有这两个基本的 curl 和 git 工具。如果不是这种情况,请运行以下命令来安装缺少的工具:
$ sudo apt update
$ sudo apt install curl git
ROS Kinetic 安装页面上的说明(wiki.ros.org/kinetic/Installation/Ubuntu)非常清晰且直接。它们适用于您的笔记本电脑(amd64/i386)和 Raspberry Pi(armhf 架构)。它们包含在此处以完成描述。
ROS Melodic 也有一个安装页面 wiki.ros.org/melodic/Installation/Ubuntu。在那里,您会发现命令与 Kinetic 相同,因为它们是以一种不依赖于所选 Ubuntu 版本的方式编写的。
按照以下步骤,您将在笔记本电脑上安装并运行 ROS:
- 首先,添加 ROS 的源仓库:
$ sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
此命令将 ROS 仓库源添加到您的系统中。由于此类源依赖于 Ubuntu 版本,上面片段中的内部命令 $(lsb_release -sc) 输出的是版本,即 Ubuntu 16.04 的 xenial 和 Ubuntu 18.04 的 bionic。
- 然后,设置您的密钥:
$ sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
或者,您可以使用 curl 而不是 apt-key 命令。如果您在代理服务器后面,这将很有用:
$ curl -sSL 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xC1CF6E31E6BADE8868B172B4F42ED6FBAB17C654' | sudo apt-key add -
如果您没有得到验证密钥,那么它可能因安全原因而更改(截至 2020 年 2 月,密钥仍然有效)。如果此刻不是这种情况,请访问官方安装页面 wiki.ros.org/melodic/Installation/Ubuntu,并找到需要替换密钥值 0xC1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 的部分。
- 更新您的源:
$ sudo apt update
- 如果你的笔记本电脑上安装了 Ubuntu 16.04,请安装完整的 ROS Kinetic 堆栈,包括名为 Gazebo 的模拟器、导航和机器人感知包(推荐):
$ sudo apt install ros-kinetic-desktop-full
如果你正在使用 Ubuntu 18.04,请执行 ROS Melodic 的安装:
$ sudo apt install ros-melodic-desktop-full
或者,你可以安装桌面版,它只包括 ROS GUI 工具(rqt,rviz)。稍后,当需要时,你可以添加模拟(Gazebo)、导航和感知的包(记住,这些包在上述第 4 步中概述的完整版本中安装):
$ sudo apt install ros-kinetic-desktop
或者,如果你使用的是 Ubuntu 18.04,你可以使用以下方法:
$ sudo apt install ros-melodic-desktop
- 初始化
rosdep。这是使你能够轻松安装源代码编译所需系统依赖的组件。它也是运行 ROS 中一些核心组件所必需的:
$ sudo rosdep init
$ rosdep update
- 为你的交互式 shell 会话设置 ROS 环境:
$ source /opt/ros/kinetic/setup.bash
或者,如果你使用的是 Ubuntu 18.04,请使用以下方法:
$ source /opt/ros/melodic/setup.bash
为了避免每次打开新终端时都需要运行此命令,请使用以下命令将其包含在 .bashrc 文件的末尾:
$ echo "source /opt/ros/kinetic/setup.bash" >> ~/.bashrc
$ source ~/.bashrc
上面的代码片段中的第二个命令执行了 .bashrc 文件,刷新你的自定义设置。如果在 Ubuntu 18.04 中,只需将 kinetic 替换为 melodic:
$ echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc $ source ~/.bashrc
- 最后,安装
rosinstall,这是一个命令行工具,它使你能够轻松下载许多 ROS 包的源代码树:
$ sudo apt install python-rosinstall python-rosinstall-generator python-wstool build-essential
请记住,随着你对机器人中的 Raspberry Pi 和你的笔记本电脑之间的通信越来越熟悉,你可以从你的电脑上执行所有桌面交互,让 Raspberry Pi 只执行机器人特定的任务。这种方法将使 GoPiGo3 更加响应,因为你将在 Raspberry Pi 上有一个最小的 Ubuntu 服务器和 ROS 基础版本,它不包括 GUI 工具,只包含核心包以及构建和通信库。
你可以参考下一节,了解如何为机器人准备 ROS 环境的具体细节。
Ubuntu 和 Raspberry Pi 上的 ROS
由于你将在 Raspberry Pi 上仅使用核心 ROS 包,因此建议你安装最新的 Ubuntu LTS 版本,即 Ubuntu Mate 18.04 Bionic (ubuntu-mate.org/download/)。这是因为,尽管几乎所有贡献的 ROS 包都适用于 ROS Kinetic,但同样真实的是,核心包已经在 ROS Melodic 2018 版本中可用。因此,在 Ubuntu 18.04 下在 Raspberry Pi 上安装此版本是安全的。
如前所述,ROS Melodic 安装页面 (wiki.ros.org/melodic/Installation/Ubuntu) 上的说明非常清晰和直接。
按照以下指南决定安装哪个版本:
- 如果安装 ROS 桌面版(对于初学者和涵盖本书内容来说推荐使用),请使用以下命令:
$ sudo apt-get install ros-melodic-desktop
- 如果您希望安装基础版本,即 ROS Base,从而从您的 Raspberry Pi 获得更好的性能,那么请使用此命令(这仅推荐给高级用户;目前,没有桌面 GUI):
$ sudo apt install ros-melodic-ros-base
如本节开头所述,对于本章,您只需要一台笔记本电脑。物理机器人留到本书的第三部分,从 第六章 开始,即 ROS 编程 – 命令和工具。在该章中,我们将提供正确设置 Raspberry Pi 上软件的必要细节。
集成开发环境 (IDE)
在 ROS wiki 专门介绍 集成开发环境 的部分 (wiki.ros.org/IDEs) 中,描述了目前可用的 ROS IDE——在撰写本书时,共有 15 个 IDE。在所有这些选项中,我们选择使用 RoboWare Studio,原因如下:
-
它是微软的通用和可定制的 IDE Visual Studio Code(VSC)的一个分支,在开发者社区中被广泛使用。它是开源的、轻量级的、易于使用,并提供大量贡献的插件,使得您可以定制 IDE 环境以满足自己的特定需求。RoboWare Studio 是基于 VSC 代码构建的,以提供 ROS 开发功能。此外,IDE 的插件面板已定制,以便您可以轻松按需安装 ROS 软件包。当前版本是 1.2.0,于 2018 年 6 月发布。其代码是开源的,并在 GitHub 上公开提供,地址为 TonyRobotics/RoboWare-Studio (
github.com/TonyRobotics/RoboWare-Studio)。 -
RoboWare Studio 的即开即用功能让您可以开始使用 ROS 的所有主要特性:工作空间、软件包、节点、消息/服务/动作等。
在本书的所有解释中,我们都会为您提供在 bash 中执行的命令,因为这是指挥 ROS 的原生方式。
RoboWare Studio 等集成开发环境在至少两种场景下可能会有所帮助:
-
当您刚开始使用 ROS 时,如果您不太熟悉命令行,可以避免处理其复杂性
-
在开发项目时,IDE 可以帮助管理与您的应用程序组成的 ROS 软件包一起散布的大量文件。这些软件包提供诸如坐标变换、计算机视觉、机器人导航等功能。
在任何情况下,我们的建议是使用 RoboWare Studio 完成这本书的第一轮学习,然后在第二轮学习中直接进入 bash。如果你想跳过其中一个,那么就放弃 IDE 选项,并继续使用命令行学习。练习 bash 命令是真正理解 ROS 的工作方式的最佳方法,你当然知道这不仅仅适用于 ROS,也适用于任何在 Linux OS 下运行的软件工具。
因此,从现在开始,使用你选择的 IDE 编辑文件,并且始终使用 ROS 命令行(或者如果你更喜欢使用 GUI 界面,则使用 RoboWare)。
安装 RoboWare Studio
假设你已经在你的计算机上安装了 ROS,请在终端中执行以下命令块以安装所需的依赖项,如 RoboWare Studio 可用手册中所示,手册链接为 github.com/TonyRobotics/RoboWare/blob/master/Studio/RoboWare_Studio_Manual_1.2.0_EN.pdf:
$ sudo apt-get update
$ sudo apt-get install build-essential python-pip pylint
然后,安装 clang-format-3.8 包:
$ sudo apt-get install clang-format-3.8
二进制文件托管在 GitHub 上,链接为 github.com/TonyRobotics/RoboWare/blob/master/Studio。你可以从以下链接下载适用于 Ubuntu OS AMD64 的 RoboWare Studio 最新版本:github.com/TonyRobotics/RoboWare/raw/master/Studio/roboware-studio_1.2.0-1524709819_amd64.deb。你还可以在 GitHub 上找到源代码,链接为 github.com/tonyrobotics/roboware-studio。
安装相当简单;从你获取 .deb 文件的位置执行以下命令:
$ sudo dpkg -i roboware-studio_1.2.0-1524709819_amd64.deb
完成后,你可以通过点击 RoboWare Studio 图标来启动 IDE。
ROS 节点之间的通信 – 消息和主题
我们将通过逐步进行的方式实现让两个节点相互通信的目标。首先,你需要创建一个个人工作空间,然后从 github.com/PacktPublishing/Hands-On-ROS-for-Robotics-Programming 拉取书籍仓库,并进入 Chapter3_ROS_basics 文件夹,自行完成练习。
创建工作空间
按照以下步骤从命令行创建工作空间:
- 首先,创建你稍后需要放置 ROS 包的文件夹:
$ mkdir -p ~/catkin_ws/src
以下是对文件夹的描述:
-
catkin_ws将成为你工作空间的根位置。 -
src是你放置代码的地方,即在 ROS 包内部。
注意,**~** 等同于主目录,即 /home/bronquillo。
- 移动到最后一个文件夹,并执行以下命令以初始化工作空间:
$ cd ~/catkin_ws/src
$ catkin_init_workspace
最后一条命令将生成 ~/catkin_ws/src/CMakeLists.txt 文件,该文件包含工作空间的定义和配置。该文件实际上是一个指向 ROS 安装文件夹中定义工作空间配置位置的符号链接:
/opt/ros/melodic/share/catkin/cmake/toplevel.cmake
- 首次构建工作空间;此时文件夹为空无关紧要:
$ cd ~/catkin_ws
$ catkin_make
通过列出内容,你会看到两个新的文件夹:
-
-
build包含我们工作空间的编译结果,并在创建用于执行 ROS 命令的包时提供所有代码。 -
devel包含工作空间的配置,每次你打开终端时都会源生它(参考以下步骤)。
-
注意,编译必须在根文件夹 ~/catkin_ws 中完成,而工作空间初始化是在应用程序代码文件夹 ~/catkin_ws/src 中完成的。
- 要将工作空间添加到你的 ROS 环境中,你需要源生生成的
setup文件:
$ source ~/catkin_ws/devel/setup.bash
- 为了避免每次打开新终端时都要运行此命令,将其包含在你的
.bashrc文件中:
$ echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
$ source ~/.bashrc
- 然后,你应该在你的
.bashrc文件中添加以下两行:
source /opt/ros/kinetic/setup.bash
source ~/catkin_ws/devel/setup.bash
记住,第一行负责 ROS 系统配置,第二行负责你的工作空间设置。
创建工作空间并使用 RoboWare 构建
以下说明允许你使用 RoboWare IDE 创建工作空间,避免使用命令行:
- 启动 RoboWare 并点击“新建工作空间…”项:
- 在弹出的窗口中,指定工作空间名称并选择你想要放置它的文件夹:
设置文件夹名称后,RoboWare 会为用户透明地执行 catkin_init_workspace,你将在 IDE 窗口的左侧看到一个新的文件和一个新的文件夹。它们是 src 文件夹和其中的文件 CMakeLists.txt,该文件包含你的工作空间定义和配置:
现在,你只需要注意到该文件有一个指向 ROS 安装文件夹 /opt/ros/kinetic 中的 ROS 系统文件的符号链接。此文件夹包含所有可能创建的工作空间的通用配置。
你可以在 RoboWare 中打开一个终端,并使用 ls -la 命令从特定的 ~/catkin/src 位置列出所有文件:
这样的终端可以通过顶部菜单栏访问,通过点击“视图”项,然后从下拉菜单中选择“集成终端 (Ctrl + `)”:
- 选择构建模式并将其设置为调试,如下面的截图所示:
- 然后,从顶部菜单栏中选择 ROS | 构建:
你将在屏幕底部的输出窗口中看到以下日志:
如果成功,最后几行应该看起来像这样:
接下来,让我们设置 ROS 软件包。
设置 ROS 软件包
按照以下步骤设置 ROS 软件包:
- 从终端克隆书籍仓库
github.com/PacktPublishing/Hands-On-ROS-for-Robotics-Programming到您的家目录:
$ cd ~
$ git clone https://github.com/PacktPublishing/Hands-On-ROS-for-Robotics-Programming
- 我们将把本章的代码复制到 ROS 工作区。这样,您将有一个更干净的 ROS 环境:
$ cp -R ~/Hands-On-ROS-for-Robotics-Programming/Chapter3_ROS_basics ~/catkin_ws/src
不要在 src 文件夹名称后添加反斜杠,\n。如果您这样做,文件将直接复制到 src 文件夹,而不是在 src/Chapter3_ROS_basics 之下。
- 在
Chapter3_ROS_basics文件夹中,您可以找到属于您将要使用的第一个 ROS 软件包的本章文件。其配置包含在package.xml文件中。请注意,软件包名称定义在<name>ros_basics</name>标签内。您可以在以下代码文件中找到它:
<?xml version="1.0"?>
<package format="2">
<name>ros_basics</name>
<version>0.0.0</version>
<description>Code samples for "Chapter 3: Getting started with ROS"</description>
<maintainer email="brjapon@therobotacademy.com">Bernardo R. Japon</maintainer
<license>GNU v3.0</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>rospy</build_depend>
<build_export_depend>rospy</build_export_depend>
<exec_depend>rospy</exec_depend>
</package>
- 然后,前往工作区根目录并再次构建:
$ cd ~/catkin_ws
$ catkin_make
$ source ~/catkin_ws/devel/setup.bash
通常,您至少需要在以下两种情况下重新构建工作区:
-
每次您包含一个新的软件包
-
如果您的代码包含用可编译语言(如 C++)编写的部分
在这本书中,我们将主要使用 Python,这是一种广泛使用的开源语言,它使得开始使用 ROS 更加容易。由于 Python 是一种解释型语言,因此您不需要每次修改软件包的代码库时都重新构建工作区。因此,只有在添加或删除 ROS 软件包时才需要重新构建。检查新添加的软件包 ros_basics 是否为 ROS 所知的方法是执行此简单命令:
$ rospack list | grep ros_basics
输出应该看起来像这样:
ros_basics /home/bronquillo/catkin_ws/src/book/Chapter3_ROS_basics
虽然在这里,我们将从一个预制的 ROS 软件包开始工作,但了解在此阶段如何从头开始创建自己的软件包是相关的。从您工作区 src 位置运行此命令($ cd ~/catkin_ws/src/):
$ catkin_create_pkg <YOUR-PACKAGE-NAME> <DEPENDENCIES>
<YOUR-PACKAGE-NAME> 代表您想要分配给软件包的名称。<DEPENDENCIES> 指的是您代码运行所需的 ROS 软件包列表。例如,如果您的软件包将包含 Python 和 C++ 代码,您将需要 rospy 用于前者,roscpp 用于后者。然后,命令将如下所示:
$ catkin_create_pkg <YOUR-PACKAGE-NAME> rospy roscpp
这将创建一个以软件包名称命名的文件夹和两个文件:
-
package.xml:如前所述的软件包配置 -
CMakelists.txt:CMake 构建系统的输入,用于构建软件包
CMakelists.txt 也包含对 <YOUR-PACKAGE-NAME> 的引用。在我们的例子中,此文件如下所示:
cmake_minimum_required(VERSION 2.8.3)
project(ros_basics)
find_package(catkin REQUIRED COMPONENTS rospy)
###################################
## catkin specific configuration ##
###################################
catkin_package()
###########
## Build ##
###########
include_directories()
使用 RoboWare 访问软件包文件并构建工作区
这里有一个替代方法。以下演示了您可以使用 RoboWare 克隆软件包仓库并构建工作区。
在按照设置 ROS 包部分中解释的方法克隆并放置章节代码后,你可以在 IDE 窗口左侧的文件树视图中探索内容。点击任何文件都会让你在主窗口中看到内容:
最后,构建工作空间;请注意,每次你创建自己的新包或克隆外部包时,你都需要做这件事。为此,转到顶部菜单栏,选择 ROS,然后像以前一样点击构建。
发布主题的节点
对于接下来的步骤,由于我们需要处理多个同时终端,我们将使用一个非常方便的工具,即 Terminator,它允许你同时处理多个终端。运行以下命令在你的系统上安装它:
$ sudo apt-get update
$ sudo apt-get install terminator
启动 Terminator 并将屏幕分为四个终端(你可以通过鼠标右键连续分割窗口)。我们将它们分别称为T1、T2、T3和T4,如下面的截图所示:
在终端 1(左上角的窗口)中启动 roscore 节点:
T1 $ roscore
你应该能在T1中看到这个输出:
这是 ROS 的根进程。roscore 启动一个节点并启动主服务,因为 ROS 是一个集中式系统。主节点始终是必需的,以便其他节点可以执行,并且必须在任何其他节点之前启动。
在下一个终端T2中,运行以下命令来启动发布者节点:
T2 $ rosrun ros_basics topic_publisher.py
这将启动topic_publisher节点,但没有任何事情发生!没错。发布者就是那样,一个发布者。我们需要一个监听器来了解正在发送什么数据。
前往终端 3 并列出当前声明的主题:
T3 $ rostopic list
/counter
/rosout
/rosout_agg
在列表中,/counter似乎是一个每 0.5 秒更新增量计数器的主题。其他两个主题/rosout和/rosout_agg是 ROS 中的控制台日志报告机制。
topic_publisher.py文件中的这一行设置了/counter主题发布者:
pub = rospy.Publisher('counter', Int32, queue_size=10)
要查看发布的消息,请在终端中运行此命令:
T3 $ rostopic echo counter -n 5
这将输出将在/counter主题中发布的下五条消息:
data: 530
---
data: 531
---
data: 532
---
data: 533
---
data: 534
---
最后,我们将展示一个实时视图,它会打印发送消息的实时频率:
T3 $ rostopic hz counter
average rate: 2.000
min: 0.500s max: 0.501s std dev: 0.00020s window: 146
average rate: 2.000
min: 0.500s max: 0.501s std dev: 0.00020s window: 148
average rate: 2.000
min: 0.500s max: 0.501s std dev: 0.00020s window: 150
average rate: 2.000
min: 0.500s max: 0.501s std dev: 0.00020s window: 152
average rate: 2.000
min: 0.500s max: 0.501s std dev: 0.00020s window: 154
average rate: 2.000
min: 0.500s max: 0.501s std dev: 0.00020s window: 156
average rate: 2.000
按Ctrl + C停止T3中的日志。请注意,如果你在前两个终端中的任何一个终端这样做,每个终端控制的进程都将终止,并产生以下后果:
-
终端 T2:发布者进程将结束,并且不再通过
/counter主题发送消息。 -
终端 T1:在此终端中按下Ctrl + C将终止 roscore,这使人们明显看出,这个过程是 ROS 的单点故障,也就是说,所有相关进程(包括节点和消息)都将终止。
监听主题的节点
由于有一个节点在/counter主题上发布增量计数,我们现在将启动一个订阅此主题的节点。
首先,让我们通过在T3中发出以下命令来可视化当前的 ROS 图:
T3 $ rqt_graph
一个窗口会弹出并显示以下内容:
只有一个节点,即我们在T2中启动的那个。/counter主题没有出现,因为没有其他节点在监听它。为了使主题显示,请在T4中启动监听器:
T4 $ rosrun ros_basics topic_subscriber.py
你将在右下角的终端窗口中看到这个日志,除非你终止(按Ctrl + C)T1或T2中的任何一个,它们分别对应于roscore和topic_publisher。
如果你回到 ROS 图窗口并点击更新图标,你会看到/topic_publisher节点,路由消息的/counter主题,以及监听节点/topic_subscriber:
这个简单的例子说明了 ROS 中通信的发布/订阅架构。你已经可以欣赏到它是如何工作的,以及底层通信原理是多么简单,这是 ROS 框架的基础。我们现在将做一些实际的操作。
让我们的计数器表现得像一个计时器。我们该如何做呢?嗯,你只需要修改脚本topic_publisher.py,通过更改指定每秒向主题发送消息次数的参数,这个概念被称为发布的频率,其单位是赫兹(=次数/秒)。在脚本中,负责这种行为的 Python 对象是:
rate = rospy.Rate(2)
在脚本下面的循环中,通过将rospy的sleep方法应用于定义的rate对象来实现配置的行为:
rate.sleep()
记住,rospy是允许我们运行用 Python 编写的节点的 ROS 库。rospy定义了一组方法来在 ROS 中实现有用的功能,例如以这种方式设置发布频率。
上面的行表示每秒发布两条消息,即每 0.5 秒一条消息。因此,如果rate设置为 1 Hz,频率将是每秒一条消息,因此模拟了一个计时器。你可以在不需要停止 ROS 的情况下修改这样的脚本topic_publisher.py,并且一旦再次执行它,节点就会回到图中。让我们一步一步地展示如何做:
-
在终端
T2中按Ctrl + C停止节点的执行。 -
修改文件以以 1 Hz 的速率发布,如之前所示。
-
然后,重新启动节点:
T2 $ rosrun ros_basics topic_publisher.py
你将在启动topic_subscriber.py的终端T4中看到效果。因此,新行出现的速度(即计数)将是之前的两倍,当速率是 2 Hz 时。这将产生每秒一次的计数更新(+1),对应于 1 Hz 的速率。
在同一节点中结合发布者和订阅者
一个节点能否像真实人类一样同时说话和监听?嗯,如果 ROS 是一个机器人框架,那么这是可能的。让我们来探索这个问题:
- 在前两个终端中启动这两个命令,每个命令都在一个独立的终端中:
T1 $ roscore
T2 $ rosrun ros_basics doubler.py
/doubler 是一个订阅 /number 主题的节点,如 doubler.py 脚本中的这两行所述:
rospy.init_node('doubler')
...
sub = rospy.Subscriber('number', Int32, callback)
...
此外,/doubler 还在 /doubled 主题中发布其结果:
...
pub = rospy.Publisher('doubled', Int32, queue_size=10)
你会注意到没有任何事情发生,因为它需要被喂以可以乘以 2 的数字,如 topic_subscriber.py 的回调中所示:
def callback(msg):
doubled = Int32()
doubled.data = msg.data * 2
- 启动一个用于监听
/doubled主题的终端:
T3 $ rostopic echo doubled
然后,让我们手动发布一个 /number 主题:
T4 $ rostopic pub number std_msgs/Int32 2
publishing and latching message. Press ctrl-C to terminate
T3 终端的输出是 4,正如预期的那样:
data: 4
---
- 在
T4中尝试发送其他数字,并检查双倍值是否立即在T3中显示。
如果你在一个第五个终端中发出 rqt_graph,你会看到类似这样的内容:
这里,你可以看到 /number 和 /doubled 主题,/doubler 节点,以及两个具有大机器名称的其他节点,它们的对应关系如下:
-
- 前一图中左侧的节点
/rostopic_5469_是由T4中的命令创建的:
- 前一图中左侧的节点
T4 $ rostopic pub number std_msgs/Int32 2
-
- 右侧的节点
/rostopic_5631_是由T3中的命令创建的:
- 右侧的节点
T3 $ rostopic echo doubled
- 为了完成这个练习,我们将把数字喂给
/counter主题,不是从命令行,而是从上一节中看到的发布节点脚本topic_publisher.py中:将doubler.py中的主题名称修改为counter:
sub = rospy.Subscriber('counter', Int32, callback)
然后,在停止所有终端后,在每个独立的终端中执行以下每一行:
T1 $ roscore
T2 $ rosrun ros_basics doubler.py
T3 $ rosrun ros_basics topic_publisher.py
T4 $ rostopic echo doubled
在这个终端中,每次发布 /counter 时,你将看到 counter * 2 的结果。看看 ROS 图(记得点击刷新按钮),你会发现它反映了正在发生的事情:
请记住,rqt_graph 在调试代码时将提供非常有用的信息,例如,检测主题名称中的任何错误。看看下面的图,其中乘以 2 不起作用,因为 /topic_publisher 订阅了 count 主题(注意末尾缺少 r 字符)。节点彼此断开连接,错误输入的主题(没有人监听)没有出现:
在下一节中,我们将概述 ROS 包系统的扩展。
使用 ROS 的公共包
ROS 贡献的包在官方网站 www.ros.org/browse/list.php 上索引。
截至 2018 年 7 月,ROS Indigo(为 Ubuntu 14.04 LTS 发布的发行版)有超过 2900 个包,而 ROS Kinetic(2016 年,Ubuntu 16.04 LTS)有超过 1600 个。其中一些下载量较大的包括以下内容:
-
rviz(wiki.ros.org/rviz): 这是 ROS 的 3D 可视化工具。您将在第四章,创建虚拟双轮 ROS 机器人中开始使用它。 -
gazebo_ros_pkgs(wiki.ros.org/gazebo_ros_pkgs): 这允许您在 ROS 内部使用 Gazebo 3D 模拟器。我们将在第五章,使用 Gazebo 模拟机器人行为中介绍 Gazebo。 -
sensor-msgs(wiki.ros.org/sensor_msgs): 这是一个定义常用传感器(如摄像头和扫描激光测距仪)消息的包。 -
tf2(wiki.ros.org/tf2): 这是一个处理环境中所用到的多个参考系之间坐标变换的包。 -
laser-geometry(wiki.ros.org/laser_geometry): 这使得将 2D 激光扫描转换为点云以用于导航成为可能。
这应该能给您一个清晰的了解,ROS 编程对您意味着什么。换句话说,集成其他开发者(即包)开发的软件,并通过设计一个连贯的 ROS 图来使它们协同工作,以构建您希望机器人拥有的功能。
摘要
在本章中,我们介绍了 ROS,并通过简单的示例进行实践,以便帮助您理解 ROS 的架构。顶级实体是工作空间,它是一个用于构建和运行软件的独立环境。
工作空间由 ROS 包组成,即提供特定功能以集成到您的机器人中的预制的软件块。随后,catkin 是每次您在工作空间中包含新包时用于构建软件的工具。
节点是 ROS 中的基本实体,它包含使机器人工作的功能代码块。提供特定功能的节点集合构成了一个 ROS 包。roscore,运行主节点的进程,允许每个节点通过订阅发布的主题来找到其他节点。roscore还管理 ROS 参数的数据库。
节点之间的通信是通过主题实现的,主题是 ROS 图中的通道——信息流过的边缘。当一个节点需要使用主题的信息时,它通过订阅它来实现。
在下一章中,你将学习如何构建一个差速驱动机器人的虚拟模型,该模型模拟 GoPiGo3 的特性。本章还将为你提供方法,首先使用虚拟机器人测试你的代码,然后安装并在物理机器人上执行它。
问题
- ROS 环境中的顶级组件是什么?
A) 包
B) 工作空间
C) ROS 图
- roscore 进程的目的是什么?
A) 允许节点与其他节点通信并管理机器人参数
B) 为图中的所有其他节点提供主节点
C) 允许 ROS 节点从 LAN 外部被发现
- 标记正确的句子:一个节点可以 __ 。
A) 只发布主题或只订阅主题
B) 同时发布主题和订阅主题
C) 发布主题和/或订阅其他主题
- 如果一个节点未能执行其程序,会发生什么?
A) 机器人的一些功能将失败
B) 机器人将无法工作
C) 它发布的主题将被设置为未定义
- 标记错误的句子:在发布的主题中识别消息的方法是 __。
A) 启动一个发布此类主题数据的节点
B) 输入 $ rostopic echo </topic_name> 命令
C) 编写一个订阅该主题的节点
进一步阅读
要深入了解本章中解释的概念,你可以遵循以下链接和教程:
-
ROS 教程s:
wiki.ros.org/ROS/Tutorials(第一部分至第六部分) -
ROS 机器人实例,第二版,Fairchild C.,Harman,Packt Publishing,T. L。(2017),第一章,ROS 入门:
www.packtpub.com/hardware-and-creative/ros-robotics-example-second-edition。 -
使用 ROS 编程机器人,Quigley M.,Gerkey B.,Bill Smart B。(2015),第一版,O’Reilly:
shop.oreilly.com/product/0636920024736.do(第二章,预备知识和第三章,主题)。
1617

被折叠的 条评论
为什么被折叠?



