diff --git a/.github/rosdep/orbbec-camera-msgs.yaml b/.github/rosdep/orbbec-camera-msgs.yaml new file mode 100644 index 00000000..97aa85ab --- /dev/null +++ b/.github/rosdep/orbbec-camera-msgs.yaml @@ -0,0 +1,5 @@ +orbbec_camera_msgs: + ubuntu: + jammy: [ros-humble-orbbec-camera-msgs] + noble: [ros-jazzy-orbbec-camera-msgs] + resolute: [ros-lyrical-orbbec-camera-msgs] diff --git a/.github/workflows/colcon.yml b/.github/workflows/colcon.yml index c8afe194..1beb8a77 100644 --- a/.github/workflows/colcon.yml +++ b/.github/workflows/colcon.yml @@ -1,20 +1,30 @@ -name: colcon +name: CI -on: [push, pull_request] +on: + push: + pull_request: + workflow_dispatch: + +permissions: read-all jobs: - # build on Ubuntu docker images build: - name: "${{ matrix.image }} (${{ matrix.ros }})" + name: "ROS2 ${{ matrix.ros }} (${{ matrix.os }})" - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.ros == 'rolling' }} + env: + ROS_DISTRO: ${{ matrix.ros }} strategy: + fail-fast: false matrix: include: - - {image: "ubuntu:22.04", ros: humble} - - {image: "ubuntu:24.04", ros: jazzy} - - {image: "ubuntu:26.04", ros: lyrical} + - {image: "ros:foxy-ros-core-focal", os: ubuntu-22.04, ros: foxy} + - {image: "ros:humble-ros-core-jammy", os: ubuntu-22.04, ros: humble} + - {image: "ros:jazzy-ros-core-noble", os: ubuntu-24.04, ros: jazzy} + - {image: "ros:lyrical-ros-core-resolute", os: ubuntu-26.04, ros: lyrical} + - {image: "ros:rolling-ros-core-resolute", os: ubuntu-26.04, ros: rolling} container: image: ${{ matrix.image }} @@ -22,8 +32,24 @@ jobs: steps: - uses: actions/checkout@v6 - - uses: ros-tooling/setup-ros@v0.7 + - name: Install build tools + shell: bash + run: | + set -euo pipefail + apt-get update + apt-get install --no-install-recommends --yes \ + build-essential \ + cmake \ + git \ + python3-colcon-common-extensions \ + python3-rosdep + rosdep init || true + rosdep update --rosdistro "${ROS_DISTRO}" --include-eol-distros - - uses: ros-tooling/action-ros-ci@v0.4 - with: - target-ros2-distro: ${{ matrix.ros }} + - name: Install dependencies and build + shell: bash + run: | + set -eo pipefail + source "/opt/ros/${ROS_DISTRO}/setup.bash" + rosdep install --from-paths . --ignore-src --rosdistro "${ROS_DISTRO}" -y + colcon build --symlink-install --event-handlers console_direct+ diff --git a/.github/workflows/debian-packages.yml b/.github/workflows/debian-packages.yml new file mode 100644 index 00000000..8acaa6e3 --- /dev/null +++ b/.github/workflows/debian-packages.yml @@ -0,0 +1,222 @@ +name: Build Debian packages + +on: + workflow_dispatch: + inputs: + ros_distro: + description: ROS 2 distribution to package + required: true + default: all + type: choice + options: + - all + - humble + - jazzy + - lyrical + architecture: + description: CPU architecture to package + required: true + default: all + type: choice + options: + - all + - amd64 + - arm64 + +permissions: + contents: read + +jobs: + prepare: + name: Prepare build matrix + runs-on: ubuntu-24.04 + outputs: + matrix: ${{ steps.matrix.outputs.matrix }} + + steps: + - name: Generate selected build matrix + id: matrix + shell: bash + env: + SELECTED_ROS_DISTRO: ${{ inputs.ros_distro }} + SELECTED_ARCHITECTURE: ${{ inputs.architecture }} + run: | + set -euo pipefail + + architectures=(amd64 arm64) + if [[ "${SELECTED_ARCHITECTURE}" != "all" ]]; then + architectures=("${SELECTED_ARCHITECTURE}") + fi + + entries=() + while IFS='|' read -r ros_distro ubuntu_codename ubuntu_version; do + if [[ "${SELECTED_ROS_DISTRO}" != "all" && + "${SELECTED_ROS_DISTRO}" != "${ros_distro}" ]]; then + continue + fi + + for architecture in "${architectures[@]}"; do + runner="ubuntu-${ubuntu_version}" + if [[ "${architecture}" == "arm64" ]]; then + runner="${runner}-arm" + fi + + printf -v entry \ + '{"ros":"%s","arch":"%s","runner":"%s","image":"ros:%s-ros-core-%s"}' \ + "${ros_distro}" \ + "${architecture}" \ + "${runner}" \ + "${ros_distro}" \ + "${ubuntu_codename}" + entries+=("${entry}") + done + done <<'EOF' + humble|jammy|22.04 + jazzy|noble|24.04 + lyrical|resolute|26.04 + EOF + + matrix=$(IFS=,; printf '{"include":[%s]}' "${entries[*]}") + echo "matrix=${matrix}" >> "${GITHUB_OUTPUT}" + + build: + name: ROS 2 ${{ matrix.ros }} (${{ matrix.arch }}) + needs: prepare + runs-on: ${{ matrix.runner }} + container: + image: ${{ matrix.image }} + strategy: + fail-fast: false + matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }} + env: + DEBIAN_FRONTEND: noninteractive + ROS_DISTRO: ${{ matrix.ros }} + + steps: + - uses: actions/checkout@v6 + + - name: Install packaging tools and dependencies + shell: bash + run: | + set -euo pipefail + apt-get update + apt-get install --no-install-recommends --yes \ + build-essential \ + cmake \ + debhelper \ + fakeroot \ + git \ + python3-bloom \ + python3-rosdep + + rosdep init || true + + local_rosdep_dir="${RUNNER_TEMP}/orbbec-rosdep" + mkdir -p "${local_rosdep_dir}" + printf 'yaml file://%s/.github/rosdep/orbbec-camera-msgs.yaml\n' \ + "${GITHUB_WORKSPACE}" \ + > "${local_rosdep_dir}/10-orbbec-camera-msgs.list" + export ROSDEP_SOURCE_PATH="${local_rosdep_dir}:/etc/ros/rosdep/sources.list.d" + echo "ROSDEP_SOURCE_PATH=${ROSDEP_SOURCE_PATH}" >> "${GITHUB_ENV}" + + rosdep update --rosdistro "${ROS_DISTRO}" + + set +u + source "/opt/ros/${ROS_DISTRO}/setup.bash" + set -u + rosdep install \ + --from-paths orbbec_camera_msgs orbbec_camera \ + --ignore-src \ + --rosdistro "${ROS_DISTRO}" \ + -y + + - name: Build and install message package + shell: bash + run: | + set -euo pipefail + set +u + source "/opt/ros/${ROS_DISTRO}/setup.bash" + set -u + + ( + cd orbbec_camera_msgs + bash .make_deb.sh + ) + + mapfile -t message_packages < <( + find . -maxdepth 1 -type f \ + -name "ros-${ROS_DISTRO}-orbbec-camera-msgs_*.deb" \ + -print + ) + if [[ "${#message_packages[@]}" -ne 1 ]]; then + echo "Expected one orbbec_camera_msgs Debian package, found ${#message_packages[@]}" >&2 + exit 1 + fi + + apt-get install --yes "${message_packages[0]}" + + - name: Build camera package + shell: bash + run: | + set -euo pipefail + set +u + source "/opt/ros/${ROS_DISTRO}/setup.bash" + set -u + + ( + cd orbbec_camera + bash .make_deb.sh + ) + + - name: Validate and install generated packages + shell: bash + env: + EXPECTED_ARCHITECTURE: ${{ matrix.arch }} + run: | + set -euo pipefail + + mapfile -t camera_packages < <( + find . -maxdepth 1 -type f \ + -name "ros-${ROS_DISTRO}-orbbec-camera_*.deb" \ + -print + ) + if [[ "${#camera_packages[@]}" -ne 1 ]]; then + echo "Expected one orbbec_camera Debian package, found ${#camera_packages[@]}" >&2 + exit 1 + fi + + actual_architecture=$(dpkg --print-architecture) + if [[ "${actual_architecture}" != "${EXPECTED_ARCHITECTURE}" ]]; then + echo "Runner architecture ${actual_architecture} does not match ${EXPECTED_ARCHITECTURE}" >&2 + exit 1 + fi + + for package in ./*.deb ./*.ddeb; do + [[ -e "${package}" ]] || continue + package_architecture=$(dpkg-deb --field "${package}" Architecture) + if [[ "${package_architecture}" != "${EXPECTED_ARCHITECTURE}" && + "${package_architecture}" != "all" ]]; then + echo "Package ${package} has unexpected architecture ${package_architecture}" >&2 + exit 1 + fi + done + + apt-get install --yes "${camera_packages[0]}" + + - name: Collect packages + shell: bash + run: | + set -euo pipefail + mkdir -p artifacts + find . -maxdepth 1 -type f \ + \( -name '*.deb' -o -name '*.ddeb' \) \ + -exec cp --target-directory artifacts {} + + + - name: Upload Debian packages + uses: actions/upload-artifact@v7 + with: + name: orbbec-ros2-debs-${{ matrix.ros }}-${{ matrix.arch }} + path: artifacts/ + if-no-files-found: error + retention-days: 14 + compression-level: 0 diff --git a/README.MD b/README.MD index 246d1109..2e9c865e 100644 --- a/README.MD +++ b/README.MD @@ -12,15 +12,25 @@ + + ROS Foxy + ROS Humble ROS Jazzy + + ROS Lyrical + + + ROS Rolling (experimental) + Ubuntu 20.04 Ubuntu 22.04 Ubuntu 24.04 + Ubuntu 26.04
@@ -37,8 +47,7 @@ ## Introduction -The **OrbbecSDK ROS2 Wrapper** provides seamless integration of Orbbec cameras with the ROS 2 ecosystem. - It supports ROS2 **Humble**, **Jazzy**, and **Lyrical** distributions. +The **OrbbecSDK ROS2 Wrapper** provides seamless integration of Orbbec cameras with the ROS 2 ecosystem and supports the **ROS2 Foxy**, **Humble**, **Jazzy**, and **Lyrical** distributions, with experimental support for **Rolling**. - Default branch: **v2-main** - For legacy **OpenNI** devices: use the **main** branch diff --git a/README_CN.MD b/README_CN.MD index c2d661d9..04827a1f 100644 --- a/README_CN.MD +++ b/README_CN.MD @@ -12,15 +12,25 @@ + + ROS Foxy + ROS Humble ROS Jazzy + + ROS Lyrical + + + ROS Rolling (experimental) + Ubuntu 20.04 Ubuntu 22.04 Ubuntu 24.04 + Ubuntu 26.04
@@ -37,7 +47,7 @@ ## 简介 -OrbbecSDK ROS2 Wrapper 提供 Orbbec 相机与 ROS 2 环境的无缝集成,支持 **ROS2 Humble 和 Jazzy** 发行版。 +OrbbecSDK ROS2 Wrapper 提供 Orbbec 相机与 ROS 2 环境的无缝集成,支持 **ROS2 Foxy、Humble、Jazzy 和 Lyrical** 发行版,并提供对 **Rolling** 的实验性支持。 - 默认推荐使用 **v2-main** 分支。 - 对于旧的 **OpenNI** 设备(v2-main 不支持),请使用 **main** 分支。 diff --git a/orbbec_camera/.make_deb.sh b/orbbec_camera/.make_deb.sh index 1261a2b7..d84db41a 100644 --- a/orbbec_camera/.make_deb.sh +++ b/orbbec_camera/.make_deb.sh @@ -11,11 +11,14 @@ sed -i '/^override_dh_shlibdeps:/,/^$/d' debian/rules cat >> debian/rules << 'EOF' +ORBBEC_PACKAGE := ros-$(ROS_DISTRO)-orbbec-camera +ORBBEC_LIB_DIR := $(CURDIR)/debian/$(ORBBEC_PACKAGE)/opt/ros/$(ROS_DISTRO)/lib + override_dh_shlibdeps: - dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info + dh_shlibdeps -Xlibengine_infer_encry.so -l$(ORBBEC_LIB_DIR) -- --ignore-missing-info EOF PARALLEL=$(nproc) if [ "$PARALLEL" -gt 3 ]; then PARALLEL=3; fi export DEB_BUILD_OPTIONS="parallel=$PARALLEL" -fakeroot debian/rules binary \ No newline at end of file +fakeroot debian/rules binary diff --git a/orbbec_camera/CMakeLists.txt b/orbbec_camera/CMakeLists.txt index de2119b6..555112fe 100644 --- a/orbbec_camera/CMakeLists.txt +++ b/orbbec_camera/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.22) +cmake_minimum_required(VERSION 3.10) project(orbbec_camera) set(CMAKE_CXX_STANDARD 17) @@ -26,13 +26,16 @@ set(dependencies cv_bridge backward_ros camera_info_manager + geometry_msgs image_transport image_publisher message_filters OpenCV orbbec_camera_msgs + rcl_interfaces rclcpp rclcpp_components + rmw sensor_msgs std_msgs std_srvs @@ -55,18 +58,49 @@ endforeach() find_package(PkgConfig REQUIRED) find_package(OpenSSL REQUIRED) -if(message_filters_VERSION VERSION_GREATER_EQUAL 5.0) - add_compile_definitions(message_filters_QoS) +set(ORBBEC_MESSAGE_FILTERS_USES_RCLCPP_QOS OFF) +if(DEFINED message_filters_VERSION AND message_filters_VERSION VERSION_GREATER_EQUAL 5.0) + set(ORBBEC_MESSAGE_FILTERS_USES_RCLCPP_QOS ON) endif() -if(image_transport_VERSION VERSION_GREATER_EQUAL 6.4) - add_compile_definitions(image_transport_NODE_INTERFACE) +set(ORBBEC_IMAGE_TRANSPORT_USES_REQUIRED_INTERFACES OFF) +if(DEFINED image_transport_VERSION AND image_transport_VERSION VERSION_GREATER_EQUAL 6.4) + set(ORBBEC_IMAGE_TRANSPORT_USES_REQUIRED_INTERFACES ON) endif() -if(image_transport_VERSION VERSION_GREATER_EQUAL 6.4) - add_compile_definitions(image_transport_QoS) +set(ORBBEC_CAMERA_INFO_MANAGER_USES_NODE_INTERFACES OFF) +if(DEFINED camera_info_manager_VERSION AND + camera_info_manager_VERSION VERSION_GREATER_EQUAL 4.1.0) + set(ORBBEC_CAMERA_INFO_MANAGER_USES_NODE_INTERFACES ON) endif() +set(ORBBEC_CAMERA_INFO_MANAGER_USES_RCLCPP_QOS OFF) +if(DEFINED camera_info_manager_VERSION AND + camera_info_manager_VERSION VERSION_GREATER_EQUAL 7.0.0) + set(ORBBEC_CAMERA_INFO_MANAGER_USES_RCLCPP_QOS ON) +endif() + +function(orbbec_target_dependencies target) + if(COMMAND ament_target_dependencies) + ament_target_dependencies(${target} ${ARGN}) + return() + endif() + + set(dependency_targets) + foreach(dependency IN LISTS ARGN) + if(dependency STREQUAL "rclcpp_components") + list(APPEND dependency_targets rclcpp_components::component) + elseif(dependency STREQUAL "sensor_msgs") + list(APPEND dependency_targets sensor_msgs::sensor_msgs_library) + elseif(TARGET "${dependency}::${dependency}") + list(APPEND dependency_targets "${dependency}::${dependency}") + else() + message(FATAL_ERROR "No CMake target exported by ${dependency}") + endif() + endforeach() + target_link_libraries(${target} ${dependency_targets}) +endfunction() + if(USE_RK_HW_DECODER) pkg_search_module(RK_MPP REQUIRED rockchip_mpp) if(NOT RK_MPP_FOUND) @@ -112,7 +146,7 @@ endif() set(COMMON_INCLUDE_DIRS $ $ - $ ${ORBBEC_INCLUDE_DIR} ${OpenCV_INCLUDED_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/tools + $ ${ORBBEC_INCLUDE_DIR} ${OpenCV_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/tools ) set(EXTRA_TARGETS @@ -182,29 +216,51 @@ endmacro() # Define library and nodes add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES}) +if(ORBBEC_MESSAGE_FILTERS_USES_RCLCPP_QOS) + target_compile_definitions(${PROJECT_NAME} PRIVATE ORBBEC_MESSAGE_FILTERS_USES_RCLCPP_QOS) +endif() +if(ORBBEC_IMAGE_TRANSPORT_USES_REQUIRED_INTERFACES) + target_compile_definitions(${PROJECT_NAME} PRIVATE ORBBEC_IMAGE_TRANSPORT_USES_REQUIRED_INTERFACES) +endif() +if(ORBBEC_CAMERA_INFO_MANAGER_USES_NODE_INTERFACES) + target_compile_definitions(${PROJECT_NAME} + PRIVATE ORBBEC_CAMERA_INFO_MANAGER_USES_NODE_INTERFACES) +endif() +if(ORBBEC_CAMERA_INFO_MANAGER_USES_RCLCPP_QOS) + target_compile_definitions(${PROJECT_NAME} + PRIVATE ORBBEC_CAMERA_INFO_MANAGER_USES_RCLCPP_QOS) +endif() target_include_directories(${PROJECT_NAME} PUBLIC ${COMMON_INCLUDE_DIRS} ${image_publisher_INCLUDE_DIRS}) target_link_directories(${PROJECT_NAME} PRIVATE ${ORBBEC_LIBS_DIR}) target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS} ${orbbec_camera_msgs_TARGETS} - ${sensor_msgs_TARGETS} ${std_srvs_TARGETS} ament_index_cpp::ament_index_cpp - camera_info_manager::camera_info_manager - cv_bridge::cv_bridge - diagnostic_updater::diagnostic_updater Eigen3::Eigen - image_transport::image_transport - message_filters::message_filters OpenSSL::Crypto OrbbecSDK + Threads::Threads + ${BACKWARD_LIBRARIES} rclcpp::rclcpp - rclcpp_components::component + rt tf2::tf2 tf2_ros::tf2_ros ${EXTRA_TARGETS} ) +orbbec_target_dependencies(${PROJECT_NAME} + camera_info_manager + cv_bridge + diagnostic_updater + geometry_msgs + image_transport + message_filters + rcl_interfaces + rclcpp_components + rmw + sensor_msgs +) rclcpp_components_register_node( ${PROJECT_NAME} PLUGIN "orbbec_camera::OBCameraNodeDriver" EXECUTABLE orbbec_camera_node @@ -221,6 +277,10 @@ add_orbbec_executable(ob_benchmark_node tools/ob_benchmark.cpp) add_orbbec_executable(435le_example_node examples/Gemini_435Le_example_node/camera_example_node.cpp) add_orbbec_executable(service_benchmark_node scripts/service_benchmark_node.cpp) add_orbbec_executable(image_sync_example_node examples/multi_camera_time_sync/image_sync_example_node.cpp) +orbbec_target_dependencies(topic_statistics_node statistics_msgs) +if(ORBBEC_MESSAGE_FILTERS_USES_RCLCPP_QOS) + target_compile_definitions(image_sync_example_node PRIVATE ORBBEC_MESSAGE_FILTERS_USES_RCLCPP_QOS) +endif() install( PROGRAMS @@ -233,11 +293,14 @@ add_library(frame_latency SHARED tools/frame_latency.cpp) target_include_directories(frame_latency PUBLIC ${COMMON_INCLUDE_DIRS}) target_link_libraries(frame_latency ${orbbec_camera_msgs_TARGETS} - ${sensor_msgs_TARGETS} ${tf2_msgs_TARGETS} - diagnostic_updater::diagnostic_updater rclcpp::rclcpp - rclcpp_components::component +) +orbbec_target_dependencies(frame_latency + diagnostic_updater + geometry_msgs + rclcpp_components + sensor_msgs ) rclcpp_components_register_node(frame_latency PLUGIN "orbbec_camera::FrameLatencyNode" EXECUTABLE frame_latency_node) @@ -247,16 +310,18 @@ target_include_directories(start_benchmark PUBLIC ${COMMON_INCLUDE_DIRS} ${image target_link_libraries(start_benchmark ${OpenCV_LIBS} ${orbbec_camera_msgs_TARGETS} - ${sensor_msgs_TARGETS} ${std_srvs_TARGETS} - camera_info_manager::camera_info_manager - diagnostic_updater::diagnostic_updater Eigen3::Eigen - image_transport::image_transport rclcpp::rclcpp - rclcpp_components::component tf2_ros::tf2_ros ) +orbbec_target_dependencies(start_benchmark + camera_info_manager + diagnostic_updater + image_transport + rclcpp_components + sensor_msgs +) rclcpp_components_register_node( start_benchmark PLUGIN "orbbec_camera::tools::StartBenchmark" EXECUTABLE start_benchmark_node @@ -268,20 +333,22 @@ target_link_directories(multi_save_rgbir PRIVATE ${ORBBEC_LIBS_DIR}) target_link_libraries(multi_save_rgbir ${OpenCV_LIBS} ${orbbec_camera_msgs_TARGETS} - ${sensor_msgs_TARGETS} ${std_srvs_TARGETS} - camera_info_manager::camera_info_manager - cv_bridge::cv_bridge - diagnostic_updater::diagnostic_updater Eigen3::Eigen - image_transport::image_transport OpenSSL::Crypto OrbbecSDK rclcpp::rclcpp - rclcpp_components::component tf2::tf2 tf2_ros::tf2_ros ) +orbbec_target_dependencies(multi_save_rgbir + camera_info_manager + cv_bridge + diagnostic_updater + image_transport + rclcpp_components + sensor_msgs +) rclcpp_components_register_node( multi_save_rgbir PLUGIN "orbbec_camera::tools::MultiCameraSubscriber" EXECUTABLE multi_save_rgbir_node diff --git a/orbbec_camera/examples/Gemini_435Le_example_node/camera_example_node.cpp b/orbbec_camera/examples/Gemini_435Le_example_node/camera_example_node.cpp index 0a99ad6d..0986ae40 100644 --- a/orbbec_camera/examples/Gemini_435Le_example_node/camera_example_node.cpp +++ b/orbbec_camera/examples/Gemini_435Le_example_node/camera_example_node.cpp @@ -139,9 +139,9 @@ class CameraExampleNode : public rclcpp::Node { "/camera/device_status", 10, std::bind(&CameraExampleNode::deviceStatusCallback, this, std::placeholders::_1)); - while (rclcpp::ok()) { - rclcpp::spin_some(shared_from_this()); - } + rclcpp::executors::SingleThreadedExecutor executor; + executor.add_node(shared_from_this()); + executor.spin(); } // Feature 7: Set Color AE ROI diff --git a/orbbec_camera/examples/multi_camera_time_sync/image_sync_example_node.cpp b/orbbec_camera/examples/multi_camera_time_sync/image_sync_example_node.cpp index aa8e838c..48791ba7 100755 --- a/orbbec_camera/examples/multi_camera_time_sync/image_sync_example_node.cpp +++ b/orbbec_camera/examples/multi_camera_time_sync/image_sync_example_node.cpp @@ -1,8 +1,17 @@ +#include +#include + +#if __has_include() #include #include #include -#include -#include +#elif __has_include() +#include +#include +#include +#else +#error "No compatible message_filters headers found" +#endif #if __has_include() #include @@ -79,7 +88,7 @@ class ImageSyncNode : public rclcpp::Node { rclcpp::QoS qos{rclcpp::KeepLast(queue_size_)}; qos.reliable(); -#ifdef message_filters_QoS +#ifdef ORBBEC_MESSAGE_FILTERS_USES_RCLCPP_QOS const rclcpp::QoS qos_prof = qos; #else const rmw_qos_profile_t qos_prof = qos.get_rmw_qos_profile(); diff --git a/orbbec_camera/include/orbbec_camera/d2c_viewer.h b/orbbec_camera/include/orbbec_camera/d2c_viewer.h index 1bb366a2..1c9f31d6 100644 --- a/orbbec_camera/include/orbbec_camera/d2c_viewer.h +++ b/orbbec_camera/include/orbbec_camera/d2c_viewer.h @@ -14,12 +14,20 @@ * limitations under the License. *******************************************************************************/ #pragma once +#include +#include + +#if __has_include() #include #include #include -#include -#include -#include +#elif __has_include() +#include +#include +#include +#else +#error "No compatible message_filters headers found" +#endif #include "utils.h" diff --git a/orbbec_camera/include/orbbec_camera/ob_camera_node.h b/orbbec_camera/include/orbbec_camera/ob_camera_node.h index 5562c6f6..f21ad31c 100644 --- a/orbbec_camera/include/orbbec_camera/ob_camera_node.h +++ b/orbbec_camera/include/orbbec_camera/ob_camera_node.h @@ -31,11 +31,6 @@ #include #include #include -#include -#include -#include -#include -#include #include #include #include @@ -81,6 +76,26 @@ #include #include +#if __has_include() +#include +#include +#elif __has_include() +#include +#include +#else +#error "No compatible tf2 LinearMath headers found" +#endif + +#if __has_include() +#include +#include +#elif __has_include() +#include +#include +#else +#error "No compatible tf2_ros broadcaster headers found" +#endif + #if __has_include() #include #elif __has_include() diff --git a/orbbec_camera/include/orbbec_camera/ob_lidar_node.h b/orbbec_camera/include/orbbec_camera/ob_lidar_node.h index 9f870638..a843ae79 100644 --- a/orbbec_camera/include/orbbec_camera/ob_lidar_node.h +++ b/orbbec_camera/include/orbbec_camera/ob_lidar_node.h @@ -31,11 +31,6 @@ #include #include #include -#include -#include -#include -#include -#include #include #include #include @@ -66,6 +61,26 @@ #include #include +#if __has_include() +#include +#include +#elif __has_include() +#include +#include +#else +#error "No compatible tf2 LinearMath headers found" +#endif + +#if __has_include() +#include +#include +#elif __has_include() +#include +#include +#else +#error "No compatible tf2_ros broadcaster headers found" +#endif + #if __has_include() #include #elif __has_include() diff --git a/orbbec_camera/include/orbbec_camera/utils.h b/orbbec_camera/include/orbbec_camera/utils.h index 84f94f41..1f6e6c89 100644 --- a/orbbec_camera/include/orbbec_camera/utils.h +++ b/orbbec_camera/include/orbbec_camera/utils.h @@ -17,13 +17,19 @@ #pragma once #include #include -#include #include #include "libobsensor/ObSensor.hpp" #include "sensor_msgs/distortion_models.hpp" #include "sensor_msgs/msg/camera_info.hpp" #include "orbbec_camera_msgs/msg/extrinsics.hpp" +#if __has_include() +#include +#elif __has_include() +#include +#else +#error "No compatible tf2 Quaternion header found" +#endif #include #include #include diff --git a/orbbec_camera/package.xml b/orbbec_camera/package.xml index 8cf3d733..790cf788 100644 --- a/orbbec_camera/package.xml +++ b/orbbec_camera/package.xml @@ -8,6 +8,8 @@ Apache-2.0 ament_cmake + pkg-config + ament_lint_auto ament_lint_common ament_index_cpp @@ -18,7 +20,7 @@ rclcpp_components cv_bridge camera_info_manager - orbbec_camera_msgs + orbbec_camera_msgs builtin_interfaces rclcpp sensor_msgs @@ -37,6 +39,21 @@ libssl-dev opengl + eigen + geometry_msgs + libopencv-dev + rcl_interfaces + rmw + yaml-cpp + + ament_index_python + launch + launch_ros + python3-psutil + python3-tabulate + python3-yaml + rclpy + ament_cmake diff --git a/orbbec_camera/src/d2c_viewer.cpp b/orbbec_camera/src/d2c_viewer.cpp index 0637f3f5..b6a4f166 100644 --- a/orbbec_camera/src/d2c_viewer.cpp +++ b/orbbec_camera/src/d2c_viewer.cpp @@ -31,7 +31,7 @@ D2CViewer::D2CViewer(rclcpp::Node* const node, rmw_qos_profile_t rgb_qos, : node_(node), logger_(rclcpp::get_logger("d2c_viewer")), is_active_(true) { rgb_sub_ = std::make_shared>( node_, "color/image_raw", -#ifdef message_filters_QoS +#ifdef ORBBEC_MESSAGE_FILTERS_USES_RCLCPP_QOS rclcpp::QoS{rclcpp::QoSInitialization::from_rmw(rgb_qos), rgb_qos} #else rgb_qos @@ -39,7 +39,7 @@ D2CViewer::D2CViewer(rclcpp::Node* const node, rmw_qos_profile_t rgb_qos, ); depth_sub_ = std::make_shared>( node_, "depth/image_raw", -#ifdef message_filters_QoS +#ifdef ORBBEC_MESSAGE_FILTERS_USES_RCLCPP_QOS rclcpp::QoS{rclcpp::QoSInitialization::from_rmw(depth_qos), depth_qos} #else depth_qos diff --git a/orbbec_camera/src/image_publisher.cpp b/orbbec_camera/src/image_publisher.cpp index 7283cb8d..0998fedb 100644 --- a/orbbec_camera/src/image_publisher.cpp +++ b/orbbec_camera/src/image_publisher.cpp @@ -35,20 +35,20 @@ size_t image_rcl_publisher::get_subscription_count() const { image_transport_publisher::image_transport_publisher(rclcpp::Node& node, const std::string& topic_name, const rmw_qos_profile_t& qos) { - image_publisher_impl = std::make_shared( - image_transport::create_publisher( -#ifdef image_transport_NODE_INTERFACE + image_publisher_impl = + std::make_shared(image_transport::create_publisher( +#ifdef ORBBEC_IMAGE_TRANSPORT_USES_REQUIRED_INTERFACES image_transport::RequiredInterfaces{node}, #else &node, #endif topic_name, -#ifdef image_transport_QoS +#ifdef ORBBEC_IMAGE_TRANSPORT_USES_REQUIRED_INTERFACES rclcpp::QoS{rclcpp::QoSInitialization::from_rmw(qos), qos} #else qos #endif - )); + )); } void image_transport_publisher::publish(sensor_msgs::msg::Image::UniquePtr image_ptr) { image_publisher_impl->publish(*image_ptr); @@ -57,4 +57,4 @@ void image_transport_publisher::publish(sensor_msgs::msg::Image::UniquePtr image size_t image_transport_publisher::get_subscription_count() const { return image_publisher_impl->getNumSubscribers(); } -} // namespace orbbec_camera \ No newline at end of file +} // namespace orbbec_camera diff --git a/orbbec_camera/src/ob_camera_node.cpp b/orbbec_camera/src/ob_camera_node.cpp index 0f9ca2a4..2db3c2a4 100755 --- a/orbbec_camera/src/ob_camera_node.cpp +++ b/orbbec_camera/src/ob_camera_node.cpp @@ -5311,15 +5311,32 @@ void OBCameraNode::publishConfidenceFrame(const std::shared_ptr &conf } void OBCameraNode::setupCameraInfo() { - std::string color_camera_name = camera_name_ + "_color"; + const auto create_camera_info_manager = [this](const std::string &camera_name, + const std::string &camera_info_url) { +#ifdef ORBBEC_CAMERA_INFO_MANAGER_USES_NODE_INTERFACES +#ifdef ORBBEC_CAMERA_INFO_MANAGER_USES_RCLCPP_QOS + return std::make_unique( + node_->get_node_base_interface(), node_->get_node_services_interface(), + node_->get_node_logging_interface(), camera_name, camera_info_url, + rclcpp::SystemDefaultsQoS()); +#else + return std::make_unique( + node_->get_node_base_interface(), node_->get_node_services_interface(), + node_->get_node_logging_interface(), camera_name, camera_info_url, rmw_qos_profile_default); +#endif +#else + return std::make_unique(node_, camera_name, + camera_info_url); +#endif + }; + + const std::string color_camera_name = camera_name_ + "_color"; if (!color_info_url_.empty()) { - color_info_manager_ = std::make_unique( - node_, color_camera_name, color_info_url_); + color_info_manager_ = create_camera_info_manager(color_camera_name, color_info_url_); } - std::string ir_camera_name = camera_name_ + "_ir"; + const std::string ir_camera_name = camera_name_ + "_ir"; if (!ir_info_url_.empty()) { - ir_info_manager_ = std::make_unique( - node_, ir_camera_name, ir_info_url_); + ir_info_manager_ = create_camera_info_manager(ir_camera_name, ir_info_url_); } } @@ -7287,8 +7304,8 @@ void OBCameraNode::publishStaticTransforms() { if (!publish_tf_) { return; } - static_tf_broadcaster_ = std::make_shared(node_); - dynamic_tf_broadcaster_ = std::make_shared(node_); + static_tf_broadcaster_ = std::make_shared(*node_); + dynamic_tf_broadcaster_ = std::make_shared(*node_); calcAndPublishStaticTransform(); if (tf_publish_rate_ > 0) { tf_thread_ = std::make_shared([this]() { publishDynamicTransforms(); }); diff --git a/orbbec_camera/src/ob_camera_node_driver.cpp b/orbbec_camera/src/ob_camera_node_driver.cpp index 98c6ef07..5634a3f3 100644 --- a/orbbec_camera/src/ob_camera_node_driver.cpp +++ b/orbbec_camera/src/ob_camera_node_driver.cpp @@ -19,8 +19,13 @@ #include #include #include -#include #include +#if __has_include() +#include +#define ORBBEC_AMENT_INDEX_USES_FILESYSTEM_PATHS +#else +#include +#endif #include #include #include @@ -39,6 +44,24 @@ std::string g_time_domain = "global"; // Assuming this is declared elsew namespace { constexpr auto kStreamStartDelayAfterReconnect = std::chrono::seconds(5); +std::filesystem::path getPackageSharePath(const std::string &package_name) { +#ifdef ORBBEC_AMENT_INDEX_USES_FILESYSTEM_PATHS + return ament_index_cpp::get_package_share_path(package_name); +#else + return ament_index_cpp::get_package_share_directory(package_name); +#endif +} + +std::filesystem::path getPackagePrefixPath(const std::string &package_name) { +#ifdef ORBBEC_AMENT_INDEX_USES_FILESYSTEM_PATHS + std::filesystem::path package_prefix; + ament_index_cpp::get_package_prefix(package_name, package_prefix); + return package_prefix; +#else + return ament_index_cpp::get_package_prefix(package_name); +#endif +} + std::string getLogDirectoryForCamera(const std::string &camera_name) { const char *log_dir_override = std::getenv("ORBBEC_LOG_DIR"); if (log_dir_override && log_dir_override[0] != '\0') { @@ -153,10 +176,10 @@ int rosLogSeverityFromString(const std::string_view &log_level) { OBCameraNodeDriver::OBCameraNodeDriver(const rclcpp::NodeOptions &node_options) : Node("orbbec_camera_node", "/", node_options), node_options_(node_options), - config_path_(ament_index_cpp::get_package_share_directory("orbbec_camera") + - "/config/OrbbecSDKConfig_v2.0.xml"), + config_path_( + (getPackageSharePath("orbbec_camera") / "config" / "OrbbecSDKConfig_v2.0.xml").string()), logger_(this->get_logger()), - extension_path_(ament_index_cpp::get_package_prefix("orbbec_camera") + "/lib/extensions") { + extension_path_((getPackagePrefixPath("orbbec_camera") / "lib" / "extensions").string()) { node_name_ = "orbbec_camera_node"; init(); } @@ -165,10 +188,10 @@ OBCameraNodeDriver::OBCameraNodeDriver(const std::string &node_name, const std:: const rclcpp::NodeOptions &node_options) : Node(node_name, ns, node_options), node_options_(node_options), - config_path_(ament_index_cpp::get_package_share_directory("orbbec_camera") + - "/config/OrbbecSDKConfig_v2.0.xml"), + config_path_( + (getPackageSharePath("orbbec_camera") / "config" / "OrbbecSDKConfig_v2.0.xml").string()), logger_(this->get_logger()), - extension_path_(ament_index_cpp::get_package_prefix("orbbec_camera") + "/lib/extensions") { + extension_path_((getPackagePrefixPath("orbbec_camera") / "lib" / "extensions").string()) { node_name_ = node_name; init(); } diff --git a/orbbec_camera/src/ob_lidar_node.cpp b/orbbec_camera/src/ob_lidar_node.cpp index 0f3d2baa..b21bc13e 100644 --- a/orbbec_camera/src/ob_lidar_node.cpp +++ b/orbbec_camera/src/ob_lidar_node.cpp @@ -1165,8 +1165,8 @@ void OBLidarNode::publishStaticTransforms() { if (!publish_tf_) { return; } - static_tf_broadcaster_ = std::make_shared(node_); - dynamic_tf_broadcaster_ = std::make_shared(node_); + static_tf_broadcaster_ = std::make_shared(*node_); + dynamic_tf_broadcaster_ = std::make_shared(*node_); calcAndPublishStaticTransform(); if (tf_publish_rate_ > 0) { tf_thread_ = std::make_shared([this]() { publishDynamicTransforms(); }); diff --git a/orbbec_camera/tools/multi_save_rgbir.cpp b/orbbec_camera/tools/multi_save_rgbir.cpp index 6496787a..69bbc290 100644 --- a/orbbec_camera/tools/multi_save_rgbir.cpp +++ b/orbbec_camera/tools/multi_save_rgbir.cpp @@ -5,9 +5,6 @@ #include #include "orbbec_camera/ob_camera_node.h" #include "orbbec_camera_msgs/msg/metadata.hpp" -#include -#include -#include #include #include #include @@ -410,4 +407,4 @@ class MultiCameraSubscriber : public rclcpp::Node { }; } // namespace tools } // namespace orbbec_camera -RCLCPP_COMPONENTS_REGISTER_NODE(orbbec_camera::tools::MultiCameraSubscriber) \ No newline at end of file +RCLCPP_COMPONENTS_REGISTER_NODE(orbbec_camera::tools::MultiCameraSubscriber) diff --git a/orbbec_camera/tools/ob_benchmark.cpp b/orbbec_camera/tools/ob_benchmark.cpp index 52022503..76a85081 100644 --- a/orbbec_camera/tools/ob_benchmark.cpp +++ b/orbbec_camera/tools/ob_benchmark.cpp @@ -3,9 +3,6 @@ #include #include #include "orbbec_camera_msgs/msg/metadata.hpp" -#include -#include -#include #include namespace orbbec_camera { diff --git a/orbbec_camera/tools/start_benchmark.cpp b/orbbec_camera/tools/start_benchmark.cpp index 9b474080..5987a554 100644 --- a/orbbec_camera/tools/start_benchmark.cpp +++ b/orbbec_camera/tools/start_benchmark.cpp @@ -3,9 +3,6 @@ #include #include #include "orbbec_camera_msgs/msg/metadata.hpp" -#include -#include -#include #include namespace orbbec_camera { diff --git a/orbbec_camera_msgs/CMakeLists.txt b/orbbec_camera_msgs/CMakeLists.txt index fd229bb6..b71437b9 100644 --- a/orbbec_camera_msgs/CMakeLists.txt +++ b/orbbec_camera_msgs/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.22) +cmake_minimum_required(VERSION 3.10) project(orbbec_camera_msgs) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") diff --git a/orbbec_description/CMakeLists.txt b/orbbec_description/CMakeLists.txt index 8310ce57..5cbf3d19 100644 --- a/orbbec_description/CMakeLists.txt +++ b/orbbec_description/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.22) +cmake_minimum_required(VERSION 3.10) project(orbbec_description) find_package(ament_cmake REQUIRED) diff --git a/orbbec_description/package.xml b/orbbec_description/package.xml index f79a7f55..10234781 100644 --- a/orbbec_description/package.xml +++ b/orbbec_description/package.xml @@ -9,6 +9,13 @@ ament_cmake + ament_index_python + launch + launch_ros + robot_state_publisher + rviz2 + xacro + ament_lint_auto ament_lint_common