参数服务器在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 参数操作A(C++)
需求:实现参数服务器参数的增删改查操作。
在 C++ 中实现参数服务器数据的增删改查,可以通过两套 API 实现:
-
ros::NodeHandle
-
ros::param
下面为具体操作演示
(1).参数服务器新增(修改)参数
#include "ros/ros.h"
/*
实现参数的新增和修改
需求:设置机器人的共享参数:类型和半径(0.15)
再修改半径(0.2)
实现:
ros::NodeHandle setParam
ros::Param set
*/
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
//初始化ros节点
ros::init(argc,argv,"set_param");
//创建节点句柄
ros::NodeHandle nh;
//参数增---------------------------------
//方式1:nh
nh.setParam("type","小黄车");
nh.setParam("radius",0.15);
//方式2:ros::Param
ros::param::set("type_param","小黑车");
ros::param::set("type_radius",0.15);
//参数改---------------------------------
//方式1:nh
//方式2:ros::Param
return 0;
}
配置文件
测试
roscore
source ./devel/setup.bash
rosrun plumbing_param_server demo01_param_set
rosparam list
修改
保证键是要修改的,值会覆盖
//参数改---------------------------------
//方式1:nh
nh.setParam("radius",0.2);
//方式2:ros::Param
ros::param::set("type_radius",0.25);
(2)参数服务器获取参数
#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 -----------------------------------------------------------
*/
int main(int argc, char *argv[])
{
//设置编码吗
setlocale(LC_ALL,"");
//初始化ros节点
ros::init(argc,argv,"get_param");
//创建节点句柄
ros::NodeHandle nh;
// ros::NodeHandle --------------------------------------------------
//1 param
double radius = nh.param("radius",0.5);
ROS_INFO("radius = %f",radius);
return 0;
}
getParam(键,存储结果的变量)
存在,返回 true,且将值赋值给参数2
若果键不存在,那么返回值为 false,且不为参数2赋值
//2 getParam
double radius2 = 0.0;
bool result = nh.getParam("radius",radius2);
if(result)
{
ROS_INFO("获取的半径是%f",radius2);
}
else
{
ROS_INFO("被查询的变量不存在");
}
getParamCached键,存储结果的变量)--提高变量获取效率
存在,返回 true,且将值赋值给参数2
若果键不存在,那么返回值为 false,且不为参数2赋值
//3 getParamCached
double radius3 = 0.0;
result = nh.getParamCached("radius",radius3);
if(result)
{
ROS_INFO("3获取的半径是%f",radius3);
}
else
{
ROS_INFO("被查询的变量不存在");
}
getParamNames(std::vector<std::string>)
获取所有的键,并存储在参数 vector 中
//4 getParamNames(std::vector<std::string>)
std::vector<std::string> names;
nh.getParamNames(names);
//遍历
for(auto &&name:names)
{
ROS_INFO("遍历到的元素是:%s",name.c_str());
}
hasParam(键)
是否包含某个键,存在返回 true,否则返回 false
//5 hasParam(键)
result = nh.hasParam("radius");
if(result)
{
ROS_INFO("radius存在");
}
else
{
ROS_INFO("radius不存在");
}
searchParam(参数1,参数2)
搜索键,参数1是被搜索的键,参数2存储搜索结果的变量
//6 searchParam(参数1,参数2)
std::string key;
nh.searchParam("radius",key);
ROS_INFO("搜索结果是:%s",key.c_str());
ros::param的函数与ros::NodeHandle相似
(3)参数服务器删除参数
参数服务器操作之删除_C++实现:
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,"param_del");
//创建节点句柄
ros::NodeHandle nh;
//删除,使用NodeHandle----------------------------------------
bool flag1 = nh.deleteParam("radius");
if(flag1)
{
ROS_INFO("删除成功");
}
else
{
ROS_INFO("删除失败");
}
//删除,使用param-------------------------------------------------
bool flag2 = ros::param::del("type_radius");
if(flag2)
{
ROS_INFO("type_radius删除成功");
}
else
{
ROS_INFO("type_radius删除失败");
}
return 0;
}
只能删一次