基于遗传算法实现自动泊车+pygame可视化

一、 背景

我曾经使用遗传算法常用于解决旅行商问题,认为遗传算法解决问题的关键是对问题编码。看到了一篇有趣的技术博文【1】,介绍使用遗传算法(Genetic Algorithm, GA) 训练小车在模拟环境中实现自动泊车。尽管文章中对泊车问题编码的思路非常精彩,但是使用 Three.js 进行算法实现和可视化的,对后端选手不太友好😢。在复现的过程中,参考了博文【1】的算法思路,为了避免碰撞,优化了损失函数。本文使用python实现算法,并使用pygame库进行可视化,源码上传了git仓库(github.com/lcmchn/self...)。

二、 算法设计

首先要理解本算法设计的核心思想:

复制代码
自动泊车的本质是 "小车根据环境(障碍物)调整动作(行驶、转向),最终精准停靠目标车位"。本文用进化(遗传算法)的方式"训练"小车学会这一过程,而不是手动编写规则。

然后大家在阅读本文前思考几个问题,这是本文解决泊车任务的关键:

👀 感知(看):小车如何获取周围环境信息? 🤔 决策(想):如何根据环境信息生成动作指令? 📖 优化(学):如何让小车通过迭代 "学会" 最优决策逻辑?

为了解决上面三个问题,本文先对小车建模,然后利用遗传算法进化小车的"大脑"。下面分别介绍。

2.1 小车控制建模

为了简化模型,小车的动作被抽象为两个独立维度的信号,每个信号仅 3 种状态。小车每隔一定步长(本文为100ms)接收一次动作信号,然后执行。

2.1.1 发动机信号
-1 0 +1
倒车 静止 前进
2.1.2 方向盘信号
-1 0 +1
左转 直行 右转
2.1.3 8方位距离传感器

每辆小车拥有8个距离传感器,检测与障碍物的距离,使小车拥有感知周围环境的能力。每隔一定步长(本文为100ms)传感器输出 8 个浮点数(对应 8 个传感器的距离值),作为大脑决策系统的输入。当监测范围内(4m)无障碍物,传感器数值为0;当传感器数值很小但不为0,表示障碍物就在附近。

2.1.4 大脑决策系统

小车的大脑决策系统实现了由"感知"到"动作"的转换:距离传感器输入, 动作信号输出。本文算法通过一个简单的线性函数+信号转换建模:

  • 信号表达:
scss 复制代码
-->发动机信号
engineSignal = brainToMuscleSignal(
  (e0 * sensor0) + (e1 * sensor1) + ... + (e7 * sensor7) + ebias // <- brainFunction
)
​
-->方向盘信号
wheelSignal = brainToMuscleSignal(
  (w0 * sensor0) + (w1 * sensor1) + ... + (w7 * sensor7) + wbias // <- brainFunction
)
sensor[i]:小车周围8方位距离传感器,返回到障碍物的距离。
e[i]、ebias、w[i]、wbias:可学习的权重参数(即"基因")。
  • 信号转换函数:brainToMuscleSignal()函数实现"多项式输出→动作信号" 的映射。
scss 复制代码
-->sigmoid函数
将多项式输出的任意浮点数压缩到 (0,1) 区间(归一化)
​
-->阈值划分
(0, 0.1)→-1,(0.1, 0.9)→0,(0.9,1)→+1(通过 margin 参数控制阈值范围,-1\0+1就是需要的动作信号!!)
2.1.5 基因

每个个体(一辆小车)的"基因"就是其线性控制函数的所有权重和偏置(e0-e7、ebias、w0-w7、wbias 共 18 个系数):

  • 编码规则:系数为浮点数,用 10 位二进制表示(1 位符号位 + 4 位指数位 + 5 位尾数位,平衡精度与长度)。
  • 基因组长度:18 个系数 × 10 位 = 180 位(0/1 序列),确保 "遗传操作(交叉、变异)" 可高效执行。

2.2 利用遗传算法进化小车的"大脑"

