🏆 第20届全国大学生智能车竞赛备赛指南

📅 注意!!!:本文并不能保证帮助完赛,仅提供完赛思路和参考代码,完赛需要个人具备一定工程能力,实际开发过程中基础问题请参考RDK手册ROS2入门教程 和求助大模型
🎯 目标:帮助参赛团队高效完成备赛,提升竞技水平
📊 版本:v3.0 (最后更新:2025年7月11日)

📋 目录

  • 🏆 第20届全国大学生智能车竞赛备赛指南
    • 📋 目录
    • 🎯 前言
      • 📚 适用对象
      • 📝 内容概览
    • 📖 比赛规则
      • 📋 官方资料
      • 🤔 个人规则理解
        • 📝 规则要点总结
    • 🚗 车模要求与硬件平台
      • ⚠️ 重要注意事项
      • 🔧 硬件配置对比
      • 📊 性能评价与选择建议
        • OriginCar (RDK X3)
        • OriginCar Pro (RDK X5) 🔥 强烈推荐
    • ⚙️ ROS包迁移
      • 🛠️ 环境准备
      • RDK X3 配置
        • 🔧 基础环境配置
        • 📦 功能包迁移
      • RDK X5 配置
        • 🔧 基础环境配置
        • 📦 功能包迁移
    • 🏁 任务一:巡线避障扫码
      • 🎯 技术方案选择
      • Part 1: 巡线功能实现
        • 📚 推荐资源
        • 🚀 快速部署
          • Step 1: 工作空间创建
          • Step 2: 源码下载
          • Step 3: 环境配置与编译
        • ⚙️ 节点配置优化
        • 🔧 摄像头和图像数据流配置
        • 🚀 启动与测试
        • 🛠️ 常见问题与解决方案
        • 🎯 测试验证
        • 📈 模型训练与优化
        • 📦 获取控制功能包
        • 🔧 编译与配置
        • 🚦 系统启动流程
        • 🎯 比赛用精简配置
        • 📈 性能调优指南
      • 🚧 Part 2: 避障功能实现
        • 🔍 避障系统原理
        • 📦 获取避障检测包
        • 🧠 模型训练与部署
          • 训练资源推荐
          • 🔧 模型配置
        • 🖥️ 调试环境配置
        • 🧪 测试与验证
        • 🔗 集成启动配置
        • 🧠 智能避障控制算法
          • 核心控制逻辑
        • 🔧 关键参数配置
        • 📊 参数调优指南
        • 💡 高级优化策略
        • 🚀 系统集成启动
        • 📈 性能监控与调试
      • 📱 Part3:智能扫码系统
        • 🔧 技术实现方案
          • 总体思路
          • 🎯 核心技术流程
        • 📝 控制逻辑修改
          • 1. 主控制逻辑
          • 2. 二维码跟踪算法
        • 📚 二维码解析实现
          • 方案一:基于OpenCV + ZBar
        • 方案二:ROS节点集成
        • ⚙️ 参数配置优化
          • 关键参数设定
        • 🎯 集成测试流程
          • 1. 训练数据准备
          • 2. 测试验证步骤
          • 3. 性能调优技巧
        • 📊 故障排除指南
        • 📱 二维码扫描库推荐
        • 📚 参考资源
        • ⚙️ 参数调优建议
    • 🎮 任务二:远程控制
      • 🔧 硬件优化建议
        • 网络性能提升
      • 📱 远程控制实现
        • 方案一:基于摄像头图像的远程控制 📹
        • 方案二:ROS2节点级远程控制 🎛️
      • 🤖 大模型图生文功能
        • 端侧部署方案(RDK X5推荐)
        • 云端推理方案(推荐)
        • 🖥️ 上位机调试环境
    • 🅿️ 任务三:智能停车系统
      • 复用现有框架
    • ⚡ 调度优化
      • 🚀 优化目标
      • 🔧 实现思路

🎯 前言

欢迎来到第20届全国大学生智能车竞赛!作为第19届的参赛选手,我将在本文中分享实战经验和实用建议,帮助大家高效完成备赛。

📚 适用对象

📝 内容概览

本文涵盖:

  • 📖 比赛规则解读与理解
  • 🚗 硬件平台选择与配置
  • ⚙️ ROS2环境搭建与调试
  • 🏁 三大任务详细实现方案
  • ⚡ 高级调度优化技巧

💡 使用建议

  • 按需阅读,重点关注感兴趣的部分
  • 新手建议按顺序阅读,老手可直接跳转到优化章节
  • 每个章节都有对应的参考链接和实用资源

📖 比赛规则

📋 官方资料

🤔 个人规则理解

状态:待补充,将在后续更新中详细展开

📝 规则要点总结
  • 🏃 任务流程:巡线 → 避障 → 扫码 → 远程控制 → 停车
  • ⏱️ 时间限制:单次任务完成时间有上限要求
  • 🏆 评分标准:完成度、用时、稳定性综合评分
  • ⚠️ 安全要求:必须确保车辆和人员安全

🚗 车模要求与硬件平台

⚠️ 重要注意事项

  • 🚫 禁止改装:请勿擅自更换核心部件(如拆壳、换电机等),违者将被取消资格
  • ✅ 允许升级:可加装风扇散热或更换更好的 WiFi 模块
  • 📋 检录要求:比赛现场需要进行硬件检录,确保符合规范

🔧 硬件配置对比

项目 OriginCar (RDK X3) OriginCar Pro (RDK X5)
主控制器 地瓜机器人 RDK X3 地瓜机器人 RDK X5
核心算力 (BPU) 5 TOPS 10 TOPS
内存 4GB LPDDR4 8GB LPDDR4
关键传感器 单目摄像头 (1080P) 单目摄像头 (1080P) + 深度相机
💡 推荐指数 ⭐⭐⭐ ⭐⭐⭐⭐⭐
💰 价格区间 经济型 高性能型

📊 性能评价与选择建议

OriginCar (RDK X3)
  • ✅ 优势
    • 成本相对较低,适合预算有限的团队
    • 能完成所有比赛任务
    • 社区资源丰富,问题解决方便
  • ❌ 劣势
    • 对算法优化要求较高
    • 多模型同时运行时可能出现性能瓶颈
    • 内存限制可能影响复杂算法部署
OriginCar Pro (RDK X5) 🔥 强烈推荐
  • ✅ 优势
    • 算力翻倍,AI模型运行更流畅
    • CPU和内存全面升级,多任务处理能力强
    • 深度相机提供额外的感知维度
    • 更好的散热设计,稳定性更高
  • ❌ 劣势
    • 成本相对较高

💡 选择建议

  • 预算充足的团队:优先选择 RDK X5
  • 注重性价比的团队:RDK X3 也能很好完成任务
  • 首次参赛的团队:推荐 RDK X5,降低技术门槛

⚙️ ROS包迁移

