燃料图平滑算法

7
我正在开发一款车队管理系统,其中一个任务是显示代表车辆燃油消耗的图表(基于来自CAN总线的数据)。
如果数据值在0到100之间,则表示百分比。因此,如果我得到一个整数为45,则意味着油箱中的燃油为45%。
然而,如果车辆在行驶,由于船舶物理学的影响,可能会出现不一致的数据。例如,数据序列可以是:
76, 76, 75, 74, 73, 73, 71, 70 <- 这是一个良好的模式,因为它显示了燃油如何下降。
76, 70, 75, 76, 77, 76, 74, 74, 73, 72, 69, 72, 73, 73, 72, 71 <- 这不是一个好的模式,因为由于跳跃,油箱中的燃油不一致,我收到的数据不适合向用户显示。
我想平滑这些值,但是根据我选择平均多少个值,结果会有所不同。
关键问题在于有时会出现必须在图表中展示的耗油和加油时刻,不能进行平滑处理。
我应该使用什么样的算法来分析并以令用户信服的方式表示我的图表呢?

1
嗯...用户有抱怨吗?我可能会先展示原始数据,然后解释传感器具有+-10%的变异性。 - Randy
2
类似移动平均线这样的东西是否适合? - Zim-Zam O'Pootertoot
2
我认为你应该等待一定数量的样本才能开始制作图表;那将是你的窗口。然后取窗口值的平均值,并随时间滑动该窗口。 - fge
这是一个数学或统计问题,不是真正的编程问题。 - Raedwald
2
指数平滑是移动平均的一种替代方法。它对最近的值比老旧的值赋予更大的权重。您可以改变平滑系数来调整平均处理过程。 - Axel Kemper
显示剩余3条评论
3个回答

3
有没有办法确定加油/排油时发生的时间?如果有,那么你可以在这些时间动态地改变算法。
否则,我建议使用指数平滑法。
设d(0<=d<1)为先前数字的权重因子。所以显示的数字=prev_data*d + new_data*(1-d)
通过适当的权重因子,似乎可以消除“颠簸”,同时反映燃料事件。
这不是唯一的选择,只是一个示例算法,但我希望你会觉得它有用。
小编辑:我没有意识到指数平滑法有一个合适的名称。我仅仅是在我创建的游戏中显示帧速率时使用了这种技术。所以,谢谢Kemper。

1
唯一确定“排空”的方法我想应该是燃烧燃料,这理论上似乎是他试图展示/测量的内容。 - Aaron McIver
是的,我同意。我认为现在我可以进一步改进我的答案,因为我现在知道引擎的状态已知。例如,在某些引擎状态下可能不会进行加油。此时,“d”可以缩小以进行补偿。你有什么想法吗?在考虑到这些信息之后,我想好再进行潜在的编辑。 - flash_fire
有时候,当引擎启动时会进行加油操作。 - Joro Seksa

1
据我理解,您希望消除小的变化,但保留大的跳跃而不进行平滑处理。可能 移动中位数 是您要寻找的。它可以保留大的跳跃而不进行平滑处理(边缘保护 属性)。
我不确定这是否是最适合您的方法。我需要看到您的数据才能确定。

1

如果不与排水共享数据,这只是一种或多或少的猜测...

我会尝试使用滑动平均值(窗口大小至少为凸起大小),这将平滑凸起,但可能会破坏排水,因为我们不知道这些信号具有什么属性。

所以我会尝试类似于以下的方法:

  1. 查找颠簸最大周期

    如果是一艘船和一个形状恒定的罐,那么最大颠簸周期由船只能够承受的最大波浪大小和船长以及罐的形状和大小来确定。如果您不知道这个周期,可以通过找到几个连续的局部极小值/极大值(峰值)并取它们之间的最大距离来进行实时测量。

  2. 创建检测排水的函数

    如何做?我无法说,因为我不知道数据的样子,因为您没有分享它。

  3. 处理您的数据(提前足够多的样本)

    所以我会构建一个大小等于滑动平均窗口的FIFO。首先完全填充FIFO的起始样本,然后将样本传递给它。但是,不要存储/显示/绘制输出值,而是使用FIFO中所有值的平均值。

    这是在FIFO(窗口)大小为9个样本的滑动平均之前(黑色)和之后(蓝色)对于您的颠簸信号的输出:

    Plot

    请注意,数据从原始信号中的半个FIFO大小(延迟)进行了时间移动(我将其向后移回图中,以使图形相对应)。

  4. 如果检测到排水并且滑动平均破坏了它

    您需要在排水开始之前暂时禁用滑动平均(只需使用较小的滑动窗口大小)。您可以在排水之前将大小从原始值线性插值到1,然后再次插值回来,以便信号不会失去平滑性。但是,滑动平均可能完全保留排水信息,因此不需要执行此部分。没有相关数据就无法知道。

如果您需要更高级的东西,那么如果您有更详细的数据,您可以假设隆起的形状具有特定的形状(由于燃料振荡所在的油箱的形状)。因此,您可以对信号进行FFT处理,去除与隆起相关的频率,并通过反向FFT重构。如果您想避免复杂的域,可以尝试使用DCT来完成此操作。但是,对于这样的任务,我们没有足够的测量数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接