在设备上发布ROS2相机话题,本机可以顺畅的收到。局域网里的设备可以收到,但是非常卡顿,丢帧验证的问题。当减小到data大小为115200byte时,局域网也可以顺畅接收
-
1、我现在遇到了 在设备上发布ROS2相机话题,本机可以顺畅的收到。局域网里的设备可以收到,但是非常卡顿,丢帧验证的问题。当减小到data大小为115200byte时,局域网也可以顺畅接收
2、发布端关键代码如下:
// 构造函数修改:添加NodeOptions设置DDS参数
CCameraPublisher::CCameraPublisher(std::string name)
: rclcpp::Node(
"Image_publisher_" + sanitizeNodeName(name),
// 配置节点选项,设置DDS参数
&{
rclcpp::NodeOptions options;
// 设置FastDDS最大消息大小(字节),4MB = 4194304
options.append_parameter_override("fastrtps.fragment_size", 1400); // 分片大小 < MTU(如1400,留足IP头空间)
options.append_parameter_override("rmw_fastrtps_max_message_size", 10 * 1024 * 1024); // 大于实际消息大小
// 发布端和订阅端均需添加:
options.append_parameter_override("fastrtps.sendBufferSize", 8 * 1024 * 1024); // 发送缓冲区8MB
options.append_parameter_override("fastrtps.receiveBufferSize", 8 * 1024 * 1024); // 接收缓冲区8MB
options.append_parameter_override("ros_network_receive_buffer_size", 10 * 1024 * 1024); // ROS层缓冲区
// 禁用DDS域名自动发现,避免多播冲突
options.append_parameter_override("rmw_fastrtps_discovery_servers", std::vectorstd::string());
return options;
}()
)
{
// QoS配置保持不变,但建议显式设置历史深度
auto qos = rclcpp::SensorDataQoS()
.keep_last(10) // 队列深度
.best_effort() // 尽力而为模式
.durability_volatile() // volatile耐用性(不存储历史数据)
.deadline(rclcpp::Duration(std::chrono::milliseconds(100))); // 使用std::chrono兼容方式.deadline(rclcpp::Duration(std::chrono::milliseconds(100))); // 使用std::chrono兼容方式tztek_info("QoS配置: best_effort, keep_last(10)"); m_Publisher = this->create_publisher<sensor_msgs::msg::CompressedImage>(name, qos); m_strTopic = name;
}
bool CCameraPublisher::Publisher(unsigned char *data, int datalen, int64_t tv_sec, int64_t tv_usec)
{
sensor_msgs::msg::CompressedImage image_msg;
image_msg.header.stamp.sec = static_cast<int32_t>(tv_sec);
image_msg.header.stamp.nanosec = static_cast<uint32_t>(tv_usec);
image_msg.header.frame_id = m_strTopic; // 设置帧ID
image_msg.data.resize(datalen);
image_msg.format = "jpg";
std::memcpy(image_msg.data.data(), (unsigned char *)data, image_msg.data.size()); // 填充压缩后的图像数据
m_Publisher->publish(image_msg);
// 更新帧信息
new_frame_ts_ = TZTEK_GetTime();
diff_time_ = new_frame_ts_ - old_frame_ts_; // 单位tztek_dbg("%d.%09d, 发布 %s,datalen:%d 间隔: %dms",
image_msg.header.stamp.sec,
image_msg.header.stamp.nanosec,
image_msg.header.frame_id.c_str(),datalen,
diff_time_);old_frame_ts_ = new_frame_ts_;
return true;
}3、订阅端关键代码如下:
CompressedImageSubscriber() :
Node(
"compressed_image_subscriber",
// 配置节点选项,与发布端保持一致的DDS参数
{
rclcpp::NodeOptions options;
// 设置与发布端相同的最大消息大小(4MB)
options.append_parameter_override("fastrtps.fragment_size", 1400); // 分片大小 < MTU(如1400,留足IP头空间)
options.append_parameter_override("rmw_fastrtps_max_message_size", 10 * 1024 * 1024); // 大于实际消息大小
// 发布端和订阅端均需添加:
options.append_parameter_override("fastrtps.sendBufferSize", 8 * 1024 * 1024); // 发送缓冲区8MB
options.append_parameter_override("fastrtps.receiveBufferSize", 8 * 1024 * 1024); // 接收缓冲区8MB
options.append_parameter_override("ros_network_receive_buffer_size", 10 * 1024 * 1024); // ROS层缓冲区
// 禁用自动发现服务器,减少网络干扰
options.append_parameter_override("rmw_fastrtps_discovery_servers", std::vectorstd::string());
return options;
}()
),
first_callback_(true)
{
// 创建订阅者,使用与发布端完全匹配的QoS配置
auto qos = rclcpp::SensorDataQoS()
.keep_last(10) // 队列深度10,与发布端一致
.best_effort() // 尽力而为可靠性,与发布端匹配
.durability_volatile() // 不存储历史数据,减少内存占用
.deadline(rclcpp::Duration(std::chrono::milliseconds(100))); // 使用std::chrono兼容方式subscriber_ = this->create_subscription<sensor_msgs::msg::CompressedImage>( "/cam1/compressed", qos, // 使用匹配的QoS配置 std::bind(&CompressedImageSubscriber::image_callback, this, std::placeholders::_1) ); RCLCPP_INFO(this->get_logger(), "Compressed image subscriber initialized with DDS params"); RCLCPP_INFO(this->get_logger(), "Subscribing to topic: %s", "/cam1/compressed"); RCLCPP_INFO(this->get_logger(), "QoS configuration: best_effort, keep_last(10)"); }
4、这个数据的 Data size: 576000 bytes,这个尺寸会异常丢帧,但是如果我修改
image_msg.data.resize(datalen/5);
std::memcpy(image_msg.data.data(), (unsigned char *)data, image_msg.data.size()/5);
局域网的设备也可以顺畅接收
5、订阅端的回调函数仅仅是打印
6、请主要关注为啥局域网的设备是否顺畅,与data size有关
7、网络带宽为
[ 5] local 192.168.37.96 port 39468 connected to 192.168.37.167 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 12.0 MBytes 101 Mbits/sec 0 206 KBytes
8、发布端发布1路数据,帧率为12.5fps,订阅端仅仅订阅一路
9、局域网的订阅端带宽:
jixufang@jixufang-Latitude-5401:~/ros2_workspace$ ros2 topic bw cam1/compressed
Subscribed to [cam1/compressed]
2.88 MB/s from 4 messages
Message size mean: 0.58 MB min: 0.58 MB max: 0.58 MB
1.28 MB/s from 4 messages
Message size mean: 0.58 MB min: 0.58 MB max: 0.58 MB
10、本机的订阅端带宽:
root@hobot:/map/ywy/cam_b24cf85b# ros2 topic bw cam1/compressed
Subscribed to [cam1/compressed]
5.78 MB/s from 13 messages
Message size mean: 0.44 MB min: 0.44 MB max: 0.44 MB
5.51 MB/s from 25 messages
Message size mean: 0.44 MB min: 0.44 MB max: 0.44 MB
5.56 MB/s from 38 messages
Message size mean: 0.44 MB min: 0.44 MB max: 0.44 MB11、scp测试丢包情况:
root@hobot:/map/ywy/cam_b24cf85b# dd if=/dev/zero of=test.bin bs=576000 count=100
100+0 records in
100+0 records out
57600000 bytes (58 MB, 55 MiB) copied, 0.0404203 s, 1.4 GB/s
root@hobot:/map/ywy/cam_b24cf85b# ls
case_tztek cfg demo init_env.sh J6_Cam_User_Guide_V1.0.pdf test.bin tools tztek_camera.sh version
root@hobot:/map/ywy/cam_b24cf85b# scp test.bin jixufang@192.168.37.96:~/
Warning: Permanently added '192.168.37.96' (ED25519) to the list of known hosts.
jixufang@192.168.37.96's password:
test.bin 没看出来丢包