个性化阅读
专注于IT技术分析

机器人操作系统简介:最终的机器人应用框架

本文概述

机械手操作系统(ROS)不是实际的操作系统, 而是在异构计算机群集上提供操作系统功能的框架和工具集。它的用途不仅限于机器人, 而是提供的大多数工具都集中在使用外围硬件上。

ROS分为2000多个软件包, 每个软件包都提供专门的功能。连接到框架的工具数量可能是其最大的功能。

为什么要使用Robot OS?

ROS提供了用于硬件抽象, 设备驱动程序, 多台机器上的进程之间的通信, 测试和可视化工具等功能。

机器人操作系统简介:最终的机器人应用程序框架

ROS的主要功能是软件的运行方式和通信方式, 使你可以在不知道某些硬件如何工作的情况下设计复杂的软件。 ROS提供了一种将过程网络(节点)与中央集线器连接的方法。节点可以在多个设备上运行, 并且它们以各种方式连接到该集线器。

创建网络的主要方式是提供可请求的服务, 或定义与其他节点的发布者/订阅者连接。两种方法都通过指定的消息类型进行通信。核心软件包提供了某些类型, 但是消息类型可以由单个软件包定义。

开发人员可以通过连接现有的小问题解决方案来组装复杂的系统。该系统的实现方式使我们能够:

  • 快速更换具有相似接口的组件, 无需停止系统进行各种更改

  • 将多个组件的输出复用为另一个组件的一个输入, 从而可以并行解决各种问题

  • 通过仅实现与消息传递系统的适当连接器即可连接以各种编程语言编写的组件, 从而通过连接来自各种开发人员的现有模块来轻松开发软件

  • 通过设备网络创建节点, 而不必担心代码在哪里运行以及实现进程间通信(IPC)和远程过程调用(RPC)系统

  • 通过使用前两个要点, 直接按需从远程硬件连接到提要, 而无需编写任何额外的代码

我们计划通过迭代开发一个简单的解决方案来证明这是多么有用。与其他方法相比, 有几个关键优势。 ROS具有多平台支持, 并允许通过在后台处理的对等连接在多个设备上的进程之间进行连接。该设计允许通过包装C ++通信类或为语言接口手动开发类来支持任何语言。

ROS由其自己的社区(即为其社区)制成。几年后, 由于系统的体系结构, 导致产生了大量易于集成的可重用软件包。

诸如MRPT, CARMEN, LCM, Player, Microsoft RDS等替代方法提供了其中一些功能, 但并非全部。在大多数情况下, 设计缺陷是语言支持限制, 流程之间的通信未优化或缺少对各种设备的支持, 这可能是最难解决的问题。

我们要建造什么?

由于我们的重点是框架而不是特定问题的实际算法, 因此给定的问题将非常简单。我们的目标是为车载计算机构建软件, 该软件允许我们通过使用计算机上的游戏手柄和安装在机器人上的摄像头来通过Wi-Fi远程控制和监视通过Wi-Fi连接到我们的机器人。

首先, 我们将使一个简单的程序与一个简单的仿真连接起来, 以演示ROS的基本原理。我们将游戏手柄连接到计算机, 并尝试设计一个好的控制方案, 将游戏手柄的输入转换为机器人的控制信号。

编写ROS代码的主要语言是C ++和Python, 由于性能更好, 因此首选C ++。由于代码中的样板较少且不需要显式构建, 因此我们将在Python中解释示例。

安装与配置

ROS版本按名称引用。到目前为止, 最新版本是Jade Turtle, 最新版本是LTS版本Indigo Igloo。最好选择LTS版本, 并且在ROS中不能保证向后兼容, 因此所有示例都将为Indigo编写。

ROS可在各种* NIX平台上使用。官方支持的版本在Ubuntu上。社区支持OS X, Arch Linux, Debian, Raspbian和Android版本。

