Rõ ràng khi ta áp dụng cảm biến, giá trị trả về từ chúng luôn biến đổi quanh vị trí cân bằng dù là rất nhỏ, và bạn biết nguyên nhân của hiện tượng này là do nhiễu, bạn luôn muốn loại bỏ nhiễu nhưng việc đó hình như ngoài tầm với của bạn.(-.-)… Đừng lo, bọn họ đã bao gồm giải pháp, bấm đọc nội dung bài viết này thôi nào!


Trong đo lường, do các yếu tố cả khinh suất lẫn khả quan mà kết quả đo đạc luôn luôn chỉ được xem như là tương đối so với mức giá trị thực cần đo. Độ chênh lệch giữa cực hiếm đo được với giá trị thực được điện thoại tư vấn là Sai số.

Bạn đang xem: Lọc kalman

Sai số gây nên bởi nhiễu, bọn chúng được phân có tác dụng 2 một số loại chính: không nên số hệ thống hoặc sai số ngẫu nhiên.

Đọc thêm tại: https://vi.wikipedia.org/wiki/Sai_s%E1%BB%91

Gỉa sử ta tiến hành đo giá trị điện áp của một viên pin tích điện mặt trời, hiệu quả thu được trên thứ thị như sau :

 

Gỉa sử quý giá điện áp thực của pin mặt trời là u0=1.9545 vol.

Do tác động bởi các yếu tố trong quy trình đo đạc, không đúng số xuất hiện là điều rất nặng nề tránh khỏi, kết quả là ta chỉ có thể đo quý giá điện áp bằng phương pháp lấy tương đối kết quả trung bình các phép đo .

Tức u0=u ± ∆ e =1.95 ± 1%, (với ∆ e là không đúng số)


Loại bỏ nhiễu bằng thuật toán lọc Kalman


Phương pháp này được đề suất năm 1960 vày nhà khoa học mang tên Kalman.

Để minh chứng hiệu quả của cách thức này bọn họ sẽ bao gồm một phép test mô rộp như sau.

float u0 = 100.0; // quý hiếm thực (không đổi)float e; // nhiễufloat u; // cực hiếm đo được (có thêm nhiễu)void setup() Serial.begin(9600);void loop() randomSeed(millis()); e = (float)random(-100, 100); u = u0 + e; Serial.println(u);Nạp code mang đến romanhords.com rồi kế tiếp mở cổng Serial plotter giúp thấy dưới dạng trang bị thị:

Kết quả hiện trên Serial plotter:

Xem lại code bên trên ta thấy có đôi nét như sau:

Gọi u0=100.0 là giá bán trị thực tế của vật dụng thể, cũng là giá trị nhưng ta mong muốn thu được, vì u0 là hằng số, (nếu như không có nhiễu). Lý tưởng thì trên đồ gia dụng thị ta vẫn thu được một con đường thẳng tuy vậy song với trục thời gian t.

Thường thì nhiễu chỉ dao động trong vòng e=±10% giá trị thực đã được xem như là rất ồn rồi (noise).

Để tăng cường mức độ khó, tôi đã cố ý mang đến e=±100% u0 bởi hàm Random khiến cho giá trị đo bị nhiễu hoàn toàn và gần như rất khó để tích lũy lẫn đo lường và thống kê sau này.

Sử dụng bộ lọc Kalman

Như đã thống nhất, trong thực tiễn u0 là giá bán trị họ không biết, việc áp dụng bộ thanh lọc sẽ đề nghị giúp ta sa thải các nhiễu, khi ấy giá trị đo được buộc phải gần con đường u0=100 hơn .

Vì đấy là mô phỏng yêu cầu giá trị u0cần được đến trước (chỉ bản thân và bạn biết) để rất có thể kiểm chứng tính đúng chuẩn của hiệu quả trước và sau khoản thời gian lọc. (bằng biện pháp trộn u0 cùng với nhiễu rồi mang lại romanhords.com lọc)

So cùng với code trên ,phần code này chỉ cần thêm một chiếc lệnh duy nhất:

