docs: add AE/AWB lock test and GigE action command examples; update documentation structure

This commit is contained in:
ob-yalian
2026-09-28 17:45:54 +08:00
parent ede89097f3
commit 9ba23c5cf9
11 changed files with 290 additions and 0 deletions
+6
View File
@@ -60,6 +60,12 @@ docs/
2. Translate and adapt for the Chinese version (`docs/zh/`)
3. Ensure both versions build successfully
## Example Documentation
For examples documented on Pages, the current-version guide is the source of truth for complete usage, configuration, and troubleshooting. Keep their READMEs in the code repository to a short purpose, prerequisites or local settings, run command, and links to the English and Chinese guides. Add new guides to both language navigation trees before shortening an existing README. Keep the example index linked to the source directory and guides.
The Gemini 435Le example is documented in its source-directory README only; keep its full instructions there and link directly to that README from the example index.
## Dependencies
- Sphinx
@@ -12,3 +12,4 @@ This chapter introduces application development with the SDK, including launch p
coordinate_and_tf.md
compressed_image.md
point_cloud.md
examples/ae_awb_lock.md
@@ -0,0 +1,48 @@
# AE/AWB Lock Test
The source file is in [ae_awb_lock](https://github.com/orbbec/OrbbecSDK_ROS2/tree/v2-main/orbbec_camera/examples/ae_awb_lock).
This sample exposes a test-only ROS 2 action that verifies the AE/AWB capture and manual
lock-in flow through the camera driver's services and color-frame metadata.
Run the camera driver and this sample in the same namespace:
```bash
ros2 run orbbec_camera ae_awb_lock_test_node --ros-args -r __ns:=/camera
```
Send a goal and print feedback:
```bash
ros2 action send_goal \
/camera/run_ae_awb_lock_test \
orbbec_camera_msgs/action/RunAeAwbLockTest \
"{timeout_ms: 10000}" \
--feedback
```
The sample subscribes to the relative `color/metadata` topic. It enables auto exposure and auto
white balance, waits until the SDK status equals `1`, captures exposure, color gain, and color
temperature from the latest color-frame metadata, and reads AWB R/B/G gains through the structured
property service. It then disables the auto controls and writes the captured values back in this
order:
1. Color exposure
2. Color gain
3. AWB R/B/G gains
4. Color temperature
The final AWB gain readback must exactly match the captured value. Other readback differences are
reported as warnings because the device may quantize those controls. On failure or cancellation,
the sample restores auto exposure and auto white balance.
Every feedback phase contains a fresh status value read from the camera service. The
`waiting_for_services` feedback is published after all required services become available, because
the status cannot be read before its service is ready.
The color stream must be enabled, and `/camera/color/metadata` must be available when using the
`/camera` namespace. The action fails instead of writing default values if no metadata arrives
before the goal timeout or if `exposure`, `gain`, or `white_balance` is missing. The goal timeout
covers the main workflow, including service discovery, service calls, convergence, capture,
writeback, and verification. Restoring auto exposure and auto white balance after a failure uses a
separate best-effort timeout.
@@ -26,6 +26,7 @@ Multi-Camera
multi_camera/multi_camera_synced.md
multi_camera/multi_camera_synced_verification_tool.md
multi_camera/gmsl_camera.md
multi_camera/gige_action_command.md
Configuration & Modes
@@ -0,0 +1,101 @@
# GigE Action Command
The source files are in [gige_action_command](https://github.com/orbbec/OrbbecSDK_ROS2/tree/v2-main/orbbec_camera/examples/gige_action_command).
This example starts two Gemini 335Le cameras in Group Actions synchronization mode and one
host-side Action Command sender. The sender is intentionally created once at the top level because
a GVCP Action Command can trigger multiple cameras.
## Requirements
- Gemini 335Le firmware 1.8.24 or later
- Orbbec SDK 2.10.2 or later
- Both cameras and the host on the same network
Before running the example, change the two `net_device_ip` values in
`multi_gige_action_command.launch.py` to match the cameras.
## Start the cameras and sender
```bash
ros2 launch orbbec_camera multi_gige_action_command.launch.py
```
The launch file creates these device-scoped configuration services and one network-scoped sender:
```text
/camera_01/get_action_config
/camera_01/set_action_config
/camera_02/get_action_config
/camera_02/set_action_config
/gige_action_command_node/send_action_command
```
## Configure the cameras
Configure Action Signal block 0 on both cameras with matching keys and masks:
```bash
ros2 service call /camera_01/set_action_config \
orbbec_camera_msgs/srv/SetActionConfig \
"{device_key: 1, selector: 0, group_key: 1, group_mask: 1}"
ros2 service call /camera_02/set_action_config \
orbbec_camera_msgs/srv/SetActionConfig \
"{device_key: 1, selector: 0, group_key: 1, group_mask: 1}"
```
Read the configuration back when needed:
```bash
ros2 service call /camera_01/get_action_config \
orbbec_camera_msgs/srv/GetActionConfig \
"{selector: 0}"
```
## Trigger the group
The service exposes three trigger modes. Every camera whose device key, group key, and group mask
match the request will be triggered.
### Immediate trigger
Set `trigger_mode` to `0`. The delay and scheduled time fields must be zero:
```bash
ros2 service call /gige_action_command_node/send_action_command \
orbbec_camera_msgs/srv/SendActionCommand \
"{device_key: 1, group_key: 1, group_mask: 1, broadcast_ip: '255.255.255.255', trigger_mode: 0, delay_ms: 0, scheduled_time: 0}"
```
### Relative-delay trigger
Set `trigger_mode` to `1` and provide a positive delay in milliseconds. The node reads the host
system clock, adds the delay, and converts the result to the absolute GVCP/PTP timestamp expected by
the SDK. This example schedules the command one second in the future:
```bash
ros2 service call /gige_action_command_node/send_action_command \
orbbec_camera_msgs/srv/SendActionCommand \
"{device_key: 1, group_key: 1, group_mask: 1, broadcast_ip: '255.255.255.255', trigger_mode: 1, delay_ms: 1000, scheduled_time: 0}"
```
The host `CLOCK_REALTIME` must be synchronized to the same PTP domain as the cameras, for example
by using `phc2sys`. The launch file enables camera PTP synchronization, but it does not configure
the host PTP services. Choose a delay long enough for the command to reach the cameras before its
target time.
### Absolute PTP-time trigger
Set `trigger_mode` to `2`, leave `delay_ms` at zero, and provide a future encoded PTP timestamp. The
upper 32 bits contain seconds and the lower 32 bits contain nanoseconds:
```bash
ros2 service call /gige_action_command_node/send_action_command \
orbbec_camera_msgs/srv/SendActionCommand \
"{device_key: 1, group_key: 1, group_mask: 1, broadcast_ip: '255.255.255.255', trigger_mode: 2, delay_ms: 0, scheduled_time: <PTP_TIMESTAMP>}"
```
The response returns `encoded_scheduled_time`, the exact 64-bit value sent to the SDK. For delayed
triggering this is the timestamp calculated by the node. `success: true` means the host dispatched
the GVCP command; the protocol does not return a device acknowledgment.
@@ -30,12 +30,16 @@ Further details on efficient intra-process communication can be found [here](htt
The [multi_camera_shared_container](https://github.com/orbbec/OrbbecSDK_ROS2/tree/v2-main/orbbec_camera/examples/multi_camera_shared_container) example creates one multithreaded component container and loads two Gemini 330 Series camera components into it. Update the two `usb_port` values in `multi_camera_shared_container.launch.py`, then run:
The default ports are `2-1` and `2-2`. Use `ros2 run orbbec_camera list_devices_node` to find the ports on your system. Give each camera a unique `camera_name`.
```bash
ros2 launch orbbec_camera multi_camera_shared_container.launch.py
```
The example passes the following arguments to both camera includes:
The top-level launch file starts `shared_orbbec_container` first, then includes the example-specific `gemini_330_series_shared_container.launch.py` for each camera. The second camera starts two seconds after the first. Both includes must use the same container name, and the container must be running before components are loaded.
* `attach_to_shared_component_container=true`: Loads the camera component into an existing container instead of creating another container.
* `component_container_name=shared_orbbec_container`: Selects the target container. The value must match the name of the container created by the parent launch file.
* `use_intra_process_comms=true`: Enables intra-process communication for the camera component.
@@ -12,3 +12,4 @@
coordinate_and_tf.md
compressed_image.md
point_cloud.md
examples/ae_awb_lock.md
@@ -0,0 +1,36 @@
# AE/AWB 锁定测试
本示例提供一个测试用 ROS 2 action,通过相机驱动服务和彩色帧元数据验证自动曝光与自动白平衡收敛后切换到手动值的流程。[查看示例源码](https://github.com/orbbec/OrbbecSDK_ROS2/tree/v2-main/orbbec_camera/examples/ae_awb_lock)。
## 运行
先启动相机驱动,再在同一命名空间启动测试节点:
```bash
ros2 run orbbec_camera ae_awb_lock_test_node --ros-args -r __ns:=/camera
```
发送目标并打印反馈:
```bash
ros2 action send_goal \
/camera/run_ae_awb_lock_test \
orbbec_camera_msgs/action/RunAeAwbLockTest \
"{timeout_ms: 10000}" \
--feedback
```
## 流程与结果
测试节点订阅相对话题 `color/metadata`,启用自动曝光和自动白平衡,等待 SDK 状态变为 `1`。随后,它从最新彩色帧元数据中读取曝光、彩色增益和色温,并通过结构化属性服务读取 AWB 的 R/B/G 增益。关闭自动控制后,按以下顺序写回捕获值:
1. 彩色曝光
2. 彩色增益
3. AWB R/B/G 增益
4. 色温
最后读取的 AWB 增益必须与捕获值完全一致。设备可能量化其他控制值,因此其他读回差异只会作为警告报告。失败或取消时,示例会尝试恢复自动曝光和自动白平衡。
每个反馈阶段都包含从相机服务新读取的状态值。只有必需服务全部可用后才会发布 `waiting_for_services` 反馈,因为此前无法读取状态。
运行时必须开启彩色流;使用 `/camera` 命名空间时,`/camera/color/metadata` 必须可用。如果超时前没有元数据,或元数据缺少 `exposure`、`gain`、`white_balance`,测试会失败,不会写入默认值。目标超时覆盖服务发现、服务调用、收敛、捕获、写回和验证;失败后的自动控制恢复使用独立的尽力而为超时。
@@ -26,6 +26,7 @@
multi_camera/multi_camera_synced.md
multi_camera/multi_camera_synced_verification_tool.md
multi_camera/gmsl_camera.md
multi_camera/gige_action_command.md
配置与模式
@@ -0,0 +1,87 @@
# GigE Action Command
本示例通过 Group Actions 同步模式启动两台 Gemini 335Le 相机,并启动一个主机侧 Action Command 发送节点。一个 GVCP Action Command 可以触发多台相机,因此发送节点只在顶层启动一次。[查看示例源码](https://github.com/orbbec/OrbbecSDK_ROS2/tree/v2-main/orbbec_camera/examples/gige_action_command)。
## 运行条件
- Gemini 335Le 固件 1.8.24 或更高版本
- Orbbec SDK 2.10.2 或更高版本
- 两台相机与主机位于同一网络
运行前,修改 `multi_gige_action_command.launch.py` 中两处 `net_device_ip`,使其与相机 IP 一致。
## 启动相机和发送节点
```bash
ros2 launch orbbec_camera multi_gige_action_command.launch.py
```
启动文件为每台相机提供配置服务,并启动一个发送服务:
```text
/camera_01/get_action_config
/camera_01/set_action_config
/camera_02/get_action_config
/camera_02/set_action_config
/gige_action_command_node/send_action_command
```
## 配置相机
将两台相机的 Action Signal block 0 配置为相同的 key 和 mask:
```bash
ros2 service call /camera_01/set_action_config \
orbbec_camera_msgs/srv/SetActionConfig \
"{device_key: 1, selector: 0, group_key: 1, group_mask: 1}"
ros2 service call /camera_02/set_action_config \
orbbec_camera_msgs/srv/SetActionConfig \
"{device_key: 1, selector: 0, group_key: 1, group_mask: 1}"
```
需要时可读取配置:
```bash
ros2 service call /camera_01/get_action_config \
orbbec_camera_msgs/srv/GetActionConfig \
"{selector: 0}"
```
## 触发相机组
请求中的 device key、group key 和 group mask 与相机配置匹配时,相机会收到触发命令。发送服务支持以下三种模式。
### 立即触发
将 `trigger_mode` 设为 `0`,延迟和指定时间均设为零:
```bash
ros2 service call /gige_action_command_node/send_action_command \
orbbec_camera_msgs/srv/SendActionCommand \
"{device_key: 1, group_key: 1, group_mask: 1, broadcast_ip: '255.255.255.255', trigger_mode: 0, delay_ms: 0, scheduled_time: 0}"
```
### 相对延迟触发
将 `trigger_mode` 设为 `1`,并提供正数毫秒延迟。节点读取主机系统时钟,加上延迟后转换为 SDK 所需的绝对 GVCP/PTP 时间戳。以下示例延迟一秒:
```bash
ros2 service call /gige_action_command_node/send_action_command \
orbbec_camera_msgs/srv/SendActionCommand \
"{device_key: 1, group_key: 1, group_mask: 1, broadcast_ip: '255.255.255.255', trigger_mode: 1, delay_ms: 1000, scheduled_time: 0}"
```
主机的 `CLOCK_REALTIME` 必须与相机处于同一 PTP 时间域,例如使用 `phc2sys` 同步。启动文件会启用相机的 PTP 同步,但不会配置主机 PTP 服务。延迟应足够长,确保命令能在目标时间前到达相机。
### 绝对 PTP 时间触发
将 `trigger_mode` 设为 `2`,`delay_ms` 设为零,并提供未来的编码 PTP 时间戳。高 32 位为秒,低 32 位为纳秒:
```bash
ros2 service call /gige_action_command_node/send_action_command \
orbbec_camera_msgs/srv/SendActionCommand \
"{device_key: 1, group_key: 1, group_mask: 1, broadcast_ip: '255.255.255.255', trigger_mode: 2, delay_ms: 0, scheduled_time: <PTP_TIMESTAMP>}"
```
响应中的 `encoded_scheduled_time` 是发送给 SDK 的准确 64 位数值。延迟触发时,该值由节点计算。`success: true` 表示主机已发出 GVCP 命令;协议不会返回设备确认。
@@ -30,10 +30,14 @@
[multi_camera_shared_container](https://github.com/orbbec/OrbbecSDK_ROS2/tree/v2-main/orbbec_camera/examples/multi_camera_shared_container) 示例创建一个多线程组件容器,并将两个 Gemini 330 系列相机组件加载到该容器中。修改 `multi_camera_shared_container.launch.py` 中两台相机的 `usb_port` 后,运行:
默认端口为 `2-1` 和 `2-2`。可通过 `ros2 run orbbec_camera list_devices_node` 查询本机端口,并为每台相机设置不同的 `camera_name`。
```bash
ros2 launch orbbec_camera multi_camera_shared_container.launch.py
```
顶层启动文件先创建 `shared_orbbec_container`,再为两台相机分别包含示例专用的 `gemini_330_series_shared_container.launch.py`;第二台相机延迟两秒启动。两个相机必须指定相同的容器名称,并在加载组件前确保容器已经运行。
该示例向两个相机 include 传递以下参数:
* `attach_to_shared_component_container=true`:将相机组件加载到已有容器中,而不是新建容器。