博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一文搞定ros
阅读量:3960 次
发布时间:2019-05-24

本文共 8876 字,大约阅读时间需要 29 分钟。

一.简介

ROS系统是起源于2007年斯坦福大学人工智能实验室的项目与机器人技术公司Willow Garage的个人机器人项目(Personal Robots Program)之间的合作,2008年之后就由Willow Garage来进行推动。已经有四年多的时间了 (视频)。随着PR2那些不可思议的表现,譬如叠衣服,插插座,做早饭,ROS也得到越来越多的关注。Willow Garage公司也表示希望借助开源的力量使PR2变成“全能”机器人。

ROS是开源的,是用于机器人的一种后操作系统,或者说次级操作系统。它提供类似操作系统所提供的功能,包含硬件抽象描述、底层驱动程序管理、共用功能的执行、程序间的消息传递、程序发行包管理,它也提供一些工具程序和库用于获取、建立、编写和运行多机整合的程序。

二.ROS文件系统介绍

  • Packages: Package是ROS系统中最底层最基本的组织,里面存放各种文件:库、工具、可执行文件等.
  • Manifest: 一个package描述xml文件,定义package之间的依赖关系.
  • Stacks: package的集合,比package这个概念高一级别
  • Stack Manifest: 作用类似package manifest文件,但是它是针对stack的.

在文件系统中很容易识别package和stack:

  • package是一个包含 manifest.xml 文件的目录.
  • stack是一个包含 stack.xml 文件的目录.

在这里插入图片描述

package.xml解析

描述标签

1.首先更新描述标签:

The beginner_tutorials package

将描述信息修改为任何你喜欢的内容,但是按照约定第一句话应该简短一些,因为它覆盖了程序包的范围。

如果用一句话难以描述完全那就需要换行了。

2.维护者标签

接下来是维护者标签:

7   
8
9
10
user

这是package.xml中要求填写的一个重要标签,因为它能够让其他人联系到程序包的相关人员。

至少需要填写一个维护者名称,但如果有需要的话你可以添加多个。

除了在标签里面填写维护者的名称外,还应该在标签的email属性中填写邮箱地址:

7   
Your Name

3.许可标签

再接下来是许可标签,同样的也需要:

12   
13
14
15
TODO

你应该选择一种许可协议并将它填写到这里。

一些常见的开源许可协议有BSD、MIT、Boost Software License、GPLv2、GPLv3、LGPLv2.1和LGPLv3。

你可以在Open Source Initiative中阅读其中的若干个许可协议的相关信息。

4.依赖项标签

接下来的标签用来描述程序包的各种依赖项,这些依赖项分为:

build_dependbuildtool_dependrun_dependtest_depend

关于这些标签的更详细介绍请参考Catkin Dependencies相关的文档。

在之前的操作中,因为我们将std_msgs、roscpp、rospy作为catkin_create_pkg命令的参数,所以生成的依赖项看起来如下:

27   
28
29
30
31
32
33
34
35
36
37
38
catkin
39
roscpp
40
rospy
41
std_msgs
除了catkin中默认提供的buildtool_depend,所有我们列出的依赖包都已经被添加到build_depend标签中。

在本例中,因为在编译和运行时我们需要用到所有指定的依赖包,因此还需要将每一个依赖包分别添加到run_depend标签中:

12   
catkin
13 14
roscpp
15
rospy
16
std_msgs
17 18
roscpp
19
rospy
20
std_msgs
# 三.创建ROS程序包## 创建一个catkin程序包

首先切换到之前通过创建catkin工作空间教程创建的catkin工作空间中的src目录下:

$ cd ~/catkin_ws/src

现在使用catkin_create_pkg命令来创建一个名为’beginner_tutorials’的新程序包

这个程序包依赖于std_msgs、roscpp和rospy:

$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp

catkin程序包组成

一个程序包要想称为catkin程序包必须符合以下要求:

  1. 该程序包必须包含catkin compliant package.xml文件,这个package.xml文件提供有关程序包的元信息。
  2. 程序包必须包含一个catkin 版本的CMakeLists.txt文件,而Catkin metapackages中必须包含一个对CMakeList.txt文件的引用。
  3. 每个目录下只能有一个程序包。这意味着在同一个目录下不能有嵌套的或者多个程序包存在。

使用rospack和rosstack

rospack和rosstack命令都包含于rospack package中.

两个命令用于获取packages 和stacks的信息.
教程中我们只提及命令的find的参数,作用是返回相应package或者stack的目录路径.
用法:

$ rospack find [package_name]$ rosstack find [stack_name]

例如:

$ rospack find roscpp

使用roscd

roscd包含于 rosbash package中.

1.该命令用于改变当前目录到指定的package或者stack的目录(cd).
用法:

$ roscd [locationname[/subdir]]

例如:

$ roscd roscpp

2.roscd也能够直接进入一个 package 或 stack的子目录中.

$ roscd roscpp/include

编译ROS程序包

一旦安装了所需的系统依赖项,我们就可以开始编译刚才创建的程序包了。

