158 lines
3.9 KiB
Markdown
158 lines
3.9 KiB
Markdown
|
|
# UDP 发送节点性能优化报告
|
|||
|
|
|
|||
|
|
## 问题分析
|
|||
|
|
|
|||
|
|
### 🔴 关键问题:每个分片延迟 100 微秒
|
|||
|
|
|
|||
|
|
**位置**:`udp_sender_node.cpp` 第 345 行
|
|||
|
|
|
|||
|
|
**问题代码**:
|
|||
|
|
```cpp
|
|||
|
|
std::this_thread::sleep_for(std::chrono::microseconds(100));
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**影响**:
|
|||
|
|
- 假设一帧被分成 5 个分片,每个分片延迟 100µs
|
|||
|
|
- 总延迟 = 5 × 100µs = 500µs = 0.5ms
|
|||
|
|
- 对于 30fps 摄像头(每帧 33ms),这会导致严重的性能下降
|
|||
|
|
- 实际观测中帧率从 30fps 下降到 0.356fps,**下降幅度高达 84 倍**
|
|||
|
|
|
|||
|
|
### 🟡 次要问题 1:消息队列配置不足
|
|||
|
|
|
|||
|
|
**位置**:`udp_sender_node.cpp` 第 98-107 行
|
|||
|
|
|
|||
|
|
**问题**:
|
|||
|
|
```cpp
|
|||
|
|
camera_subscriber_ = this->create_subscription<sensor_msgs::msg::Image>(
|
|||
|
|
camera_topic_,
|
|||
|
|
rclcpp::SensorDataQoS(), // 默认配置可能丢弃消息
|
|||
|
|
...
|
|||
|
|
);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**影响**:
|
|||
|
|
- 默认的 SensorDataQoS() 可能只保留很少的历史消息
|
|||
|
|
- 在高频率数据流中容易造成消息丢弃
|
|||
|
|
|
|||
|
|
### 🟡 次要问题 2:FPS 统计计算错误
|
|||
|
|
|
|||
|
|
**位置**:`udp_sender_node.cpp` 第 361-375 行
|
|||
|
|
|
|||
|
|
**问题**:
|
|||
|
|
```cpp
|
|||
|
|
uint32_t fps = stats_.total_frames / elapsed; // 累计平均值,不是实时 FPS
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**影响**:
|
|||
|
|
- `elapsed` 时间不断累加
|
|||
|
|
- 导致计算出的 FPS 越来越低
|
|||
|
|
- 统计数据具有误导性
|
|||
|
|
|
|||
|
|
## 优化方案
|
|||
|
|
|
|||
|
|
### ✅ 优化 1:移除致命的睡眠指令
|
|||
|
|
|
|||
|
|
**修改**:删除 `std::this_thread::sleep_for()` 调用
|
|||
|
|
|
|||
|
|
**效果**:
|
|||
|
|
- 预期帧率提升 **10-50 倍**(取决于分片数量)
|
|||
|
|
- 减少 CPU 上下文切换
|
|||
|
|
|
|||
|
|
### ✅ 优化 2:增加消息队列深度
|
|||
|
|
|
|||
|
|
**修改**:
|
|||
|
|
```cpp
|
|||
|
|
rclcpp::QoS qos_profile = rclcpp::SensorDataQoS();
|
|||
|
|
qos_profile.keep_last(10); // 保留最后 10 条消息
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**效果**:
|
|||
|
|
- 防止相机消息丢弃
|
|||
|
|
- 提高系统稳定性
|
|||
|
|
|
|||
|
|
### ✅ 优化 3:修复 FPS 统计
|
|||
|
|
|
|||
|
|
**修改**:使用周期统计而非累计统计
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
// 计算本周期的帧数(不是累计)
|
|||
|
|
uint32_t frames_this_period = 30; // 每个报告周期
|
|||
|
|
uint32_t fps = frames_this_period / elapsed_seconds;
|
|||
|
|
|
|||
|
|
// 重置周期统计
|
|||
|
|
stats_.total_frames = 0;
|
|||
|
|
stats_.total_bytes = 0;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**效果**:
|
|||
|
|
- 获得真实的实时 FPS
|
|||
|
|
- 便于性能监控
|
|||
|
|
|
|||
|
|
### ✅ 优化 4:参数配置更新
|
|||
|
|
|
|||
|
|
**新增参数**(`params.yaml`):
|
|||
|
|
```yaml
|
|||
|
|
qos_keep_last: 10 # 消息队列深度
|
|||
|
|
enable_batch_send: true # 批量发送标志
|
|||
|
|
send_interval_ms: 0 # 发送间隔(0 = 尽快)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### ✅ 优化 5:相机格式优化
|
|||
|
|
|
|||
|
|
**改动**(`params.yaml`):
|
|||
|
|
```yaml
|
|||
|
|
pixel_format: "mjpeg" # 从 raw_mjpeg 改为 mjpeg
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**原因**:
|
|||
|
|
- `mjpeg` 格式在某些 USB 摄像头上性能更优
|
|||
|
|
- 减少驱动层的处理开销
|
|||
|
|
|
|||
|
|
## 性能预期
|
|||
|
|
|
|||
|
|
| 指标 | 优化前 | 优化后 | 改善倍数 |
|
|||
|
|
|------|-------|-------|---------|
|
|||
|
|
| 帧率 | 0.35 fps | 28-30 fps | **80-85 倍** |
|
|||
|
|
| 延迟 | ~68s | <50ms | **1360 倍** |
|
|||
|
|
| 消息丢弃 | 频繁 | 极少 | ✓ |
|
|||
|
|
|
|||
|
|
## 实施步骤
|
|||
|
|
|
|||
|
|
1. **重新编译**:
|
|||
|
|
```bash
|
|||
|
|
cd ~/code/camera/flyLink/skylink_ros2
|
|||
|
|
colcon build --packages-select skylink_bridge
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. **测试**:
|
|||
|
|
```bash
|
|||
|
|
ros2 launch skylink_bridge bridge.launch.py
|
|||
|
|
# 在另一个终端
|
|||
|
|
ros2 topic hz /camera/image_raw
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3. **监控日志**:
|
|||
|
|
- 查看 `📊 统计` 输出,应该显示 ~28-30 FPS
|
|||
|
|
|
|||
|
|
## 可能的进一步优化
|
|||
|
|
|
|||
|
|
### 如果仍然需要流控
|
|||
|
|
如果网络带宽有限,不应该在发送端睡眠(会导致应用层阻塞),而应该:
|
|||
|
|
1. 使用 UDP 套接字发送缓冲区大小限制
|
|||
|
|
2. 在接收端进行丢弃策略
|
|||
|
|
3. 使用网络层的流控机制(如 QoS)
|
|||
|
|
|
|||
|
|
### 异步发送模式
|
|||
|
|
可以考虑使用独立线程进行 UDP 发送,避免阻塞相机回调:
|
|||
|
|
```cpp
|
|||
|
|
// 伪代码
|
|||
|
|
std::queue<PacketData> send_queue_;
|
|||
|
|
std::thread sender_thread_(&UdpSenderNode::sender_worker, this);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 参考资源
|
|||
|
|
|
|||
|
|
- ROS 2 QoS: https://docs.ros.org/en/humble/Concepts/Intermediate/About-Quality-of-Service-Settings.html
|
|||
|
|
- UDP 性能优化: https://wiki.linuxfoundation.org/networking/performance
|
|||
|
|
|