我们将在桌面上介绍Ubuntu 14.04的安装过程。官方网站上提供了所有受支持的版本和平台的过程。也可以使用安装了ROS的虚拟机。

安装取决于平台(大多数平台都提供了软件包), 但是所有平台的工作空间配置都是相同的。

在Ubuntu上安装

ROS提供了自己的存储库。第一步是添加它们。

sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
sudo apt-key adv --keyserver hkp://pool.sks-keyservers.net --recv-key 0xB01FA116
sudo apt-get update

之后, 你将拥有适用于Ubuntu版本的所有ROS版本的所有托管程序包。例如, Ubuntu 14.04支持靛蓝和玉石。

在桌面上安装基本软件包具有以下三个选项之一:

  • sudo apt-get install ros-indigo-ros-base用于最小的安装

  • sudo apt-get install ros-indigo-desktop用于获得基本的附加GUI工具

  • sudo apt-get install ros-indigo-desktop-full, 具有所有正式功能, 包括各种用于导航和感知的模拟器和库

为了获得最佳的工作体验, 建议使用完整选项。对于在仅用于运行节点的设备上的安装, 基本版本就足够了。无论选择什么选项, 都可以通过运行以下命令安装任何需要的名为package_name的软件包:

sudo apt-get install ros-indigo-<package-name>

下划线在最终名称中由连字符替换, 因此stage_ros将在软件包ros-indigo-stage-ros中。

下一步是初始化rosdep。 ROS中的软件包可以声明它们所依赖的组件。 rosdep允许你编译这些软件包, 而无需过多的手动依赖项处理。要初始化它, 请调用:

sudo rosdep init
rosdep update

ROS的工具使用了几个环境变量。对于默认安装, 用于初始化它们的bash脚本位于/opt/ros/indigo/setup.bash中。变量需要在每个bash会话中初始化, 因此最好的解决方案是将它们添加到〜/ .bashrc中。

echo "source /opt/ros/indigo/setup.bash" >> ~/.bashrc
source ~/.bashrc

一些软件包通过rosinstall安装外部依赖项, 该软件包作为软件包提供, 并通过sudo apt-get install python-rosinstall安装。

这是在Ubuntu上安装的结束。接下来是安装工作区的简短介绍。

组态

自Groovy Galapagos以来, ROS工作区是通过catkin管理的。我们需要为我们托管的所有软件包定义一个目录。在目录中, 我们创建一个src文件夹, 并在其中调用catkin_init_workspace表单。这将创建指向当前来源ROS版本的各种符号链接。下一步是将该工作空间也添加到环境变量中。

要执行整个工作区配置, 请选择一个空目录并执行以下命令:

mkdir src
cd src
catkin_init_workspace
cd ..
catkin_make
echo "source $(pwd)/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc

现在, 你已经创建了一个工作区, 可以在其中创建自己的ROS包。

熟悉工具

创建任何代码都是一大步。首先, 让我们熟悉一些在后台运行的系统。我们的第一步将是运行基本GUI并查看其生成的消息。

要在ROS中运行任何程序, 都需要启动一个核心过程。就像打开新的终端窗口并键入以下命令一样简单:

roscore

在整个连接的设备网络中, roscore仅需在托管中央集线器以进行通信调度的设备上启动一次。

roscore的主要作用是告诉节点它们应该连接到其他节点以及以哪种方式(无论是通过网络端口还是共享内存)。目的是使节点仅关心它们想知道的数据, 而不是关心它们要连接的节点, 同时使执行所有通信所需的时间和带宽最小化。

q

运行roscore之后, 我们可以启动ROS的主要GUI工具:rqt。我们所看到的非常令人难以置信-一个空的窗口。 rqt托管了各种各样的插件, 可以将其配置为任何可视配置和任意数量的预定义视图。

机器人操作系统简介:最终的机器人应用框架2

