一、概述

1.1 为什么要仿真

搭建Gazebo仿真环境对于智能车比赛(特别是涉及视觉巡线、强化学习等算法开发)来说,不是可选项,而是最优解。以下是需要搭建仿真环境的核心理由,以及它能解决的实际问题。

1.1.1 硬件不足

问题:你现在没有久久派、摄像头、电机等硬件,但需要写程序、验证算法。

Gazebo的作用:

  • 提供虚拟的小车模型(带摄像头、激光雷达等传感器);
  • 提供虚拟的赛道环境(可以自定义颜色、形状、材质);
  • 程序写完后,直接在Gazebo里运行,效果等同于在真车上测试;

结果:硬件还没到,你的巡线算法已经跑通了。硬件一到,只需换底层驱动即可。

1.1.2 缩短调试周期
调试场景 真车调试 Gazebo仿真
修改PID参数 烧录→上电→跑一圈→观察→再烧录(5-10分钟/次) 改代码→保存→重启仿真(10秒/次)
小车撞墙 可能损坏硬件(电机、舵机、车架) 重置位置,继续调试
跑完一整圈 需要清场、充电、防止撞人 无限制运行,无人值守
测试极端情况 可能翻车、失控 完全安全

结论:仿真环境让的调试效率提升30-50倍。

1.1.3 提供可复现的测试环境

问题:真车测试时,光线变化、地面摩擦力、电池电量都会影响结果,今天跑通的代码明天可能就失效。

Gazebo的优势:

  • 每次启动都是完全相同的环境(相同的光照、相同的摩擦力、相同的传感器噪声);
  • 可以精确控制变量:比如只改变线条颜色,其他不变;
  • 算法性能变化只由代码改动引起,排除了环境干扰;

这对于调参、对比算法优劣至关重要。

1.1.4、支持强化学习训练

强化学习需要数百万次试错,这在真车上完全不可能:

训练需求 真车 Gazebo仿真
试错次数 几百次就报废 无限次
训练速度 1倍速 可以加速到10-100倍
并行训练 需要多台真车 开多个Gazebo实例
复位成本 手动搬回起点 代码一键复位

实例:训练一个简单的巡线RL模型,真车可能需要3个月+损坏5台车,仿真只需要1周+电费。

1.1.5、提前发现算法缺陷

仿真中可以轻松制造"事故场景":

  • 突然的强光照射(模拟阳光直射摄像头);
  • 赛道上有污渍(模拟线条部分缺失);
  • 传感器故障(模拟某个像素坏点);

这些在真车上很难刻意制造,但在仿真中可以随时开启。提前让你的算法适应这些情况,比赛时就不会翻车。

1.2 环境搭建步骤

走马观碑组Gazebo仿真环境搭建主要包含以下几个步骤:

① 环境准备(ubuntu + ROS2):这个可以参考《ROS2概述和基于RK3588的环境搭建》;

② 小车建模(URDF):有关URFD介绍可以参考《ROS2URDF建模》;

③ 赛道建模(World);

④ 视觉巡线算法开发。

1.2.1 工程目录简介

我们可以先创建工程目录,创建目录car_ws

zhengyang@ubuntu:~$ cd /opt/2k0300/loongson_2k300_lib
zhengyang@ubuntu:/opt/2k0300/loongson_2k300_lib$ mkdir -p car_ws/src
zhengyang@ubuntu:/opt/2k0300/loongson_2k300_lib$ cd car_ws/src

完整的目录结构大致如下,这个我们后续内容会依次创建:

car_ws/
├── src/
│   ├── car_description/      # 功能包1:机器人URDF模型
│   ├── car_gazebo/           # 功能包2:Gazebo仿真
│   └── car_vision/           # 功能包3:视觉算法

ROS的开发规范中,src/ 下的每个子目录叫功能包(Package),而不是独立项目。它们共同组成一个完整的机器人项目。

功能包 职责 修改频率
car_description 小车的物理模型(尺寸、颜色、传感器位置) 低(硬件确定后很少改)
car_gazebo 仿真环境、赛道、启动脚本 中(换赛道时需要改)
car_vision 图像处理、巡线算法 高(天天调参)
1.2.2 功能包关系

功能包之间的协作关系如下:

启动顺序:
1. car_gazebo 启动仿真世界,生成小车模型
   └── 调用 car_description 中的 car.urdf 描述小车长什么样

2. car_vision 订阅摄像头图像
   └── 处理图像 → 发布速度指令

3. car_gazebo 中的 Gazebo 接收速度指令
   └── 驱动仿真小车运动

二、小车建模

创建car_descriptionPython版本的功能包;

zhengyang@ubuntu:/opt/2k0300/loongson_2k300_lib/car_ws/src$ ros2 pkg create --build-type ament_python car_description