Gọi u_kalman là cực hiếm đo sẽ qua cỗ lọc Kalman:

u_kalman=bo_loc.updateEstimate(u);

Code

#include SimpleKalmanFilter bo_loc(2, 2, 0.001);float u0 = 100.0; // quý giá thực (không đổi)float e; // nhiễufloat u; // quý giá đo được (có thêm nhiễu)float u_kalman; // giá bán được thanh lọc nhiễuvoid setup() Serial.begin(9600);void loop() randomSeed(millis()); e = (float)random(-100, 100); u = u0 + e; Serial.print(u); Serial.print(","); u_kalman = bo_loc.updateEstimate(u); Serial.print(u_kalman); Serial.println();Và đây là tác dụng khi sử dụng thêm cỗ lọc:

Đường màu sắc xanh: u.

Đường màu sắc vàng: u_kalman.

Dừng lại một ít để quan liền kề đồ thị, hẳn bạn cũng đồng ý với bản thân thuật toán lọc Kalman tỏ ra cực kỳ hiệu quả, có những khi nhiễu dồn ra biên cực to (±100%u0). Tuy nhiên giá trị vẫn khá cạnh bên đường u0.

Ghép tầng những bộ thanh lọc ta chiếm được kết quả đúng chuẩn hơn, tất nhiên nó sẽ thỏa mãn nhu cầu trễ rộng 1 tầng

#include SimpleKalmanFilter bo_loc(2, 2, 0.001);float u0 = 100.0; // giá trị thực (không đổi)float e; // nhiễufloat u; // quý hiếm đo được (có thêm nhiễu)float u_kalman; // giá chỉ được lọc nhiễuvoid setup() Serial.begin(9600);void loop() randomSeed(millis()); e = (float)random(-100, 100); u = u0 + e; Serial.print(u); Serial.print(","); u_kalman = bo_loc.updateEstimate(u); // tầng 1 u_kalman = bo_loc.updateEstimate(u_kalman); // tầng 2 u_kalman = bo_loc.updateEstimate(u_kalman); // tầng 3 u_kalman = bo_loc.updateEstimate(u_kalman); // tầng 4 Serial.print(u_kalman); Serial.println();Kết quả đến 4 tầng lọc

Bạn làm sao còn nghi ngờ tác dụng giống bản thân thì copy code rồi kiểm tra lại dùm mình nhé, thật cạnh tranh tin yêu cầu không ! ^^ 

*


Đây là thành quả nghiên cứu và phân tích có từ 56 năm trước, chủ nhân của thuật toán là ông Rudolf (Rudy) E. Kálmán

Bộ lọc này được sử dụng rộng thoải mái trong các máy tính xách tay kỹ thuật số của các hệ thống điều khiển, khối hệ thống định vị, khối hệ thống điện tử, RADA, vệ tinh dẫn đường để lọc nhiễu.

Bộ lọc chuyển động ổn định mang đến mức, nó vẫn được thực hiện trong chương trình Apollo, tàu nhỏ thoi của NASA, tàu ngầm thủy quân và xe từ hành không gian không người lái và vũ khí, thương hiệu lửa hành trình.

Với thành công xuất sắc đó, ông cũng đã nhận được được khôn cùng nhiều phần thưởng lớn không giống nhau.

https://vi.wikipedia.org/wiki/Rudolf_E._K%C3%A1lm%C3%A1n


Đây là thuật toán dễ dàng và đơn giản mình kiếm tìm được, hãy vào add bên dưới nhằm hiểu được chân thành và ý nghĩa của những tham số K (Kalman Gian) ,P,Q,R….