📚 新手提示:如首次接触 ROS2,建议先阅读 ROS2入门教程
🎥 视频资源:推荐观看B站相关ROS2教程视频加深理解

🛠️ 环境准备

在开始之前,请确保:

  • ✅ SD卡容量至少32GB,推荐64GB
  • ✅ 网络连接稳定,支持SSH访问
  • ✅ PC端安装SSH客户端(推荐MobaXterm或VSCode)
  • ✅ 准备好官方origincar功能包

RDK X3 配置

🔧 基础环境配置
  1. 💾 烧录系统镜像

    • 按 RDK 手册烧录最新 RDK X3 镜像到 SD 卡
    • 插入 OriginCar,上电后:红灯常亮、绿灯闪烁 = 正常状态

    💡 优化建议:烧录 server 端镜像以节省计算资源
    📥 镜像下载官方镜像下载地址

  2. 🌐 网络配置

    • 确保 OriginCar 可联网,PC 端可通过 SSH 连接
    • 有线连接时,确保 IP 同网段,默认静态 IP:192.168.127.10
    • WiFi配置可通过图形界面或命令行完成
  3. ℹ️ 系统信息检查

    # 查看系统信息
    rdkos_info
    
  4. 🔄 系统更新

    # 更新系统组件
    sudo rdk-miniboot-update
    sudo apt update && sudo apt full-upgrade
    
    # 清理缓存(可选)
    sudo apt autoremove
    sudo apt autoclean
    

    ⚠️ 故障排除:截至 2025.7.1,RDK X3 最新镜像为 v3.0.0,若遇 GPG key 错误,使用以下命令修复:

    sudo apt install gpg
    cp /usr/share/keyrings/ros-archive-keyring.gpg /usr/share/keyrings/ros-archive-keyring.gpg.b && rm /usr/share/keyrings/ros-archive-keyring.gpg
    sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key | sudo gpg --dearmor -o /usr/share/keyrings/ros-archive-keyring.gpg 
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://mirrors4.tuna.tsinghua.edu.cn/ros2/ubuntu $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
    sudo apt update
    
📦 功能包迁移
  1. 🏗️ 创建工作空间并迁移功能包

    # 创建ROS2工作空间
    mkdir -p ~/ros2_ws/src
    cd ~/ros2_ws/src
    
    # 检查目录结构
    ls -la
    

    📁 目录结构:上传官方 origincar 功能包,确保目录结构如下:

    ~/ros2_ws/
    └── src/
        └── origincar/
            ├── 3rdparty/          
            ├── origincar_base/    # 底盘控制包
            ├── origincar_bringup/ # 启动文件包
            ├── origincar_description/ # 机器人描述文件
            └── origincar_msg/     # 消息定义包
    
  2. 📚 安装依赖包

    # 安装colcon编译工具
    pip3 install colcon-common-extensions
    
    # 安装ROS2相关依赖包
    sudo apt install \
      ros-humble-navigation2 \
      ros-humble-nav2-bringup \
      ros-humble-robot-localization \
      ros-humble-teleop-twist-keyboard \
      python3-ament-package \
      ros-humble-ament-cmake \
      ros-humble-cv-bridge \
      ros-humble-image-transport
    
    # 验证安装
    pip3 show colcon-common-extensions
    
  3. 🔨 编译功能包

    # 进入工作空间根目录
    cd ~/ros2_ws
    
    # 设置环境变量
    source /opt/tros/humble/setup.bash
    
    # 编译(首次编译可能较慢)
    colcon build --symlink-install
    
    # 检查编译结果
    ls install/
    

    编译成功标志:出现 install/ 目录且无错误输出
    🐛 常见问题:缺少依赖包时会有明确的错误提示,按提示安装即可

  4. 🧪 验证安装

    # 设置环境变量
    source ~/ros2_ws/install/setup.bash
    
    # 启动底盘节点
    ros2 launch origincar_bringup origincar_base.launch.py
    

    新开终端测试键盘控制:

    # 设置环境变量
    source /opt/tros/humble/setup.bash
    
    # 启动键盘控制
    ros2 run teleop_twist_keyboard teleop_twist_keyboard
    

    验证成功:小车能够响应键盘控制命令即表示环境配置完成


RDK X5 配置

🔧 基础环境配置
  1. 💾 烧录系统镜像

    • 按 RDK 手册烧录最新 RDK X5 镜像到 SD 卡
    • 插入 OriginCar Pro,上电后:绿灯常亮、红灯闪烁 = 正常状态

    💡 新特性:RDK X5 支持更快的启动速度和更稳定的系统

  2. 🌐 网络配置

    • 确保 OriginCar 可联网,PC 端可通过 SSH 连接
    • 支持 RDK Studio 闪连功能,操作更便捷
    • 有线连接时,确保 IP 同网段,默认静态 IP:192.168.127.10

    🚀 RDK Studio:图形化连接工具,支持一键连接和文件传输

  3. ℹ️ 系统信息检查

    # 查看系统版本(X5有专门的版本信息)
    rdkos_info
    
    # 查看BPU状态
    hrut_somstatus
    
  4. 🔄 系统更新

    # 更新系统组件
    sudo rdk-miniboot-update
    sudo apt update && sudo apt full-upgrade
    
    # 检查更新状态
    apt list --upgradable
    
📦 功能包迁移
  1. 🏗️ 创建工作空间并迁移功能包

    # 创建工作空间
    mkdir -p ~/ros2_ws/src
    cd ~/ros2_ws/src
    

    📁 目录结构:上传官方 origincar 功能包,确保目录结构如下:

    ~/ros2_ws/
    └── src/
        └── origincar/
            ├── 3rdparty/          # 第三方依赖包
            ├── origincar_base/    # 底盘控制包
            ├── origincar_bringup/ # 启动文件包
            ├── origincar_description/ # 机器人描述文件
            └── origincar_msg/     # 消息定义包
    
  2. 📚 安装依赖包

    # 安装colcon编译工具
    pip3 install colcon-common-extensions
    
    # 安装ROS2相关依赖包(X5版本优化)
    sudo apt install \
      ros-humble-navigation2 \
      ros-humble-nav2-bringup \
      ros-humble-robot-localization \
      ros-humble-teleop-twist-keyboard \
      python3-ament-package \
      ros-humble-cv-bridge \
      ros-humble-image-transport
    
  3. 🔨 编译功能包

    # 进入工作空间
    cd ~/ros2_ws
    
    # 编译(X5编译速度更快)
    colcon build --symlink-install
    
    # 检查编译结果
    echo "编译完成,检查安装目录..."
    ls -la install/
    
  4. 🧪 验证安装

    # 启动底盘节点
    source ~/ros2_ws/install/setup.bash
    ros2 launch origincar_bringup origincar_base.launch.py
    

    新开终端测试键盘控制:

    source /opt/tros/humble/setup.bash
    ros2 run teleop_twist_keyboard teleop_twist_keyboard
    

    验证成功:小车能够响应键盘控制命令即表示环境配置完成