首先, 让我们运行”机器人转向”插件, 方法是在”插件”>”机器人工具”>”机器人转向”中进行选择。我们得到的是两个滑块, 分别表示我们希望机器人具有的线性和旋转运动。在插件顶部, 我们看到一个带有/ cmd_vel的文本框。我们可以将其重命名为我们想要的任何名称。它代表指导将发布到的主题的名称。终端工具是查看背景情况的最佳位置。

机器人操作系统简介:最终的机器人应用框架3

终端工具

ROS有几个强大的工具可以检查系统中正在发生的事情。我们将介绍的第一个工具是rostopic。它使我们可以检查节点可以订阅和发布的主题。运行rostopic列表将产生:

/cmd_vel
/rosout
/rosout_agg

后两个主题始终在运行, 并且与中央ROS系统相关。 / cmd_vel主题正在由我们的指导发布。在指导中重命名主题也会在此处重命名。现在, 我们对该主题中发生的事情感兴趣。运行rostopic echo / cmd_vel将不会显示任何内容(除非你对滑块进行了修改)。该过程一直运行到我们取消它为止。现在让我们将垂直滑块移动到20 m / s。查看回声, 我们可以看到以下内容一遍又一遍:

linear:
  x: 0.2
  y: 0.0
  z: 0.0
angular:
  x: 0.0
  y: 0.0
  z: 0.0

此邮件多久发送一次垃圾邮件? rostopic hz / cmd_vel表示平均速率为10 Hz。那么, 我可以通过慢速Wi-Fi连接运行多少个这样的主题? rostopic bw / cmd_vel可检测到平均480 B / s。

现在一切都很好, 但是我们讨论了消息类型。此数据对人类有益, 但是应用程序需要原始数据, 并且需要知道消息类型, 以便它可以解释数据。可以使用rostopic类型/ cmd_vel确定类型, 告诉我们它是geometry_msgs / Twist。所有不带任何参数的ROS终端工具都将返回标准帮助消息。

ROS Wiki足以在网络上搜索此字符串, 从而在Wiki中解释了该字符串包含的内容以及其结构。但是我们不必依赖它。 rosmsg是消息类型的常规工具。运行rosmsg show geometry_msgs / Twist将返回:

geometry_msgs/Vector3 linear
  float64 x
  float64 y
  float64 z
geometry_msgs/Vector3 angular
  float64 x
  float64 y
  float64 z

该消息由两个3D向量组成, 分别表示3D空间中的线速度和角速度。

如果我们想要节点连接的主题, rosnode info <node-name>将为我们提供有关该节点的详细数据。 rostopic, rosmsg和rosnode工具是检查原始ROS功能的主要工具。 ROS有更多的GUI和终端工具, 但是这些在我们的介绍范围之外。

运行ROS节点的主要工具是rusrun和roslaunch。 rosrun可以通过rosrun <package_name> <node_name>运行节点, 并且roslaunch基于启动文件运行节点, 由于它们是ROS自动化中最复杂的元素, 因此我们会在一定程度上对其进行熟悉。

我们可以关闭所有运行内容以开始处理第一个代码。供以后参考, 不用说运行与ROS相关的任何东西都需要一个活动的roscore实例。你可以通过关闭运行roscore的终端窗口并打开一个新窗口以重新启动它来解决你遇到的许多问题。这将更新bash和roscore中所有需要重新加载的依赖项。

创建游戏手柄遥控

我们的首要目标是通过创建一个节点, 以模仿Robot Steering的功能, 该节点根据游戏手柄的输入将geometry_msgs / Twist数据发布到/ cmd_vel。我们的第一站是欢乐套餐。

欢乐套餐

Joy软件包为操纵杆和游戏手柄提供了通用的ROS驱动程序。它不包括在默认安装中, 因此需要通过以下方式安装:

sudo apt-get install ros-indigo-joy

