From d9fca90bcc629ca0bf577041240c591df85840b4 Mon Sep 17 00:00:00 2001 From: slz Date: Thu, 3 Sep 2026 11:36:53 +0800 Subject: [PATCH] fix: publish matching camera distortion models --- orbbec_camera/CMakeLists.txt | 4 + orbbec_camera/package.xml | 2 + orbbec_camera/src/utils.cpp | 19 +++-- .../test/camera_info_distortion_test.cpp | 73 +++++++++++++++++++ 4 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 orbbec_camera/test/camera_info_distortion_test.cpp diff --git a/orbbec_camera/CMakeLists.txt b/orbbec_camera/CMakeLists.txt index 3d64408e..869bfa03 100644 --- a/orbbec_camera/CMakeLists.txt +++ b/orbbec_camera/CMakeLists.txt @@ -391,7 +391,11 @@ install(TARGETS list_devices_node list_depth_work_mode_node list_camera_profile_ if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) + find_package(ament_cmake_gtest REQUIRED) ament_lint_auto_find_test_dependencies() + + ament_add_gtest(camera_info_distortion_test test/camera_info_distortion_test.cpp) + target_link_libraries(camera_info_distortion_test ${PROJECT_NAME}) endif() ament_export_include_directories(include) diff --git a/orbbec_camera/package.xml b/orbbec_camera/package.xml index 90cce657..c745be29 100644 --- a/orbbec_camera/package.xml +++ b/orbbec_camera/package.xml @@ -55,6 +55,8 @@ python3-yaml rclpy + ament_cmake_gtest + ament_cmake diff --git a/orbbec_camera/src/utils.cpp b/orbbec_camera/src/utils.cpp index 3cb41255..17371bbe 100644 --- a/orbbec_camera/src/utils.cpp +++ b/orbbec_camera/src/utils.cpp @@ -95,15 +95,14 @@ sensor_msgs::msg::CameraInfo convertToCameraInfo(OBCameraIntrinsic intrinsic, info.distortion_model = getDistortionModels(distortion); info.width = intrinsic.width; info.height = intrinsic.height; - info.d.resize(8, 0.0); - info.d[0] = distortion.k1; - info.d[1] = distortion.k2; - info.d[2] = distortion.p1; - info.d[3] = distortion.p2; - info.d[4] = distortion.k3; - info.d[5] = distortion.k4; - info.d[6] = distortion.k5; - info.d[7] = distortion.k6; + if (info.distortion_model == sensor_msgs::distortion_models::RATIONAL_POLYNOMIAL) { + info.d = {distortion.k1, distortion.k2, distortion.p1, distortion.p2, + distortion.k3, distortion.k4, distortion.k5, distortion.k6}; + } else if (info.distortion_model == sensor_msgs::distortion_models::EQUIDISTANT) { + info.d = {distortion.k1, distortion.k2, distortion.k3, distortion.k4}; + } else { + info.d = {distortion.k1, distortion.k2, distortion.p1, distortion.p2, distortion.k3}; + } bool all_zero = std::all_of(info.d.begin(), info.d.end(), [](double val) { return val == 0.0; }); info.roi.do_rectify = all_zero; @@ -1174,7 +1173,7 @@ std::string getDistortionModels(OBCameraDistortion distortion) { case OB_DISTORTION_BROWN_CONRADY: return sensor_msgs::distortion_models::PLUMB_BOB; case OB_DISTORTION_BROWN_CONRADY_K6: - return sensor_msgs::distortion_models::PLUMB_BOB; + return sensor_msgs::distortion_models::RATIONAL_POLYNOMIAL; case OB_DISTORTION_KANNALA_BRANDT4: return sensor_msgs::distortion_models::EQUIDISTANT; default: diff --git a/orbbec_camera/test/camera_info_distortion_test.cpp b/orbbec_camera/test/camera_info_distortion_test.cpp new file mode 100644 index 00000000..5c303284 --- /dev/null +++ b/orbbec_camera/test/camera_info_distortion_test.cpp @@ -0,0 +1,73 @@ +#include + +#include + +#include "orbbec_camera/utils.h" + +namespace orbbec_camera { +namespace { + +OBCameraIntrinsic makeIntrinsic() { + OBCameraIntrinsic intrinsic{}; + intrinsic.width = 1280; + intrinsic.height = 800; + intrinsic.fx = 600.0F; + intrinsic.fy = 601.0F; + intrinsic.cx = 640.0F; + intrinsic.cy = 400.0F; + return intrinsic; +} + +OBCameraDistortion makeDistortion(OBCameraDistortionModel model) { + OBCameraDistortion distortion{}; + distortion.k1 = 0.1F; + distortion.k2 = 0.2F; + distortion.k3 = 0.3F; + distortion.k4 = 0.4F; + distortion.k5 = 0.5F; + distortion.k6 = 0.6F; + distortion.p1 = 0.01F; + distortion.p2 = 0.02F; + distortion.model = model; + return distortion; +} + +TEST(CameraInfoDistortionTest, ConvertsBrownConradyToPlumbBob) { + const auto intrinsic = makeIntrinsic(); + const auto distortion = makeDistortion(OB_DISTORTION_BROWN_CONRADY); + + const auto info = convertToCameraInfo(intrinsic, distortion, intrinsic.width); + + EXPECT_EQ(info.distortion_model, sensor_msgs::distortion_models::PLUMB_BOB); + EXPECT_EQ(info.d, std::vector({distortion.k1, distortion.k2, distortion.p1, distortion.p2, + distortion.k3})); +} + +TEST(CameraInfoDistortionTest, KeepsK6ModelWhenHigherOrderCoefficientsAreZero) { + const auto intrinsic = makeIntrinsic(); + auto distortion = makeDistortion(OB_DISTORTION_BROWN_CONRADY_K6); + distortion.k4 = 0.0F; + distortion.k5 = 0.0F; + distortion.k6 = 0.0F; + + const auto info = convertToCameraInfo(intrinsic, distortion, intrinsic.width); + + EXPECT_EQ(info.distortion_model, sensor_msgs::distortion_models::RATIONAL_POLYNOMIAL); + EXPECT_EQ(info.d, + std::vector({distortion.k1, distortion.k2, distortion.p1, distortion.p2, + distortion.k3, distortion.k4, distortion.k5, distortion.k6})); +} + +TEST(CameraInfoDistortionTest, ConvertsKannalaBrandtToEquidistant) { + const auto intrinsic = makeIntrinsic(); + const auto distortion = makeDistortion(OB_DISTORTION_KANNALA_BRANDT4); + + const auto info = convertToCameraInfo(intrinsic, distortion, intrinsic.width); + + EXPECT_EQ(info.distortion_model, sensor_msgs::distortion_models::EQUIDISTANT); + EXPECT_EQ(info.d, + std::vector({distortion.k1, distortion.k2, distortion.k3, distortion.k4})); +} + +} // namespace +} // namespace orbbec_camera