🏁 任务一:巡线避障扫码

🎯 任务目标:实现自主巡线、智能避障、精准扫码的完整功能链
⏱️ 预期时间:熟练后单次完成时间可控制在10秒以内

任务一包含三个核心功能:🛣️ 巡线 + 🚧 避障 + 📱 扫码

🎯 技术方案选择

我为大家提供两种成熟的实现思路,各有优劣:

方案 技术栈组合 优势分析 劣势分析 适用场景
方案一 ResNet 巡线 + YOLOv5s 避障 + 追踪二维码车库 ✅ 技术成熟稳定
✅ 巡线精度高
✅ 社区支持好
❌ 模型切换复杂
❌ 帧率相对较低
❌ 调试难度大
追求稳定性的团队
方案二 YOLOv5s 全功能检测(巡线+避障+扫码+车库) ✅ 统一模型架构
✅ 易于维护升级
✅ RDK X3 可达30fps
✅ 部署简单
❌ 单一模型压力大
❌ 需要大量训练数据
❌ 精度依赖数据质量
注重开发效率的团队

🔥 推荐方案二的理由

  • YOLOv5s 巡线效果优秀,可同时检测多种目标
  • 统一的模型训练和部署流程,减少维护成本
  • 对 RDK X3 算力要求更友好,X5 上性能更佳
  • 便于后续功能扩展和优化

💡 经验分享

  • 作者去年使用方案一在决赛中跑出24秒的成绩
  • 方案二在维护性和实现难度上更有优势
  • 建议新手从方案二入手,有经验后可尝试方案一优化

📝 使用建议:选择方案二的同学可以快速浏览巡线部分,重点关注 避障功能实现 部分


Part 1: 巡线功能实现

🎯 功能目标:实现稳定、精准的赛道中心线检测和跟踪
📊 性能指标:检测精度>95%,处理帧率>20fps

📚 推荐资源

建议使用 Nodehub 中的优质功能包,这些包经过实战验证,稍作修改即可高效完成任务:

💡 选择建议:这些包来自社区贡献,经过多次比赛验证,是快速上手的最佳选择

🚀 快速部署
Step 1: 工作空间创建
# 创建比赛专用工作空间
mkdir -p ~/ros2_ws/src/racing_car
cd ~/ros2_ws/src/racing_car

# 验证当前路径
pwd  # 应显示: /root/ros2_ws/src/racing_car
Step 2: 源码下载

根据硬件平台选择对应分支:

# 🔧 RDK X5
git clone https://github.com/wunuo1/racing_track_detection_resnet.git -b feature-x5

# 🔧 RDK X3  
git clone https://github.com/wunuo1/racing_track_detection_resnet.git -b feature-x3

# 验证下载结果
ls -la racing_track_detection_resnet/

💡 备用方案

  • 若无法使用 git,可从 GitHub 网页下载对应分支的 zip 文件
  • 注意选择正确的分支:feature-x5 或 feature-x3
  • 下载后需要解压到正确的目录结构
Step 3: 环境配置与编译
# 🔧 配置环境变量(首次必需)
source /opt/tros/humble/setup.bash

# 💡 自动化配置:添加到 ~/.bashrc 避免重复操作
echo "# ROS2 环境配置" >> ~/.bashrc
echo "source /opt/tros/humble/setup.bash" >> ~/.bashrc
echo "source ~/ros2_ws/install/setup.bash" >> ~/.bashrc

# 🔨 编译项目
cd ~/ros2_ws
colcon build --symlink-install

# 🧪 验证编译结果
echo "编译完成状态:"
ls -la install/racing_track_detection_resnet/

编译状态判断

  • 正常情况:无错误输出,install目录生成成功
  • 异常情况:通常为依赖包缺失,按错误提示安装
  • 警告信息:多数可以忽略,不影响功能实现
⚙️ 节点配置优化

修改 launch 文件,优化启动配置。编辑赛道检测的 launch.py 文件:

def generate_launch_description():

   racing_track_detection_resnet18_node = Node(
      package='racing_track_detection_resnet',
      executable='racing_track_detection_resnet',
      output='screen',
      parameters=[
        {"sub_img_topic": "/hbmem_img"},
        {"model_path": "config/race_track_detection.bin"}
      ],
      arguments=['--ros-args', '--log-level', 'warn']
   )

   return LaunchDescription([
      racing_track_detection_resnet18_node
   ])
🔧 摄像头和图像数据流配置

数据流分析:
赛道检测节点需要订阅 /hbmem_img 话题,这是摄像头发布的 NV12 格式的高效共享内存图像数据。理解数据流对后续调试至关重要。

创建摄像头启动文件:

origincar_bringup 包中创建 camera.launch.py 文件,这是系统的核心入口:

import os
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.actions import IncludeLaunchDescription
from ament_index_python import get_package_share_directory

def generate_launch_description():
    # NV12编解码节点 - 将MJPEG转换为共享内存格式
    nv12_codec_node = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(
                get_package_share_directory('hobot_codec'),
                'launch/hobot_codec_decode.launch.py'
            )
        ),
        launch_arguments={
            'codec_in_mode': 'ros',           # 输入模式:ROS话题
            'codec_out_mode': 'shared_mem',   # 输出模式:共享内存
            'codec_sub_topic': '/image',      # 订阅原始图像
            'codec_pub_topic': '/hbmem_img'   # 发布共享内存图像
        }.items()
    )

    # WebSocket调试节点 - 用于实时预览
    web_node = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(
                get_package_share_directory('websocket'),
                'launch/websocket.launch.py'
            )
        ),
        launch_arguments={
            'websocket_image_topic': '/image',
            'websocket_smart_topic': '/racing_track_center_detection'
        }.items()
    )

    # USB摄像头节点配置
    usb_cam_node = Node(
        package='hobot_usb_cam',
        executable='hobot_usb_cam',
        name='hobot_usb_cam',
        parameters=[
            {"camera_calibration_file_path": "/opt/tros/lib/hobot_usb_cam/config/usb_camera_calibration.yaml"},
            {"frame_id": "default_usb_cam"},
            {"framerate": 30},                # 帧率:30fps
            {"image_width": 640},             # 图像宽度
            {"image_height": 480},            # 图像高度
            {"io_method": "mmap"},            # 内存映射方式
            {"pixel_format": "mjpeg"},        # 像素格式
            {"video_device": "/dev/video8"},  # 设备节点(需根据实际调整)
            {"zero_copy": False}
        ],
        arguments=['--ros-args', '--log-level', 'error']
    )

    return LaunchDescription([
        usb_cam_node,
        nv12_codec_node,
        web_node,
    ])

🔍 关键参数说明:

  • video_device: 通常为 /dev/video8,可通过 ls /dev/video* 查看
  • framerate: 推荐 30fps,过高可能影响处理性能
  • image_width/height: 640x480 是性能与质量的良好平衡点

📊 节点数据流图:

hobot_usb_cam ──(MJPEG)──> nv12_codec_node ──(NV12)──> racing_track_detection_resnet
       │                                                         │
       └──(MJPEG)──> web_node <──(检测结果)───────────────────────┘
🚀 启动与测试

分步启动命令:

# 1. 启动赛道检测节点
cd ~/ros2_ws/src/racing_car/racing_track_detection_resnet/config
ros2 launch racing_track_detection_resnet racing_track_detection_resnet.launch.py

# 2. 启动摄像头节点(新终端)
ros2 launch origincar_bringup camera.launch.py
🛠️ 常见问题与解决方案

问题1:开发环境推荐
推荐使用 VSCode + Remote-SSH 插件进行远程开发:

  • 安装 C/C++、Python、ROS 等插件
  • 支持代码补全、语法高亮、调试功能
  • 便于多文件编辑和项目管理

问题2:QoS策略不兼容

如遇到以下错误:

[racing_track_detection_resnet-1] [WARN] [1751361111.644720579] [GetLineCoordinate]: 
New publisher discovered on topic '/hbmem_img', offering incompatible QoS. 
No messages will be sent to it. Last incompatible policy: RELIABILITY_QOS_POLICY

解决方案: 修改订阅者QoS策略

// 在 racing_track_detection_resnet 节点中添加
rclcpp::QoS img_qos(10);
img_qos.reliability(rclcpp::ReliabilityPolicy::BestEffort);  // 匹配发布者策略

subscriber_hbmem_ = this->create_subscription<hbm_img_msgs::msg::HbmMsg1080P>(
    sub_img_topic_,
    img_qos,  // 使用兼容的QoS
    std::bind(&TrackDetectionNode::subscription_callback, this, std::placeholders::_1)
);

重新编译后问题即可解决。

🎯 测试验证

启动成功后,访问 http://[设备IP]:8000 查看:

  • 摄像头实时图像
  • 赛道检测结果
  • 中心点坐标信息
📈 模型训练与优化

预训练模型效果评估:
默认模型在标准环境下表现一般,建议训练自定义模型以适应具体赛道环境。

训练资源推荐:

模型部署流程:

  1. 准备模型文件:

    • 训练完成后转换为 .bin 格式
    • 将模型文件放置在 config/ 目录下
  2. 更新启动配置:

racing_track_detection_resnet18_node = Node(
    package='racing_track_detection_resnet',
    executable='racing_track_detection_resnet',
    output='screen',
    parameters=[
        {"sub_img_topic": "/hbmem_img"},
        {"model_path": "config/your_custom_model.bin"}  # 使用自定义模型
    ],
    arguments=['--ros-args', '--log-level', 'warn']
)
  1. 性能验证:
    • 重新启动节点
    • 在Web界面观察检测效果
    • 记录模型推理时间和精度
📦 获取控制功能包

推荐使用 Nodehub 中的成熟巡线控制包:

cd ~/ros2_ws/src/racing_car
git clone https://github.com/nodehubs/racing_control.git

💡 备用方案:如无法使用 git,可从网页下载 ZIP 包后上传

🔧 编译与配置
cd ~/ros2_ws
colcon build --package-select racing_control --symlink-install

关键参数调整:

修改 racing_control/launch/racing_control.launch.py 中的控制参数:

# 巡线控制参数
parameters=[
    {"follow_linear_speed": 0.5},        # 直线速度(m/s)
    {"follow_angular_ratio": 1.2},       # 角速度系数
    {"max_angular_velocity": 1.0},       # 最大角速度限制
    {"center_offset_threshold": 50},     # 中心偏移阈值(像素)
]
🚦 系统启动流程

完整启动序列(4个核心节点):

# Terminal 1: 底盘控制
ros2 launch origincar_base origincar_bringup.launch.py

# Terminal 2: 摄像头与图像处理
ros2 launch origincar_bringup camera.launch.py

# Terminal 3: 赛道检测
ros2 launch racing_track_detection_resnet racing_track_detection_resnet.launch.py

# Terminal 4: 巡线控制
ros2 launch racing_control racing_control.launch.py
🎯 比赛用精简配置

为提高系统稳定性,比赛时建议关闭Web调试功能:

# camera_race.launch.py - 去除webnode的精简版本
import os
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.actions import IncludeLaunchDescription
from ament_index_python import get_package_share_directory

def generate_launch_description():
    nv12_codec_node = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(
                get_package_share_directory('hobot_codec'),
                'launch/hobot_codec_decode.launch.py'
            )
        ),
        launch_arguments={
            'codec_in_mode': 'ros',
            'codec_out_mode': 'shared_mem',
            'codec_sub_topic': '/image',
            'codec_pub_topic': '/hbmem_img'
        }.items()
    )

    usb_cam_node = Node(
        package='hobot_usb_cam',
        executable='hobot_usb_cam',
        name='hobot_usb_cam',
        parameters=[
            {"camera_calibration_file_path": "/opt/tros/lib/hobot_usb_cam/config/usb_camera_calibration.yaml"},
            {"frame_id": "default_usb_cam"},
            {"framerate": 30},
            {"image_width": 640},
            {"image_height": 480},
            {"io_method": "mmap"},
            {"pixel_format": "mjpeg"},
            {"video_device": "/dev/video8"},
            {"zero_copy": False}
        ],
        arguments=['--ros-args', '--log-level', 'error']
    )

    return LaunchDescription([
        usb_cam_node,
        nv12_codec_node,
    ])
📈 性能调优指南

实时监控命令:

# 查看话题发布频率
ros2 topic hz /racing_track_center_detection

# 监控系统资源使用
htop

# 检查消息延迟
ros2 topic echo /racing_track_center_detection --once

关键调优参数:

参数名称 推荐范围 影响说明
follow_linear_speed 0.5-1.0 m/s 基础前进速度,过高影响稳定性
follow_angular_ratio 0.8-1.5 转向响应强度,过大易震荡

⚠️ 注意事项:此配置仅为基础版本,后续避障和扫码功能需要进一步集成优化。

🚧 Part 2: 避障功能实现

🎯 核心目标:在巡线基础上实现动态障碍物检测与智能避障
📊 技术指标:避障成功率100%,响应时间<50ms,稳定性优先

🔍 避障系统原理

技术方案:

  • 检测模块:基于YOLOv5s的实时障碍物检测
  • 判断逻辑:结合障碍物位置与赛道中心线进行距离评估
  • 控制策略:优先级决策 → 避障机动 → 恢复巡线

决策流程图:

摄像头图像 → YOLOv5检测 → 距离判断 → 控制决策
                ↓              ↓         ↓
         [障碍物位置]    [安全距离]   [避障/巡线]
📦 获取避障检测包

克隆功能包:

cd ~/ros2_ws/src/racing_car

# RDK X5 版本
git clone https://github.com/wunuo1/racing_obstacle_detection_yolo.git -b feature-x5

