文章目录
- 前言
- 1. 参数服务器理论模型
- 2. 参数操作(C++)
- 2.1 增加参数
- 2.2 参数修改
- 2.3 参数的获取
- 2.3.1 ros::NodeHandle
- 2.3.2 ros::param
- 2.4 参数的删除
- 3. 参数操作(python)
- 3.1 增加参数与修改参数
- 3.2 获取参数
- 3.3 删除参数
前言
📢本系列将依托赵虚左老师的ROS课程,写下自己的一些心得与笔记。
📢课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ
📢讲义链接:http://www.autolabor.com.cn/book/ROSTutorials/index.html
📢 文章可能存在疏漏的地方,恳请大家指出。
参数服务器在ROS中主要用于实现不同节点之间的数据共享。参数服务器相当于是独立于所有节点的一个公共容器,可以将数据存储在该容器中,被不同的节点调用,当然不同的节点也可以往其中存储数据。
概念
以共享的方式实现不同节点之间数据交互的通信模式。
作用
存储一些多节点共享的数据,类似于全局变量。
1. 参数服务器理论模型
参数服务器实现是最为简单的,该模型如下图所示,该模型中涉及到三个角色:
- ROS Master (管理者)
- Talker (参数设置者)
- Listener (参数调用者)
ROS Master 作为一个公共容器保存参数,Talker 可以向容器中设置参数,Listener 可以获取参数。
整个流程由以下步骤实现:
1.Talker 设置参数
Talker 通过 RPC 向参数服务器发送参数(包括参数名与参数值),ROS Master 将参数保存到参数列表中。
2.Listener 获取参数
Listener 通过 RPC 向参数服务器发送参数查找请求,请求中包含要查找的参数名。
3.ROS Master 向 Listener 发送参数值
ROS Master 根据步骤2请求提供的参数名查找参数值,并将查询结果通过 RPC 发送给 Listener。
参数可使用数据类型:
- 32-bit integers
- booleans
- strings
- doubles
- iso8601 dates
- lists
- base64-encoded binary data
- 字典
2. 参数操作(C++)
在 C++ 中实现参数服务器数据的增删改查,可以通过两套 API 实现:
- ros::NodeHandle
- ros::param
2.1 增加参数
#include "ros/ros.h"
/*
实现参数的新增与修改
需求:首先设置机器人的共享参数、类型、半径(0.15m)
实现:
ros::NodeHandle
setParam()
ros::param
set()
*/
int main(int argc, char *argv[])
{
//初始化ros节点
ros::init(argc,argv,"set_param");
//创建ROS节点句柄
ros::NodeHandle nh;
//参数增
//方案1:nh
nh.setParam("type","silun");
nh.setParam("radius",0.15);
//方案2:ros::param
ros::param::set("type_param","silun");
ros::param::set("radius_param",0.15);
//参数改
return 0;
}
配置完后,运行如下
使用rosparam list
可以查看参数是否已经设置进入参数服务器
rosparam list
使用rosparam get 参数名
可以查看所设置的参数值。
2.2 参数修改
#include "ros/ros.h"
/*
实现参数的新增与修改
需求:首先设置机器人的共享参数、类型、半径(0.15m)
实现:
ros::NodeHandle
setParam()
ros::param
set()
*/
int main(int argc, char *argv[])
{
//初始化ros节点
ros::init(argc,argv,"set_param");
//创建ROS节点句柄
ros::NodeHandle nh;
//参数增
//方案1:nh
nh.setParam("type","silun");
nh.setParam("radius",0.15);
//方案2:ros::param
ros::param::set("type_param","silun");
ros::param::set("radius_param",0.15);
//参数改
//方案1:nh
nh.setParam("radius",0.20);
//方案2:ros::param
ros::param::set("radius_param",0.25);
return 0;
}
重新rosrun后,再查看参数:
参数的修改其实是一个参数覆盖的过程。
2.3 参数的获取
2.3.1 ros::NodeHandle
param(键,默认值)
存在,返回对应结果,否则返回默认值
getParam(键,存储结果的变量)
存在,返回 true,且将值赋值给参数2
若果键不存在,那么返回值为 false,且不为参数2赋值
getParamCached(键,存储结果的变量)–提高变量获取效率
存在,返回 true,且将值赋值给参数2
若果键不存在,那么返回值为 false,且不为参数2赋值
会判断之前是否已经查询过参数,若查询过,直接从本地返回。是底层性能上的提升。一般情况下看不出来
getParamNames(std::vector<std::string>)
获取所有的键,并存储在参数 vector 中
hasParam(键)
是否包含某个键,存在返回 true,否则返回 false
searchParam(参数1,参数2)
搜索键,参数1是被搜索的键,参数2存储搜索结果的变量
2.3.2 ros::param
ros::param基本与nodehandle方式一致。
#include "ros/ros.h"
/*
实现参数的查询
实现:
ros::NodeHandle
param(键,默认值)
存在,返回对应结果,否则返回默认值
getParam(键,存储结果的变量)
存在,返回 true,且将值赋值给参数2
若果键不存在,那么返回值为 false,且不为参数2赋值
getParamCached键,存储结果的变量)--提高变量获取效率
存在,返回 true,且将值赋值给参数2
若果键不存在,那么返回值为 false,且不为参数2赋值
getParamNames(std::vector<std::string>)
获取所有的键,并存储在参数 vector 中
hasParam(键)
是否包含某个键,存在返回 true,否则返回 false
searchParam(参数1,参数2)
搜索键,参数1是被搜索的键,参数2存储搜索结果的变量
ros::param ----- 与 NodeHandle 类似
*/
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
//初始化ros节点
ros::init(argc,argv,"get_param");
//创建ROS节点句柄
ros::NodeHandle nh;
//param(键,默认值)
double radius = nh.param("radius",0.5);
ROS_INFO("查询结果为: radius=%lf",radius);
// getParam(键,存储结果的变量)
double radius2 = 0.0;
bool result1 = nh.getParam("radius",radius2);
if(result1)
{
ROS_INFO("查询变量为:%0.2f",radius2);
}
else
{
ROS_INFO("结果不存在");
}
//getParamCached键,存储结果的变量)--提高变量获取效率
double radius3= 0.0;
bool result2 = nh.getParamCached("radius1",radius3);
if(result2)
{
ROS_INFO("查询变量为:%0.3f",radius3);
}
else
{
ROS_INFO("结果不存在");
}
// getParamNames(std::vector<std::string>)
std::vector<std::string> names;
nh.getParamNames(names);
for(auto &&name : names)
{
ROS_INFO("遍历的元素:%s",name.c_str());
}
//hasParam(键)
bool flag1 = nh.hasParam("radius");
bool flag2 = nh.hasParam("");
ROS_INFO("查询的元素是否存在:%d",flag1);
ROS_INFO("查询的元素是否存在:%d",flag2);
//searchParam(参数1,参数2)
std::string key;
nh.searchParam("raduis",key);
ROS_INFO("搜寻到的结果为:%s",key.c_str());
nh.searchParam("radius",key);
ROS_INFO("搜寻到的结果为:%s",key.c_str());
//ros::param
double radius_param = ros::param::param("radius",10);
ROS_INFO("结果为:%lf",radius_param);
return 0;
}
2.4 参数的删除
ros::NodeHandle
deleteParam(“键”)
根据键删除参数,删除成功,返回 true,否则(参数不存在),返回 false
ros::param
del(“键”)
根据键删除参数,删除成功,返回 true,否则(参数不存在),返回 false
#include "ros/ros.h"/*
参数服务器操作之删除_C++实现:
ros::NodeHandle
deleteParam("键")
根据键删除参数,删除成功,返回 true,否则(参数不存在),返回 false
ros::param
del("键")
根据键删除参数,删除成功,返回 true,否则(参数不存在),返回 false
*/
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
//初始化ros节点
ros::init(argc,argv,"get_param");
//创建ROS节点句柄
ros::NodeHandle nh;
// ros::NodeHandle
bool flag1 = nh.deleteParam("radius");
if(flag1){
ROS_INFO("删除成功");
}
else{
ROS_INFO("删除失败");
}
//ros::param
bool flag2 =ros::param::del("radius");
if(flag2){
ROS_INFO("删除2成功");
}
else{
ROS_INFO("删除2失败");
}
return 0;
}
3. 参数操作(python)
3.1 增加参数与修改参数
#! /usr/bin/env python
#-- coding:UTF-8 --
"""
参数服务器操作之新增与修改(二者API一样)_Python实现:
"""
import rospy
if __name__ == "__main__":
rospy.init_node("set_update_paramter_p")
# 设置各种类型参数
rospy.set_param("p_int",10)
rospy.set_param("p_double",3.14)
rospy.set_param("p_bool",True)
rospy.set_param("p_string","hello python")
rospy.set_param("p_list",["hello","haha","xixi"])
rospy.set_param("p_dict",{"name":"hulu","age":8})
# 修改
rospy.set_param("p_int",100)
3.2 获取参数
#! /usr/bin/env python
#-- coding:UTF-8 --
"""
参数服务器操作之查询_Python实现:
get_param(键,默认值)
当键存在时,返回对应的值,如果不存在返回默认值
get_param_cached
get_param_names
has_param
search_param
"""
import rospy
if __name__ == "__main__":
rospy.init_node("get_param_p")
#获取参数
int_value = rospy.get_param("p_int",10000)
double_value = rospy.get_param("p_double")
bool_value = rospy.get_param("p_bool")
string_value = rospy.get_param("p_string")
p_list = rospy.get_param("p_list")
p_dict = rospy.get_param("p_dict")
rospy.loginfo("获取的数据:%d,%.2f,%d,%s",
int_value,
double_value,
bool_value,
string_value)
for ele in p_list:
rospy.loginfo("ele = %s", ele)
rospy.loginfo("name = %s, age = %d",p_dict["name"],p_dict["age"])
# get_param_cached
int_cached = rospy.get_param_cached("p_int")
rospy.loginfo("缓存数据:%d",int_cached)
# get_param_names
names = rospy.get_param_names()
for name in names:
rospy.loginfo("name = %s",name)
rospy.loginfo("-"*80)
# has_param
flag = rospy.has_param("p_int")
rospy.loginfo("包含p_int吗?%d",flag)
# search_param
key = rospy.search_param("p_int")
rospy.loginfo("搜索的键 = %s",key)
3.3 删除参数
#! /usr/bin/env python
#-- coding:UTF-8 --
"""
参数服务器操作之删除_Python实现:
rospy.delete_param("键")
键存在时,可以删除成功,键不存在时,会抛出异常
"""
import rospy
if __name__ == "__main__":
rospy.init_node("delete_param_p")
try:
rospy.delete_param("p_int")
except Exception as e:
rospy.loginfo("删除失败")
/p_int 被删除