——参数服务器)
ros学习笔记6——参数服务器一、参数服务器理论模型二、参数服务器操作2.1参数服务器新增(修改)参数2.1.1 写cpp文件2.1.2 修改CMake2.1.3 实验效果2.2 参数服务器获取参数2.2.1 写cpp文件2.2.1.1 问题排查2.2.2 修改CMake2.2.3 实验效果2.3 参数服务器删除参数2.3.1 写cpp文件2.3.2 修改CMake2.3.3 实验效果一、参数服务器理论模型参数服务器实现是最为简单的该模型如下图所示,该模型中涉及到三个角色: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 integersbooleansstringsdoublesiso8601 dateslistsbase64-encoded binary data字典注意:参数服务器不是为高性能而设计的因此最好用于存储静态的非二进制的简单数据二、参数服务器操作需求:实现参数服务器参数的增删改查操作。在 C 中实现参数服务器数据的增删改查可以通过两套 API 实现:ros::NodeHandleros::param下面为具体操作演示2.1参数服务器新增(修改)参数2.1.1 写cpp文件在功能包下面的src添加cpp文件#includeros/ros.h/* 需要实现参数的新增和修改 需求首先设置机器人共享参数类型半径(0.15m) 再修改半径(0.2m) 实现 ros::NodeHandle setParam() ros::param set() 修改只需要继续调用函数保证键是已经存在的那么值会覆盖 */intmain(intargc,char*argv[]){//初始化ros节点ros::init(argc,argv,demo01_param_set);//创建ros节点句柄ros::NodeHandle nh;//参数增---------------//方案一nhnh.setParam(car_type,xaiomisu7);nh.setParam(car_radius,0.15);//方案二ros::paramros::param::set(type_param,xiaomisu8);ros::param::set(radius_param,0.15);//参数改---------------//方案一nhnh.setParam(car_radius,0.2);//其实是参数的覆盖//方案二ros::paramros::param::set(car_radius,0.25);return0;}2.1.2 修改CMake添加add_executable和target_link_libraries函数。分别在136行和149-151行add_executable(demo01_param_set src/demo01_param_set.cpp)target_link_libraries(demo01_param_set ${catkin_LIBRARIES} )2.1.3 实验效果编译启动rossource一下然后rosrunsource./devel/setup.bash rosrun plumbing_permit_sever demo01_param_set开一个新终端source一下然后用rosparam list可以列出现在的参数列表rosparam get 参数名可以看到具体参数source./devel/setup.bash rosparam list rosparam get car_radius2.2 参数服务器获取参数2.2.1 写cpp文件在功能包下的src目录下添加cpp文件内容如下#includeros/ros.h/* 演示参数查询 实现 ros::NodeHandle param(键,默认值) 存在返回对应结果否则返回默认值 getParam(键,存储结果的变量) 存在,返回 true,且将值赋值给参数2 若果键不存在那么返回值为 false且不为参数2赋值 getParamCached键,存储结果的变量)--提高变量获取效率 存在,返回 true,且将值赋值给参数2 若果键不存在那么返回值为 false且不为参数2赋值 getParamNames(std::vectorstd::string) 获取所有的键,并存储在参数 vector 中 hasParam(键) 是否包含某个键存在返回 true否则返回 false searchParam(参数1参数2) 搜索键参数1是被搜索的键参数2存储搜索结果的变量 ros::param ----- 与 NodeHandle 类似 */intmain(intargc,char*argv[]){//设置编码setlocale(LC_ALL,);//初始化ros节点ros::init(argc,argv,param_get);//创建节点句柄ros::NodeHandle nh;//ros::NodeHandle------------------------------//1.paramdoubleradiusnh.param(radius,10);ROS_INFO(半径是 %.2f,radius);//2.getParamdoubleradius20.0;boolresultnh.getParam(radius_param,radius2);if(result){ROS_INFO(getParam获取的半径是 %.2f,radius2);}else{ROS_INFO(getParam获取失败);}//3.getParamCached//getParamCached 和 getParam一样只是在性能上有提升一般的测试性能提升肉眼不可见// double radius2 0.0;// bool result nh.getParamCached(radius_param,radius2);if(result){ROS_INFO(getParamCached获取的半径是 %.2f,radius2);}else{ROS_INFO(getParamCached获取失败);}//4.getParamNamesstd::vectorstd::stringnames;nh.getParamNames(names);for(autoname:names){ROS_INFO(遍历的元素%s,name.c_str());}//5.hasParamboolflag1nh.hasParam(radius_param);boolflag2nh.hasParam(radius);ROS_INFO(radius_param是否存在:%d,flag1);ROS_INFO(radius是否存:%d,flag2);//6.searchParamstd::string key1;std::string key2;nh.searchParam(radius_param,key1);nh.searchParam(radius,key2);ROS_INFO(搜索的结果 %s,key1.c_str());ROS_INFO(搜索的结果 %s,key2.c_str());return0;}2.2.1.1 问题排查在看着老师的视频跟练第二个的时候//ros::NodeHandle------------------------------//1.paramdoubleradiusnh.param(radius,10);ROS_INFO(半径是 %.2f,radius);//2.getParamdoubleradius20.0;boolresultnh.getParam(radius,radius2);if(result){ROS_INFO(getParam获取的半径是 %.2f,radius2);}else{ROS_INFO(getParam获取失败);}运行结果是这是因为代码查找的是/radius但参数服务器里实际存在的是/radius_param它们不是同一个参数。看一下参数列表rosparam list参数应该是/radius_param而代码是doubleradius20.0;boolresultnh.getParam(radius,radius2);普通节点句柄ros::NodeHandle nh;会把radius解析成全局参数/radius由于参数服务器没有/radius所以resultfalse于是程序输出获取失败为什么上一行还能显示 10doubleradiusnh.param(radius,10);param()和getParam()的行为不同nh.param(radius,10);意思是尝试获取/radius获取不到就使用默认值10。所以输出10.00并不代表成功读取到了参数而是使用了默认值。而nh.getParam(radius,radius2);没有提供默认值找不到就返回false。2.2.2 修改CMake添加add_executable和target_link_libraries函数。分别在136行和149-151行add_executable(demo01_param_get src/demo01_param_get.cpp)target_link_libraries(demo01_param_get ${catkin_LIBRARIES} )2.2.3 实验效果编译启动rossource一下然后rosrunsource./devel/setup.bash rosrun plumbing_permit_sever demo01_param_get2.3 参数服务器删除参数2.3.1 写cpp文件在功能包下的src目录下添加cpp文件内容如下#includeros/ros.h/* 演示参数的删除 实现 ros::NodeHandle deleteParam() ros::param del() */intmain(intargc,char*argv[]){setlocale(LC_ALL,);ros::init(argc,argv,param_del);ros::NodeHandle nh;//删除ros::NodeHandle-----------------boolflag1nh.deleteParam(radius_param);if(flag1){ROS_INFO(deleteParam删除radius_param成功);}else{ROS_INFO(deleteParam删除radius_param失败);}boolflag2nh.deleteParam(radius);if(flag2){ROS_INFO(deleteParam删除radius成功);}else{ROS_INFO(deleteParam删除radius失败);}//删除ros::param----------------------boolflag3ros::param::del(car_type);if(flag3){ROS_INFO(ros::param::del删除car_type成功);}else{ROS_INFO(ros::param::del删除car_type失败);}boolflag4ros::param::del(type);if(flag4){ROS_INFO(ros::param::del删除type成功);}else{ROS_INFO(ros::param::del删除type失败);}return0;}2.3.2 修改CMake添加add_executable和target_link_libraries函数。分别在136行和149-151行add_executable(demo01_param_del src/demo01_param_del.cpp)target_link_libraries(demo01_param_del ${catkin_LIBRARIES} )2.3.3 实验效果编译启动rossource一下然后rosrunsource./devel/setup.bash rosrun plumbing_permit_sever demo01_param_del开一个新终端source一下再rosparam list一下看到去试试被删除了学习的为赵虚左老师的教程 1.老师的文档 2.老师的视频在笔记上理论部分大量参考了老师的文档