上一篇:奥特学园ROS笔记--1_echo_gou的博客-CSDN博客_奥特学园ros
目录
----------2.3参数----------
76节 参数服务器
参数服务器在ROS中主要用于实现不同节点之间的数据共享。参数服务器相当于是独立于所有节点的一个公共容器,可以将数据存储在该容器中,被不同的节点调用,当然不同的节点也可以往其中存储数据。
作用类似于全局变量
77节 参数服务器模型
整个流程由以下步骤实现:
1.Talker 设置参数:Talker 通过 RPC 向参数服务器发送参数(包括参数名与参数值),ROS Master 将参数保存到参数列表中。
2.Listener 获取参数:Listener 通过 RPC 向参数服务器发送参数查找请求,请求中包含要查找的参数名。
3.ROS Master 向 Listener 发送参数值:ROS Master 根据步骤2请求提供的参数名查找参数值,并将查询结果通过 RPC 发送给 Listener。
参数可使用的数据类型:
78节 参数操作(c++)
增加param
1新建功能包,并且创建cpp文件
2编写代码
#include "ros/ros.h"
int main(int argc, char *argv[])
{
ros::init(argc,argv,"set_param_c");
ros::NodeHandle nh;
//方法1
nh.setParam("type","xiaohuang"); //前面是键后面是值
nh.setParam("radius",0.15);
//方法2
ros::param::set("type_param","xiaobai");
ros::param::set("radius_param",0.16);
return 0;
}
3配置
4启动roscore的时候可以发现参数服务器已经启动,图中最下面
5 然后编译运行:将参数设置进参数服务器
6 列出参数:使用语句rosparam list列出参数服务器的所有参数
7 查看参数的值:使用以下命令
8修改参数:命名一样即可进行修改
79、80、81节 参数操作
79-80:
nh.param
nh.getParam
nh.getParamCached 结果上和上一个一样,只是提高获取变量的效率
nh.getParamNames 获取所有的参数(键)名称保存到vector当中
nh.hasParam 键是否存在
nh.searchParam 搜索键名,如果不存在搜索结果为空
81:
ros::param::中也有和79-80内容对应的函数,
#include "ros/ros.h"
//都使用的nh.xxx这种方式调用
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
ros::init(argc,argv,"get_param_c");
ros::NodeHandle nh;
//1 .param
double radius1=nh.param("radius_param",0.5); //查询radius的值如果没有则返回-1
ROS_INFO("1:%lf",radius1);
//2 .getParam
double radius2=0;
bool result2=nh.getParam("radius",radius2); //将查询结果放入radiu2中,查询成功返回true否则返回false。
if(result2){
ROS_INFO("2:%lf",radius2);
}
else{
ROS_INFO("查询的值不存在");
}
//3 .getParamCached 结果上和上一个一样,只是提高获取变量的效率
double radius3=0;
bool result3=nh.getParamCached("radius",radius3);
if(result3){
ROS_INFO("3:%lf",radius3);
}
else{
ROS_INFO("查询的值不存在");
}
//4 .getParamNames 获取所有的参数(键)名称保存到vector当中
std::vector<std::string> names;
nh.getParamNames(names);
ROS_INFO("获取的键有:");
for(int i=0;i<names.size();i++){
ROS_INFO("%s",names[i].c_str());
}
// for(auto &&name:names){ //这里是老师写的遍历,不太懂,其中&&name中删除一个&也是可以工作运行的??
// ROS_INFO("遍历的元素:%s",name.c_str());
// }
//5 .hasParam 键是否存在
bool flag1=nh.hasParam("radius");
bool flag2=nh.hasParam("radius2");
ROS_INFO("键是否存在:%d %d",flag1,flag2);
//6 .searchParam 搜索键名,如果不存在搜索结果为空
std::string key;
nh.searchParam("radius",key);
ROS_INFO("搜索结果:%s",key.c_str());
return 0;
}
81节:
这里就不一一列举了
eg:
82节 参数操作(删除)
#include "ros/ros.h"
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
ros::init(argc,argv,"param_del_c");
ros::NodeHandle nh;
bool flag1=nh.deleteParam("radius");
if(flag1){
ROS_INFO("删除成功");
}
else{
ROS_INFO("删除失败");
}
//方法2
bool flag2 = ros::param::del("radius_param");
if(flag2){
ROS_INFO("删除成功");
}else{
ROS_INFO("删除失败");
}
return 0;
}
84节 参数操作(python)
增加param
#! /usr/bin/env python
#coding-UTF-8
import rospy
if __name__=="__main__":
rospy.init_node("param_set_p")
rospy.set_param("radius_p",0.11)
rospy.set_param("type_p","helllo")
然后编译运行:
查看是否加入param成功
85节 参数操作(python)
查询
首先和84节一样cmake配置和给执行权限
然后:
#! /usr/bin/env python
#coding=UTF-8
import rospy
if __name__=="__main__":
rospy.init_node("get_paam_p")
#.get_param获取param的值,如果没有返回-1
radius1=rospy.get_param("radius_p",-1) #
radius2=rospy.get_param("radius_p_xxx",-1) #
rospy.loginfo("radius_p=%f",radius1)
rospy.loginfo("radius_p_xxx=%f",radius2)
#.get_param_cached 和上一个类似只是速度更快
radius3=rospy.get_param_cached("radius_p",-1) #
radius4=rospy.get_param_cached("radius_p_xxx",-1) #
rospy.loginfo("radius_p=%f",radius3)
rospy.loginfo("radius_p_xxx=%f",radius4)
#.get_param_names 获取所有键
names=rospy.get_param_names()
for name in names:
rospy.loginfo("name=%s",name)
#键是否存在
flag1=rospy.has_param("radius_p")
if(flag1):
rospy.loginfo("存在")
else:
rospy.loginfo("不存在")
flag2=rospy.has_param("radius_p_xxx")
if(flag2):
rospy.loginfo("存在")
else:
rospy.loginfo("不存在")
#.search_param 查找某个参数的键并且返回完整健名
key=rospy.search_param("radius_p")
rospy.loginfo("%s",key)
86节 参数操作(python)
删除
首先创建文件并且添加可执行权限
然后代码:
#! /usr/bin/env python
#coding=UTF-8
import rospy
if __name__=="__main__":
rospy.init_node("param_del_p")
try:
rospy.delete_param("radius_p")
except Exception as e:
rospy.loginfo("删除的键不存在")
----------2.4常用命令----------
88节 常用命令
88节
在 ROS 同提供了一些实用的命令行工具,可以用于获取不同节点的各类信息,常用的命令如下:
2.4 常用命令 · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程
- rosnode : 操作节点
- rostopic : 操作话题
- rosservice : 操作服务
- rosmsg : 操作msg消息
- rossrv : 操作srv消息
- rosparam : 操作参数
在ROS程序启动后,可以动态的获取运行中的节点或参数的相关信息。
官网:
http://wiki.ros.org/ROS/CommandLineTool
89节
需要查看某个命令的使用可以直接输入这个命令来查看:
我们运行之前写的_pub_sub的文件
命令行输入相关命令即可:
eg:
89-94节 常用命令汇总
----------2.5通信机制实操----------
96节 通信机制实操1 话题发布
编码实现乌龟运动控制,让小乌龟做圆周运动。
实现流程:
1通过计算图结合ros命令获取话题与消息类型信息。
2编码实现运动控制节点。
3启动 roscore、turtlesim_node 以及自定义的控制节点,查看运行结果。
97节 话题和消息格式获取
首先启动小乌龟,然后查看计算图
可以发现箭头上面的文本(/turtle1/cmd_vel)就是两个节点之间的话题
然后通过rostopic info /turtle1/cmd_vel来获取话题的相关信息(或者使用rostopic type),其中就有消息类型
然后使用rosmsg info(或者show) 来获取消息里面的具体格式
98节 线速度和角速度
上节最后一个图中,分为了线速度和角速度。因为乌龟只能前后运动,所以这里只有x的线速度;同时乌龟只有z轴方向的角速度。
线速度xyz中x表示前进和后退,y表示左右平移,z表示上下移动
角速度:速度为rad/s,1s转一圈就是2π rad/s。角速度的xyz可以理解为飞机的这三种运动方式,运动方向为x轴所在(理解为牙通牙式旋转),垂直与平面的是y轴(理解为飞机抬头或者低头),与另外两者垂直为z轴(理解为像扑克飞出去类似的旋转)
99节 验证98节
运行小乌龟
输入
然后去控制小乌龟即可echo输出相关信息:
这里猜测从原点向轴的正方向看去,顺时针就位正的角速度。
100节 控制乌龟运动(c++)
100节:
首先可以使用命令行(rostopic pub)的简单方式来控制,但不能实现更复杂的运行。
101节:
新建功能包,依赖geometry_msgs,roscpp,rospy,std_msgs。然后创建一个cpp文件。
之前已经获取话题为 /turtle/cmd_vel,消息类为型goemetry_msg/Twist中编写的。
代码:
#include "ros/ros.h"
#include "geometry_msgs/Twist.h"
int main(int argc, char *argv[])
{
ros::init(argc,argv,"my_control");
ros::NodeHandle nh;
ros::Publisher pub=nh.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",10); //创建发布者对象
ros::Rate rate(10);
geometry_msgs::Twist twist;
twist.linear.x=1;
// twist.linear.y=0;
// twist.linear.z=0;
twist.angular.x=0;
// twist.angular.y=0;
// twist.angular.z=1;
while(ros::ok()){
pub.publish(twist);
rate.sleep();
ros::spinOnce();
}
return 0;
}
然后配置CMakeLists
运行
102节 控制乌龟运动(python)
创建文件
代码
#! /usr/bin/env python
#coding=UTF-8
import rospy
from geometry_msgs.msg import Twist
if __name__=="__main__":
rospy.init_node("my_control_p")
pub=rospy.Publisher("/turtle1/cmd_vel",Twist,queue_size=10)
rate=rospy.Rate(10)
twist=Twist()
twist.linear.x=1
twist.linear.y=0
twist.linear.z=0
twist.angular.x=0
twist.angular.y=0
twist.angular.z=1
while not rospy.is_shutdown():
pub.publish(twist)
rate.sleep()
然后chmod改权限
配置CMakeLists
运行
103节 通信机制实操2 话题订阅
已知turtlesim中的乌龟显示节点,会发布当前乌龟的位姿(窗体中乌龟的坐标以及朝向),要求控制乌龟运动,并实时打印当前乌龟的位姿。
首先,需要启动乌龟显示以及运动控制节点并控制乌龟运动。
要通过ROS命令,来获取乌龟位姿发布的话题以及消息。
编写订阅节点,订阅并打印乌龟的位姿。
104节 输出乌龟位姿
首先为了方便我们创建一个.launch文件
然后运行.launch文件
然后查看话题相关的信息
105、106节 输出乌龟位姿
命令行方式:
rostopic echo /turtle1/pose
代码实现:
实现之前进行配置,因为之前已经创建过功能包了,所以这里我们在上一个功能包的基础上对package和CMakeLists进行修改即可
加入turtlesim依赖
CMakeLists
配置完了开始编码
#include "ros/ros.h"
#include "turtlesim/Pose.h"
void doPose(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,doPose);
ros::spin();
return 0;
}
配置CMakeLists
然后运行,先运行.launch文件,再运行编写的这个代码
107节 python实现
略
108节 实操3 服务调用
实现流程:
- 通过ros命令获取服务与服务消息信息。
- 编码实现服务请求节点。
- 启动 roscore、turtlesim_node 、乌龟生成节点,生成新的乌龟。
109节 信息获取
首先启动之前编写的.launch文件
然后分别是:获取服务话题,话题的自定义类型,和其中的数据组成。
其中Args为生成乌龟所需要提交的信息
110、111节
命令行方式:输入rosservice call /spawn点回车即可
首先创建文件test03_service_client.cpp
代码
#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.x=1;
spawn.request.y=2;
spawn.request.name="turtle2";
spawn.request.theta=1.57;
client.waitForExistence();
bool flag = client.call(spawn);
if(flag){
ROS_INFO("乌龟生成成功");
}else{
ROS_INFO("请求失败");
}
return 0;
}
配置CMakeLists
运行:
112节 python实现
#! /usr/bin/env python
#coding=UTF-8
from distutils.spawn import spawn
from logging import exception
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=3
request.y=3
request.theta=-1
request.name="turtle3"
client.wait_for_service()
try:
response= client.call(request)
rospy.loginfo("生成乌龟的名字:%s",response.name)
except Exception as e:
rospy.loginfo("请求处理异常")
设置权限
配置CMakeLists
运行
113节 实操4 参数设置
需求描述: 修改turtlesim乌龟显示节点窗体的背景色,已知背景色是通过参数服务器的方式以 rgb 方式设置的。
实现分析:
- 首先,需要启动乌龟显示节点。
- 要通过ROS命令,来获取参数服务器中设置背景色的参数。
- 编写参数设置节点,修改参数服务器中的参数值。
114、115、116节
命令行方式:
启动roscore 和乌龟节点(注意这里不能使用launch文件来启动,因为我们要去修改的参数数保存在roscore中的,如果使用roslaunch,每次使用的时候roscore都会重启,这样之前改变的参数就重置了)
获取参数并且修改
修改后重启节点即可
115节 代码方式:
#include "ros/ros.h"
/*
1初始化节点
2不一定需要创建句柄
3修改参数
*/
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
ros::init(argc,argv,"change_color");
ros::param::set("/turtlesim/background_r",0);
ros::param::set("/turtlesim/background_g",0);
ros::param::set("/turtlesim/background_b",0);
return 0;
}
配置CMakeLists运行
116节:
或者使用句柄方式:
117节 python实现
代码:
#! /usr/bin/env python
#coding=UTF-8
import rospy
if __name__=="__main__":
rospy.init_node("change_color_p")
rospy.set_param("/turtlesim/background_r",0)
rospy.set_param("/turtlesim/background_g",0)
rospy.set_param("/turtlesim/background_b",0)
赋予权限,配置CMakeLists
运行
119节 通信机制比较
三种通信机制中,参数服务器是一种数据共享机制,可以在不同的节点之间共享数据,话题通信与服务通信是在不同的节点之间传递数据的,三者是ROS中最基础也是应用最为广泛的通信机制。