# Типы нод

Конечно! Давайте подробно разберем каждый тип нод в ROS2 launch системе.

### 1. Обычные ноды (Node)

#### Основное понятие

Обычные ноды - это стандартные ROS2 ноды, которые запускаются и работают до завершения.

#### Пример использования

```python
from launch_ros.actions import Node

basic_node = Node(
    package='my_package',
    executable='my_node',
    name='basic_node',
    namespace='sensors',
    parameters=[
        {'param1': 10},
        {'param2': 'value'},
        # или из файла
        LaunchConfiguration('config_file')
    ],
    arguments=['--custom-arg', 'value'],
    remappings=[
        ('input_topic', 'remapped_input'),
        ('output_topic', 'remapped_output')
    ],
    output='screen',  # или 'log', 'both'
    emulate_tty=True,
    respawn=True,
    respawn_delay=3.0,
    shell=True,
)
```

#### Ключевые параметры:

* **package** - имя пакета
* **executable** - имя исполняемого файла
* **name** - уникальное имя ноды в графе
* **namespace** - пространство имен для топиков и сервисов
* **parameters** - список параметров (dict или файлы)
* **remappings** - переназначение имен топиков/сервисов
* **output** - куда направлять вывод (`screen`, `log`, `both`)
* **emulate\_tty** - эмулировать терминал для цветного вывода
* **respawn** - перезапускать при падении
* **respawn\_delay** - задержка перед перезапуском

### 2. Lifecycle ноды (LifecycleNode)

#### Основное понятие

Ноды с управляемым жизненным циклом, которые могут менять состояния (unconfigured, inactive, active, etc.).

#### Состояния жизненного цикла:

1. **Unconfigured** - не сконфигурирована
2. **Inactive** - сконфигурирована, но не активна
3. **Active** - активна и работает
4. **Finalized** - завершена

#### Пример использования

```python
from launch_ros.actions import LifecycleNode
from launch.actions import ExecuteProcess, TimerAction
from launch.conditions import IfCondition

lifecycle_node = LifecycleNode(
    package='lifecycle_package',
    executable='camera_node',
    name='camera_driver',
    namespace='hardware',
    parameters=[{'camera_id': 0, 'frame_rate': 30}],
    output='screen',
)

# Автоматическая активация после запуска
activate_camera = TimerAction(
    period=2.0,
    actions=[
        ExecuteProcess(
            cmd=['ros2', 'lifecycle', 'set', '/camera_driver', 'configure'],
            output='screen'
        ),
        ExecuteProcess(
            cmd=['ros2', 'lifecycle', 'set', '/camera_driver', 'activate'],
            output='screen'
        )
    ]
)
```

#### Полный пример с управлением состоянием:

```python
from launch import LaunchDescription
from launch.actions import (
    ExecuteProcess,
    TimerAction,
    RegisterEventHandler,
)
from launch_ros.actions import LifecycleNode
from launch.event_handlers import OnProcessStart

def generate_launch_description():
    lifecycle_node = LifecycleNode(
        package='camera_package',
        executable='camera_lifecycle_node',
        name='camera',
        namespace='sensors',
        parameters=[{'device_id': '/dev/video0'}],
    )
    
    # Автоматическая конфигурация после старта
    configure_camera = RegisterEventHandler(
        OnProcessStart(
            target_action=lifecycle_node,
            on_start=[
                ExecuteProcess(
                    cmd=['ros2', 'lifecycle', 'set', '/camera', 'configure'],
                    output='screen'
                )
            ]
        )
    )
    
    # Активация после конфигурации
    activate_camera = TimerAction(
        period=3.0,
        actions=[
            ExecuteProcess(
                cmd=['ros2', 'lifecycle', 'set', '/camera', 'activate'],
                output='screen'
            )
        ]
    )
    
    return LaunchDescription([
        lifecycle_node,
        configure_camera,
        activate_camera,
    ])
```

### 3. Группы нод (GroupAction с PushRosNamespace)

#### Основное понятие

Группировка нод с общими настройками (namespace, параметры, условия).

#### Пример использования

```python
from launch_ros.actions import Node, PushRosNamespace
from launch.actions import GroupAction

sensor_group = GroupAction(
    actions=[
        # Применяем namespace ко всем нодам в группе
        PushRosNamespace('sensor_system'),
        
        # Нода 1 - драйвер камеры
        Node(
            package='camera_package',
            executable='camera_driver',
            name='front_camera',
            parameters=[{'resolution': '1920x1080'}],
        ),
        
        # Нода 2 - обработчик изображений
        Node(
            package='image_processing',
            executable='image_processor',
            name='vision_processor',
            parameters=[{'processing_rate': 30.0}],
        ),
        
        # Нода 3 - публикатор результатов
        Node(
            package='sensor_fusion',
            executable='results_publisher',
            name='results_node',
        ),
    ]
)
```

