mirror of
https://github.com/orbbec/OrbbecSDK_ROS2.git
synced 2026-10-04 12:07:46 +08:00
Merge branch 'docs/improve-user-navigation' into v2/develop
This commit is contained in:
@@ -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) |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<ob::Device> initializeDevice(const std::string& serial_number) {
|
||||
auto context = std::make_shared<ob::Context>();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user