安装完成后, 我们可以运行rosrun joy joy_node。这会将我们连接到默认的操纵杆或游戏手柄。运行rostopic列表显示我们有一个名为/ joy的主题。通过rostopic echo收听它会向我们显示以下格式的消息(请注意, 你必须与游戏手柄或操纵杆进行交互才能发布消息)。

header:
  seq: 4156
  stamp:
    secs: 1450707466
    nsecs: 204517084
  frame_id: ''
axes: [0.0, 0.0, 0.0, -0.0, 0.0, 0.0, 0.0, 0.0]
buttons: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

你现在可以忽略标题。除此之外, 我们还有轴和按钮, 很好地解释了它们所代表的含义。控制器上的移动轴和按钮将导致这些数字更改。使用我们的工具, 我们可以确定消息类型为sensor_msgs / Joy, 格式为:

std_msgs/Header header
  uint32 seq
  time stamp
  string frame_id
float32[] axes
int32[] buttons

创建我们的远程操作

编写代码的第一步是制作一个程序包。在工作区的src文件夹中, 运行:

catkin_create_pkg srcmini_tutorial rospy joy geometry_msgs sensor_msgs

在这里, 我们声明要创建的程序包的名称, 然后是我们计划依赖的程序包。不用担心, 依赖项可以稍后手动更新。

现在, 我们有一个srcmini_tutorial文件夹。在该文件夹中, 创建一个脚本文件夹, 其中将包含我们所有的Python脚本。

我们创建一个名为teleop.py的文件, 并在其中进行设置:

#!/usr/bin/env python

import rospy
from sensor_msgs.msg import Joy


def joy_callback(data):
    print data


def main():
    rospy.init_node('teleop')
    rospy.Subscriber('joy', Joy, joy_callback)

    while not rospy.is_shutdown():
        pass


if __name__ == '__main__':
    main()

我们还需要设置chmod + x teleop.py, 以便脚本可以运行。在一个终端上运行rosrun joy joy_node并在另一终端上运行rosrun srcmini_tutorial teleop.py将导致teleop.py的终端输出中充满Joy消息。

让我们检查一下代码的作用。

首先, 我们导入rospy, 它托管用于与ROS框架进行交互的库。每个定义消息的程序包都有一个msg子程序包, 其中包含消息定义。我们正在导入Joy来处理输入。除非我们要明确提及它们, 否则无需导入嵌入式消息类型(如Joy消息中的std_msgs.msg中的Header)。

我们的第一步是初始化一个具有特定名称的节点(在这种情况下, 我们称其为” teleop”)。之后, 我们创建一个订阅者, 该订阅者订阅类型为sensor_msgs.msg.Joy的” joy”主题, 并通过调用joy_callback函数来处理每条消息。回调接收一个参数, 即消息中的数据。访问数据成员很简单。如果我们想打印第一个轴的状态, 如果我们想起消息类型, 我们将调用print data.axes [0], 它将是一个浮点数。最后的循环一直循环到ROS关闭为止。

我们的下一步将是以某种方式处理我们的数据。我们应该创建一个Twist消息, 该消息会根据输入而变化, 然后将其发布到cmd_vel主题。

#!/usr/bin/env python

import rospy
from sensor_msgs.msg import Joy
from geometry_msgs.msg import Twist  # new
from functools import partial  # new


def joy_callback(pub, data):  # modified
    cmd_vel = Twist()  # new
    cmd_vel.linear.x = data.axes[1]  # new
    cmd_vel.angular.z = data.axes[0]  # new
    pub.publish(cmd_vel)  # new


def main():
    rospy.init_node('teleop')
    pub = rospy.Publisher('cmd_vel', Twist, queue_size=1000)  # new
    rospy.Subscriber('joy', Joy, partial(joy_callback, pub))  # modified

    while not rospy.is_shutdown():
        pass


if __name__ == '__main__':
    main()