# RDK X3 版本  
git clone https://github.com/wunuo1/racing_obstacle_detection_yolo.git -b feature-x3

💡 备用方案:从GitHub网页下载对应分支的ZIP包

编译安装:

cd ~/ros2_ws
colcon build --packages-select racing_obstacle_detection_yolo --symlink-install
🧠 模型训练与部署
训练资源推荐

核心教程:

🔧 模型配置

1. 修改配置文件:

编辑 racing_obstacle_detection_yolo/config/yolov5sconfig.json

{
    "model_file": "/root/ros2_ws/src/racing_car/racing_obstacle_detection_yolo/config/your_custom_model.bin",
    "class_num": 3,
    "cls_names_list": "/root/ros2_ws/src/racing_car/racing_obstacle_detection_yolo/config/obstacles.list"
}

2. 更新类别列表:

编辑 obstacles.list 文件,根据你的训练数据定义:

construction_cone  
qr_code
park

3. 修改启动文件:

更新 racing_obstacle_detection_yolo.launch.py

def generate_launch_description():
    # 图像尺寸参数
    image_width_launch_arg = DeclareLaunchArgument(
        "dnn_sample_image_width", default_value=TextSubstitution(text="640")
    )
    image_height_launch_arg = DeclareLaunchArgument(
        "dnn_sample_image_height", default_value=TextSubstitution(text="480")
    )

    # 障碍物检测节点
    racing_obstacle_detection_yolov5_node = Node(
        package='racing_obstacle_detection_yolo',
        executable='racing_obstacle_detection_yolo',
        output='screen',
        parameters=[
            {"is_shared_mem_sub": True},
            {"sub_img_topic": "/hbmem_img"},
            {"config_file": "/root/ros2_ws/src/racing_car/racing_obstacle_detection_yolo/config/yolov5sconfig.json"},
            {"confidence_threshold": 0.7},    # 置信度阈值
            {"nms_threshold": 0.5},           # NMS阈值
        ],
        arguments=['--ros-args', '--log-level', 'warn']
    )

    return LaunchDescription([
        image_width_launch_arg,
        image_height_launch_arg,
        racing_obstacle_detection_yolov5_node
    ])
🖥️ 调试环境配置

创建障碍物调试用摄像头配置:

创建 obstacle_camera.launch.py

def generate_launch_description():
    nv12_codec_node = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(
                get_package_share_directory('hobot_codec'),
                'launch/hobot_codec_decode.launch.py'
            )
        ),
        launch_arguments={
            'codec_in_mode': 'ros',
            'codec_out_mode': 'shared_mem',
            'codec_sub_topic': '/image',
            'codec_pub_topic': '/hbmem_img'
        }.items()
    )

    # WebSocket调试 - 专门用于障碍物检测可视化
    web_node = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            get_package_share_directory('websocket') + '/launch/websocket.launch.py'
        ),
        launch_arguments={
            'websocket_image_topic': '/image',
            'websocket_image_type': 'mjpeg',
            'websocket_smart_topic': '/racing_obstacle_detection'  # 障碍物检测话题
        }.items()
    )

    usb_cam_node = Node(
        package='hobot_usb_cam',
        executable='hobot_usb_cam',
        name='hobot_usb_cam',
        parameters=[
            {"camera_calibration_file_path": "/opt/tros/lib/hobot_usb_cam/config/usb_camera_calibration.yaml"},
            {"frame_id": "default_usb_cam"},
            {"framerate": 30},
            {"image_width": 640},
            {"image_height": 480},
            {"io_method": "mmap"},
            {"pixel_format": "mjpeg"},
            {"video_device": "/dev/video8"},
            {"zero_copy": False}
        ],
        arguments=['--ros-args', '--log-level', 'error']
    )

    return LaunchDescription([
        usb_cam_node,
        nv12_codec_node,
        web_node,
    ])
🧪 测试与验证

启动检测测试:

# Terminal 1: 启动障碍物检测
ros2 launch racing_obstacle_detection_yolo racing_obstacle_detection_yolo.launch.py

# Terminal 2: 启动调试摄像头
ros2 launch origincar_bringup obstacle_camera.launch.py

验证检查项:

  • Web界面显示检测框
  • 置信度数值合理(>0.7)
  • 检测响应时间<100ms
  • 无漏检或误检
🔗 集成启动配置

创建统一启动文件 camera_all.launch.py

def generate_launch_description():
    # 图像编解码
    nv12_codec_node = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(get_package_share_directory('hobot_codec'), 'launch/hobot_codec_decode.launch.py')
        ),
        launch_arguments={
            'codec_in_mode': 'ros',
            'codec_out_mode': 'shared_mem',
            'codec_sub_topic': '/image',
            'codec_pub_topic': '/hbmem_img'
        }.items()
    )

    # 赛道检测模块
    racing_track_detection_node = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(get_package_share_directory('racing_track_detection_resnet'), 'launch', 'racing_track_detection_resnet.launch.py')
        )
    )

    # 障碍物检测模块
    racing_obstacle_detection_node = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(get_package_share_directory('racing_obstacle_detection_yolo'), 'launch', 'racing_obstacle_detection_yolo.launch.py')
        )
    )

    # 调试WebSocket(可选)
    web_node = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            get_package_share_directory('websocket') + '/launch/websocket.launch.py'
        ),
        launch_arguments={
            'websocket_image_topic': '/image',
            'websocket_image_type': 'mjpeg',
            'websocket_smart_topic': '/racing_obstacle_detection'
        }.items()
    )

    # USB摄像头
    usb_cam_node = Node(
        package='hobot_usb_cam',
        executable='hobot_usb_cam',
        name='hobot_usb_cam',
        parameters=[
            {"camera_calibration_file_path": "/opt/tros/lib/hobot_usb_cam/config/usb_camera_calibration.yaml"},
            {"frame_id": "default_usb_cam"},
            {"framerate": 30},
            {"image_width": 640},
            {"image_height": 480},
            {"io_method": "mmap"},
            {"pixel_format": "mjpeg"},
            {"video_device": "/dev/video8"},
            {"zero_copy": False}
        ],
        arguments=['--ros-args', '--log-level', 'error']
    )

    return LaunchDescription([
        usb_cam_node,
        nv12_codec_node,
        racing_track_detection_node,
        racing_obstacle_detection_node,
        # web_node,  # 比赛时可注释掉
    ])

💡 提示:调试时保留 web_node,比赛时注释掉以节省资源

🧠 智能避障控制算法
核心控制逻辑

在启动避障控制前,需要修改 racing_control 包的核心算法。主要修改文件:src/racing_car/racing_control/src/racing_control.cpp

关键决策算法:

// 核心避障决策逻辑
void processObstacleAvoidance(const TargetsMsg::SharedPtr targets_msg, 
                             const PointMsg::SharedPtr point_msg) {
    
    // 无障碍物 - 执行正常巡线
    if(targets_msg->targets.size() == 0) {
        if(!point_msg->targets.empty()) {
            LineFollowing(point_msg->targets[0]);
        }
        return;
    }
    
    // 有障碍物 - 分析威胁等级
    for(const auto &target : targets_msg->targets) {
        if(target.type == "construction_cone") {  // 替换为你的类别名称
            
            // 计算障碍物底部坐标(距离代理指标)
            int bottom_y = target.rois[0].rect.y_offset + target.rois[0].rect.height;
            float confidence = target.rois[0].confidence;
            
            // 距离判断逻辑
            if (bottom_y < bottom_threshold_) {
                // 障碍物距离较远,继续巡线
                if(!point_msg->targets.empty()) {
                    LineFollowing(point_msg->targets[0]);
                }
            } else {
                // 障碍物接近,执行避障
                if(confidence > confidence_threshold_) {
                    ObstacleAvoidance(target, point_msg->targets[0]);
                }
            }
        }
    }
}

// 避障机动算法
void ObstacleAvoidance(const Target& obstacle, const Point& track_center) {
    int obstacle_center_x = obstacle.rois[0].rect.x_offset + obstacle.rois[0].rect.width / 2;
    int image_center_x = 320;  // 假设图像宽度640
    
    // 根据障碍物位置选择避障方向
    if (obstacle_center_x < image_center_x) {
        // 障碍物在左侧,向右避障
        publishTwist(avoidance_linear_speed_, -avoidance_angular_speed_);
    } else {
        // 障碍物在右侧,向左避障
        publishTwist(avoidance_linear_speed_, avoidance_angular_speed_);
    }
}
🔧 关键参数配置

修改参数文件位置: racing_control/launch/racing_control.launch.py

racing_control_node = Node(
    package='racing_control',
    executable='racing_control',
    name='racing_control',
    parameters=[
        # 巡线控制参数
        {"follow_linear_speed": 0.3},        # 正常巡线速度
        {"follow_angular_ratio": 1.2},       # 巡线角速度系数
        
        # 避障控制参数  
        {"obstacle_avoidance_speed": 0.2},   # 避障时的线速度
        {"obstacle_avoidance_angular_ratio": 1.8},  # 避障角速度系数
        
        # 检测阈值参数
        {"bottom_threshold": 400},           # 距离阈值(像素)
        {"confidence_threshold": 0.7},       # 置信度阈值
        
        # 安全参数
        {"max_angular_velocity": 1.5},       # 最大角速度限制
        {"emergency_stop_distance": 450},    # 紧急停车距离
    ],
    output='screen'
)
📊 参数调优指南
参数名称 推荐范围 作用说明 调优技巧
bottom_threshold 350-450 触发避障的距离阈值 数值越大越早避障,越小越激进
confidence_threshold 0.6-0.8 YOLO检测置信度阈值 过低易误检,过高易漏检
obstacle_avoidance_speed 0.5-0.8 避障时前进速度 速度越低越安全,过低影响效率
avoidance_angular_ratio 1.5-2.0 避障转向强度 需要根据赛道调整
💡 高级优化策略

1. 多障碍物处理:

// 选择最近的威胁障碍物
float min_distance = std::numeric_limits<float>::max();
Target nearest_obstacle;
for(const auto &target : targets_msg->targets) {
    float distance = calculateDistance(target);
    if(distance < min_distance) {
        min_distance = distance;
        nearest_obstacle = target;
    }
}

2. 渐进式避障:

// 根据距离调整避障强度
float distance_ratio = static_cast<float>(bottom_y) / image_height;
float dynamic_angular_speed = base_angular_speed * (1.0 + distance_ratio);

3. 预测性避障:

// 结合赛道中心点预判最佳避障路径
int track_direction = track_center.x - image_center_x;
int obstacle_direction = obstacle_center_x - image_center_x;

// 如果障碍物阻挡预期路径,提前避障
if ((track_direction > 0 && obstacle_direction > 0) || 
    (track_direction < 0 && obstacle_direction < 0)) {
    early_avoidance = true;
}
🚀 系统集成启动

完整避障系统启动序列:

# Terminal 1: 底盘控制
ros2 launch origincar_base origincar_bringup.launch.py

# Terminal 2: 视觉处理模块(集成版)
ros2 launch origincar_bringup camera_all.launch.py

# Terminal 3: 智能控制
ros2 launch racing_control racing_control.launch.py
📈 性能监控与调试

实时监控命令:

# 监控检测结果
ros2 topic echo /racing_obstacle_detection --once

# 监控控制指令
ros2 topic echo /cmd_vel --once

# 检查系统延迟
ros2 topic hz /racing_track_center_detection
ros2 topic hz /racing_obstacle_detection

调试检查清单:

  • 障碍物检测准确率 > 95%
  • 避障响应时间 < 50ms
  • 无频繁震荡现象
  • 能够顺利恢复巡线
  • 在不同光照条件下稳定工作

⚠️ 安全提醒:测试时请确保周围环境安全

📱 Part3:智能扫码系统

🎯 功能目标:实现快速、准确的二维码识别与内容解析
📊 性能指标:识别成功率100%,响应时间<1秒,支持多种二维码格式

🔧 技术实现方案
总体思路

扫码功能基于现有的YOLOv5检测框架,通过增加二维码类别实现目标检测,然后结合专业的二维码解析库完成内容识别。

🎯 核心技术流程
    A[摄像头图像] --> B[YOLOv5检测] --> C[检测到二维码] --> D[达到阈值] --> E[停车扫码] --> F[二维码解析] --> G[内容输出] --> H[任务完成]
📝 控制逻辑修改
1. 主控制逻辑

修改 racing_control.cpp 中的控制逻辑,添加二维码检测和跟踪功能:

void processQRCodeDetection(const TargetsMsg::SharedPtr targets_msg, 
                           const PointMsg::SharedPtr point_msg) {
    
    bool qr_detected = false;
    bool obstacle_detected = false;
    Target qr_target, obstacle_target;
    
    // 遍历检测结果,分类处理
    for(const auto &target : targets_msg->targets) {
        if(target.type == "qr_code") {
            qr_detected = true;
            qr_target = target;
        } else if(target.type == "construction_cone") {
            int bottom_y = target.rois[0].rect.y_offset + target.rois[0].rect.height;
            if(bottom_y > obstacle_threshold_ && target.rois[0].confidence > confidence_threshold_) {
                obstacle_detected = true;
                obstacle_target = target;
            }
        }
    }
    
    // 优先级决策逻辑
    if(obstacle_detected) {
        // 最高优先级:避障
        ObstacleAvoidance(obstacle_target, point_msg->targets[0]);
    } else if(qr_detected) {
        // 中优先级:二维码处理
        QRCodeTracking(qr_target);
    } else {
        // 默认:巡线
        if(!point_msg->targets.empty()) {
            LineFollowing(point_msg->targets[0]);
        }
    }
}
2. 二维码跟踪算法
void QRCodeTracking(const Target& qr_target) {
    // 计算二维码中心位置
    int qr_center_x = qr_target.rois[0].rect.x_offset + qr_target.rois[0].rect.width / 2;
    int qr_bottom_y = qr_target.rois[0].rect.y_offset + qr_target.rois[0].rect.height;
    int image_center_x = 320;  // 图像中心
    
    // 距离判断
    if(qr_bottom_y > scan_distance_threshold_) {
        // 距离足够近,停车扫码
        StopAndScan(qr_target);
    } else {
        // 距离较远,跟踪接近
        TrackTowardsQR(qr_center_x, image_center_x);
    }
}

