【技术分享】一文带你完成20届智能车备赛

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

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

:clipboard: 目录


:bullseye: 前言

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

:books: 适用对象

:memo: 内容概览

本文涵盖:

  • :open_book: 比赛规则解读与理解
  • :automobile: 硬件平台选择与配置
  • :gear: ROS2环境搭建与调试
  • :chequered_flag: 三大任务详细实现方案
  • :high_voltage: 高级调度优化技巧

:light_bulb: 使用建议

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

:open_book: 比赛规则

:clipboard: 官方资料

:thinking: 个人规则理解

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

:memo: 规则要点总结

  • :person_running: 任务流程:巡线 → 避障 → 扫码 → 远程控制 → 停车
  • :stopwatch: 时间限制:单次任务完成时间有上限要求
  • :trophy: 评分标准:完成度、用时、稳定性综合评分
  • :warning: 安全要求:必须确保车辆和人员安全

:automobile: 车模要求与硬件平台

:warning: 重要注意事项

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

:wrench: 硬件配置对比

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

:bar_chart: 性能评价与选择建议

OriginCar (RDK X3)

  • :white_check_mark: 优势
    • 成本相对较低,适合预算有限的团队
    • 能完成所有比赛任务
    • 社区资源丰富,问题解决方便
  • :cross_mark: 劣势
    • 对算法优化要求较高
    • 多模型同时运行时可能出现性能瓶颈
    • 内存限制可能影响复杂算法部署

OriginCar Pro (RDK X5) :fire: 强烈推荐

  • :white_check_mark: 优势
    • 算力翻倍,AI模型运行更流畅
    • CPU和内存全面升级,多任务处理能力强
    • 深度相机提供额外的感知维度
    • 更好的散热设计,稳定性更高
  • :cross_mark: 劣势
    • 成本相对较高

:light_bulb: 选择建议

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

:gear: ROS包迁移

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

:hammer_and_wrench: 环境准备

在开始之前,请确保:

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

RDK X3 配置

:wrench: 基础环境配置

  1. :floppy_disk: 烧录系统镜像

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

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

  2. :globe_with_meridians: 网络配置

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

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

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

    :warning: 故障排除:截至 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
    

:package: 功能包迁移

  1. :building_construction: 创建工作空间并迁移功能包

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

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

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

    # 安装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. :hammer: 编译功能包

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

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

  4. :test_tube: 验证安装

    # 设置环境变量
    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
    

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


RDK X5 配置

:wrench: 基础环境配置

  1. :floppy_disk: 烧录系统镜像

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

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

  2. :globe_with_meridians: 网络配置

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

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

  3. :information_source: 系统信息检查

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

    # 更新系统组件
    sudo rdk-miniboot-update
    sudo apt update && sudo apt full-upgrade
    
    # 检查更新状态
    apt list --upgradable
    

:package: 功能包迁移

  1. :building_construction: 创建工作空间并迁移功能包

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

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

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

    # 安装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. :hammer: 编译功能包

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

    # 启动底盘节点
    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
    

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


:chequered_flag: 任务一:巡线避障扫码

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

任务一包含三个核心功能::motorway: 巡线 + :construction: 避障 + :mobile_phone: 扫码

:bullseye: 技术方案选择

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

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

:fire: 推荐方案二的理由

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

:light_bulb: 经验分享

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

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


Part 1: 巡线功能实现

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

:books: 推荐资源

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

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

:rocket: 快速部署

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/

:light_bulb: 备用方案

  • 若无法使用 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/

:white_check_mark: 编译状态判断

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

:gear: 节点配置优化

修改 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
   ])

:wrench: 摄像头和图像数据流配置

数据流分析:
赛道检测节点需要订阅 /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,
    ])

:magnifying_glass_tilted_left: 关键参数说明:

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

:bar_chart: 节点数据流图:

hobot_usb_cam ──(MJPEG)──> nv12_codec_node ──(NV12)──> racing_track_detection_resnet
       │                                                         │
       └──(MJPEG)──> web_node <──(检测结果)───────────────────────┘

:rocket: 启动与测试

分步启动命令:

# 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

:hammer_and_wrench: 常见问题与解决方案

问题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)
);

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

:bullseye: 测试验证

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

  • 摄像头实时图像
  • 赛道检测结果
  • 中心点坐标信息

:chart_increasing: 模型训练与优化

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

训练资源推荐:

模型部署流程:

  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界面观察检测效果
    • 记录模型推理时间和精度

:package: 获取控制功能包

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

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

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

:wrench: 编译与配置

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},     # 中心偏移阈值(像素)
]

:vertical_traffic_light: 系统启动流程

完整启动序列(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

:bullseye: 比赛用精简配置

为提高系统稳定性,比赛时建议关闭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,
    ])

:chart_increasing: 性能调优指南

实时监控命令:

# 查看话题发布频率
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 转向响应强度,过大易震荡

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

:construction: Part 2: 避障功能实现

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

:magnifying_glass_tilted_left: 避障系统原理

技术方案:

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

决策流程图:

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

:package: 获取避障检测包

克隆功能包:

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

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

编译安装:

cd ~/ros2_ws
colcon build --packages-select racing_obstacle_detection_yolo --symlink-install

:brain: 模型训练与部署

训练资源推荐

核心教程:

:wrench: 模型配置

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
    ])

:desktop_computer: 调试环境配置

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

创建 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,
    ])

:test_tube: 测试与验证

启动检测测试:

# 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
  • 无漏检或误检

:link: 集成启动配置

