2023-09-08 08:55:16 +08:00
|
|
|
/*******************************************************************************
|
2024-04-07 15:30:59 +08:00
|
|
|
* Copyright (c) 2023 Orbbec 3D Technology, Inc
|
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*******************************************************************************/
|
2022-06-06 19:00:12 +08:00
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
#include <ostream>
|
|
|
|
|
#include <Eigen/Dense>
|
|
|
|
|
#include <tf2/LinearMath/Quaternion.h>
|
2022-06-08 10:21:57 +08:00
|
|
|
#include <rclcpp/rclcpp.hpp>
|
2022-06-06 19:00:12 +08:00
|
|
|
|
2022-06-08 14:51:00 +08:00
|
|
|
#include "libobsensor/ObSensor.hpp"
|
2022-06-06 19:00:12 +08:00
|
|
|
#include "sensor_msgs/distortion_models.hpp"
|
|
|
|
|
#include "sensor_msgs/msg/camera_info.hpp"
|
2022-06-08 14:51:00 +08:00
|
|
|
#include "orbbec_camera_msgs/msg/extrinsics.hpp"
|
2023-02-06 17:26:10 +08:00
|
|
|
#include "magic_enum/magic_enum.hpp"
|
2023-09-07 16:09:35 +08:00
|
|
|
#include <sensor_msgs/msg/point_cloud2.hpp>
|
2024-07-31 14:30:54 +08:00
|
|
|
#include <opencv2/opencv.hpp>
|
2025-08-28 21:59:50 +08:00
|
|
|
#include <openssl/evp.h>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#include <iomanip>
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
|
2024-06-19 10:40:57 +08:00
|
|
|
namespace orbbec_camera {
|
2024-07-31 14:30:54 +08:00
|
|
|
inline void LogFatal(const char* file, int line, const std::string& message) {
|
2024-06-19 10:40:57 +08:00
|
|
|
std::cerr << "Check failed at " << file << ":" << line << ": " << message << std::endl;
|
|
|
|
|
std::abort();
|
|
|
|
|
}
|
2026-04-01 20:52:46 +08:00
|
|
|
|
|
|
|
|
inline const char* getObErrorMessage(const ob::Error& e) {
|
|
|
|
|
return e.getMessage() ? e.getMessage() : "Unknown OB error";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline std::string formatObErrorWithStatus(const ob::Error& e) {
|
|
|
|
|
std::ostringstream os;
|
|
|
|
|
os << getObErrorMessage(e) << " status:" << static_cast<int>(e.getStatus());
|
|
|
|
|
return os.str();
|
|
|
|
|
}
|
2024-06-19 10:40:57 +08:00
|
|
|
} // namespace orbbec_camera
|
|
|
|
|
|
2025-08-29 17:33:26 +08:00
|
|
|
#define TRY_EXECUTE_BLOCK(block) \
|
|
|
|
|
try { \
|
|
|
|
|
block; \
|
|
|
|
|
} catch (const ob::Error& e) { \
|
2026-04-01 20:52:46 +08:00
|
|
|
std::string error_msg = orbbec_camera::formatObErrorWithStatus(e); \
|
2025-08-29 17:33:26 +08:00
|
|
|
if (error_msg.find("Device is deactivated") != std::string::npos || \
|
|
|
|
|
error_msg.find("disconnected") != std::string::npos || \
|
|
|
|
|
error_msg.find("Send control transfer failed") != std::string::npos) { \
|
|
|
|
|
RCLCPP_WARN(logger_, \
|
|
|
|
|
"Device communication error in %s at line %d: %s - Device may be disconnected", \
|
|
|
|
|
__FUNCTION__, __LINE__, error_msg.c_str()); \
|
|
|
|
|
} else { \
|
|
|
|
|
RCLCPP_ERROR(logger_, "Error in %s at line %d: %s", __FUNCTION__, __LINE__, \
|
|
|
|
|
error_msg.c_str()); \
|
|
|
|
|
} \
|
|
|
|
|
} catch (const std::exception& e) { \
|
|
|
|
|
RCLCPP_ERROR(logger_, "Exception in %s at line %d: %s", __FUNCTION__, __LINE__, e.what()); \
|
|
|
|
|
} catch (...) { \
|
|
|
|
|
RCLCPP_ERROR(logger_, "Unknown exception in %s at line %d", __FUNCTION__, __LINE__); \
|
2024-09-10 20:23:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define TRY_TO_SET_PROPERTY(func, property, value) \
|
|
|
|
|
try { \
|
|
|
|
|
device_->func(property, value); \
|
|
|
|
|
} catch (const ob::Error& e) { \
|
|
|
|
|
RCLCPP_ERROR_STREAM(logger_, "Failed to set " << property << " to " << value << " in " \
|
|
|
|
|
<< __FUNCTION__ << " at line " << __LINE__ \
|
2026-04-01 20:52:46 +08:00
|
|
|
<< ": " << orbbec_camera::formatObErrorWithStatus(e)); \
|
2024-09-10 20:23:20 +08:00
|
|
|
} catch (const std::exception& e) { \
|
|
|
|
|
RCLCPP_ERROR_STREAM(logger_, "Failed to set " << property << " to " << value << " in " \
|
|
|
|
|
<< __FUNCTION__ << " at line " << __LINE__ \
|
|
|
|
|
<< ": " << e.what()); \
|
|
|
|
|
} catch (...) { \
|
|
|
|
|
RCLCPP_ERROR_STREAM(logger_, "Failed to set " << property << " to " << value << " in " \
|
|
|
|
|
<< __FUNCTION__ << " at line " << __LINE__); \
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 10:40:57 +08:00
|
|
|
// Macros for checking conditions and comparing values
|
|
|
|
|
#define CHECK(condition) \
|
|
|
|
|
(!(condition) ? LogFatal(__FILE__, __LINE__, "Check failed: " #condition) : (void)0)
|
|
|
|
|
|
|
|
|
|
template <typename T1, typename T2>
|
2024-07-31 14:30:54 +08:00
|
|
|
void CheckOp(const char* expr, const char* file, int line, T1 val1, T2 val2, bool result) {
|
2024-06-19 10:40:57 +08:00
|
|
|
if (!result) {
|
|
|
|
|
std::ostringstream os;
|
|
|
|
|
os << "Check failed: " << expr << " (" << val1 << " vs. " << val2 << ")";
|
|
|
|
|
orbbec_camera::LogFatal(file, line, os.str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define CHECK_OP(opname, op, val1, val2) \
|
|
|
|
|
CheckOp(#val1 " " #op " " #val2, __FILE__, __LINE__, val1, val2, (val1)op(val2))
|
|
|
|
|
|
|
|
|
|
#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==, val1, val2)
|
|
|
|
|
#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=, val1, val2)
|
|
|
|
|
#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=, val1, val2)
|
|
|
|
|
#define CHECK_LT(val1, val2) CHECK_OP(_LT, <, val1, val2)
|
|
|
|
|
#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=, val1, val2)
|
|
|
|
|
#define CHECK_GT(val1, val2) CHECK_OP(_GT, >, val1, val2)
|
|
|
|
|
|
|
|
|
|
// Overload for raw pointers
|
|
|
|
|
template <typename T>
|
2024-07-31 14:30:54 +08:00
|
|
|
T* CheckNotNull(T* ptr, const char* file, int line) {
|
2024-06-19 10:40:57 +08:00
|
|
|
if (ptr == nullptr) {
|
|
|
|
|
std::ostringstream os;
|
|
|
|
|
os << "Null pointer passed to CheckNotNull at " << file << ":" << line;
|
|
|
|
|
orbbec_camera::LogFatal(file, line, os.str());
|
|
|
|
|
}
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Template for smart pointers like std::shared_ptr, std::unique_ptr
|
|
|
|
|
template <typename T>
|
2024-07-31 14:30:54 +08:00
|
|
|
T& CheckNotNull(T& ptr, const char* file, int line) {
|
2024-06-19 10:40:57 +08:00
|
|
|
if (ptr == nullptr) {
|
|
|
|
|
std::ostringstream os;
|
|
|
|
|
os << "Null pointer passed to CheckNotNull at " << file << ":" << line;
|
|
|
|
|
orbbec_camera::LogFatal(file, line, os.str());
|
|
|
|
|
}
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(CHECK_NOTNULL)
|
|
|
|
|
#undef CHECK_NOTNULL
|
|
|
|
|
#endif
|
|
|
|
|
#define CHECK_NOTNULL(val) CheckNotNull(val, __FILE__, __LINE__)
|
|
|
|
|
|
2022-06-06 19:00:12 +08:00
|
|
|
namespace orbbec_camera {
|
|
|
|
|
sensor_msgs::msg::CameraInfo convertToCameraInfo(OBCameraIntrinsic intrinsic,
|
2022-12-28 16:39:11 +08:00
|
|
|
OBCameraDistortion distortion, int width);
|
2022-06-06 19:00:12 +08:00
|
|
|
|
2023-02-20 13:58:37 +08:00
|
|
|
void saveRGBPointsToPly(const std::shared_ptr<ob::Frame>& frame, const std::string& fileName);
|
2022-06-06 19:00:12 +08:00
|
|
|
|
2024-05-16 14:34:55 +08:00
|
|
|
void saveRGBPointCloudMsgToPly(const sensor_msgs::msg::PointCloud2::UniquePtr& msg,
|
2024-04-07 15:30:59 +08:00
|
|
|
const std::string& fileName);
|
2023-09-15 16:54:30 +08:00
|
|
|
|
2024-07-31 14:30:54 +08:00
|
|
|
void saveDepthPointsToPly(const sensor_msgs::msg::PointCloud2::UniquePtr& msg,
|
|
|
|
|
const std::string& fileName);
|
2023-09-07 16:09:35 +08:00
|
|
|
|
2023-02-20 13:58:37 +08:00
|
|
|
void savePointsToPly(const std::shared_ptr<ob::Frame>& frame, const std::string& fileName);
|
2022-06-06 19:00:12 +08:00
|
|
|
|
|
|
|
|
tf2::Quaternion rotationMatrixToQuaternion(const float rotation[9]);
|
|
|
|
|
|
|
|
|
|
std::ostream& operator<<(std::ostream& os, const OBCameraParam& rhs);
|
|
|
|
|
|
|
|
|
|
orbbec_camera_msgs::msg::Extrinsics obExtrinsicsToMsg(const OBD2CTransform& extrinsics,
|
|
|
|
|
const std::string& frame_id);
|
|
|
|
|
|
2024-03-15 10:24:38 +08:00
|
|
|
rclcpp::Time fromMsToROSTime(uint64_t ms);
|
|
|
|
|
|
|
|
|
|
rclcpp::Time fromUsToROSTime(uint64_t us);
|
2022-06-08 10:21:57 +08:00
|
|
|
|
2022-06-09 15:47:02 +08:00
|
|
|
std::string getObSDKVersion();
|
|
|
|
|
|
2022-06-24 14:08:31 +08:00
|
|
|
OBFormat OBFormatFromString(const std::string& format);
|
|
|
|
|
|
2025-06-09 21:24:06 +08:00
|
|
|
OBLiDARScanRate OBScanRateFromInt(const int rate);
|
|
|
|
|
|
2024-05-08 20:59:49 +08:00
|
|
|
std::string OBFormatToString(const OBFormat& format);
|
|
|
|
|
|
2024-07-31 14:30:54 +08:00
|
|
|
std::ostream& operator<<(std::ostream& os, const OBFormat& rhs);
|
2024-05-08 20:59:49 +08:00
|
|
|
|
2022-12-28 13:55:26 +08:00
|
|
|
std::string ObDeviceTypeToString(const OBDeviceType& type);
|
|
|
|
|
|
2023-02-06 17:26:10 +08:00
|
|
|
rmw_qos_profile_t getRMWQosProfileFromString(const std::string& str_qos);
|
|
|
|
|
|
2023-03-02 20:15:01 +08:00
|
|
|
bool isOpenNIDevice(int pid);
|
|
|
|
|
|
2023-03-20 11:18:59 +08:00
|
|
|
OB_DEPTH_PRECISION_LEVEL depthPrecisionLevelFromString(
|
|
|
|
|
const std::string& depth_precision_level_str);
|
|
|
|
|
|
2024-05-06 10:34:19 +08:00
|
|
|
float depthPrecisionFromString(const std::string& depth_precision_level_str);
|
2024-04-15 09:59:56 +08:00
|
|
|
|
2026-04-15 15:24:58 +08:00
|
|
|
std::string colorPowerLineFrequencyToString(int value);
|
|
|
|
|
|
|
|
|
|
std::string depthPrecisionLevelToString(int value);
|
|
|
|
|
|
2023-09-05 17:59:19 +08:00
|
|
|
OBMultiDeviceSyncMode OBSyncModeFromString(const std::string& mode);
|
2023-03-20 11:18:59 +08:00
|
|
|
|
2026-04-15 15:24:58 +08:00
|
|
|
std::string disparityRangeModeToString(int value);
|
|
|
|
|
|
|
|
|
|
std::string exposureRangeModeToString(int value);
|
|
|
|
|
|
|
|
|
|
std::string intraCameraSyncReferenceToString(int value);
|
|
|
|
|
|
2023-04-28 09:44:16 +08:00
|
|
|
OB_SAMPLE_RATE sampleRateFromString(std::string& sample_rate);
|
|
|
|
|
|
2023-09-07 16:09:35 +08:00
|
|
|
std::string sampleRateToString(const OB_SAMPLE_RATE& sample_rate);
|
2023-08-23 17:14:08 +08:00
|
|
|
|
2024-07-31 14:30:54 +08:00
|
|
|
std::ostream& operator<<(std::ostream& os, const OB_SAMPLE_RATE& rhs);
|
2024-05-08 20:59:49 +08:00
|
|
|
|
2023-04-28 09:44:16 +08:00
|
|
|
OB_GYRO_FULL_SCALE_RANGE fullGyroScaleRangeFromString(std::string& full_scale_range);
|
|
|
|
|
|
2023-09-07 16:09:35 +08:00
|
|
|
std::string fullGyroScaleRangeToString(const OB_GYRO_FULL_SCALE_RANGE& full_scale_range);
|
2023-08-23 17:14:08 +08:00
|
|
|
|
2024-07-31 14:30:54 +08:00
|
|
|
std::ostream& operator<<(std::ostream& os, const OB_GYRO_FULL_SCALE_RANGE& rhs);
|
2024-05-08 20:59:49 +08:00
|
|
|
|
2023-04-28 09:44:16 +08:00
|
|
|
OBAccelFullScaleRange fullAccelScaleRangeFromString(std::string& full_scale_range);
|
|
|
|
|
|
2023-09-07 16:09:35 +08:00
|
|
|
std::string fullAccelScaleRangeToString(const OBAccelFullScaleRange& full_scale_range);
|
2023-08-23 17:14:08 +08:00
|
|
|
|
2024-07-31 14:30:54 +08:00
|
|
|
std::ostream& operator<<(std::ostream& os, const OBAccelFullScaleRange& rhs);
|
2024-05-08 20:59:49 +08:00
|
|
|
|
2023-07-05 15:00:34 +08:00
|
|
|
std::string parseUsbPort(const std::string& line);
|
|
|
|
|
|
2023-09-07 20:55:25 +08:00
|
|
|
bool isValidJPEG(const std::shared_ptr<ob::ColorFrame>& frame);
|
|
|
|
|
|
2024-04-07 15:30:59 +08:00
|
|
|
std::string metaDataTypeToString(const OBFrameMetadataType& meta_data_type);
|
|
|
|
|
|
2024-07-31 14:30:54 +08:00
|
|
|
std::ostream& operator<<(std::ostream& os, const OBFrameMetadataType& rhs);
|
2024-05-08 20:59:49 +08:00
|
|
|
|
2024-04-07 15:30:59 +08:00
|
|
|
OBHoleFillingMode holeFillingModeFromString(const std::string& hole_filling_mode);
|
2024-03-15 10:24:38 +08:00
|
|
|
|
2024-04-15 09:59:56 +08:00
|
|
|
bool isGemini2R(int pid);
|
|
|
|
|
|
2024-05-06 10:34:19 +08:00
|
|
|
OBStreamType obStreamTypeFromString(const std::string& stream_type);
|
|
|
|
|
|
2025-12-29 09:46:48 +08:00
|
|
|
struct UndistortedImageResult {
|
|
|
|
|
cv::Mat image;
|
|
|
|
|
OBCameraIntrinsic new_intrinsic;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
UndistortedImageResult undistortImage(const cv::Mat& image, const OBCameraIntrinsic& intrinsic,
|
|
|
|
|
const OBCameraDistortion& distortion);
|
2024-07-31 14:30:54 +08:00
|
|
|
|
2025-03-31 13:40:28 +08:00
|
|
|
std::string getDistortionModels(OBCameraDistortion distortion);
|
2025-08-28 21:59:50 +08:00
|
|
|
|
2025-08-29 17:33:26 +08:00
|
|
|
std::string calcMD5(const std::string& data);
|
2025-07-08 15:01:28 +08:00
|
|
|
double getScanAngleIncrement(OBLiDARScanRate fps);
|
|
|
|
|
|
2025-06-09 21:24:06 +08:00
|
|
|
double deg2rad(double deg);
|
|
|
|
|
|
|
|
|
|
double rad2deg(double rad);
|
2022-06-06 19:00:12 +08:00
|
|
|
} // namespace orbbec_camera
|