/** Need lớn tweak value of sensor and process noise* arguments :* process noise covariance* measurement noise covariance* estimation error covariance */class Kalman_Filter_Distance protected: double _q; //process noise covariance double _q_init; double _r; //measurement noise covariance double _r_init; double _x; //value double _p; //estimation error covariance double _p_init; double _k; //kalman gainpublic: /** Need lớn tweak value of sensor & process noise* arguments :* process noise covariance* measurement noise covariance* estimation error covariance */ Kalman_Filter_Distance(double q, double r, double p) : _q(q) , _q_init(q) , _r(r) , _r_init(0) , _x(0) , _p(p) , _p_init(p) , _k(_p / (_p + _r)); virtual void init(double x) _x = x; virtual void setProcessNoiseCovariance(double i) _q = i; _q_init = i; virtual void setMeasurementNoiseCovariance(double i) _r = i; _r_init = i; virtual void setEstimatiomErrorCovariance(double i) _p = i; _p_init = i; virtual double kalmanUpdate(double measurement); virtual void reset() _q = _q_init; _r = _r_init; _p = _p_init; ;;double Kalman_Filter_Distance::kalmanUpdate(double measurement) //prediction update //omit _x = _x _p = _p + _q; //measurement update _k = _p / (_p + _r); _x = _x + _k * (measurement - _x); _p = (1 - _k) * _p; return _x;
Của tác giả denyssene : https://github.com/denyssene/SimpleKalmanFilter

Link dự trữ : https://drive.google.com/file/d/0BzMEcyRK_uUFZy1sSjE4c0E3aUk/view?usp=sharing (mirror)

Test tủ sách với la bàn số

#include #include #include SimpleKalmanFilter pressureKalmanFilter(1, 1, 0.001);HMC5883L compass;float x_kalman;void checkSettings()void setup() Serial.begin(9600); // Initialize HMC5883L Serial.println("Initialize HMC5883L"); while (!compass.begin()) Serial.println("Could not find a valid HMC5883L sensor, check wiring!"); delay(500); compass.setRange(HMC5883L_RANGE_1_3GA); compass.setMeasurementMode(HMC5883L_CONTINOUS); compass.setDataRate(HMC5883L_DATARATE_15HZ); compass.setSamples(HMC5883L_SAMPLES_1); // kiểm tra settings checkSettings();void loop() Vector raw = compass.readRaw(); Vector norm = compass.readNormalize(); x_kalman = pressureKalmanFilter.updateEstimate(raw.XAxis); Serial.print(raw.XAxis); Serial.print(","); Serial.print(x_kalman, 3); Serial.println(); delay(100);

Test thực tế với cảm biến áp suất

#include #include /* This sample code demonstrates how the SimpleKalmanFilter object can be used with a pressure sensor khổng lồ smooth a mix of altitude measurements. This example needs a BMP180 barometric sensor as a data source. Https://www.sparkfun.com/products/11824 SimpleKalmanFilter(e_mea, e_est, q); e_mea: Measurement Uncertainty e_est: Estimation Uncertainty q: Process Noise */SimpleKalmanFilter pressureKalmanFilter(1, 1, 0.01);SFE_BMP180 pressure;// Serial output đầu ra refresh timeconst long SERIAL_REFRESH_TIME = 100;long refresh_time;float baseline; // baseline pressuredouble getPressure() char status; double T, P; status = pressure.startTemperature(); if (status != 0) delay(status); status = pressure.getTemperature(T); if (status != 0) status = pressure.startPressure(3); if (status != 0) delay(status); status = pressure.getPressure(P, T); if (status != 0) return (P); void setup() Serial.begin(115200); // BMP180 Pressure sensor start if (!pressure.begin()) Serial.println("BMP180 Pressure Sensor Error!"); while (1) ; // Pause forever. baseline = getPressure();void loop() float p. = getPressure(); float altitude = pressure.altitude(p, baseline); float estimated_altitude = pressureKalmanFilter.updateEstimate(altitude); if (millis() > refresh_time) Serial.print(altitude, 6); Serial.print(","); Serial.print(estimated_altitude, 6); Serial.println(); refresh_time = millis() + SERIAL_REFRESH_TIME;

Test thư viện với cảm ứng gia tốc