注意: 如果你是通过apt或者其它软件包管理工具来安装ROS的,那么系统已经默认安装好所有依赖项。
记得事先source你的环境配置(setup)文件,在Ubuntu中的操作指令如下:

$ source /opt/ros/groovy/setup.bash

CMake标准工作流程主要可以分为以下几个步骤:

# 在一个CMake项目里$ mkdir build$ cd build$ cmake ..$ make$ make install  # (可选)

多个catkin项目可以放在工作空间中一起编译,工作流程如下:

# In a catkin workspace$ catkin_make$ catkin_make install  # (可选)

ROS节点

Nodes:节点,一个节点即为一个可执行文件,它可以通过ROS与其它节点进行通信。

  • 一个节点其实只不过是ROS程序包中的一个可执行文件。
  • ROS节点可以使用ROS客户库与其他节点通信。
  • 节点可以发布或接收一个话题。
  • 节点也可以提供或使用某种服务。

roscore是你在运行所有ROS程序前首先要运行的命令。

$ roscore

rosnode

rosnode显示当前运行的ROS节点信息。

注意: 当打开一个新的终端时,你的运行环境会复位,同时你的~/.bashrc文件会复原。

如果你在运行类似于rosnode的指令时出现一些问题 也许你需要添加一些环境设置文件到你的~/.bashrc或者手动重新配置他们。

  • rosnode list指令列出活跃的节点:
$ rosnode list

rosnode info命令返回的是关于一个特定节点的信息。

$ rosnode info /rosout

rosrun允许你使用包名直接运行一个包内的节点(而不需要知道这个包的路径)。

$ rosrun [package_name] [node_name]

例如:

$ rosrun turtlesim turtlesim_node

ROS话题与服务

ROS中有四种通信方式:Topic(话题)、Service(服务)、Parameter Serivce(参数服务器)、Actionlib(动作库)。

所谓通信,ros中每个程序包是一个node(节点),通信就是节点与节点间的数据传输。

对比

在这里插入图片描述

python编写简单的消息发布器和订阅器

编写发布节点

  • “节点”是ROS术语,它连接到ROS网络的可执行文件。在这里,我们将创建发布器(“talker”)节点不断广播消息。

进入之前创建的beginner_tutorials包

$ roscd beginner_tutorials

首先创建scripts目录存放Python代码:

$ mkdir scripts$ cd scripts

下载例子脚本talker.py到scripts目录,并修改权限为可执行:

$ wget https://raw.github.com/ros/ros_tutorials/kinetic-devel/rospy_tutorials/001_talker_listener/talker.py$ chmod +x talker.py

浏览和编辑:

$ rosed beginner_tutorials talker.py

代码如下:

内容如下:#!/usr/bin/env python# license removed for brevityimport rospyfrom std_msgs.msg import Stringdef talker():    pub = rospy.Publisher('chatter', String, queue_size=10)    rospy.init_node('talker', anonymous=True)#定义talker接口,pub = rospy.Publisher("chatter", String, queue_size=10)表示节点发布chatter话题,使用String字符类型,实际上就是类std_msgs.msg.String。queue_size表示队列的大小(适合hydro以后版本),如果队列消息处理不够快,就会丢弃旧的消息。#rospy.init_node(NAME),初始化节点,开始跟ROS master通讯。    rate = rospy.Rate(10) # 10hz#创建Rate对象,与sleep()函数结合使用,控制话题消息的发布频率。#10hz表示每秒发布10次。    while not rospy.is_shutdown():#rospy.is_shutdown()返回false就会退出        hello_str = "hello world %s" % rospy.get_time()        rospy.loginfo(hello_str)        pub.publish(hello_str)        rate.sleep()#程序执行pub.publish(String(str)),在chatter话题发布String消息#rospy.sleep()通过睡眠来,保持消息发送频率#rospy.loginfo(str)函数在屏幕输出调试信息,同时写入到节点日志文件和rosout节点if __name__ == '__main__':    try:        talker()    except rospy.ROSInterruptException:        pass

编写订阅节点

下载listener.py到scripts目录

$ roscd beginner_tutorials/scripts/$ wget https://raw.github.com/ros/ros_tutorials/kinetic-devel/rospy_tutorials/001_talker_listener/listener.py

代码:

#!/usr/bin/env pythonimport rospyfrom std_msgs.msg import Stringdef callback(data):    rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)    def listener():    # In ROS, nodes are uniquely named. If two nodes with the same    # node are launched, the previous one is kicked off. The    # anonymous=True flag means that rospy will choose a unique    # name for our 'listener' node so that multiple listeners can    # run simultaneously.    rospy.init_node('listener', anonymous=True)    rospy.Subscriber("chatter", String, callback)    # spin() simply keeps python from exiting until this node is stopped    rospy.spin()if __name__ == '__main__':    listener()

不要忘记增加可执行权限:

$ chmod +x listener.py

python编写简单的Service和Clien

编写服务端节点

在beginner_tutorials包创建scripts/add_two_ints_server.py文件

