feat: add force IP configuration support (single-device only)

This commit is contained in:
obyalian
2025-09-18 14:09:49 +08:00
parent fdcb7022d7
commit c4ddbcb5de
3 changed files with 90 additions and 5 deletions
@@ -82,6 +82,8 @@ class OBCameraNodeDriver : public rclcpp::Node {
void firmwareUpdateCallback(OBFwUpdateState state, const char* message, uint8_t percent); void firmwareUpdateCallback(OBFwUpdateState state, const char* message, uint8_t percent);
bool applyForceIpConfig();
private: private:
const rclcpp::NodeOptions node_options_; const rclcpp::NodeOptions node_options_;
std::string config_path_; std::string config_path_;
@@ -131,5 +133,11 @@ class OBCameraNodeDriver : public rclcpp::Node {
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; rclcpp::Publisher<orbbec_camera_msgs::msg::DeviceStatus>::SharedPtr device_status_pub_ = nullptr;
std::string node_name_; std::string node_name_;
bool force_ip_enable_{false};
bool force_ip_dhcp_{false};
std::string force_ip_address_; // e.g. "192.168.1.10"
std::string force_ip_subnet_mask_; // e.g. "255.255.255.0"
std::string force_ip_gateway_; // e.g. "192.168.1.1"
std::atomic<bool> force_ip_success_{false};
}; };
} // namespace orbbec_camera } // namespace orbbec_camera
@@ -295,6 +295,12 @@ def generate_launch_description():
DeclareLaunchArgument('left_ir.image_raw.enable_pub_plugins',default_value='["image_transport/compressed", "image_transport/raw", "image_transport/theora"]'), DeclareLaunchArgument('left_ir.image_raw.enable_pub_plugins',default_value='["image_transport/compressed", "image_transport/raw", "image_transport/theora"]'),
#infra2 #infra2
DeclareLaunchArgument('right_ir.image_raw.enable_pub_plugins',default_value='["image_transport/compressed", "image_transport/raw", "image_transport/theora"]'), DeclareLaunchArgument('right_ir.image_raw.enable_pub_plugins',default_value='["image_transport/compressed", "image_transport/raw", "image_transport/theora"]'),
DeclareLaunchArgument("force_ip_enable", default_value="false"),
DeclareLaunchArgument("force_ip_dhcp", default_value="false"),
DeclareLaunchArgument("force_ip_address", default_value="192.168.1.10"),
DeclareLaunchArgument("force_ip_subnet_mask", default_value="255.255.255.0"),
DeclareLaunchArgument("force_ip_gateway", default_value="192.168.1.1"),
] ]
def get_params(context, args): def get_params(context, args):
+76 -5
View File
@@ -243,6 +243,12 @@ void OBCameraNodeDriver::init() {
ctx_->setUvcBackendType(OB_UVC_BACKEND_TYPE_LIBUVC); ctx_->setUvcBackendType(OB_UVC_BACKEND_TYPE_LIBUVC);
RCLCPP_INFO_STREAM(logger_, "setUvcBackendType:" << uvc_backend_); RCLCPP_INFO_STREAM(logger_, "setUvcBackendType:" << uvc_backend_);
} }
// Force IP
force_ip_enable_ = declare_parameter<bool>("force_ip_enable", false);
force_ip_dhcp_ = declare_parameter<bool>("force_ip_dhcp", false);
force_ip_address_ = declare_parameter<std::string>("force_ip_address", "192.168.1.10");
force_ip_subnet_mask_ = declare_parameter<std::string>("force_ip_subnet_mask", "255.255.255.0");
force_ip_gateway_ = declare_parameter<std::string>("force_ip_gateway", "192.168.1.1");
ctx_->enableNetDeviceEnumeration(enumerate_net_device_); ctx_->enableNetDeviceEnumeration(enumerate_net_device_);
ctx_->setDeviceChangedCallback([this](const std::shared_ptr<ob::DeviceList> &removed_list, ctx_->setDeviceChangedCallback([this](const std::shared_ptr<ob::DeviceList> &removed_list,
const std::shared_ptr<ob::DeviceList> &added_list) { const std::shared_ptr<ob::DeviceList> &added_list) {
@@ -393,8 +399,11 @@ void OBCameraNodeDriver::queryDevice() {
now - last_reset_device_completion_time_); now - last_reset_device_completion_time_);
if (time_since_last_reset.count() < 10) { if (time_since_last_reset.count() < 10) {
RCLCPP_DEBUG_STREAM(logger_, "queryDevice: Only " << time_since_last_reset.count() RCLCPP_DEBUG_STREAM(
<< " seconds since last reset completion, waiting before starting device..."); logger_,
"queryDevice: Only "
<< time_since_last_reset.count()
<< " seconds since last reset completion, waiting before starting device...");
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::this_thread::sleep_for(std::chrono::milliseconds(1000));
continue; continue;
} }
@@ -476,9 +485,9 @@ void OBCameraNodeDriver::resetDevice() {
} }
device_.reset(); device_.reset();
RCLCPP_INFO_STREAM(logger_, "device_ reset completed"); RCLCPP_INFO_STREAM(logger_, "device_ reset completed");
} catch (const ob::Error& e) { } catch (const ob::Error &e) {
RCLCPP_WARN_STREAM(logger_, "OB Exception during device reset: " << e.getMessage()); RCLCPP_WARN_STREAM(logger_, "OB Exception during device reset: " << e.getMessage());
} catch (const std::exception& e) { } catch (const std::exception &e) {
RCLCPP_WARN_STREAM(logger_, "Standard exception during device reset: " << e.what()); RCLCPP_WARN_STREAM(logger_, "Standard exception during device reset: " << e.what());
} catch (...) { } catch (...) {
RCLCPP_WARN_STREAM(logger_, "Unknown exception during device reset"); RCLCPP_WARN_STREAM(logger_, "Unknown exception during device reset");
@@ -991,6 +1000,66 @@ void OBCameraNodeDriver::initializeDevice(const std::shared_ptr<ob::Device> &dev
} // namespace orbbec_camera } // namespace orbbec_camera
bool OBCameraNodeDriver::applyForceIpConfig() {
if (!force_ip_enable_) {
return false;
}
if (force_ip_success_) {
return false;
}
OBNetIpConfig config{};
config.dhcp = force_ip_dhcp_ ? 1 : 0;
if (config.dhcp == 0) {
if (force_ip_address_.empty() || force_ip_subnet_mask_.empty() || force_ip_gateway_.empty()) {
RCLCPP_WARN(logger_, "Force IP enabled but parameters are incomplete");
return false;
}
auto parseIp = [](const std::string &ip, uint8_t out[4]) {
std::stringstream ss(ip);
std::string item;
int i = 0;
while (std::getline(ss, item, '.') && i < 4) {
out[i++] = static_cast<uint8_t>(std::stoi(item));
}
};
parseIp(force_ip_address_, config.address);
parseIp(force_ip_subnet_mask_, config.mask);
parseIp(force_ip_gateway_, config.gateway);
}
force_ip_success_ = false;
try {
auto device_list = ctx_->queryDeviceList();
uint32_t index = 0;
const char *mac = device_list->getUid(index);
if (ctx_->changeNetDeviceIpConfig(mac, config)) {
RCLCPP_INFO(logger_,
"Force IP config applied. force_ip_dhcp=%d ip=%s mask=%s force_ip_gateway=%s",
config.dhcp, force_ip_address_.c_str(), force_ip_subnet_mask_.c_str(),
force_ip_gateway_.c_str());
RCLCPP_INFO(logger_, "Reboot device after Force IP");
device_connected_ = false;
force_ip_success_ = true;
{
std::unique_lock<decltype(reset_device_mutex_)> reset_device_lock(reset_device_mutex_);
reset_device_flag_ = true;
}
reset_device_cond_.notify_all();
} else {
RCLCPP_ERROR(logger_, "Failed to apply Force IP config (SDK returned false)");
}
} catch (const ob::Error &e) {
RCLCPP_ERROR(logger_, "Force IP config failed with ob::Error: %s", e.getMessage());
} catch (const std::exception &e) {
RCLCPP_ERROR(logger_, "Force IP config failed with std::exception: %s", e.what());
} catch (...) {
RCLCPP_ERROR(logger_, "Force IP config failed with unknown error");
}
return force_ip_success_;
}
void OBCameraNodeDriver::connectNetDevice(const std::string &net_device_ip, int net_device_port) { void OBCameraNodeDriver::connectNetDevice(const std::string &net_device_ip, int net_device_port) {
if (net_device_ip.empty() || net_device_port == 0) { if (net_device_ip.empty() || net_device_port == 0) {
RCLCPP_ERROR_STREAM(logger_, "Invalid net device ip or port"); RCLCPP_ERROR_STREAM(logger_, "Invalid net device ip or port");
@@ -1032,7 +1101,9 @@ void OBCameraNodeDriver::startDevice(const std::shared_ptr<ob::DeviceList> &list
if (device_connected_.load()) { if (device_connected_.load()) {
return; return;
} }
if (applyForceIpConfig()) {
return;
}
// Try to set connecting flag atomically // Try to set connecting flag atomically
bool expected = false; bool expected = false;
if (!device_connecting_.compare_exchange_strong(expected, true)) { if (!device_connecting_.compare_exchange_strong(expected, true)) {