【概述】0 什么是智能系统

【阶段一】1 PlatformIO环境配置和GPIO

【阶段一】2 PWM与电机控制

【阶段一】3 外部中断和定时器中断

【阶段一】4 串口与串口中断

【阶段一】5 I2C与MPU6050模块

【阶段一】6 基础小车设计

【阶段二】7 智能系统概述

7.1 自动控制系统

7.1.1 什么是自动控制系统

自动控制是指在无人直接参与的情况下,利用控制器(或系统)使被控对象(或过程)按照给定规律(给定信号,输入信号)自动运行或保持状态不变。

自动控制的目的:

  • 通过自动控制减轻人的体力、脑力劳动强度;
  • 提高控制效率和控制精度;
  • 提高生产效率和产品质量;
  • 实现机器逐步替代人的智力,实现智能自动化。

我们期望在输入信号的作用下,让被控对象能快速、稳定、准确的按照预定的规律运行或保持不变。即在有干扰被控对象参数变化的不利情况下,控制作用仍能保持系统以允许的误差按预定的规律运行。

对于一个自动控制系统而言,我们希望通过稳定性、快速性、准确性三个维度去衡量其优劣。也就是要求被控对象在控制器的控制作用下,尽可能地快、稳、准地按照给定的规律运行。

然而在控制中存在一个矛盾问题:在自动控制系统中快速性、稳定性和准确性三者之间往往存在着矛盾,要快就难稳,要稳就难准。解决控制系统快稳准的问题是控制界面临的重要课题。

7.1.2 反馈控制

如图所示为控制系统的基本结构。下面以人类控制车辆运行速度为例进行讲解:

① 输入的期望状态:我希望车子运行速度为20km/h;

② 我需要获取被控对象当前的状态:例如车子此时的时速为17km/h;

③ 那么我需要获取”当前状态“与”期望状态“之间的差值,也就是误差,为17-20=-3km/h;

④ 人作为”控制器“,我需要根据误差的大小判断给出相应的控制量(也就是给多少油门);

⑤ 由于此时误差为为-3,则需要加大油门。

⑥ 重复①-⑤步。

可以看出,我们理想中的控制系统需要不断地根据被控对象的当前状态和期望状态进行比较,从而决定控制量的大小,也就是需要不断的比较输入和输出的差异→误差。这就是反馈控制

反馈控制:将输出反馈到输入一侧,并比较与输入的误差。设计一个以误差(包含误差的导数、积分)为变量的控制律,通过不断地负反馈作用,使输出与输入的误差不断减小,直到满足要求。

7.1.3 自动控制基本原理(PID算法)

如图所示为一个电加热炉,用于烧水。通过调整电阻丝两端的电压,我们可以调整加热功率。如果我们想将水温维持在一个给定的温度下。我们来看看如何控制它。

7.1.3.1 比例控制——主要满足对控制系统“快”的要求

水温,有它现在的『当前值』,也有我们期望的『目标值』

  • 当两者差距不大时,就让加热器“轻轻地”加热一下,也就是给较小的控制量(较低的电压)
  • 要是因为某些原因,温度降低了很多,就让加热器“稍稍用力”加热一下,也就是稍微加大一些控制量(稍微加大一点电压)
  • 要是当前温度比目标温度低得多,就让加热器“开足马力”加热,尽快让水温到达目标附近,也就是给较大的控制量(较大的电压)

也就是说,比例控制器的输出信号正比于系统误差,误差一旦出现,比例控制就会发生作用。那么控制量u(t)的大小由误差的大小决定。

kP越大,调节作用越激进,

kP调小会让调节作用更保守。

理想情况下,可以很快的将温度维持在指定温度。然而我们控制的对象是有惯性的——热惯性:拔掉加热器,余热将继续加温。

7.1.3.2 微分控制——主要满足对控制系统“稳”的要求

只有比例水温控制得晃晃悠悠,好像整个系统不是特别稳定,总是在“抖动”。

需要一个控制作用,让被控制的物理量的“变化速度”趋于0,即类似于“阻尼”的作用。

微分控制(D)的作用就是让物理量的速度趋于0,只要什么时候,这个量具有了速度,D就向相反的方向用力,尽力刹住这个变化。

微分对变化快的信号敏感,微分的作用是通过误差变化的变化率预报误差变化趋势。将微分环节引入反馈回路可改善系统动态特性。

微分控制不能单独使用,需要和比例控制一起使用,即PD控制

PD控制器能把水温控制的非常准吗?

7.1.3.3 积分控制——主要满足对控制系统“准”的要求

假设加热装置处于非常冷的地方,开始烧水了。需要烧到50℃。

