Fix crash and change parameter order in gemini435_le launch file by repositioning time_sync_period argument

This commit is contained in:
xiexun
2025-09-02 17:09:25 +08:00
parent 757ed3c4af
commit e7c4a4acef
6 changed files with 296 additions and 99 deletions
@@ -193,13 +193,6 @@ class OBCameraNode {
void getDepthStatus(orbbec_camera_msgs::msg::DeviceStatus& status_msg) { void getDepthStatus(orbbec_camera_msgs::msg::DeviceStatus& status_msg) {
fps_delay_status_depth_->fillDepthStatus(status_msg); fps_delay_status_depth_->fillDepthStatus(status_msg);
status_msg.header.frame_id = camera_link_frame_id_;
}
void publishDeviceStatus(const orbbec_camera_msgs::msg::DeviceStatus& msg) {
if (device_status_pub_) {
device_status_pub_->publish(msg);
}
} }
bool checkUserCalibrationReady() { bool checkUserCalibrationReady() {
@@ -245,8 +238,6 @@ class OBCameraNode {
void setupDiagnosticUpdater(); void setupDiagnosticUpdater();
void setupPeriodicHostTimeSync();
void onTemperatureUpdate(diagnostic_updater::DiagnosticStatusWrapper& status); void onTemperatureUpdate(diagnostic_updater::DiagnosticStatusWrapper& status);
void setupCameraCtrlServices(); void setupCameraCtrlServices();
@@ -776,9 +767,7 @@ class OBCameraNode {
// soft ware trigger // soft ware trigger
rclcpp::TimerBase::SharedPtr software_trigger_timer_; rclcpp::TimerBase::SharedPtr software_trigger_timer_;
rclcpp::TimerBase::SharedPtr diagnostic_timer_; rclcpp::TimerBase::SharedPtr diagnostic_timer_;
rclcpp::TimerBase::SharedPtr sync_timer_;
std::chrono::milliseconds software_trigger_period_{33}; std::chrono::milliseconds software_trigger_period_{33};
std::chrono::milliseconds time_sync_period_{6000};
bool enable_heartbeat_ = false; bool enable_heartbeat_ = false;
bool enable_color_undistortion_ = false; bool enable_color_undistortion_ = false;
std::shared_ptr<image_publisher> color_undistortion_publisher_; std::shared_ptr<image_publisher> color_undistortion_publisher_;
@@ -835,6 +824,5 @@ class OBCameraNode {
std::unique_ptr<FpsDelayStatus> fps_delay_status_color_{nullptr}; std::unique_ptr<FpsDelayStatus> fps_delay_status_color_{nullptr};
std::unique_ptr<FpsDelayStatus> fps_delay_status_depth_{nullptr}; std::unique_ptr<FpsDelayStatus> fps_delay_status_depth_{nullptr};
rclcpp::Publisher<orbbec_camera_msgs::msg::DeviceStatus>::SharedPtr device_status_pub_;
}; };
} // namespace orbbec_camera } // namespace orbbec_camera
@@ -22,6 +22,7 @@
#include "ob_camera_node.h" #include "ob_camera_node.h"
#include "utils.h" #include "utils.h"
#include "dynamic_params.h" #include "dynamic_params.h"
#include <orbbec_camera_msgs/msg/device_status.hpp>
#include "libobsensor/ObSensor.hpp" #include "libobsensor/ObSensor.hpp"
#include <pthread.h> #include <pthread.h>
@@ -116,6 +117,7 @@ class OBCameraNodeDriver : public rclcpp::Node {
int net_device_port_ = 0; int net_device_port_ = 0;
int connection_delay_ = 100; int connection_delay_ = 100;
bool enable_sync_host_time_ = true; bool enable_sync_host_time_ = true;
std::chrono::milliseconds time_sync_period_{6000};
std::string preset_firmware_path_; std::string preset_firmware_path_;
rclcpp::Service<std_srvs::srv::Empty>::SharedPtr reboot_device_srv_ = nullptr; rclcpp::Service<std_srvs::srv::Empty>::SharedPtr reboot_device_srv_ = nullptr;
std::chrono::time_point<std::chrono::system_clock> start_time_; std::chrono::time_point<std::chrono::system_clock> start_time_;
@@ -125,5 +127,7 @@ class OBCameraNodeDriver : public rclcpp::Node {
std::atomic<bool> firmware_update_success_{false}; std::atomic<bool> firmware_update_success_{false};
rclcpp::TimerBase::SharedPtr device_status_timer_ = nullptr; rclcpp::TimerBase::SharedPtr device_status_timer_ = nullptr;
int device_status_interval_hz = 2; // 2Hz int device_status_interval_hz = 2; // 2Hz
rclcpp::Publisher<orbbec_camera_msgs::msg::DeviceStatus>::SharedPtr device_status_pub_ = nullptr;
std::string node_name_;
}; };
} // namespace orbbec_camera } // namespace orbbec_camera
+20 -11
View File
@@ -32,7 +32,6 @@
#include <iomanip> #include <iomanip>
#include <arpa/inet.h> #include <arpa/inet.h>
namespace orbbec_camera { namespace orbbec_camera {
inline void LogFatal(const char* file, int line, const std::string& message) { inline void LogFatal(const char* file, int line, const std::string& message) {
std::cerr << "Check failed at " << file << ":" << line << ": " << message << std::endl; std::cerr << "Check failed at " << file << ":" << line << ": " << message << std::endl;
@@ -40,15 +39,25 @@ inline void LogFatal(const char* file, int line, const std::string& message) {
} }
} // namespace orbbec_camera } // namespace orbbec_camera
#define TRY_EXECUTE_BLOCK(block) \ #define TRY_EXECUTE_BLOCK(block) \
try { \ try { \
block; \ block; \
} catch (const ob::Error& e) { \ } catch (const ob::Error& e) { \
RCLCPP_ERROR(logger_, "Error in %s at line %d: %s", __FUNCTION__, __LINE__, e.getMessage()); \ std::string error_msg = e.getMessage() ? e.getMessage() : "Unknown OB error"; \
} catch (const std::exception& e) { \ if (error_msg.find("Device is deactivated") != std::string::npos || \
RCLCPP_ERROR(logger_, "Exception in %s at line %d: %s", __FUNCTION__, __LINE__, e.what()); \ error_msg.find("disconnected") != std::string::npos || \
} catch (...) { \ error_msg.find("Send control transfer failed") != std::string::npos) { \
RCLCPP_ERROR(logger_, "Unknown exception in %s at line %d", __FUNCTION__, __LINE__); \ 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__); \
} }
#define TRY_TO_SET_PROPERTY(func, property, value) \ #define TRY_TO_SET_PROPERTY(func, property, value) \
@@ -200,5 +209,5 @@ cv::Mat undistortImage(const cv::Mat& image, const OBCameraIntrinsic& intrinsic,
std::string getDistortionModels(OBCameraDistortion distortion); std::string getDistortionModels(OBCameraDistortion distortion);
std::string calcMD5(const std::string &data); std::string calcMD5(const std::string& data);
} // namespace orbbec_camera } // namespace orbbec_camera
+1 -1
View File
@@ -240,13 +240,13 @@ def generate_launch_description():
DeclareLaunchArgument('align_mode', default_value='HW'), DeclareLaunchArgument('align_mode', default_value='HW'),
DeclareLaunchArgument('align_target_stream', default_value='COLOR'),# COLOR or DEPTH DeclareLaunchArgument('align_target_stream', default_value='COLOR'),# COLOR or DEPTH
DeclareLaunchArgument('diagnostic_period', default_value='1.0'), # seconds DeclareLaunchArgument('diagnostic_period', default_value='1.0'), # seconds
DeclareLaunchArgument('time_sync_period', default_value='6.0'), # seconds
DeclareLaunchArgument('enable_laser', default_value='true'), DeclareLaunchArgument('enable_laser', default_value='true'),
DeclareLaunchArgument('depth_precision', default_value=''), DeclareLaunchArgument('depth_precision', default_value=''),
DeclareLaunchArgument('device_preset', default_value='Default'), DeclareLaunchArgument('device_preset', default_value='Default'),
DeclareLaunchArgument('retry_on_usb3_detection_failure', default_value='false'), DeclareLaunchArgument('retry_on_usb3_detection_failure', default_value='false'),
DeclareLaunchArgument('laser_energy_level', default_value='-1'), DeclareLaunchArgument('laser_energy_level', default_value='-1'),
DeclareLaunchArgument('enable_sync_host_time', default_value='true'), DeclareLaunchArgument('enable_sync_host_time', default_value='true'),
DeclareLaunchArgument('time_sync_period', default_value='6.0'), # seconds
DeclareLaunchArgument('time_domain', default_value='global'),# global, device, system DeclareLaunchArgument('time_domain', default_value='global'),# global, device, system
DeclareLaunchArgument('enable_color_undistortion', default_value='false'), DeclareLaunchArgument('enable_color_undistortion', default_value='false'),
DeclareLaunchArgument('config_file_path', default_value=''), DeclareLaunchArgument('config_file_path', default_value=''),
+18 -41
View File
@@ -1885,9 +1885,6 @@ void OBCameraNode::getParameters() {
int software_trigger_period = 33; int software_trigger_period = 33;
setAndGetNodeParameter<int>(software_trigger_period, "software_trigger_period", 33); setAndGetNodeParameter<int>(software_trigger_period, "software_trigger_period", 33);
software_trigger_period_ = std::chrono::milliseconds(software_trigger_period); software_trigger_period_ = std::chrono::milliseconds(software_trigger_period);
double time_sync_period = 6.0;
setAndGetNodeParameter<double>(time_sync_period, "time_sync_period", 6.0);
time_sync_period_ = std::chrono::milliseconds((int)(time_sync_period * 1000));
setAndGetNodeParameter<int>(gmsl_trigger_fps_, "gmsl_trigger_fps", 3000); setAndGetNodeParameter<int>(gmsl_trigger_fps_, "gmsl_trigger_fps", 3000);
setAndGetNodeParameter<bool>(enable_gmsl_trigger_, "enable_gmsl_trigger", false); setAndGetNodeParameter<bool>(enable_gmsl_trigger_, "enable_gmsl_trigger", false);
setAndGetNodeParameter<std::string>(interleave_ae_mode_, "interleave_ae_mode", "hdr"); setAndGetNodeParameter<std::string>(interleave_ae_mode_, "interleave_ae_mode", "hdr");
@@ -1974,7 +1971,6 @@ void OBCameraNode::setupTopics() {
setupCameraCtrlServices(); setupCameraCtrlServices();
setupPublishers(); setupPublishers();
setupDiagnosticUpdater(); setupDiagnosticUpdater();
setupPeriodicHostTimeSync();
} catch (const ob::Error &e) { } catch (const ob::Error &e) {
RCLCPP_ERROR_STREAM(logger_, "Failed to setup topics: " << e.getMessage()); RCLCPP_ERROR_STREAM(logger_, "Failed to setup topics: " << e.getMessage());
throw std::runtime_error(e.getMessage()); throw std::runtime_error(e.getMessage());
@@ -2034,7 +2030,7 @@ void OBCameraNode::onTemperatureUpdate(diagnostic_updater::DiagnosticStatusWrapp
} catch (...) { } catch (...) {
// Ignore exceptions during cleanup // Ignore exceptions during cleanup
} }
RCLCPP_ERROR_STREAM(logger_, "Failed to TemperatureUpdate: " << e.getMessage()); RCLCPP_ERROR_STREAM(logger_, "Failed to TemperatureUpdate1: " << e.getMessage());
status.summary(diagnostic_msgs::msg::DiagnosticStatus::ERROR, e.getMessage()); status.summary(diagnostic_msgs::msg::DiagnosticStatus::ERROR, e.getMessage());
} catch (const std::exception &e) { } catch (const std::exception &e) {
try { try {
@@ -2045,7 +2041,7 @@ void OBCameraNode::onTemperatureUpdate(diagnostic_updater::DiagnosticStatusWrapp
} catch (...) { } catch (...) {
// Ignore exceptions during cleanup // Ignore exceptions during cleanup
} }
RCLCPP_ERROR_STREAM(logger_, "Failed to TemperatureUpdate: " << e.what()); RCLCPP_ERROR_STREAM(logger_, "Failed to TemperatureUpdate2: " << e.what());
status.summary(diagnostic_msgs::msg::DiagnosticStatus::ERROR, e.what()); status.summary(diagnostic_msgs::msg::DiagnosticStatus::ERROR, e.what());
} catch (...) { } catch (...) {
try { try {
@@ -2056,7 +2052,7 @@ void OBCameraNode::onTemperatureUpdate(diagnostic_updater::DiagnosticStatusWrapp
} catch (...) { } catch (...) {
// Ignore exceptions during cleanup // Ignore exceptions during cleanup
} }
RCLCPP_ERROR(logger_, "Failed to TemperatureUpdate: Device is deactivated/disconnected!"); RCLCPP_ERROR(logger_, "Failed to TemperatureUpdate3: Device is deactivated/disconnected!");
status.summary(diagnostic_msgs::msg::DiagnosticStatus::ERROR, "Unknown error"); status.summary(diagnostic_msgs::msg::DiagnosticStatus::ERROR, "Unknown error");
} }
} }
@@ -2072,8 +2068,21 @@ void OBCameraNode::setupDiagnosticUpdater() {
diagnostic_updater_ = std::make_unique<diagnostic_updater::Updater>(node_, 10000.0); diagnostic_updater_ = std::make_unique<diagnostic_updater::Updater>(node_, 10000.0);
diagnostic_updater_->setHardwareID(serial_number); diagnostic_updater_->setHardwareID(serial_number);
diagnostic_updater_->add("Temperatures", this, &OBCameraNode::onTemperatureUpdate); diagnostic_updater_->add("Temperatures", this, &OBCameraNode::onTemperatureUpdate);
diagnostic_timer_ = node_->create_wall_timer(std::chrono::seconds(int(diagnostic_period_)), diagnostic_timer_ =
[this]() { diagnostic_updater_->force_update(); }); node_->create_wall_timer(std::chrono::seconds(int(diagnostic_period_)), [this]() {
try {
if (is_running_.load() && diagnostic_updater_) {
diagnostic_updater_->force_update();
}
} catch (const ob::Error &e) {
RCLCPP_WARN_STREAM(logger_, "Diagnostic update failed: "
<< e.getMessage() << " - Device may be disconnected");
} catch (const std::exception &e) {
RCLCPP_WARN_STREAM(logger_, "Diagnostic update failed: " << e.what());
} catch (...) {
RCLCPP_WARN(logger_, "Diagnostic update failed: Unknown error");
}
});
} catch (const ob::Error &e) { } catch (const ob::Error &e) {
RCLCPP_ERROR_STREAM(logger_, "Failed to setup diagnostic updater: " << e.getMessage()); RCLCPP_ERROR_STREAM(logger_, "Failed to setup diagnostic updater: " << e.getMessage());
} catch (const std::exception &e) { } catch (const std::exception &e) {
@@ -2083,35 +2092,6 @@ void OBCameraNode::setupDiagnosticUpdater() {
} }
} }
void OBCameraNode::setupPeriodicHostTimeSync() {
if (time_sync_period_.count() <= 0) {
RCLCPP_INFO(logger_, "Periodic host time sync disabled (time_sync_period <= 0)");
return;
}
try {
RCLCPP_INFO_STREAM(
logger_, "Enable periodic host time sync every " << time_sync_period_.count() << " ms");
sync_timer_ = node_->create_wall_timer(std::chrono::milliseconds(time_sync_period_), [this]() {
try {
device_->timerSyncWithHost();
RCLCPP_DEBUG(logger_, "Camera time synchronized with host");
} catch (const ob::Error &e) {
RCLCPP_WARN_STREAM(logger_, "Time sync failed: " << e.getMessage());
} catch (const std::exception &e) {
RCLCPP_WARN_STREAM(logger_, "Time sync failed: " << e.what());
} catch (...) {
RCLCPP_WARN(logger_, "Time sync failed due to unknown error");
}
});
} catch (const ob::Error &e) {
RCLCPP_ERROR_STREAM(logger_, "Failed to setup periodic host time sync: " << e.getMessage());
} catch (const std::exception &e) {
RCLCPP_ERROR_STREAM(logger_, "Failed to setup periodic host time sync: " << e.what());
} catch (...) {
RCLCPP_ERROR(logger_, "Failed to setup periodic host time sync due to unknown error");
}
}
void OBCameraNode::setupPipelineConfig() { void OBCameraNode::setupPipelineConfig() {
if (pipeline_config_) { if (pipeline_config_) {
pipeline_config_.reset(); pipeline_config_.reset();
@@ -2315,9 +2295,6 @@ void OBCameraNode::setupPublishers() {
std_msgs::msg::String msg; std_msgs::msg::String msg;
msg.data = filter_status_.dump(2); msg.data = filter_status_.dump(2);
filter_status_pub_->publish(msg); filter_status_pub_->publish(msg);
device_status_pub_ = node_->create_publisher<orbbec_camera_msgs::msg::DeviceStatus>(
"device_status", extrinsics_qos);
} }
void OBCameraNode::publishPointCloud(const std::shared_ptr<ob::FrameSet> &frame_set) { void OBCameraNode::publishPointCloud(const std::shared_ptr<ob::FrameSet> &frame_set) {
+253 -34
View File
@@ -94,6 +94,7 @@ OBCameraNodeDriver::OBCameraNodeDriver(const rclcpp::NodeOptions &node_options)
"/config/OrbbecSDKConfig_v2.0.xml"), "/config/OrbbecSDKConfig_v2.0.xml"),
logger_(this->get_logger()), logger_(this->get_logger()),
extension_path_(ament_index_cpp::get_package_prefix("orbbec_camera") + "/lib/extensions") { extension_path_(ament_index_cpp::get_package_prefix("orbbec_camera") + "/lib/extensions") {
node_name_ = "orbbec_camera_node";
init(); init();
} }
@@ -105,6 +106,7 @@ OBCameraNodeDriver::OBCameraNodeDriver(const std::string &node_name, const std::
"/config/OrbbecSDKConfig_v2.0.xml"), "/config/OrbbecSDKConfig_v2.0.xml"),
logger_(this->get_logger()), logger_(this->get_logger()),
extension_path_(ament_index_cpp::get_package_prefix("orbbec_camera") + "/lib/extensions") { extension_path_(ament_index_cpp::get_package_prefix("orbbec_camera") + "/lib/extensions") {
node_name_ = node_name;
init(); init();
} }
@@ -123,13 +125,30 @@ OBCameraNodeDriver::~OBCameraNodeDriver() {
// Stop timers that might access the device // Stop timers that might access the device
if (sync_host_time_timer_) { if (sync_host_time_timer_) {
sync_host_time_timer_->cancel(); try {
sync_host_time_timer_.reset(); sync_host_time_timer_->cancel();
sync_host_time_timer_.reset();
} catch (...) {
RCLCPP_WARN_STREAM(logger_, "Exception during sync timer cleanup in destructor");
}
} }
if (check_connect_timer_) { if (check_connect_timer_) {
check_connect_timer_->cancel(); try {
check_connect_timer_.reset(); check_connect_timer_->cancel();
check_connect_timer_.reset();
} catch (...) {
RCLCPP_WARN_STREAM(logger_, "Exception during check connect timer cleanup in destructor");
}
}
if (device_status_timer_) {
try {
device_status_timer_->cancel();
device_status_timer_.reset();
} catch (...) {
RCLCPP_WARN_STREAM(logger_, "Exception during device status timer cleanup in destructor");
}
} }
// Now stop threads // Now stop threads
@@ -171,6 +190,8 @@ void OBCameraNodeDriver::init() {
auto log_level = obLogSeverityFromString(log_level_str); auto log_level = obLogSeverityFromString(log_level_str);
connection_delay_ = static_cast<int>(declare_parameter<int>("connection_delay", 100)); connection_delay_ = static_cast<int>(declare_parameter<int>("connection_delay", 100));
enable_sync_host_time_ = declare_parameter<bool>("enable_sync_host_time", true); enable_sync_host_time_ = declare_parameter<bool>("enable_sync_host_time", true);
double time_sync_period = declare_parameter<double>("time_sync_period", 60.0);
time_sync_period_ = std::chrono::milliseconds((int)(time_sync_period * 1000));
upgrade_firmware_ = declare_parameter<std::string>("upgrade_firmware", ""); upgrade_firmware_ = declare_parameter<std::string>("upgrade_firmware", "");
g_camera_name = declare_parameter<std::string>("camera_name", g_camera_name); g_camera_name = declare_parameter<std::string>("camera_name", g_camera_name);
g_time_domain = declare_parameter<std::string>("time_domain", g_time_domain); g_time_domain = declare_parameter<std::string>("time_domain", g_time_domain);
@@ -235,6 +256,10 @@ void OBCameraNodeDriver::init() {
device_status_timer_ = device_status_timer_ =
this->create_wall_timer(std::chrono::milliseconds(1000 / device_status_interval_hz), this->create_wall_timer(std::chrono::milliseconds(1000 / device_status_interval_hz),
[this]() { deviceStatusTimer(); }); [this]() { deviceStatusTimer(); });
// Initialize device status publisher
device_status_pub_ = this->create_publisher<orbbec_camera_msgs::msg::DeviceStatus>(
"device_status", rclcpp::QoS(1).transient_local());
} }
void OBCameraNodeDriver::onDeviceConnected(const std::shared_ptr<ob::DeviceList> &device_list) { void OBCameraNodeDriver::onDeviceConnected(const std::shared_ptr<ob::DeviceList> &device_list) {
@@ -388,6 +413,16 @@ void OBCameraNodeDriver::resetDevice() {
continue; continue;
} }
// Stop sync timer to prevent it from accessing the device during reset
if (sync_host_time_timer_) {
try {
sync_host_time_timer_->cancel();
sync_host_time_timer_.reset();
} catch (...) {
RCLCPP_WARN_STREAM(logger_, "Exception during sync timer cleanup during reset");
}
}
RCLCPP_INFO_STREAM(logger_, "resetDevice : Reset device uid: " << device_unique_id_); RCLCPP_INFO_STREAM(logger_, "resetDevice : Reset device uid: " << device_unique_id_);
std::lock_guard<decltype(device_lock_)> device_lock(device_lock_); std::lock_guard<decltype(device_lock_)> device_lock(device_lock_);
{ {
@@ -448,30 +483,165 @@ void OBCameraNodeDriver::resetDevice() {
} }
void OBCameraNodeDriver::deviceStatusTimer() { void OBCameraNodeDriver::deviceStatusTimer() {
if (ob_camera_node_ == nullptr) { // Always publish device status regardless of device connection state
return;
}
orbbec_camera_msgs::msg::DeviceStatus status_msg; orbbec_camera_msgs::msg::DeviceStatus status_msg;
status_msg.header.stamp = this->now(); status_msg.header.stamp = this->now();
status_msg.device_online = device_connected_.load(); status_msg.device_online = device_connected_.load();
status_msg.header.frame_id = node_name_;
ob_camera_node_->getColorStatus(status_msg); // Initialize default values for when device is not connected
ob_camera_node_->getDepthStatus(status_msg); status_msg.connection_type = "";
status_msg.calibration_from_factory = false;
status_msg.calibration_from_launch_param = false;
status_msg.customer_calibration_ready = false;
status_msg.connection_type = device_info_->getConnectionType(); // Flag to track if device communication error occurs
bool device_communication_error = false;
auto camera_params = device_->getCalibrationCameraParamList(); // Only try to get device information if device is connected and stable
bool calibration_from_factory = (camera_params != nullptr && camera_params->count() > 0); if (device_connected_.load() && !device_connecting_.load()) {
status_msg.calibration_from_factory = calibration_from_factory; // Check if reset is in progress
status_msg.calibration_from_launch_param = ob_camera_node_->isParamCalibrated(); std::unique_lock<decltype(reset_device_mutex_)> reset_lock(reset_device_mutex_,
std::try_to_lock);
if (reset_lock.owns_lock() && !reset_device_flag_) {
// Only get device-specific info if we have a valid camera node and device
if (ob_camera_node_) {
// Safely get color and depth status - these may access device
try {
ob_camera_node_->getColorStatus(status_msg);
ob_camera_node_->getDepthStatus(status_msg);
} catch (const ob::Error &e) {
std::string error_msg = e.getMessage() ? e.getMessage() : "Unknown OB error";
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());
device_communication_error = true;
} 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__);
}
if (!ob_camera_node_->checkUserCalibrationReady()) { // These should be safe as they don't directly access hardware
status_msg.customer_calibration_ready = false; status_msg.calibration_from_launch_param = ob_camera_node_->isParamCalibrated();
} else { }
status_msg.customer_calibration_ready = true;
// Safely get connection type
try {
if (device_info_) {
status_msg.connection_type = device_info_->getConnectionType();
}
} catch (const ob::Error &e) {
std::string error_msg = e.getMessage() ? e.getMessage() : "Unknown OB error";
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());
device_communication_error = true;
} 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__);
}
// Safely get calibration info
try {
if (device_) {
auto camera_params = device_->getCalibrationCameraParamList();
bool calibration_from_factory = (camera_params != nullptr && camera_params->count() > 0);
status_msg.calibration_from_factory = calibration_from_factory;
}
} catch (const ob::Error &e) {
std::string error_msg = e.getMessage() ? e.getMessage() : "Unknown OB error";
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());
device_communication_error = true;
} 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__);
}
// Safely check user calibration readiness - this may also access device
// Only execute for 435LE devices (check by device name for network devices)
try {
if (device_info_ && ob_camera_node_) {
std::string device_name = device_info_->getName();
if (device_name.find("435Le") != std::string::npos ||
device_name.find("435LE") != std::string::npos) {
if (!ob_camera_node_->checkUserCalibrationReady()) {
status_msg.customer_calibration_ready = false;
} else {
status_msg.customer_calibration_ready = true;
}
} else {
// For non-435LE devices, set a default value or skip this check
status_msg.customer_calibration_ready = false;
}
} else {
status_msg.customer_calibration_ready = false;
}
} catch (const ob::Error &e) {
std::string error_msg = e.getMessage() ? e.getMessage() : "Unknown OB error";
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());
device_communication_error = true;
} 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__);
}
}
} }
ob_camera_node_->publishDeviceStatus(status_msg); // If device communication error occurred, set device_online to false
if (device_communication_error) {
status_msg.device_online = false;
}
// if status_msg.connection_type is empty, set it to "unknown"
if (status_msg.connection_type.empty()) {
status_msg.connection_type = "unknown";
status_msg.device_online = false;
}
// Always publish the status message, regardless of device state
if (device_status_pub_) {
device_status_pub_->publish(status_msg);
}
// RCLCPP_INFO_STREAM(logger_, "deviceStatusTimer() "); // RCLCPP_INFO_STREAM(logger_, "deviceStatusTimer() ");
} }
@@ -705,21 +875,68 @@ void OBCameraNodeDriver::initializeDevice(const std::shared_ptr<ob::Device> &dev
if (enable_sync_host_time_ && !isOpenNIDevice(device_info_->pid())) { if (enable_sync_host_time_ && !isOpenNIDevice(device_info_->pid())) {
TRY_EXECUTE_BLOCK(device_->timerSyncWithHost()); TRY_EXECUTE_BLOCK(device_->timerSyncWithHost());
if (g_time_domain != "global") { if (g_time_domain != "global") {
sync_host_time_timer_ = this->create_wall_timer(std::chrono::milliseconds(60000), [this]() { sync_host_time_timer_ = this->create_wall_timer(time_sync_period_, [this]() {
if (device_) { // Multiple safety checks before attempting time sync
TRY_EXECUTE_BLOCK(device_->timerSyncWithHost()); if (!device_) {
RCLCPP_DEBUG_STREAM(logger_, "sync_host_time_timer_: device is null, skip time sync");
return;
} }
// Check device connection status
if (!device_connected_.load()) {
RCLCPP_DEBUG_STREAM(logger_,
"sync_host_time_timer_: device not connected, skip time sync");
return;
}
// Check if device is in connecting state
if (device_connecting_.load()) {
RCLCPP_DEBUG_STREAM(logger_, "sync_host_time_timer_: device connecting, skip time sync");
return;
}
// Check if reset is in progress
{
std::unique_lock<decltype(reset_device_mutex_)> reset_lock(reset_device_mutex_,
std::try_to_lock);
if (!reset_lock.owns_lock() || reset_device_flag_) {
RCLCPP_DEBUG_STREAM(logger_,
"sync_host_time_timer_: device reset in progress, skip time sync");
return;
}
}
// Additional safety check with device lock
std::unique_lock<decltype(device_lock_)> device_lock(device_lock_, std::try_to_lock);
if (!device_lock.owns_lock()) {
RCLCPP_DEBUG_STREAM(logger_,
"sync_host_time_timer_: cannot acquire device lock, skip time sync");
return;
}
// Verify device is still valid after acquiring lock
if (!device_) {
RCLCPP_DEBUG_STREAM(
logger_, "sync_host_time_timer_: device became null after lock, skip time sync");
return;
}
RCLCPP_INFO_STREAM(logger_, "Sync device time with host");
TRY_EXECUTE_BLOCK(device_->timerSyncWithHost());
}); });
} }
} }
RCLCPP_INFO_STREAM(logger_, "Device " << device_info_->getName() << " connected"); // Safely log device information - these calls can throw if device disconnects
RCLCPP_INFO_STREAM(logger_, "Serial number: " << device_info_->getSerialNumber()); TRY_EXECUTE_BLOCK({
RCLCPP_INFO_STREAM(logger_, "Firmware version: " << device_info_->getFirmwareVersion()); RCLCPP_INFO_STREAM(logger_, "Device " << device_info_->getName() << " connected");
RCLCPP_INFO_STREAM(logger_, "Hardware version: " << device_info_->getHardwareVersion()); RCLCPP_INFO_STREAM(logger_, "Serial number: " << device_info_->getSerialNumber());
RCLCPP_INFO_STREAM(logger_, "Firmware version: " << device_info_->getFirmwareVersion());
RCLCPP_INFO_STREAM(logger_, "Hardware version: " << device_info_->getHardwareVersion());
RCLCPP_INFO_STREAM(logger_, "usb connect type: " << device_info_->getConnectionType());
});
RCLCPP_INFO_STREAM(logger_, "device unique id: " << device_unique_id_); RCLCPP_INFO_STREAM(logger_, "device unique id: " << device_unique_id_);
RCLCPP_INFO_STREAM(logger_, "Current node pid: " << getpid()); RCLCPP_INFO_STREAM(logger_, "Current node pid: " << getpid());
RCLCPP_INFO_STREAM(logger_, "usb connect type: " << device_info_->getConnectionType());
auto time_cost = std::chrono::duration_cast<std::chrono::milliseconds>( auto time_cost = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start_time_); std::chrono::high_resolution_clock::now() - start_time_);
RCLCPP_INFO_STREAM(logger_, "Start device cost " << time_cost.count() << " ms"); RCLCPP_INFO_STREAM(logger_, "Start device cost " << time_cost.count() << " ms");
@@ -727,12 +944,14 @@ void OBCameraNodeDriver::initializeDevice(const std::shared_ptr<ob::Device> &dev
if (!upgrade_firmware_.empty()) { if (!upgrade_firmware_.empty()) {
firmware_update_success_ = false; firmware_update_success_ = false;
ob_camera_node_->withDeviceLock([&]() { TRY_EXECUTE_BLOCK({
device_->updateFirmware( ob_camera_node_->withDeviceLock([&]() {
upgrade_firmware_.c_str(), device_->updateFirmware(
std::bind(&OBCameraNodeDriver::firmwareUpdateCallback, this, std::placeholders::_1, upgrade_firmware_.c_str(),
std::placeholders::_2, std::placeholders::_3), std::bind(&OBCameraNodeDriver::firmwareUpdateCallback, this, std::placeholders::_1,
false); std::placeholders::_2, std::placeholders::_3),
false);
});
}); });
if (firmware_update_success_) { if (firmware_update_success_) {
return; return;
@@ -1041,7 +1260,7 @@ void OBCameraNodeDriver::firmwareUpdateCallback(OBFwUpdateState state, const cha
sync_host_time_timer_->cancel(); sync_host_time_timer_->cancel();
sync_host_time_timer_.reset(); sync_host_time_timer_.reset();
} catch (...) { } catch (...) {
// Ignore exceptions during timer cleanup RCLCPP_WARN_STREAM(logger_, "Exception during sync timer cleanup in firmware update");
} }
} }