为了得到优秀的基因(180位0/1 序列),解决自动泊车问题。本算法使用遗传算,模拟自然选择,迭代产生更优个体。下图为算法的关键步骤和流程。

2.2.2 关键步骤
遗传算法概念 泊车任务实现
个体(Individual) 一个小车基因组(180位0/1 序列)
种群(Population) 一代小车的集合(默认 1000 个个体)
适应度函数(Fitness Function) 基于 "车轮到车位角的平均距离" 计算:fitness = 1 / (loss + 1),其中 loss 是 4 个车轮到车位 4 个角的平均距离(距离越近,fitness 越高) 🔑 加入碰撞惩罚项:发生碰撞直接将适应度降至1%
选择(Selection) 加权随机选择:适应度越高的个体,被选中作为父母的概率越大;同时保留 10%"最优个体" 直接进入下一代(避免优质基因丢失)
交叉(Crossover) 均匀交叉:父母基因组的每一位以 50% 概率遗传给子女(模拟基因重组)
变异(Mutation) 随机变异:每个基因位以 4% 概率翻转(0→1 或 1→0,引入新基因多样性)
python 复制代码
    def car_fitness_from_loss(loss: float, has_collision: bool = False, is_loop: bool = False,
                              is_timeout: bool = False) -> float:
        """
        增强版适应度函数:
        - loss越小(离车位越近),适应度越高
        - 碰撞大幅惩罚适应度
        """
        base_fitness = 1.0 / (loss + 1e-6)
​
        # 惩罚项:碰撞/循环/超时直接将适应度降至1%
        if has_collision:
            base_fitness *= 0.01
​
        # 额外奖励:离车位足够近(<50像素)时翻倍奖励
        if loss < 50:
            print()
            base_fitness *= 2.0
​
        return 
2.2.3 算法流程
  1. 初始化种群(N 辆随机小车)。

  2. 对每辆车:

    • 在仿真环境中运行其控制策略。
    • 计算适应度(评价基因好坏)。
  3. 根据适应度选择、交叉、变异,生成新一代种群。

  4. 重复步骤 2--3,直到某代出现能成功泊车的小车,或达到最大代数。

三、结果可视化

初始代的小车的"基因"是随机的,完全没有自动泊车的能力:

遗传算法训练50代后,小车掌握了自动泊车的能力,基本能停靠在目标车位附近:

平均适应度随着迭代呈上升趋势,说明算法正在有效筛选优质基因,种群整体的泊车能力在持续提升。

四、总结与反思

虽然本文的算法不适合直接用于真实自动驾驶(训练的小车一路上有时会撞到别的车,而且停车位也停得不准确),但为理解机器学习、优化算法和机器人控制提供了起点。下面是针对本文算法的几点反思:

  • 当前使用线性控制器过于简单,难以泛化到不同车位布局或初始位置。
  • 若想提升性能,应改用多层感知机(MLP) 作为控制器(即神经网络)。
  • 当前策略倾向于"一直倒车找空位",缺乏复杂机动(如前进+后退配合)。

五、参考文献

dev.to/trekhleb/se...

相关推荐
4***17542 小时前
强化学习中的蒙特卡洛方法
python
pen-ai2 小时前
打通 Python 与 C++ 的参数传递机制
开发语言·c++·python
至此流年莫相忘2 小时前
Python之深拷贝和浅拷贝
python
像风一样自由20202 小时前
XGBoost、LightGBM、CatBoost 原理深度剖析与全面对比
python
用户230826676652 小时前
Python的管道符(|)联合类型语法糖
python
东木月2 小时前
使用python获取Windows产品标签
开发语言·windows·python
AIFQuant2 小时前
2026 越南证券交易所(VN30, HOSE)API 接口指南
大数据·后端·python·金融·restful
dagouaofei3 小时前
AI 生成 2026 年工作计划 PPT,模板与结构能力对比
人工智能·python·powerpoint
木头左3 小时前
波动率期限结构调整策略在指数期权日历价差中的应用研究
python