在P的作用下,水温慢慢升高。直到升高到45℃时:天气太冷,水散热的速度,和P控制的加热的速度相等了。此时,比例控制和微分控制各自会怎样呢?

  • 比例环节:和目标温度只差5℃了,已经很近了,只需要轻轻加热就可以了。
  • 微分环节:加热功率和散热功率相等,温度没有波动,不用调整什么。

最终呈现出一个效果:水温永远地停留在45℃,永远到不了50℃

解决方案是继续增加加热功率,但问题是应该如何决定增加多少功率呢?

这就需要积分环节来完成了,设置一个积分量。只要偏差存在,就不断地对偏差进行积分(累加),并反应在调节力度上。在控制过程中对误差信号的积分产生积分控制作用,去消除系统的稳态误差,即使误差为零。由于积分控制作用,常值干扰信号不会影响系统的稳态特性。通常将积分控制与比例控制联合使用,即PI控制。

因此PID算法是将比例、微分、积分三个环节联合使用的算法。

7.2 智能控制系统

7.2.1 系统辨识(建模)

再次回到这个控制系统基本结构。如图所示,我们最重要控制的是让被控对象处于我们希望的状态上。也就是我们给被控对象一个输入(控制量),它会有一个输出(状态)。

因此,是否可以通过一个数学关系表述出控制量与被控对象状态之间的关系?

例如理想状态下,一个自行车的后轮转速可以由y=f(x)=kx表示。其中k为脚踏板齿轮与后轮的齿比;x为脚踏板输入的转速。如果我们想让后轮转速处于y1状态下,则可求f(x)的逆函数g(x)求得对应的x1。那么这个逆函数就是我们设计控制规律的依据。显然这是一个非常简单的系统,因为我们忽略了很多东西(例如摩擦、惯性等)。

对于更加复杂的系统我们可以通过其他方法建立起一个数学模型,这个过程被称为系统辨识(系统建模)

7.2.2 智能 系统辨识(建模)

然而对于一些非常复杂的系统,我们很难通过数学方式建立起显性的数学模型。而传统的控制理论(经典控制理论、现代控制理论)依赖被控对象的精确数学模型设计控制规律。此时我们可以基于智能控制理论设计控制系统。

由于复杂被控对象的逆函数g(x)难以建立,但是我们可以需求一个等价模型来代替。对于这样的被控对象,我们不再寻求建立其内部机理而是将其视为一个”黑箱“。

我们可以通过观测试验,建立起大量输入与输出之间的时序数据序列。利用神经网络具有逼近非线性函数的能力来模拟 g(·)。尽管 g(·)的形式未知,但根据系统的实际输出 y 与期望输出𝒚𝒅 之间的误差,通过神经网络学习算法调整神经网终联结权重直至误差趋近于0。

这样的过程就是神经网络逼近逆函数的过程,实际上是对被控对象的一种求逆过程。由神经网络的学习算法实现逼近被控对象逆模型的过程,就是神经网络实现直接控制的基本思想。

7.3 分级控制

对于大系统而言,由于系统内部复杂,且子系统众多,一般采用分级控制的结构。还是以人体为例,人的神经系统中有:

  • 下丘脑:有体温/水平衡的调节中枢,还与生物节律有关
  • 脑干:有许多维持生命的中枢,如呼吸中枢
  • 大脑皮层:调节机体活动的最高级中枢。例如:①对外部世界的感知②控制机体的反射活动③言语、学习、记忆和思维等方面的高级功能
  • 小脑:有维持身体平衡的中枢
  • 脊髓:调节躯体运动的低级中枢

它们各司其职分别管理不同的子系统,同时也有相互配合。例如,当我们要走路去一个地方时,由大脑皮层规划路线进行决策,由脊髓调节肢体的具体运动。

人的中枢神经系统是按多级递阶结构组织起来的,因此,多级递阶的控制结构已成为智能控制的一种典型结构。多级递阶智能控制的结构如图所示,按智能程度的高低分为组织级、协调级和控制级3级。

(1)组织级

组织级是递阶智能控制系统的最高级,是智能系统的“大脑”,它具有相应的学习能力和决策能力,对一系列随机输入的语句能够进行分析,能辨别控制情况以及在大致了解任务执行细节的情况下,组织任务,提出适当的控制模式。

(2)协调级

协调级是递阶智能控制系统的次高级,它的主要任务是协调各控制器的控制作用,或者协调各子任务的执行。这一级只要求较低的运算精度,但要有较高的决策能力,甚至具有一定的学习能力。

(3)控制级

控制级是系统的最低级,它直接控制局部过程并完成子任务。控制级和协调级相反,这一级必须高精度地执行局部任务,而不要求具有更多智能。

我们最后要做的智能小车就是基于分级结构设计的。其中:

  • 方向控制算法运行在电脑上,通过复杂的深度学习算法决策小车的前进方向。
  • 轮速控制算法运行在ESP32上,通过简单的PID算法实现。

