> For the complete documentation index, see [llms.txt](https://m1801899.gitbook.io/translate-book/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://m1801899.gitbook.io/translate-book/7.3-dobavlenie-podderzhki-klienta-dinamicheskoi-rekonfiguracii-k-uzlu-ros.md).

# 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**.<br>
