diff --git a/README.MD b/README.MD index 0eef390a..89b10d57 100644 --- a/README.MD +++ b/README.MD @@ -53,6 +53,27 @@ The **OrbbecSDK ROS2 Wrapper** provides seamless integration of Orbbec cameras w - For legacy **OpenNI** devices: use the **main** branch - For users in China: use the [Gitee repository](https://gitee.com/orbbecdeveloper/OrbbecSDK_ROS2) +## Start Here + +Detailed usage, parameters, and troubleshooting are maintained on the official +[OrbbecSDK ROS2 documentation site](https://orbbec.github.io/OrbbecSDK_ROS2/en/index.html). +Use the links below to go directly to the guide for your task. + +| I want to... | Go to... | +| --- | --- | +| Install the wrapper and configure device permissions | [Installation](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/2_installation/installation.html) | +| Launch a camera and view images in RViz2 | [ROS Package QuickStarts](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/3_quickstarts/quickstart.html) | +| Check device support, firmware, and the correct launch file | [Supported hardware](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/1_overview/introduction.html) | +| Configure launch parameters, topics, services, TF, or point clouds | [Application Guide](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/4_application_guide/application_guide.html) | +| Find maintenance, diagnostic, benchmark, or multi-camera tools | [Tool Index](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/6_benchmark/tools.html) | +| Use network cameras, GMSL, multi-camera, or advanced modes | [Advanced Guide](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/5_advanced_guide/advanced_guide.html) | +| Diagnose a failure or collect logs for support | [Frequently Asked Questions](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/8_FAQ/FAQ.html) | +| Migrate an existing project from main (v1.x) | [Migration Guide](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/7_developer_guide/migration_guide.html) | +| Use an Orbbec LiDAR | [LiDAR documentation](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/lidar_devices/index.html) | + +Source files for practical launch examples are listed in the +[Examples index](./orbbec_camera/examples/). + ## branch selection Here is the device support list of main branch (v1.x) and v2-main branch (v2.x): @@ -490,17 +511,10 @@ For optimal performance, we strongly recommend updating to the latest firmware v All launch files are essentially similar, with the primary difference being the default values of the parameters set for different models within the same series. Differences in USB standards, such as USB 2.0 versus USB 3.0, may require adjustments to these parameters. If you encounter a startup failure, please carefully review the specification manual. Pay special attention to the resolution settings in the launch file, as well as other parameters, to ensure compatibility and optimal performance. -## Tutorial - -please refer to the official [OrbbecSDK ROS2 documentation](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/5_advanced_guide/advanced_guide.html) - -## Examples - -To explore practical examples and gain insight into how to use the camera in ROS, please navigate to the [Examples](./orbbec_camera/examples/) section for more information. - -## Other useful links +## Related Links - [OrbbecSDK ROS2 documentation](https://orbbec.github.io/OrbbecSDK_ROS2/en/index.html) +- [Examples index](./orbbec_camera/examples/) - [OrbbecSDK_v2](https://github.com/orbbec/OrbbecSDK_v2/releases) - [Gemini 330 depth presets](https://www.orbbec.com/docs/g330-use-depth-presets/) diff --git a/README_CN.MD b/README_CN.MD index 0ae10dea..17639ac4 100644 --- a/README_CN.MD +++ b/README_CN.MD @@ -5,46 +5,6 @@

OrbbecSDK ROS2 Wrapper v2

- -

- English | 中文 -

- - - - - ROS Foxy - - - ROS Humble - - - ROS Jazzy - - - ROS Lyrical - - - ROS Rolling (experimental) - - Ubuntu 20.04 - Ubuntu 22.04 - Ubuntu 24.04 - Ubuntu 26.04 - - -
- - branch v2-main - - - license Apache-2.0 - - - Gitee mirror - - - ## 简介 OrbbecSDK ROS2 Wrapper 提供 Orbbec 相机与 ROS 2 环境的无缝集成,支持 **ROS2 Foxy、Humble、Jazzy 和 Lyrical** 发行版,并提供对 **Rolling** 的实验性支持。 @@ -53,6 +13,26 @@ OrbbecSDK ROS2 Wrapper 提供 Orbbec 相机与 ROS 2 环境的无缝集成,支 - 对于旧的 **OpenNI** 设备(v2-main 不支持),请使用 **main** 分支。 - 如果您在中国使用,建议使用 [gitee 仓库](https://gitee.com/orbbecdeveloper/OrbbecSDK_ROS2)。 +## 从这里开始 + +完整的使用方法、参数说明和故障排查统一维护在官方 +[OrbbecSDK ROS2 文档站](https://orbbec.github.io/OrbbecSDK_ROS2/zh/index.html)。 +请根据您的目标直接进入对应指南。 + +| 我想要…… | 请查看…… | +| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- | +| 安装驱动并配置设备权限 | [安装指南](https://orbbec.github.io/OrbbecSDK_ROS2/zh/source/camera_devices/2_installation/installation.html) | +| 启动相机并在 RViz2 中查看图像 | [ROS 包快速入门](https://orbbec.github.io/OrbbecSDK_ROS2/zh/source/camera_devices/3_quickstarts/quickstart.html) | +| 确认设备支持、固件版本和启动文件 | [支持的硬件](https://orbbec.github.io/OrbbecSDK_ROS2/zh/source/camera_devices/1_overview/introduction.html) | +| 配置启动参数、话题、服务、TF 或点云 | [应用指南](https://orbbec.github.io/OrbbecSDK_ROS2/zh/source/camera_devices/4_application_guide/application_guide.html) | +| 查找维护、诊断、性能测试或多相机工具 | [工具索引](https://orbbec.github.io/OrbbecSDK_ROS2/zh/source/camera_devices/6_benchmark/tools.html) | +| 使用网络相机、GMSL、多相机或高级模式 | [高级指南](https://orbbec.github.io/OrbbecSDK_ROS2/zh/source/camera_devices/5_advanced_guide/advanced_guide.html) | +| 排查故障或收集技术支持所需日志 | [常见问题](https://orbbec.github.io/OrbbecSDK_ROS2/zh/source/camera_devices/8_FAQ/FAQ.html) | +| 将现有项目从 main (v1.x) 迁移 | [迁移指南](https://orbbec.github.io/OrbbecSDK_ROS2/zh/source/camera_devices/7_developer_guide/migration_guide.html) | +| 使用 Orbbec LiDAR | [LiDAR 文档](https://orbbec.github.io/OrbbecSDK_ROS2/zh/source/lidar_devices/index.html) | + +实用启动示例的源文件可在[示例索引](./orbbec_camera/examples/)中查找。 + ## 分支选择 以下是 main 分支 (v1.x) 和 v2-main 分支 (v2.x) 的设备支持列表: @@ -301,6 +281,7 @@ git checkout v2-main cd ~/ros2_ws colcon build --event-handlers console_direct+ --cmake-args -DCMAKE_BUILD_TYPE=Release ``` + ## 注册脚本(必需) 为了让 Orbbec 相机在 Linux 上被正确识别,请安装 udev 规则。 @@ -488,17 +469,10 @@ ros2 service call /camera/get_sdk_version orbbec_camera_msgs/srv/GetString '{}' 所有启动文件基本相似,主要区别在于针对不同型号的默认参数设置。不同的 USB 标准(如 USB 2.0 和 USB 3.0)可能需要调整这些参数。如果遇到启动失败,请仔细查看规格说明书,特别是启动文件中的分辨率设置以及其他参数,以确保兼容性和最佳性能。 -## 教程 - -请参考官方 [OrbbecSDK ROS2 文档](https://orbbec.github.io/OrbbecSDK_ROS2/zh/source/camera_devices/5_advanced_guide/advanced_guide.html) - -## 示例 - -要查看更多实践示例并了解如何在 ROS 中使用相机,请参阅 [Examples](./orbbec_camera/examples/) 部分。 - -## 其他有用链接 +## 相关链接 - [OrbbecSDK ROS2 文档](https://orbbec.github.io/OrbbecSDK_ROS2/zh/index.html) +- [示例索引](./orbbec_camera/examples/) - [OrbbecSDK_v2](https://github.com/orbbec/OrbbecSDK_v2/releases) - [Gemini 330 深度预设](https://www.orbbec.com/docs/g330-use-depth-presets/) diff --git a/orbbec_camera/examples/README.MD b/orbbec_camera/examples/README.MD index 51cd7ffd..536d3d45 100644 --- a/orbbec_camera/examples/README.MD +++ b/orbbec_camera/examples/README.MD @@ -1,12 +1,17 @@ -# Sample launch for OrbbecSDK_ROS2 +# OrbbecSDK ROS2 Examples -These simple examples demonstrate how to easily use the camera with OrbbecSDK_ROS2 +This directory contains practical launch and tool examples. Full usage, +configuration, and troubleshooting are maintained on the official documentation +site so that instructions have a single source of truth. -## List of Examples: +For command-line maintenance and diagnostic utilities, see the official +[Tool Index](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/6_benchmark/tools.html). -| Name | Description | Experience Level | Document | -| :---------------------------------------------------------------------------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | ----------------------------------------------------------------------------- | -| [Net_camera](./net_camera) | How to use Net camera in OrbbecSDK_ROS2(Only Femto Mega nad Gemini 335Le) | ⭐️ | [Net_camera](https://orbbec.github.io/OrbbecSDK_ROS2/source/5_advanced_guide/configuration/net_camera.html) | -| [Gmsl_camera](./gmsl_camera) | How to use GMSL cameras (Gemini 335Lg, 338Lg, 345Lg, and 305g). | ⭐️ | [Gmsl_camera](https://orbbec.github.io/OrbbecSDK_ROS2/source/5_advanced_guide/multi_camera/gmsl_camera.html) | -| [Benchmark](./benchmark) | The goal of this tool is to benchmark the performance of various OrbbecSDK_ROS2 camera configurations. | ⭐️⭐️ | [Benchmark](https://orbbec.github.io/OrbbecSDK_ROS2/source/5_advanced_guide/performance/benchmark.html) | -| [Multi_camera_synced_verification_tool](./multi_camera_synced_verification_tool) | How to verify the synchronization accuracy of multi-camera synchronization. | ⭐️⭐️⭐️ | [Multi_camera_synced_verification_tool](https://orbbec.github.io/OrbbecSDK_ROS2/source/5_advanced_guide/multi_camera/multi_camera_synced_verification_tool.html) | +## Example Index + +| Source | Purpose | Experience Level | Official Guide | +| :---: | --- | :---: | --- | +| [Net camera](./net_camera) | Launch supported Orbbec network cameras. | ⭐️ | [Network camera guide](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/5_advanced_guide/configuration/net_camera.html) | +| [GMSL camera](./gmsl_camera) | Launch single, multiple, or synchronized GMSL cameras. | ⭐️ | [GMSL camera guide](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/5_advanced_guide/multi_camera/gmsl_camera.html) | +| [Benchmark](./benchmark) | Benchmark the performance of different camera configurations. | ⭐️⭐️ | [Performance benchmark tools](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/6_benchmark/benchmark_tools.html) | +| [Multi-camera synchronization verification](./multi_camera_synced_verification_tool) | Verify synchronization accuracy across multiple cameras. | ⭐️⭐️⭐️ | [Synchronization verification guide](https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/5_advanced_guide/multi_camera/multi_camera_synced_verification_tool.html) | diff --git a/orbbec_camera/scripts/common_benchmark_node.py b/orbbec_camera/scripts/common_benchmark_node.py index 97f4e169..a012d5a6 100644 --- a/orbbec_camera/scripts/common_benchmark_node.py +++ b/orbbec_camera/scripts/common_benchmark_node.py @@ -12,6 +12,7 @@ usage: """ import argparse +import sys import rclpy from rclpy.node import Node import psutil @@ -21,11 +22,24 @@ import os from collections import defaultdict from orbbec_camera_msgs.msg import DeviceStatus from sensor_msgs.msg import Image -import sys from tabulate import tabulate CAMERA_NODE_NAMES = ["component_container", "orbbec_camera_node", "nodelet"] +DOCUMENTATION_URL = ( + "https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/" + "6_benchmark/benchmark_tools.html" +) + + +class DocumentationArgumentParser(argparse.ArgumentParser): + def error(self, message): + self.print_usage(sys.stderr) + self.exit( + 2, + f"{self.prog}: error: {message}\n" + f"For usage and troubleshooting, see: {DOCUMENTATION_URL}\n", + ) # ----------------tool functions---------------- def parse_duration(s): @@ -471,7 +485,10 @@ class CameraMonitorNode(Node): def main(argv=None): - parser = argparse.ArgumentParser() + parser = DocumentationArgumentParser( + epilog=f"Documentation: {DOCUMENTATION_URL}", + formatter_class=argparse.RawDescriptionHelpFormatter, + ) parser.add_argument("--run_time", type=str, default="10s", help="Total run time for monitoring, e.g., 10s, 5m, 1h.") parser.add_argument("--csv_file", type=str, default="camera_monitor_log.csv") parser.add_argument("--ideal_fps", type=float, default=0.0, help="Optional ideal frame rate to use for drop detection (overrides reported avg).") @@ -494,4 +511,8 @@ def main(argv=None): node.destroy_node() if __name__ == "__main__": - main() + try: + main() + except Exception: + print(f"For usage and troubleshooting, see: {DOCUMENTATION_URL}", file=sys.stderr) + raise diff --git a/orbbec_camera/scripts/service_benchmark_node.py b/orbbec_camera/scripts/service_benchmark_node.py index 3aaed950..e79dd93e 100644 --- a/orbbec_camera/scripts/service_benchmark_node.py +++ b/orbbec_camera/scripts/service_benchmark_node.py @@ -23,6 +23,23 @@ from statistics import mean from tabulate import tabulate import importlib import csv +import sys + + +DOCUMENTATION_URL = ( + "https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/" + "6_benchmark/benchmark_tools.html" +) + + +class DocumentationArgumentParser(argparse.ArgumentParser): + def error(self, message): + self.print_usage(sys.stderr) + self.exit( + 2, + f"{self.prog}: error: {message}\n" + f"For usage and troubleshooting, see: {DOCUMENTATION_URL}\n", + ) class ServiceBenchmark: @@ -180,7 +197,10 @@ class BenchmarkRunner: def main(): - parser = argparse.ArgumentParser() + parser = DocumentationArgumentParser( + epilog=f"Documentation: {DOCUMENTATION_URL}", + formatter_class=argparse.RawDescriptionHelpFormatter, + ) parser.add_argument("--service", help="Service name") parser.add_argument("--count", type=int, default=10, help="Number of calls") parser.add_argument("--yaml_file", help="YAML config file for batch testing") @@ -207,4 +227,8 @@ def main(): if __name__ == "__main__": - main() + try: + main() + except Exception: + print(f"For usage and troubleshooting, see: {DOCUMENTATION_URL}", file=sys.stderr) + raise diff --git a/orbbec_camera/tools/firmware_update_tool.cpp b/orbbec_camera/tools/firmware_update_tool.cpp index 01943fe5..3fdb97b5 100644 --- a/orbbec_camera/tools/firmware_update_tool.cpp +++ b/orbbec_camera/tools/firmware_update_tool.cpp @@ -33,6 +33,9 @@ #include "orbbec_camera/utils.h" namespace { +constexpr char kDocumentationUrl[] = + "https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/6_benchmark/" + "firmware_update_tool.html"; constexpr int kProgressLogBucketPercent = 25; constexpr int kFirmwareLogDrainDelaySec = 5; @@ -131,7 +134,9 @@ void printUsage() { << " 2) If multiple devices are connected, specify target by serial/usb/ip to avoid wrong " "updates.\n" << " 3) Repeating --serial_number or passing comma-separated values enables sequential " - "batch update.\n"; + "batch update.\n\n" + << "Documentation:\n" + << " " << kDocumentationUrl << "\n"; } bool parseArgs(int argc, char **argv, CliArgs &args, std::string &error) { @@ -862,6 +867,7 @@ int main(int argc, char **argv) { RCLCPP_ERROR(logger, "Unknown error"); } + RCLCPP_ERROR(logger, "For usage and troubleshooting, see: %s", kDocumentationUrl); rclcpp::shutdown(); return 1; } diff --git a/orbbec_camera/tools/ip_config_tool.cpp b/orbbec_camera/tools/ip_config_tool.cpp index 2a1fef60..6f36ecde 100644 --- a/orbbec_camera/tools/ip_config_tool.cpp +++ b/orbbec_camera/tools/ip_config_tool.cpp @@ -14,6 +14,9 @@ using namespace ob; namespace { constexpr int kFirmwareLogDrainDelaySec = 5; +constexpr char kDocumentationUrl[] = + "https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/6_benchmark/" + "network_config_tools.html"; void waitForFirmwareLogDrain(const rclcpp::Logger &logger) { RCLCPP_INFO(logger, "Waiting %d seconds to keep firmware log alive...", @@ -25,6 +28,12 @@ bool isSdkLogEnabled(const std::string &log_level) { return orbbec_camera::obLogSeverityFromString(log_level) != OBLogSeverity::OB_LOG_SEVERITY_OFF; } +int reportFailure(const rclcpp::Logger &logger) { + RCLCPP_ERROR(logger, "For usage and troubleshooting, see: %s", kDocumentationUrl); + rclcpp::shutdown(); + return 1; +} + } // namespace struct CliArgs { @@ -177,7 +186,9 @@ void printHelp() { << " Debug: ros2 run orbbec_camera ip_config_tool -- \\\n" << " set_ip --current_ip 192.168.1.10 --enable_dhcp true " "--enable_persistent_ip false \\\n" - << " --sdk_log_level debug\n"; + << " --sdk_log_level debug\n\n" + << "Documentation:\n" + << " " << kDocumentationUrl << "\n"; } bool parseArgs(int argc, char **argv, CliArgs &args, std::string &error) { @@ -461,18 +472,15 @@ int main(int argc, char **argv) { uint8_t gateway[4] = {0}; if (args.persistent_ip && !parseIpString(args.new_ip, address)) { RCLCPP_ERROR(logger, "Invalid new_ip format: %s", args.new_ip.c_str()); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } if (args.persistent_ip && !parseIpString(args.mask, mask)) { RCLCPP_ERROR(logger, "Invalid mask format: %s", args.mask.c_str()); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } if (args.persistent_ip && !parseIpString(args.gateway, gateway)) { RCLCPP_ERROR(logger, "Invalid gateway format: %s", args.gateway.c_str()); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } OBNetIpConfigV2 ip_config_v2{}; @@ -521,8 +529,7 @@ int main(int argc, char **argv) { "Legacy IP config (1041) supports mutually exclusive DHCP and persistent " "IP only. Use --enable_dhcp true --enable_persistent_ip false or " "--enable_dhcp false --enable_persistent_ip true."); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } ip_config.dhcp = args.dhcp ? 1 : 0; uint8_t address[4] = {0}; @@ -530,18 +537,15 @@ int main(int argc, char **argv) { uint8_t gateway[4] = {0}; if (args.persistent_ip && !parseIpString(args.new_ip, address)) { RCLCPP_ERROR(logger, "Invalid new_ip format: %s", args.new_ip.c_str()); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } if (args.persistent_ip && !parseIpString(args.mask, mask)) { RCLCPP_ERROR(logger, "Invalid mask format: %s", args.mask.c_str()); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } if (args.persistent_ip && !parseIpString(args.gateway, gateway)) { RCLCPP_ERROR(logger, "Invalid gateway format: %s", args.gateway.c_str()); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } if (args.persistent_ip) { std::memcpy(ip_config.address, address, sizeof(address)); @@ -579,18 +583,15 @@ int main(int argc, char **argv) { if (!args.dhcp) { if (!parseIpString(args.new_ip, ip_config.address)) { RCLCPP_ERROR(logger, "Invalid new_ip format: %s", args.new_ip.c_str()); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } if (!parseIpString(args.mask, ip_config.mask)) { RCLCPP_ERROR(logger, "Invalid mask format: %s", args.mask.c_str()); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } if (!parseIpString(args.gateway, ip_config.gateway)) { RCLCPP_ERROR(logger, "Invalid gateway format: %s", args.gateway.c_str()); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } } @@ -607,8 +608,7 @@ int main(int argc, char **argv) { } } else { RCLCPP_ERROR(logger, "Force-ip failed (SDK returned false)."); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } } @@ -621,16 +621,14 @@ int main(int argc, char **argv) { if (!device->isPropertySupported(OB_PROP_DHCP_ASSIGN_IP_TIMEOUT_INT, OB_PERMISSION_WRITE)) { RCLCPP_ERROR(logger, "Current device or firmware does not support DHCP assign IP timeout"); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } auto range = device->getIntPropertyRange(OB_PROP_DHCP_ASSIGN_IP_TIMEOUT_INT); if (args.dhcp_assign_ip_timeout < range.min || args.dhcp_assign_ip_timeout > range.max) { RCLCPP_ERROR(logger, "Timeout %d is out of range [%d, %d]", args.dhcp_assign_ip_timeout, range.min, range.max); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } device->setIntProperty(OB_PROP_DHCP_ASSIGN_IP_TIMEOUT_INT, args.dhcp_assign_ip_timeout); @@ -645,16 +643,13 @@ int main(int argc, char **argv) { } catch (ob::Error &e) { RCLCPP_ERROR(logger, "ip_config_tool: %s", orbbec_camera::formatObErrorWithStatus(e).c_str()); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } catch (const std::exception &e) { RCLCPP_ERROR(logger, "ip_config_tool: %s", e.what()); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } catch (...) { RCLCPP_ERROR(logger, "ip_config_tool: unknown error"); - rclcpp::shutdown(); - return 1; + return reportFailure(logger); } rclcpp::shutdown(); diff --git a/orbbec_camera/tools/list_camera_profile.cpp b/orbbec_camera/tools/list_camera_profile.cpp index 364e8825..78c03a6f 100644 --- a/orbbec_camera/tools/list_camera_profile.cpp +++ b/orbbec_camera/tools/list_camera_profile.cpp @@ -15,6 +15,9 @@ using namespace orbbec_camera; namespace { constexpr int kFirmwareLogDrainDelaySec = 5; +constexpr char kDocumentationUrl[] = + "https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/6_benchmark/" + "device_query_tools.html"; struct CliArgs { bool help = false; @@ -33,7 +36,9 @@ void printUsage() { "(default: off).\n" << " -h, --help Show this help message.\n" << "Examples:\n" - << " ros2 run orbbec_camera list_camera_profile_mode_node -- --sdk_log_level debug\n"; + << " ros2 run orbbec_camera list_camera_profile_mode_node -- --sdk_log_level debug\n\n" + << "Documentation:\n" + << " " << kDocumentationUrl << "\n"; } bool parseArgs(int argc, char** argv, CliArgs& args, std::string& error) { @@ -116,7 +121,8 @@ std::shared_ptr initializeDevice(const std::string& serial_number) { auto context = std::make_shared(); auto device_list = context->queryDeviceList(); if (!device_list || device_list->getCount() == 0) { - std::cout << "No device found" << std::endl; + std::cout << "No device found\nFor usage and troubleshooting, see: " << kDocumentationUrl + << std::endl; return nullptr; } diff --git a/orbbec_camera/tools/list_devices_node.cpp b/orbbec_camera/tools/list_devices_node.cpp index aeca24a3..6cdfcb36 100644 --- a/orbbec_camera/tools/list_devices_node.cpp +++ b/orbbec_camera/tools/list_devices_node.cpp @@ -29,6 +29,9 @@ namespace { constexpr int kFirmwareLogDrainDelaySec = 5; +constexpr char kDocumentationUrl[] = + "https://orbbec.github.io/OrbbecSDK_ROS2/en/source/camera_devices/6_benchmark/" + "device_query_tools.html"; struct CliArgs { bool help = false; @@ -42,7 +45,9 @@ void printUsage() { << " --sdk_log_level LEVEL SDK file log level: debug/info/warn/error/fatal/off " "(default: off).\n\n" << "Examples:\n" - << " ros2 run orbbec_camera list_devices_node -- --sdk_log_level debug\n"; + << " ros2 run orbbec_camera list_devices_node -- --sdk_log_level debug\n\n" + << "Documentation:\n" + << " " << kDocumentationUrl << "\n"; } bool parseArgs(int argc, char **argv, CliArgs &args, std::string &error) { @@ -339,10 +344,16 @@ int main(int argc, char **argv) { } catch (ob::Error &e) { RCLCPP_ERROR_STREAM(rclcpp::get_logger("list_device_node"), orbbec_camera::formatObErrorWithStatus(e)); + RCLCPP_ERROR_STREAM(rclcpp::get_logger("list_device_node"), + "For usage and troubleshooting, see: " << kDocumentationUrl); } catch (const std::exception &e) { RCLCPP_ERROR_STREAM(rclcpp::get_logger("list_device_node"), e.what()); + RCLCPP_ERROR_STREAM(rclcpp::get_logger("list_device_node"), + "For usage and troubleshooting, see: " << kDocumentationUrl); } catch (...) { RCLCPP_ERROR_STREAM(rclcpp::get_logger("list_device_node"), "unknown error"); + RCLCPP_ERROR_STREAM(rclcpp::get_logger("list_device_node"), + "For usage and troubleshooting, see: " << kDocumentationUrl); } return 0; }