ROS-创建功能包和节点
个人博客:http://www.chenjianqu.com/
原文链接:http://www.chenjianqu.com/show-72.html
本文是我学习ROS的笔记,介绍了如何通过命令行从零创建一个功能包:基于roscpp的Service通信和基于rospy的topic通信。
一.基于roscpp的service通信
1.首先,创建一个工作空间
Catkin工作空间是创建、修改、编译catkin软件包的目录。
(base) chenjianqu@chen:~$ cd ros (base) chenjianqu@chen:~/ros$ cd project (base) chenjianqu@chen:~/ros/project$ mkdir -p ws2/src (base) chenjianqu@chen:~/ros/project$ cd ws2 (base) chenjianqu@chen:~/ros/project/ws2$ catkin_make #初始化工作空间
catkin工作空间包括了src、build、devel三个文件夹:
src/: ROS的catkin软件包(源代码包)
build/: catkin(CMake)的缓存信息和中间文件
devel/: 生成的目标文件(包括头文件,动态链接库,静态链接库,可执行文件等)、环境变量
2.创建一个Package
(base) chenjianqu@chen:~/ros/project/ws2$ cd src (base) chenjianqu@chen:~/ros/project/ws2/src$ catkin_create_pkg serve_test std_msgs rospy roscpp
创建一个package需要在catkin_ws/src下,用到catkin_create_pkg命令,用法是:catkin_create_pkg package depends,其中package是包名,depends是依赖的包名,可以依赖多个软件包。上面的命令创建了serve_test软件包,依赖于roscpp rospy std_msgs。
一个package下常见的文件、路径有:
CMakeLists.txt: 定义package的包名、依赖、源文件、目标文件等编译规则,是package不可少的成分
package.xml: 描述package的包名、版本号、作者、依赖等信息,是package不可少的成分
src/: 存放ROS的源代码,包括C++的源码和(.cpp)以及Python的module(.py)
include/: 存放C++源码对应的头文件
scripts/: 存放可执行脚本,例如shell脚本(.sh)、Python脚本(.py)
msg/: 存放自定义格式的消息(.msg)
srv/: 存放自定义格式的服务(.srv)
models/: 存放机器人或仿真场景的3D模型(.sda, .stl, .dae等)
urdf/: 存放机器人的模型描述(.urdf或.xacro)
launch/: 存放launch文件(.launch或.xml)
其中定义package的是CMakeLists.txt和package.xml,这两个文件是package中必不可少的。catkin编译系统在编译前,首先就要解析这两个文件。这两个文件就定义了一个package。 通常ROS文件组织都是按照以上的形式,这是约定俗成的命名习惯,建议遵守。以上路径中,只有CMakeLists.txt和package.xml是必须的,其余路径根据软件包是否需要来决定。
3.创建服务消息文件
(base) chenjianqu@chen:~/ros/project/ws2/src$ ls (base) chenjianqu@chen:~/ros/project/ws2/src$ cd serve_test (base) chenjianqu@chen:~/ros/project/ws2/src/serve_test$ mkdir -p srv (base) chenjianqu@chen:~/ros/project/ws2/src/serve_test$ cd srv(base) chenjianqu@chen:~/ros/project/ws2/src/serve_test/srv$ vim Greeting.srv
在Greeting.srv中写入消息内容:
string name int32 age --- string feedback
srv文件是用来描述服务(service数据类型的,service通信的数据格式定义在*.srv中。它声明了一个服务,包括请求(request)和响应(reply)两部分。
4.修改CMakeLists.txt和package.xml,编译服务消息
(base) chenjianqu@chen:~/ros/project/ws2/src/serve_test/srv$ cd .. (base) chenjianqu@chen:~/ros/project/ws2/src/serve_test$ ls (base) chenjianqu@chen:~/ros/project/ws2/src/serve_test$ vim CMakeLists.txt #修改CMakeLists文件
修改内容如下:
find_package(catkin REQUIRED COMPONENTS roscppstd_msgsmessage_generation #需要添加的地方 ) #catkin在cmake之上新增的命令,指定从哪个消息文件生成 add_service_files(FILES Greeting.srv) #添加这一项 #catkin新增的命令,用于生成消息 #DEPENDENCIES后面指定生成msg需要依赖其他什么消息,由于gps.msg用到了flaot32这种ROS标准消息,因此需要再把std_msgs作为依赖 generate_messages(DEPENDENCIES std_msgs) #添加这一项
(base) chenjianqu@chen:~/ros/project/ws2/src/serve_test$ vim package.xml #修改package.xml文件
修改内容加入:
<build_depend>message_generation</build_depend> #添加这一项 <exec_depend>message_runtime</exec_depend> #添加这一项
最后编译服务消息
(base) chenjianqu@chen:~/ros/project/ws2/src/serve_test$ cd .. (base) chenjianqu@chen:~/ros/project/ws2/src$ cd .. (base) chenjianqu@chen:~/ros/project/ws2$ catkin_make
编译完成之后会在devel路径下生成Greeting.srv对应的头文件,头文件按照C++的语法规则定义了serve_test::Greeting::Request和 serve_test::Greeting::Response类型的数据。
5.编写Server和Client两个节点的源代码
(base) chenjianqu@chen:~/ros/project/ws2$ cd src (base) chenjianqu@chen:~/ros/project/ws2/src$ cd serve_test (base) chenjianqu@chen:~/ros/project/ws2/src/serve_test$ ls (base) chenjianqu@chen:~/ros/project/ws2/src/serve_test$ cd src #创建server节点的源代码 (base) chenjianqu@chen:~/ros/project/ws2/src/serve_test/src$ vim server.cpp
代码内容如下:
#include <ros/ros.h> #include <serve_test/Greeting.h> bool handle_function(serve_test::Greeting::Request &req, serve_test::Greeting::Response &res){//显示请求信息ROS_INFO("Request from %s with age %d", req.name.c_str(), req.age);//处理请求,结果写入responseres.feedback = "Hi " + req.name + ". I’m server!";//返回true,正确处理了请求return true; } int main(int argc, char** argv){ros::init(argc, argv, "greetings_server");//解析参数,命名节点ros::NodeHandle nh;//创建句柄,实例化noderos::ServiceServer service = nh.advertiseService("greetings", handle_function); //写明服务的处理函数ros::spin();return 0; }
接着创建client节点的源代码
(base) chenjianqu@chen:~/ros/project/ws2/src/serve_test/src$ vim client.cpp
代码如下:
#include <ros/ros.h> #include <serve_test/Greeting.h>int main(int argc, char **argv) {ros::init(argc, argv, "greetings_client");// 初始化,节点命名为"greetings_client"ros::NodeHandle nh;ros::ServiceClient client = nh.serviceClient<serve_test::Greeting>("greetings");// 定义service客户端,service名字为“greetings”,service类型为serve_test// 实例化srv,设置其request消息的内容,这里request包含两个变量,name和age,见Greeting.srvserve_test::Greeting srv;srv.request.name = "HAN";srv.request.age = 20;if (client.call(srv)){// 注意我们的response部分中的内容只包含一个变量response,另,注意将其转变成字符串ROS_INFO("Response from server: %s", srv.response.feedback.c_str());}else{ROS_ERROR("Failed to call service serve_test");return 1;}return 0; }
5.配置CMakeLists.txt,编译工作空间
(base) chenjianqu@chen:~/ros/project/ws2/src/serve_test/src$ cd .. (base) chenjianqu@chen:~/ros/project/ws2/src/serve_test$ vim CMakeLists.txt
在CMakeLists.txt文件里添加:
#要生成的可执行文件server和需要编译的源文件src/server.cpp,如需要多个代码文件,则可在后面一次列出,中间使用空格分隔 add_executable(server src/server.cpp) #设置依赖项,这里必须添加add_dependencies,否则找不到自定义的srv产生的头文件 add_dependencies(server serve_test_generate_messages_cpp) #设置链接库,很多工序要需要使用第三方库函数,这里可以配置默认链接库 target_link_libraries(server ${catkin_LIBRARIES}) add_executable(client src/client.cpp ) add_dependencies(client serve_test_generate_messages_cpp) target_link_libraries(client ${catkin_LIBRARIES})
然后编译工作空间
(base) chenjianqu@chen:~/ros/project/ws2/src/serve_test$ cd .. (base) chenjianqu@chen:~/ros/project/ws2/src$ cd .. (base) chenjianqu@chen:~/ros/project/ws2$ catkin_make
6.测试
A.打开一个新的终端,运行roscore
B.再打开一个新的终端,运行server节点
(base) chenjianqu@chen:~/ros/project/ws2$ source devel/setup.bash (base) chenjianqu@chen:~/ros/project/ws2$ rosrun serve_test server
C.再打开一个新的终端,运行client节点
(base) chenjianqu@chen:~/ros/project/ws2$ source devel/setup.bash (base) chenjianqu@chen:~/ros/project/ws2$ rosrun serve_test client
然后服务端节点会收到客户端节点的消息:[ INFO] [1575818511.403724893]: Request from HAN with age 20。
接着客户端节点收到服务端节点返回的消息:[ INFO] [1575818511.403884222]: Response from server: Hi HAN. I???m server!。
编译完成后必须刷新一下工作空间的环境,否则可能找不到工作空间。许多时候我们为了打开终端就能够运行工作空间中编译好的ROS程序,我们习惯把“source 工作空间路径/devel/setup.bash”命令追加到~/.bashrc文件中,这样每次打开终端,系统就会刷新工作空间环境。可以通过“echo "source 工作空间路径/devel/setup.bash" >> ~/.bashrc”命令来追加。
二.基于rospy的topic通信
在上面创建工作空间的基础上,创建另一个包。
(base) chenjianqu@chen:~/ros/project/ws2/src$ catkin_create_pkg topic_test std_msgs rospy
然后在包目录下创建一个用于存放topic消息的目录msg,创建topic通信格式gps.msg
(base) chenjianqu@chen:~/ros/project/ws2/src/topic_test/msg$ vim gps.msg
写入下面的代码,格式与service通信不同,topic通信是单向通信:
string state float32 x float32 y
然后像上面的service例子一样,修改CMakeLists.txt和package.xml,并编译服务消息。
接下来就可以开始写rospy的程序,这里在包目录下创建scripts文件夹,用于存放简单的python脚本代码,
(base) chenjianqu@chen:~/ros/project/ws2/src/topic_test/scripts$ vim pytalker.py
代码如下:
#!/usr/bin/env python #coding=utf-8 import rospy from topic_test.msg import gps #导入自定义的数据类型def talker():pub = rospy.Publisher('gps_info', gps , queue_size=10)rospy.init_node('pytalker', anonymous=True)#更新频率是1hzrate = rospy.Rate(1) x=1.0y=2.0state='working'while not rospy.is_shutdown():#计算距离rospy.loginfo('Talker: GPS: x=%f ,y= %f',x,y)pub.publish(gps(state,x,y))x=1.03*xy=1.01*yrate.sleep()if __name__ == '__main__':talker()#Publisher 函数第一个参数是话题名称,第二个参数 数据类型,现在就是我们定义的msg 最后一个是缓冲区的大小 #queue_size: None(不建议) #这将设置为阻塞式同步收发模式! #queue_size: 0(不建议)#这将设置为无限缓冲区模式,很危险! #queue_size: 10 or more #一般情况下,设为10 。queue_size太大了会导致数据延迟不同步。
写完后设置该文件为可执行文件:
(base) chenjianqu@chen:~/ros/project/ws2/src/topic_test/scripts$ chmod +x pytalker.py
再新建一个节点脚本文件:
(base) chenjianqu@chen:~/ros/project/ws2/src/topic_test/scripts$ vim pylistener.py
代码:
#!/usr/bin/env python #coding=utf-8 import rospy import math from topic_test.msg import gps#回调函数输入的应该是msg def callback(gps):distance = math.sqrt(math.pow(gps.x, 2)+math.pow(gps.y, 2)) rospy.loginfo('Listener: GPS: distance=%f, state=%s', distance, gps.state) def listener():rospy.init_node('pylistener', anonymous=True)#Subscriber函数第一个参数是topic的名称,第二个参数是接受的数据类型 第三个参数是回调函数的名称rospy.Subscriber('gps_info', gps, callback)rospy.spin() if __name__ == '__main__':listener()
(base) chenjianqu@chen:~/ros/project/ws2/src/topic_test/scripts$ chmod +x pylistener.py
python代码是动态语言,因此无需修改cmakelists.txt文件,直接在工作空间catkin_make一下,再刷新环境变量,即可运行。
代码首行#!/usr/bin/env python这种用法是为了防止操作系统用户没有将python装在默认的/usr/bin路径里。当系统看到这一行的时候,首先会到env设置里查找python的安装路径,再调用对应路径下的解释器程序完成操作。
参考文献
[0]中科院软件所,重德智能公司.中国大学MOOC---《机器人操作系统入门》课程讲义.https://sychaichangkun.gitbooks.io/ros-tutorial-icourse163/content/
ROS-创建功能包和节点相关推荐
- ros创建功能包和编译过程问题处理
文章目录 1. 创建工作空间和功能包 2.新建cpp文件 3.修改CMakeLists.txt 4.编译问题 4.1 Could NOT find rospy (missing: rospy_DIR) ...
- 相机标定原理 用ROS camera_calibration 功能包 在gazebo中进行 相机校准
在gazebo中进行相机标定 相机标定原理 相机标定意义 相机标定原理 相机标定参数 相关坐标系 世界坐标系 相机坐标系 像素坐标系.图像坐标系 相机坐标系转换为世界坐标系 像素坐标系转换为图像坐标系 ...
- 工作空间、功能包、节点
相关课程视频下载链接 和彩云 网盘链接: 链接:和彩云网盘 提取码:qo1z 简介:和彩云网盘是中国移动旗下的网盘,目前对免费用户下载不限速,只要简单注册一个账号就可以下载 迅雷云盘 网盘链接: 迅雷 ...
- ROS rviz_satellite功能包可视化GNSS轨迹,卫星地图的使用
安装步骤 mkdir -p catkin_ws/src cd catkin_ws/src git clone https://github.com/nobleo/rviz_satellite # cl ...
- ROS系统 创建工作空间与功能包
ROS 学习目标: 学习内容: 使用环境 操作步骤: 基本命令 二.使用步骤 创建工作空间 编译工作空间 创建功能包 使用C++执行程序 编写源文件 编辑功能包下的 Cmakelist.txt文件 修 ...
- ROS中工作空间和功能包的创建以及发布者Publisher的实现
最近刚刚开始学习ROS,对于整个ROS的框架和功能正在一点点的了解,跟着B站古月居的<ROS入门21讲>课程,在安装好linux和ROS后,正式开始ROS的学习,动手实践敲代码,在这里先记 ...
- ROS学习笔记4:创建工作空间和功能包
一.linux命令行使用基础: 1.cd命令(change directory): (1)语法: cd [dirName](dirName:要切换到的目录)cd ..(返回上一级) (2)功能:用于切 ...
- ros自带package在哪里_【ROS】创建ROS功能包(ROS package)
创建功能包(ROS package) 1 常用工具 roscreate-pkg catkin 2 catkin package组成 命名规则 只允许使用小写字母,数字,下划线三种元素组成,并且首字母必 ...
- 【RK3399Pro学习笔记】四、ROS 创建工作空间与功能包
目录 创建工作空间 编译工作空间 功能包 创建功能包 编译功能包 设置环境变量 检查环境变量 平台:华硕 Thinker Edge R 瑞芯微 RK3399Pro 固件版本:Tinker_Edge_R ...
- ROS 学习笔记(一):工作空间+功能包创建
ROS 学习笔记(一):工作空间+功能包创建 一.创建工作空间(catkin_make编译): 1.创建工作空间 catkin_ws 创建空间.初始化(建立一个文件夹) cd ~ mkdir -p ~ ...
最新文章
- ASA和4503的配置
- 【Groovy】集合遍历 ( 操作符重载 | 集合中的 “ << “ 操作符重载 | 使用集合中的 “ << “ 操作符添加一个元素 | 使用集合中的 “ << “ 操作符添加一个集合 )
- 【设计模式】代理模式 ( 动态代理使用流程 | 创建目标对象 | 创建被代理对象 | 创建调用处理程序 | 动态创建代理对象 | 动态代理调用 )
- log4.properties文件【笔记自用】
- 奇怪的.strip(alir) #()里面有东西 待问老师........
- HADOOP2.5.0_64安装日志
- 爱立信与中国联通成功完成国内首个LTE三载波聚合大规模部署测试
- 给即将35岁的产品经理提个醒
- (三)Clang/ LLVM编译流程简述
- GIT的初步使用记录
- 揭开艺术特长考试神秘面纱
- Linux操作系统——Linux 内核源码介绍内核升级
- 如何用python刷屏_利用python实现在微信群刷屏的方法
- 【优秀的截图软件】jietu 2.2.2 for mac
- 飞控C语言开源,几大主流开源飞控平台优劣比较.doc
- Emacs指北(做一个搬运工好累)
- 微信朋友圈图片处理策略
- 2013,我的创业记忆片段
- win10 桌面的的文件都不见了 提示不注销保存都文件都为临时_你的电脑垃圾文件再不清理就要留到牛年了!...
- 专访 | wuhan2020拾柴者王欣:开源的世界里没有老师
热门文章
- mysql 5.6.20 优化_mysql 5.6.20 占用内存超大,大概400M左右
- 中的枚举属性函数_软件特攻队|Qt中的反射机制之Q_PROPERTY
- [crypto][ipsec] 简述ESP协议的sequence number机制
- token验证+vuex的localStorage应用
- 上传github代码
- 百度网盘搜索源码,新加分词功能,内容相关度聚合更高
- mysql myisam简单分表设计
- windows端口备忘
- Memcache for Windows
- 数据结构与算法之排序(归纳总结三)