一、机器人操作系统入门
本书的主要目的是教您如何从头开始构建自动移动机器人。 机器人将使用 ROS 进行编程,其操作将使用名为 Gazebo 的模拟器进行模拟。 在接下来的章节中,您还将看到使用 ROS 的机器人的机械设计,电路设计,嵌入式编程和高级软件编程。
在本章中,我们将从 ROS 的基础知识,如何安装 ROS,如何使用 ROS 和 Python 编写基本应用以及 Gazebo 的基础知识开始。 本章将成为您自主机器人项目的基础。 如果您已经了解 ROS 的基础知识,并且已经在系统上安装了 ROS,则可以跳过本章。 但是,您仍然可以在后面的章节中浏览有关 ROS 基础的内容。
本章将涵盖以下主题:
- ROS 介绍
- 在 Ubuntu 16.04.3 上安装 ROS Kinetic
- Gazebo 的介绍,安装和测试
让我们开始使用 Python 和机器人操作系统(ROS)对机器人进行编程。
技术要求
要获取本章中提到的完整代码,可以克隆以下链接。
ROS 介绍
ROS 是用于创建机器人应用的软件框架。 ROS 框架的主要目的是提供可用于创建功能强大的机器人应用的功能,这些功能可重复用于其他机器人。 ROS 拥有软件工具,库和包的集合,这使得机器人软件开发变得容易。
ROS 是根据 BSD 许可许可的完整开源项目。 我们可以将其用于研究和商业应用。 即使 ROS 代表机器人操作系统,它也不是真正的操作系统。 相反,它是一个元操作系统,提供了真实操作系统的功能。 ROS 提供的主要功能如下:
- 消息传递接口:这是 ROS 的核心功能,它使进程间通信成为可能。 使用此消息传递功能,ROS 程序可以与其链接的系统进行通信并交换数据。 在接下来的章节中,我们将学习有关 ROS 程序/节点之间的数据交换的更多技术术语。
- 硬件抽象:ROS 具有一定程度的抽象,使开发人员可以创建与机器人无关的应用。 这些类型的应用可用于任何机器人。 开发人员只需要担心底层机器人硬件。
- 包管理:ROS 节点被组织在称为 ROS 包的包中。 ROS 包包括源代码,配置文件,构建文件等。 我们创建包,构建包并安装该包。 ROS 中有一个构建系统,可以帮助构建这些包。 ROS 中的包管理使 ROS 开发更加系统和有组织。
- 第三方库集成:ROS 框架与许多第三方库集成,例如 OpenCV,PCL,OpenNI 等。 这有助于开发人员在 ROS 中创建各种应用。
- 低级设备控制:使用机器人时,我们可能需要使用低级设备,例如控制 I/O 引脚,通过串行端口发送数据的设备等。 这也可以使用 ROS 完成。
- 分布式计算:处理来自机器人传感器的数据所需的计算量非常大。 使用 ROS,我们可以轻松地将计算分配到计算节点的群集中。 这样可以分配计算能力,并使您可以比使用单台计算机更快地处理数据。
- 代码重用:ROS 的主要目标是代码重用。 代码重用使世界各地良好的研发社区得以发展。 ROS 可执行文件称为节点。 这些可执行文件可以分组为一个称为 ROS 包的实体。 一组包称为元包,包和元包都可以共享和分发。
- 语言独立性:可以使用流行的语言(例如 Python,C 和 Lisp)对 ROS 框架进行编程。 节点可以用任何语言编写,并且可以通过 ROS 进行通信而没有任何问题。
- 易于测试:ROS 有一个内置的单元/集成测试框架,称为 rostest,用于测试 ROS 包。
- 缩放比例:可以缩放 ROS,以在机器人中执行复杂的计算。
- 免费和开源:ROS 的源代码是开放的,并且绝对免费。 ROS 的核心部分已获得 BSD 许可,并可以在商业和封闭源产品中重复使用。
ROS 是管道(消息传递),工具,功能和生态系统的组合。 ROS 中有强大的工具可以调试和可视化机器人数据。 ROS 中具有内置的机器人功能,例如机器人导航,本地化,地图绘制,操纵等。 它们有助于创建功能强大的机器人应用。
下图显示了 ROS 方程:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n1Fukqk8-1681873679406)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00005.jpeg)]
ROS 方程
有关 ROS 的更多信息,请参见这个页面。
ROS 概念
ROS 中有三个主要的组织级别:
- ROS 文件系统
- ROS 计算图
- ROS 社区
ROS 文件系统
ROS 文件系统主要介绍如何在磁盘上组织 ROS 文件。 以下是使用 ROS 文件系统时必须了解的主要术语:
- 包:ROS 包是 ROS 软件框架的独立单元。 ROS 包可能包含源代码,第三方库,配置文件等。 ROS 包可以重复使用和共享。
- 包清单:清单(
package.xml
)文件将包含包的所有详细信息,包括名称,描述,许可证,以及更重要的是包的依赖项。 - 消息(
msg
)类型:消息描述存储在包的msg
文件夹中。 ROS 消息是用于通过 ROS 的消息传递系统发送数据的数据结构。 消息定义存储在扩展名为.msg
的文件中。 - 服务(
srv
)类型:服务描述以.srv
扩展名存储在srv
文件夹中。srv
文件在 ROS 中定义了服务的请求和响应数据结构。
ROS 计算图
ROS 计算图是处理数据的 ROS 系统的对等网络。 ROS 计算图的基本功能是节点,ROS 主节点,参数服务器,消息和服务:
- 节点:ROS 节点是使用 ROS 功能来处理数据的过程。 节点基本上进行计算。 例如,节点可以处理激光扫描仪数据以检查是否存在任何冲突。 这将在后续部分“在 ROS 客户端库的帮助下编写 ROS 节点”(例如
roscpp
和rospy
)中进行讨论。 - ROS 主机:ROS 节点可以使用称为 ROS 主机的程序相互连接。 这将为其余的计算图提供名称,注册和查找。 如果不启动主服务器,节点将不会彼此发现并发送消息。
- 参数服务器:ROS 参数是静态值,存储在称为参数服务器的全局位置中。 从参数服务器,所有节点都可以访问这些值。 我们甚至可以将参数服务器的范围设置为私有或公共,以便它可以访问一个节点或访问所有节点。
- ROS 主题:ROS 节点使用名为 ROS 主题的命名总线相互通信。 数据以消息的形式流经主题。 通过主题发送消息称为发布,通过主题接收数据称为订阅。
- 消息:ROS 消息是一种数据类型,可以由原始数据类型组成,例如整数,浮点数和布尔值。 ROS 消息流经 ROS 主题。 主题一次只能发送/接收一种类型的消息。 我们可以创建自己的消息定义并通过主题发送它。
- 服务:我们已经看到使用 ROS 主题的发布/订阅模型是一种非常简单的通信方式。 这种通信方法是一对多的通信方式,这意味着可以由任意数量的节点订阅主题。 在某些情况下,我们可能还需要一种请求/答复类型的交互,通常在分布式系统中使用。 可以使用 ROS 服务来完成这种交互。 ROS 服务与 ROS 主题的工作方式类似,因为它们具有消息类型定义。 使用该消息定义,我们可以将服务请求发送到另一个提供服务的节点。 服务结果将作为答复发送。 该节点必须等待,直到从另一个节点接收到结果。
- 袋子:这些是保存和播放 ROS 主题的格式。 ROS 袋子是记录传感器数据和处理后数据的重要工具。 这些包可以稍后用于离线测试我们的算法。
下图显示了主题和服务如何在节点与主服务器之间工作:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fkw8ONnr-1681873679407)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00006.jpeg)]
ROS 节点与 ROS 主机之间的通信
在上图中,您可以看到两个 ROS 节点以及它们之间的 ROS 主机。 我们必须记住的一件事是,在启动 ROS 中的任何节点之前,您应该启动 ROS 主机。 ROS 主机就像节点之间的中介程序一样,用于交换有关其他 ROS 节点的信息以建立通信。 假设节点 1 要发布消息类型为abc
的名为/xyz
的主题。 它将首先接近 ROS 主机,并说I am going to publish a topic called /xyz with message type abc and share its details
。 当另一个节点(例如节点 2)想要订阅消息类型为abc
的同一主题/xyz
时,主节点将共享有关节点 1 的信息,并分配一个端口以直接开始这两个节点之间的通信,而无需与 ROS 主机通信。
ROS 服务以相同的方式工作。 ROS 主机是一种 DNS 服务器,当第二个节点向第一个节点请求主题或服务时,可以共享节点详细信息。 ROS 使用的通信协议是 TCPROS,它基本上使用 TCP/IP 套接字进行通信。
ROS 社区级别
ROS 社区由 ROS 开发人员和研究人员组成,他们可以创建和维护包并交换与现有包,新发布的包以及与 ROS 框架相关的其他新闻的新信息。 ROS 社区提供以下服务:
- 发行版:ROS 发行版具有一组特定版本的包。 本书中使用的发行版是 ROS Kinetic。 还有其他可用的版本,例如 ROS Lunar 和 Indigo,它们具有可以安装的特定版本。 在每个发行版中维护包都比较容易。 在大多数情况下,发行版中的包将相对稳定。
- 存储库:在线存储库是我们保存包的位置。 通常,开发人员会在存储库中保留一组称为元包的类似包。 我们还可以将单个包保存在单个存储库中。 我们可以简单地克隆这些存储库并构建或重用这些包。
- ROS Wiki:几乎所有 ROS 文档都可以在 ROS Wiki 上找到。 您可以使用 ROS Wiki 了解 ROS,从最基本的概念到最高级的编程。
- 邮件列表:如果要获取有关 ROS 的更新,可以订阅 ROS 邮件列表 您还可以从 ROS Discourse 获取最新的 ROS 新闻。
- ROS 回答:这与 Stack Overflow 网站非常相似。 您可以在此门户网站中提出与 ROS 相关的问题,并且可能会得到来自世界各地的开发人员的支持。
ROS 中还有许多其他功能。 您可以访问 ROS 官方网站 www.ros.org 以获得更多信息。 现在,我们将继续进行 ROS 的安装过程。
在 Ubuntu 上安装 ROS
根据前面的讨论,我们知道 ROS 是安装在主机系统上的元操作系统。 在 Ubuntu/Linux 上以及在 Windows 和 OS X 的试验阶段,都完全支持 ROS。一些最新的 ROS 发行版如下:
分发版 | 发布日期 |
---|---|
ROS Melodic Morenia | 2018 年 5 月 23 日 |
ROS Lunar Loggerhead | 2017 年 5 月 23 日 |
ROS Kinetic Kame | 2016 年 5 月 23 日 |
ROS Indigo Igloo | 2014 年 7 月 22 日 |
现在,我们将研究 Ubuntu 16.04.3 LTS 上称为 Kinetic 的 ROS 的稳定,长期支持(LTS)发行版的安装过程。 ROS Kinetic Kame 将主要针对 Ubuntu 16.04 LTS。 在查看以下说明后,您还可以在 Ubuntu 18.04 LTS 的最新 LTS Melodic Morenia 中找到设置 ROS 的说明。 如果您是 Windows 或 OS X 用户,则可以先在 VirtualBox 应用中安装 Ubuntu,然后再在其上安装 ROS。 下载 VirtualBox 的链接是这里。
您可以在这个页面找到完整的说明。
步骤如下:
- 配置您的 Ubuntu 存储库,以允许受限制的,Universe 和多版本的可下载文件。 我们可以使用 Ubuntu 的软件和更新工具对其进行配置。 我们可以通过简单地在 Ubuntu Unity 搜索菜单上进行搜索并勾选以下屏幕快照中的显示来获得此工具:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F0JcxSoW-1681873679407)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00007.jpeg)]
Ubuntu 的软件和更新工具
- 设置系统以接受
packages.ros.org
中的 ROS 包。 仅 Ubuntu 15.10 和 16.04 支持 ROS Kinetic。 以下命令将packages.ros.org
存储在 Ubuntu 的apt
存储库列表中:
$ sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
- 接下来,我们必须添加
apt-key
。apt-key
用于管理 APT 用来验证包的密钥列表。 使用这些密钥进行身份验证的包将被视为受信任的包。 以下命令将为 ROS 包添加apt-key
:
sudo apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-key 421C365BD9FF1F717815A3895523BAEEB01FA116
- 添加
apt-key
后,我们必须更新 Ubuntu 包列表。 以下命令将添加和更新 ROS 包以及 Ubuntu 包:
$ sudo apt-get update
- 更新 ROS 包后,我们可以安装这些包。 以下命令将安装所有必需的 ROS 包,工具和库:
$ sudo apt-get install ros-kinetic-desktop-full
- 即使在桌面完全安装后,我们也可能需要安装其他包。 每个附加安装将在相应的部分中提到。 桌面完整安装将需要一些时间。 安装 ROS 之后,您几乎可以完成。 下一步是初始化
rosdep
,这使您可以轻松安装 ROS 源包的系统依赖关系:
$ sudo rosdep init
$ rosdep update
- 要在当前 bash shell 上访问 ROS 的工具和命令,我们可以将 ROS 环境变量添加到
.bashrc
文件中。 这将在每个 bash 会话开始时执行。 以下是将 ROS 变量添加到.bashrc
的命令:
echo "source /opt/ros/kinetic/setup.bash" >> ~/.bashrc
以下命令将在当前 shell 上执行.bashrc
脚本,以在当前 shell 中生成更改:
source ~/.bashrc
rosinstall
是安装包依赖项的有用工具。 该工具必须单独安装。 它使您能够通过一个命令轻松下载 ROS 包的许多源代码树:
$ sudo apt-get install python-rosinstall python-rosinstall-generator python-wstool build-essential
最新的 LTS Melodic 的安装与前面的说明类似。 您可以将 Melodic 与 Ubuntu 18.04 LTS 一起安装。 您可以在这个页面中找到完整的说明。
安装 ROS 之后,我们将讨论如何在 ROS 中创建示例包。 在创建包之前,我们必须创建一个 ROS 工作区。 这些包是在 ROS 工作区中创建的。 我们将使用 catkin 构建系统,该系统是用于在 ROS 中构建包的一组工具。 catkin 构建系统从源代码生成可执行文件或共享库。 ROS Kinetic 使用 catkin 构建系统来构建包。 让我们看看什么是柳絮。
Catkin 介绍
Catkin 是 ROS 的官方构建系统。 在发布 catkin 之前,ROS 使用 rosbuild 系统来构建包。 它的替代品是最新 ROS 版本上的柳絮。 Catkin 结合了 CMake 宏和 Python 脚本,以提供与 CMake 相同的正常工作流程。 与 rosbuild 系统相比,Catkin 可提供更好的包分发,更好的交叉编译和更好的可移植性。 有关更多信息,请参阅 wiki.ros.org/catkin。
Catkin 工作区是一个文件夹,您可以在其中修改,构建和安装 catkin 包。
让我们检查一下如何创建 ROS catkin 工作区。
以下命令将创建一个名为catkin_ws
的父目录和一个名为src
的子文件夹:
$ mkdir -p ~/catkin_ws/src
使用以下命令将目录切换到src
文件夹。 我们将在src
文件夹中创建包:
$ cd ~/catkin_ws/src
使用以下命令初始化 catkin 工作区:
代码语言:javascript复制 $ catkin_init_workspace
初始化 catkin 工作区之后,您可以使用以下命令简单地构建包(即使没有源文件):
代码语言:javascript复制 $ cd ~/catkin_ws/
$ catkin_make
catkin_make
命令用于在src
目录中构建包。 构建包后,我们将在catkin_ws
中看到build
和devel
文件夹。可执行文件存储在build
文件夹中。 在devel
文件夹中,有一些外壳脚本文件可将工作空间添加到 ROS 环境中。
创建一个 ROS 包
在本节中,我们将研究如何创建一个包含两个 Python 节点的示例包。 其中一个节点用于在名为/hello_pub
的主题上发布Hello World
字符串消息,而另一个节点将订阅该主题。
可以使用 ROS 中的catkin_create_pkg
命令来创建 catkin ROS 包。
包是在创建工作区期间创建的src
文件夹中创建的。 在创建包之前,使用以下命令切换到src
文件夹:
$ cd ~/catkin_ws/src
以下命令将创建具有std_msgs
依赖项的hello_world
包,其中包含标准消息定义。 rospy
是 ROS 的 Python 客户端库:
$ catkin_create_pkg hello_world std_msgs rospy
这是我们成功创建时得到的信息:
代码语言:javascript复制 Created file hello_world/package.xml
Created file hello_world/CMakeLists.txt
Created folder hello_world/src
Successfully created files in /home/lentin/catkin_ws/src/hello_world.
Please adjust the values in package.xml.
成功创建hello_world
包后,我们需要添加两个 Python 节点或脚本来演示主题的订阅和发布。
首先,使用以下命令在hello_world
包中创建一个名为scripts
的文件夹:
$ mkdir scripts
切换到scripts
文件夹,创建一个名为hello_world_publisher.py
的脚本和另一个名为hello_world_subscriber.py
的脚本,以发布和订阅hello world
消息。 以下部分介绍了这些脚本或节点的代码和功能:
Hello_world_publisher.py
hello_world_publisher.py
节点基本上将名为hello world
的问候消息发布到名为/hello_pub
的主题。 问候消息以 10Hz 的速率发布到主题。
这是显示两个 ROS 节点之间的相互作用如何工作的图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z3Pjj2UK-1681873679407)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00008.jpeg)]
发布者和订阅者节点之间的通信
本书的完整代码可在这个页面获得。
有关此代码如何工作的分步说明如下:
- 如果要编写 ROS Python 节点,则需要导入
rospy
。 它包含与 ROS 主题,服务等交互的 Python API。 - 要发送
Hello World
消息,我们必须从std_msgs
包中导入String
消息数据类型。std_msgs
包具有标准数据类型的消息定义。 我们可以使用以下代码行导入:
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
- 下面的代码行创建名为
hello_pub
的主题的发布者对象。 消息类型为String
,queue_size
值为10
。 如果订阅者的速度不足以接收数据,我们可以使用queue_size
选项对其进行缓冲:
def talker():
pub = rospy.Publisher('hello_pub', String, queue_size=10)
- 下面的代码行初始化 ROS 节点。 还将为该节点分配名称。 如果两个节点以相同的节点名称运行,则一个节点将关闭。 如果我们要同时运行两者,请使用匿名
=True
标志,如以下代码所示:
rospy.init_node('hello_world_publisher', anonymous=True)
- 下一行创建一个名为
r
的费率对象。 使用Rate
对象中的sleep()
方法,我们可以以所需的速率更新循环。 在这里,我们给比率为10
的值:
r = rospy.Rate(10) # 10hz
- 以下循环将检查
rospy
是否构造了rospy.is_shutdown()
标志。 然后,它执行循环。 如果单击Ctrl C
,则此循环将退出。
在循环内部,终端世界上将打印一个hello world
消息,并以 10Hz 的速率发布在hello_pub
主题上:
while not rospy.is_shutdown():
str = "hello world %s"%rospy.get_time()
rospy.loginfo(str)
pub.publish(str)
r.sleep()
- 以下代码具有 Python
__main__
检查并调用talker()
函数。 该代码将继续执行talker()
,并在按Ctrl C
时关闭该节点:
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException: pass
发布主题后,我们将了解如何订阅它。 下一节介绍了订阅hello_pub
主题所需的代码。
Hello_world_subscriber.py
订户代码如下:
代码语言:javascript复制#!/usr/bin/env python
import rospy
from std_msgs.msg import String
以下代码是当消息到达hello_pub
主题时执行的回调函数。 data
变量包含来自主题的消息,它将使用rospy.loginfo()
打印:
def callback(data):
rospy.loginfo(rospy.get_caller_id() "I heard %s",data.data)
以下步骤将以hello_world_subscriber
名称启动节点并开始订阅/hello_pub
主题:
- 消息的数据类型为
String
,当消息到达此主题时,将调用一种称为回调的方法:
def listener():
rospy.init_node('hello_world_subscriber',
anonymous=True)
rospy.Subscriber("hello_pub", String, callback)
- 以下代码将阻止您的节点退出,直到该节点关闭:
rospy.spin()
- 以下是 Python 代码的主要部分。 主要部分将调用
listener()
方法,该方法将订阅/hello_pub
主题:
if __name__ == '__main__':
listener()
- 保存两个 Python 节点后,您需要使用
chmod
命令将权限更改为可执行文件:
chmod x hello_world_publisher.py
chmod x hello_world_subscriber.py
- 更改文件许可权后,使用
catkin_make
命令构建包:
cd ~/catkin_ws
catkin_make
- 以下命令将当前 ROS 工作空间路径添加到所有终端中,以便我们可以访问此工作空间内的 ROS 包:
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc
以下是订阅服务器和发布服务器节点的输出:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ovtimJzf-1681873679408)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00009.jpeg)]
你好世界节点的输出
- 首先,我们需要在启动节点之前运行
roscore
。 需要roscore
命令或 ROS 主节点才能在节点之间进行通信。 因此,第一个命令如下:
$ roscore
- 执行
roscore
之后,使用以下命令运行每个节点:
$ rosrun hello_world hello_world_publisher.py
代码语言:javascript复制 $ rosrun hello_world hello_world_subscriber.py
我们已经介绍了 ROS 的一些基础知识。 现在,我们将了解什么是 Gazebo,以及如何使用 ROS 与 Gazebo 一起工作。
Gazebo 介绍
Gazebo是一个免费的开源机器人模拟器,我们可以在其中测试自己的算法,设计机器人并在不同的模拟环境中测试机器人。 Gazebo 可以在室内和室外环境中准确,高效地模拟复杂的机器人。 Gazebo 是使用物理引擎构建的,通过它我们可以创建高质量的图形和渲染。
Gazebo 的功能如下:
- 动态仿真:Gazebo 可以使用诸如开放式动力学引擎(ODE),Bullet,Simbody 和 DART 之类的物理引擎来模拟机器人的动力学。。
- 高级 3D 图形:Gazebo 使用 OGRE 框架提供了高质量的渲染,照明,阴影和纹理。
- 传感器支持:Gazebo 支持多种传感器,包括激光测距仪,Kinect 型传感器,2D/3D 摄像机等。 我们还可以使用它来模拟噪声以测试音频传感器。
- 插件:我们可以为机器人,传感器和环境控件开发自定义插件。 插件可以访问 Gazebo 的 API。
- 机器人模型:Gazebo 为流行的机器人提供模型,例如 PR2,Pioneer 2 DX,iRobot Create 和 TurtleBot。 我们还可以构建机器人的自定义模型。
- TCP/IP 传输:我们可以通过基于套接字的消息传递服务在远程计算机和 Gazebo 接口上运行模拟。
- 云模拟:我们可以使用 CloudSim 框架在云服务器上运行模拟。
- 命令行工具:广泛的命令行工具用于检查和记录模拟。
安装 Gazebo
Gazebo 可以与 ROS 一起安装为独立应用或集成应用。 在本章中,我们将结合使用 Gazebo 和 ROS 来模拟机器人的行为并使用 ROS 框架来测试我们编写的代码。
如果您想亲自尝试最新的 Gazebo 模拟器,则可以按照这个页面中给出的步骤进行操作。
要使用 Gazebo 和 ROS,我们不需要单独安装它们,因为 Gazebo 随附了 ROS 桌面完整安装。
将 Gazebo 与 ROS 集成在一起的 ROS 包称为gazebo_ros_pkgs
。 独立的 Gazebo 周围有包装纸。 该包提供了使用 ROS 消息服务在 Gazebo 中模拟机器人的必要接口。
可以使用以下命令将完整的gazebo_ros_pkgs
安装在 ROS Indigo 中:
$ sudo apt-get install ros-kinetic-gazebo-ros-pkgs ros-kinetic-
ros-control
使用 ROS 接口测试 Gazebo
假设 ROS 环境已正确设置,我们可以在启动 Gazebo 之前使用以下命令启动roscore
:
$ roscore
以下命令将使用 ROS 运行 Gazebo:
代码语言:javascript复制 $ rosrun gazebo_ros gazebo
Gazebo 运行两个可执行文件-Gazebo 服务器和 Gazebo 客户端。 Gazebo 服务器将执行模拟过程,而 Gazebo 客户端可以是 Gazebo GUI。 使用前面的命令,Gazebo 客户端和服务器将并行运行。
Gazebo GUI 显示在以下屏幕截图中:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u6iYnsBu-1681873679408)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00010.jpeg)]
Gazebo 模拟器
启动 Gazebo 之后,将生成以下主题:
代码语言:javascript复制$ rostopic list
/gazebo/link_states
/gazebo/model_states
/gazebo/parameter_descriptions
/gazebo/parameter_updates
/gazebo/set_link_state
/gazebo/set_model_state
我们可以使用以下命令分别运行服务器和客户端:
- 使用以下命令运行 Gazebo 服务器:
$ rosrun gazebo_ros gzserver
- 使用以下命令运行 Gazebo 客户端:
$ rosrun gazebo_ros gzclient
总结
本章是对机器人操作系统的介绍。 本章的主要目的是概述 ROS,ROS 的功能,如何安装,ROS 的基本概念以及如何使用 Python 对其进行编程。 同时,我们研究了一种名为 Gazebo 的机器人模拟器,该模拟器可以与 ROS 一起使用。 我们已经看到了如何安装和运行 Gazebo。 在下一章中,我们将介绍差动机器人的基本概念。
问题
- ROS 的重要特征是什么?
- ROS 中概念的不同层次是什么?
- 什么是 ROS catkin 构建系统?
- 什么是 ROS 主题和消息?
- ROS 计算图有哪些不同的概念?
- ROS 主机的主要功能是什么?
- Gazebo 的重要特征是什么?
二、了解差动机器人的基础
在上一章中,我们讨论了 ROS 的基础知识,如何安装它以及 Gazebo 机器人模拟器的基础知识。 正如我们已经提到的,我们将从头开始创建一个自动轮式机器人。 我们将要设计的机器人是差动机器人,该机器人涉及在机器人底盘的相对两侧具有两个轮子,从而可以通过更改两个轮子中每个轮子的速度来调整机器人的方向。
在对机器人进行编程之前,最好先了解差动轮机器人背后的基本思想和术语。 本章将为您提供有关如何数学分析机器人以及如何求解机器人运动学方程的想法。 运动方程可帮助您根据传感器数据预测机器人的位置。
在本章中,我们将介绍以下主题:
- 差动机器人的数学建模
- 差动机器人的正向运动学
- 差动机器人的逆向运动学
机器人的数学建模
移动机器人的重要组成部分是其转向系统。 这将帮助机器人导航其环境。 差速驱动系统是最简单,最具成本效益的转向系统之一。 差动机器人由两个安装在同一轴上的主轴组成,并由单独的电动机控制。 差动驱动系统/转向系统是非完整系统,这意味着它对改变机器人的姿势有限制。
汽车是非完整系统的一个例子,因为它不能不改变姿势就不能改变位置。 让我们看看这种类型的机器人是如何工作的,以及如何根据其数学模型对它进行建模。
差动驱动系统和机器人运动学简介
机器人运动学是对运动数学的研究,没有考虑影响运动的力。 它主要处理控制系统的几何关系。 机器人动力学是对机器人运动的研究,其中模拟了机器人运动中涉及的所有力。
移动机器人或车辆具有六个自由度(DOF),这些自由度由姿势(x, y, z
,侧倾,俯仰和偏航)表示。 这些自由度包括位置(x, y, z
)和姿态(侧倾,俯仰和偏航)。 横滚表示横向旋转,俯仰表示向前和向后旋转,偏航(称为航向或方向)表示机器人在 xy 平面上的移动方向。 差动机器人在水平面上从x
移到y
,因此 2D 姿态主要包含x
,y
和θ
,其中θ
是指向机器人向前方向的机器人航向。 此信息足以描述差分机器人姿态:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6BI429nU-1681873679408)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00011.jpeg)]
全局坐标系中机器人在x
,y
和θ
中的姿态
在差动机器人中,可以通过调节左侧和右侧的两个独立控制的电动机(分别称为V_left
和V_right
)的速度来控制运动。 下图显示了市场上几个流行的差动机器人:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WUX9iCVj-1681873679408)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00012.jpeg)]
机器人 Roomba
Roomba 系列自动吸尘器是 iRobot 最受欢迎的差动机器人。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AjR7HQSN-1681873679409)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00013.jpeg)]
先锋 3-DX
Pioneer 3-DX 是欧姆龙自适应移动机器人公司流行的差速驱动研究平台。
差动机器人的正向运动学
具有差动驱动系统的机器人的正向运动学方程用于解决以下问题:
如果机器人在时间t
站立在x
,y
,θ
的位置,请确定t δt
处的姿势x'
,y'
,θ'
(给定控制参数V_left
和V_right
)。
该技术可以由机器人计算以遵循特定的轨迹。
正向运动学方程的解释
我们可以从制定正向运动学解决方案开始。 下图是机器人的一个轮子的图示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gfpxk5SQ-1681873679409)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00014.gif)]
机器人的单个轮子沿局部 y 轴旋转
围绕 y 轴的运动称为滚动; 其他的一切都称为单据。 假设在这种情况下不会发生打滑。 车轮完成一整圈时,它的距离为2πr
,其中r
是车轮的半径。 我们将假设运动是二维的。 这意味着表面平坦且平坦。
当机器人要执行转弯运动时,机器人必须绕着沿其共同的左右车轮轴的点旋转。 机器人旋转的点称为 ICC - 瞬时曲率中心。 ICC 位于机器人外部。 下图显示了差动机器人相对于其 ICC 的车轮配置:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gJhz7JoE-1681873679409)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00015.jpeg)]
差动机器人的车轮配置
运动方程的推导的中心概念是机器人的ω
角速度。 机器人上的每个车轮都沿一个圆的圆周围绕 ICC 旋转,车轮半径为r
。
车轮速度为v = 2πr / T
,其中T
是完成 ICC 整圈的时间。ω
角速度定义为2π / T
,通常具有每秒的弧度(或度)单位。 结合v
和ω
的等式,得出ω= 2π / T
,我们可以得出以下结论:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TwmZti28-1681873679409)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00016.jpeg)]
线速度方程
下图显示了差动驱动系统的详细模型:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qLxkgppe-1681873679410)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00017.jpeg)]
差动驱动系统的详细图
如果将前面的方程式应用到两个车轮,结果将是相同的,即ω
:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vodXujCJ-1681873679410)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00018.jpeg)]
差动驱动轮方程
在此, R
是 ICC 与轮轴中点之间的距离, l
是轮轴长度。 在求解ω
和R
之后,我们得到以下结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zjc88jlG-1681873679410)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00019.jpeg)]
用于找到从 ICC 到机器人中心的距离以及机器人角速度的方程式
前面的等式对于解决正向运动学问题很有用。 假设机器人以ω
的角速度移动δt
秒。 这将导致机器人的方向或航向更改为以下内容:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jx6mNpqR-1681873679410)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00020.jpeg)]
寻找方向变化的方程式
在这里,ICC 旋转的中心由基本三角函数给出,如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lp2AjYqR-1681873679411)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00021.jpeg)]
找到 ICC 的方程式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1UzOogqy-1681873679411)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00022.jpeg)]
围绕 ICC 旋转机器人ωδt
度
给定起始位置x, y
,可以使用 2D 计算新位置x', y'
。 旋转矩阵。 以δt
秒的角速度ω
围绕 ICC 旋转在t δt
时产生以下位置:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pBz1uLyg-1681873679411)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00023.jpeg)]
用于计算机器人新位置的方程式
给定ω
,δt
和R
,可以根据公式(6)和(8)计算新姿势x'
,y'
和θ'
。
ω
可以根据式(5)算出。 Vr
和V1
通常更难准确测量。 代替测量速度,可以使用称为车轮编码器的传感器来测量每个车轮的旋转。 来自车轮编码器的数据是机器人的里程表值。 这些传感器安装在车轮轴上,并针对车轮旋转的每个角度(每个角度约为 0.1 毫米)传递二进制信号。 在第 6 章,“执行器和传感器与机器人控制器的接口连接”中,我们将详细介绍车轮编码器的工作原理。 这些信号被馈送到计数器,使得vδt
为从时间t
到t δt
的距离。 我们可以编写以下内容:
n * step = vδt
由此,我们可以计算出v
:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XnrVLCbB-1681873679411)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00024.jpeg)]
根据编码器数据计算线速度的方程式
如果将方程式(9)插入方程式(3)和(4),我们将得到以下结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ujq5jXHo-1681873679411)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00025.jpeg)]
根据编码器值计算R
的公式
在此,nl
和nr
是左轮和右轮的编码器计数。Vl
和Vr
分别是左轮和右轮的速度。 因此,机器人站立姿势(x
,y
,θ
)并移动nl
和nr
在δt
的时间范围内计数; 新姿势(x'
,y'
,θ'
)通过以下公式得出:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0R1ph6RW-1681873679412)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00026.jpeg)]
根据编码器值计算机器人位置的方程式
在哪里,
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TLPkyUGF-1681873679412)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00027.jpeg)]
根据编码器值计算 ICC 和其他参数的公式
得出的运动方程主要取决于机器人的设计和几何形状。 不同的设计可能导致不同的方程式。
逆向运动学
前向运动学方程在给定的车轮速度下提供了更新的姿态。 现在我们可以考虑反问题了。
在时间t
站立姿势(x
,y
,θ
)并确定V_left
和V_right
控制参数,以使t δt
时的姿态为(x'
,y'
和θ'
)。
在差动驱动系统中,这个问题可能并不总是可以解决的,因为仅通过设置车轮速度就无法将这种机器人移动到任何姿势。 这是由于非完整机器人的限制。
在非完整机器人中,如果我们允许一系列不同的运动(V_left
,V_right
)运动,则有一些方法可以增加约束运动性。 如果插入方程(12)和(15)中的值,我们可以确定一些可以编程的特殊运动:
- 如果
V_right = V_left => nr = nl => R = ∞ => ωδT= 0
,则表示机器人沿直线运动,θ
保持不变 - 如果
V_right = -V_left => nr = -nl => R = 0 => ωδt = 2nl * step / l
和ICC = [ICC[x], ICC[y]] = [x, y] => x'= x, y'= y, θ' = θ ωδt
,这意味着机器人会绕着 ICC 旋转,即θ
均可到达,而x, y
保持不变
结合这些操作,可以使用以下步骤从起始姿势达到任何目标姿势:
- 旋转直到机器人的方向与从起始位置到目标位置的直线重合
V_right = -V_left = V_rot
。 - 直行直到机器人的位置与目标位置一致
V_right = V_left = V_ahead
。 - 旋转直到机器人的方向与目标方向一致
V_right = -V_left = V_rot
。 在此,可以任意选择V_rot
和V_ahead
。
在接下来的章节中,我们将看到如何使用 ROS 来实现机器人的运动学方程。
总结
本章介绍了差动机器人的基本概念,并探讨了如何推导此类机器人的运动学方程。 在本章的开头,我们了解了差动机器人的基础知识,然后讨论了在这些机器人中使用的正向运动学方程。 这些方程式用图表解释。 在查看了正向运动学方程后,我们研究了差动机器人的逆向运动学方程。 我们还研究了逆运动学方程的基础。
在下一章中,我们将看到如何使用 ROS 和 Gazebo 创建自动移动机器人的仿真。
问题
- 什么是完整和非完整配置?
- 什么是机器人运动学和动力学?
- 差动机器人的 ICC 是多少?
- 差分机器人中的正向运动方程是什么?
- 差分机器人中的逆向运动方程是什么?
更多信息
有关运动学方程式的更多信息,请参见这个页面。
三、建模差动机器人
在本章中,我们将研究如何为差动机器人建模以及如何在 ROS 中创建该机器人的 URDF 模型。 我们将在本章中设计的机器人的主要用例是在旅馆和饭店中提供食物和饮料。 该机器人名为 Chefbot。 本章将介绍该机器人的完整建模。
我们将研究此机器人中使用的各种机械组件的 CAD 设计以及如何组装它们。 我们将研究该机器人的 2D 和 3D CAD 设计,并讨论如何创建该机器人的 URDF 模型。
在酒店中部署的实际机器人模型可能很大,但是在这里,我们打算构建一个微型版本来测试我们的软件。 如果您有兴趣从头开始构建机器人,那么本章适合您。 如果您对构建机器人不感兴趣,可以选择一些机器人平台(如 Turtlebot)在市场上购买,以与本书一起使用。
要构建机器人硬件,首先我们需要获得机器人的要求。 获得要求后,我们可以对其进行设计并在 2D CAD 工具中绘制模型以制造机器人零件。 机器人的 3D 建模将使我们对机器人的外观有更多的了解。 3D 建模后,我们可以将设计转换为可与 ROS 一起使用的 URDF 模型。
本章将涵盖以下主题:
- 根据给定规格设计机器人参数
- 使用 LibreCAD 设计 2D 机器人主体零件
- 使用 Blender 和 Python 设计 3D 机器人模型
- 为 Chefbot 创建 URDF 模型
- 在 Rviz 中可视化 Chefbot 模型
技术要求
要测试本章中的应用和代码,您需要安装了 ROS Kinetic 的 Ubuntu 16.04 LTS PC /笔记本电脑
机器人要满足的要求
在设计任何机器人系统之前,第一个步骤是确定系统需求。 以下是此机器人要满足的一组机器人设计要求。 这包括硬件和软件要求:
- 机器人应配备食物
- 机器人应携带的最大有效载荷为 2 千克
- 机械手应以 0.25m/s 至 0.35m/s 的速度移动
- 机器人的离地间隙应大于 3 厘米
- 机器人必须连续工作 2 个小时
- 机器人应能够移动并向任何桌子供应食物,避免障碍物
- 机械手的高度可以在 80 厘米至 100 厘米之间。
- 该机器人的成本应低(不到 500 美元)
现在我们有了设计要求,例如有效载荷,速度,离地高度,机器人的高度,机器人的成本以及要在机器人中实现的功能,我们可以设计机器人主体并选择与上述要求匹配的组件。 让我们讨论可用于满足这些要求的机器人机制。
机器人驱动机构
差动驱动系统是移动机器人导航的一种经济高效的解决方案。 它是移动机器人最简单的驱动机制之一,主要用于室内导航。 差动机器人包括两个轮子,两个轮子安装在由两个单独的电动机控制的公共轴上。 有两个支撑轮,称为脚轮。 这样可以确保机器人的稳定性和重量分配。 下图显示了典型的差动驱动系统:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J6bscMJK-1681873679412)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00029.gif)]
差动驱动系统
下一步是选择此机器人驱动系统的机械组件,主要是电动机,车轮和机器人底盘。 根据要求,我们将首先讨论如何选择电动机。
电机和车轮的选择
在查看规格后选择电动机。 电机选择的一些重要参数是转矩和 RPM。 我们可以根据给定的要求计算这些值。
电机转速的计算
该机器人所需的速度范围是 0.25 至 0.35m/s。 在设计中,我们可以将此机器人的最大速度设为 0.35m/s。 将轮子的直径设为 9cm,因为根据要求,离地间隙应大于 3cm,我们将机器人本体固定在与电机轴相同的高度上。 在这种情况下,我们将获得更大的离地间隙。
使用以下方程式,我们可以计算电动机的 RPM:
代码语言:javascript复制RPM = (60 * 速度) / (3.14 * 车轮直径)
= (60 * 0.35) / (3.14 * 0.09) = 21 / 0.2826 = 74 RPM
您也可以查看这个页面进行计算。
车轮直径为 9cm 且速度为 0.35m/s 时,计算得出的 RPM 为 74 RPM。 我们可以将 80 RPM 作为标准值。
电机转矩的计算
让我们计算一下移动机器人所需的扭矩:
- 车轮数为四个车轮,其中包括两个脚轮。
- 电机数量为 2。
- 假设摩擦系数为 0.6,车轮半径为 4.5cm。
- 取
机器人的总重量 = 机器人的重量 有效载荷 = (W = mg) = (~100 N ~20 N) W = ~150 N
,而总质量为 12 Kg。 - 作用在四个车轮上的重量可以写成
2 * N1 2 * N2 = W
; 也就是说,N1
是作用在每个脚轮上的重量,N2
是作用在电动车轮上的重量。 - 假设机器人是静止的。 机器人开始移动时需要最大扭矩。 它还应克服摩擦。
- 我们可以将摩擦力写为机器人扭矩为 0,直到机器人运动为止。 如果在此条件下获得机器人扭矩,则将获得最大扭矩,如下所示:
设计总结
设计之后,我们计算以下值并四舍五入到市场上可用的标准电动机规格:
- 电机 RPM 为 80(四舍五入到标准值)
- 电机扭矩为 18 kg-cm
- 轮径为 9 厘米
机器人底盘设计
在计算了机器人的电动机和车轮参数之后,我们可以设计机器人底盘或机器人主体。 根据要求,机器人底盘应具有容纳食物的设施,应能够承受 5 公斤的负载,机器人的离地间隙应大于 3 厘米,并且成本应低。 除此之外,机器人还应提供放置电子元件的设备,例如个人计算机(PC),传感器和电池。
满足这些要求的最简单的设计之一就是多层架构,例如 Turtlebot 2。 它在机箱中有三层。 名为 Kobuki 的机器人平台是该平台的主要驱动机制。 Roomba 平台内置了电动机和传感器,因此无需担心设计机器人驱动系统。 下图显示了 TurtleBot 2 机械手机箱设计:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qaz7ZtsO-1681873679412)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00030.jpeg)]
TurtleBot 2 机器人
我们将设计一个与 TurtleBot 2 类似的机器人,并带有我们自己的移动平台和组件。 我们的设计还具有三层架构。 在开始设计之前,让我们确定我们需要的所有工具。
在开始设计机器人机箱之前,我们需要计算机辅助设计(CAD)工具。 可用于 CAD 的流行工具有:
- SolidWorks
- AutoCAD
- Maya
- Inventor
- SketchUp
- Blender
- LibreCAD
可以使用任何您喜欢的软件来设计机箱设计。 在这里,我们将演示 LibreCAD 中的 2D 模型和 Blender 中的 3D 模型。 这些应用的亮点之一是它们是免费的,并且可用于所有 OS 平台。 我们将使用称为 MeshLab 的 3D 网格查看工具来查看和检查 3D 模型设计,并使用 Ubuntu 作为主要操作系统。 另外,我们可以在 Ubuntu 16.04 中看到这些应用的安装过程,以开始设计过程。 我们还将提供教程链接,以在其他平台上安装应用。
安装 LibreCAD,Blender 和 MeshLab
LibreCAD 是一个免费的开源 2D CAD 应用,适用于 Windows,OS X 和 Linux。 Blender 是一款免费的开源 3D 计算机图形软件,用于创建 3D 模型,动画和视频游戏。 它带有 GPL 许可证,允许用户共享,修改和分发应用。 MeshLab 是一个开放源代码,便携式且可扩展的系统,用于处理和编辑非结构化 3D 三角网格。
以下是在 Windows,Linux 和 OS X 上安装 LibreCAD 的链接:
- 访问这个页面下载 LibreCAD
- 访问这个页面从源代码构建 LibreCAD
- 访问这个页面在 Debian/Ubuntu 中安装 LibreCAD
- 访问这个页面在 Fedora 中安装 LibreCAD
- 访问这个页面在 OS X 中安装 LibreCAD
- 访问这个页面在 Windows 中安装 LibreCAD
您可以在以下链接中找到 LibreCAD 上的文档。
安装 LibreCAD
提供了所有操作系统的安装过程。 如果您是 Ubuntu 用户,则也可以直接从 Ubuntu 软件中心进行安装。
如果使用的是 Ubuntu,以下是安装 LibreCAD 的命令:
代码语言:javascript复制 $ sudo add-apt-repository ppa:librecad-dev/librecad-stable
$ sudo apt-get update
$ sudo apt-get install librecad
安装 Blender
访问以下下载页面以为您的 OS 平台安装 Blender。您可以在此处找到 Blender 的最新版本。 另外,您可以在这个页面上找到有关 Blender 的最新文档。
如果您使用的是 Ubuntu/Linux,则只需通过 Ubuntu 软件中心安装 Blender 或使用以下命令:
代码语言:javascript复制 $ sudo apt-get install blender
安装 MeshLab
MeshLab 适用于所有 OS 平台。 以下链接将为您提供预编译二进制文件的下载链接和 MeshLab 的源代码。
如果您是 Ubuntu 用户,则可以使用以下命令从 APT 包管理器中安装 MeshLab:
代码语言:javascript复制 $sudo apt-get install meshlab
使用 LibreCAD 创建机器人的 2D CAD 图
我们将看一下 LibreCAD 的基本界面。 以下屏幕截图显示了 LibreCAD 的界面:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-23w31L1h-1681873679412)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00031.jpeg)]
LibreCAD 工具
CAD 工具栏具有绘制模型所需的组件。 下图显示了 CAD 工具栏的详细概述:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vgKqL81l-1681873679413)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00032.jpeg)]
以下链接提供了 LibreCAD 工具的详细说明。
以下是每种工具的简短说明:
- 命令框:仅用于使用命令绘制图形。 我们可以绘制图表而无需触摸任何工具栏。 有关命令框用法的详细说明,请参见:
- 图层列表:这将具有当前图形中使用的图层。 计算机辅助绘图中的一个基本概念是使用图层来组织图形。 有关图层的详细说明,请参见这个页面。
- 块:这是一组实体,可以在不同的位置,不同的比例和旋转角度以不同的属性多次插入同一图形中。 可以在以下链接中找到有关块的详细说明。
- 绝对零:这是图形
(0, 0)
的原点。
现在,通过设置图形单位开始草绘。 将绘图单位设置为厘米。 打开 LibreCAD,然后导航到编辑| 应用首选项。 将“单位”设置为“厘米”,如以下屏幕截图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rBDxYlfe-1681873679413)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00033.jpeg)]
让我们从机器人的底板设计开始。 底板具有连接电动机,放置电池和控制板的装置。
底板设计
下图显示了机器人的底板。 该板为差速驱动器提供了两个电动机,底板的前后都有每个脚轮。 在图中将电动机称为M1
和M2
,脚轮表示为C1
和C2
。 它还具有四个极,以连接到下一个板。 极点表示为P1-1
,P1-2
,P1-3
和P1-4
。 螺丝标记为S
,在此我们将使用相同的螺丝。 中心处有一个孔,可将电线从电动机引到板的顶部。 在左侧和右侧切割该板,以便将车轮安装到电动机上。 从中心到脚轮的距离称为 12.5cm,从中心到电机的距离称为 5.5cm。 极点的中心距中心的长度为 9cm,高度为 9cm。 所有板的孔都遵循相同的尺寸:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xtSusz43-1681873679413)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00034.jpeg)]
底板设计
尺寸未在图中标出; 相反,它们在下表中列出:
零件 | 尺寸(长 x 高/半径,厘米) |
---|---|
M1和M2 | 5 x 4 |
C1和C2 | 半径为 1.5 |
S(螺丝)(在图中未显示) | 0.15 |
P1-1,P1-2,P1-3,P1-4 | 外径 0.7,高度 3.5cm |
左右轮部分 | 2.5 x 10 |
底盘 | 半径为 15 |
稍后我们将更详细地讨论电机尺寸和夹具尺寸。
底板杆设计
基板有四个极点以延伸到下一层。 磁极的长度为 3.5cm,半径为 0.7cm。 通过将空心管连接到杆上,我们可以延伸到下一个板。 在中空管的顶部,我们将插入硬质塑料以形成螺孔。 该孔对于延伸到顶层很有用。 下图显示了底板极和每个极上的空心管。 中空管的半径为 0.75cm,长度为 15cm:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dXSKKIjZ-1681873679413)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00035.jpeg)]
空心管设计 15 厘米
车轮,电机和电机夹具设计
我们必须确定轮子的直径并计算电动机的要求。 在这里,我们给出了设计成功时可以使用的典型电动机和车轮:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pInCuih8-1681873679413)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00036.jpeg)]
机器人的电机设计
电动机的设计可以根据电动机的选择而变化。 如有必要,可以将该电动机作为设计,并可以在仿真后进行更改。 电动机图中的L
值可以根据电动机的速度和转矩而变化。 这是电动机的齿轮组件。
下图显示了我们可以使用的 90cm 直径的典型砂轮。 放置手柄后,直径 86.5mm 的砂轮将变为 90mm:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DJzmsQSa-1681873679414)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00037.gif)]
机器人的车轮设计
电机需要安装在基板上。 要安装,我们需要一个可以拧到板上的夹具,还将电动机连接到夹具。 下图显示了可用于此目的的典型夹具。 这是一个 L 型夹钳,我们可以使用它在一侧安装电动机,然后将另一侧安装到板上:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VAkgKg2b-1681873679414)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00038.gif)]
机器人的典型夹具设计
脚轮设计
脚轮不需要特殊设计。 我们可以使用任何可以与地面接触的脚轮。 以下链接收集了可用于该设计的脚轮的集合。
中板设计
该板的尺寸与基板相同,螺钉尺寸也相似:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q7AnvQht-1681873679414)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00039.jpeg)]
机器人中间板设计
中间板可从基板固定在中空管上方。 该布置使用另一个从中板伸出的中空管连接。 中间板的管子的底部将有一个螺钉,以固定底板和中间板的管子,并在空心端连接顶板。 下图显示了从中间板伸出的管子的俯视图和侧视图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TWQIoOe8-1681873679414)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00040.gif)]
中空管设计 20 厘米
该管将中间板连接到底板,同时提供顶板的连接。
顶板设计
顶板与其他板相似; 它有四个 3 厘米的小杆,类似于底板。 磁极可以从中间板放置在空心管上。 四个极连接到板本身:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AiAQj4r3-1681873679414)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00041.gif)]
顶板设计
完成顶板设计后,机器人底盘设计几乎完成。 我们来看一下使用 Blender 的该机器人的 3D 模型构建。 3D 模型是出于仿真目的而构建的,而我们构建的 2D 设计主要是出于制造目的。
使用 Blender 处理机器人的 3D 模型
在本节中,我们将设计机器人的 3D 模型。 3D 模型主要用于仿真目的。 建模将使用 Blender 完成。 该版本必须大于 2.6,因为我们仅测试了这些版本的教程。
以下屏幕截图显示了 Blender 工作区和可用于 3D 模型的工具:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EfNf93BC-1681873679415)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00042.jpeg)]
Blender 3D CAD 工具
我们在这里使用 Blender 的主要原因是我们可以使用 Python 脚本对机器人进行建模。 Blender 具有内置的 Python 解释器和 Python 脚本编辑器,用于编码。 我们将不在这里讨论 Blender 的用户界面。 您可以在其网站上找到 Blender 的良好教程。 请参考以下链接以了解 Blender 的用户界面。
让我们开始使用 Python 在 Blender 中进行编码。
Blender 中的 Python 脚本
Blender 主要用 C,C 和 Python 编写。 用户可以编写自己的 Python 脚本并访问 Blender 的所有功能。 如果您是 Blender Python API 的专家,则可以使用 Python 脚本而不是手动建模来对整个机器人进行建模。
Blender 使用 Python3.x。 搅拌机。 Python API 通常是稳定的,但仍在某些方面进行了添加和改进。 有关 Blender Python API 的文档,请参考这个页面。
让我们快速概述一下我们将在机器人模型脚本中使用的 Blender Python API。
Blender Python API 简介
Blender 中的 Python API 可以执行 Blender 的大部分功能。 API 可以完成的主要工作如下:
- 编辑 Blender 内部的任何数据,例如场景,网格,粒子等
- 修改用户首选项,键映射和主题
- 创建新的 Blender 工具
- 使用 Python 的 OpenGL 命令绘制 3D 视图
Blender 为 Python 解释器提供了bpy
模块。 该模块可以导入脚本中,并可以访问 Blender 数据,类和函数。 处理 Blender 数据的脚本将需要导入此模块。 我们将在 bpy 中使用的主要 Python 模块是:
- 上下文访问:这可从(
bpy.context
)脚本访问 Blender 用户界面功能 - 数据访问:这提供对 Blender 内部数据(
bpy.data
)的访问 - 运算符:这提供对调用运算符的 Python 访问,其中包括用 C,Python 或宏(
bpy.ops
)编写的运算符
要在 Blender 中切换到脚本,我们需要更改 Blender 的屏幕布局。 以下屏幕截图显示了可帮助您切换到脚本布局的选项:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bYS60H6c-1681873679415)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00043.jpeg)]
Blender 脚本选项
选择脚本选项卡后,我们可以在 Blender 中看到一个文本编辑器和 Python 控制台窗口。 在文本编辑器中,我们可以使用 Blender API 进行编码,也可以通过 Python 控制台尝试使用 Python 命令。 单击“新建”按钮创建一个新的 Python 脚本并将其命名为robot.py
。 现在,我们可以仅使用 Python 脚本来设计机器人的 3D 模型。 接下来的部分提供了用于设计机器人模型的完整脚本。 我们可以在运行代码之前对其进行讨论。 希望您已经从其站点阅读了 Blender 的 Python API。 下一节中的代码分为六个 Python 函数,以绘制三个机器人板,绘制电动机和车轮,绘制四个支撑管,并导出模拟格式到立体光刻(STL)3D 文件中。
机器人模型的 Python 脚本
以下是我们将设计的机器人模型的 Python 脚本:
- 在 Blender 中启动 Python 脚本之前,我们必须导入
bpy
模块。bpy
模块包含 Blender 的所有功能,并且只能从 Blender 应用内部进行访问:
import bpy
- 以下功能将绘制机器人的底板。 此功能将绘制一个半径为 5cm 的圆柱体,并从相反的侧面切开一部分,以便可以使用 Blender 中的
Boolean
修改器连接电动机:
#This function will draw base plate
def Draw_Base_Plate():
- 以下两个命令将在基板的任一侧上创建两个半径为 0.05 米的立方体。 这些多维数据集的目的是创建一个修改器,以从基板中减去这些多维数据集。 因此,实际上,我们将获得带有两个切口的基板。 切开两侧后,我们将删除多维数据集:
bpy.ops.mesh.primitive_cube_add(radius=0.05,
location=(0.175,0,0.09))bpy.ops.mesh.primitive_cube_add(radius=0.05,
location=(-0.175,0,0.09))
####################################################
####################################################
#Adding base plate
bpy.ops.mesh.primitive_cylinder_add(radius=0.15,
depth=0.005, location=(0,0,0.09))
#Adding boolean difference modifier from first cube
bpy.ops.object.modifier_add(type='BOOLEAN')
bpy.context.object.modifiers["Boolean"].operation =
'DIFFERENCE'bpy.context.object.modifiers["Boolean"].object =
bpy.data.objects["Cube"]
bpy.ops.object.modifier_apply(modifier="Boolean")
######################################################
######################################################
#Adding boolean difference modifier from second cube
bpy.ops.object.modifier_add(type='BOOLEAN')
bpy.context.object.modifiers["Boolean"].operation =
'DIFFERENCE'bpy.context.object.modifiers["Boolean"].object =
bpy.data.objects["Cube.001"]
bpy.ops.object.modifier_apply(modifier="Boolean")
#######################################################
#######################################################
#Deselect cylinder and delete cubes
bpy.ops.object.select_pattern(pattern="Cube")
bpy.ops.object.select_pattern(pattern="Cube.001")
bpy.data.objects['Cylinder'].select = False
bpy.ops.object.delete(use_global=False)
- 以下功能将拉动安装在底板上的电动机和车轮:
#This function will draw motors and wheels
def Draw_Motors_Wheels():
- 以下命令将绘制一个半径为 0.045 且圆柱体深度为 0.01 米的圆柱体。 创建轮子之后,它将旋转并平移到基板的切割部分:
#Create first Wheel
bpy.ops.mesh.primitive_cylinder_add(radius=0.045,
depth=0.01, location=(0,0,0.07))
#Rotate
bpy.context.object.rotation_euler[1] = 1.5708
#Transalation
bpy.context.object.location[0] = 0.135
#Create second wheel
bpy.ops.mesh.primitive_cylinder_add(radius=0.045,
depth=0.01, location=(0,0,0.07))
#Rotate
bpy.context.object.rotation_euler[1] = 1.5708
#Transalation
bpy.context.object.location[0] = -0.135
- 以下代码将在基板上添加两个虚拟电机。 在 2D 设计中提到了电动机的尺寸。 电机基本上是一个圆柱体,它将被旋转并放置在底板中:
#Adding motors
bpy.ops.mesh.primitive_cylinder_add(radius=0.018,
depth=0.06, location=(0.075,0,0.075))
bpy.context.object.rotation_euler[1] = 1.5708
bpy.ops.mesh.primitive_cylinder_add(radius=0.018,
depth=0.06, location=(-0.075,0,0.075))
bpy.context.object.rotation_euler[1] = 1.5708
- 以下代码将向电动机添加轴,类似于电动机模型。 轴也是一个圆柱体,它将旋转并插入电动机模型中:
#Adding motor shaft
bpy.ops.mesh.primitive_cylinder_add(radius=0.006,
depth=0.04, location=(0.12,0,0.075))
bpy.context.object.rotation_euler[1] = 1.5708
bpy.ops.mesh.primitive_cylinder_add(radius=0.006,
depth=0.04, location=(-0.12,0,0.075))
bpy.context.object.rotation_euler[1] = 1.5708
#######################################################
#######################################################
- 以下代码将在底板上添加两个脚轮。 目前,我们正在添加一个圆柱体作为轮子。 在模拟中,我们可以将其指定为车轮:
#Adding Caster Wheel
bpy.ops.mesh.primitive_cylinder_add(radius=0.015,
depth=0.05, location=(0,0.125,0.065))bpy.ops.mesh.primitive_cylinder_add(radius=0.015,
depth=0.05, location=(0,-0.125,0.065))
- 以下代码将添加一个虚拟 Kinect 传感器:
#Adding Kinect
bpy.ops.mesh.primitive_cube_add(radius=0.04,
location=(0,0,0.26))
- 此功能将绘制机器人的中间板:
#Draw middle plate
def Draw_Middle_Plate():
bpy.ops.mesh.primitive_cylinder_add(radius=0.15,
depth=0.005, location=(0,0,0.22))
#Adding top plate
def Draw_Top_Plate():
bpy.ops.mesh.primitive_cylinder_add(radius=0.15,
depth=0.005, location=(0,0,0.37))
- 此功能将为所有三个板绘制所有四个支撑空心管:
#Adding support tubes
def Draw_Support_Tubes():
#############################################################################################
#Cylinders
bpy.ops.mesh.primitive_cylinder_add(radius=0.007,
depth=0.30, location=(0.09,0.09,0.23))bpy.ops.mesh.primitive_cylinder_add(radius=0.007,
depth=0.30, location=(-0.09,0.09,0.23))bpy.ops.mesh.primitive_cylinder_add(radius=0.007,
depth=0.30, location=(-0.09,-0.09,0.23))bpy.ops.mesh.primitive_cylinder_add(radius=0.007,
depth=0.30, location=(0.09,-0.09,0.23))
- 此功能会将设计的机械手导出到 STL。 在执行脚本之前,我们必须更改 STL 文件路径:
#Exporting into STL
def Save_to_STL():
bpy.ops.object.select_all(action='SELECT')
# bpy.ops.mesh.select_all(action='TOGGLE')
bpy.ops.export_mesh.stl(check_existing=True,
filepath="/home/lentin/Desktop/exported.stl",
filter_glob="*.stl", ascii=False,
use_mesh_modifiers=True, axis_forward='Y',
axis_up='Z', global_scale=1.0)
#Main code
if __name__ == "__main__":
Draw_Base_Plate()
Draw_Motors_Wheels()
Draw_Middle_Plate()
Draw_Top_Plate()
Draw_Support_Tubes()
Save_to_STL()
- 在文本编辑器中输入代码后,请按“运行脚本”按钮执行脚本,如以下屏幕截图所示。 输出的 3D 模型将显示在 Blender 的 3D 视图上。 另外,如果我们检查桌面,我们可以看到
exported.stl
文件用于仿真目的:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r0J2w10s-1681873679415)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00044.jpeg)]
在 Blender 中运行 Python 脚本
- 可以使用 MeshLab 打开
exported.stl
文件,以下是 MeshLab 的屏幕截图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ljGxdhDl-1681873679415)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00045.jpeg)]
MeshLab 中的 Chefbot 3D 模型
创建机器人的 URDF 模型
ROS 中的机械手模型包含用于对机械手各个方面进行建模的包,这些包在 XML 机械手描述格式中指定。 该栈的核心包是 URDF,它可以解析 URDF 文件并构造机器人的对象模型。
统一机器人描述格式(URDF)是用于描述机器人模型的 XML 规范。 我们可以使用 URDF 表示机器人的以下功能:
- 机器人的运动学和动态描述
- 机器人的视觉表示
- 机器人的碰撞模型
对机器人的描述由一组链接(零件),元素和一组关节元素组成,这些元素将这些链接连接在一起。 以下代码显示了典型的机器人描述:
代码语言:javascript复制<robot name="chefbot">
<link> ... </link>
<link> ... </link>
<link> ... </link>
<joint> .... </joint>
<joint> .... </joint>
<joint> .... </joint>
</robot>
如果您参考以下链接以获取有关 URDF 的更多信息,那就太好了。
Xacro(XML 宏)是一种 XML 宏语言。 使用 xacro,我们可以创建更短,更易读的 XML 文件。 我们可以将 xacro 与 URDF 一起使用以简化 URDF 文件。 如果将 xacro 添加到 URDF,则必须调用附加的解析器程序以将 xacro 转换为 URDF。
以下链接将为您提供有关 xacro 的更多详细信息。
robot_state_publisher
允许您将机器人的状态发布到tf
。 该节点读取名为robot_description
的 URDF 参数,并从名为joint_states
的主题读取机器人的关节角度作为输入,并使用的运动树模型发布机器人链接的 3D 姿势。 该包可用作库和 ROS 节点。 该包已经过良好的测试,并且代码稳定。
- 世界文件:这些文件代表 Gazebo 的环境,必须与机器人模型一起加载。
empty.world
和Playground.world
是 Gazebo 世界文件的一些示例。empty.world
仅包含一个空白空间。 在Playground.world
中,环境中将存在一些静态对象。 我们可以使用 Gazebo 创建自己的*.world
文件。 在下一章中,我们将进一步介绍 Gazebo 世界文件。 CMakeList.txt
和package.xml
:这些文件是在创建包时创建的。CmakeList.txt
文件有助于在包中构建 ROS C 节点或库,而package.xml
文件保存此包的所有依赖项列表。
创建一个 Chefbot 描述 ROS 包
chefbot_description
包包含我们机器人的 URDF 模型。 在自己创建此包之前,您可以浏览chapter3_codes
中下载的 Chefbot 包。 这将帮助您加快流程。
让我们检查一下如何创建chefbot_description
包。 以下过程将指导您创建此包:
- 首先,我们需要切换到
src
文件夹中的chefbot
文件夹:
$ cd ~/catkin_ws/src/
- 以下命令将创建机器人描述包以及相关性,例如
urdf
和xacro
。 这将在catkin_ws/src
文件夹中创建chefbot_description
包:
$ catkin_create_pkgchefbot_descriptioncatkinxacro
- 将所有文件夹从下载的
chefbot_description
包复制到新的包文件夹。meshes
文件夹包含机器人的 3D 零件,urdf
文件夹包含具有机器人运动学和动力学模型的 URDF 文件。 机械手模型分为多个 xacro 文件,从而使调试更容易且可读性更好。
让我们看一下该包中每个文件的功能。 您可以检查chefbot_description
中的每个文件。 下图显示了此包中的文件:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g8jmwFuq-1681873679415)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00046.jpeg)]
Chefbot 描述包
包中每个文件的功能如下:
urdf/chefbot.xacro
:这是具有机器人运动学和动态参数的主要 xacro 文件。urdf/common_properties.xacro
:此 xacro 文件包含一些属性及其在机器人模型中使用的值。 例如,机械手链接的不同颜色定义和一些常数。gazebo/chefbot.gazebo.xacro
:此文件包含机器人的仿真参数。 它主要具有 Gazebo 参数和用于执行模拟的插件。 仅当我们使用此模型开始仿真时,这些参数才有效。launch/upload_model.launch
:此启动文件具有一个节点,该节点基本上可以解析机械手 xacro 文件,并将解析后的数据上载到名为robot_description
的 ROS 参数。 然后robot_description
参数在 Rviz 中用于可视化,在 Gazebo 中用于仿真。 如果我们的 xacro 模型错误,则此启动文件将引发错误。launch/view_model.launch
:此启动文件将上载机器人 URDF 模型并在 Rviz 中查看该模型。launch/view_navigation.launch
:将在 Rviz 中显示 URDF 模型和导航相关的显示类型。launch/view_robot_gazebo.launch
:这将在 Gazebo 中启动 URDF 模型并启动所有 Gazebo 插件。meshes/
:此文件夹包含机器人模型所需的网格。- 您可以使用
catkin_make
命令来构建工作区。
构建包后,我们可以使用以下命令在 Rviz 中启动 Chefbot 模型:
代码语言:javascript复制 $ roslaunch chefbot_descriptionview_robot.launch
以下屏幕快照显示了 Rviz 中的机器人模型:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tKzBh2HP-1681873679416)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00047.jpeg)]
Rviz 中的 Chefbot URDF 模型
这是在 Rviz 中可视化机器人的view_robot.launch
文件:
<launch>
<!-- This launch file will parse the URDF model and create robot_description parameter - ->
<include file="$(find chefbot_description)/launch/upload_model.launch" />
<!-Publish TF from joint states -- >
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
<!-Start slider GUI for controlling the robot joints -- >
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" args="_use_gui:=True" />
<!-Start Rviz with a specific configuration -- >
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find chefbot_description)/rviz/robot.rviz" />
</launch>
这是upload_model. launch
的定义。 xacro
命令将解析chefbot.xacro
文件并存储到robot_description
中:
<launch>
<!-- Robot description -->
<param name="robot_description" command="$(find xacro)/xacro --inorder '$(find chefbot_description)/urdf/chefbot.xacro'" />
</launch>
我们可以看一下udf/chefbot.xacro
,它是主要的 URDF 模型文件。 我们可以看到如何在 xacro 文件中定义链接和关节。
以下代码段显示了机器人 xacro 模型的标题。 它具有 XML 版本,机械手名称,并且还包含其他一些 xacro 文件,例如common_properties.xacro
和chefbot.gazebo.xacro.
。之后,我们可以看到标头中定义的一些相机属性:
<?xml version="1.0"?>
<robot name="chefbot" xmlns:xacro="http://ros.org/wiki/xacro">
<xacro:include filename="$(find chefbot_description)/urdf/common_properties.xacro" />
<xacro:include filename="$(find chefbot_description)/gazebo/chefbot.gazebo.xacro" />
<xacro:property name="astra_cam_py" value="-0.0125"/>
<xacro:property name="astra_depth_rel_rgb_py" value="0.0250" />
<xacro:property name="astra_cam_rel_rgb_py" value="-0.0125" />
<xacro:property name="astra_dae_display_scale" value="0.8" />
以下代码片段显示了模型中链接和关节的定义:
代码语言:javascript复制<link name="base_footprint"/>
<joint name="base_joint" type="fixed">
<origin xyz="0 0 0.0102" rpy="0 0 0" />
<parent link="base_footprint"/>
<child link="base_link" />
</joint>
<link name="base_link">
<visual>
<geometry>
<!-- new mesh -->
<mesh filename="package://chefbot_description/meshes/base_plate.dae" />
<material name="white"/>
</geometry>
<origin xyz="0.001 0 -0.034" rpy="0 0 ${M_PI/2}"/>
</visual>
<collision>
<geometry>
<cylinder length="0.10938" radius="0.178"/>
</geometry>
<origin xyz="0.0 0 0.05949" rpy="0 0 0"/>
</collision>
<inertial>
<!-- COM experimentally determined -->
<origin xyz="0.01 0 0"/>
<mass value="2.4"/><!-- 2.4/2.6 kg for small/big battery pack -->
<inertia ixx="0.019995" ixy="0.0" ixz="0.0"
iyy="0.019995" iyz="0.0"
izz="0.03675" />
</inertial>
</link>
在此代码中,我们可以看到两个名为base_footprint
和base_link
的链接的定义。 base_footprint
链接是虚拟链接,表示它具有任何属性; 它仅用于显示机器人的起源。 base_link
是机器人的起源,具有视觉和碰撞特性。 我们还可以看到该链接被可视化为网格文件。 我们还可以在定义中看到链接的惯性参数。 关节是两个环节的结合。 我们可以通过提及两个链接和关节的类型来在 URDF 中定义关节。 URDF 中有不同类型的关节,例如固定,旋转,连续和棱柱形。 在此代码段中,我们将创建一个固定的关节,因为这些框架之间没有运动。
本章主要涉及 Chefbot URDF 的基础知识。 在下一章中,我们将学习有关 Chefbot 仿真的更多信息,并对参数进行解释。
总结
在本章中,我们讨论了 Chefbot 机器人的建模。 建模涉及机器人硬件的 2D 和 3D 设计,最终成为可在 ROS 中使用的 URDF 模型。 本章从机器人要满足的各种要求开始,我们已经看到了如何计算各种设计参数。 计算完设计参数后,我们开始设计机器人硬件的 2D 草图。 使用免费的 CAD 工具 LibreCAD 完成了设计。 之后,我们使用 Python 脚本在 Blender 中研究了 3D 模型。 我们已经从 Blender 创建了网格模型,并创建了机器人的 URDF 模型。 创建 URDF 模型后,我们研究了如何在 Rviz 中可视化机器人。
在下一章中,我们将讨论如何模拟该机器人以及执行映射和定位。
问题
- 什么是机器人建模及其用途?
- 2D 机器人模型的目标是什么?
- 3D 机器人模型的目标是什么?
- 与手动建模相比,Python 脚本有什么优势?
- 什么是 URDF 文件,其用途是什么?
进一步阅读
要了解有关 URDF,Xacro 和 Gazebo 的更多信息,请参阅以下书籍:《精通 ROS 机器人程序设计第二版》。
四、使用 ROS 模拟差动机器人
在上一章中,我们研究了如何建模 Chefbot。 在本章中,我们将学习如何使用 ROS 中的 Gazebo 模拟器来模拟机器人。 我们将学习如何创建 Chefbot 的仿真模型,并在 Gazebo 中创建类似于酒店的环境来测试我们的应用,该应用被编程为自动向客户交付食物。 我们将查看每个步骤的详细说明,以测试我们的应用。 以下是我们将在本章中介绍的重要主题:
- Gazebo 模拟器入门
- 使用 TurtleBot 2 模拟
- 模拟 Chefbot
- 用于仿真的 URDF 标签和插件
- 同步定位和映射入门
- 在 Gazebo 环境中实现 SLAM
- 使用 SLAM 创建地图
- 自适应蒙特卡洛定位入门
- 在 Gazebo 环境中实现 AMCL
- 使用 Gazebo 在酒店内自动导航 Chefbot
技术要求
要测试本章中的应用和代码,您需要安装了 ROS Kinetic 的 Ubuntu 16.04 LTS PC /笔记本电脑。
Gazebo 模拟器入门
在第一章中,我们研究了 Gazebo 仿真器的基本概念及其安装过程。 在本章中,我们将了解有关 Gazebo 的用法以及如何在 Gazebo 模拟器中模拟差动机器人的更多信息。 第一步是了解 GUI 界面及其各种控件。 正如我们在第一章中所讨论的,Gazebo 有两个主要部分。 第一个是 Gazebo 服务器,第二个是 Gazebo 客户端。 仿真是在充当后端的 Gazebo 服务器上完成的。 GUI 是前端,它充当 Gazebo 客户端。 我们还将介绍 Rviz(ROS 可视化工具),它是 ROS 中的 GUI 工具,用于可视化来自机器人硬件或模拟器(如 Gazebo)的各种机器人传感器数据。
我们可以使用 Gazebo 作为独立的模拟器来模拟机器人,也可以使用具有 ROS 和 Python 的接口,这些接口可用于在 Gazebo 模拟器中对机器人进行编程。 如果我们将 Gazebo 用作独立模拟器,则模拟机器人的默认选项是编写基于 C 的插件。 我们可以编写 C 插件来模拟机器人的行为,创建新的传感器,创建新的世界,等等。 默认情况下,使用 SDF 文件完成对 Gazebo 中机器人和环境的建模。 如果我们为 Gazebo 使用 ROS 接口,则必须创建一个 URDF 文件,其中包含机器人的所有参数,并具有特定于 Gazebo 的标签来提及机器人的仿真属性。 当我们使用 URDF 启动仿真时,它将使用某些工具转换为 SDF 文件,并在 Gazebo 中显示机器人。 Gazebo 的 ROS 接口称为 gazebo-ros-pkgs。 它是一组包装程序和插件,它们能够在 Gazebo 中对传感器,机器人控制器和其他模拟进行建模并通过 ROS 主题进行通信。 在本章中,我们将主要关注用于模拟 Chefbot 的 ROS-Gazebo 接口。 ROS-Gazebo 接口的优点是我们可以通过使用 ROS 框架对机器人进行编程。 我们可以使用 ROS 等常用的编程语言(例如 C 和 Python)对机器人进行编程。
如果您对使用 ROS 不感兴趣,并且想使用 Python 编程机器人,则应签出一个名为 pygazebo 的接口。 它是 Gazebo 的 Python 绑定。 在下一节中,我们将看到 Gazebo 的 GUI 及其一些重要控件。
Gazebo 的图形用户界面
我们可以通过几种方式启动 Gazebo。 您已经在第 1 章,“机器人操作系统入门”中看到了这一点。 在本章中,我们使用以下命令启动一个空白世界,这意味着没有机器人,也没有环境:
代码语言:javascript复制$ roslaunch gazebo_ros empty_world.launch
前面的命令将启动 Gazebo 服务器和客户端,并将一个空白世界加载到 Gazebo 中。 这是 Gazebo 里空虚的世界的景象:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SMyXpCQR-1681873679416)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00048.jpeg)]
Gazebo 用户界面
Gazebo 用户界面可分为三个部分:场景,左面板和右面板。
场景
场景是模拟机器人的地方。 我们可以向场景中添加各种对象,并且可以使用鼠标和键盘与场景中的机器人进行交互。
左面板
当我们启动 Gazebo 时,您会看到左侧面板。 左面板中有三个主要选项卡:
- 世界:世界选项卡包含当前 Gazebo 场景中的模型列表。 在这里,我们可以修改模型参数(例如姿势),也可以更改相机的姿势。
- 插入:插入选项卡允许您向场景添加新的仿真模型。 这些模型在本地系统和远程服务器中均可用。
/home/<user_name>/.gazebo/model
文件夹会将本地模型文件和模型保存在这个页面中的远程服务器中,如以下屏幕快照所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IM0IOXRr-1681873679416)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00049.jpeg)]
Gazebo 左侧面板中的“插入”标签
您可以在前面的屏幕快照中显示的插入标签中看到本地文件和远程文件。
首次启动 Gazebo 时,或者从远程服务器启动具有模型的世界时,您可能会在 Gazebo 上看到黑屏或在终端上看到警告。 这是因为正在下载远程服务器中的模型,并且 Gazebo 必须等待一段时间。 等待时间会根据您的互联网连接速度而变化。 下载模型后,它将保存在本地模型文件夹中,因此下次不会有任何延迟。
- 图层:大多数时候,我们不会使用此选项卡。 此选项卡用于组织模拟中可用的不同可视化。 我们可以通过切换各层来隐藏/取消隐藏仿真中的模型。 在仿真中,大多数时候此选项卡将为空。
右面板
默认情况下,“右侧”面板是隐藏的。 我们必须拖动它才能查看它。 该面板使我们能够与模型的移动部分进行交互。 如果在场景中选择模型,则可以看到模型的关节。
Gazebo 工具栏
Gazebo 有两个工具栏。 一个在场景之上,另一个在场景之下。
顶部工具栏
顶部工具栏对于与 Gazebo 场景进行交互非常有用。 该工具栏主要用于操纵 Gazebo 场景。 它具有选择模型,缩放,平移和旋转以及向场景添加新形状的功能:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gIJp7aed-1681873679416)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00050.jpeg)]
Gazebo 上层工具栏
以下列表为您显示了每个选项的详细说明:
- 选择模式:如果处于“选择模式”,则可以在场景中选择模型并设置其属性,以及在场景内导航。
- 平移模式:在平移模式中,我们可以选择模型并通过单击向左按钮来平移模型。
- 旋转模式:在旋转模式下,我们可以选择模型并更改其方向。
- 缩放模式:在“缩放模式”中,我们可以选择模型并进行缩放。
- 撤消/重做:这使我们能够撤消或重做场景中的动作。
- 简单形状:使用此选项,我们可以将原始形状插入场景,例如圆柱体,立方体或球体。
- 灯光:“灯光”选项使我们能够将不同种类的光源添加到场景中。
- 复制/粘贴:“复制和粘贴”选项使我们能够复制和粘贴场景的不同模型和部分。
- 对齐:这使我们能够彼此对齐模型。
- 捕捉:捕捉一个模型并将其移入场景。
- 更改视图:这将更改场景的视图。 它主要使用透视图和正交视图。
- 屏幕截图:这是当前场景的屏幕截图。
- 记录日志:这将保存 Gazebo 的日志。
底部工具栏
底部的工具栏主要为我们提供了有关模拟的想法。 它显示“仿真时间”,它是指仿真器中经过的时间。 模拟会加快或减慢速度。 这取决于当前仿真所需的计算。
实时显示是指模拟器运行时在现实生活中经过的实际时间。 实时因子(RTF)是模拟时间与实时速度之间的比率。 如果 RTF 为 1,则表示仿真以与实际时间相同的速率进行。
Gazebo 的世界状态可以随着每次迭代而改变。 每次迭代都可以在 Gazebo 中进行固定时间的更改。 该固定时间称为步长。 默认情况下,步长为 1 毫秒。 步长和迭代显示在工具栏中,如以下屏幕截图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mfAHk7j5-1681873679416)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00051.jpeg)]
Gazebo 的下部工具栏
我们可以暂停仿真,并使用步骤按钮查看每个步骤。
您可以从这个页面获取有关 Gazebo GUI 的更多信息。
在进入下一部分之前,您可以使用 Gazebo,并详细了解其工作方式。
使用 TurtleBot 2 模拟
与 Gazebo 合作之后,现在该在其上进行仿真并与一些机器人一起工作了。 可用于教育和研究的最受欢迎的机器人之一是 TurtleBot。 TurtleBot 软件是在 ROS 框架内开发的,并且在 Gazebo 中可以很好地模拟其操作。 TurtleBot 的流行版本是 TurtleBot 2 和 3。我们将在本节中学习 TurtleBot 2,因为我们 Chefchebot 的开发受到其设计的启发。
在 Ubuntu 16.04 中安装 TurtleBot 2 仿真包非常简单。 您可以使用以下命令为 Gazebo 安装 TurtleBot 2 仿真包:
代码语言:javascript复制 $ sudo apt-get install ros-kinetic-turtlebot-gazebo
安装包后,我们可以开始运行仿真。 turtlebot_gazebo
包中有几个启动文件,它们具有不同的世界文件。 Gazebo 世界文件(*.world
)是一个 SDF 文件,由环境中模型的属性组成。 当世界文件更改时,Gazebo 将在其他环境中加载。
以下命令将启动一个具有一组特定组件的世界:
代码语言:javascript复制 $ roslaunch turtlebot_gazebo turtlebot_world.launch
加载模拟将花费一些时间,并且在加载时,您会在 Gazebo 场景中看到以下模型:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YiGPQGpd-1681873679417)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00052.jpeg)]
Gazebo 中的 TurtleBot 2 模拟
当我们在 Gazebo 中加载仿真时,它还将加载必要的插件以与 ROS 交互。 TurtleBot 2 具有以下重要组件:
- 带有差动驱动器的移动底座
- 用于创建地图的深度传感器
- 可检测碰撞的保险杠开关
当模拟加载时,它将加载 ROS-Gazebo 插件以模拟差动驱动器移动基座,深度传感器(Kinect 或 Astra)以及保险杠开关的插件。 因此,在加载模拟后,如果我们在终端中输入$ rostopic list
命令,则会出现一个主题选择,如以下屏幕截图所示。
如前所述,我们可以从差动驱动器插件,深度传感器和保险杠开关中看到主题。 除此之外,我们还可以从 ROS-Gazebo 插件中看到主题,这些主题主要包含机器人的当前状态以及仿真中的其他模型。
Kinect/Astra 传感器可以提供 RGB 图像和深度图像。 差分驱动器插件可以在/odom
(nav_msgs/Odometry
)主题中发送机器人的里程表数据,并可以在/tf
(tf2_msgs/TFMessage
)主题中发布机器人的变换,如以下屏幕快照所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eIk8V1VX-1681873679417)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00053.jpeg)]
TurtleBot 2 模拟中的 ROS 主题
我们可以在 Rviz 中可视化机器人模型和传感器数据。 有一个专门用于可视化的 TurtleBot 包。 您可以安装以下包以可视化机器人数据:
代码语言:javascript复制 $ sudo apt-get install ros-kinetic-turtlebot-rviz-launchers
安装此包后,我们可以使用以下启动文件来可视化机器人及其传感器数据:
代码语言:javascript复制 $ roslaunch turtlebot-rviz-launchers view_robot.launch
我们将获得以下 Rviz 窗口,其中显示了机器人模型。 然后,我们可以使传感器显示器可视化此特定数据,如以下屏幕截图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WqnvPLcZ-1681873679417)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00054.jpeg)]
Rviz 中的 TurtleBot 2 可视化
在下一节中,我们将学习如何移动该机器人。
移动机器人
机器人的差分驱动器插件能够接收 ROS 扭曲消息(geometry_msgs/Twist
),该消息包括机器人当前的线速度和角速度。 机器人的遥控意味着通过操纵杆或键盘使用 ROS Twist 消息手动移动机器人。 现在,我们将研究如何使用键盘遥控操作移动 Turtlebot 2 机器人。
我们必须安装一个包才能遥控 TurtleBot 2 机器人。 以下命令将安装 TurtleBot 远程操作包:
代码语言:javascript复制 $ sudo apt-get install ros-kinetic-turtlebot-teleop
要启动远程操作,我们必须先启动 Gazebo 仿真器,然后使用以下命令启动远程操作节点:
代码语言:javascript复制 $ roslaunch turtlebot_teleop keyboard_teleop.launch
在终端中,我们可以看到用于移动机器人的按键组合。 您可以使用这些键移动它,然后您将看到机器人在 Gazebo 和 Rviz 中移动,如以下屏幕截图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rhZMV01X-1681873679418)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00055.jpeg)]
TurtleBot 2 键盘遥控
当我们按下键盘上的按钮时,它将向扭转驱动器控制器发送 Twist 消息,并且该控制器将在模拟中移动机器人。 Teleop 节点发送一个名为/cmd_vel_mux/input/teleop
(geometry_msgs/Twist
)的主题,如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mal8sjcN-1681873679418)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00056.gif)]
TurtleBot 键盘遥操作节点
模拟 Chefbot
我们已经看到了乌龟机器人模拟的工作方式。 在本节中,我们将研究如何使用 Gazebo 创建我们自己的机器人仿真。
在我们开始讨论这个主题之前,您应该将chefbot_gazebo
包复制到您的 catkin 工作区,然后输入catkin_make
来构建该包。 确保工作区中有两个包,一个称为chefbot_description
,另一个称为chefbot_gazebo
。 chefbot_gazebo
包包含与仿真相关的启动文件和参数,chefbot_description
包含机器人的 URDF 模型及其仿真参数,以及用于在 Rviz 和 Gazebo 中查看机器人的启动文件。
让我们开始在 Gazebo 中创建 Chefbot 模型,以便您熟悉该过程。 之后,我们将深入研究 xacro 文件并查看模拟参数。
以下启动文件将显示一个空白世界的 Gazebo 机器人模型,并启动该机器人的所有 Gazebo 插件:
代码语言:javascript复制 $ roslaunch chefbot_description view_robot_gazebo.launch
下图显示了 Gazebo 内 Chefbot 的屏幕截图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0OH8A7xW-1681873679419)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00057.jpeg)]
Gazebo 的厨师机器人
让我们看看如何在 Gazebo 中添加 URDF 机器人模型。 您可以在chefbot_description/launch/view_robot_gazebo.launch
找到 URDF 机械手模型的定义。
代码的第一部分调用upload_model.launch
文件以创建robot_description
参数。 如果成功,那么它将在 Gazebo 开始一个空的世界:
<launch>
<include file="$(find chefbot_description)/launch/upload_model.launch" />
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="paused" value="false"/>
<arg name="use_sim_time" value="true"/>
<arg name="gui" value="true"/>
<arg name="recording" value="false"/>
<arg name="debug" value="false"/>
</include>
那么robot_description
参数中的机器人模型如何在 Gazebo 中显示? 启动文件中的以下代码片段完成了该工作:
<node name="spawn_urdf" pkg="gazebo_ros" type="spawn_model" args="-param robot_description -urdf -z 0.1 -model chefbot" />
gazebo_ros
包中名为spawn_model
的节点将读取robot_description
并在 Gazebo 中生成模型。 -z 0.1
参数指示要放置在 Gazebo 中的模型的高度。 如果高度为 0.1,则将以 0.1 的高度生成模型。 如果启用了重力,则模型将跌落至地面。 我们可以根据需要更改此参数。 -model
参数是 Gazebo 中机器人模型的名称。 该节点将解析robot_description
中的所有 Gazebo 参数,并在 Gazebo 中开始仿真。
生成模型后,我们可以使用以下代码行发布机器人变换(TF):
代码语言:javascript复制 <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher">
<param name="publish_frequency" type="double" value="30.0" />
</node>
我们正在发布 30Hz 的 ROS TF。
深度图像到激光扫描的转换
机器人上的深度传感器可提供环境的 3D 坐标。 为了实现自主导航,我们可以使用这些数据来创建 3D 地图。 有多种创建环境图的技术。 我们用于此机器人的一种算法称为 gmapping。 映射算法主要使用激光扫描来创建地图,但在本例中,我们从传感器获得了整个 3D 点云。 我们可以通过切片深度数据来转换激光扫描的 3D 深度数据。 此启动文件中的以下 nodelet 能够接收深度数据并将其转换为激光扫描数据:
代码语言:javascript复制 <node pkg="nodelet" type="nodelet" name="laserscan_nodelet_manager" args="manager"/>
<node pkg="nodelet" type="nodelet" name="depthimage_to_laserscan"
args="load depthimage_to_laserscan/DepthImageToLaserScanNodelet laserscan_nodelet_manager">
<param name="scan_height" value="10"/>
<param name="output_frame_id" value="/camera_depth_frame"/>
<param name="range_min" value="0.45"/>
<remap from="image" to="/camera/depth/image_raw"/>
<remap from="scan" to="/scan"/>
</node>
</launch>
Nodelet 是一种特殊的 ROS 节点,具有称为零拷贝传输的属性,这意味着它不需要网络带宽即可订阅主题。 这将使从深度图像(sensor_msgs/Image
)到激光扫描(sensor_msgs/LaserScan
)的转换更快,更有效。 Nodelet 的其他属性之一是它可以作为插件动态加载。 我们可以设置此 Nodelet 的各种属性,例如range_min
,图像主题的名称和输出激光主题。
Gazebo 模拟的 URDF 标签和插件
我们已经在 Gazebo 看到了模拟机器人。 现在,我们将更详细地介绍 URDF 中与仿真相关的标签以及 URDF 模型中包含的各种插件。
Gazebo 的大多数特定标签位于chefbot_description/gazebo/chefbot.gazebo.xacro
文件中。 此外,chefbot_description/urdf/chefbot.xacro
中的某些标签也用于仿真中。 在Chefbot.xacro
中定义<collision>
和<inertial>
标签对于我们的仿真非常重要。 URDF 中的<collision>
标签定义了机器人链接周围的边界,该边界主要用于检测该特定链接的碰撞,而<inertial>
标签则包含了链接的质量和惯性矩。 这是<inertial>
标签定义的示例:
<inertial>
<mass value="0.564" />
<origin xyz="0 0 0" />
<inertia ixx="0.003881243" ixy="0.0" ixz="0.0"
iyy="0.000498940" iyz="0.0"
izz="0.003879257" />
</inertial>
这些参数是机器人动力学的一部分,因此在仿真中,这些值将对机器人模型产生影响。 同样,在仿真中,它将处理所有链接和接头及其属性。
接下来,我们将查看gazebo/chefbot.gazebo.xacro
文件中的标签。 我们正在使用的重要的特定于 Gazebo 的标签是<gazebo>
,用于定义机器人中元素的仿真属性。 我们可以定义一个适用于所有链接的属性,也可以定义一个特定于链接的属性。 这是 xacro 文件中的代码片段,用于定义链接的摩擦系数:
<gazebo reference="chefbot_wheel_left_link">
<mu1>1.0</mu1>
<mu2>1.0</mu2>
<kp>1000000.0</kp>
<kd>100.0</kd>
<minDepth>0.001</minDepth>
<maxVel>1.0</maxVel>
</gazebo>
reference
属性用于指定机械手中的链接。 因此,前述属性仅适用于chefbot_wheel_left_link
。
以下代码段显示了如何设置机械手链接的颜色。 我们可以创建自定义颜色,定义自定义颜色或使用 Gazebo 中的默认颜色。 您可以看到,对于base_link
,我们使用的是 Gazebo 默认属性中的Gazebo/White
颜色:
<material name="blue">
<color rgba="0 0 0.8 1"/>
</material>
<gazebo reference="base_link">
<material>Gazebo/White</material>
</gazebo>
请参阅这个页面以查看模拟中使用的所有标签。
涵盖了模拟的主要标签。 现在,我们将看一下在此模拟中使用的 Gazebo-ROS 插件。
悬崖传感器插件
悬崖传感器是一组检测悬崖的红外传感器,有助于避免踩踏并防止机器人跌落。 这是 Turtlebot 2 移动基地中的一种传感器,称为 Kobuki。 我们在 Turtlebot 2 仿真中使用了这个插件。
我们可以设置传感器的参数,例如红外光束的最小和最大角度,分辨率以及每秒的采样数。 我们还可以限制传感器的检测范围。 我们的仿真模型中有三个悬崖传感器,如以下代码所示:
代码语言:javascript复制 <gazebo reference="cliff_sensor_front_link">
<sensor type="ray" name="cliff_sensor_front">
<always_on>true</always_on>
<update_rate>50</update_rate>
<visualize>true</visualize>
<ray>
<scan>
<horizontal>
<samples>50</samples>
<resolution>1.0</resolution>
<min_angle>-0.0436</min_angle> <!-- -2.5 degree -->
<max_angle>0.0436</max_angle> <!-- 2.5 degree -->
</horizontal>
</scan>
<range>
<min>0.01</min>
<max>0.15</max>
<resolution>1.0</resolution>
</range>
</ray>
</sensor>
</gazebo>
接触式传感器插件
这是我们机器人上的接触式传感器的代码段。 如果机器人的底部与任何对象碰撞,则此插件将触发。 它通常附着在机器人的base_link
上,因此,只要保险杠碰到任何物体,就会触发该传感器:
<gazebo reference="base_link">
<mu1>0.3</mu1>
<mu2>0.3</mu2>
<sensor type="contact" name="bumpers">
<always_on>1</always_on>
<update_rate>50.0</update_rate>
<visualize>true</visualize>
<contact>
<collision>base_footprint_collision_base_link</collision>
</contact>
</sensor>
</gazebo>
陀螺仪插件
陀螺仪插件用于测量机器人的角速度。 使用角速度,我们可以计算机器人的方向。 机器人的方向在机器人驱动控制器中用于计算机器人的姿势,如以下代码所示:
代码语言:javascript复制 <gazebo reference="gyro_link">
<sensor type="imu" name="imu">
<always_on>true</always_on>
<update_rate>50</update_rate>
<visualize>false</visualize>
<imu>
<noise>
<type>gaussian</type>
<rate>
<mean>0.0</mean>
<stddev>${0.0014*0.0014}</stddev> <!-- 0.25 x 0.25 (deg/s) -->
<bias_mean>0.0</bias_mean>
<bias_stddev>0.0</bias_stddev>
</rate>
<accel> <!-- not used in the plugin and real robot, hence using tutorial values -->
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
<bias_mean>0.1</bias_mean>
<bias_stddev>0.001</bias_stddev>
</accel>
</noise>
</imu>
</sensor>
</gazebo>
差分驱动器插件
差分驱动器插件是仿真中最重要的插件。 该插件可模拟机器人中的差分驱动器行为。 当它以 ROS Twist 消息(geometry_msgs/Twist
)的形式接收命令速度(线速度和角速度)时,它将移动机器人模型。 该插件还计算机器人的里程表,从而给出机器人的本地位置,如以下代码所示:
<gazebo>
<plugin name="kobuki_controller" filename="libgazebo_ros_kobuki.so">
<publish_tf>1</publish_tf>
<left_wheel_joint_name>wheel_left_joint</left_wheel_joint_name>
<right_wheel_joint_name>wheel_right_joint</right_wheel_joint_name>
<wheel_separation>.30</wheel_separation>
<wheel_diameter>0.09</wheel_diameter>
<torque>18.0</torque>
<velocity_command_timeout>0.6</velocity_command_timeout>
<cliff_detection_threshold>0.04</cliff_detection_threshold>
<cliff_sensor_left_name>cliff_sensor_left</cliff_sensor_left_name>
<cliff_sensor_center_name>cliff_sensor_front</cliff_sensor_center_name>
<cliff_sensor_right_name>cliff_sensor_right</cliff_sensor_right_name>
<cliff_detection_threshold>0.04</cliff_detection_threshold>
<bumper_name>bumpers</bumper_name>
<imu_name>imu</imu_name>
</plugin>
</gazebo>
要计算机器人的里程表,我们必须提供机器人的参数,例如车轮之间的距离,车轮直径和电动机的扭矩。 根据我们的设计,车轮间距为 30cm,车轮直径为 9cm,扭矩为 18N。如果要发布机器人的变形,可以将publish_tf
设置为 1。 插件是相应插件的参数。 如您所见,它接收来自接触传感器,IMU 和悬崖传感器的所有输入。
libgazebo_ros_kobuki.so
插件与 Turtlebot 2 仿真包一起安装。 我们在机器人中使用了相同的插件。 在运行此仿真之前,我们必须确保在您的系统上安装了 Turtlebot 2 仿真。
深度相机插件
深度相机插件可模拟深度相机的特征,例如 Kinect 或 Astra。 插件名称为libgazebo_ros_openni_kinect.so
,它可以帮助我们模拟具有不同特征的各种深度传感器。 插件显示在以下代码中:
<plugin name="kinect_camera_controller" filename="libgazebo_ros_openni_kinect.so">
<cameraName>camera</cameraName>
<alwaysOn>true</alwaysOn>
<updateRate>10</updateRate>
<imageTopicName>rgb/image_raw</imageTopicName>
<depthImageTopicName>depth/image_raw</depthImageTopicName>
<pointCloudTopicName>depth/points</pointCloudTopicName>
<cameraInfoTopicName>rgb/camera_info</cameraInfoTopicName>
<depthImageCameraInfoTopicName>depth/camera_info</depthImageCameraInfoTopicName>
<frameName>camera_depth_optical_frame</frameName>
<baseline>0.1</baseline>
<distortion_k1>0.0</distortion_k1>
<distortion_k2>0.0</distortion_k2>
<distortion_k3>0.0</distortion_k3>
<distortion_t1>0.0</distortion_t1>
<distortion_t2>0.0</distortion_t2>
<pointCloudCutoff>0.4</pointCloudCutoff>
</plugin>
插件的发布者,RGB 图像,深度图像和点云数据。 我们可以在插件中设置相机矩阵,以及自定义其他参数。
您可以参考这个页面,以了解有关 Gazebo 中深度相机插件的更多信息。
可视化机器人传感器数据
在本节中,我们将学习如何可视化来自模拟机器人的传感器数据。 在chefbot_gazebo
包中,有启动文件,用于在空旷的环境或类似酒店的环境中启动机器人。 可以使用 Gazebo 本身构建自定义环境。 只需使用原始网格物体创建环境并保存为*. world
文件即可,该文件可以作为启动文件中gazebo_ros
节点的输入。 要在 Gazebo 中启动酒店环境,可以使用以下命令:
$ roslaunch chefbot_gazebo chefbot_hotel_world.launch
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iYe7HE25-1681873679419)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00058.jpeg)]
酒店环境中 Gazebo 的 Chefbot
空间中的九个多维数据集代表九个表。 机器人可以导航到任何桌子以运送食物。 我们将学习如何执行此操作,但是在此之前,我们将学习如何从机器人模型中可视化各种传感器数据。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DDVQSrB6-1681873679419)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00059.jpeg)]
酒店环境中 Gazebo 的 Chefbot
以下命令将启动 Rviz,该 Rviz 显示来自机器人的传感器数据:
代码语言:javascript复制 $ roslaunch chefbot_description view_robot.launch
这将生成传感器数据的可视化效果,如以下屏幕截图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H9nkIf4p-1681873679419)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00060.jpeg)]
Rviz 中的 Chefbot 的传感器可视化
我们可以启用 Rviz 显示类型来查看不同类型的传感器数据。 在上图中,您可以看到深度云,激光扫描,TF,机器人模型和 RGB 摄像机图像。
同步定位和映射入门
Chefbot 的要求之一是,它应该能够自动导航环境并运送食物。 为了达到这个要求,我们必须使用几种算法,例如 SLAM(同时定位和映射)和 AMCL(自适应蒙特卡洛定位)。 解决自治导航问题有多种方法。 在本书中,我们主要坚持使用这些算法。 SLAM 算法用于在将机器人定位在同一张地图上的同时映射环境。 这似乎是个鸡与蛋的问题,但是现在有不同的算法可以解决它。 AMCL 算法用于在现有地图中定位机器人。 我们在本书中使用的算法称为 Gmapping,该算法实现了 Fast SLAM 2.0。 标准映射库包装在称为 ROS Gmapping 的 ROS 包中,可在我们的应用中使用。
SLAM 节点的想法是,当我们在环境中移动机器人时,它将使用激光扫描数据和里程计数据创建环境地图。
有关更多详细信息,请参见这个页面上的 ROS Gmapping Wiki 页面。
在 Gazebo 环境中实现 SLAM
在本节中,我们将学习如何实现 SLAM 并将其应用于我们构建的仿真。 您可以在chefbot_gazebo/launch/gmapping_demo.launch
和launch/includes/ gmapping.launch.xml
检查代码。 基本上,我们使用来自 Gmapping 包的节点,并使用适当的参数对其进行配置。 gmapping.launch.xml
代码片段具有此节点的完整定义。 以下是此节点的代码片段:
<launch>
<arg name="scan_topic" default="scan" />
<node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen">
<param name="base_frame" value="base_footprint"/>
<param name="odom_frame" value="odom"/>
<param name="map_update_interval" value="5.0"/>
<param name="maxUrange" value="6.0"/>
<param name="maxRange" value="8.0"/>
我们正在使用的节点的名称为slam_gmapping
,而包的名称为gmapping
。 我们必须为此节点提供一些参数,可以在 Gmapping Wiki 页面中找到。
使用 SLAM 创建地图
在本节中,我们将学习如何使用 SLAM 创建环境地图。 但是,首先,我们必须使用几个命令来开始映射。 您应该在每个 Linux 终端中执行每个命令。
首先,我们必须使用以下命令开始仿真:
代码语言:javascript复制 $ roslaunch chefbot_gazebo chefbot_hotel_world.launch
接下来,我们必须在新终端中启动键盘遥操作节点。 这将帮助我们使用键盘手动移动机器人:
代码语言:javascript复制 $ roslaunch chefbot_gazebo keyboard_teleop.launch
下一条命令在新终端中启动 SLAM:
代码语言:javascript复制 $ roslaunch chefbot_gazebo gmapping_demo.launch
现在将开始映射。 为了可视化映射过程,我们可以在导航设置的帮助下启动 Rviz:
代码语言:javascript复制 $ roslaunch chefbot_description view_navigation.launch
现在,我们可以看到在 Rviz 中创建的地图,如以下屏幕截图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xx35EpFJ-1681873679419)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00061.jpeg)]
使用 Gmapping 在 Rviz 中创建地图。
现在我们可以使用 Teleop 节点移动机器人,您可以看到在 Rviz 中正在创建地图。 为了创建良好的环境图,您必须缓慢移动机器人,并且经常必须旋转机器人。 当我们在环境中移动机器人并构建地图时,可以使用以下命令保存当前地图:
代码语言:javascript复制 $ rosrun map_server map_saver -f ~/Desktop/hotel
该地图将另存为*.pgm
和*.yaml
,其中pgm
文件是地图,yaml
文件是地图的配置。 您可以在桌面上查看已保存的地图。
在环境中移动机器人之后,您可能会得到一张完整的地图,例如以下屏幕快照所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3lXaTUS1-1681873679420)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00062.jpeg)]
使用映射的最终地图。
可以随时保存地图,但是请确保机器人覆盖了环境的整个区域并绘制了其所有空间,如前面的屏幕快照所示。 一旦确定地图已完全构建,请再次输入map_saver
命令并关闭端子。 如果您无法映射环境,则可以从chefbot_gazebo/maps/hotel
检查现有的地图。
自适应蒙特卡洛定位入门
我们已经成功建立了环境地图。 现在,我们必须从当前机器人位置自主导航到目标位置。 开始自主导航之前的第一步是在当前地图中定位机器人。 我们用于在地图上定位的算法称为 AMCL。 AMCL 使用粒子过滤器来跟踪机器人相对于地图的位置。 我们正在使用 ROS 包在我们的机器人中实现 AMCL。 与 Gmapping 相似,amcl
包内部有许多要为amcl
节点配置的参数。 您可以在 ROS Wiki 页面本身上找到 AMCL 的所有参数。
那么如何为机器人启动 AMCL? 为此,有一个启动文件,该文件位于chefbot_gazebo/amcl_demo.launch
和chefbot_gazebo/includes/amcl.launch.xml
中。
我们可以看到amcl_demo.launch
的定义。 以下代码显示了此启动文件的定义:
<launch>
<!-- Map server -->
<arg name="map_file" default="$(find chefbot_gazebo)/maps/hotel.yaml"/>
<node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)" />
此启动文件中的第一个节点从map_server
包中启动map_server
。 map_server
节点加载我们已经保存的静态地图,并将其发布到名为map
(nav_msgs/OccupancyGrid
)的主题中。 我们可以将映射文件作为amcl_demo.launch
文件的参数提及,如果有映射文件,则map_server
节点将加载该文件。 否则,它将加载位于chefbot_gazeob/maps/hotel.yaml
文件中的默认地图。
加载地图后,我们启动amcl
节点并移动基础节点。 AMCL 节点有助于将机器人定位在 ROS 导航栈内的当前map
和move_base
节点上,这有助于将机器人从起点导航到目标位置。 在接下来的章节中,我们将详细了解move_base
节点。 move_base
节点也需要配置参数。 参数文件保存在chefbot_gazebo/param
文件夹中,如以下代码所示:
<!-- Localization -->
<arg name="initial_pose_x" default="0.0"/>
<arg name="initial_pose_y" default="0.0"/>
<arg name="initial_pose_a" default="0.0"/>
<include file="$(find chefbot_gazebo)/launch/includes/amcl.launch.xml">
<arg name="initial_pose_x" value="$(arg initial_pose_x)"/>
<arg name="initial_pose_y" value="$(arg initial_pose_y)"/>
<arg name="initial_pose_a" value="$(arg initial_pose_a)"/>
</include>
<!-- Move base -->
<include file="$(find chefbot_gazebo)/launch/includes/move_base.launch.xml"/>
</launch>
您可以通过以下链接进一步了解 ROS 导航栈。
在 Gazebo 环境中实现 AMCL
在本节中,我们将学习如何在 Chefbot 中实现 AMCL。 我们将使用以下过程将 AMCL 合并到模拟中。 每个命令应在每个终端中执行。
第一个命令启动 Gazebo 模拟器:
代码语言:javascript复制 $ roslaunch chefbot_gazebo chefbot_hotel_world.launch
现在,无论是否带有映射文件,我们都可以启动 AMCL 启动文件。 如果要使用已构建的自定义映射,请使用以下命令:
代码语言:javascript复制 $ roslaunch chefbot_gazebo amcl_demo.launch map_file:=/home/<your_user_name>/Desktop/hotel
如果要使用默认地图,则可以使用以下命令:
代码语言:javascript复制 $ roslaunch chefbot_gazebo amcl_demo.launch
启动 AMCL 之后,我们可以启动 Rviz 以可视化地图和机器人。 我们将在 Rviz 中看到一个视图,如以下屏幕快照所示。 您可以看到地图和被绿色粒子包围的机器人。 绿色粒子称为amcl
粒子。 它们指示机器人位置的不确定性。 如果机器人周围有更多的粒子,则意味着机器人位置的不确定性更高。 当它开始移动时,粒子数将减少并且其位置将更加确定。 如果机器人无法定位地图的位置,则可以使用 Rviz 中的 2D 姿态估计按钮(在工具栏上)来手动设置机器人在地图上的初始位置。 您可以在以下屏幕截图中看到该按钮:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f9BrJKoP-1681873679420)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00063.jpeg)]
在酒店地图上启动 AMCL。
如果放大到 Rviz 中机器人的位置,则可以看到粒子,如前面的屏幕快照所示。 我们还可以通过不同的颜色看到机器人周围的障碍物:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CRgnab4g-1681873679420)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00064.jpeg)]
机器人周围的 AMCL 云。
在下一部分中,我们将学习如何对 Chefbot 进行编程以自动导航该地图。 您无需关闭当前端子; 我们可以在 Rviz 本身中自主导航机器人。
使用 Gazebo 在酒店内自动驾驶 Chefbot
要开始机器人的自主导航,我们只需要在地图上命令机器人的目标位置即可。 Rviz 中有一个名为 2D Nav Goal 的按钮。 我们可以单击该按钮,然后单击地图上的一个点。 现在,您可以看到一个指示机器人位置的箭头。 在地图上指定目标位置时,可以看到机器人正在规划从其当前位置到目标位置的路径。 它将从当前位置缓慢移动到目标位置,避开所有障碍物。 以下屏幕快照显示了机器人的路径规划和导航到目标位置。 机器人周围的彩色网格显示了机器人的本地成本图,本地计划程序路径以及机器人周围的障碍物:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RZDuTATd-1681873679420)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00065.jpeg)]
机器人的自主导航。
这样,如果我们在地图内命令一个位置更靠近桌子,则机器人可以转到该桌子并提供食物,然后返回其原始位置。 不用从 Rviz 命令它,我们可以编写一个 ROS 节点来做同样的事情。 这将在本书的最后几章中进行解释。
总结
在本章中,我们学习了如何模拟自己的名为 Chefbot 的机器人。 我们在上一章中介绍了 Chefbot 的设计。 我们通过学习 Gazebo 仿真器及其不同的特性和功能来开始本章。 之后,我们研究了如何使用 ROS 框架和 Gazebo 仿真器执行机器人仿真。 我们安装了 TurtleBot 2 包,并在 Gazebo 中测试了 Turtlebot 2 仿真。 之后,我们创建了 Chefbot 仿真,并在酒店环境中使用了 Gmapping,AMCL 和自主导航。 我们了解到模拟的准确率取决于地图,并且如果生成的地图是完美的,则机器人将在模拟中更好地工作。
在下一章中,我们将学习如何设计机器人的硬件和电路。
问题
- 我们如何在 Gazebo 中为传感器建模?
- ROS 如何与 Gazebo 连接?
- 用于仿真的重要 URDF 标签是什么?
- 什么是映射,我们如何在 ROS 中实现它?
- ROS 中
move_base
节点的功能是什么? - 什么是 AMCL,我们如何在 ROS 中实现它?
进一步阅读
要了解有关 URDF,Xacro 和 Gazebo 的更多信息,请参阅《精通 ROS 机器人编程第二版》。
五、设计 ChefBot 硬件和电路
在本章中,我们将讨论 ChefBot 硬件的设计和工作原理,并介绍其硬件组件的选择。 在上一章中,我们使用 Gazebo 和 ROS 设计和仿真了旅馆环境中的基本机器人框架,并测试了一些变量,例如机器人的体重,电机扭矩,车轮直径等。 我们还在酒店环境中测试了 ChefBot 的自主导航功能。
为了使用硬件实现此目的,我们需要选择所有硬件组件,并弄清楚如何连接所有这些组件。 我们知道该机器人的主要功能是导航:该机器人将能够从起始位置导航到终点,而不会与周围环境发生任何碰撞。 我们将讨论实现此目标所需的不同传感器和硬件组件。 我们将查看这些组件的框图表示及其说明,并讨论机器人的主要功能和物理操作。 最后,我们需要选择构建机器人所需的组件。 我们还将熟悉可以在其中购买这些组件的在线商店。
如果您有 TurtleBot,则可以跳过本章,因为本章仅适用于需要创建机器人硬件的用户。 让我们看看在硬件设计中必须满足的规格。 机器人硬件主要包括机器人机箱,传感器,执行器,控制器板和 PC。
本章将涵盖以下主题:
- Chefbot 机器人的框图和说明
- 机械手组件的选择和说明
- Chefbot 硬件的运作方式
技术要求
本章介绍了构建机器人所需的组件。 您必须购买这些组件或类似组件才能构建 ChefBot。
ChefBot 的硬件规格
在本节中,我们将讨论在第 3 章“建模差动机器人”中提到的一些重要规范。 最终的机器人原型将满足以下规格:
- 简单且经济高效的机器人机箱设计:与现有机器人相比,机器人机箱设计应该简单且具有成本效益。
- 自主导航功能:机器人应该自主导航,并且应该包含执行此操作所需的传感器。
- 电池寿命长:机器人应具有较长的电池寿命才能连续工作。 它可以工作的时间长度应大于一小时。
- 避开障碍物:机器人应该能够避免周围环境中的静态和动态物体。
机械手的硬件设计应符合这些规格。 让我们看一下互连此机器人中组件的可能方法之一。 在下一节中,我们将查看机器人的框图,并使用它来检查其工作原理。
机器人的框图
机器人的运动由两个直流(DC)齿轮电机通过编码器控制。 两个马达通过马达驱动器驱动。 电机驱动器与嵌入式控制器板接口,该控制器板将向电机驱动器发送命令以控制电机的运动。 电动机的编码器与控制器板连接,以便计算电动机轴的转数。 该数据用于计算机器人的里程数据。 有超声波传感器与控制板连接,以便感应障碍物并测量与障碍物的距离。 有一个 IMU 传感器可以改善里程计的计算。 嵌入式控制器板与 PC 相连,后者在机器人中执行所有高端处理。 视觉和声音传感器与 PC 连接,并连接了 Wi-Fi 以进行远程操作。 下图说明了机器人的每个组件:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-guzOvZnY-1681873679420)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00066.gif)]
机器人硬件框图
电机和编码器
我们将要设计的机器人是带有两个轮子的差速驱动机器人,因此我们需要两个电动机来实现其运动。 每个电动机都由正交编码器组成,这样我们就可以获得电动机的旋转反馈数据。
正交编码器将以平方脉冲的形式发送有关电动机旋转的数据; 我们可以解码脉冲以获得编码器的滴答声数量,该数量可用于反馈。 如果我们知道轮子的直径和电机的刻度数,就可以计算出移动机器人的位移和角度。 这种计算对我们导航机器人的尝试非常有用。
为机器人选择电动机,编码器和轮子
通过仿真,我们了解了机器人的参数。 在试验仿真参数时,我们提到驱动机器人所需的电机转矩为 18 N,但计算出的转矩略大于此。 我们正在选择非常接近实际扭矩的标准扭矩电动机,以便于选择电动机。 我们可能考虑的标准电动机之一是 Pololu。 根据我们的设计规范,我们可以选择一种高转矩直流齿轮电动机,该电动机的编码器工作在 12V DC 且转速为 80 RPM。
下图显示了为此机器人选择的电动机。 电机带有集成的正交编码器,其分辨率为电机轴每转 64 个计数,这对应于变速箱输出轴每转 8400 个计数:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J5JVKY7Q-1681873679421)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00067.jpeg)]
带编码器和车轮的直流齿轮电动机
该马达具有六个不同颜色的插针。 下表中给出了该电机销的说明:
颜色 | 功能 |
---|---|
红 | 电机功率(连接到一个电机端子) |
黑 | 电机功率(连接到另一个电机端子) |
绿 | 编码器 GND |
蓝 | 编码器 VCC(3.5V-20V) |
黄 | 编码器 A 输出 |
白 | 编码器 B 输出 |
根据我们的设计规格,我们将选择 90 毫米的车轮直径。 Pololu 提供了 90 毫米的砂轮,可从这个页面获得。 上图显示了装有此轮的电动机。
将电动机和车轮连接在一起所需的其他连接器如下:
- 可通过这个页面获得将车轮安装到电机轴所需的安装轮毂。
- 可在这个页面上获得用于将电机安装到机器人机箱上的 L 型支架。
电动机驱动
电动机驱动器或电动机控制器是可以控制电动机速度的电路。 通过控制电动机,我们的意思是我们可以控制电动机两端的电压,也可以控制电动机的方向和速度。 如果更改电机端子的极性,则电机可以顺时针或逆时针旋转。
H 桥电路通常用于电动机控制器。 H 桥是一种可以在负载的任一方向施加电压的电子电路。 它具有高电流处理性能,并且可以改变电流的方向。
下图显示了使用开关的基本 H 桥电路:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xkUwcrbZ-1681873679421)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00068.gif)]
H 桥电路
根据四个开关的状态,电动机的方向如下:
S1 | S2 | S3 | S4 | 结果 |
---|---|---|---|---|
1 | 0 | 0 | 1 | 电机向右移动 |
0 | 1 | 1 | 0 | 电机向左移动 |
0 | 0 | 0 | 0 | 电机自由运行 |
0 | 1 | 0 | 1 | 电机刹车 |
1 | 0 | 1 | 0 | 电机刹车 |
1 | 1 | 0 | 0 | 电机直射 |
0 | 0 | 1 | 1 | 电机直射 |
1 | 1 | 1 | 1 | 电机直射 |
在前面的电机驱动器电路图中,我们已经了解了 H 桥电路的基础知识。 现在,我们将为我们的应用选择一种电机驱动器,并讨论其工作原理。
选择电动机驱动器/控制器
Pololu 中有一些与所选电动机兼容的电动机驱动器。 下图显示了我们将在机器人中使用的电机驱动器之一:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TfTa3lTw-1681873679421)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00069.jpeg)]
双 VNH2SP30 电动机驱动器支架 MD03A
该电动机驱动器可从这个页面获得。
该驱动器可以驱动两个最大额定电流为 30A 的电动机,并包含两个用于驱动每个电动机的集成 IC。 该驱动器的引脚说明在后面的章节中给出。
输入引脚
以下引脚是电动机驱动器的输入引脚,通过它们我们可以主要控制电动机的速度和方向:
引脚名称 | 功能 |
---|---|
1DIAG/EN,2DIAG/EN | 它们监视电动机驱动器 1 和 2 的故障状态。在正常操作中,它们将保持断开状态。 |
1INa,1INb,2INa,2INb | 这些引脚将通过以下方式控制电动机 1 和 2 的方向: |
如果INA = INB = 0,则电动机将断开 | |
如果INA = 1, INB = 0,则电动机将顺时针旋转 | |
如果INA = 0, INB = 1,则电动机将逆时针旋转 | |
如果INA = INB = 1,则电动机将断开 | |
1PWM,2PWM | 这将通过以非常高的速度打开和关闭它们来控制电动机 1 和 2 的速度。 |
1CS,2CS | 这是每个电机的电流检测引脚。 |
输出引脚
电机驱动器的输出引脚将驱动两个电机。 以下是输出引脚:
引脚名称 | 功能 |
---|---|
OUT 1A,OUT 1B | 这些引脚可以连接到电动机 1 的电源端子。 |
OUT 2A,OUT 2B | 这些引脚可以连接到电动机 2 的电源端子。 |
电源引脚
以下是电源引脚:
引脚名称 | 功能 |
---|---|
VIN( ),GND(-) | 这些是两个电机的电源引脚。 电压范围为 5.5V 至 16V. |
5VIN( ),GND(-) | 这是电机驱动器的电源。 电压应为 5V。 |
嵌入式控制器板
控制器板通常是 I/O 板,可以将数字脉冲形式的控制信号发送到 H 桥/电动机驱动器板,并可以接收来自传感器(例如超声波和 IR 传感器)的输入。 我们还可以将电机编码器与控制板接口,以便从电机发送数据。
该机器人中控制板的主要用途如下:
- 连接电机驱动器和编码器
- 连接超声波传感器
- 使用 PC 收发传感器值
在接下来的章节中,我们将处理 I/O 板并与不同组件进行接口。 一些比较流行的 I/O 板是德州仪器(TI)的 Arduino(arduino.cc)和 Tiva-C LaunchPad。 由于以下因素,我们选择基于 Arduino 的 Tiva-C LaunchPad:
- Tiva-C LaunchPad 的微控制器基于 32 位 ARM Cortex-M4,具有 256KB 闪存,32KB SRAM 和 80MHz 数据传输频率。 大多数 Arduino 开发板都在这些规格下运行。
- 出色的处理性能与快速的中断处理相结合。
- 12 个计时器。
- 16 个 PWM 输出。
- 2 个正交编码器输入。
- 8 通用异步收发器(UART)。
- 5V 耐压通用输入/输出(GPIO)。
- 与 Arduino 开发板相比,成本低,尺寸小。
- 易于编程的接口 IDE,称为 Energia。 用 Energia 编写的代码与 Arduino 板兼容。
下图显示了德州仪器(TI)的 Tiva-C LaunchPad:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-thKLVsMz-1681873679421)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00070.jpeg)]
Tiva-C LaunchPad 123
德州仪器(TI)的 LaunchPad 系列的引脚排列在这个页面中给出。 该引脚分配图与所有 LaunchPad 系列版本兼容。 在 Energia IDE 中进行编程时也可以使用它。
超声波传感器
超声波传感器,也称为 PING 传感器,主要用于测量与物体的距离。 PING 传感器的主要应用是避免障碍物。 超声波传感器发出高频声波,并评估从物体接收到的回声。 传感器将计算回波的发送和接收之间的延迟,并确定其与物体的距离。
在我们的机器人中,无碰撞导航是设计规范的重要组成部分,否则会损坏机器人。 您将在下一部分中看到显示超声波传感器的图像。 该传感器可以安装在机器人的侧面,以检测机器人侧面和背面的碰撞。 当用于机器人技术时,Kinect 还主要用于障碍物检测和避免碰撞。 Kinect 只能在 0.8m 的范围内是准确的,因此可以使用超声波传感器检测距 0.8m 范围极限的剩余距离。 在这种情况下,超声波传感器实际上是我们机器人的附加组件,目的是提高其避免碰撞和检测的能力。
选择超声波传感器
HC-SR04 是最流行和便宜的超声波传感器之一。 由于以下因素,我们正在为机器人选择此传感器:
- 检测范围为 2cm 至 4m
- 工作电压为 5V
- 工作电流非常低,通常为 15mA
我们可以使用此传感器来准确检测障碍物。 它也可以在 5V 电压下工作。这是 HC-SR04 及其引脚排列的图像:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9M1PgBvG-1681873679421)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00071.jpeg)]
超声波传感器
引脚及其功能如下:
引脚 | 功能 |
---|---|
VCC,GND | 这些是超声波传感器的电源引脚。 通常,我们需要施加 5V 电压才能使其正常运行。 |
PING | 这是传感器的输入引脚。 我们需要向此引脚施加特定持续时间的脉冲以发送超声波。 |
ECHO | 这是传感器的输出引脚。 它将根据接收触发脉冲的延迟在此引脚上产生一个持续时间的脉冲。 |
惯性测量单元
我们将在此机器人中使用惯性测量单位(IMU)来获得对里程表值和机器人姿势的良好估计。 仅从编码器计算出的里程表值可能不足以进行有效导航,因为它们可能包含错误。 为了补偿机器人运动(尤其是旋转)过程中的错误,我们将在该机器人中使用 IMU。 由于以下原因,我们选择 IPU 的 MPU 6050:
- 在 MPU 6050 中,加速度计和陀螺仪集成在单个芯片中
- 它提供了高精度和高灵敏度
- 我们能够与磁力计对接以获得更好的 IMU 性能
- MPU 6050 的分线板非常便宜
- MPU 6050 可直接与 LaunchPad 交互
- MPU 6050 和 LaunchPad 均兼容 3.3V
- 还提供了软件库,可简化 MPU 6050 和 LaunchPad 之间的接口
下图显示了 MPU 6050 的分线板:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-09yjmCXj-1681873679422)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00072.jpeg)]
MPU 6050 设备
引脚及其功能如下:
引脚 | 功能 |
---|---|
VDD,GND | 电源电压 2.3V-3.4V |
INT | 当数据到达设备缓冲器时,该引脚将产生一个中断 |
SCL,SDA | 串行数据线(SDA)和串行时钟线(SCL)用于 I2C 通信 |
ASCL,ASDA | 与磁力计通讯的辅助 I2C |
我们可以从亚马逊购买分线板。
Kinect/Orbbec Astra
Kinect 是 3D 视觉传感器,主要用于 3D 视觉应用和基于运动的游戏。 我们将 Kinect 用于 3D 视觉。 使用 Kinect,机器人将获得周围环境的 3D 图像。 3D 图像被转换为更细的点,这些点被收集以形成点云。 点云数据将具有构成周围环境的所有 3D 参数。
Kinect 在机器人上的主要用途是模拟激光扫描仪的功能。 激光扫描仪数据对于 SLAM 算法构建环境图至关重要。 激光扫描仪是一种非常昂贵的设备,因此,我们无需购买昂贵的激光扫描仪,而是可以将 Kinect 转换为虚拟激光扫描仪。 Kinect 已正式停止生产,但仍可从某些供应商处获得。 Kinect 的替代品之一是 Orbbec Astra。 它将支持为 Kinect 编写的相同软件。 点云到激光数据的转换是使用此软件完成的,因此,如果您使用的是 Astra,我们只需要更改设备驱动程序即可; 软件的重置是相同的。 生成环境图后,机器人可以导航周围的环境。 下图显示了 Kinect 传感器(A)和 Orbbec Astra(B):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q2OM533J-1681873679422)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00073.jpeg)]
Kinect 和 Orbbec Astra
Kinect 主要具有红外摄像机和投影仪,以及 RGB 摄像机。 红外摄像机和投影仪会生成周围区域的 3D 点云。 它还具有麦克风阵列和电动倾斜装置,可上下移动 Kinect。 Astra 与 Kinect 非常相似。
我们可以从这个页面购买 Kinect。
我们可以从这个页面购买 Astra。
中央处理器
机器人主要由其 PC 上运行的导航算法控制。 我们可以选择笔记本电脑,微型 PC 或上网本来用于机器人的处理功能。 最近,英特尔推出了一款微型计算机,称为英特尔下一计算单元(NUC)。 它具有超小的外形尺寸(尺寸),重量轻,并且具有 Intel Celeron,Core i3 或 Core i5 的出色计算处理器。 它最多可支持 16GB 的 RAM,并集成了 Wi-Fi /蓝牙。 我们之所以选择英特尔 NUC,是因为其性能,超小外形和轻巧的特性。 我们不打算使用 Raspberry Pi 或 Beagle Bone 这样的流行主板。 ,因为我们需要强大的计算能力,而这些电路板无法提供这种能力。
我们正在使用的 NUC 是 Intel DN2820FYKH。 这是这台计算机的规格:
- 英特尔赛扬双核处理器(2.39GHz)
- 4GB 内存
- 500GB 硬盘
- 英特尔集成显卡
- 耳机/麦克风插孔
- 12V 电源
下图显示了英特尔 NUC 小型计算机:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iizD3lMb-1681873679422)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00074.gif)]
英特尔 NUC DN2820FYKH
我们可以通过这个页面从亚马逊购买 NUC。
这种 NUC 模型是旧模型; 如果不可用,则可以使用下面显示的链接检查低成本的 NUC:
- 英特尔 NUC BOXNUC6CAYH
- 英特尔 NUC 套件 NUC7CJYH
- 英特尔 NUC 套件 NUC5CPYH
- 英特尔 NUC 套件 NUC7PJYH
扬声器/麦克风
机器人的主要功能是自主导航。 我们将添加一个附加功能,机器人可以通过语音与用户互动。 机器人可以通过语音输入获得命令,并可以使用文本到语音(TTS)引擎与用户对话,该引擎可以将文本转换为语音格式。 麦克风和扬声器对于此应用至关重要。 对于此硬件,没有特别推荐的建议。 如果扬声器和麦克风与 USB 兼容,那就太好了。 其他选择之一是蓝牙耳机。
电源/电池
电源是最重要的硬件组件之一。 我们在规格书中看到机器人必须工作超过一个小时。 如果电池的电源电压与组件所需的电压兼容,那将是很好的。 另外,如果电池的尺寸和重量小于我们的预期,则不会影响机器人的有效负载。
另一个问题是整个电路所需的最大电流不会超过其可提供的电池最大电流。 电路各部分的最大电压和电流分布如下:
组件 | 最大电流(以安培为单位) |
---|---|
英特尔 NUC PC | 12V,5A |
Kinect | 12V,1A |
马达 | 12V,0.7A |
电机驱动器,超声波传感器,IMU,扬声器 | 5V,<0.5A |
为了满足这些规格,我们为机器人选择了 12V,10AH 锂聚合物或密封铅酸(SLA)电池。 这是我们可以用于此目的的典型低成本 SLA 电池:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qtEZ3tD5-1681873679422)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00075.jpeg)]
密封铅酸电池
我们可以从这个页面购买此电池。 您可以根据方便程度选择电池,但它应满足机器人的电源要求。
ChefBot 的硬件如何工作?
我们可以使用以下框图来说明 ChefBot 的硬件如何工作。 这是我们第一个框图的改进版本,因为它提到了每个组件的电压及其互连:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0IDFH4DO-1681873679422)(https://gitcode.net/apachecn/apachecn-cv-zh/-/raw/master/docs/learn-robot-py/img/00076.gif)]
Chefbot 硬件的详细框图
本章的主要目的是为 ChefBot 设计硬件,其中包括找到合适的硬件组件以及学习各部分之间的互连。 该机器人的主要功能是执行自主导航。 机器人的硬件设计针对自主导航进行了优化。
机器人驱动基于差速驱动系统,该系统由两个电机和两个轮子组成。 有用于支撑主车轮的脚轮。 这两个电机可以通过调整机器人的方向和旋转速度来使其在 2D 平面上面向任意方向移动。
为了控制车轮的速度和方向,我们必须连接一个可以执行这些功能的电机控制器。 我们选择的电动机驱动器应该能够同时控制两个电动机,并且还应该能够改变它们的方向和速度。
电机驱动器引脚与名为 Tiva-C LaunchPad 的微控制器板连接,该板可以发送命令以更改电机的方向和速度。 借助电平转换器,将电机驱动器与 LaunchPad 连接。 电平转换器是一种可以将电压电平从 3.3V 转换到 5V,反之亦然的电路。 我们使用电平转换器是因为电动机驱动器的工作电压为 5V,而 LaunchPad 板的工作电压为 3.3V。
每个电机都有一个称为编码器的旋转反馈传感器,可用于估计机器人的位置。 编码器通过电平转换器与 LaunchPad 连接。
与 LaunchPad 接口的其他传感器包括超声波传感器和 IMU。 超声波传感器可以检测到附近但 Kinect 传感器无法检测到的对象。 IMU 与编码器一起使用,可以很好地估计机器人的姿势。
所有传感器值都在 LaunchPad 上接收,并通过 USB 发送到 PC。 LaunchPad 板运行的固件代码可以接收所有传感器值并将其发送到 PC。
PC 与 Kinect,LaunchPad 板,扬声器和麦克风连接。 PC 上运行有 ROS,它将接收 Kinect 数据并将其转换为等效的激光扫描仪数据。 该数据可用于使用 SLAM 构建环境地图。 扬声器和麦克风用于用户和机器人之间的通信。 在 ROS 节点中生成的速度命令将发送到 LaunchPad。 LaunchPad 将处理速度命令,并将适当的 PWM 值发送到电动机驱动器电路。
在设计并讨论了机器人硬件的工作原理之后,我们将在下一章中讨论每个组件的详细接口以及为此接口所必需的固件编码。
总结
在本章中,我们研究了要设计的机器人的功能。 该机器人的主要特征是其自主导航。 机器人可以通过分析传感器读数来导航周围的环境。 我们查看了机器人的框图,并讨论了每个模块的作用,并选择了满足我们要求的适当组件。 我们还建议了一些经济的组件来构建此机器人。 在下一章中,我们将仔细研究执行器及其在该机器人中将用于它们的接口。
问题
- 机器人硬件设计到底是什么?
- 什么是 H 桥电路,其功能是什么?
- 机器人导航算法的基本元素是什么?
- 选择机器人组件时必须牢记的标准是什么?
- Kinect 在此机器人方面的主要应用是什么?