This commit is contained in:
hq 2026-08-13 11:01:21 +08:00
parent 8f0f859f48
commit b07527e208
6 changed files with 23 additions and 13 deletions

View File

@ -25,7 +25,7 @@ def generate_launch_description():
position_y = LaunchConfiguration("position_y") position_y = LaunchConfiguration("position_y")
orientation_yaw = LaunchConfiguration("orientation_yaw") orientation_yaw = LaunchConfiguration("orientation_yaw")
camera_enabled = LaunchConfiguration("camera_enabled", default=True) camera_enabled = LaunchConfiguration("camera_enabled", default=True)
stereo_camera_enabled = LaunchConfiguration("stereo_camera_enabled", default=False) stereo_camera_enabled = LaunchConfiguration("stereo_camera_enabled", default=True)
two_d_lidar_enabled = LaunchConfiguration("two_d_lidar_enabled", default=True) two_d_lidar_enabled = LaunchConfiguration("two_d_lidar_enabled", default=True)
odometry_source = LaunchConfiguration("odometry_source", default="world") odometry_source = LaunchConfiguration("odometry_source", default="world")
robot_namespace = LaunchConfiguration("robot_namespace", default='bcr_bot') robot_namespace = LaunchConfiguration("robot_namespace", default='bcr_bot')

View File

@ -23,7 +23,7 @@ def generate_launch_description():
position_y = LaunchConfiguration("position_y") position_y = LaunchConfiguration("position_y")
orientation_yaw = LaunchConfiguration("orientation_yaw") orientation_yaw = LaunchConfiguration("orientation_yaw")
camera_enabled = LaunchConfiguration("camera_enabled", default=True) camera_enabled = LaunchConfiguration("camera_enabled", default=True)
stereo_camera_enabled = LaunchConfiguration("stereo_camera_enabled", default=False) stereo_camera_enabled = LaunchConfiguration("stereo_camera_enabled", default=True)
two_d_lidar_enabled = LaunchConfiguration("two_d_lidar_enabled", default=True) two_d_lidar_enabled = LaunchConfiguration("two_d_lidar_enabled", default=True)
odometry_source = LaunchConfiguration("odometry_source") odometry_source = LaunchConfiguration("odometry_source")
@ -126,4 +126,4 @@ def generate_launch_description():
DeclareLaunchArgument("odometry_source", default_value="world"), DeclareLaunchArgument("odometry_source", default_value="world"),
robot_state_publisher, robot_state_publisher,
gz_spawn_entity, transform_publisher, gz_ros2_bridge gz_spawn_entity, transform_publisher, gz_ros2_bridge
]) ])

View File

@ -23,7 +23,7 @@ def generate_launch_description():
position_y = LaunchConfiguration("position_y") position_y = LaunchConfiguration("position_y")
orientation_yaw = LaunchConfiguration("orientation_yaw") orientation_yaw = LaunchConfiguration("orientation_yaw")
camera_enabled = LaunchConfiguration("camera_enabled", default=True) camera_enabled = LaunchConfiguration("camera_enabled", default=True)
stereo_camera_enabled = LaunchConfiguration("stereo_camera_enabled", default=False) stereo_camera_enabled = LaunchConfiguration("stereo_camera_enabled", default=True)
two_d_lidar_enabled = LaunchConfiguration("two_d_lidar_enabled", default=True) two_d_lidar_enabled = LaunchConfiguration("two_d_lidar_enabled", default=True)
odometry_source = LaunchConfiguration("odometry_source") odometry_source = LaunchConfiguration("odometry_source")

View File

@ -38,7 +38,7 @@
<xacro:arg name="robot_namespace" default=""/> <xacro:arg name="robot_namespace" default=""/>
<xacro:arg name="wheel_odom_topic" default="odom" /> <xacro:arg name="wheel_odom_topic" default="odom" />
<xacro:arg name="camera_enabled" default="false" /> <xacro:arg name="camera_enabled" default="false" />
<xacro:arg name="stereo_camera_enabled" default="false" /> <xacro:arg name="stereo_camera_enabled" default="true" />
<xacro:arg name="two_d_lidar_enabled" default="false" /> <xacro:arg name="two_d_lidar_enabled" default="false" />
<xacro:arg name="publish_wheel_odom_tf" default="true" /> <xacro:arg name="publish_wheel_odom_tf" default="true" />
<xacro:arg name="conveyor_enabled" default="false"/> <xacro:arg name="conveyor_enabled" default="false"/>

View File

@ -6,10 +6,10 @@ YAML 配置文件。节点自动发现 `sensor_msgs/msg/Image` 和
## 输出 ## 输出
- RGB直接加载 `image_transport/compressed_pub`只发布其 - RGB直接加载 `image_transport/compressed_pub`插件发布
`/viz/<source>/rgb/compressed` 传输 topic,不创建 raw base topic。 `/viz/<source>/rgb/compressed`,不创建 raw base topic。
- 深度:直接加载 `image_transport/compressedDepth_pub`只发布其 - 深度:直接加载 `image_transport/compressedDepth_pub`插件发布
`/viz/<source>/depth/compressedDepth` 传输 topic,不创建 raw base topic。 `/viz/<source>/depth/compressedDepth`,不创建 raw base topic。
- 点云:`/viz/<source>/points`,消息仍为 `sensor_msgs/msg/PointCloud2`,但只保留 - 点云:`/viz/<source>/points`,消息仍为 `sensor_msgs/msg/PointCloud2`,但只保留
`x/y/z`,去除 NaN执行体素降采样、最大点数限制和限频。 `x/y/z`,去除 NaN执行体素降采样、最大点数限制和限频。

View File