运行成功后,终端会显示创建的文件和目录信息。此时, car_description 功能包目录结构将如下所示:

zhengyang@ubuntu:/opt/2k0300/loongson_2k300_lib/car_ws/src$ tree ./car_description/
./car_description/
├── car_description  # 核心Python模块目录,用于存放Python代码
│   └── __init__.py
├── package.xml      # 功能包的描述文件(含依赖信息)
├── resource         # 资源文件夹
│   └── car_description
├── setup.cfg        # setuptools 的配置文件 
├── setup.py         # Python 包的安装脚本
└── test             # 测试文件夹

2.1 子目录

功能包创建好了,但按照规划我们需要在 car_description 中存放小车的URDF模型文件。这些不是.py文件,放在自动生成的 car_description 子目录下并不合适。

我们可以手动创建多个目录来更好地组织文件:

  • urdf: 专门存放 .urdf.xacro 模型文件;
  • launch:保存相关启动文件;
  • rviz:保存rviz的配置文件;
  • meshes:放置URDF中引用的模型渲染文件;
  • config: 存放Gazebo控制器的配置文件。

在终端中执行:

zhengyang@ubuntu:/opt/2k0300/loongson_2k300_lib/car_ws/src$ cd car_description/
zhengyang@ubuntu:/opt/2k0300/loongson_2k300_lib/car_ws/src/car_description$ mkdir urdf config launch rviz meshes

我们需要修改setup.py文件,添加配置文件:

import os
from glob import glob

    ...

    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
        (os.path.join('share', package_name, 'launch'), glob(os.path.join('launch', '*.launch.py'))),
        (os.path.join('share', package_name, 'urdf'), glob(os.path.join('urdf', '*.*'))),
        (os.path.join('share', package_name, 'urdf/sensors'), glob(os.path.join('urdf/sensors', '*.*'))),
        (os.path.join('share', package_name, 'meshes'), glob(os.path.join('meshes', '*.*'))),
        (os.path.join('share', package_name, 'rviz'), glob(os.path.join('rviz', '*.rviz'))),
        (os.path.join('share', package_name, 'config'), glob(os.path.join('config', '*.*'))),
    ],

    ...

2.2 模型文件

接下来就是编写一个完整的 car.xacro 文件,这个模型包含车身、三个轮子、摄像头传感器,并且配置了Gazebo仿真所需的插件;

首先进入 urdf 目录并创建文件:

zhengyang@ubuntu:/opt/2k0300/loongson_2k300_lib/car_ws/src/car_description$ cd urdf/
zhengyang@ubuntu:/opt/2k0300/loongson_2k300_lib/car_ws/src/car_description/urdf$ vim car.xacro

内容如下:

点击查看详情



  
  
  
  
  
  
  
  
  
      
  
  
  
  
    
   
  
  
  

  
  
  
  
  
  
  

  
  
    
  
  
  
    
  
  
  
    
  

  
    
  

  
    
  

  
  
    
      
      
        
      
      
    
    
      
      
        
      
    
    
      
      
      
    
  

  
  
    
    
    
    
  
  
  
    
      
      
        
      
      
    
    
      
      
        
      
    
    
      
      
      
    
  

  
  
    
    
    
    
  
  
  
    
      
      
        
      
      
    
    
      
      
        
      
    
    
      
      
      
    
  

  
  
    
    
    
      
  
  
  
    
      
      
        
      
      
    
    
      
      
        
      
    
    
      
      
      
    
  

  
  
    
    
    
  
  
  
    
      
      
        
      
      
    
  

  
  
    
    
    
  
  
  

  
  
  
  
    
      60.0
      
        1.0472
        
          160
          128
          R8G8B8
        
        
          0.05
          10.0
        
        
          gaussian
          0.0
          0.007
        
      
      
        /
        camera/image_raw
        camera_link
        0.07
      
    
  

  
  
    
      left_rear_wheel_joint
      right_rear_wheel_joint
      ${wheel_track}
      ${wheel_radius * 2}
      0.3
      cmd_vel
      odom
      odom
      base_link
      true
      false
      true
    
  


文件内容说明:

部分 作用
材质定义 定义蓝色车身、黑色轮胎、红色摄像头支架
车身尺寸 28x16cm(F车模实际尺寸)、轮距12cm、轮径3.2cm
三轮 后2驱动轮 + 前1万向轮(前部中心位置,球形从动轮)
摄像头传感器 160x128分辨率,60fps,发布到 /camera/image_raw 话题
差速驱动插件 接收 /cmd_vel 指令,控制小车运动

2.3 launch文件

launch文件夹下创建display.launch.py文件;

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch_ros.parameter_descriptions import ParameterValue
from launch_ros.actions import Node
from launch.substitutions import Command, LaunchConfiguration
from ament_index_python.packages import get_package_share_directory
import os

