智能车声标定位相关算法优化

相关

相关部分比较简单,相关的意义和实现有需要可以参考下面两篇博文,
https://blog.csdn.net/jbb0523/article/details/6669883?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4
https://blog.csdn.net/LiuXF93/article/details/88956643?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-5&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-5

相关函数优化

将相关部分转化成代码

/*!
  * @brief    互相关
  *
  * @param    acor: 互相关结果
  * @param    x   : 互相关数据 x
  * @param    y   : 互相关数据 y
  * @param    len : 互相关数据长度
  *
  * @return   无
  *
  * @note     无
  *
  * @see
  *
  * @date     2020/4/28
  */
void xcorr(float *acor, int16_t *x, int16_t *y, uint16 len)
{
	double sum = 0;
	int delay, i, j;
	for(delay = -len + 1; delay < 0; delay++)
	{
		sum = 0;

		for(i = 0; i < len; i++)
		{
			j = i + delay;
			if((j < 0))
			{
				sum += 0.00001f * x[j + len] * y[i];   //防止溢出,缩小一定倍数
			}
			else if(j >= len)
			{
				sum += 0.00001f * x[j - len] * y[i];   //防止溢出,缩小一定倍数
			}
			else
			{
				sum += 0.00001f * x[j] * y[i];   //防止溢出,缩小一定倍数
			}
		}
		acor[delay + len - 1] = (float)sum;
	}
}

运行时间巨慢,简直无法使用,但是这个和fft加速相比,占用内存比较小,TC264官方的FFT库需要输入输出都是float32的复数,在做相关的时候还需要把2048点的原始数据补零变成4096点的复数,两组数据进行相关就需要 4 x 2 x 4096 x 3 字节,也就是96KB。而TC264双核架构,CPU0的dsram只有72KB,CPU1的dsram只有120KB,嗯,也就是只可以用CPU1的内存了,但是这只是一个麦克风和FM做相关计算,一般确定位置最少也要三个麦克风,内存不够用了!怎么降低内存消耗?

1.可以降低采样率,以5KHz的频率进行采样,这样1024点就可以采集到一个周期,缺点就是原始数据粒度下降了,可能会影响相关结果,实测的时候发现相关峰值位置不会变,没有发现和原始结果有太大区别(也可能是测的不太久)。

2.可以使用TC264DA版芯片,DA芯片多了512K的EMEM内存,可以在CPU0中进行使用,缺点EMEM速度比常规的RAM要慢一些。

使用FFT加速相关运算的步骤比较简单

1.将ADC采集到FM信号1和9814信号2从2048点补零成4096点
2.对信号1和信号2进行FFT变换
3.对信号2求共轭
4.(信号1FFT结果)* (信号2FFT结果的共轭)
5.对上述结果进行IFFT变换
6.求出IFFT变换结果的幅值
7.找出最大幅值的下标
8.两个信号之间的时延 = 最大下标 * 1/采样频率
9.距离信息 = 时延 * 声速

那么是否必须使用FFT加速呢?

我们可以上述直接相关函数进行优化,直接相关函数一样可以得到最大下标(也就是FFT加速的第7个步骤),赛场大小是固定的,因此距离信息其实有最大值的,而距离信息 = 时延 * 声速,声速固定,因此时延其实有最大值,时延和最大下标又有关系,因此最大下标其实在一个范围内,我们直接进行相关的时候,可以只求最大下标范围内的相关值,因此相关函数可以改成如下

/*!
  * @brief    互相关
  *
  * @param    acor: 互相关结果
  * @param    x   : 互相关数据 x
  * @param    y   : 互相关数据 y
  * @param    len : 互相关数据长度
  *
  * @return   无
  *
  * @note     无
  *
  * @see
  *
  * @date     2020/4/28
  */
void xcorr(float *acor, int16_t *x, int16_t *y, uint16 len)
{
	double sum = 0;
	int delay, i, j;
	for(delay = -300; delay < 0; delay++)  //300 * 100us * 0.0346 cm/us (声速) 可以检测最远距离 10.38m
//	for(delay = -len + 1; delay < len; delay++)
	{
		sum = 0;

		for(i = 0; i < len; i++)
		{
			j = i + delay;
			if((j < 0))
			{
				sum += 0.00001f * x[j + len] * y[i];   //防止溢出,缩小一定倍数
			}
			else if(j >= len)
			{
				sum += 0.00001f * x[j - len] * y[i];   //防止溢出,缩小一定倍数
			}
			else
			{
				sum += 0.00001f * x[j] * y[i];   //防止溢出,缩小一定倍数
			}
		}
		acor[delay + 300] = (float)sum;
	}
}

速度有所提升,将对应的变量全部放到运行CPU的dram中,大概需要50ms,50ms还是有点好长啊,是否可以接着优化?

分析这个函数,发现循环次数非常多,大部分资源都耗费在循环上了,按一般最少使用3个4468模块来算,一次循环做三组相关,是否可以提高效率?

void xcorr(float *acor1, float *acor2, float *acor3, int16_t *x, int16_t *y, int16_t *y1, int16_t *y2, uint16 len)
{
	float sum3 = 0;
	float sum1 = 0;
	float sum2 = 0;
	int delay, i, j;
	for(delay = -300; delay < 0; delay++)
//	for(delay = -len + 1; delay < len; delay++)
	{
		sum1 = 0;
		sum2 = 0;
		sum3 = 0;
		for(i = 0; i < len; i++)
		{
			j = i + delay;
			if((j < 0))
			{
				sum1 += 0.0001f * (float)x[j + len] * (float)y[i];
				sum2 += 0.0001f * (float)x[j + len] * (float)y1[i];
				sum3 += 0.0001f * (float)x[j + len] * (float)y2[i];
			}
//			else if ((j >= len))
//			{
//				sum1 += 0.0001f * (float)x[j - len] * (float)y[i];
//				sum2 += 0.0001f * (float)x[j - len] * (float)y1[i];
//				sum3 += 0.0001f * (float)x[j - len] * (float)y2[i];
//			}
			else
			{
				sum1 += 0.0001f * (float)x[j] * (float)y[i];
				sum2 += 0.0001f * (float)x[j] * (float)y1[i];
				sum3 += 0.0001f * (float)x[j] * (float)y2[i];
			}
		}
		/* 相关结果存放在 300长度数组中 */
		acor1[300 + delay] = (float)sum1;
		acor2[300 + delay] = (float)sum2;
		acor3[300 + delay] = (float)sum3;
	}
}

实测发现,三组相关时间上大概需要70ms左右,这样子就和用FFT加速效果差不多,如果使用更多9814模块,速度上就可能超过FFT加速,而且内存消耗相比FFT减少的不要太多。

思考

小车在运动过程中采集数据是否会影响距离信息精确度?该如何减小该方面误差?

可以在灭灯后原地静止,当下一个信标灯响起,采集到一帧静止状态的数据,获取精确的距离信息,根据此距离信息和编码器信息,在空间位置上进行控制。不过这样有个问题,计算的距离信息必须准确,编码器距离积分必须精确(脉轮车估计不行)。

可以运动过程中进行采集计算,计算大概方位,然后横冲直撞莽过去,个人觉得这种比较靠谱。

你可能感兴趣的:(飞思卡尔,嵌入式)