7.3 Добавление поддержки клиента динамической реконфигурации к узлу ROS

В предыдущем разделе мы показали, как добавить динамически настраиваемые параметры в узел симулятора батареи. Для этого мы использовали библиотеку сервера динамической реконфигурации. Запуск узла в качестве сервера динамической реконфигурации позволяет ему принимать запросы на изменение параметров от клиентских узлов, таких как rqt_reconfigure. Однако иногда вы можете захотеть, чтобы один из ваших собственных узлов действовал как клиент и запрашивал изменения параметров в других узлах, или же вы можете захотеть, чтобы узел просто знал, когда параметры другого узла были изменены, и действовал соответственно. Хотя это не так часто, как настройка узла в качестве сервера динамической настройки, давайте быстро рассмотрим, как это можно сделать.

Наш демо-скрипт называется dyna_client.py и может быть найден в каталоге rbx2_utils/nodes. Этот узел подключается к имитатору батареи и устанавливает уровень заряда батареи попеременно между 100 и 0 каждые 10 секунд. Хотя это и не самый полезный пример, он, по крайней мере, иллюстрирует этот процесс. Вот полный сценарий.

1 #!/usr/bin/env python
2
3 import rospy
4 import dynamic_reconfigure.client
5
6 class DynaClient():
7 def __init__(self):
8 rospy.init_node("dynamic_client")
9
10 rospy.loginfo("Connecting to battery simulator node...")
11
12 client = dynamic_reconfigure.client.Client("battery_simulator",
timeout=30, config_callback=self.callback)
13
14 r = rospy.Rate(0.1)
15
16 charge = True
17
18 while not
rospy.is_shutdown():
19 if charge: 20
level = 100 21
else:
22 level = 0
23
24 charge = not charge
25
26 client.update_configuration({"new_battery_level": level})
27
28 r.sleep()
29
30 def callback(self, config):
31 rospy.loginfo("Battery Simulator config set to: " +
str(config['new_battery_level']))
32
33
34 if __name__ == "__main__":
35 DynaClient()

Давайте теперь посмотрим на ключевые строки:

4 import dynamic_reconfigure.client

Сначала мы импортируем клиентскую библиотеку dynamic configure, а не серверную библиотеку.

12 client = dynamic_reconfigure.client.Client("battery_simulator", timeout=30, config_callback=self.callback)

Здесь мы создаем клиентское соединение с узлом Battery simulator, устанавливаем тайм-аут на 30 секунд и назначаем функцию обратного вызова, определенную ниже. Обратите внимание, что функция обратного вызова будет вызываться всякий раз, когда параметры узла Battery simulator изменяются, даже другим узлом, таким как rqt_reconfigure. Это позволяет узлу dyna_client отслеживать изменения параметров в узле Battery simulator и при необходимости корректировать свое собственное поведение.

13 r = rospy.Rate(0.1)

Эта линия устанавливает скорость для нашего основного контура 0,1 Гц или один цикл в 10 секунд

16 charge = True
17
18 while not
rospy.is_shutdown():
19 if charge: 20
level = 100 21
else:
22 level = 0
23
24 charge = not charge
25
26 client.update_configuration({"new_battery_level": level})
27
28 r.sleep()

Мы используем переменную заряда, чтобы чередовать уровень заряда батареи от 100 до 0. Затем мы входим в основной цикл и запускаем клиент.функция update_configuration() позволяет установить параметр new_battery_level имитатора батареи равным 100 или 0 в зависимости от значения заряда. Обратите внимание, как имя и значение параметра задаются в виде словаря Python. Если бы мы хотели изменить оба параметра new_battery_level и battery_runtime одновременно, строка обновления выглядела бы так:

client.update_configuration({"new_battery_level": level, "battery_runtime":runtime})

Где runtime приобретёт новое значение во время выполнения.

Наконец, давайте рассмотрим функцию обратного вызова клиента:

30 def callback(self, config): 
30 rospy.loginfo("Battery Simulator config set to: " + str(config['new_battery_level']))

Функция динамического обратного вызова клиента конфигурирования автоматически получает текущую конфигурацию параметров в качестве аргумента, который мы назвали config выше. Этот аргумент является словарем значений, и мы можем вытащить текущее значение любого параметра по имени. В строке 30 выше мы просто показываем значение параметра new_battery_level в окне терминала.

Чтобы увидеть сценарий в действии, сначала запустите узел имитатора батареи:

$ roslaunch rbx2_utils battery_simulator.launch

Далее запустите узел dyna_client.py:

$ rosrun rbx2_utils dyna_client.py

Если вы контролируете dyna_client.py в окне терминала вы увидите вывод с командой rospy.loginfo() выше каждые 10 секунд, и значение параметра new_battery_level будет чередоваться между 100 и 0. Чтобы убедиться, что имитатор батареи действительно реагирует на новый уровень заряда батареи, откройте другой терминал и проверьте сам уровень заряда батареи, опубликованный в разделе /battery_level:

$ rostopic echo /battery_level

Здесь вы должны увидеть обратный отсчет уровня заряда батареи, как обычно, начиная с 100, но каждые 10 секунд он будет прыгать либо до 0, либо обратно до 100.

Наконец, вызовите rqt_reconfigure и измените параметр new_battery_level с помощью графического интерфейса. В окне dyna_client.py вы должны видеть выходные данные функции обратного вызова как каждые 10 секунд от ее собственного действия, так и каждый раз, когда вы изменяете значение с помощью rqt_reconfigure.

Last updated