Unity 3D :卡爾曼濾波 ( Kalman Filter )

6 篇文章 0 订阅
3 篇文章 0 订阅

前言 :

卡爾曼濾波,沒啥好介紹的,網路上應該有很多人做介紹,如果你不知道卡爾曼濾波是啥,可以先去看別人寫的介紹,嘛…知道的大概就行。

但你可能會遇到 : 網路上的介紹,真正能用的程式碼太少,都是他媽的數學推導,又他媽的老闆又壓 Dead Line…,說要在指定時間內完成…Orz。

所以我做一個 C# Library 給大家使用,簡單易用。以貢獻世界,造福人群。 ( 灑花 )

回歸正題 : KalmanFilter_Test.cs 是執行腳本 ( 你的程序邏輯 ) ,KalmanFilter.cs 則是 Library。至於使用方法可以直接看 KalmanFilter_Test.cs,很簡單的淺而以懂,比我在上面這講廢話來的快。

執行結果 :

在这里插入图片描述

KalmanFilter_Test.cs :

// 本程式碼由黃彥霖所有,轉載請註明出處 : https://blog.csdn.net/weixin_38884324
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KalmanFilter_Test : MonoBehaviour
{
    void Start()
    {
        float[] data = new float[] { 5, 6, 8, 3, 7, 6, 2 }; // 先給一組數字, 當然之後你也可以把 Sensor 讀到的值放入這

        KalmanFilter kf = new KalmanFilter();

        kf.SetQ(0.00001f); // 理想誤差 : 數值越大, 濾波效果越小
        kf.SetR(0.0001f);  // 實際誤差

        float[] s = kf.Filter(data); // 陣列濾波

        kf.SetFirst(data[0]); // [ 可選 ] 是否要先加入 "前一個" 值

        string ss = "實際數值\t陣列濾波\t即時濾波\n\n";

        for (int i = 1; i < data.Length; i++)
        {
            float d = kf.Filter(data[i]); // 即時濾波
            ss += data[i] + "\t" + s[i] + "\t" + d + "\n";
        }

        print(ss);
    }
}

KalmanFilter.cs :

// 本程式碼由黃彥霖所有,轉載請註明出處 : https://blog.csdn.net/weixin_38884324
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KalmanFilter
{
    public float[] Filter(float[] z)
    {
        float[] xhat = new float[z.Length];
        xhat[0] = z[0];
        float P = 1;

        for (int k = 1; k < xhat.Length; k++)
        {
            float xhatminus = xhat[k - 1];
            float Pminus = P + Q;
            float K = Pminus / (Pminus + R);
            xhat[k] = xhatminus + K * (z[k] - xhatminus);
            P = (1 - K) * Pminus;
        }
        return xhat;
    }

    bool isFirst = true;
    bool haveSetFirst = false;
    float xhat;
    float P;
    float z0;
    float Q = 1e-5f; // 0.00001
    float R = 0.0001f;

    public void SetFirst(float z0)
    {
        this.z0 = z0;
        haveSetFirst = true;
    }

    // 理想誤差
    public void SetQ(float Q) {
        this.Q = Q;
    }

    // 實際誤差
    public void SetR(float R) {
        this.R = R;
    }

    public float Filter(float z1)
    {
        if (isFirst)
        {
            isFirst = false;
            if (haveSetFirst == false) z0 = z1;
            xhat = z0;
            P = 1;
        }
        
        float xhatminus = xhat;
        float Pminus = P + Q;
        float K = Pminus / (Pminus + R);
        xhat = xhatminus + K * (z1 - xhatminus);
        P = (1 - K) * Pminus;

        return xhat;
    }

    public void Reset()
    {
        isFirst = true;
        haveSetFirst = false;
        xhat = 0;
        P = 0;
        z0 = 0;
        Q = 1e-5f; // 0.00001
        R = 0.0001f;
    }
}

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值