void TrackTowardsQR(int qr_x, int center_x) {
    float error = static_cast<float>(qr_x - center_x) / center_x;
    float angular_velocity = -qr_tracking_angular_ratio_ * error;
    
    // 限制角速度
    angular_velocity = std::max(-max_angular_velocity_, 
                               std::min(max_angular_velocity_, angular_velocity));
    
    publishTwist(qr_tracking_linear_speed_, angular_velocity);
}

void StopAndScan(const Target& qr_target) {
    // 停车
    publishTwist(0.0, 0.0);
    
    // 触发扫码流程
    triggerQRScanning(qr_target);
}
📚 二维码解析实现
方案一:基于OpenCV + ZBar

安装依赖:

# 在RDK系统中安装
sudo apt update
sudo apt install libzbar-dev libzbar0
pip3 install pyzbar opencv-python

Python实现:

import cv2
from pyzbar import pyzbar
import numpy as np

class QRCodeScanner:
    def __init__(self):
        self.scanner_active = False
        
    def scan_qr_code(self, image_region):
        """
        扫描图像区域中的二维码
        :param image_region: 裁剪后的图像区域
        :return: 解析结果字符串或None
        """
        try:
            # 预处理图像
            gray = cv2.cvtColor(image_region, cv2.COLOR_BGR2GRAY)
            
            # 增强对比度
            enhanced = cv2.equalizeHist(gray)
            
            # 使用pyzbar解码
            decoded_objects = pyzbar.decode(enhanced)
            
            if decoded_objects:
                for obj in decoded_objects:
                    qr_data = obj.data.decode('utf-8')
                    print(f"扫码成功: {qr_data}")
                    return qr_data
                    
        except Exception as e:
            print(f"扫码错误: {e}")
            
        return None
        
    def crop_qr_region(self, full_image, detection_box):
        """
        根据检测框裁剪二维码区域
        """
        x = detection_box.x_offset
        y = detection_box.y_offset
        w = detection_box.width
        h = detection_box.height
        
        # 扩大裁剪区域以确保完整性
        margin = 20
        x_start = max(0, x - margin)
        y_start = max(0, y - margin)
        x_end = min(full_image.shape[1], x + w + margin)
        y_end = min(full_image.shape[0], y + h + margin)
        
        return full_image[y_start:y_end, x_start:x_end]
方案二:ROS节点集成

创建扫码服务节点:

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from std_msgs.msg import String
import cv2
from pyzbar import pyzbar

class QRScannerNode(Node):
    def __init__(self):
        super().__init__('qr_scanner_node')
        
        # 订阅图像话题
        self.image_subscription = self.create_subscription(
            Image,
            '/image',
            self.image_callback,
            10
        )
        
        # 发布扫码结果
        self.qr_result_publisher = self.create_publisher(
            String,
            '/qr_scan_result',
            10
        )
        
        self.bridge = CvBridge()
        self.scanning_enabled = False
        
    def image_callback(self, msg):
        if not self.scanning_enabled:
            return
            
        try:
            # 转换图像格式
            cv_image = self.bridge.imgmsg_to_cv2(msg, "bgr8")
            
            # 扫描二维码
            result = self.scan_qr_codes(cv_image)
            
            if result:
                # 发布结果
                result_msg = String()
                result_msg.data = result
                self.qr_result_publisher.publish(result_msg)
                
                # 关闭扫描
                self.scanning_enabled = False
                
        except Exception as e:
            self.get_logger().error(f'扫码处理错误: {e}')
    
    def scan_qr_codes(self, image):
        # 转换为灰度图
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        
        # 解码二维码
        decoded_objects = pyzbar.decode(gray)
        
        for obj in decoded_objects:
            return obj.data.decode('utf-8')
            
        return None
        
    def enable_scanning(self):
        self.scanning_enabled = True
        self.get_logger().info('二维码扫描已启用')

def main(args=None):
    rclpy.init(args=args)
    node = QRScannerNode()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()
⚙️ 参数配置优化
关键参数设定

修改 racing_control.launch.py 添加扫码相关参数:

parameters=[
    # 现有参数...
    
    # 扫码控制参数
    {"qr_tracking_linear_speed": 1.15},      # 接近二维码时的速度,直接拉满急停
    {"qr_tracking_angular_ratio": 1.5},      # 跟踪角速度系数
    {"scan_distance_threshold": 420},        # 开始扫码的距离阈值
    {"qr_confidence_threshold": 0.8},        # 二维码检测置信度
    
    # 扫码行为参数
    {"scan_timeout": 5.0},                   # 扫码超时时间(秒)
    {"scan_retry_count": 3},                 # 扫码重试次数
    {"post_scan_delay": 2.0},                # 扫码后等待时间
]
🎯 集成测试流程
1. 训练数据准备

在YOLOv5训练数据中添加二维码类别:

  • 收集不同角度、光照的二维码图片
  • 标注时类别设为 qr_code
  • 确保训练数据多样性
2. 测试验证步骤
# 1. 启动完整系统
ros2 launch origincar_base origincar_bringup.launch.py
ros2 launch origincar_bringup camera_all.launch.py
ros2 launch racing_control racing_control.launch.py

# 2. 启动扫码节点(如果使用独立节点)
ros2 run qr_scanner qr_scanner_node

# 3. 监控扫码结果
ros2 topic echo /qr_scan_result
3. 性能调优技巧

提高识别成功率:

  • 优化图像预处理:增强对比度、去噪
  • 调整检测阈值:平衡误检与漏检
  • 多帧融合:连续多帧确认结果

优化响应速度:

  • 减小图像处理分辨率
  • 限制扫码区域大小
  • 使用异步处理
📊 故障排除指南
问题现象 可能原因 解决方案
无法检测到二维码 模型未训练该类别 重新训练包含二维码的模型
检测到但无法解析 图像质量差/距离不当 调整scan_distance_threshold
扫码成功率低 光照条件/角度问题 优化图像预处理算法
系统响应慢 图像处理负载过重 降低处理频率或分辨率

💡 实用技巧:建议在二维码检测时临时提高摄像头亮度,以提高识别成功率。

📱 二维码扫描库推荐

推荐使用OpenCV的WeChat QRCode模块,具有以下优势:

  • 识别率高:对各种角度、光照条件适应性强
  • 性能优秀:针对移动设备优化,速度快
  • 易于集成:Python和C++接口简单