#include #include #include "I2C.h"#define RESTRICT_PITCHSimpleKalmanFilter simpleKalmanFilter(1, 1, 0.001);uint8_t i2cData<14>; // Buffer for I2C dataint16_t accX;float accX_kalman;void setup() Serial.begin(9600); Wire.begin();#if romanhords.com >= 157 Wire.setClock(400000UL); // mix I2C frequency to lớn 400kHz#else TWBR = ((F_CPU / 400000UL) - 16) / 2; // set I2C frequency to 400kHz#endif i2cData<0> = 7; // set the sample rate lớn 1000Hz - 8kHz/(7+1) = 1000Hz i2cData<1> = 0x00; // Disable FSYNC và set 260 Hz Acc filtering, 256 Hz Gyro filtering, 8 KHz sampling i2cData<2> = 0x00; // phối Gyro Full Scale Range khổng lồ ±250deg/s i2cData<3> = 0x03; // phối Accelerometer Full Scale Range to lớn ±16g while (i2cWrite(0x19, i2cData, 4, false)) ; // Write to lớn all four registers at once while (i2cWrite2(0x6B, 0x01, true)) ; // PLL with X axis gyroscope reference & disable sleep modevoid loop(){ while (i2cRead(0x3B, i2cData, 14)) ; accX = (int16_t)((i2cData<0>
Ngay từ đầu mình đã bị lôi kéo về tài năng của cỗ lọc Kalman. Rất mong muốn hiểu nó để nhà động áp dụng vào những trường hợp khác.

Xem thêm: Tổng Quan Western Blot Là Gì, Phương Pháp Western Blot 1, Western Blot1

Tuy nhiên, ở trình độ hiện tại của mình, câu hỏi tiếp cận cùng hiểu về bộ lọc này còn khôn xiết mơ hồ, cho nên việc đặc tả những thuật ngữ cùng lời phân tích và lý giải thấu đáo về phương trình và cách tùy chỉnh cấu hình là rất khó khăn (thậm chí với tất cả bạn). Phải mình không thể comment hoặc viết được gì rộng ngoài share những trang web để tự học về cỗ lọc Kalman mà tôi đã sưu tầm trong suốt thời hạn qua:

Một vài thư viện xuất xắc về cỗ lọc Kalman:

Của tác giả bachagas  :https://github.com/bachagas/Kalman

Link dự trữ : https://drive.google.com/file/d/0BzMEcyRK_uUFT19jS2lIZlBNWVU/view?usp=sharing

Thư viện thanh lọc nhiễu do cảm biến góc PMU6050 :

Của tác giả  Lauszus : https://github.com/TKJElectronics/KalmanFilter

Link dự trữ :https://drive.google.com/file/d/0BzMEcyRK_uUFbWQtbENlVnI2YnM/view?usp=sharing

Thư viện Kalman dễ dàng :

Của tác giả denyssene : https://github.com/denyssene/SimpleKalmanFilter

Link dự trữ : https://drive.google.com/file/d/0BzMEcyRK_uUFZy1sSjE4c0E3aUk/view?usp=sharing

Tổng hợp tổng thể tài liệu offline

Nhấn nhằm tải

https://drive.google.com/file/d/0BzMEcyRK_uUFcUVaNzNFVVlwWm8/view?usp=sharing

http://www.bzarg.com/p/how-a-kalman-filter-works-in-pictures/

Hy vọng vào tương lai, ai đó trong họ sẽ quay lại để share kiến thức của bản thân mình về cách tiếp cận bộ lọc Kalman, để độc giả có thời cơ học hỏi nhiều hơn thế nữa. Mong bài viết này hữu dụng cho mọi fan ^^ . Yeah. Đây cũng là nội dung bài viết đánh dấu mốc quan trọng đặc biệt về hoạt động của mình bên trên romanhords.com , bản thân xin gởi lời cảm ơn trân thành tới chúng ta đã ủng hộ bản thân và các tác giả trong quãng thời gian vừa qua, sự khích lệ từ mọi tín đồ là nguồn cổ vũ to bự để chúng mình có thêm nụ cười và cồn lực nhắm tới mục tiêu share kiến thức cùng rất romanhords.com.