参数服务器
理论模型
参数服务器实现是最为简单的,该模型如下图所示,该模型中涉及到三个角色:
- 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
- 字典
实现
实现参数服务器参数的增删改查操作。
c++ 实现
在 C++ 中实现参数服务器数据的增删改查,可以通过两套 API 实现:
- ros::NodeHandle
- ros::param
下面为具体操作演示
1.参数服务器新增(修改)参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
#include "ros/ros.h"
int main(int argc, char *argv[]) { ros::init(argc,argv,"set_update_param");
std::vector<std::string> stus; stus.push_back("zhangsan"); stus.push_back("李四"); stus.push_back("王五"); stus.push_back("孙大脑袋");
std::map<std::string,std::string> friends; friends["guo"] = "huang"; friends["yuang"] = "xiao";
ros::NodeHandle nh; nh.setParam("nh_int",10); nh.setParam("nh_double",3.14); nh.setParam("nh_bool",true); nh.setParam("nh_string","hello NodeHandle"); nh.setParam("nh_vector",stus); nh.setParam("nh_map",friends);
nh.setParam("nh_int",10000);
ros::param::set("param_int",20); ros::param::set("param_double",3.14); ros::param::set("param_string","Hello Param"); ros::param::set("param_bool",false); ros::param::set("param_vector",stus); ros::param::set("param_map",friends);
ros::param::set("param_int",20000);
return 0; } Copy
|
2.参数服务器获取参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
#include "ros/ros.h"
int main(int argc, char *argv[]) { setlocale(LC_ALL,""); ros::init(argc,argv,"get_param");
ROS_INFO("++++++++++++++++++++++++++++++++++++++++"); int res3 = ros::param::param("param_int",20); int res4 = ros::param::param("param_int2",20); ROS_INFO("param获取结果:%d,%d",res3,res4);
int param_int_value; double param_double_value; bool param_bool_value; std::string param_string_value; std::vector<std::string> param_stus; std::map<std::string, std::string> param_friends;
ros::param::get("param_int",param_int_value); ros::param::get("param_double",param_double_value); ros::param::get("param_bool",param_bool_value); ros::param::get("param_string",param_string_value); ros::param::get("param_vector",param_stus); ros::param::get("param_map",param_friends);
ROS_INFO("getParam获取的结果:%d,%.2f,%s,%d", param_int_value, param_double_value, param_string_value.c_str(), param_bool_value ); for (auto &&stu : param_stus) { ROS_INFO("stus 元素:%s",stu.c_str()); }
for (auto &&f : param_friends) { ROS_INFO("map 元素:%s = %s",f.first.c_str(), f.second.c_str()); }
ros::param::getCached("param_int",param_int_value); ROS_INFO("通过缓存获取数据:%d",param_int_value);
std::vector<std::string> param_names2; ros::param::getParamNames(param_names2); for (auto &&name : param_names2) { ROS_INFO("名称解析name = %s",name.c_str()); } ROS_INFO("----------------------------");
ROS_INFO("存在 param_int 吗? %d",ros::param::has("param_int")); ROS_INFO("存在 param_intttt 吗? %d",ros::param::has("param_intttt"));
std::string key; ros::param::search("param_int",key); ROS_INFO("搜索键:%s",key.c_str());
return 0; } Copy
|
3.参数服务器删除参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
#include "ros/ros.h"
int main(int argc, char *argv[]) { setlocale(LC_ALL,""); ros::init(argc,argv,"delete_param");
ros::NodeHandle nh; bool r1 = nh.deleteParam("nh_int"); ROS_INFO("nh 删除结果:%d",r1);
bool r2 = ros::param::del("param_int"); ROS_INFO("param 删除结果:%d",r2);
return 0; }
|
Python实现
1.参数服务器新增(修改)参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| """ 参数服务器操作之新增与修改(二者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) Copy
|
2.参数服务器获取参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
""" 参数服务器操作之查询_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"])
int_cached = rospy.get_param_cached("p_int") rospy.loginfo("缓存数据:%d",int_cached)
names = rospy.get_param_names() for name in names: rospy.loginfo("name = %s",name)
rospy.loginfo("-"*80)
flag = rospy.has_param("p_int") rospy.loginfo("包含p_int吗?%d",flag)
key = rospy.search_param("p_int") rospy.loginfo("搜索的键 = %s",key) Copy
|
3.参数服务器删除参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| """ 参数服务器操作之删除_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("删除失败")
|