创建统一启动文件 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,  # 比赛时可注释掉
    ])

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

:brain: 智能避障控制算法

核心控制逻辑

在启动避障控制前,需要修改 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_);
    }
}

:wrench: 关键参数配置

修改参数文件位置: 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'
)

:bar_chart: 参数调优指南

参数名称 推荐范围 作用说明 调优技巧
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 避障转向强度 需要根据赛道调整

:light_bulb: 高级优化策略

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;
}

:rocket: 系统集成启动

完整避障系统启动序列:

# 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

:chart_increasing: 性能监控与调试

实时监控命令:

# 监控检测结果
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
  • 无频繁震荡现象
  • 能够顺利恢复巡线
  • 在不同光照条件下稳定工作

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

:mobile_phone: Part3:智能扫码系统

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

:wrench: 技术实现方案

总体思路

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

:bullseye: 核心技术流程
    A[摄像头图像] --> B[YOLOv5检测] --> C[检测到二维码] --> D[达到阈值] --> E[停车扫码] --> F[二维码解析] --> G[内容输出] --> H[任务完成]

:memo: 控制逻辑修改

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);
}

:books: 二维码解析实现

方案一:基于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()

:gear: 参数配置优化

关键参数设定

修改 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},                # 扫码后等待时间
]

:bullseye: 集成测试流程

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. 性能调优技巧

提高识别成功率:

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

优化响应速度:

  • 减小图像处理分辨率
  • 限制扫码区域大小
  • 使用异步处理

:bar_chart: 故障排除指南

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

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

:mobile_phone: 二维码扫描库推荐

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

  • :white_check_mark: 识别率高:对各种角度、光照条件适应性强
  • :white_check_mark: 性能优秀:针对移动设备优化,速度快
  • :white_check_mark: 易于集成: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

:books: 参考资源

:gear: 参数调优建议

关键参数

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

调试技巧

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

:video_game: 任务二:远程控制

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

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

:wrench: 硬件优化建议

网络性能提升

  • RDK X3 用户

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

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

:mobile_phone: 远程控制实现

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

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

技术架构

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

实现要点

  1. 图像采集发布

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

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

    • 通过 ROS2 话题机制实现双向通信
    • 低延迟的指令响应机制

方案二:ROS2节点级远程控制 :control_knobs:

技术架构

上位机界面 → 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 发布当前状态供上位机显示

:robot: 大模型图生文功能

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

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

云端推理方案(推荐)

技术流程

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

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

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

快速部署

  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
    • 返回图像的文字描述结果

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

:desktop_computer: 上位机调试环境

环境配置步骤:

  1. 安装 coStudio 客户端

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

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

界面布局建议:

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

:p_button: 任务三:智能停车系统

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

复用现有框架

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

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


:high_voltage: 调度优化

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

:rocket: 优化目标

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

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

:wrench: 实现思路

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

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

24 个赞

sos , origin car pro的哪个src功能包是在哪来的呀,下载的镜像里也没有,就是"5.迁移官方origincar功能包"那一步

/userdata/dev_ws/src

佬,X5的编译racing_track_detection_resnet 报错怎么解决

如何实现节点之间的订阅关系,我们现在已经创建好了摄像头的launch文件

你好,在智能车竞赛的老版本镜像里

你好,需要先学习一下ROS2基本内容 https://docs.ros.org/en/humble/

为什么用了障碍检测的功能包,yolo跑出来帧率非常的低,是哪里的问题?

可以自己查看具体耗时在哪一部分,目前X3默认只调用了一个BPU核

执行ros2 launch racing_track_detection_resnet racing_track_detection_resnet.launch.py时,显示Open config/race_track_detection.bin failed

仔细检查自己的配置文件 检查文件路径

参考 racing_vision_ai 文档这个打不开

正常的Github链接,请你先检查啊自己的网络配置能否访问Github

大佬,Web界面不显示检测框是什么原因

具体的log信息呢,可以自己ros2 topic echo 检测的信息,web_node没订阅对话题?

非常感谢,给我许多优化提速的方向 :two_hearts:

请问在配置图生文云端大模型时在小车终端运行python3 -c "import volcengine; print(‘SDK安装成功’)"后显示无volcengine,但是在上一步的pip时显示下载成功了是为什么

ros2包构建成功后,运行大模型节点并从上位机发出了对应信号值,其接收信号之后显示了成功订阅/image节点,但是不输出生成结果,云端大模型平台也无调用记录
root@ubuntu:~/y_ws# ros2 run racing_vision_ai vision_ai_node
[INFO] [1752326201.479195596] [vision_ai_node]: 成功加载配置文件: /root/y_ws/build/racing_vision_ai/config/vision_ai_config.yaml
[INFO] [1752326201.542515398] [vision_ai_node]: Volcengine Ark client initialized successfully
[INFO] [1752326201.554000601] [vision_ai_node]: Vision AI Node initialized
[INFO] [1752326201.557322902] [vision_ai_node]: Waiting for sign4return=11 signal…
[INFO] [1752326231.737332321] [vision_ai_node]: Received sign4return: 11
[INFO] [1752326231.740951118] [vision_ai_node]: Received trigger signal (sign4return=11), subscribing to image topic…
[INFO] [1752326231.757753837] [vision_ai_node]: Subscribed to /image topic

有大佬能帮忙解答一下吗

1 个赞

你好,可以检查一下自己的网络呢,目前修改config下的配置文件需要重新编译生效
,也可以在源码打印更多调试内容

你好 请问解决了么 我们也是这个情况 :smiling_face_with_tear: