2 ROS1通讯编程基础
- 其他ROS1学习笔记: ROS1学习笔记
- 代码仓库:Github连接地址
- 欢迎各位互相学习交流
2.5 参数服务器编程
2.5.1 参数服务器理论模型
参数服务器的理论模型如图所示:ROS Master 作为一个公共容器保存参数,Setter可以向容器中设置参数,Getter可以获取参数,即通过Setter和Getter实现对参数服务器的增删改查操作。注意:参数服务器不是为高性能而设计的,因此最好用于存储静态的非二进制的简单数据,如int、bool、string、doubles、iso8601 dates(时间数据)、lists和字典等。
整个流程由以下步骤实现:
- ①Setter设置参数:Setter通过 RPC 向参数服务器发送参数(包括参数名与参数值),ROS Master 将参数保存到参数列表中。
- ②Getter获取参数:Getter通过 RPC 向参数服务器发送参数查找请求,请求中包含要查找的参数名。
- ③ROS Master向Getter发送参数值:ROS Master 根据步骤2请求提供的参数名查找参数值,并将查询结果通过 RPC 发送给 Getter。
2.5.2参数服务器增删改查编程
参数服务器类型主要为:(key,value)
类型,因此在编程上C++或者是Python可以采用map函数或者字典的用法去简化编程。
此外C++在参数服务器的API中提供了两套方法进行参数的操作,即ros::NodeHandle
或ros::param
,下面编程中依次对其进行使用。
2.5.2.1 新建功能包
- 新建功能包,在工作空间下新建功能包
param_server
并预设依赖项rospy roscpp std_msgs
,并在功能包param_server
下创建scripts文件夹用于存放Python文件,如图所示:
2.5.2.2 C++代码实现参数服务器增加操作
- 采用C++编写代码,两种API的具体操作见注释
-
- 编写代码
catkin_ws/src/param_server/src/add_modparam_cpp.cpp
#include "ros/ros.h"
using namespace std;
/*
两套API对参数的增加或者修改的操作是类似的,主要采用set函数进行
ros::NodeHandle
setParam("键",值)
ros::param
set("键","值")
*/
int main(int argc, char *argv[])
{
ros::init(argc,argv,"add_modparam_cpp");
// API1---使用NodeHandle-------------------------------------------------
ros::NodeHandle nh;
nh.setParam("nh_int",10); //整型
nh.setParam("nh_double",3.14); //浮点型
//修改演示替换掉键的值
nh.setParam("nh_int",10000);
//API2---使用param--------------------------------------------------------
ros::param::set("param_int",20);
ros::param::set("param_double",3.14);
//修改演示替换掉键的值
ros::param::set("param_int",20000);
return 0;
}
-
- 对CMakeList.txt进行设置,因为没有调用自定义文件,因此只需要设置
add_executable
和target_link_libraries
两项:
- 对CMakeList.txt进行设置,因为没有调用自定义文件,因此只需要设置
catkin_ws/src/param_server/CMakeList.txt
add_executable(add_modparam_cpp_node src/add_modparam_cpp.cpp)
target_link_libraries(add_modparam_cpp_node ${catkin_LIBRARIES})
-
- 编译运行查看参数。
2.5.2.3 Python代码实现参数服务器增加操作
- 编写Python代码,API只有一种,编写完赋予可执行权限。
-
- 编写代码
add_modparam_py.py
- 编写代码
catkin_ws/src/param_server/scripts/add_modparam_py.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
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_int",100)
rospy.loginfo("参数设置成功,采用命令rosparam list 查看param 列表")
rospy.loginfo("自定义参数只有:p_int,p_double")
rospy.loginfo("查看参数值采用rosparam get 参数名,如rosparam get /p_int")
-
- 在scripts文件夹输入
sudo chmod +x *.py
赋予可执行权限
- 在scripts文件夹输入
-
- 编译执行,查看输出结果
2.5.2.4 C++代码删除参数操作
- 采用C++编写代码,代码见注释
-
- 编写删除参数操作,
delparam_cpp.cpp
代码
- 编写删除参数操作,
catkin_ws/src/param_server/src/delparam_cpp.cpp
#include "ros/ros.h"
/*
ros::NodeHandle
deleteParam("键")
根据键删除参数,删除成功,返回 true,否则(参数不存在),返回 false
ros::param
del("键")
根据键删除参数,删除成功,返回 true,否则(参数不存在),返回 false
*/
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
ros::init(argc,argv,"delete_param_cpp");
ROS_INFO("希望删除nh_int和param_int两个参数");
ROS_INFO("删除成功,返回 true,否则(参数不存在),返回 false");
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;
}
-
- 对CMakeList.txt进行设置,同理只需要设置
add_executable
和target_link_libraries
两项:
- 对CMakeList.txt进行设置,同理只需要设置
catkin_ws/src/param_server/CMakeList.txt
add_executable(delparam_cpp_node src/delparam_cpp.cpp)
target_link_libraries(delparam_cpp_node ${catkin_LIBRARIES})
-
- 编译运行查看结果。
2.5.2.5 Python代码删除参数操作
- 编写Python代码,编写完赋予可执行权限。
-
- 编写代
delparams_py.py
- 编写代
catkin_ws/src/param_server/scripts/delparams_py.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
"""
rospy.delete_param("键")
键存在时,可以删除成功,键不存在时,会抛出异常
"""
import rospy
if __name__ == "__main__":
rospy.init_node("delete_param_py")
rospy.loginfo("尝试删除p_int,删除成功返回数值,删除失败提示输出")
try:
rospy.delete_param("p_int")
except Exception as e:
rospy.loginfo("删除失败")
-
- 在scripts文件夹输入
sudo chmod +x *.py
赋予可执行权限
- 在scripts文件夹输入
-
- 编译执行,查看输出结果
2.5.2.6 修改参数操作
修改参数操作和增加参数操作一致,只需要覆盖掉同key的value即可。
2.5.2.7 C++代码查询参数操作
- 采用C++编写代码,具体操作见注释
-
- 编写查询参数操作,
getparam_cpp.cpp
代码
- 编写查询参数操作,
catkin_ws/src/param_server/src/getparam_cpp.cpp
#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存储搜索结果的变量
*/
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
ros::init(argc,argv,"get_param_cpp");
// ros::NodeHandle--------------------------------------------------------
ros::NodeHandle nh;
// param 函数,其余函数操作查看API
int get1 = nh.param("nh_int",100); // 键存在
ROS_INFO("获取param参数nh_int的值:%d",get1);
// ros::param--------------------------------------------------------
int get2 = ros::param::param("param_int",20); //存在
ROS_INFO("获取param参数param_int的值:%d",get2);
return 0;
}
-
- 对CMakeList.txt进行设置,同理只需要设置
add_executable
和target_link_libraries
两项:
- 对CMakeList.txt进行设置,同理只需要设置
catkin_ws/src/param_server/CMakeList.txt
add_executable(getparam_cpp_node src/getparam_cpp.cpp)
target_link_libraries(getparam_cpp_node ${catkin_LIBRARIES})
-
- 编译运行查看结果。
2.5.2.8 Python代码查询参数操作
- 编写Python代码,编写完赋予可执行权限。
-
- 编写代getparam_py.py
catkin_ws/src/param_server/scripts/getparam_py.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
"""
get_param
get_param_cached
get_param_names
has_param
search_param
"""
import rospy
if __name__ == "__main__":
rospy.init_node("getparam_py")
#获取参数
int_value = rospy.get_param("p_int",10000)
rospy.loginfo("获取的数据:%d",int_value)
-
- 在scripts文件夹输入
sudo chmod +x *.py
赋予可执行权限
- 在scripts文件夹输入
-
- 编译执行,查看输出结果
2.5.3 参数服务器编程总结
参数服务器使用多用于数据的共享,其编程逻辑主要在于创建句柄,然后通过内置的API函数进行参数增删改查,其中增加参数的操作和修改参数的操作方法是一样的,难点在于对参数的查询,函数太多,可以根据实际情况查阅API进行编程。
参考文献:B站视频:【奥特学园】ROS机器人入门课程《ROS理论与实践》零基础教程
ROS-WIKI:Parameter Server
ROS-WIKI:C++的API
ROS-WIKI:Python的API