Python实现示例

import cv2

def scan_qr_code(self, image):
    """优化的二维码扫描函数"""
    # 创建检测器(只需初始化一次)
    if not hasattr(self, 'qr_detector'):
        self.qr_detector = cv2.wechat_qrcode.WeChatQRCode(
            "detect.prototxt", "detect.caffemodel",
            "sr.prototxt", "sr.caffemodel"
        )
    
    # 检测和解码
    data, points = self.qr_detector.detectAndDecode(image)
    
    if data:
        return {
            'content': data[0],  # 二维码内容
            'position': points[0] if points else None,  # 位置信息
            'confidence': 1.0  # 置信度
        }
    return None
📚 参考资源
⚙️ 参数调优建议

关键参数

  • scan_threshold:触发扫码的距离阈值
  • follow_speed:跟踪二维码时的移动速度
  • scan_timeout:扫码超时时间
  • retry_count:扫码失败重试次数

调试技巧

  1. 先在静态环境下测试二维码识别效果
  2. 逐步增加移动速度,观察识别稳定性
  3. 测试不同光照条件下的识别率
  4. 调整摄像头焦距和曝光参数

🎮 任务二:远程控制

🎯 任务目标:实现流畅的远程控制体验 + 智能的大模型图生文功能
核心技术:实时图像传输 + ROS2远程通信 + 云端AI推理

任务二的核心是实现小车的远程控制功能,这是区别于其他参赛队伍的关键优势!

🔧 硬件优化建议

网络性能提升
  • RDK X3 用户

    • 由于板载WiFi模块性能有限,强烈建议外接高性能USB网卡
    • 推荐型号:debug
    • 提升效果:图像传输稳定性和流畅度显著改善
  • RDK X5 用户

    • 板载WiFi模块性能已经足够强大,可直接使用
    • 支持更高带宽的数据传输
    • 延迟更低,控制响应更及时

📱 远程控制实现

远程控制分为两大类实现方案:

方案一:基于摄像头图像的远程控制 📹

技术架构

摄像头采集 → 图像编码 → 网络传输 → PC端显示 → 用户操控 → 指令回传 → 小车执行

实现要点

  1. 图像采集发布

    • 使用 hobot_usb_cam 包采集摄像头图像
    • 发布 /image 话题,图像格式为 MJPEG
    • 话题类型:sensor_msgs/msg/CompressedImage
  2. 上位机显示

    • 推荐使用 Foxglove 作为上位机程序
    • 支持 CompressedImage 类型图像显示
    • 直接订阅 /image 话题即可实现图像传输
  3. 控制指令传输

    • 通过 ROS2 话题机制实现双向通信
    • 低延迟的指令响应机制
方案二:ROS2节点级远程控制 🎛️

技术架构

上位机界面 → ROS2话题发布 → 网络传输 → 下位机话题订阅 → 节点状态切换

实现细节

  1. 消息定义
    src/origincar/origincar_msg/msg 下创建 Sign.msg 文件:

    int32 sign_data  # 控制信号数据
    
  2. 话题通信

    • 上位机发布:sign4return 话题(控制指令)
    • 消息类型:std_msgs::msg::Int32 或自定义消息
    • 下位机发布:sign_switch 话题(状态反馈)
    • 消息类型:origincar_msg::msg::Sign
  3. 状态管理

    • 下位机订阅 sign4return 实现节点控制
    • 根据不同信号切换任务模式(巡线/避障/扫码等)
    • sign_switch 发布当前状态供上位机显示

🤖 大模型图生文功能

端侧部署方案(RDK X5推荐)

对于 RDK X5 用户,可以直接在端侧部署视觉语言模型:

云端推理方案(推荐)

技术流程

  1. 图像采集:摄像头实时采集前方图像
  2. 图像预处理:缩放、裁剪、格式转换
  3. 云端推理:上传至云端大模型进行图像理解
  4. 结果返回:获取文字描述并展示

推荐服务:火山引擎 Doubao-1.5-vision-lite 模型

  • 💰 性价比高:新用户送50万Token
  • 🎯 效果优秀:图像理解能力强
  • 🚀 响应快速:推理速度快,延迟低

快速部署

  1. 环境准备

    # 安装火山引擎SDK
    pip install volcengine-python-sdk[ark]
    
    # 验证安装
    python3 -c "import volcengine; print('SDK安装成功')"
    
  2. 配置API密钥

    • 在火山引擎控制台获取API密钥
  3. 功能包获取

    cd ~/ros2_ws/src/racing_car
    git clone https://github.com/Machao615/racing_vision_ai.git
    
    # 编译
    cd ~/ros2_ws
    colcon build --packages-select racing_vision_ai --symlink-install
    
  4. 配置说明
    这个ROS2功能包的特点:

    • 监听 sign4return 信号触发
    • 当信号值达到配置的目标值时自动执行
    • 订阅一帧图像并调用火山引擎API
    • 返回图像的文字描述结果

📖 详细使用方法:参考 racing_vision_ai 文档

🖥️ 上位机调试环境

环境配置步骤:

  1. 安装 coStudio 客户端

    • 下载安装包并完成安装
    • 导入 demo.json 配置文件
    • 按需配置模块布局
  2. 日志监控配置

    • 添加"日志订阅"模块
    • 设置命名空间过滤:仅订阅 ai_vision 话题
    • 配置实时显示大模型推理结果

界面布局建议:

  • 左侧:实时图像显示窗口
  • 右侧:AI分析结果文本框
  • 底部:控制按钮和状态栏

🅿️ 任务三:智能停车系统

🎯 任务目标:实现精准的停车位识别与自动停车功能

复用现有框架

💡 实现提示:可复用任务一中的 YOLOv5s 检测框架,专门针对停车位进行优化,直接修改任务一逻辑中的追踪二维码->追踪车库即可。

更新计划:详细的实现代码和调试技巧将在后续更新中提供


⚡ 调度优化

🎯 核心价值:这是区别于其他参赛队伍的关键优势!
🏆 竞争意义:优秀的调度系统能至少将成绩控制进30s内

🚀 优化目标

优秀的任务调度系统能够实现:

优化维度 具体目标 预期效果
🔄 流畅切换 各任务间无缝过渡,减少等待时间 节省2-5秒切换时间
⚡ 性能最大化 充分平衡硬件平台算力 CPU合理分配避免进程互相抢占CPU
🛡️ 稳定可靠 提高系统整体鲁棒性 异常恢复时间<1秒
🧠 智能决策 根据环境动态调整策略 适应性提升100%

🔧 实现思路

核心思路是通过 ROS2 的节点管理和话题订阅机制,实现任务间的智能调度和资源分配。

具体实现:在每一个任务进行中,保证只运行必要的节点和话题,但是为了快速启动和响应不能关闭节点和话题,可以通过设置参数来控制节点的行为。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