@ -56,7 +56,10 @@ private:
std::string e = encoding; std::string e = encoding;
std::transform(e.begin(), e.end(), e.begin(), [](unsigned char c) { return std::tolower(c); }); std::transform(e.begin(), e.end(), e.begin(), [](unsigned char c) { return std::tolower(c); });
if (e == "16uc1" || e == "32fc1" || e == "mono16" || e == "32sc1") return ImageKind::DEPTH; if (e == "16uc1" || e == "32fc1" || e == "mono16" || e == "32sc1") return ImageKind::DEPTH;
if (e == "rgb8" || e == "bgr8" || e == "rgba8" || e == "bgra8" || e == "mono8") return ImageKind::RGB; if (e == "rgb8" || e == "bgr8" || e == "rgba8" || e == "bgra8" ||
e == "mono8" || e == "8uc3" || e == "8uc4" || e == "r8g8b8" ||
e == "b8g8r8" || e == "rgb_int8" || e == "rgba_int8" ||
e == "bgr_int8" || e == "bgra_int8") return ImageKind::RGB;
return ImageKind::UNKNOWN; return ImageKind::UNKNOWN;
} }
@ -77,6 +80,7 @@ private:
if (subscriptions_.count(topic) || cloud_subscriptions_.count(topic)) continue; if (subscriptions_.count(topic) || cloud_subscriptions_.count(topic)) continue;
const auto & types = entry.second; const auto & types = entry.second;
if (std::find(types.begin(), types.end(), "sensor_msgs/msg/Image") != types.end()) { if (std::find(types.begin(), types.end(), "sensor_msgs/msg/Image") != types.end()) {
RCLCPP_INFO(get_logger(), "Discovered image topic: %s", topic.c_str());
subscriptions_[topic] = create_subscription<Image>(topic, qos_, [this, topic](Image::ConstSharedPtr msg) { on_image(topic, msg); }); subscriptions_[topic] = create_subscription<Image>(topic, qos_, [this, topic](Image::ConstSharedPtr msg) { on_image(topic, msg); });
} else if (std::find(types.begin(), types.end(), "sensor_msgs/msg/PointCloud2") != types.end()) { } else if (std::find(types.begin(), types.end(), "sensor_msgs/msg/PointCloud2") != types.end()) {
cloud_subscriptions_[topic] = create_subscription<PointCloud2>(topic, qos_, [this, topic](PointCloud2::ConstSharedPtr msg) { on_cloud(topic, msg); }); cloud_subscriptions_[topic] = create_subscription<PointCloud2>(topic, qos_, [this, topic](PointCloud2::ConstSharedPtr msg) { on_cloud(topic, msg); });
@ -87,7 +91,11 @@ private:
void on_image(const std::string & topic, Image::ConstSharedPtr msg) { void on_image(const std::string & topic, Image::ConstSharedPtr msg) {
if (!due(topic, input_fps_, false)) return; if (!due(topic, input_fps_, false)) return;
const auto kind = classify(msg->encoding); const auto kind = classify(msg->encoding);
if (kind == ImageKind::UNKNOWN) return; if (kind == ImageKind::UNKNOWN) {
RCLCPP_WARN_THROTTLE(get_logger(), *get_clock(), 5000, "Ignoring image topic %s with encoding '%s'", topic.c_str(), msg->encoding.c_str());
return;
}
RCLCPP_INFO_ONCE(get_logger(), "Classified image topic %s as %s (encoding=%s)", topic.c_str(), kind == ImageKind::RGB ? "RGB" : "DEPTH", msg->encoding.c_str());
std::lock_guard<std::mutex> lock(data_mutex_); std::lock_guard<std::mutex> lock(data_mutex_);
auto & slot = kind == ImageKind::RGB ? rgb_latest_ : depth_latest_; auto & slot = kind == ImageKind::RGB ? rgb_latest_ : depth_latest_;
slot[topic] = msg; slot[topic] = msg;
@ -105,7 +113,8 @@ private:
} }
std::string image_topic(const std::string & topic, bool depth) const { std::string image_topic(const std::string & topic, bool depth) const {
return (output_ns_.empty() ? "/viz" : output_ns_) + "/" + safe_name(topic) + (depth ? "/depth/compressedDepth" : "/rgb/compressed"); // Publisher plugins append their own transport suffix.
return (output_ns_.empty() ? "/viz" : output_ns_) + "/" + safe_name(topic) + (depth ? "/depth" : "/rgb");
} }
void image_loop(std::unordered_map<std::string, Image::ConstSharedPtr> & slots, bool depth) { void image_loop(std::unordered_map<std::string, Image::ConstSharedPtr> & slots, bool depth) {
@ -126,9 +135,10 @@ private:
try { try {
auto plugin = image_loader_->createSharedInstance(lookup); auto plugin = image_loader_->createSharedInstance(lookup);
plugin->advertise(this, image_topic(item.first, depth), qos_.get_rmw_qos_profile()); plugin->advertise(this, image_topic(item.first, depth), qos_.get_rmw_qos_profile());
RCLCPP_INFO(get_logger(), "Loaded %s -> %s", lookup, plugin->getTopic().c_str());
it = image_publishers_.emplace(key, std::move(plugin)).first; it = image_publishers_.emplace(key, std::move(plugin)).first;
} catch (const pluginlib::PluginlibException & ex) { } catch (const pluginlib::PluginlibException & ex) {
RCLCPP_ERROR(get_logger(), "Cannot load image_transport plugin %s: %s", lookup, ex.what()); RCLCPP_ERROR(get_logger(), "Cannot load image_transport plugin %s for %s: %s", lookup, item.first.c_str(), ex.what());
continue; continue;
} }
} }