#### Группы с условиями:

```python
from launch.conditions import IfCondition

debug_group = GroupAction(
    condition=IfCondition(LaunchConfiguration('enable_debug')),
    actions=[
        PushRosNamespace('debug'),
        Node(
            package='debug_tools',
            executable='debug_node',
            name='system_monitor',
        ),
        Node(
            package='rqt',
            executable='rqt_gui',
            name='rqt_dashboard',
        ),
    ]
)
```

#### Группы с общими параметрами:

```python
sensor_network = GroupAction(
    actions=[
        PushRosNamespace('sensor_network'),
        
        # Общие параметры для всех нод группы
        Node(
            package='sensor_package',
            executable='temperature_sensor',
            name='temp_sensor1',
            parameters=[{'sensor_id': 1, 'network_id': 100}],
        ),
        Node(
            package='sensor_package',
            executable='humidity_sensor',
            name='humidity_sensor1',
            parameters=[{'sensor_id': 2, 'network_id': 100}],
        ),
        Node(
            package='sensor_package',
            executable='pressure_sensor',
            name='pressure_sensor1',
            parameters=[{'sensor_id': 3, 'network_id': 100}],
        ),
    ]
)
```

### Комбинированный пример всех типов

```python
from launch import LaunchDescription
from launch.actions import (
    DeclareLaunchArgument,
    GroupAction,
    RegisterEventHandler,
    TimerAction,
    ExecuteProcess,
)
from launch_ros.actions import Node, LifecycleNode, PushRosNamespace
from launch.substitutions import LaunchConfiguration
from launch.conditions import IfCondition
from launch.event_handlers import OnProcessStart

def generate_launch_description():
    return LaunchDescription([
        DeclareLaunchArgument(
            'use_lifecycle',
            default_value='true',
            description='Use lifecycle nodes'
        ),
        
        DeclareLaunchArgument(
            'sensor_namespace',
            default_value='robot_sensors',
            description='Namespace for sensor nodes'
        ),
        
        # Группа сенсоров
        GroupAction(
            actions=[
                PushRosNamespace(LaunchConfiguration('sensor_namespace')),
                
                # Обычная нода - GPS
                Node(
                    package='gps_package',
                    executable='gps_driver',
                    name='gps_receiver',
                ),
                
                # Lifecycle нода - камера (если включена)
                LifecycleNode(
                    package='camera_package',
                    executable='camera_lifecycle',
                    name='front_camera',
                    condition=IfCondition(LaunchConfiguration('use_lifecycle')),
                ),
                
                # Обычная нода - лидар
                Node(
                    package='lidar_package',
                    executable='lidar_driver',
                    name='lidar_scanner',
                ),
            ]
        ),
        
        # Активация lifecycle нод после запуска
        RegisterEventHandler(
            OnProcessStart(
                target_action=LifecycleNode,
                on_start=[
                    TimerAction(
                        period=2.0,
                        actions=[
                            ExecuteProcess(
                                cmd=['ros2', 'lifecycle', 'set', 
                                     '/robot_sensors/front_camera', 'configure'],
                                output='screen'
                            ),
                            ExecuteProcess(
                                cmd=['ros2', 'lifecycle', 'set',
                                     '/robot_sensors/front_camera', 'activate'],
                                output='screen'
                            )
                        ]
                    )
                ]
            )
        )
    ])
```

### Ключевые различия:

| Тип ноды      | Управление состоянием | Перезапуск     | Сложность |
| ------------- | --------------------- | -------------- | --------- |
| **Обычная**   | Нет                   | Автоматический | Простая   |
| **Lifecycle** | Полное                | Ручное         | Сложная   |
| **Группа**    | Зависит от нод        | Зависит от нод | Гибкая    |

### Когда использовать:

* **Обычные ноды**: простые компоненты, не требующие управления состоянием
* **Lifecycle ноды**: аппаратные драйверы, критичные к состоянию системы
* **Группы**: логически связанные компоненты с общими настройками

Это мощный инструмент для создания сложных, управляемых систем в ROS2!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://alice-and-alex-docs.gitbook.io/alice_and_alex_docs/ros2-development/tipy-nod.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
