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个节点(以及对应的进程):

  1. /rosout节点,对应的进程是rosout。这个节点是ROS内置的日志记录节点,用于记录ROS系统和用户节点的日志信息。
  2. /master节点,对应的进程是rosmaster。这个节点是ROS的中央管理器,用于协调所有节点的通信。
  3. /parameter_server节点,对应的进程是roscore。这个节点是ROS的全局参数服务器,用于存储和管理全局参数。
  4. /xmlrpc_server节点,对应的进程是roscore。这个节点是ROS的XML-RPC服务器,用于提供ROS节点间的通信服务。
  5. /rosout_agg节点,由rosout进程承担。将多个rosout节点的输出信息聚合到一起,以便于更好地查看和管理ROS系统的日志信息。

四,rosmaster 和 roscore 两个进程功能上有什么区别?

在ROS中,roscorerosmaster实际上是同一个节点,只是在ROS官方文档中,roscore通常指的是包含了rosmaster和其他相关组件的整个ROS系统。

具体来说,roscore是ROS系统的核心,提供了ROS Name Service(命名服务)和ROS Parameter Server(参数服务器)等功能,而rosmasterroscore中的一部分,是负责协调各个ROS节点之间的通信的核心组件,实现了ROS图形结构中节点的发现、注册、名称分配等功能。因此,可以说rosmasterroscore的一个子组件。

总之,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文件加载参数,区别也只是加载的参数命名空间不一样而已。

posted @ 2023-04-14 14:26  透明飞起来了  阅读(1110)  评论(0编辑  收藏  举报