卡尔曼滤波和角度测定
- 格式:doc
- 大小:471.50 KB
- 文档页数:11
倾角卡尔曼滤波-概述说明以及解释1.引言1.1 概述倾角卡尔曼滤波是一种用于测量倾角的方法,它结合了倾角测量与卡尔曼滤波原理。
倾角的测量在许多领域中都是非常重要的,例如航空航天、导航系统以及工业自动化等。
倾角的准确测量可以帮助我们判断物体的姿态、稳定性以及对周围环境做出合适的调整。
然而,由于当前倾角传感器本身存在一定的误差和干扰,因此需要采用合适的滤波算法来对倾角进行精确估计和校正。
在这方面,倾角卡尔曼滤波是一种被广泛应用的方法。
倾角卡尔曼滤波算法基于卡尔曼滤波原理,通过对倾角的测量数据进行预测和更新,以得到更加准确、稳定的倾角估计值。
它利用了传感器测量数据的统计特性和系统模型的动态特性,通过权衡预测值和测量值的不确定性来对倾角进行优化估计。
相比其他滤波算法,倾角卡尔曼滤波具有以下优势:首先,它能够有效地抑制传感器数据中的噪声和干扰,并能够适应不同程度的噪声;其次,它具有较高的估计精度和稳定性,能够准确地跟踪目标物体的倾角变化;最后,倾角卡尔曼滤波算法具有较快的收敛速度和较低的计算复杂度,适用于实时应用场景。
未来,倾角卡尔曼滤波在自动化控制、导航系统等领域具有广阔的应用前景。
随着技术的不断进步和创新,倾角卡尔曼滤波算法将更加成熟和精确,为各行各业提供更加可靠和准确的倾角测量方法。
同时,倾角卡尔曼滤波的应用也将得到进一步的拓展,为我们创造更多便利和可能性。
1.2 文章结构文章结构部分的内容如下:文章结构部分的目的是为了向读者介绍本文的大致结构和内容安排。
本文将按照以下方式进行组织和撰写:第一部分是引言,主要包括概述、文章结构和目的三个小节。
在概述部分,会简要介绍倾角卡尔曼滤波的背景和重要性,引起读者的兴趣。
在文章结构部分,将详细说明本文的结构安排,以便读者能够清楚地了解整篇文章的内容。
在目的部分,将明确本文的目标和意义,为读者提供一个阅读的导向。
第二部分是正文,主要包括倾角测量方法和卡尔曼滤波原理两个小节。
陀螺仪卡尔曼滤波算法1. 引言陀螺仪是一种用于测量角速度的传感器,广泛应用于惯性导航、无人机控制、姿态估计等领域。
然而,由于传感器噪声和误差的存在,陀螺仪输出的数据往往不够稳定和准确。
为了解决这个问题,人们提出了许多滤波算法,其中最常用且效果良好的就是卡尔曼滤波算法。
本文将介绍陀螺仪卡尔曼滤波算法的原理、实现过程以及应用场景,并对其优缺点进行讨论。
2. 陀螺仪陀螺仪是一种基于角动量守恒原理工作的传感器。
它通常由一个旋转部件和一个测量部件组成。
旋转部件可以是一个旋转的轴或者一个旋转的盘片,当外界施加力矩时,旋转部件会发生相应的转动。
测量部件通过测量旋转部件的角速度来获取外界施加力矩的信息。
陀螺仪输出的数据通常是角速度,单位为弧度/秒。
然而,由于制造工艺和环境因素的限制,陀螺仪的输出往往存在噪声和误差。
这些噪声和误差会对应用场景中的姿态估计、运动控制等任务产生不利影响。
3. 卡尔曼滤波算法卡尔曼滤波算法是一种递归滤波算法,通过利用系统模型和观测数据,对状态进行估计和预测。
它在估计过程中综合考虑了系统模型的预测值和观测数据的测量值,并通过最小均方误差准则来优化估计结果。
陀螺仪卡尔曼滤波算法主要包括以下几个步骤:3.1 状态空间模型首先,需要建立一个状态空间模型来描述陀螺仪系统。
状态空间模型通常由状态方程和观测方程组成。
状态方程描述了系统的演化规律,可以表示为:x(k) = F * x(k-1) + B * u(k-1) + w(k-1)其中,x(k)表示时刻k的系统状态,F是状态转移矩阵,B是控制输入矩阵,u(k)是控制输入,w(k)是过程噪声。
观测方程描述了系统的输出与状态之间的关系,可以表示为:z(k) = H * x(k) + v(k)其中,z(k)表示时刻k的观测值,H是观测矩阵,v(k)是观测噪声。
3.2 初始化在开始滤波之前,需要对滤波器进行初始化。
通常情况下,可以将初始状态和协方差矩阵设置为零向量和单位矩阵。
卡尔曼滤波器的状态方程和测量方程
卡尔曼滤波器的状态方程和测量方程如下:
状态方程:X(k)=AX(k-1)+Bu(k-1)+W(k-1)。
其中,X(k)表示k时刻的状态向量,A是状态转移矩阵,u(k-1)是k-1时刻的控制输入向量,B是控制输入矩阵,W(k-1)是k-1时刻的噪声向量。
测量方程:Z(k)=HX(k)+V(k)。
其中,Z(k)表示k时刻的测量向量,H是测量矩阵,V(k)是k时刻的测量噪声向量。
卡尔曼滤波器的目的是通过综合测量值和预测值得到一个最优值,它采用分配权重的方式来综合结果。
具体来说,它通过状态方程来预测下一个结果,然后通过测量方程来矫正预测结果,从而得到最优值。
MPU6050使⽤⼀阶互补和卡尔曼滤波算法平滑⾓度数据最近项⽬上想⽤MPU6050来⾃动探测物体的转向⾓度,花了2天时间学习如何拿陀螺仪的姿态⾓度,发现蛮难的,写点笔记。
下⾯是哔哩哔哩的⼀堆废话讲解,只想看代码本体的可以直接跳到最后。
应⽤场景是51单⽚机环境,有⼀块MPU6060,需要知道硬件板⼦⽔平摆放时,板⼦摆放的姿态和旋转的⾓度。
编译环境只能⽤C语⾔。
⾸先单⽚机通过TTL串⼝接到MPU6050上拿到通信数据,⽔平旋转⾓度需要另外加地磁仪通过南北极磁性拿到。
很遗憾设计硬件时没注意这茬,只⽤了⼀块MPU6050。
不过呢可以⽤旋转时的⾓速度求出旋转幅度(这个下篇说)。
但是拿到原始数据后,发现原始数据的跳动⾮常厉害,需要⽤带滤波的积分算法平滑过滤。
代码演⽰了计算Roll,Pitch⾓和Yaw⾓并⽤卡尔曼过滤算法。
样例⾥⾯有四种芯⽚的演⽰,我⽤的是MPU6050,就直接看这个⽬录了,⾥⾯还有MPU6050+HMC5883L磁⼒计的样式,可惜⼿头板⼦当初没有想过算Yaw⾓旋转要磁⼒计,也就莫法实现读取Yaw⾓。
加HMC5883L磁⼒计的那个样例,是读的磁⼒计的数据来算Yaw轴⾓度。
MPU6050的重⼒加速度出来的z轴数据基本不咋变化,仅依靠x和y轴数据肯定不准的,所以这⾥通过重⼒加速度算出来Yaw轴的⾓度⽆意义。
继续回来说代码。
下载回来的样例代码扩展名是.ino,搞不懂啥,改成.c,⼀样看,c语⾔万岁!⾸先要先拿到陀螺仪的数据,⾓速度和重⼒加速度。
如何读取MPU6050的数据我略过。
⽹上有很多现成的样例,直接拿来⽤。
/* IMU Data */float accX, accY, accZ;float gyroX, gyroY, gyroZ;accX = ((i2cData[0] << 8) | i2cData[1]);accY = ((i2cData[2] << 8) | i2cData[3]);accZ = ((i2cData[4] << 8) | i2cData[5]);//tempRaw = (i2cData[6] << 8) | i2cData[7];gyroX = (i2cData[8] << 8) | i2cData[9];gyroY = (i2cData[10] << 8) | i2cData[11];gyroZ = (i2cData[12] << 8) | i2cData[13];i2cData是MPU6050读到的14个字节的数据。
卡尔曼滤波:以陀螺仪测量的角速度作为预测值的控制量,加速度传感器测量的角度作为观测值。
下面程序中angle_m为测量角度,gyro_m为测量角速度,gyro_m*dt为控制量。
以下程序是按卡尔曼滤波的五个公式来编写的。
X(k|k-1)=A X(k-1|k-1)+B U(k) (1)P(k|k-1)=A P(k-1|k-1) A’+Q (2)X(k|k)= X(k|k-1)+Kg(k) (Z(k)-H X(k|k-1)) (3)Kg(k)= P(k|k-1) H’ / (H P(k|k-1) H’ + R) (4)P(k|k)=(I-Kg(k) H)P(k|k-1) (5)对于单输入单输出系统,A、B、H、I不为矩阵且值都为1。
卡尔曼滤波参数的调整:其参数有三个,p0是初始化最优角度估计的协方差(初始化最优角度估计可设为零),它是一个初值。
Q是预测值的协方差,R是测量值的协方差。
对Q和R的设定只需记住,Q/(Q+R)的值就是卡尔曼增益的收敛值,比如其值为0.2,那么卡尔曼增益会向0.2收敛(对于0.2的含义解释一下,比如预测角度值是5度,角度测量值是10度,那么最优化角度为:5+0.2*(10-5)=6。
从这里可以看出,卡尔曼增益越小,说明预测值越可靠,最优化角度越接近预测值;相反的,卡尔曼增益越大,说明测量值越可靠,最优化角度越接近测量值)。
p0/(Q+R)反映收敛的快慢程度,该值设定越小,收敛越快,该值越大,收敛越慢(这里的p0是指初始最优角度值的协方差),因为卡尔曼增益收敛总的来说是很快的,所以该值设定大一点或小一点都没什么关系。
注:以下程序只用于说明算法,存在语法错误,初始的参数也是随意给定的。
x=0;/* 最优角度初值*/p=1;/* 最优角度对应协方差初值*/dt=0.02;Q=0.0025;R=0.25;void Kalman_Filter(float angle_m,float gyro_m) //gyro_m:gyro_measure{x=x+gyro_m*dt; 等号右边的x表示上一次最优角度值,等号左边的x表示这一次的角度的预测值p=p+Q; 等号右边的p表示上一次最优角度值的协方差,等号左边的p表示这一次的角度预测值的协方差k=p/(p+R); k值为卡尔曼增益(k值每次计算都不一样,它会越来越趋近于Q/(Q+R)这个收敛值)x=x+k*(angle_m-x); 等号左边的x表示根据预测值和测量值计算出来的这一次的最优角度值(从这里可以看出,k越大,等号左边的最优值x与等号右边的测量值angle_m越接近;k越小,等号左边的最优值x与等号右边的预测值x越接近;)p=(1-k)*p; 等号左边的p表示这一次最优角度值的协方差}从上面的程序可以看出,卡尔曼滤波是一个递推过程,初始的最优角度值可设为x=0,初始最优角度值的协方差p一定不能设为零,dt是采样周期,Q与R可共同决定卡尔曼增益收敛的大小。
小车下面就是 L3G4200D + ADXL345 两个模块,加速度模块没固定好,板子太小了没地方打孔,有时间将两个模块焊到一个万能板上应该会容易固定一些。
加速度模块角度计算:如果传感器x 轴朝下,y 轴朝前那竖直方向弧度计算公式为:angle = atan2(y, z) //结果以弧度表示并介于-pi 到pi 之间(不包括-pi)如果要换算成具体角度:angle = atan2(y, z) * (180/3.14)陀螺仪角度计算:式中angle(n)为陀螺仪采样到第n次的角度值;angle(n-1)为陀螺仪第n-1次采样时的角度值;gyron为陀螺仪的第n次采样得到的瞬时角速率值;dt为运行一遍所用时间;angle_n += gyro(n) * dt //积分计算卡尔曼滤波网上找的kalman滤波,具体代码如下static const float dt = 0.02;static float P[2][2] = {{ 1, 0 }, { 0, 1 }};float angle;float q_bias; //偏心、倾向于float rate; //比率static const float R_angle = 0.5 ; //R倾角static const float Q_angle = 0.001; //Q倾角static const float Q_gyro = 0.003; //Q陀螺仪float stateUpdate(const float gyro_m){ /*状态更新*/float q;float Pdot[4];q = gyro_m - q_bias;Pdot[0] = Q_angle - P[0][1] - P[1][0]; /* 0,0 */ Pdot[1] = - P[1][1]; /* 0,1 */Pdot[2] = - P[1][1]; /* 1,0 */Pdot[3] = Q_gyro; /* 1,1 */rate = q;angle += q * dt;P[0][0] += Pdot[0] * dt;P[0][1] += Pdot[1] * dt;P[1][0] += Pdot[2] * dt;P[1][1] += Pdot[3] * dt;return angle;}float kalmanUpdate(const float incAngle){float angle_m = incAngle;float angle_err = angle_m - angle;float h_0 = 1;const float PHt_0 = h_0*P[0][0]; /* + h_1*P[0][1] = 0*/ const float PHt_1 = h_0*P[1][0]; /* + h_1*P[1][1] = 0*/float E = R_angle +(h_0 * PHt_0);float K_0 = PHt_0 / E;float K_1 = PHt_1 / E;float Y_0 = PHt_0; /*h_0 * P[0][0]*/float Y_1 = h_0 * P[0][1];P[0][0] -= K_0 * Y_0;P[0][1] -= K_0 * Y_1;P[1][0] -= K_1 * Y_0;P[1][1] -= K_1 * Y_1;angle += K_0 * angle_err;q_bias += K_1 * angle_err;return angle;复制代码}波形显示测试说明——单片机采集加速度和陀螺仪的信号,并使用上面的kalman滤波,计算出最优倾角,通过串口发送到pc机,pc机运行的串口示波器将相关波形显示出来。
数字信号处理实验报告姓名: 专业: 通信与信息系统 学号: 日期:2015.11实验内容任务一:一连续平稳的随机信号()t x ,自相关函数()tx er -=τ,信号()t x 为加性噪声所干扰,噪声是白噪声,测量值的离散值()k z 为已知,s T s 02.0=,-3.2,-0.8,-14,-16,-17,-18,-3.3,-2.4,-18,-0.3,-0.4,-0.8,-19,-2.0,-1.2,-11,-14,-0.9,-0.8,10,0.2,0.5,-0.5,2.4,-0.5,0.5,-13,0.5,10,-12,0.5,-0.6,-15,-0.7,15,0.5,-0.7,-2.0,-19,-17,-11,-14,自编卡尔曼滤波递推程序,估计信号()t x 的波形。
任务二:设计一维纳滤波器。
(1)产生三组观测数据:首先根据()()()n w n as n s +-=1产生信号()n s ,将其加噪(信噪比分别为20dB ,10dB ,6dB ),得到观测数据() n x 1,() n x 2,() n x 3。
(2)估计() n x i , 1=i ,2,3的AR 模型参数。
假设信号长度为L ,AR 模型阶数为N ,分析实验结果,并讨论改变L ,N 对实验结果的影响。
实验任务一 1. 卡尔曼滤波原理1.1 卡尔曼滤波简介早在20世纪40年代,开始有人用状态变量模型来研究随机过程,到60年代初,由于空间技术的发展,为了解决对非平稳、多输入输出随机序列的估计问题,卡尔曼提出了递推最优估计理论。
它用状态空间法描述系统,由状态方程和量测方程所组成,即知道前一个状态的估计值和最近一个观测数据,采用递推的算法估计当前的状态值。
由于卡尔曼滤波采用递推法,适合于计算机处理,并且可以用来处理多维和非平稳随机信号,现已广泛应用于很多领域,并取得了很好的结果。
卡尔曼滤波一经出现,就受到人们的很大重视,并 在实践中不断丰富和完善,其中一个成功的应用是设计运载体的高精度组合导航系统。
2015.12.12void Kalman_Filter(float Gyro,float Accel){Angle+=(Gyro - Q_bias) * dt;Pdot[0]=Q_angle - PP[0][1] - PP[1][0];Pdot[1]= - PP[1][1];Pdot[2]= - PP[1][1];Pdot[3]=Q_gyro;PP[0][0] += Pdot[0] * dt;PP[0][1] += Pdot[1] * dt;PP[1][0] += Pdot[2] * dt;PP[1][1] += Pdot[3] * dt;Angle_err = Accel - Angle;PCt_0 = C_0 * PP[0][0];PCt_1 = C_0 * PP[1][0];E = R_angle + C_0 * PCt_0;K_0 = PCt_0 / E;K_1 = PCt_1 / E;t_0 = PCt_0;t_1 = C_0 * PP[0][1];PP[0][0] -= K_0 * t_0;PP[0][1] -= K_0 * t_1;PP[1][0] -= K_1 * t_0;PP[1][1] -= K_1 * t_1;Angle += K_0 * Angle_err;Q_bias += K_1 * Angle_err;Gyro_x = Gyro - Q_bias;}首先是卡尔曼滤波的5个方程:(|1)(1|1)()X k k AX k k Bu k -=--+(1)先验估计(|1)(1|1)'P k k AP k k A Q -=--+(2)协方差矩阵的预测 ()(|1)'/(|1)')Kg k P k k H HP k k H R =--+(3)计算卡尔曼增益(|)(|1)()(()(|1))X k k X k k Kg k Z k HX k k =-+--(4)进行修正5个式子比较抽象,现在直接用实例来说:一、卡尔曼滤波第一个式子对于角度来说,我们认为此时的角度可以近似认为是上一时刻的角度值加上上一时刻陀螺仪测得的角加速度值乘以时间,因为d dt θω=⨯,角度微分等于时间的微分乘以角速度。
卡尔曼滤波一、卡尔曼滤波的起源谈到信号的分析与处理,就离不开滤波两个字。
通常,信号的频谱处于有限的频率范围内,而噪声的频谱则散布在很广的频率范围内,为了消除噪声,可以把FIR滤波器或者IIR滤波器设计成合适的频带滤波器,进行频域滤波。
但在许多应用场合,需要直接进行时域滤波,从带噪声的信号中提取有用信号。
虽然这样的过程其实也算是对信号的滤波,但其所依据的理论,即针对随机信号的估计理论,是自成体系的.人们对于随机信号干扰下的有用信号不能“确知”,只能“估计”.为了“估计",要事先确定某种准则以评定估计的好坏程度.最小均方误差是一种常用的比较简单的经典准则。
对于平稳时间序列的最小均方误差估计的第一个明确解是维纳在1942年2月首先给出的.当时美国的一个战争研究团体发表了一个秘密文件,其中就包括维纳关于滤波问题的研究工作,这项研究是用于防空火力控制系统的.维纳滤波器是基于最小均方误差准则的估计器。
为了寻求维纳滤波器的冲激响应,需要求解著名的维纳–霍夫方程。
这种滤波理论所求的是使均方误差最小的系统最佳冲激响应的明确表达式。
从维纳–霍夫方程来看,维纳滤波算法是十分低效的。
这种算法要求设置大量的存储器来保存过去的测量数据,一个新的数据到来后,要进行刷新,重新计算自相关和互相关序列。
再者,求解这个方程需要耗费大量时间对高阶矩阵求逆。
因此,维纳滤波算法难以运用于实时处理中,尤其是无法用于军事、航空航天等领域。
为此,许多科技工作者进行了多方探索,但在解决非平稳过程的滤波问题时,能给出的方法很少。
到20世纪50年代中期,随着空间技术的发展,要求对卫星轨道进行精确地测量,这种方法越来越不能满足实际应用的需要。
为此,人们将滤波问题以微分方程表示,提出了一系列适应空间技术应用的精炼算法。
1960年和1961年,卡尔曼(R. E. Kalman)和布西(R. S。
Bucy)提出了递推滤波算法,成功的将状态变量引入到滤波理论中来,用消息与干扰的状态空间模型代替了通常用来描述它们的协方差函数,将状态空间描述与离散数间刷新联系起来,适于计算机直接进行计算,而不是去寻求滤波器冲激响应的明确公式。
惯性数据测量——卡尔曼滤波介绍对于大多数人来说,卡尔曼滤波很难理解。
的确,他奇迹般地解决了其他方法很难解决的问题。
但是注意,卡尔曼滤波并不是解决你所有问题万能的良方。
这篇文章将阐述卡尔曼滤波的使用。
我们将使用多的实际方法而避免那些很难理解的繁琐理论,因为大多数人仅仅将其用于MAV/UAV(微型飞行器/无人机)应用上,我将试图将它形象具体化。
必须确保你已经知道了怎样使用加速度计和陀螺仪来进行数据采集,另外,一些基础的代数知识也是必要的。
基本操作卡尔曼滤波是一种链形滤波器(累接滤波器),他需要两个东西:首先,你将需要几种输入(一路或更多的数据源),你可以仅仅使用线性计算将他们转换为你预期的输出。
换句话说,在我们的问题中,我们需要建立一个线性模型。
其次,你需要另一路输入。
这一路是期望数据中的实际外界数据值,或者是它的近似。
每一次迭代,卡尔曼滤波器都将微小地改变线性模型中的变量,因此线性模型的输出将于第二次输入接近。
简化模型显然,两路输入包含陀螺仪和加速度计的数据。
使用陀螺仪数据模型看起来像这样:第一个公式展示了一个线性模型的一般形式。
我们需要在B矩阵中“填入”A矩阵,然后选择一个状态x。
变量_u_k代表输入。
对我们来说,这就是陀螺仪的数据。
记住,怎样去积分?我们只是对归一化的数据进行求和:alpha k = alpha k-1 + (_u_ k –bias)我们需要再两个测量(_dt_)之间加入时间参数,因为我们要处理角速度(degrees/s): alpha k = alpha k-1 + (_u_ k –bias) * dt重写如下:alpha k = alpha k-1 –bias * dt + u k * dt上式在矩阵乘法中我将用到。
注意bias保持恒定!在个别陀螺仪中,我们看到了bias 的漂移。
接下来就是卡尔曼的神奇之处了:滤波器通过将加速度计的输出和结果进行比较调整每次迭代的bias。
小车下面就是 L3G4200D + ADXL345 两个模块,加速度模块没固定好,板子太小了没地方打孔,有时间将两个模块焊到一个万能板上应该会容易固定一些。
加速度模块角度计算:如果传感器x 轴朝下,y 轴朝前那竖直方向弧度计算公式为:angle = atan2(y, z) //结果以弧度表示并介于-pi 到pi 之间(不包括-pi)如果要换算成具体角度:angle = atan2(y, z) * (180/3.14)陀螺仪角度计算:式中angle(n)为陀螺仪采样到第n次的角度值;angle(n-1)为陀螺仪第n-1次采样时的角度值;gyron为陀螺仪的第n次采样得到的瞬时角速率值;dt为运行一遍所用时间;angle_n += gyro(n) * dt //积分计算卡尔曼滤波网上找的kalman滤波,具体代码如下static const float dt = 0.02;static float P[2][2] = {{ 1, 0 }, { 0, 1 }};float angle;float q_bias; //偏心、倾向于float rate; //比率static const float R_angle = 0.5 ; //R倾角static const float Q_angle = 0.001; //Q倾角static const float Q_gyro = 0.003; //Q陀螺仪float stateUpdate(const float gyro_m){ /*状态更新*/float q;float Pdot[4];q = gyro_m - q_bias;Pdot[0] = Q_angle - P[0][1] - P[1][0]; /* 0,0 */ Pdot[1] = - P[1][1]; /* 0,1 */Pdot[2] = - P[1][1]; /* 1,0 */Pdot[3] = Q_gyro; /* 1,1 */rate = q;angle += q * dt;P[0][0] += Pdot[0] * dt;P[0][1] += Pdot[1] * dt;P[1][0] += Pdot[2] * dt;P[1][1] += Pdot[3] * dt;return angle;}float kalmanUpdate(const float incAngle){float angle_m = incAngle;float angle_err = angle_m - angle;float h_0 = 1;const float PHt_0 = h_0*P[0][0]; /* + h_1*P[0][1] = 0*/ const float PHt_1 = h_0*P[1][0]; /* + h_1*P[1][1] = 0*/float E = R_angle +(h_0 * PHt_0);float K_0 = PHt_0 / E;float K_1 = PHt_1 / E;float Y_0 = PHt_0; /*h_0 * P[0][0]*/float Y_1 = h_0 * P[0][1];P[0][0] -= K_0 * Y_0;P[0][1] -= K_0 * Y_1;P[1][0] -= K_1 * Y_0;P[1][1] -= K_1 * Y_1;angle += K_0 * angle_err;q_bias += K_1 * angle_err;return angle;复制代码}波形显示测试说明——单片机采集加速度和陀螺仪的信号,并使用上面的kalman滤波,计算出最优倾角,通过串口发送到pc机,pc机运行的串口示波器将相关波形显示出来。
1、蓝色为加速度换算后的角度。
2、黄色为陀螺仪直接积分后的角度。
3、红色为kalman滤波后的角度。
用手指敲小车可以看到加速度模块计算获取的角度震动比较厉害,经过卡尔曼滤波后的波形相对平缓一些。
局部放大看一下曲线还是很优美的哦,哈。
波形显示用了园子里xf_z1988的开源波形控件,他的主页是:/xf_z1988/Relax Blog第二个Arduino小车两轮自平衡自从做了第一个Arduino小车兴趣大增,于是开始制作第二个Arduino小车,这次我想做得相对复杂一点。
一直对SEGWAY非常着迷,查了些技术资料发现自平衡小车的原理也比较简单:利用陀螺仪和加速度模块获得小车角度,Arduino对获取的数据进行处理,然后控制电机运转纠正倾斜,从而达到平衡的效果。
先来个视频:需要准备的硬件有:1、陀螺仪我选用的是L3G4200D三轴陀螺仪,其实自平衡小车只用到其中的一轴2、加速度计我用的是ADXL345三轴加速度计,自平衡小车也只用到其中两轴3、Arduino板子我用的是我使用的是arduino duemilanove 2009 arduino硬件区别请看这里:/en/Main/Hardware4、L298N电机驱动模块一个需要带光耦5、直流减速电机两个小车轮胎两个塑料盒子一个还需要一些杜邦线、电池、螺丝等辅助的东西有朋友问我这些东西哪里能买到,其实这些材料拜一下淘宝大神就能找到的。
组装过程比较简单,在塑料盒合适的位置打孔,然后用螺丝固定住电路板和电机即可:制作之前我们需要对陀螺仪+ 加速度计进行测试,看我们获取的角度数据是否满足要求。
网上常用的方法是使用卡尔曼滤波将陀螺仪和加速度计的数据进行融合而得到一个相对稳定正确的角度值,具体方法在我前面的文章中提到过:L3G4200D + ADXL345 卡尔曼滤波获取到角度以后需要找到小车的平衡点,也就是无外力作用的时候小车能够立在地面上的角度:角度差= 小车角度- 平衡点角度。
用小车角度数据结合当前的倾斜目标值,通过PID运算,得出电机PWM脉宽数据,指挥电机运行即可。
PID算法相对比较简单,而且arduino有现成的PIDlibraries : /playground/Code/PIDLibraryPID::PID(double* Input, double* Output, double* Setpoint,double Kp, double Ki, double Kd, int ControllerDirection){PID::SetOutputLimits(0, 255); //default output limit corr esponds to//the arduino pwm limitsSampleTime = 100; //default Controller Sample Time is 0.1 secondsPID::SetControllerDirection(ControllerDirection);PID::SetTunings(Kp, Ki, Kd);lastTime = millis()-SampleTime;inAuto = false;myOutput = Output;myInput = Input;mySetpoint = Setpoint;}复制代码PID LIB的参数分别是这样的:Input 输入值(这里输入卡尔曼融合获取的角度值)Output PID计算的结果,供电机驱动的PWM使用Setpoint 期望值(这里输入小车平衡点的角度值)Kp、Ki、Kd 这是KPI的三个重要参数这三个参数的详细说明我从网上摘录了一段:比例(P)控制比例控制是一种最简单的控制方式。
其控制器的输出与输入误差信号成比例关系。
当仅有比例控制时系统输出存在稳态误差(Steady-state error)。
积分(I)控制在积分控制中,控制器的输出与输入误差信号的积分成正比关系。
对一个自动控制系统,如果在进入稳态后存在稳态误差,则称这个控制系统是有稳态误差的或简称有差系统(System with Steady-state Error)。
为了消除稳态误差,在控制器中必须引入“积分项”。
积分项对误差取决于时间的积分,随着时间的增加,积分项会增大。
这样,即便误差很小,积分项也会随着时间的增加而加大,它推动控制器的输出增大使稳态误差进一步减小,直到等于零。
因此,比例+积分(PI)控制器,可以使系统在进入稳态后无稳态误差。
微分(D)控制在微分控制中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。
自动控制系统在克服误差的调节过程中可能会出现振荡甚至失稳。
其原因是由于存在有较大惯性组件(环节)或有滞后(delay)组件,具有抑制误差的作用,其变化总是落后于误差的变化。
解决的办法是使抑制误差的作用的变化“超前”,即在误差接近零时,抑制误差的作用就应该是零。
这就是说,在控制器中仅引入“比例”项往往是不够的,比例项的作用仅是放大误差的幅值,而目前需要增加的是“微分项”,它能预测误差变化的趋势,这样,具有比例+微分的控制器,就能够提前使抑制误差的控制作用等于零,甚至为负值,从而避免了被控量的严重超调。
所以对有较大惯性或滞后的被控对象,比例+微分(PD)控制器能改善系统在调节过程中的动态特性。
PID计算相关代码如下:PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT); //PID对象声明setupPID(); //PID初始化....Kalman_Filter(Adxl_angle, Gyro_sensor); //卡尔曼融合获取angleInput = angle;pute(); //PID计算获取 OutputDrive(Output); //根据Output驱动电机void setupPID(){Input = 0;Setpoint = 17; //我的小车自平衡角度为17myPID.SetSampleTime(100); //控制器的采样时间100ms//myPID.SetOutputLimits(0, 2000);myPID.SetMode(AUTOMATIC);}复制代码如果你做完这些小车也能成功站起来了,我的小车抖动得比较厉害,是因为我的直流电机减速太多了(减速比1:220的单轴电机),而且PID的kp,ki,kd三个参数没调整好。
等有时间换个电机再仔细调整一下参数,最好能做成可以控制前景、后退、转弯的小车。
弄个体积大点的就能骑着上下班了,哈。
这是我们自己整理出来的double kalmanUpdate(double Acc_Mess,double Gyro_Media) {double Acc_Real=0.0,Acc_Media=0.0,T=0.0,Q=0.5,Kg=0.0,q=0.6;//测量不确定度Q=10,全局变量//最优角度值的偏差L全局变量//q全局变量//T高斯白噪声T//中间变量 Acc_Media//T陀螺仪的高斯白噪声//L上一时刻陀螺仪与真实值的真实误差//Q此时刻陀螺仪与真实值的估计误差//Kg高斯增益//Acc_Media=Gyro_Media ;//计算瞬时角度值T=sqrt(Q*Q+L*L);Kg=T*T/(T*T+q*q) ;Acc_Real=Acc_Media+Kg*(Acc_Mess-Acc_Media);L=sqrt((1-Kg)*T*T);return Acc_Real ;}。