作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Adnan Ademovic
Verified Expert in Engineering
9 Years of Experience

Adnan拥有桌面、嵌入式和分布式系统方面的经验. 他对c++、Python和其他语言进行了广泛的研究.

Read More
Share

The Robot Operating System (ROS)并不是一个实际的操作系统, 而是在异构计算机集群上提供操作系统功能的框架和一组工具. 它的用途不仅限于机器人, 但是提供的大多数工具都集中在外围硬件上.

ROS 分为2000多个包,每个包提供专门的功能. 连接到框架的工具的数量可能是它最大的力量.

我为什么要使用机器人操作系统?

ROS提供了硬件抽象的功能, device drivers, 多台机器上进程之间的通信, 测试和可视化工具, and much more.

ROS的关键特性是软件的运行方式和通信方式, 允许您在不知道某些硬件如何工作的情况下设计复杂的软件. ROS提供了一种将进程(节点)网络与中心集线器连接起来的方法. 节点可以在多个设备上运行,它们以各种方式连接到该集线器.

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

开发人员可以通过连接针对小问题的现有解决方案来组装一个复杂的系统. 系统的实现方式,它允许我们:

  • 动态替换具有类似接口的组件, 消除了因各种变化而停止系统的需要

  • 将多个组件的输出多路复用为另一个组件的一个输入, 允许并行解决各种问题

  • 通过实现消息传递系统的适当连接器来连接用各种编程语言制作的组件, 通过连接来自不同开发人员的现有模块,使开发软件变得容易

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

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

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

ROS是由它自己的社区制作的,为它的社区服务. After several years, 这就产生了大量易于集成的可重用包, 多亏了系统的架构.

其他方法包括 MRPT, CARMEN, LCM, Player, Microsoft RDS 还有一些提供了其中的一些功能,但不是全部. Most of the time, 设计缺陷是语言支持的限制, 进程间未优化的通信, 或者缺乏对各种设备的支持,这可以说是最难解决的问题.

我们要建设什么?

因为我们关注的是框架,而不是特定问题的实际算法, 给定的问题相当简单. 我们的目标是为机载计算机开发软件,使我们能够远程控制和监视机器人, 通过Wi-Fi连接到我们, 通过使用我们电脑上的游戏手柄和安装在机器人上的摄像头.

First of all, 我们将制作一个简单的程序连接到一个简单的模拟程序, 只是为了展示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 on desktop. 所有支持的版本和平台的流程都可以在官方网站上找到 website. 还可以使用安装了ROS的虚拟机.

安装依赖于平台(并且大多数平台都提供了包), 但是所有平台的工作空间配置是相同的.

Installation on 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'
执行命令apt-key adv——keyserver hkp://池.sks-keyservers.net—recv-key 0xB01FA116
sudo apt-get update

在那之后,你就有了Ubuntu版本可用的所有ROS版本的所有托管包. For example, Ubuntu 14.04 supports indigo and jade.

在桌面上安装基础软件包有以下三种选择:

  • 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 by running:

sudo apt-get install ros-indigo-

在最终名称中,下划线被连字符取代,因此 stage_ros will be in the package ros-indigo-stage-ros.

下一步是初始化 rosdep. ROS中的包可以声明它们所依赖的组件. rosdep 允许您编译这些包,而不需要太多的手动依赖处理. To initialize it, call:

sudo rosdep init
rosdep update

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

Echo“source /opt/ros/indigo/setup . conf”.bash" >> ~/.bashrc
source ~/.bashrc

一些包通过 rosinstall,它作为一个包提供,并通过 Sudo apt-get install python-rosinstall.

这是Ubuntu安装的结束. 下面是安装工作区的简短介绍.

Configuration

Ever since Groovy Galapagos, ROS工作空间通过 catkin. 我们需要为我们托管的所有包定义一个目录. 在目录中创建一个 src folder, and call catkin_init_workspace form inside it. 这将创建到当前来源的ROS版本的各种符号链接. 下一步是将这个工作空间也添加到环境变量中.

来执行整个工作空间配置, 选择一个空目录,执行如下命令:

mkdir src
cd src
catkin_init_workspace
cd ..
catkin_make
Echo“source $(pwd)/dev /setup . exe”.bash" >> ~/.bashrc
source ~/.bashrc

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

熟悉工具

创建任何代码都是一个巨大的飞跃. 让我们首先熟悉幕后运行的一些系统. 我们的第一步将是运行基本GUI并查看它生成的消息.

要在ROS中运行任何东西,需要启动一个核心进程. 这就像打开一个新的终端窗口,然后输入:

roscore

在你的整个联网设备中, roscore 只需要启动一次, 在将承载用于通信调度的中央集线器的设备上.