7.4 模拟平台安装和基本使用

下载地址:Releases · tawnkramer/gym-donkeycar · GitHub

该地址中提供的模拟器是基于Unity开发的,是经过删减过后的可执行程序,不再需要额外安装unity,下载下来后就可以直接运行。目前覆盖windows、Linux、Mac共3个版本。本文为了简单教学,只讲解如何在windows平台上运行和使用该模拟器。

具体的,下载Windows平台对应的DonkeySimWin.zip压缩包,解压后内容如下所示:

双击运行其中的donkey_sim.exe即可启动模拟器。

主界面如下所示:

该模拟器中提供了很多不同的赛道,在模拟器左侧是相关设置,可以设置不同的视角等。这里我们选择最简单的赛道generated road,因为这个赛道没有障碍物且跟我们真实高速公路环境比较像,上手比较容易。我们先设置左侧的Settings如下:

注意我们设置了paceCar并且勾选了manualDriving,这样我们就可以自己手动操作小车了,不需要使用内置的自动驾驶模式。

接下来单击generated road,进入具体的场景:

在场景中,如果我们前面主界面使用了手工模式(paceCar处勾选manualDriving),那么我们就可以通过键盘来操控小车进行体验了。与一般的赛车游戏类似(qq飞车、跑跑卡丁车等),W键表示前进,A表示左转,D表示右转,S表示后退。

在该模拟器中,控制小车的主要是两个参数:油门(W和S键)和转向角度(A和D键),这个与我们真实驾驶的汽车基本一致:挂挡+踩油门来控制前进动力,打方向盘控制车辆转向。为了能够实现自动驾驶,我们首先要能够根据这两个参数去控制模拟器里面小车的运行。我们怎么样通过Python代码来控制这个模拟器呢?

这个模拟器的好处就在于预留了Python控制接口,我们只需要安装一个驱动库就可以直接驱动模拟器里面的小车运行(提前安装好Git工具):

pip install git+https://github.com/tawnkramer/gym-donkeycar

安装好以后我们可以运行下面的python代码来实现小车的控制(注意:运行下面的代码前先启动模拟器,并停留在模拟器主界面上):

# 导入库
import gym
import gym_donkeycar
import numpy as np
import cv2
 
 
# 设置模拟器环境
env = gym.make("donkey-generated-roads-v0")
 
# 重置当前场景
obv = env.reset()
 
# 运行100帧
for t in range(100):
    # 定义控制动作
    action = np.array([0.3,0.5]) # 动作控制,0.3表示转向,0.5表示油门
    # 执行动作
    obv, reward, done, info = env.step(action)
    # 取一张图像保存
    if t == 20:
        img = cv2.cvtColor(obv,cv2.COLOR_RGB2BGR)
        cv2.imwrite('test.jpg',img)
 
# 运行完以后重置当前场景
obv = env.reset()

我们先分析下这段代码。下面这行代码用于设置模拟器环境,简单来说就是启用哪张地图:

env = gym.make("donkey-generated-roads-v0")

在这个模拟器里面我们可以用到的地图如下所示:

"donkey-warehouse-v0"
"donkey-generated-roads-v0"
"donkey-avc-sparkfun-v0"
"donkey-generated-track-v0"
"donkey-roboracingleague-track-v0"
"donkey-waveshare-v0"
"donkey-minimonaco-track-v0"
"donkey-warren-track-v0"
"donkey-thunderhill-track-v0"
"donkey-circuit-launch-track-v0"

接下来的代码里面,我们运行了100帧,每帧都用固定的控制参数来执行:右转0.3、前进0.5。这两个字段就是我们前面提到的转向和油门值。下面给出这两个值的具体定义:

油门值取值范围是[-1,1],负值代表倒退,正值代表前进。转向值取值范围也是[-1,1],负值代表向左,正值代表向右。

接下来使用np.array封装这两个参数,然后通过env.step来执行单步动作。执行完动作以后会返回一些信息,其中我们需要重点关注obs这个返回参数,这个参数表示当前位于小车正中间行车记录仪摄像头返回的一帧图像 ,图像宽160像素,高120像素,3通道RGB图像。如下图所示:

由于本文主要使用摄像头图像数据来控制小车运行,因此上述代码中我们抽取了一张图像并保存到本地用来分析并测试算法。

通过上述代码,我们就可以使用python调整两个参数[油门值、转向值]来控制小车的运行,并且可以得到小车每次运行后的图像数据。实现了这样一个逻辑,我们自然就可以通过建立自动驾驶模型,逐帧分析图像,然后控制小车的这两个参数来实现小车的自动驾驶。

本小节内容重点使读者重新熟悉下python基本使用方法,同时熟悉下这个小车驾驶模拟器,接下来我们将正式进入自动驾驶算法研发环节。

Avatar photo

作者 skyate

发表回复