首先, 我们添加Twist消息, 并通过functools.partial添加对绑定函数参数的支持。我们创建一个发布者pub, 该发布者将类型为Twist的消息发布到cmd_vel。我们将该发布者绑定到回调, 并使其在每个输入上发布Twist消息, 其速度由前两个轴表示。这段代码完成了我们期望的工作, 并且可以通过rostopic echo / cmd_vel查看结果输出。

我们还有一个问题。 / joy主题可以以很高的速度发布。如果我们监视rostopic hz / cmd_vel并绕圈移动模拟摇杆, 则可以看到大量消息。这不仅导致大量的通信, 而且接收这些消息的进程必须处理它们中的每一个。无需如此频繁地发布该数据, 最好以10 Hz的稳定速率发布。我们可以使用以下代码完成此操作。

#!/usr/bin/env python

import rospy
from sensor_msgs.msg import Joy
from geometry_msgs.msg import Twist
from functools import partial


def joy_callback(cmd_vel, data):  # modified
    cmd_vel.linear.x = data.axes[1]
    cmd_vel.angular.z = data.axes[0]
    # moved pub.publish(cmd_vel) to main loop


def main():
    rospy.init_node('teleop')

    cmd_vel = Twist()  # new

    pub = rospy.Publisher('cmd_vel', Twist, queue_size=1000)
    rospy.Subscriber('joy', Joy, partial(joy_callback, cmd_vel))  # modified

    rate = rospy.Rate(10)  # new
    while not rospy.is_shutdown():
        pub.publish(cmd_vel)  # new
        rate.sleep()  # new


if __name__ == '__main__':
    main()

我们修改了回调以接收可变的Twist对象, 并在循环内对其进行了修改。 rospy.Rate的睡眠功能可保持稳定的输出频率。

最终代码将导致/ cmd_vel主题以10 Hz的速度获取速度命令, 从而模仿Robot Steering rqt插件的输出。

运行模拟系统

模拟世界

我们的首要目标是创建一个环境, 在其中我们可以模拟想要实现的方案。 stage_ros包中的节点stageros允许我们在通过图像定义的2D阶段中运行一个机器人。在stage_ros软件包中介绍了用于世界文件以及如何生成它们的完整语法。这很简单, 但不在我们的讨论范围之内。幸运的是, 该软件包附带了几个演示世界。首先, 通过运行以下命令进入文件目录:

roscd stage_ros
cd world

文件夹中有几个文件。让我们运行一个。

rosrun stage_ros stageros willow-erratic.world

这创建了几个主题。包中还记录了它们每个的含义。重要的是它具有cmd_vel。

机器人操作系统简介:最终的机器人应用框架4

在显示的阶段中, 有一个蓝色方块, 代表你控制的机器人。通过使用我们的代码或机器人转向, 我们可以控制该机器人。试试看。

通过启动文件设置我们的系统

让我们在包中创建一个启动文件夹, 并在其中创建一个名为teleop.launch的文件。最终的文件夹结构应如下所示:

srcmini_tutorial/
├── CMakeLists.txt
├── launch
│   └── teleop.launch
├── package.xml
├── scripts
│   └── teleop.py
└── src

在teleop.launch文件中, 我们将定义一组节点及其互连。

<launch>
  <arg name="world_file" default="$(find stage_ros)/world/willow-four-erratics-multisensor.world" />
  <node pkg="stage_ros" type="stageros" name="simulated_world" args="$(arg world_file)"></node>
  <group ns="robot_0">
    <node pkg="joy" type="joy_node" name="joy_input"></node>
    <node pkg="srcmini_tutorial" type="teleop.py" name="joy_convert"></node>
  </group>
</launch>

新世界由四个机器人组成, 每个主题都有一个robot_ <n>前缀。因此, 编号为0的机械手具有一个速度命令主题, 称为robot_0 / cmd_vel。这就是为什么我们将控件放在名为robot_0的命名空间中, 以将其名称调整为新格式的原因。从这种意义上讲, 你可以将主题名称视为文件系统中的文件夹。

机器人操作系统简介:最终的机器人应用框架5

