本文共 8876 字,大约阅读时间需要 29 分钟。
ROS系统是起源于2007年斯坦福大学人工智能实验室的项目与机器人技术公司Willow Garage的个人机器人项目(Personal Robots Program)之间的合作,2008年之后就由Willow Garage来进行推动。已经有四年多的时间了 (视频)。随着PR2那些不可思议的表现,譬如叠衣服,插插座,做早饭,ROS也得到越来越多的关注。Willow Garage公司也表示希望借助开源的力量使PR2变成“全能”机器人。
ROS是开源的,是用于机器人的一种后操作系统,或者说次级操作系统。它提供类似操作系统所提供的功能,包含硬件抽象描述、底层驱动程序管理、共用功能的执行、程序间的消息传递、程序发行包管理,它也提供一些工具程序和库用于获取、建立、编写和运行多机整合的程序。
在文件系统中很容易识别package和stack:
描述标签
1.首先更新描述标签:
The beginner_tutorials package
将描述信息修改为任何你喜欢的内容,但是按照约定第一句话应该简短一些,因为它覆盖了程序包的范围。
如果用一句话难以描述完全那就需要换行了。
2.维护者标签
接下来是维护者标签:
7 8 9 10user
这是package.xml中要求填写的一个重要标签,因为它能够让其他人联系到程序包的相关人员。
至少需要填写一个维护者名称,但如果有需要的话你可以添加多个。除了在标签里面填写维护者的名称外,还应该在标签的email属性中填写邮箱地址:
7Your Name
3.许可标签
再接下来是许可标签,同样的也需要:
12 13 14 15TODO
你应该选择一种许可协议并将它填写到这里。
一些常见的开源许可协议有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 38catkin 39roscpp 40rospy 41std_msgs 除了catkin中默认提供的buildtool_depend,所有我们列出的依赖包都已经被添加到build_depend标签中。
在本例中,因为在编译和运行时我们需要用到所有指定的依赖包,因此还需要将每一个依赖包分别添加到run_depend标签中:
12catkin 13 14roscpp 15rospy 16std_msgs 17 18roscpp 19rospy 20std_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程序包必须符合以下要求:
rospack和rosstack命令都包含于rospack package中.
两个命令用于获取packages 和stacks的信息. 教程中我们只提及命令的find的参数,作用是返回相应package或者stack的目录路径. 用法:$ rospack find [package_name]$ rosstack find [stack_name]
例如:
$ rospack find roscpp
roscd包含于 rosbash package中.
1.该命令用于改变当前目录到指定的package或者stack的目录(cd). 用法:$ roscd [locationname[/subdir]]
例如:
$ roscd roscpp
2.roscd也能够直接进入一个 package 或 stack的子目录中.
$ roscd roscpp/include
一旦安装了所需的系统依赖项,我们就可以开始编译刚才创建的程序包了。
注意: 如果你是通过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 # (可选)
Nodes:节点,一个节点即为一个可执行文件,它可以通过ROS与其它节点进行通信。
roscore是你在运行所有ROS程序前首先要运行的命令。
$ roscore
rosnode显示当前运行的ROS节点信息。
注意: 当打开一个新的终端时,你的运行环境会复位,同时你的~/.bashrc文件会复原。
如果你在运行类似于rosnode的指令时出现一些问题 也许你需要添加一些环境设置文件到你的~/.bashrc或者手动重新配置他们。
$ rosnode list
rosnode info命令返回的是关于一个特定节点的信息。
$ rosnode info /rosout
rosrun允许你使用包名直接运行一个包内的节点(而不需要知道这个包的路径)。
$ rosrun [package_name] [node_name]
例如:
$ rosrun turtlesim turtlesim_node
ROS中有四种通信方式:Topic(话题)、Service(服务)、Parameter Serivce(参数服务器)、Actionlib(动作库)。
所谓通信,ros中每个程序包是一个node(节点),通信就是节点与节点间的数据传输。进入之前创建的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
在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
有4个主要文件夹
mkdir catkin_wscd catkin_wsmkdir src
编译不在src下,要回到catkin_ws下
catkin_make
编译后如果没有产生install这个空间
catkin_make install
在创建代码的时候一定要创建一个功能包。功能包放置在src目录下功能包是放置ROS源码的最小单元所有源码必须全部放在功能包里面,不能直接放在src下面去编译,这是不允许的同一个工作空间下,不允许存在同名功能包。不同工作空间下,允许存在同名功能包
catkin_create_pkg 包名 依赖
编译功能包回到catkin_ws中
catkin_make
编译成功之后,如果想运行功能包里的某个程序的话,要先设置一下工作空间的环境变量
source devel/setup.bash
参考文档:
转载地址:http://qwhzi.baihongyu.com/