def generate_launch_description():
    # xacro 文件路径(注意扩展名是 .xacro)
    xacro_path = os.path.join(
        get_package_share_directory('car_description'),
        'urdf',
        'car.xacro'  # 关键:改为 .xacro
    )
    
    # 声明 model 参数
    model_arg = DeclareLaunchArgument(
        name='model',
        default_value=xacro_path,
        description='Absolute path to robot xacro file'
    )
    
    # 使用 xacro 命令解析 URDF
    robot_description = ParameterValue(
        Command(['xacro ', LaunchConfiguration('model')]),
        value_type=str
    )
    
    return LaunchDescription([
        model_arg,  # 必须包含这个声明
        
        # 机器人状态发布器
        Node(
            package='robot_state_publisher',
            executable='robot_state_publisher',
            output='screen',
            parameters=[{'robot_description': robot_description}]
        ),
        
        # 关节状态发布器 GUI(可手动拖动关节)
        Node(
            package='joint_state_publisher_gui',
            executable='joint_state_publisher_gui',
            name='joint_state_publisher_gui'
        ),
        
        # RViz2 可视化
        Node(
            package='rviz2',
            executable='rviz2',
            name='rviz2',
            arguments=['-d', os.path.join(get_package_share_directory('car_description'), 'rviz', 'car_display.rviz')],
	    	output='screen'
        )
    ])

这个Launch文件主要做三件事:

  • 加载机器人URDF模型(支持xacro格式);
  • 发布机器人的状态变换(TF);
  • rviz2中可视化机器人。
2.3.1 节点

脚本运行会创建以下几个节点:

  • joint_state_publisher_gui:发布每个joint(除fixed类型)的状态,可以通过UI界面对joint进行控制;
  • robot_state_publisher:将机器人各个linksjoints之间的关系,通过TF的形式,整理成三维姿态信息发布。
  • rviz2:在rviz2中可视化机器人;

joint_state_publisher这是一个官方ROS2包,主要功能:

  • 输入:
    • 读取URDF中的关节定义;
    • 接收用户或程序指定的关节角度;
  • 输出:
    • 发布 /joint_states 话题,消息类型为 sensor_msgs/msg/JointState
    • 包含所有关节的名称、位置、速度、力等信息。
2.3.2 数据流与节点关系

数据流与节点关系:

用户通过滑动条/GUI或程序 → joint_state_publisher_gui
                                     ↓ 发布/joint_states话题
                        robot_state_publisher
                                     ↓ 计算并发布TF变换
                              rviz2 和其他节点
                                     ↓ 接收TF并可视化

2.4 car_display.rviz

创建rviz配置文件,避免手动设置rviz,在rviz目录下新建car_display.rviz文件;

Panels:
  - Class: rviz_common/Displays
    Name: Displays
  - Class: rviz_common/Views
    Name: Views
Visualization Manager:
  Class: ""
  Displays:
    - Class: rviz_default_plugins/Grid
      Name: Grid
      Value: true
    - Alpha: 0.8
      Class: rviz_default_plugins/RobotModel
      Description Source: Topic
      Description Topic:
        Value: /robot_description
      Enabled: true
      Name: RobotModel
      Value: true
    - Class: rviz_default_plugins/TF
      Name: TF
      Value: true
  Global Options:
    Fixed Frame: base_link
    Frame Rate: 30
  Name: root
  Tools:
    - Class: rviz_default_plugins/MoveCamera
  Value: true
  Views:
    Current:
      Class: rviz_default_plugins/Orbit
      Distance: 1.7
      Name: Current View
      Pitch: 0.33
      Value: Orbit (rviz)
      Yaw: 5.5
Window Geometry:
  Height: 800
  Width: 1200

2.5 编译运行

2.4.1 编译

car_ws 目录下编译并检查:

zhengyang@ubuntu:~$ cd /opt/2k0300/loongson_2k300_lib/car_ws

zhengyang@ubuntu:/opt/2k0300/loongson_2k300_lib/car_ws$ colcon build --paths src/car_description
.....
Finished <<< car_description [0.92s]

zhengyang@ubuntu:/opt/2k0300/loongson_2k300_lib/car_ws$ source install/setup.sh
2.4.2 运行

启动终端,运行如下命令;

zhengyang@ubuntu:/opt/2k0300/loongson_2k300_lib/car_ws$ ros2 launch car_description display.launch.py

可以看到rviz窗口打开,并且显示了小车模型(蓝色车身、黑色轮子、红色摄像头支架);

三、赛道建模

四、视觉巡线算法


原文地址: https://www.cveoy.top/t/topic/qGlN 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录