The main role of roscore 是告诉节点它们应该连接到哪些其他节点, 以何种方式(无论是通过网络端口还是共享内存). 目标是允许节点只关心它们想知道的数据, 而不是他们想要连接到哪个节点, 同时最大限度地减少执行所有通信所需的时间和带宽.

rqt

After running roscore,我们可以启动ROS的主要GUI工具: rqt. 我们看到的是非常平淡无奇的——一个空窗口. rqt 托管各种各样的插件,可以配置为任何可视化配置和任意数量的预定义视图.

标题为“默认- rqt”的空GUI窗口的截图,和菜单文件, Plugins, Running, Perspectives, and Help.

首先,让我们运行 Robot Steering 插件,通过选择它 Plugins > Robot Tools > Robot Steering. 我们得到的是两个滑块,分别代表我们希望机器人拥有的线性和旋转运动. 在插件的顶部,我们可以看到一个文本框 /cmd_vel in it. 我们可以把它重命名为任何我们想要的. 它表示转向要向其发布的主题的名称. 终端工具是查看后台运行情况的最佳场所.

屏幕截图显示与之前相同的窗口, 而是有一个机器人驾驶界面,有D, reload, help, minimize, circle, and X icons---within it. The first line has a text box with "/cmd_vel" in it and a Stop button. 下面是一个垂直居中的垂直滑块,中间设置为0.0 m/s, 左边有按钮表示+, 0, and -, 上面和下面的数字控制是1,00 and -1,00.  下面是一个类似的水平滑块,测量单位为rad/s, set to 0 in the middle, 把数字控制在3,00 on the left and -3,00 on the right.

Terminal Tools

ROS有几个强大的工具用于检查系统中正在发生的事情. 我们要介绍的第一个工具是 rostopic. 它允许我们检查节点可以订阅和发布的主题. Running rostopic list will yield:

/cmd_vel
/rosout
/rosout_agg

后两个主题一直在运行,并且与中央ROS系统相关. The /cmd_vel 主题正在由我们的舵手出版. 在转向中重命名主题也会在这里重命名它. 现在,我们感兴趣的是主题内部发生了什么. Running rostopic echo /cmd_vel 不会显示任何内容(除非你修改了滑块). 该进程一直运行,直到我们取消它. 现在让我们将垂直滑块移动到20米/秒. 从回声中,我们可以看到以下内容一遍又一遍地重复:

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赫兹. 我的无线网很慢,这样的话题我能讲多少呢? rostopic bw /cmd_vel 平均检测480b /s.

现在一切都很好,但是我们讨论了消息类型. 这些数据对人类是有益的, 但是应用程序需要原始数据, 并且需要知道消息类型,以便能够解释数据. 类型可以用 rostopic type /cmd_vel, telling us it’s a geometry_msgs/Twist. 所有不带任何参数调用的ROS终端工具都会返回一个标准的帮助消息.

ROS Wiki很好,可以对这个字符串进行web搜索,结果是Wiki解释它包含什么以及它是如何结构的. 但我们不必依赖它. rosmsg 是消息类型的通用工具吗. Running rosmsg show geometry_msgs/Twist will return:

geometry_msgs / Vector3线性
  float64 x
  float64 y
  float64 z
geometry_msgs / Vector3角
  float64 x
  float64 y
  float64 z

该信息由两个三维矢量组成,分别表示三维空间中的线速度和角速度.

如果我们想知道一个节点连接到什么主题, rosnode info 会给我们节点的详细数据吗. The tools rostopic, rosmsg and rosnode 检查原始ROS功能的主要工具是什么. ROS有更多的GUI和终端工具,但这些超出了我们的介绍范围.

运行ROS节点的主要工具有 rusrun and roslaunch. rosrun can run nodes via rosrun , and roslaunch 基于启动文件运行节点, 因为它们是ROS自动化中最复杂的元素,所以我们对它们的熟悉程度很小.

我们可以关闭运行过的所有程序,开始编写第一个代码. For future reference, 不用说,运行任何与ROS相关的操作都需要的活动实例 roscore. 您遇到的许多问题可以通过关闭终端窗口来解决 roscore 在里面运行,然后打开一个新的重新启动它. 这将更新所有需要重新加载的依赖项,包括 bash and in roscore.

创建手柄远程操作

我们的第一个目标是模仿 Robot Steering 通过创建一个节点来发布 geometry_msgs/Twist data to /cmd_vel based on gamepad input. Our first stop is the joy package.

The joy Package

The joy 包为操纵杆和手柄提供通用的ROS驱动程序. 它不包含在默认安装中,因此需要通过以下方式安装:

Sudo apt-get install ros-indigo-joy

安装完成后,就可以运行了 rosrun joy joy_node. 这将把我们连接到默认的操纵杆或手柄. Running rostopic list 显示我们有一个主题叫做 /joy. Listening to it via 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]
按钮:[0,0,0,0,0,0,0,0,0]

现在可以忽略头文件. Other than that, we have axes and buttons很好地解释了它们所代表的含义. 移动坐标轴和按下控制器上的按钮将导致这些数字发生变化. 使用我们的工具,我们可以确定消息类型是 sensor_msgs/Joy and the format is:

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

创造我们的远程操作

编写代码的第一步是创建一个包. Within the src 工作区的文件夹,运行:

Catkin_create_pkg toptal_tutorial rospy joy geometry_msgs sensor_msgs

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

We now have a toptal_tutorial folder. 在该文件夹中创建一个 scripts 文件夹,存放我们所有的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.订阅者('joy', joy, joy_callback)

    while not rospy.is_shutdown():
        pass


如果__name__ == '__main__':
    main()

We’ll also need to set chmod +x teleop.py 这样,脚本就可以运行了. Running rosrun joy joy_node in one terminal and Rosrun toptal_tutorial teleop.py 在另一个将导致在 teleop.py的终端输出充满了Joy消息.

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

首先,我们导入rospy,它托管用于与ROS框架交互的库. 定义消息的每个包都有 msg 包含消息定义的子包. We are importing Joy to handle the input. 不需要导入嵌入的消息类型(如 Header from std_msgs.msg that is in the Joy 消息),除非我们想明确提及它们.

第一步是初始化具有特定名称的节点(在本例中,我们称之为“teleop”)。. 然后,我们创建一个订阅类型的“joy”主题的订阅者 sensor_msgs.msg.Joy的方法来处理每条消息 joy_callback function. 回调函数接收一个参数,即来自消息的数据. 访问数据的成员很简单. 如果我们想要打印第一个轴的状态,如果我们调用消息类型,我们将调用 print data.axes[0],它将是一个浮点数. 末端的循环循环,直到ROS被关闭.

我们的下一步就是以某种方式处理我们的数据. 我们应该创建一个根据输入变化的Twist消息, 然后我们会把它发布到 cmd_vel topic.

#!/usr/bin/env python

import rospy
from sensor_msgs.msg import Joy
from geometry_msgs.msg import Twist  # new
从functools导入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.发布者('cmd_vel', Twist, queue_size=1000) # new
    rospy.订阅者('joy', joy, partial(joy_callback, pub)) #已修改

    while not rospy.is_shutdown():
        pass


如果__name__ == '__main__':
    main()

First, we add the Twist 消息,并增加了通过 functools.partial. We create a publisher, pub, that publishes to cmd_vel a message of type Twist. 我们将发布者绑定到回调, 并让它在每个输入上发布一个Twist消息,其中速度由前两个轴表示. 这段代码完成了我们所期望的工作,我们可以通过 rostopic echo /cmd_vel.

We still have one issue. The /joy Topic可以以很高的速度发布. If we monitor the rostopic hz /cmd_vel 转动模拟摇杆,我们可以看到大量的信息. 这不仅导致了大量的交流, 但是接收这些消息的进程必须处理每一个消息. 没有必要如此频繁地公布这些数据, 我们最好以10赫兹的稳定速率发布. 我们可以用下面的代码来完成.

#!/usr/bin/env python

import rospy
from sensor_msgs.msg import Joy
from geometry_msgs.msg import Twist
从functools导入partial


Def joy_callback(cmd_vel, data): # modified
    cmd_vel.linear.x = data.axes[1]
    cmd_vel.angular.z = data.axes[0]
    # moved pub.将(cmd_vel)发布到主循环


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

    cmd_vel = Twist() # new

    pub = rospy.发布者('cmd_vel', Twist, queue_size=1000)
    rospy.订阅者('joy', joy, partial(joy_callback, cmd_vel)) #已修改

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


如果__name__ == '__main__':
    main()

我们修改了回调来接收可变的 Twist 对象,并在循环中修改它. The sleep function from rospy.Rate 保持稳定的输出频率.

最后的代码将导致 /cmd_vel 主题得到速度命令在10赫兹,模仿输出 Robot Steering rqt plugin.

运行模拟系统

Simulating the World

我们的第一个目标是创建一个环境,在其中我们可以模拟我们想要实现的场景. The node stageros within the stage_ros 软件包允许我们在通过图像定义的2D阶段内运行一个机器人. 中描述了一个完整的语法 stage_ros package 获取世界文件以及如何生成它们. 这相当简单,但超出了我们的范围. 幸运的是,该软件包附带了几个演示世界. 首先,让我们运行命令进入files目录:

roscd stage_ros
cd world

文件夹中有几个文件. Let’s run one.

蔷薇stage_ros stageros柳树飘忽不定.world

这就产生了几个主题. 它们的含义也随包一起记录. 重要的是,它已经做到了 cmd_vel.

标题为Stage: willow-飘忽的窗口截图.world. The status label reads, "0m 20s 300msec (1.0)." There's a scale at the right running from 18 at the bottom to 30 at the top, in increments of one. 主图像是一个棋盘,主要的黑点和线散布在整个图像中, 加上中间的一个蓝色方块, 还有一个稍微大一点的红色方块距离它有几个棋盘格.

在显示的舞台中,有一个蓝色的方块,代表你所控制的机器人. 通过使用我们的代码或 Robot Steering,我们可以控制这个机器人. Try it out.

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

let’s create a launch 文件夹,并在其中创建一个名为 teleop.launch. 最终的文件夹结构应该是这样的:

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

Within the teleop.launch 文件中,我们将定义一组节点及其相互连接.


  
  
  
    
    
  

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

有两个部分的图表,模拟世界和/robot_0. 后者具有以/robot_0/开头的框和气泡. 前者有一个标记为/模拟世界的气泡与后者的cmd_vel气泡相连, 哪个连接到joy_convert框, which joins a joy box, 哪个加入了joy_input泡沫. / simulation -world也连接到/robot-0中的四个盒子, namely image_1, depth_0, depth_1, and image_0.

To run launchfiles, no roscore is needed. In a sense, roscore 只是一个特殊的启动文件,什么都不做. If a roscore 是丢失,只有第一个启动文件启动将运行一个核心,而其余的将连接到它. 现在,我们使用:

rolaunch toptal_tutorial teleop.launch

If all is correct, 这将产生一个包含4个机器人的模拟器, 其中一个是用手柄或操纵杆控制的. 这个世界比之前的世界要复杂得多. 四个机器人中的每一个都有:

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

We replace with 0, 1, 2, or 3. 这就引出了我们的最后一个话题.

Viewing Our Data with rqt

我们没有深入研究 rqt,但它是查看更复杂数据的完美工具. 你可以尝试所有的主题,但我们将专注于 image_0, image_1, depth_0, and depth_1 topics.

Let’s launch rqt 并删除任何打开的插件. 现在我们将打开4个图像可视化器(Plugins > Visualization > Image View),并将它们放置在2x2的网格中. 最后,在每个视图的左上角,让我们从四个指定的主题中选择一个 robot_0.

显示机器人转向界面的截图, 使用前面提到的文本框和滑块, 但是文本框里的"/robot_0/cmd_vel". 右边是四个图像视图. 最上面的两个(image_0和image_1)在3D中显示了两个蓝框和一个红框. 底部两个(depth_0和depth_1)显示的图像与顶部相似, but in greyscale, 尤其是前景色的盒子比背景中的物体呈现更深的灰色.

我们得到的是具有深度感知的立体视觉,还有低分辨率的摄像头. 记住,我们甚至可以在没有输入系统的情况下得到这个结果. 如果我们运行这个(在 stage_ros/world folder):

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

and add the Robot Steering 插件,主题名为 /robot_0/cmd_vel,如果控件位于屏幕滑块上,我们也会得到相同的结果.

将结果应用于实际系统

很多硬件都完全支持ROS,通常由第三方志愿者提供. 许多机器人平台都有生成这类信息的驱动程序, ROS的节点可以接收网络摄像头并发布图像馈送.

而最后的结果是我们想要达到的模拟, 同样可以通过以下修改来实现:

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

这实际上就是在远程设备上导出适当的环境变量, 剩下的就自己搞定了. 在计算机集群上运行ROS只需要为每台机器执行这一步.

Conclusion

We have demonstrated how, with very little coding, 你可以有一个复杂的变量系统,你可以随心所欲地操纵它. 简单的发布者/订阅者系统允许您快速开发处理计算机集群中的数据的软件管道, 而不用担心某些元素的底层实现.

虽然我们使用了一个简单的模拟器,但更复杂的模拟器,比如 gazebo (也包含在完整桌面版本中)允许您创建 带有物理和复杂传感器的3D世界,可以让你在产品开发出来之前就体验到最终的结果和产品.

这是一个非常基础的介绍, 但是希望您对使用这个通用框架更感兴趣.

聘请Toptal这方面的专家.
Hire Now
Adnan Ademovic

Adnan Ademovic

Verified Expert in Engineering
9 Years of Experience

萨拉热窝,波斯尼亚和黑塞哥维那

2015年7月20日加入

About the author

Adnan拥有桌面、嵌入式和分布式系统方面的经验. 他对c++、Python和其他语言进行了广泛的研究.

Read More
作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

Toptal Developers

Join the Toptal® community.