ROS学习笔记(三)- 参数服务器
样例代码在最后面,供参考。
一,简单介绍ROS的参数服务器:
ROS的参数服务器是一种全局的、名称空间分层的键值存储系统,用于在ROS系统中存储和共享参数数据。它允许ROS节点在运行时获取和设置参数,而不需要在代码中硬编码参数。
参数服务器提供了许多优点,例如:
- 可以在ROS系统中共享参数数据,使得多个节点可以访问同一组参数,避免了代码中硬编码的重复
- 可以在运行时更新参数数据,而无需停止或重新启动ROS节点或ROS系统
- 可以使用命令行工具或GUI工具轻松地获取和设置参数,无需编写代码
- 可以使用参数服务器中的参数作为ROS Launch文件的参数
在ROS系统中,参数服务器是一种全局的、分布式的、层次结构的存储系统。它提供了一个由命名空间组成的层次结构,可以使用ROS命名约定来管理节点、话题、服务、参数等。
可以使用ROS中的roscpp、rospy、roslisp等库来与参数服务器进行交互。以下是一些常见的操作:
- 获取参数:可以使用getParam方法从参数服务器中获取参数的值,会先从本地参数服务器中查找指定的参数,如果本地参数服务器中没有该参数,则会从全局参数服务器中查找。如果在两者中都找不到,则会抛出rospy.ROSException异常。
- 设置参数:可以使用setParam方法向参数服务器中设置参数的值,设置的参数默认是在全局参数服务器中,除非在调用时使用
local
参数将其设置为在本地参数服务器中。rospy.set_param('my_param', 'my_value', local=True)
- 删除参数:可以使用deleteParam方法从参数服务器中删除参数。
- 搜索参数:可以使用searchParam方法搜索参数服务器中与指定名称匹配的参数。
在ROS系统中,有两个常用的参数服务器:全局参数服务器和本地参数服务器。全局参数服务器存储在ROS网络中,所有连接到该网络的节点都可以访问它。本地参数服务器只在当前节点中可用,并不会共享给其他节点。节点可以通过ROS参数服务器中的特殊参数~parameter_name来设置它们的本地参数服务器。
总之,ROS的参数服务器是一种非常有用的工具,可以使ROS节点的参数更加灵活和可配置,可以避免硬编码和重复,提高了ROS系统的可维护性和可扩展性。
二,全局参数服务器是运行在roscore启动的master进程里吗?
是的,全局参数服务器是运行在roscore启动的master进程里的一个节点,它是ROS参数服务器的一个实例,用于存储和共享ROS系统中的全局参数。在ROS系统中,参数服务器可以通过命令行工具或编程接口进行读写,允许节点之间共享参数并支持动态重新配置节点的参数。
三,roscore命令启动了哪些节点,分别由哪些进程承担的?(这个回答似乎是不太准确,因为gpt自己都前言不搭后语,一会这么说一会那么说,所以仅供参考)
运行roscore命令会启动以下5个节点(以及对应的进程):
- /rosout节点,对应的进程是rosout。这个节点是ROS内置的日志记录节点,用于记录ROS系统和用户节点的日志信息。
- /master节点,对应的进程是rosmaster。这个节点是ROS的中央管理器,用于协调所有节点的通信。
- /parameter_server节点,对应的进程是roscore。这个节点是ROS的全局参数服务器,用于存储和管理全局参数。
- /xmlrpc_server节点,对应的进程是roscore。这个节点是ROS的XML-RPC服务器,用于提供ROS节点间的通信服务。
- /rosout_agg节点,由rosout进程承担。将多个rosout节点的输出信息聚合到一起,以便于更好地查看和管理ROS系统的日志信息。
四,rosmaster 和 roscore 两个进程功能上有什么区别?
在ROS中,roscore
和rosmaster
实际上是同一个节点,只是在ROS官方文档中,roscore
通常指的是包含了rosmaster
和其他相关组件的整个ROS系统。
具体来说,roscore
是ROS系统的核心,提供了ROS Name Service(命名服务)和ROS Parameter Server(参数服务器)等功能,而rosmaster
是roscore
中的一部分,是负责协调各个ROS节点之间的通信的核心组件,实现了ROS图形结构中节点的发现、注册、名称分配等功能。因此,可以说rosmaster
是roscore
的一个子组件。
总之,roscore
包含了整个ROS系统的核心组件,而rosmaster
是其中一个核心组件,负责实现ROS节点之间的协调和通信。
五,一个ROS节点一定是一个进程吗?
一个ROS节点不一定是一个单独的进程,它可能由多个进程组成。例如,ROS Master节点是由一个单独的进程和多个后台进程组成的。另外,一个ROS节点也可以由多个线程组成,这些线程可以同时运行并执行不同的任务。另外,普通的ROS节点一般都是单个进程,但也可以将一个ROS节点拆分成多个进程,进行分布式处理。在这种情况下,可以使用ROS提供的一些工具来协调多个进程之间的通信和同步,例如roslaunch和rospy等。同时,ROS也提供了一些库,如rospy和roscpp,用于在进程之间进行通信和交换数据。
六,背景介绍的挺多了,现在实践一下。
将前面两篇博客提到的talker.py和listener.py略作修改,加上存取参数的代码(初始化项目的步骤这里就不赘述,参考前面的博客):
talker.py(请注意参数键值是launch文件里的节点name+参数name,并且用/分割了):
#!/usr/bin/env python import rospy from std_msgs.msg import String def talker(): i=0 pub = rospy.Publisher('chatter', String, queue_size=10) rospy.init_node('talker', anonymous=True) rate = rospy.Rate(1) # 1hz while not rospy.is_shutdown(): hello_str = " hello world %s" % rospy.get_time() d = str(i) + hello_str uname = rospy.get_param("/T007/username") uage = rospy.get_param("/T007/age") oldsquareage = rospy.get_param("/T007/squareage") iuage = int(uage) squareage = iuage * iuage rospy.loginfo("d: %s, username: %s, age: %s, squareage: %s", d, uname, uage, squareage) rospy.set_param("/T007/age", iuage + 1) rospy.set_param("/T007/squareage", squareage) pub.publish(d) rate.sleep() i = i + 1 if __name__ == '__main__': try: talker() except rospy.ROSInterruptException: pass
listener.py:
#!/usr/bin/env python import rospy from std_msgs.msg import String def callback(data): oldsquareage = rospy.get_param("/T007/squareage") rospy.loginfo(rospy.get_caller_id() + " I heard %s, oldsquareage:%s ", data.data, oldsquareage) def listener(): rospy.init_node('listener', anonymous=True) rospy.Subscriber('chatter', String, callback) rospy.spin() if __name__ == '__main__': listener()
接下来是launch文件内容:
<launch> <!-- <node pkg="roscore" type="roscore" name="master" output="screen" 不需要手动指定因为roslaunch命令会自动启动roscore节点/> --> <node pkg="lesson001" type="talker.py" name="T007" output="screen"> <param name="username" value="Eric" /> <param name="age" value="18" /> <param name="squareage" value="-1" /> </node> <node pkg="lesson001" type="listener.py" name="L009" output="screen" /> </launch>
注意在launch文件里写了param其实就定义了这个参数的键和初始值了。
然后到项目根目录也就是`~/ros-learning/`目录,执行下面的命令:
catkin_make source devel/setup.bash roslaunch lesson001 001launch.launch
输出如下:
七,<rosparam />标签和<param />标签的区别
<rosparam />
标签和<param />
标签都可以用于在launch文件中设置ROS参数,它们的区别在于参数的命名空间不同。
<rosparam />
标签的参数会被设置到全局的参数服务器中,命名空间为/
。<param />
标签的参数则被设置到当前节点的私有命名空间中,命名空间为/节点名称/
。
例如,假设我们有一个名为my_node
的ROS节点,使用<rosparam />
标签设置参数my_param
的值为123
,则在全局的参数服务器中会创建一个名为/my_param
的参数。如果使用<param />
标签设置同样的参数,那么在my_node
节点的私有命名空间中会创建一个名为/my_node/my_param
的参数。
在使用这些参数时,我们需要根据它们的命名空间来引用它们。使用<rosparam />
设置的参数可以被整个ROS系统的节点共享,因此在任何节点中都可以通过ros::param::get()
等API来读取它们的值。而使用<param />
设置的参数则只能被当前节点访问,可以通过ros::NodeHandle::getParam()
等API来读取。
另外,这两个标签都可以通过指定file路径而从yaml文件加载参数,区别也只是加载的参数命名空间不一样而已。