帮助文档
专业提供香港服务器、香港云服务器、香港高防服务器租用、香港云主机、台湾服务器、美国服务器、美国云服务器vps租用、韩国高防服务器租用、新加坡服务器、日本服务器租用 一站式全球网络解决方案提供商!专业运营维护IDC数据中心,提供高质量的服务器托管,服务器机房租用,服务器机柜租用,IDC机房机柜租用等服务,稳定、安全、高性能的云端计算服务,实时满足您的多样性业务需求。 香港大带宽稳定可靠,高级工程师提供基于服务器硬件、操作系统、网络、应用环境、安全的免费技术支持。
服务器资讯 / 香港服务器租用 / 香港VPS租用 / 香港云服务器 / 美国服务器租用 / 台湾服务器租用 / 日本服务器租用 / 官方公告 / 帮助文档
[ROS 系列学习教程] ROS参数服务器(Param):通信模型、Hello World与拓展
发布时间:2024-02-29 08:37:43   分类:帮助文档
[ROS 系列学习教程] ROS参数服务器(Param):通信模型、Hello World与拓展 ROS 系列学习教程(总目录) 文章目录 一、参数服务器通讯模型二、Param Hello World2.1 创建并初始化功能包2.2 操作参数(C++版)2.3 其他操作参数的函数1.param2.getParamCached()3.getParamNames()4.hasParam()5.searchParam()6.unsubscribeCachedParam() (ros::param特有) 2.4 操作参数(Python版) 参数服务器在ROS中主要用于实现不同节点之间的数据共享。 参数服务器相当于是独立于所有节点的一个公共容器,可以将数据存储在该容器中,被不同的节点调用,当然不同的节点也可以往其中存储数据。 使用场景一般存储一些机器人的固有参数,如产品定义、全局配置等。 主要思想就是一个共享数据域,供不同节点使用。 一、参数服务器通讯模型 参数服务器模型涉及到三个角色: Master (管理者)Setter(设置者)User(使用者) Master 负责管理参数与 Setter/User 的操作,Setter 可以向 Master 设置参数,User 可以从 Master 获取参数。 这里只是方便说明,实际上通讯方操作参数前不会向 ROS Master 注册身份信息,所以对 ROS Master 而言,没有 Setter 与 User 之分,每个访问参数服务器的通讯方都是使用者。 通讯流程: 1)Setter设置参数 ​ Setter 通过 RPC 向参数服务器设置参数(包括参数名与参数值),ROS Master 将参数保存到参数列表中。 2)User获取参数 ​ User 通过 RPC 向参数服务器发送参数查找请求,请求中包含要查找的参数名。 3)ROS Master返回参数信息 ​ ROS Master 根据请求提供的参数名查找参数值,并将查询结果通过 RPC 发送给 User。 参数服务器使用 XMLRPC 数据格式存储参数,支持的数据类型如下: 32-bit integersbooleansstringsdoublesiso8601 dateslistsbase64-encoded binary data Note: 二、Param Hello World 万物始于Hello World,同样,使用Hello World介绍参数服务器的简单使用。 使用参数服务器,通讯方操作参数前没有向 ROS Master 注册身份信息,直接对参数进行操作。 接下来实现一个简单的参数操作,设置不同数据类型的参数,如机器人的名字(name)、长(length)、宽(width)、高(height)等,并对其进行读取删除等操作。 2.1 创建并初始化功能包 (这一步不是必须,这里只是为了方便清晰的说明,也可以使用已有的包,在包里新增节点等方法) 首先创建 param_hello_world 包,命令如下: catkin_creat_pkg param_hello_world roscpp rospy 创建后,文件结构如下: 2.2 操作参数(C++版) ROS 为 C++ 提供了两套 API,如下: 通过 ros::NodeHandle 对象调用通过 ros::param 名空间调用 示例如下: 在创建的 param_hello_world 包路径下有一个 src 目录,在这里存储C++源码,我们创建 param_hello_world_set.cpp 和 param_hello_world_get.cpp ,修改 CMakeLists.txt ,添加如下内容: add_executable(${PROJECT_NAME}_set src/param_hello_world_set.cpp) add_executable(${PROJECT_NAME}_get src/param_hello_world_get.cpp) target_link_libraries(${PROJECT_NAME}_set ${catkin_LIBRARIES} ) target_link_libraries(${PROJECT_NAME}_get ${catkin_LIBRARIES} ) 编辑 param_hello_world_set.cpp 内容如下: #include int main(int argc, char argv) { setlocale(LC_ALL, ""); ros::init(argc, argv, "param_hello_world_set"); ros::NodeHandle nh; std::cout << std::endl << " ros::NodeHandle " << std::endl; { std::string name = "vbot"; std::string geometry = "rectangle"; double wheel_radius = 0.1; int wheel_num = 4; bool vision = true; std::vector base_size = {0.7, 0.6, 0.3}; std::map sensor_id = {{"camera", 0}, {"laser", 2}}; // 设置参数 std::cout << "-- 设置参数 --" << std::endl; nh.setParam("name", "vbot"); // 字符串, char* nh.setParam("geometry", geometry); // 字符串, string nh.setParam("wheel_radius", wheel_radius); // double nh.setParam("wheel_num", wheel_num); // int nh.setParam("vision", vision); // bool nh.setParam("base_size", base_size); // vector nh.setParam("sensor_id", sensor_id); // map // 验证是否设置成功 system("rosparam get name"); system("rosparam get geometry"); system("rosparam get wheel_radius"); system("rosparam get wheel_num"); system("rosparam get vision"); system("rosparam get base_size"); system("rosparam get sensor_id"); } std::cout << std::endl << " ros::param " << std::endl; { std::string name = "vbot"; std::string geometry = "rectangle"; double wheel_radius = 0.1; int wheel_num = 4; bool vision = true; std::vector base_size = {0.7, 0.6, 0.3}; std::map sensor_id = {{"camera", 0}, {"laser", 2}}; // 设置参数 std::cout << "-- 设置参数 --" << std::endl; ros::param::set("name_p", "vbot"); // 字符串, char* ros::param::set("geometry_p", geometry); // 字符串, string ros::param::set("wheel_radius_p", wheel_radius); // double ros::param::set("wheel_num_p", wheel_num); // int ros::param::set("vision_p", vision); // bool ros::param::set("base_size_p", base_size); // vector ros::param::set("sensor_id_p", sensor_id); // map // 验证是否设置成功 system("rosparam get name_p"); system("rosparam get geometry_p"); system("rosparam get wheel_radius_p"); system("rosparam get wheel_num_p"); system("rosparam get vision_p"); system("rosparam get base_size_p"); system("rosparam get sensor_id_p"); } return 0; } 编译运行,结果如下: 编辑 param_hello_world_get.cpp 内容如下: #include int main(int argc, char argv) { setlocale(LC_ALL, ""); ros::init(argc, argv, "param_hello_world_get"); ros::NodeHandle nh; std::cout << std::endl << " ros::NodeHandle " << std::endl; { // 修改参数 std::cout << std::endl << "-- 修改参数 --" << std::endl; nh.setParam("name", "mybot"); // 字符串, char* nh.setParam("geometry", "circular"); // 字符串, char* nh.setParam("wheel_radius", 0.15); // double nh.setParam("wheel_num", 2); // int nh.setParam("vision", false); // bool std::vector base_size = {0.2, 0.04}; nh.setParam("base_size", base_size); // vector std::map sensor_id = {{"camera", 0}, {"laser", 2}}; sensor_id.insert({"ultrasonic", 5}); ros::param::set("sensor_id", sensor_id); // map // 获取参数 std::cout << std::endl << "-- 获取参数 --" << std::endl; std::string name; std::string geometry; double wheel_radius; int wheel_num; bool vision; nh.getParam("name", name); nh.getParam("geometry", geometry); nh.getParam("wheel_radius", wheel_radius); nh.getParam("wheel_num", wheel_num); nh.getParam("vision", vision); nh.getParam("base_size", base_size); nh.getParam("sensor_id", sensor_id); ROS_INFO("ros::NodeHandle getParam, name: %s, geometry: %s, wheel_radius: %lf, wheel: %d, vision: %s, base_size: (%lf, %lf)", name.c_str(), geometry.c_str(), wheel_radius, wheel_num, vision ? "true" : "false", base_size[0], base_size[1]); for (auto sensor : sensor_id) { ROS_INFO("ros::NodeHandle getParam, %s_id: %d", sensor.first.c_str(), sensor.second); } // 删除参数 std::cout << std::endl << "-- 删除参数 --" << std::endl; nh.deleteParam("vision"); system("rosparam get vision"); // 其他操作函数 std::cout << std::endl << "-- 其他操作函数 --" << std::endl; double wheel_radius1; wheel_radius1 = nh.param("wheel_radius", wheel_radius1); ROS_INFO("param, wheel_radius: %lf", wheel_radius1); nh.getParamCached("wheel_radius", wheel_radius1); std::vector keys_v; nh.getParamNames(keys_v); for (auto key : keys_v) { ROS_INFO("getParamNames, key: %s", key.c_str()); } if (nh.hasParam("vision")) { ROS_INFO("hasParam, 存在该参数"); } else { ROS_INFO("hasParam, 不存在该参数"); } std::string result; nh.searchParam("name", result); ROS_INFO("searchParam, result: %s", result.c_str()); } std::cout << std::endl << " ros::param " << std::endl; { // 修改参数 std::cout << std::endl << "-- 修改参数 --" << std::endl; ros::param::set("name_p", "mybot"); // 字符串, char* ros::param::set("geometry_p", "circular"); // 字符串, char* ros::param::set("wheel_radius_p", 0.15); // double ros::param::set("wheel_num_p", 2); // int ros::param::set("vision_p", false); // bool std::vector base_size = {0.2, 0.04}; ros::param::set("base_size_p", base_size); // vector std::map sensor_id = {{"camera", 0}, {"laser", 2}}; sensor_id.insert({"ultrasonic", 5}); ros::param::set("sensor_id_p", sensor_id); // map // 获取参数 std::cout << std::endl << "-- 获取参数 --" << std::endl; std::string name; std::string geometry; double wheel_radius; int wheel_num; bool vision; ros::param::get("name_p", name); ros::param::get("geometry_p", geometry); ros::param::get("wheel_radius_p", wheel_radius); ros::param::get("wheel_num_p", wheel_num); ros::param::get("vision_p", vision); ros::param::get("base_size_p", base_size); ros::param::get("sensor_id_p", sensor_id); ROS_INFO("ros::param get, name: %s, geometry: %s, wheel_radius: %lf, wheel: %d, vision: %s, base_size: (%lf, %lf)", name.c_str(), geometry.c_str(), wheel_radius, wheel_num, vision ? "true" : "false", base_size[0], base_size[1]); for (auto sensor : sensor_id) { ROS_INFO("ros::param getParam, %s_id: %d", sensor.first.c_str(), sensor.second); } // 删除参数 std::cout << std::endl << "-- 删除参数 --" << std::endl; ros::param::del("vision_p"); system("rosparam get vision_p"); // 其他操作函数 std::cout << std::endl << "-- 其他操作函数 --" << std::endl; double wheel_radius1; wheel_radius1 = ros::param::param("wheel_radius", wheel_radius1); ROS_INFO("param, wheel_radius: %lf", wheel_radius1); ros::param::getCached("wheel_radius", wheel_radius1); std::vector keys_v; ros::param::getParamNames(keys_v); for (auto key : keys_v) { ROS_INFO("getParamNames, key: %s", key.c_str()); } if (ros::param::has("vision")) { ROS_INFO("has, 存在该参数"); } else { ROS_INFO("has, 不存在该参数"); } std::string result; ros::param::search("name", result); ROS_INFO("search, result: %s", result.c_str()); } return 0; } 编译运行,结果如下: 2.3 其他操作参数的函数 除了上文提到的setParam()、getParam()、deleteParam() 函数,还有一些其他的参数操作函数,如下: 这里只以通过 ros::NodeHandle 对象调用为例,通过 ros::param 名空间调用类似,只多了一个 unsubscribeCachedParam函数,后面说明 1.param 获取 param_name 的值,如果 param_name 不存在,则返回 default_val 原型: T param(const std::string& param_name, const T& default_val) const double wheel_radius2; wheel_radius2 = nh.param("wheel_radius", wheel_radius2); ROS_INFO("param, wheel_radius: %lf", wheel_radius2); 2.getParamCached() 与getParam()使用方法一样。 首次调用会判断该参数是否获取过,如果获取过则从缓存读取,并向 Master 订阅该参数的变化,不再像getParam()一样通过 RPC 向 Master获取,以提高效率。 示例参考 getParam()。 3.getParamNames() 获取所有设置到 Master 的参数的键,并通过 vector 返回。 原型:bool getParamNames(std::vector& keys) const; std::vector keys_v; nh.getParamNames(keys_v); for (auto key : keys_v) { ROS_INFO("getParamNames, key: %s", key.c_str()); } 4.hasParam() 判断是否存在该参数 原型:bool hasParam(const std::string& key) const; if (nh.hasParam("vision")) { ROS_INFO("存在该参数"); } else { ROS_INFO("不存在该参数"); } 5.searchParam() 搜索给定参数名,如果存在,返回键名,不存在返回空字符串。 原型:bool searchParam(const std::string& key, std::string& result) const; std::string result; nh.searchParam("name", result); ROS_INFO("searchParam, result: %s", result.c_str()); 6.unsubscribeCachedParam() (ros::param特有) 不明白该函数有什么具体作用,如果你知道欢迎交流(留言或加下方微信)。 没有找到官方说明,源码及注释如下: 头文件:param.h 源文件:param.cpp 直译注释为:取消订阅master中的缓存参数 猜测和 getCached() 有关, getCached() 会订阅参数变化,unsubscribeCachedParam则是取消订阅,但验证未生效: // 设置参数 ros::param::set("wheel_radius", 0.15); // 首次调用getCached,这里会订阅"wheel_radius"的变化 double wheel_radius; ros::param::getCached("wheel_radius", wheel_radius); ROS_INFO("before unsubscribeCachedParam, wheel_radius: %lf", wheel_radius); // 调用unsubscribeCachedParam取消订阅 ros::param::unsubscribeCachedParam("wheel_radius"); // 修改master中的"wheel_radius"值 // 由于已取消参数变化的订阅,此次变化不会同步到缓存 // 所以master中的值是0.5,而缓存中的值是0.15 ros::param::set("wheel_radius", 0.5); // 再次调用getCached, // 理论上,再次调用getCached,会从缓存读取,此时缓存中的值是0.15 double wheel_radius1; ros::param::getCached("wheel_radius", wheel_radius1); ROS_INFO("after unsubscribeCachedParam, wheel_radius1: %lf", wheel_radius1); 实际输出为: before unsubscribeCachedParam, wheel_radius: 0.15 after unsubscribeCachedParam, wheel_radius: 0.50 欢迎交流(留言或加下方微信)。 2.4 操作参数(Python版) 与 C++ 不同,ROS 只为 Python 提供了一套操作参数的 API。 在创建的 param_hello_world 包路径下 src 目录的同级,创建一个 scripts 目录,在这里存储脚本(如python脚本),修改 CMakeLists.txt ,添加如下内容: catkin_install_python(PROGRAMS scripts/param_hello_world_set.py scripts/param_hello_world_get.py DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} ) 在 scripts 中创建 param_hello_world_set.py 编辑内容如下: import rospy import os if __name__ == "__main__": rospy.init_node("param_hello_world_set") # 设置参数 rospy.set_param("name", "vbot") # 字符串, string rospy.set_param("geometry", "rectangle") # 字符串, string rospy.set_param("wheel_radius", 0.1) # double rospy.set_param("wheel_num", 4) # int rospy.set_param("vision", True) # bool rospy.set_param("base_size", [0.7, 0.6, 0.3]) # list rospy.set_param("sensor_id", {"camera": 0, "laser": 2}) # dictionary # 验证是否设置成功 os.system("rosparam get name") os.system("rosparam get geometry") os.system("rosparam get wheel_radius") os.system("rosparam get wheel_num") os.system("rosparam get vision") os.system("rosparam get base_size") os.system("rosparam get sensor_id") 在 scripts 中创建 param_hello_world_get.py 编辑内容如下: import rospy if __name__ == "__main__": rospy.init_node("param_hello_world_get") # 修改参数 rospy.set_param("name", "mybot") # 字符串, string rospy.set_param("geometry", "circular") # 字符串, string rospy.set_param("wheel_radius", 0.15) # double rospy.set_param("wheel_num", 2) # int rospy.set_param("vision", False) # bool rospy.set_param("base_size", [0.2, 0.04]) # list rospy.set_param("sensor_id", {"camera": 0, "laser": 2, "ultrasonic": 5}) # dictionary # 获取参数 name = rospy.get_param("name") # 字符串, string geometry = rospy.get_param("geometry") # 字符串, string wheel_radius = rospy.get_param("wheel_radius") # double wheel_num = rospy.get_param("wheel_num") # int vision = rospy.get_param("vision") # bool base_size = rospy.get_param("base_size") # list sensor_id = rospy.get_param("sensor_id") # dictionary rospy.loginfo("get_param, name: {}, geometry: {}, wheel_radius: {}, wheel: {}, vision: {}, base_size: ({}, {})" .format(name, geometry, wheel_radius, wheel_num, vision, base_size[0], base_size[1])) for key, value in sensor_id.items(): rospy.loginfo("get_param, sensor: {}, id: {}".format(key, value)) # 删除参数 rospy.delete_param("vision") # 其他操作 wheel_radius1 = rospy.get_param_cached("wheel_radius") keys = rospy.get_param_names() for key in keys: rospy.loginfo("get_param_names, key: {}".format(key)) if rospy.has_param("vision"): rospy.loginfo("has_param, 存在该参数") else: rospy.loginfo("has_param, 不存在该参数") result = rospy.search_param("name") rospy.loginfo("search_param, result: {}".format(result)) 编译执行结果如下:
香港云服务器租用推荐
服务器租用资讯
·广东云服务有限公司怎么样
·广东云服务器怎么样
·广东锐讯网络有限公司怎么样
·广东佛山的蜗牛怎么那么大
·广东单位电话主机号怎么填写
·管家婆 花生壳怎么用
·官网域名过期要怎么办
·官网邮箱一般怎么命名
·官网网站被篡改怎么办
服务器租用推荐
·美国服务器租用
·台湾服务器租用
·香港云服务器租用
·香港裸金属服务器
·香港高防服务器租用
·香港服务器租用特价