赞
踩
目录
主要是通过ROS内置的turtlesim案例,结合已经介绍ROS命令获取节点、话题、话题消息、服务、服务消息与参数的信息,最终再以编码的方式实现乌龟运动的控制、乌龟位姿的订阅、乌龟生成与乌龟窗体背景颜色的修改。
实现分析:
实现流程:
话题与消息获取
准备: 先启动键盘控制乌龟运动案例。
话题获取
显示了节点的话题
消息获取
通过上面获取的话题名来获取消息type
获取消息格式:
乌龟线速度取值只有x和角速度z
因为只有前后左右四个键位控制运动
来验证一下
可以看到只有线速度x和角速度y
因为只有上下左右四个键
上下控制线速度x
左右控制角速度z
弧度: 单位弧度定义为圆弧长度等于半径时的圆心角。
输入这一段,然后一直按Tab补全
改成这个
然后回车
就简单实现了
新建功能包
建立依赖
新建文件
复制以下代码
- /*
- 编写 ROS 节点,控制小乌龟画圆
- 准备工作:
- 1.获取topic(已知: /turtle1/cmd_vel)
- 2.获取消息类型(已知: geometry_msgs/Twist)
- 3.运行前,注意先启动 turtlesim_node 节点
- 实现流程:
- 1.包含头文件
- 2.初始化 ROS 节点
- 3.创建发布者对象
- 4.循环发布运动控制消息
- */
-
- #include "ros/ros.h"
- #include "geometry_msgs/Twist.h"
-
- int main(int argc, char *argv[])
- {
- setlocale(LC_ALL,"");
- // 2.初始化 ROS 节点
- ros::init(argc,argv,"control");
- ros::NodeHandle nh;
- // 3.创建发布者对象
- ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",1000);
- // 4.循环发布运动控制消息
- //4-1.组织消息
- geometry_msgs::Twist msg;
- msg.linear.x = 1.0;
- msg.linear.y = 0.0;
- msg.linear.z = 0.0;
-
- msg.angular.x = 0.0;
- msg.angular.y = 0.0;
- msg.angular.z = 2.0;
-
- //4-2.设置发送频率
- ros::Rate r(10);
- //4-3.循环发送
- while (ros::ok())
- {
- pub.publish(msg);
-
- ros::spinOnce();
- }
-
-
- return 0;
- }
然后编译
运行完成
如果出现编译无异常,但是运行起来,小乌龟不动的话,肯定是话题名有问题输错了
新建文件
复制以下代码
- #! /usr/bin/env python
- """
- 编写 ROS 节点,控制小乌龟画圆
- 准备工作:
- 1.获取topic(已知: /turtle1/cmd_vel)
- 2.获取消息类型(已知: geometry_msgs/Twist)
- 3.运行前,注意先启动 turtlesim_node 节点
- 实现流程:
- 1.导包
- 2.初始化 ROS 节点
- 3.创建发布者对象
- 4.循环发布运动控制消息
- """
-
- import rospy
- from geometry_msgs.msg import Twist
-
- if __name__ == "__main__":
- # 2.初始化 ROS 节点
- rospy.init_node("control_circle_p")
- # 3.创建发布者对象
- pub = rospy.Publisher("/turtle1/cmd_vel",Twist,queue_size=1000)
- # 4.循环发布运动控制消息
- rate = rospy.Rate(10)
- msg = Twist()
- msg.linear.x = 1.0
- msg.linear.y = 0.0
- msg.linear.z = 0.0
- msg.angular.x = 0.0
- msg.angular.y = 0.0
- msg.angular.z = 0.5
-
- while not rospy.is_shutdown():#判断rospy是否是关闭状态,如果不是运行以下代码
- pub.publish(msg)
- rate.sleep()
授予权限
修改配置
编译
打开终端测试
此处实现成功
需求描述: 已知turtlesim中的乌龟显示节点,会发布当前乌龟的位姿(窗体中乌龟的坐标以及朝向),要求控制乌龟运动,并时时打印当前乌龟的位姿。
实现分析:
- 首先,需要启动乌龟显示以及运动控制节点并控制乌龟运动。
- 要通过ROS命令,来获取乌龟位姿发布的话题以及消息。
- 编写订阅节点,订阅并打印乌龟的位姿。
实现流程:
- 通过ros命令获取话题与消息信息。
- 编码实现位姿获取节点。
- 启动 roscore、turtlesim_node 、控制节点以及位姿订阅节点,控制乌龟运动并输出乌龟的位姿。
话题与消息获取
先编写一个launch文件
实现订阅节点
创建功能包需要依赖的功能包: roscpp rospy std_msgs turtlesim
直接修改包依赖
然后编译一下看看有没有问题
然后修改CMakeLists
然后复制以下代码
- /*
- 订阅小乌龟的位姿: 时时获取小乌龟在窗体中的坐标并打印
- 准备工作:
- 1.获取话题名称 /turtle1/pose
- 2.获取消息类型 turtlesim/Pose
- 3.运行前启动 turtlesim_node 与 turtle_teleop_key 节点
- 实现流程:
- 1.包含头文件
- 2.初始化 ROS 节点
- 3.创建 ROS 句柄
- 4.创建订阅者对象
- 5.回调函数处理订阅的数据
- 6.spin
- */
-
- #include "ros/ros.h"
- #include "turtlesim/Pose.h"
-
- void doPose(const turtlesim::Pose::ConstPtr& p){
- ROS_INFO("乌龟位姿信息:x=%.2f,y=%.2f,theta=%.2f,lv=%.2f,av=%.2f",
- p->x,p->y,p->theta,p->linear_velocity,p->angular_velocity
- );
- }
-
- int main(int argc, char *argv[])
- {
- setlocale(LC_ALL,"");
- // 2.初始化 ROS 节点
- ros::init(argc,argv,"sub_pose");
- // 3.创建 ROS 句柄
- ros::NodeHandle nh;
- // 4.创建订阅者对象
- ros::Subscriber sub = nh.subscribe<turtlesim::Pose>("/turtle1/pose",1000,doPose);
- // 5.回调函数处理订阅的数据
- // 6.spin
- ros::spin();
- return 0;
- }
然后打开终端进行测试
实现成功
新建文件
复制以下代码
- #! /usr/bin/env python
- """
- 订阅小乌龟的位姿: 时时获取小乌龟在窗体中的坐标并打印
- 准备工作:
- 1.获取话题名称 /turtle1/pose
- 2.获取消息类型 turtlesim/Pose
- 3.运行前启动 turtlesim_node 与 turtle_teleop_key 节点
- 实现流程:
- 1.导包
- 2.初始化 ROS 节点
- 3.创建订阅者对象
- 4.回调函数处理订阅的数据
- 5.spin
- """
-
- import rospy
- from turtlesim.msg import Pose
-
- def doPose(data):
- rospy.loginfo("乌龟坐标:x=%.2f, y=%.2f,theta=%.2f",data.x,data.y,data.theta)
- #指向节点里的信息(data只是一个名字可以任意取)
-
- if __name__ == "__main__":
-
- # 2.初始化 ROS 节点
- rospy.init_node("sub_pose_p")
-
- # 3.创建订阅者对象
- sub = rospy.Subscriber("/turtle1/pose",Pose,doPose,queue_size=1000)
- # 4.回调函数处理订阅的数据
- # 5.spin
- rospy.spin()
修改CMakeList
授予权限
编译
然后打开终端测试
实现成功
需求描述:编码实现向 turtlesim 发送请求,在乌龟显示节点的窗体指定位置生成一乌龟,这是一个服务请求操作。
实现分析:
- 首先,需要启动乌龟显示节点。
- 要通过ROS命令,来获取乌龟生成服务的服务名称以及服务消息类型。
- 编写服务请求节点,生成新的乌龟。
实现流程:
- 通过ros命令获取服务与服务消息信息。
- 编码实现服务请求节点。
- 启动 roscore、turtlesim_node 、乌龟生成节点,生成新的乌龟。
先启动launch文件打开乌龟
服务名称与服务消息获取
输入这一行命令后按Tab补齐
输入对应指令后生成了一只新的乌龟
新建文件此处依赖跟上一个实现一致,所以不再修改依赖
复制以下代码
- /*
- 生成一只小乌龟
- 准备工作:
- 1.服务话题 /spawn
- 2.服务消息类型 turtlesim/Spawn
- 3.运行前先启动 turtlesim_node 节点
- 实现流程:
- 1.包含头文件
- 需要包含 turtlesim 包下资源,注意在 package.xml 配置
- 2.初始化 ros 节点
- 3.创建 ros 句柄
- 4.创建 service 客户端
- 5.等待服务启动
- 6.发送请求
- 7.处理响应
- */
-
- #include "ros/ros.h"
- #include "turtlesim/Spawn.h"
-
- int main(int argc, char *argv[])
- {
- setlocale(LC_ALL,"");
- // 2.初始化 ros 节点
- ros::init(argc,argv,"set_turtle");
- // 3.创建 ros 句柄
- ros::NodeHandle nh;
- // 4.创建 service 客户端
- ros::ServiceClient client = nh.serviceClient<turtlesim::Spawn>("/spawn");
- // 5.等待服务启动
- // client.waitForExistence();
- ros::service::waitForService("/spawn");
- // 6.发送请求
- turtlesim::Spawn spawn;
- spawn.request.x = 1.0;
- spawn.request.y = 1.0;
- spawn.request.theta = 1.57;
- spawn.request.name = "my_turtle";
- bool flag = client.call(spawn);
- // 7.处理响应结果
- if (flag)
- {
- ROS_INFO("新的乌龟生成,名字:%s",spawn.response.name.c_str());
- } else {
- ROS_INFO("乌龟生成失败!!!");
- }
-
-
- return 0;
- }
修改配置
编译
打开终端测试
运行成功
新建文件
复制以下代码
- #! /usr/bin/env python
- """
- 生成一只小乌龟
- 准备工作:
- 1.服务话题 /spawn
- 2.服务消息类型 turtlesim/Spawn
- 3.运行前先启动 turtlesim_node 节点
- 实现流程:
- 1.导包
- 需要包含 turtlesim 包下资源,注意在 package.xml 配置
- 2.初始化 ros 节点
- 3.创建 service 客户端
- 4.等待服务启动
- 5.发送请求
- 6.处理响应
- """
-
- import rospy
- from turtlesim.srv import Spawn,SpawnRequest,SpawnResponse
-
- if __name__ == "__main__":
- # 2.初始化 ros 节点
- rospy.init_node("set_turtle_p")
- # 3.创建 service 客户端
- client = rospy.ServiceProxy("/spawn",Spawn)
- # 4.等待服务启动
- client.wait_for_service()
- # 5.发送请求
- req = SpawnRequest()
- req.x = 2.0
- req.y = 2.0
- req.theta = -1.57
- req.name = "my_turtle_p"
- try:
- response = client.call(req)
- # 6.处理响应
- rospy.loginfo("乌龟创建成功!,叫:%s",response.name)
- except expression as identifier:
- rospy.loginfo("服务调用失败")
授权
修改配置
编译
终端中打开
运行成功
需求描述: 修改turtlesim乌龟显示节点窗体的背景色,已知背景色是通过参数服务器的方式以 rgb 方式设置的。
实现分析:
- 首先,需要启动乌龟显示节点。
- 要通过ROS命令,来获取参数服务器中设置背景色的参数。
- 编写参数设置节点,修改参数服务器中的参数值。
实现流程:
- 通过ros命令获取参数。
- 编码实现服参数设置节点。
- 启动 roscore、turtlesim_node 与参数设置节点,查看运行结果。
用终端启动小乌龟GUI
不用launch启动的原因
因为launch同时启动roscore和GUI节点
更新参数后需要重启节点
关闭了launch后roscore也关闭了
参数服务器重置
更新的参数失效
所以用终端
保持roscore启动的同时关闭节点
让节点从roscore参数服务器中重新获取参数更新GUI
这里可以看到三个参数的值构成了这样的背景色
修改后颜色没变
是因为节点启动的时候调用的未修改的参数
重新启动节点即可
新建文件
复制以下代码
- /*
- 注意命名空间的使用。
- */
- #include "ros/ros.h"
-
-
- int main(int argc, char *argv[])
- {
- ros::init(argc,argv,"haha");
-
- ros::NodeHandle nh("turtlesim");
- //ros::NodeHandle nh;
-
- // ros::param::set("/turtlesim/background_r",0);
- // ros::param::set("/turtlesim/background_g",0);
- // ros::param::set("/turtlesim/background_b",0);
-
- nh.setParam("background_r",0);
- nh.setParam("background_g",0);
- nh.setParam("background_b",0);
-
-
- return 0;
- }
修改配置
编译
打开终端测试
变成黑色了
代码如下
测试
新建文件
授予权限
修改配置
此处注意,编译是针对整个功能包进行编译,会自动保存
打开终端测试
三种通信机制中,参数服务器是一种数据共享机制,可以在不同的节点之间共享数据,话题通信与服务通信是在不同的节点之间传递数据的,三者是ROS中最基础也是应用最为广泛的通信机制。
这其中,话题通信和服务通信有一定的相似性也有本质上的差异,在此将二者做一下简单比较:
二者的实现流程是比较相似的,都是涉及到四个要素:
下表为话题通信和服务通信比较
话题通信可以理解成打电话(a要联系b)
服务通信可以理解成跟服务商联系进行服务(比如说a要计算1+1,发给了b,b算好了发给a)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。