用于布尔开关的简单低通滤波器

问题描述 投票:0回答:3

如果更改之间的间隔太短,则在C#类中需要过滤掉或忽略Update方法中的布尔更改。

从本质上讲,我需要所谓的“低通滤波器”

假设我们在Update或FixedUpdate中都有以下内容

if (myBoolean condition){
 myVal  =0;
}else{

 myVal= _rawInput;
}

发生的事情是上面的myBoolean条件切换太快了。我需要“过滤掉”或忽略这些短暂的间隔。

我已尝试使用此LowPass Filter类与移动加速度计输入一起使用,但没有运气,因为它假设被过滤的值是浮点数。 http://devblog.aliasinggames.com/accelerometer-unity/任何人都可以帮忙吗?

c# unity3d boolean lowpass-filter
3个回答
1
投票

低通滤波器?

using System;
using System.Linq;

public class Program
{
    public static bool MyValue = false;

    public static DateTime lastChange { get; set; } = DateTime.MinValue;

    public static void ChangeValue(bool b)
    {
        // do nothing if not 2s passed since last trigger AND the value is different
        // dont reset the timer if we would change it to the same value
        if (DateTime.Now - lastChange < TimeSpan.FromSeconds(2) || MyValue == b)
            return;
        // change it and remember change time
        lastChange = DateTime.Now;
        MyValue = b;
        Console.WriteLine($"Bool changed from {!b} to {b}. Time: {lastChange.ToLongTimeString()}");
    }

    public static void Main(string[] args)
    {
        for (int i = 0; i < 10000000; i++)
        {
            ChangeValue(!MyValue);
        }
    }
}

输出:

Bool changed from False to True. Time: 23:29:23
Bool changed from True to False. Time: 23:29:25
Bool changed from False to True. Time: 23:29:27

整个循环运行大约7秒 - 即每秒大约115万次触发器来改变它。


1
投票

你可以把它变成一个类:

public class FilteredBool
{
    private bool _inputValue;
    private bool _outputValue;
    private TimeSpan _minimumTime = TimeSpan.FromSeconds(5);
    private DateTime _lastChangeTime = DateTime.MinValue;

    public bool Value
    {
        get
        {
            if (_outputValue != _inputValue)
            {
                if (_lastChangeTime + _minimumTime < DateTime.Now)
                    _outputValue = _inputValue;
            }
            return _outputValue;
        }
        set
        {
            if (_inputValue != value)
            {
                _inputValue = value;
                _lastChangeTime = DateTime.Now;
            }
        }
    }

    public TimeSpan MinimumTime
    {
        get { return _minimumTime; }
        set { _minimumTime = value; }
    }

    public static implicit operator bool(FilteredBool value)
    {
        return value.Value;
    }
}

这有一个bool的隐式运算符,这样你就可以替换任何需要bool(或if)的函数调用,而不必调用.Value。没有隐式运算符返回FilteredBool,因为这需要设置过滤时间。如果你愿意,你可以添加它,我觉得这将是一个很大的假设。


0
投票

OP感谢您提供出色的解决方案。作为布尔低通滤波器的快速入侵,我也想知道是否可以简单地使用计数器和模数运算,实质上是“减慢”FixedUpdate方法。布尔值永远不会比模数运算的间隔(或余数)=零更快地改变。没有想过通过实施细节。思考?

© www.soinside.com 2019 - 2024. All rights reserved.