赞
踩
摘自:https://mp.weixin.qq.com/s/JGPSqJ_oimw0de1FMN189A
原创 across超越者 across说 2019-11-17
要完成飞行器的定位,则必须要有位置的反馈数据。在户外,我们一般使用GPS作为位置传感器,然而,在室内,GPS无法使用,要完成定位功能,可以选用光流传感器。
本讲主要介绍如何通过下视摄像头估计飞行器的平移速度,即光流传感器。
光流传感器输出什么?
首先要知道光流传感器的输出是什么?光流传感器输出的是xy两个轴向的速度数据,注意,没有位置数据,而位置反馈可以通过速度积分获得,不可避免会产生漂移,但实际通过组合导航算法的处理,也可获得较为满意的使用效果。
光流算法的原理?
总体来看,光流算法分为两步:
通过下视摄像头获得图像数据,分析图像的不同时刻的帧数据,得到像素的移动速度;
将像素的移动速度转换成飞行器的移动速度;
那如何判定图像的运动?
选择对应的特征点,通过特征点的运动来判定图像的运动。
图中可以看出,摄像头在向右运动。
选择什么样的特征点?
简单来说就是能看出运动状态的。
例:
这个特征点选择,看不出运动
这个能看出左右,但看不出上下
这个就都可以能看出所有的运动。
完成特征点选择后,就该知道如何使用他们?首先如何根据前后两个像素点估计出运动?
图中由t时刻到t+1时刻,得到两个时刻的像素坐标后,如何知道运动?
这里引出光流算法的两个假设,即认为两个时刻的运动很小和亮度恒定不变(上述等式才能成立)。
将上式右侧进行泰勒展开,忽略二阶无穷小项,则可以得到
该方程有两个未知数u,v。一个方程,两个未知数,所以无法得到确定的u和v。
此时需要引入另外的约束条件,从不同的角度引入约束条件,导致了不同光流场计算方法。这里介绍其中的一种,基于梯度的方法。利用时变图像灰度(或其滤波形式)的时空微分(即时空梯度函数)来计算像素的速度矢量。
LK光流法在光流法两个基本假设的基础上,增加了一个“空间一致”的假设,即所有的相邻像素有相似的行动。也即在目标像素周围m×m的区域内,每个像素均拥有相同的光流矢量。
图中A的部分能提供很多关于估计的信息。表示图像的梯度。
以上就是Lucas Kanade Optical Flow算法。
开源PX4的光流算法则是采用块匹配法进行光流定位,具体细节可参看其源码部分:
px4 flow 光流算法源码
https://github.com/PX4/Flow/blob/master/src/modules/flow/flow.c
问题:
1、LK算法的约束条件即:小速度,亮度不变以及区域一致性都是较强的假设,并不很容易得到满足。如当物体运动速度较快时,假设不成立,那么后续的假设就会有较大的偏差,使得最终求出的光流值有较大的误差。对于其改进的相关理论,这里不做过多介绍;
对于亮度不变的假设,实际情况是光流场并不一定反映了目标的实际运动情况,光源与物体发生相对运动,就会有光流产生。因此可以说光流法对光线敏感, 光线变化极易影响识别效果;
2、孔径问题,在进行光流计算时,我们是选取了一个小窗口进行判定的,这个窗口的选择大小也会对结果产生影响。
上图中可以看到目标是在向右移动,但是由于“观察窗口”过小我们无法观测到边缘也在下降。邻域大小的选取会影响到最终的效果;
得到像素速度u v后如何转换?
一般第二项可不考虑,则简单来说就是考虑焦距的变化,这样处理带来的问题是没有标准单位的速度输出,不过可以在后面进行标定的处理。
那得到光流输出的数据,飞控又如何使用?
具体的光流数据,如何应用到位置估计算法里,可以参考位置估计的算法原理,本文不再赘述。
这里就讲一下光流的数据在进融合算法前,常见的需要进行哪些预处理。
1、首先是与高度的关系,光流的数据一般在低空范围内有效,比如5m以内,超过一定高度,得到的数据精度就会比较差了,同时与高度有一个线性的关系,根据高度的大小,对光流得到的机体xy速度进行缩放;
一般来说,配合光流的高度数据主要来自超声波传感器,同样可以测得低空的高度,而且较气压计而言,精度较高,得到的相对高度比较准确(气压计有漂移,受风影响大,噪音也大)。
2、其次,需要进行姿态补偿。
什么意思呢?假设一种情况,飞行器在原地晃动,比如左右摆动,此时光流会输出一个速度数据出来,而实际飞行器并未有位置上的变化,所以需要将这个误判的速度进行修正掉。
如何做?
由于这个误判的速度、距离信息与姿态角的变化有关,所以我们可以用角度的变化去提前标定这个补偿。
if(get_flow_quality()!=0)
{
flow_angle_fix_x = +(120.0f * tan(pitch_delay[3]));
flow_angle_fix_y = -(120.0f * tan(roll_delay[3]));
}
else
{
flow_angle_fix_x = 0;
flow_angle_fix_y = 0;
}
flow_cal_distance_x = flow_ori_distance_x - flow_angle_fix_x; //cm
flow_cal_distance_y = flow_ori_distance_y - flow_angle_fix_y; //cm
float flow_speed_x = (flow_cal_distance_x - last_distance_x) / 0.02f;
float flow_speed_y = (flow_cal_distance_y - last_distance_y) / 0.02f;
last_distance_x = flow_cal_distance_x;
last_distance_y = flow_cal_distance_y;
如上代码所示,先将光流的数据进行积分,得到位移。然后用角度乘以一个系数得到补偿量,这个是需要调试的部分,同时,因为角度的变化相对较快,所以我们需要进行大概的时间同步,然后减去补偿量,得到处理后的位移数据,再微分可得到速度数据,输入给位置估计算法。
如图所示,两个曲线分别是校正前的位移flow_ori_distance_x,位移补偿量flow_angle_fix_x,调至图中两者变化一致即可。
这里,对光流数据先积分再微分的处理,基于两个考虑:
有一定的滤波效果;
由于光流得到的速度并不是标准单位,而位移量是可以提前标定的,比如实际飞行器移动了1m,而测量值是1.2m,则可以进行校正处理,得到标准单位的数据;
3、最后还有一个yaw的旋转补偿。这个主要针对的是光流传感器并未放在飞行器中心位置,所以在原地yaw旋转运动时,xy会不对称的输出错误的数据,而这个数据是我们不需要的(实际飞行器并未运动)。
与Z轴的角速度有关,具体实现如下:
也是需要进行实现的参数调试,调至原地转圈时,得到的光流速度为0左右即可。
across说:一个有趣有用的公众号,分享笔者在无人机、无人驾驶、机器人等领域的技术开发心得与见解。扫描下方二维码,即可关注本公众号。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。