目录
一、ROS常用命令
1.1 ROS常用命令
1.1.1 为什么要学习这些命令
机器人系统中启动的节点少则几个,多则十几个、几十个,不同的节点名称各异,通信时使用话题、服务、消息、参数等等都各不相同,一个显而易见的问题是: 当需要自定义节点和其他某个已经存在的节点通信时,如何获取对方的话题、以及消息载体的格式呢。
和之前介绍的文件系统操作命令比较,文件操作命令是静态的,操作的是磁盘上的文件,而上述命令是动态的,在ROS程序启动后,可以动态的获取运行中的节点或参数的相关信息。
1.1.2 rosnode 命令
1.介绍
rosnode是获取节点信息的命令
2. rosnode list :列出活跃的节点
Ⅰ.以话题通信的代码为例练习rosnode命令
#include "ros/ros.h" #include"plumbing_pub_sub/Person.h" int main(int argc ,char * argv[]) { setlocale(LC_ALL,""); ros::init(argc,argv,"banZhuren"); ros::NodeHandle nh; ros::Publisher pub = nh.advertise<plumbing_pub_sub::Person>("liaoTian",10); //创建发布数据 plumbing_pub_sub::Person person; person.name = "张三"; person.age = 1; person.height = 180.78; //设置发布频率 ros::Rate rate(1); //循环发布数据 while(ros::ok()) { person.age++; //数据发布 pub.publish(person); rate.sleep(); //建议 ros::spinOnce(); } return 0; }
#include "ros/ros.h" #include "plumbing_pub_sub/Person.h" void doPerson(const plumbing_pub_sub::Person::ConstPtr & person) { ROS_INFO("订阅人的信息:%s,%d,%.2f",person->name.c_str(),person->age,person->height); } int main(int argc,char * argv[]) { setlocale(LC_ALL,""); ROS_INFO("订阅方实现"); ros::init(argc,argv,"jiaZhang"); ros::NodeHandle nh; ros::Subscriber sub = nh.subscribe("liaoTian",10,doPerson); ros::spin(); return 0; }
Ⅱ.将源文件在终端命令行中运行
Ⅲ.在终端中运行:一共有三个活跃的节点
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosnode list /banZhuren /jiaZhang /rosout
3. rosnode ping 节点名称 :测试某个节点的连接状态
仍以上例为例 :测试班主任节点是否联通
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosnode ping banZhuren rosnode: node is [/banZhuren] pinging /banZhuren with a timeout of 3.0s xmlrpc reply from http://liuhongwei-virtual-machine:42805/ time=0.368118ms xmlrpc reply from http://liuhongwei-virtual-machine:42805/ time=0.463009ms xmlrpc reply from http://liuhongwei-virtual-machine:42805/ time=0.549078ms xmlrpc reply from http://liuhongwei-virtual-machine:42805/ time=0.633001ms xmlrpc reply from http://liuhongwei-virtual-machine:42805/ time=0.450850ms xmlrpc reply from http://liuhongwei-virtual-machine:42805/ time=0.592947ms xmlrpc reply from http://liuhongwei-virtual-machine:42805/ time=0.566959ms xmlrpc reply from http://liuhongwei-virtual-machine:42805/ time=0.498056ms xmlrpc reply from http://liuhongwei-virtual-machine:42805/ time=0.447035ms xmlrpc reply from http://liuhongwei-virtual-machine:42805/ time=0.396967ms
4.rosnode info 节点名称:列出关于当前节点的信息
仍以上例为例 :列出班主任节点相关信息
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosnode info banZhuren -------------------------------------------------------------------------------- Node [/banZhuren] Publications: * /liaoTian [plumbing_pub_sub/Person] * /rosout [rosgraph_msgs/Log] Subscriptions: None Services: * /banZhuren/get_loggers * /banZhuren/set_logger_level contacting node http://liuhongwei-virtual-machine:42805/ ... Pid: 75422 Connections: * topic: /rosout * to: /rosout * direction: outbound (47133 - 127.0.0.1:51692) [11] * transport: TCPROS * topic: /liaoTian * to: /jiaZhang * direction: outbound (47133 - 127.0.0.1:51752) [12] * transport: TCPROS
5.rosnode machine 机器名称:多台计算机协作时该计算机运行的节点信息
输出本电脑的节点信息
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosnode machine liuhongwei-virtual-machine /banZhuren /jiaZhang /rosout
6.rosnode kill 节点名称:杀死某个正在运行中的节点
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosnode kill banZhuren killing /banZhuren killed
这时,banZhuren节点被杀死,再看发布节点,抛出异常并终止
7.rosnode cleanup:杀死僵死进程(详见深入理解计算机系统--进程与线程)
1.1.3 rostopic 命令
1.介绍
rostopic包含rostopic命令行工具,用于显示有关ROS 主题的调试信息,包括发布者,订阅者,发布频率和ROS消息。它还包含一个实验性Python库,用于动态获取有关主题的信息并与之交互。
2.rostopic list:列出所有话题
liuhongwei@liuhongwei-virtual-machine:~$ rostopic list /liaoTian /rosout /rosout_agg
3.rostopic echo 话题:打印出某个话题下发布的消息
Ⅰ.若是自定义消息,应到工作空间下刷新环境变量后再使用
liuhongwei@liuhongwei-virtual-machine:~$ cd demo03_ws/ liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ source ./devel/setup.bash liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rostopic echo liaoTian name: !!python/str "\u5F20\u4E09" age: 249 height: 180.779998779 --- name: !!python/str "\u5F20\u4E09" age: 250 height: 180.779998779 ---
Ⅱ.非自定义消息,直接使用即可
4.rostopic pub 话题 Tab补齐 :用命令行发布数据,做测试用
然后自己修改这些空着的地方就好
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rostopic pub liaoTian plumbing_pub_sub/Person "name: '' age: 0 height: 0.0"
5.rostopic info 话题:显示话题具体信息
6.rostopic hz 话题:显示发布频率
1.1.4 rosservice 命令
1.准备工作:以下述代码为例演示rosservice命令
#include "ros/ros.h" #include"plumbing_server_client/addints.h" /* 服务端实现:解析客户端提交的数据,并运算再产生响应 1.包含相关头文件 2.初始化ros节点 3.创建节点句柄 4.创建服务对象 5.处理请求并产生响应 6.spin() */ bool doNums(plumbing_server_client::addints::Request & request,plumbing_server_client::addints::Response &response) //返回bool值,表明成功或者失败 { //1.处理请求 int num1 = request.num1; int num2 = request.num2; ROS_INFO("收到的请求数据为:num1=%d,num2=%d",num1,num2); //2.组织响应 int sum = num1+num2; response.sum = sum; ROS_INFO("求和结果为%d",sum); return true; } int main(int argc, char *argv[]) { setlocale(LC_ALL,""); ros::init(argc,argv,"heishui"); //节点名称唯一 ros::NodeHandle nh; ros::ServiceServer server = nh.advertiseService("addInts",doNums); //话题名称、回调函数 ros::spin(); return 0; }
#include "ros/ros.h" #include "plumbing_server_client/addints.h" /* 客户端:提交两个数据,处理响应结果 1.包含相关头文件 2.初始化ros节点 3.创建节点句柄 4.创建客户端对象 5.提交请求并产生响应 */ int main(int argc, char *argv[]) { setlocale(LC_ALL,""); //优化实现,获取命令中的参数 if(argc!=3) { ROS_INFO("提交的参数个数不对"); return 1 ; } ros::init(argc,argv,"daBao"); ros::NodeHandle nh; ros::ServiceClient client = nh.serviceClient<plumbing_server_client::addints>("addInts"); //话题 //5-1组织请求 plumbing_server_client::addints ai; ai.request.num1 = atoi(argv[1]); ai.request.num2 = atoi(argv[2]); //调用判断服务器状态的函数 client.waitForExistence(); //如果服务器没启动,服务器就会挂起 //5-2处理响应 bool flag = client.call(ai); //客户端带着ai对象访问服务器 if(flag) { ROS_INFO("响应成功"); //获取sum ROS_INFO("响应结果 = %d",ai.response.sum); //传进去是引用变量 } else { ROS_INFO("处理失败........."); } return 0; }
2.rosservice list:当前ros服务中启动的服务
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosservice list /addInts /banZhuren/get_loggers /banZhuren/set_logger_level /heishui/get_loggers /heishui/set_logger_level /jiaZhang/get_loggers /jiaZhang/set_logger_level /rosout/get_loggers /rosout/set_logger_level
3.rosservice call 服务名称:扮演客户端的角色,向服务器发送请求
4.rosservice info 服务名称:服务相关信息
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosservice info addInts Node: /heishui URI: rosrpc://liuhongwei-virtual-machine:59523 Type: plumbing_server_client/addints Args: num1 num2
1.1.5 rosmsg 命令
1.作用
rosmsg是用于显示有关 ROS消息类型的 信息的命令行工具。主要用于发布订阅模型中
2.准备工作:
执行两个发布订阅模型的文件
#include "ros/ros.h" #include"plumbing_pub_sub/Person.h" int main(int argc ,char * argv[]) { setlocale(LC_ALL,""); ros::init(argc,argv,"banZhuren"); ros::NodeHandle nh; ros::Publisher pub = nh.advertise<plumbing_pub_sub::Person>("liaoTian",10); //创建发布数据 plumbing_pub_sub::Person person; person.name = "张三"; person.age = 1; person.height = 180.78; //设置发布频率 ros::Rate rate(1); //循环发布数据 while(ros::ok()) { person.age++; //数据发布 pub.publish(person); rate.sleep(); //建议 ros::spinOnce(); } return 0; }
#include "ros/ros.h" #include "plumbing_pub_sub/Person.h" void doPerson(const plumbing_pub_sub::Person::ConstPtr & person) { ROS_INFO("订阅人的信息:%s,%d,%.2f",person->name.c_str(),person->age,person->height); } int main(int argc,char * argv[]) { setlocale(LC_ALL,""); ROS_INFO("订阅方实现"); ros::init(argc,argv,"jiaZhang"); ros::NodeHandle nh; ros::Subscriber sub = nh.subscribe("liaoTian",10,doPerson); ros::spin(); return 0; }
3.rosmsg list:列出所有消息类型
4.rosmsg info/show:列出消息信息
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosmsg show plumbing_pub_sub/Person string name int32 age float32 height
1.1.6 rossrv 命令
1.作用
rossrv是用于显示有关 ROS消息类型的 信息的命令行工具。主要用于服务通信中
2.与rosmsg相同,不再演示。
1.1.7 rosparam 命令
1.作用
rosparam包含rosparam命令行工具,用于使用YAML编码文件在参数服务器上获取和设置ROS参数。是ROS参数服务器的命令。
2.rosparam list:列出参数服务器里面的一些数据
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosparam list /rosdistro /roslaunch/uris/host_liuhongwei_virtual_machine__36123 /rosversion /run_id /type_p
3.rosparam set 键名 值名:向参数服务器设置数据
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosparam set name xiaohuang liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosparam list /name /rosdistro /roslaunch/uris/host_liuhongwei_virtual_machine__36123 /rosversion /run_id /type_p
3.rosparam get 键名:获取键名所对应的值
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosparam get name xiaohuang
4.rosparam delete 键名:删除参数服务器里面的键值对
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosparam list /len /name /rosdistro /roslaunch/uris/host_liuhongwei_virtual_machine__36123 /rosversion /run_id /type_p /width liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosparam delete name liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosparam list /len /rosdistro /roslaunch/uris/host_liuhongwei_virtual_machine__36123 /rosversion /run_id /type_p /width
5.rosparam dump 文件名.yaml:将参数写入磁盘文件(序列化)
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosparam dump param.yaml
6.rosparam load 文件名.yaml:反序列化
二、通信机制实操
2.1 本节内容概述
本节主要是通过ROS内置的turtlesim案例,结合已经介绍ROS命令获取节点、话题、话题消息、服务、服务消息与参数的信息,最终再以编码的方式实现乌龟运动的控制、乌龟位姿的订阅、乌龟生成与乌龟窗体背景颜色的修改。
2.2 实操01_话题发布
2.2.1 需求分析
1.需求描述
编码实现乌龟运动控制,让小乌龟做圆周运动。
2.实现分析
- 乌龟运动控制实现,关键节点有两个,一个是乌龟运动显示节点 turtlesim_node,另一个是控制节点,二者是订阅发布模式实现通信的,乌龟运动显示节点直接调用即可,运动控制节点之前是使用的 turtle_teleop_key通过键盘 控制,现在需要自定义控制节点。
- 控制节点自实现时,首先需要了解控制节点与显示节点通信使用的话题与消息,可以使用ros命令结合计算图来获取。
- 了解了话题与消息之后,通过 C++ 或 Python 编写运动控制节点,通过指定的话题,按照一定的逻辑发布消息即可。
3.实现流程
- 通过计算图结合ros命令获取话题与消息信息。
- 编码实现运动控制节点。
- 启动 roscore、turtlesim_node 以及自定义的控制节点,查看运行结果。
2.2.2 话题与消息的获取
1.话题的获取
Ⅰ.rostopic list 命令可以获取当前全部的话题
liuhongwei@liuhongwei-virtual-machine:~$ rostopic list /liaoTian /rosout /rosout_agg /turtle1/cmd_vel /turtle1/color_sensor /turtle1/pose
Ⅱ.rqt_graph 也可以显示不同结点之间的情况
Ⅲ.由此可见,小乌龟运动的话题为 /turtle1/cmd_vel
2.消息的获取
Ⅰ.用rostpoic info 命令获取当前话题的一些信息
liuhongwei@liuhongwei-virtual-machine:~$ rostopic info /turtle1/cmd_vel Type: geometry_msgs/Twist Publishers: * /teleop_turtle (http://liuhongwei-virtual-machine:46283/) Subscribers: * /turtlesim (http://liuhongwei-virtual-machine:36721/)
由此可见,话题的发布方是 /teleop_turtle ,话题的订阅方为 /turtlesim ,话题类型为 geometry_msgs/Twists
Ⅱ.消息格式的获取:用rosmsg show 获取消息格式
liuhongwei@liuhongwei-virtual-machine:~$ rosmsg show geometry_msgs/Twist geometry_msgs/Vector3 linear float64 x float64 y float64 z geometry_msgs/Vector3 angular float64 x float64 y float64 z
linear 线速度 ; abgular 角速度;
线速度:开车前进后退速度
x:前进后退速度 y:平移速度 z:垂直方向运动
PS:小乌龟只有前进后退
角速度:开车转弯速度
x:翻滚:贯穿整个机体的坐标系 Roll(机翼上下移动)
y:俯仰:贯穿机翼的坐标系 Pitch(机头上下移动)
z:偏航:垂直方向的坐标系 Yaw(往左偏移或者往右偏移)
PS:小乌龟运动只有偏航!
2.2.3 C++实现发布节点
1.实现步骤
Ⅰ.新建功能包,plumbing_test。导入依赖包 roscpp rospy std_msgs geometry_msgs,在src目录下建立 test01_pub_twist.cpp 文件
Ⅱ.分析流程:
/*
需求:发布速度消息
话题:/turtle/cmd_vel
消息: geometry_msg/Twist
*/Ⅲ.代码实现
#include "ros/ros.h" #include "geometry_msgs/Twist.h" /* 需求:发布速度消息 话题:/turtle/cmd_vel 消息: geometry_msg/Twist 步骤:包含头文件,初始化ros节点,创建节点句柄,创建发布对象,发布逻辑实现,spinonce */ int main(int argc, char *argv[]) { ros::init(argc,argv,"my_control"); ros::NodeHandle nh; ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("/turtle/cmd_vel",10); ros::Rate rate(10); //组织消息 geometry_msgs::Twist twist; twist.linear.x = 1.0; twist.linear.y = 0; twist.linear.z = 0; twist.angular.x = 0; twist.angular.y = 0; twist.angular.z = 0.5; while(ros::ok()) { pub.publish(twist); rate.sleep(); ros::spinOnce(); } return 0; }
Ⅳ.修改配置文件
Ⅴ.执行流程
①启动roscore
②启动乌龟UI rosrun turtlesim turtlesim_node
③切换到工作空间,刷新环境变量,执行文件
2.2.4 python实现发布节点
1.实现步骤
Ⅰ.新建目录scripts,新建文件 test01_pub_twist.py.
Ⅱ.代码
#! /usr/bin/env python # encoding:utf-8 import rospy from geometry_msgs.msg import Twist """ 发布方实现:发布速度信息 话题: /turtle1/cmd_vel 消息:geometry_msg/Twist """ if __name__ == "__main__": ros,rospy.init_node("my_control_p") pub = rospy.Publisher("/turtle1/cmd_vel",Twist,10) rate = rospy.Rate(10) twist = Twist() twist.linear.x = 1.0 twist.linear.y = 0 twist.linear.z = 0 twist.angular.x = 0 twist.angular.y = 0 twist.angular.z = 0.5 while not rospy.is_shutdown(): pub.publish(twist) rate.sleep() pass
Ⅲ.添加可执行权限,更改配置文件,编译
Ⅳ.执行
2.3 实操02_话题订阅
2.3.1 需求分析
1.需求描述
已知turtlesim中的乌龟显示节点,会发布当前乌龟的位姿(窗体中乌龟的坐标以及朝向),要求控制乌龟运动,并时时打印当前乌龟的位姿。
2.实现分析
- 首先,需要启动乌龟显示以及运动控制节点并控制乌龟运动。
- 要通过ROS命令,来获取乌龟位姿发布的话题以及消息。
- 编写订阅节点,订阅并打印乌龟的位姿。
3.实现流程
- 通过ros命令获取话题与消息信息。
- 编码实现位姿获取节点。
- 启动 roscore、turtlesim_node 、控制节点以及位姿订阅节点,控制乌龟运动并输出乌龟的位姿。
2.3.2 话题与消息的获取
Ⅰ.新建launch文件夹,建立start_turtle.launch文件。
<!-- 启动乌龟GUI与键盘控制节点 --> <launch> <!-- 乌龟GUI --> <node pkg = "turtlesim" type = "turtlesim_node" name = "turtle1" output = "screen"/> <!-- 乌龟键盘控制 --> <node pkg = "turtlesim" type = "turtle_teleop_key" name = "key" output = "screen"/> </launch>
Ⅱ.启动launch文件
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ source ./devel/setup.bash liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ roslaunch plumbing_test start_launch.launch
Ⅲ.启动成功
Ⅳ.获取话题
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rostopic list /rosout /rosout_agg /turtle1/cmd_vel /turtle1/color_sensor /turtle1/pose
Ⅳ.获取话题消息
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rostopic info /turtle1/pose Type: turtlesim/Pose Publishers: * /turtle1 (http://liuhongwei-virtual-machine:43221/) Subscribers: None
Ⅴ.获取消息格式
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosmsg info turtlesim/Pose float32 x float32 y float32 theta float32 linear_velocity float32 angular_velocity
Ⅵ.用命令实现获取订阅信息
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rostopic echo /turtle1/pose x: 5.42456293106 y: 4.59195899963 theta: 0.319999992847 linear_velocity: 0.0 angular_velocity: 0.0 ---
2.3.3 C++实现话题订阅
1.追加功能包
在package.xml下追加依赖包turtlesim
<build_depend>turtlesim</build_depend> <exec_depend>turtlesim</exec_depend>
更改CMakeLists
find_package(catkin REQUIRED COMPONENTS geometry_msgs roscpp rospy std_msgs turtlesim )
编译
2 .具体实现
Ⅰ.处理逻辑
需求:订阅乌龟的位置信息并输出到工作台
1.包含头文件
2.初始化ros节点
3.创建节点句柄
4.创建订阅对象
5.处理订阅数据(回调)
6.spinⅡ.代码实现
#include "ros/ros.h" #include "turtlesim/Pose.h" /* 需求:订阅乌龟的位置信息并输出到工作台 1.包含头文件 2.初始化ros节点 3.创建节点句柄 4.创建订阅对象 5.处理订阅数据(回调) 6.spin */ void doPos(const turtlesim::Pose::ConstPtr &pose) { ROS_INFO("乌龟的位置信息:坐标(%.2f,%.2f),朝向(%.2f),线速度(%.2f),角速度(%.2f)",pose->x,pose->y,pose->theta,pose->linear_velocity,pose->angular_velocity); } int main(int argc, char *argv[]) { setlocale(LC_ALL,""); ros::init(argc,argv,"sub_pose"); ros::NodeHandle nh; ros::Subscriber sub = nh.subscribe("/turtle1/pose",100,doPos); ros::spin(); return 0; }
Ⅲ.编写配置信息,编译
Ⅳ.执行
①执行roslaunch文件
②执行此代码,观察
roslaunch plumbing_test start_launch.launch
rosrun plumbing_test test02_sub_pose
2.3.4 python实现话题订阅
1.需求
需求:订阅并输出乌龟的位置信息
1.导包
2.初始化ros节点
3.创建订阅对象
4.回调函数处理信息
5.spin
2.具体实现
Ⅰ.代码
#! /usr/bin/env python #encoding:utf-8 import rospy from turtlesim.msg import Pose """ 需求:订阅并输出乌龟的位置信息 1.导包 2.初始化ros节点 3.创建订阅对象 4.回调函数处理信息 5.spin """ def doPos(pose): rospy.loginfo("乌龟的位置信息:坐标(%.2f,%.2f),朝向%.2f,线速度%.2f,角速度%.2f",pose.x,pose.y,pose.theta,pose.linear_velocity,pose.angular_velocity) if __name__ == "__main__": rospy.init_node("sub_pose_p") sub = rospy.Subscriber("/turtle1/pose","Pose",doPos,queue_size=100) rospy.spin() pass
Ⅱ.添加可执行权限,修改配置文件,编译
Ⅲ.执行(与C++流程相同,不再演示)
2.4 实操03_服务调用
2.4.1 需求分析
1.需求描述
编码实现向 turtlesim 发送请求,在乌龟显示节点的窗体指定位置生成一乌龟,这是一个服务请求操作。
2.需求分析
- 首先,需要启动乌龟显示节点。
- 要通过ROS命令,来获取乌龟生成服务的服务名称以及服务消息类型。
- 编写服务请求节点,生成新的乌龟。
3. 实现流程
- 通过ros命令获取服务与服务消息信息。
- 编码实现服务请求节点。
- 启动 roscore、turtlesim_node 、乌龟生成节点,生成新的乌龟。
2.4.2 服务名称与服务信息获取
操作步骤
Ⅰ.调用launch文件启动乌龟的GUI
roslaunch plumbing_test start_launch.launch
Ⅱ.新建窗口,获取服务话题
liuhongwei@liuhongwei-virtual-machine:~$ rosservice list /clear /kill /reset /rosout/get_loggers /rosout/set_logger_level /spawn /sub_pose/get_loggers /sub_pose/set_logger_level /turtle1/get_loggers /turtle1/set_logger_level /turtle1/set_pen /turtle1/teleport_absolute /turtle1/teleport_relative
生成新的小乌龟的话题是 /spawn
Ⅲ.获取更多话题的信息
liuhongwei@liuhongwei-virtual-machine:~$ rosservice info /spawn Node: /turtle1 URI: rosrpc://liuhongwei-virtual-machine:39847 Type: turtlesim/Spawn Args: x y theta name
话题服务使用的消息类型:turtlesim/Spawn
请求服务提交的字段:x y theta name
Ⅳ.获取服务消息的数据格式
liuhongwei@liuhongwei-virtual-machine:~$ rossrv info turtlesim/Spawn float32 x float32 y float32 theta string name --- string name
Ⅴ.通过命令实现
liuhongwei@liuhongwei-virtual-machine:~$ rosservice call /spawn "x: 0.0 y: 0.0 theta: 0.0 name: ''"
2.4.3 C++实现服务调用
1.实现
Ⅰ.实现code
#include "ros/ros.h" #include "turtlesim/Spawn.h" /* 需求:向服务端发送请求,生成一只新乌龟 话题:/spawn 消息:turtlesim/Spawn */ int main(int argc, char *argv[]) { setlocale(LC_ALL,""); ros::init(argc,argv,"service_call"); ros::NodeHandle nh; ros::ServiceClient client = nh.serviceClient<turtlesim::Spawn>("/spawn"); turtlesim::Spawn spawn; spawn.request.name = "shazi"; spawn.request.theta = 0.0; spawn.request.x = 1.0; spawn.request.y = 4.0; //ros::service::waitForService("/spawn"); client.waitForExistence(); bool flag = client.call(spawn); if(flag) { ROS_INFO("乌龟生成成功,新乌龟叫:%s",spawn.response.name.c_str()); } else { ROS_INFO("请求失败"); } return 0; }
Ⅱ.编写配置文件,编译
Ⅲ.执行
首先,启动 roscore;
然后启动乌龟显示节点;
最后启动乌龟生成请求节点;
2.4.4 python实现服务调用
1.实现代码
Ⅰ.code
#! /usr/bin/env python #encoding:utf-8 import rospy from turtlesim.srv import Spawn,SpawnRequest,SpawnResponse if __name__ =="__main__": rospy.init_node("service_call_p") client = rospy.ServiceProxy("/spawn",Spawn) request = SpawnRequest() request.x = 4.5 request.y = 2.0 request.theta = -3 request.name = "chenzhuo" client.wait_for_service() response = client.call(request) rospy.loginfo("生成乌龟的名字为:%s",response.name) pass
Ⅱ.修改配置文件并编译
Ⅳ.执行
2.4 实操04_参数设置
2.4.1 需求分析
1.需求描述
修改turtlesim乌龟显示节点窗体的背景色,已知背景色是通过参数服务器的方式以 rgb 方式设置的。
2.实现分析
- 首先,需要启动乌龟显示节点。
- 要通过ROS命令,来获取参数服务器中设置背景色的参数。
- 编写参数设置节点,修改参数服务器中的参数值。
3.实现流程
- 通过ros命令获取参数。
- 编码实现服参数设置节点。
- 启动 roscore、turtlesim_node 与参数设置节点,查看运行结果。
2.4.2 服务名称与服务信息获取
Ⅰ.参数名获取
先要启动乌龟UI节点,
rosrun turtlesim turtlesim_node
Ⅱ.利用命令列出所有参数
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosparam list /rosdistro /roslaunch/uris/host_liuhongwei_virtual_machine__40263 /roslaunch/uris/host_liuhongwei_virtual_machine__40397 /rosversion /run_id /turtle1/background_b /turtle1/background_g /turtle1/background_r /turtlesim/background_b /turtlesim/background_g /turtlesim/background_r
Ⅲ.查看参数值
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosparam get /turtlesim/background_r 69
Ⅳ.此时背景色
Ⅴ.利用命令行修改参数
liuhongwei@liuhongwei-virtual-machine:~/demo03_ws$ rosparam set /turtlesim/background_r 255
Ⅵ.结果演示
2.4.3 C++实现更改参数
Ⅰ.code1
#include "ros/ros.h" /* 修改参数服务器中turtlesim背景色相关参数 */ int main(int argc, char *argv[]) { ros::init(argc,argv,"chage_bgcolor"); ros::param::set("/turtlesim/background_r",0); ros::param::set("/turtlesim/background_g",0); ros::param::set("/turtlesim/background_b",0); return 0; }
2.运行测试1:
3.code2
#include "ros/ros.h" /* 修改参数服务器中turtlesim背景色相关参数 */ int main(int argc, char *argv[]) { ros::init(argc,argv,"chage_bgcolor"); ros::NodeHandle nh("turtlesim"); nh.setParam("background_r",255); nh.setParam("background_g",255); nh.setParam("background_b",255); return 0; }
2.4.4 python实现更改参数
Ⅰ.code
#! /usr/bin/env python #encoding:utf-8 import rospy if __name__ == "__main__": rospy.init_node("change_bgColor") rospy.set_param("/turtlesim/background_r",100) rospy.set_param("/turtlesim/background_g",100) rospy.set_param("/turtlesim/background_b",100) pass
2.5 通信机制比较
三种通信机制中,参数服务器是一种数据共享机制,可以在不同的节点之间共享数据,话题通信与服务通信是在不同的节点之间传递数据的,三者是ROS中最基础也是应用最为广泛的通信机制。
这其中,话题通信和服务通信有一定的相似性也有本质上的差异,在此将二者做一下简单比较:
二者的实现流程是比较相似的,都是涉及到四个要素:
- 要素1: 消息的发布方/客户端(Publisher/Client)
- 要素2: 消息的订阅方/服务端(Subscriber/Server)
- 要素3: 话题名称(Topic/Service)
- 要素4: 数据载体(msg/srv)
可以概括为: 两个节点通过话题关联到一起,并使用某种类型的数据载体实现数据传输。
2.6 本章小结
本章主要介绍了ROS中最基本的也是最核心的通信机制实现: 话题通信、服务通信、参数服务器。每种通信机制,都介绍了如下内容:
伊始介绍了当前通信机制的应用场景;
介绍了当前通信机制的理论模型;
分别介绍了当前通信机制的C++与Python实现。
除此之外,还介绍了:
- ROS中的常用命令方便操作、调试节点以及通信信息;
- 通过实操又将上述知识点加以整合;
- 最后又着重比较了话题通信与服务通信的相同点以及差异。
掌握本章内容后,基本上就可以从容应对ROS中大部分应用场景了。