#!/usr/bin/env pythonfrom beginner_tutorials.srv import *import rospydef handle_add_two_ints(req):    print "Returning [%s + %s = %s]"%(req.a, req.b, (req.a + req.b))    return AddTwoIntsResponse(req.a + req.b)def add_two_ints_server():    rospy.init_node('add_two_ints_server')    s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)    print "Ready to add two ints."    rospy.spin()if __name__ == "__main__":    add_two_ints_server()

文件更改为可执行权限:

chmod +x scripts/add_two_ints_server.py

代码解释init_node()初始化节点,并声明服务:

s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)

声明一个名为add_two_ints新服务,使用AddTwoInts服务类型。

所有请求传递到handle_add_two_ints函数处理,并传递实例AddTwoIntsRequest和返回AddTwoIntsResponse实例。
rospy.spin()会保持代码不退出,直到服务关闭

编写客户端节点

#!/usr/bin/env pythonimport sysimport rospyfrom beginner_tutorials.srv import *def add_two_ints_client(x, y):    rospy.wait_for_service('add_two_ints')    try:        add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)        resp1 = add_two_ints(x, y)        return resp1.sum    except rospy.ServiceException, e:        print "Service call failed: %s"%edef usage():    return "%s [x y]"%sys.argv[0]if __name__ == "__main__":    if len(sys.argv) == 3:        x = int(sys.argv[1])        y = int(sys.argv[2])    else:        print usage()        sys.exit(1)    print "Requesting %s+%s"%(x, y)    print "%s + %s = %s"%(x, y, add_two_ints_client(x, y))

设置为可执行:

$ chmod +x scripts/add_two_ints_client.py

代码解释客户端调用服务更简单,甚至可以不调用init_node()来初始化节点

rospy.wait_for_service('add_two_ints')

这是便利的参数阻塞直到服务名为add_two_ints的服务生效。

下一步创建实例来调用服务:

add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)

我们使用实例就如平常的函数一样:

resp1 = add_two_ints(x, y)return resp1.sum

因为我们已声明服务类型AddTwoInts,它生成AddTwoIntsRequest对象。返回值是一个AddTwoIntsResponse对象。如果调用失败,rospy.ServiceException会抛出异常,因此你应该建立适当的try/except代码块

构建节点我们使用CMake作为构建系统,在Python也同样使用作为构建系统,它能确保之前创建的消息和服务能自动生成Python代码。

进入catkin 工作空间,运行catkin_make

$ cd ~/catkin_ws$ catkin_make

测试新终端,运行:

$ cd ~/catkin_ws$ . devel/setup.bash$ rosrun beginner_tutorials add_two_ints_server.py

另开新终端,运行:

$ cd ~/catkin_ws$ . devel/setup.bash$ rosrun beginner_tutorials add_two_ints_client.py

工作空间 workspace

有4个主要文件夹

  • src:代码空间(Source Space)
  • build:编译空间(Build Space)
  • devel:开发空间(Development Space)
  • install:安装空间(Install Space)

创建工作空间

mkdir catkin_wscd catkin_wsmkdir src

编译工作空间

编译不在src下,要回到catkin_ws下

catkin_make

编译后如果没有产生install这个空间

catkin_make install

创建功能包

在创建代码的时候一定要创建一个功能包。功能包放置在src目录下功能包是放置ROS源码的最小单元所有源码必须全部放在功能包里面,不能直接放在src下面去编译,这是不允许的同一个工作空间下,不允许存在同名功能包。不同工作空间下,允许存在同名功能包

catkin_create_pkg 包名 依赖
  • std_msgs是标准的消息结构
  • rospy是python依赖
  • roscpp是c++依赖

编译功能包回到catkin_ws中

catkin_make

编译成功之后,如果想运行功能包里的某个程序的话,要先设置一下工作空间的环境变量

source devel/setup.bash

参考文档:

转载地址:http://qwhzi.baihongyu.com/

你可能感兴趣的文章
华为路由器交换机配置命令
查看>>
docker下运行kalilinux并配置ssh访问
查看>>
使用 Docker 容器应该避免的 10 个事情
查看>>
postgres基本操作(个人总结版)
查看>>
求数组中最长递增子序列
查看>>
用C++设计一个不能被继承的类
查看>>
linux core文件机制
查看>>
私有继承中的派生类对象与基类对象间的转换
查看>>
5.7 观察者模式observer(行为模式)
查看>>
建造者模式Builder(创建模式)
查看>>
Linux文件系统目录结构的详细解说(一)
查看>>
TIME_WAIT状态的意义
查看>>
千万不要把 bool 设计成函数参数
查看>>
linux文件属性及权限详解
查看>>
Find 命令使用详解
查看>>
Ext4,Ext3的特点和区别
查看>>
Linux文件系统目录结构的详细解说(二)
查看>>
Linux umount 报 device is busy 的处理方法
查看>>
一个大小为n的数组,里面的数都属于范围[0, n-1],有不确定的重复元素,找到至少一个重复元素,要求O(1)空间和O(n)时间。
查看>>
提供机制而不是策略
查看>>