参数服务器是以参数共享模式实现的,参数服务器在ROS中主要用于实现不同节点之间的数据共享。参数服务器相当于是独立于所有节点的一个公共容器,可以将数据存储在该容器中,被不同的节点调用,当然不同的节点也可以往其中存储数据。参数服务器,一般适用于存在数据共享的一些应用场景。
**注意:**参数服务器不是为高性能而设计的,因此最好用于存储静态的非二进制的简单数据。
一、参数服务器理论模型图
二、角色
参数服务器实现是三种通信机制中最为简单的,该模型如下图所示,该模型中涉及到三个角色:
- ROS Master (管理者)
- Talker (参数设置者)
- Listener (参数调用者)
ROS Master 作为一个公共容器保存参数,Talker 可以向容器中设置参数,Listener 可以获取参数。
三、流程
1、Talker 设置参数
setParam("foo",1)
Talker 通过 RPC 向参数服务器发送参数(包括参数名与参数值),ROS Master 将参数保存到参数列表中。
2、Listener 请求获取参数
getParam("foo")
Listener 通过 RPC 向参数服务器发送参数查找请求,请求中包含要查找的参数名。
3、ROS Master 向 Listener 发送参数值
{foo:1}
ROS Master 根据步骤2请求提供的参数名查找参数值,并将查询结果通过 RPC 发送给 Listener。
四、C++实现参数服务器参数的增删改查操作
ros在NodeHandle和param下都有一套增删改查的命令。
4.1 参数服务器增、改参数
#include "ros/ros.h"
/*
需要实现参数的新增和修改
需求:
首先设置机器人的共享参数,"名字"、"半径"
再修改半径
实现:
1、ros::NodeHandle
setParam("键",值)
2、ros::param
set("键","值")
*/
int main(int argc, char *argv[])
{
/* code */
setlocale(LC_ALL,"");
//初始化节点
ros::init(argc,argv,"add_modify_param");
//创建节点句柄
ros::NodeHandle nh;
//---------参数增-----------
//方案1、nh
nh.setParam("name","robot1");
nh.setParam("radius",0.15);
//方案2、ros::param
ros::param::set("name_param","robot2");
ros::param::set("radius_param",0.2);
//---------参数改:其实就是用增的命令覆盖原来的数据-----------
//方案1、nh
// nh.setParam("radius",0.155);
//方案2、ros::param
// ros::param::set("radius_param",0.25);
return 0;
}
4.2 参数服务器获取参数
#include "ros/ros.h"
/*
参数查询
实现:
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、ros::param ----- 与 NodeHandle 类似
*/
int main(int argc, char *argv[])
{
/* code */
setlocale(LC_ALL,"");
ros::init(argc,argv,"get_param");
ros::NodeHandle nh;
//ros::NodeHandle------------------
//1、param(键,默认值)
double radius = nh.param("radius",0.5);
ROS_INFO("1/ radius = %.2f",radius);
//2、getParam(键,存储结果的变量)
//3、getParamCached(键,存储结果的变量)
double radius2;
//bool result = nh.getParam("radius",radius2);
bool result = nh.getParamCached("radius",radius2);
if(result)
{
ROS_INFO("2/3/ radius = %.2f",radius);
}else{
ROS_INFO("查询变量不存在!");
}
//4、getParamNames(std::vector<std::string>)
std::vector<std::string> names;
nh.getParamNames(names);
for(auto &&name : names)
{
ROS_INFO("4/ 遍历到的元素:%s",name.c_str());
}
//5、hasParam(键)
bool flag1 = nh.hasParam("radius");
bool flag2 = nh.hasParam("radiuss");
ROS_INFO("5/ radius 存在吗?%d",flag1);
ROS_INFO("5/ radiuss 存在吗?%d",flag2);
//6、searchParam(参数1,参数2)
std::string key;
nh.searchParam("radius",key);
ROS_INFO("6/ 搜索结果:%s",key.c_str());
return 0;
}
4.3 参数服务器删除参数
#include "ros/ros.h"
/*
参数删除:
1、ros::NodeHandle
delParam()
删除成功true
删除失败false
2、ros::param
del()
*/
int main(int argc, char *argv[])
{
/* code */
setlocale(LC_ALL,"");
ros::init(argc,argv,"del_param");
ros::NodeHandle nh;
//NodeHandle-------------------------
//1、delParam()
bool flag1 = nh.deleteParam("radius");
if(flag1)
{
ROS_INFO("radius删除成功");
}else{
ROS_INFO("radius删除失败");
}
//param
bool flag2 = ros::param::del("radius_param");
if(flag2)
{
ROS_INFO("radius_param删除成功");
}else{
ROS_INFO("radius_param删除失败");
}
return 0;
}