要运行启动文件, 不需要roscore。从某种意义上讲, roscore只是启动文件的一种特例, 它什么都不做。如果缺少roscore, 则只有第一个启动的launchfile将运行一个核心, 其余的将连接到该核心。现在, 我们使用以下命令运行启动:

roslaunch srcmini_tutorial teleop.launch

如果一切正确, 这将导致带有4个机器人的模拟器, 其中一个由我们的游戏手柄或操纵杆控制。这个世界比前一个世界拥有更多优势。四个机器人分别具有:

/robot_<n>/base_pose_ground_truth
/robot_<n>/base_scan_0
/robot_<n>/base_scan_1
/robot_<n>/camera_info_0
/robot_<n>/camera_info_1
/robot_<n>/cmd_vel
/robot_<n>/depth_0
/robot_<n>/depth_1
/robot_<n>/image_0
/robot_<n>/image_1
/robot_<n>/odom

我们将<n>替换为0、1、2或3。这使我们进入了最后一个主题。

使用rqt查看我们的数据

我们并没有深入研究rqt, 但是它是查看更复杂数据的理想工具。你可以尝试所有主题, 但我们将重点关注image_0, image_1, depth_0和depth_1主题。

让我们启动rqt并删除所有打开的插件。现在, 我们将打开4个图像可视化器(插件>可视化>图像视图), 并将其放置在2×2网格形式中。最后, 在每个视图的左上角, 我们为robot_0选择四个陈述的主题之一。

机器人操作系统简介:最终的机器人应用框架6

我们得到的是带有深度感知的立体视觉, 以及低分辨率相机。请记住, 如果没有输入系统, 我们甚至可以得到此结果。如果我们只是运行此文件(在stage_ros / world文件夹中):

rosrun stage_ros stageros willow-four-erratics-multisensor.world

并添加名为/ robot_0 / cmd_vel的主题的Robot Steering插件, 我们将获得相同的结果, 并且控件位于屏幕上。

将结果应用于实际系统

许多硬件对ROS都有完全支持, 通常由第三方志愿者提供。许多机器人平台都具有生成此类消息的驱动程序, 而ROS的节点则带有网络摄像头并发布图像供稿。

尽管最后的结果是对我们要实现的目标的仿真, 但可以通过以下修改来实现相同目标:

  • 在机器人的机载计算机上安装ROS
  • 为车载计算机创建一个启动文件, 该启动文件将ROS连接到底层平台以及所有高级传感器(如相机, 激光测距仪等)。所需的节点可能已经存在, 或者可以通过在一侧创建ROS的发布者/订阅者, 在另一侧创建用于串行通信的驱动程序来实现
  • 在启动时运行启动文件
  • 在远程计算机上, 将export ROS_MASTER_URI = http:// <robot_hostname>:11311 /添加到bash启动中, 从而使远程计算机在给定的主机名和端口上查找roscore
  • 启动rqt和/或任何脚本来监视和控制机器人

这实际上归结为只是在远程设备上导出适当的环境变量, 其余部分自行处理。在计算机群集上运行ROS仅需要为每台计算机完成一个步骤。

总结

我们已经展示了如何通过很少的编码就能拥有一个复杂的变量系统, 你可以一时兴起来操纵它们。简单的发布者/订阅者系统使你可以快速开发在计算机集群中处理数据的软件管道, 而不必担心某些元素的底层实现。

尽管我们使用了简单的模拟器, 但像凉亭(也包含在完整的台式机版本中)这样的更复杂的模拟器中, 你可以使用物理条件和复杂的传感器来创建3D世界, 并可以在开发之前就获得最终结果和产品的体验。

这篇介绍是非常基础的介绍, 但是希望你对使用这个通用框架更加感兴趣。

赞(0)
未经允许不得转载:srcmini » 机器人操作系统简介:最终的机器人应用框架

评论 抢沙发

评论前必须登录!