Contents

Contents
1
2
3
cd /home/nvidia/orbbec_camera_ros2
source install/setup.bash
ros2 launch orbbec_camera gemini_330_series.launch.py
  1. ob_camera_node_driver.cpp : RCLCPP_COMPONENTS_REGISTER_NODE 注册 OBCameraNodeDriver 为ROS2组件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
GroupAction([
                    PushRosNamespace(LaunchConfiguration("camera_name")),
                    ComposableNodeContainer(
                        name="camera_container",
                        namespace="",
                        package="rclcpp_components",
                        executable="component_container",
                        composable_node_descriptions=[
                            ComposableNode(
                                package="orbbec_camera",
                                plugin="orbbec_camera::OBCameraNodeDriver",
                                name=LaunchConfiguration("camera_name"),
                                parameters=params,
                            ),
                        ],
                        output="screen",
                    )
                ])

可以,下面简要介绍 ROS2 组件机制如何把 name 参数合并到 node_options

当 launch 系统解析 ComposableNode 时,会把 namenamespaceparameters 等参数自动封装到 NodeOptions,并通过 ROS2 组件管理器(component_container)传递给 C++ 端。

  • name 会被转换为 NodeOptionsnode_name 字段。
  • parameters 会被合并到 NodeOptions 的参数列表。

这样你就可以在 launch 文件里灵活指定节点名称,无需修改 C++ 代码。

rclcpp::Node 构造函数会优先使用 [NodeOptions](vscode-file://vscode-app/Applications/Visual Studio Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html) 里的 name,如果没有设置才用你代码里的默认值。

代码块如下:

https://github.com/ros2/rcl/blob/bb46ee68a43cdb91a3c9517cc3ae61d3b6bc489b/rcl/src/rcl/node.c#L218C1-L242C4

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  rcl_arguments_t * global_args = NULL;
  if (node->impl->options.use_global_arguments) {
    global_args = &(node->context->global_arguments);
  }
  ret = rcl_remap_node_name(
    &(node->impl->options.arguments), global_args, name, *allocator,
    &remapped_node_name);
  if (RCL_RET_OK != ret) {
    goto fail;
  } else if (NULL != remapped_node_name) {
    name = remapped_node_name;
  }
  char * remapped_namespace = NULL;
  ret = rcl_remap_node_namespace(
    &(node->impl->options.arguments), global_args, name,
    *allocator, &remapped_namespace);
  if (RCL_RET_OK != ret) {
    goto fail;
  } else if (NULL != remapped_namespace) {
    if (should_free_local_namespace_) {
      allocator->deallocate((char *)local_namespace_, allocator->state);
    }
    should_free_local_namespace_ = true;
    local_namespace_ = remapped_namespace;
  }

启动相机流

是否需要启动IR流

1
const std::vector<stream_index_pair> IMAGE_STREAMS = {COLOR, DEPTH, INFRA0, INFRA1, INFRA2};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    launch2_include = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(launch_file_dir, 'gemini_330_series.launch.py')
        ),
        launch_arguments={
            'camera_name': 'ob_camera_waist',
            'usb_port': '2-3.1',
            'device_num': '2',
            'sync_mode': 'standalone',
            'enable_left_ir': 'true',
            'enable_right_ir': 'true',
        }.items()
    )

    launch3_include = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(launch_file_dir, 'gemini_330_series.launch.py')
        ),
        launch_arguments={
            'camera_name': 'ob_camera_back',
            'usb_port': '2-3.2',
            'device_num': '2',
            'sync_mode': 'standalone',
            'enable_left_ir': 'true',
            'enable_right_ir': 'true',
            'color_rotation': '180',
            'color_format': 'RGB',
        }.items()
    )