个人博客: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-创建功能包和节点相关推荐

  1. ros创建功能包和编译过程问题处理

    文章目录 1. 创建工作空间和功能包 2.新建cpp文件 3.修改CMakeLists.txt 4.编译问题 4.1 Could NOT find rospy (missing: rospy_DIR) ...

  2. 相机标定原理 用ROS camera_calibration 功能包 在gazebo中进行 相机校准

    在gazebo中进行相机标定 相机标定原理 相机标定意义 相机标定原理 相机标定参数 相关坐标系 世界坐标系 相机坐标系 像素坐标系.图像坐标系 相机坐标系转换为世界坐标系 像素坐标系转换为图像坐标系 ...

  3. 工作空间、功能包、节点

    相关课程视频下载链接 和彩云 网盘链接: 链接:和彩云网盘 提取码:qo1z 简介:和彩云网盘是中国移动旗下的网盘,目前对免费用户下载不限速,只要简单注册一个账号就可以下载 迅雷云盘 网盘链接: 迅雷 ...

  4. ROS rviz_satellite功能包可视化GNSS轨迹,卫星地图的使用

    安装步骤 mkdir -p catkin_ws/src cd catkin_ws/src git clone https://github.com/nobleo/rviz_satellite # cl ...

  5. ROS系统 创建工作空间与功能包

    ROS 学习目标: 学习内容: 使用环境 操作步骤: 基本命令 二.使用步骤 创建工作空间 编译工作空间 创建功能包 使用C++执行程序 编写源文件 编辑功能包下的 Cmakelist.txt文件 修 ...

  6. ROS中工作空间和功能包的创建以及发布者Publisher的实现

    最近刚刚开始学习ROS,对于整个ROS的框架和功能正在一点点的了解,跟着B站古月居的<ROS入门21讲>课程,在安装好linux和ROS后,正式开始ROS的学习,动手实践敲代码,在这里先记 ...

  7. ROS学习笔记4:创建工作空间和功能包

    一.linux命令行使用基础: 1.cd命令(change directory): (1)语法: cd [dirName](dirName:要切换到的目录)cd ..(返回上一级) (2)功能:用于切 ...

  8. ros自带package在哪里_【ROS】创建ROS功能包(ROS package)

    创建功能包(ROS package) 1 常用工具 roscreate-pkg catkin 2 catkin package组成 命名规则 只允许使用小写字母,数字,下划线三种元素组成,并且首字母必 ...

  9. 【RK3399Pro学习笔记】四、ROS 创建工作空间与功能包

    目录 创建工作空间 编译工作空间 功能包 创建功能包 编译功能包 设置环境变量 检查环境变量 平台:华硕 Thinker Edge R 瑞芯微 RK3399Pro 固件版本:Tinker_Edge_R ...

  10. ROS 学习笔记(一):工作空间+功能包创建

    ROS 学习笔记(一):工作空间+功能包创建 一.创建工作空间(catkin_make编译): 1.创建工作空间 catkin_ws 创建空间.初始化(建立一个文件夹) cd ~ mkdir -p ~ ...

最新文章

  1. ASA和4503的配置
  2. 【Groovy】集合遍历 ( 操作符重载 | 集合中的 “ << “ 操作符重载 | 使用集合中的 “ << “ 操作符添加一个元素 | 使用集合中的 “ << “ 操作符添加一个集合 )
  3. 【设计模式】代理模式 ( 动态代理使用流程 | 创建目标对象 | 创建被代理对象 | 创建调用处理程序 | 动态创建代理对象 | 动态代理调用 )
  4. log4.properties文件【笔记自用】
  5. 奇怪的.strip(alir) #()里面有东西 待问老师........
  6. HADOOP2.5.0_64安装日志
  7. 爱立信与中国联通成功完成国内首个LTE三载波聚合大规模部署测试
  8. 给即将35岁的产品经理提个醒
  9. (三)Clang/ LLVM编译流程简述
  10. GIT的初步使用记录
  11. 揭开艺术特长考试神秘面纱
  12. Linux操作系统——Linux 内核源码介绍内核升级
  13. 如何用python刷屏_利用python实现在微信群刷屏的方法
  14. 【优秀的截图软件】jietu 2.2.2 for mac
  15. 飞控C语言开源,几大主流开源飞控平台优劣比较.doc
  16. Emacs指北(做一个搬运工好累)
  17. 微信朋友圈图片处理策略
  18. 2013,我的创业记忆片段
  19. win10 桌面的的文件都不见了 提示不注销保存都文件都为临时_你的电脑垃圾文件再不清理就要留到牛年了!...
  20. 专访 | wuhan2020拾柴者王欣:开源的世界里没有老师

热门文章

  1. mysql 5.6.20 优化_mysql 5.6.20 占用内存超大,大概400M左右
  2. 中的枚举属性函数_软件特攻队|Qt中的反射机制之Q_PROPERTY
  3. [crypto][ipsec] 简述ESP协议的sequence number机制
  4. token验证+vuex的localStorage应用
  5. 上传github代码
  6. 百度网盘搜索源码,新加分词功能,内容相关度聚合更高
  7. mysql myisam简单分表设计
  8. windows端口备忘
  9. Memcache for Windows
  10. 数据结构与算法之排序(归纳总结三)