背景

公司有个板子,能过滤几乎所有脉冲式声学设备的报文,只把数据回传,兼容性非常强。但是也有一个问题,就是不知道脉冲何时发出。。频率倒是知道,大家都用50KHz和200KHz的频率。采样率也是知道的。

要我拿这个东西测水深。

方案

分4步走,第1步是区分脉冲何时发出,也就是数据何时有效;第2步是跳过脉冲发出的那段回波;第3步是找海底。第4步是计算水深。

  1. 区分脉冲何时发出:接收器就在发射器旁边,脉冲发出的时候会有非常强烈的回波值(拉满有效位数)。所以找连续的数据最大值即可用于分割不同道采样,很简单。
  2. 跳过脉冲发出的那段回波:我试了一下,水的背景振幅值是很低的,但是脉冲刚发出时的回波也有振幅震荡到低值的情况。于是滑动窗口算均值,通过固定阈值找到第一个均值小于阈值的窗口,窗口的bg就是不受干扰的水的开端。
  3. 找海底:回波中途会有干扰,比如说打到鱼了,或者打到什么悬浮物了。但是这些干扰的特点就是深度很浅,超过3米已经算庞然大物了。然而海底界面的一串回波远不止3米。基于这么一个经验,继续滑动窗口,找长距离的异常值区间。窗口就至少要大于6米嘛,这样才能规避干扰。按理说应该用中值滤波,但中值滤波要排序,在线做有点慢,毕竟这破CPU还拖着雷达等一众东西呢。于是就换了均值滤波,窗口加大进一步消除干扰影响,每次滑动kernel都增量更新缓存的上一个窗口的avg值,当当前窗口avg值大于2倍缓存的avg值时,视为检测到海底。这个滤波其实也是提前返回的,就不是要整道都要滤波一遍。
  4. 计算水深:很粗糙,把水中声速视为定值。知道采样率,便知道双程走时,乘速度就是2倍的测深。

补充方案

然后我就发现这坑爹的板子并不一定在脉冲发出时会回传拉满有效位数的回波值。。嵌入式出来挨打!他们也解释不清楚为什么,那我自然也不知道为啥。。

于是我又做了帧间平滑。

平滑方式也是说来很简单,缓存上一帧的深度,与当前测深进行加权平均。深度变化越大,则更新权重越小(让深度趋于平滑)。这个权重是一个分段函数,深度波动在10%以内时就是0.5。深度波动大于10%则是一个反比函数。

结果

我要往后端回传数据,结果说重启下服务端程序跟要了运维的命一样。。。无奈我说那我整个微服务吧?运维:没有端口给你。。。于是我直接将结果保存在了本地,等海上运维去拷数据。真的无语

如果觉得我的文章对你有用,请随意赞赏