Mpu6050 den 6 dof imu ivme ve gyro bilgilerini kalman filtresi ile birleştirip açı bilgisi elde etmem gerekiyor.Sitede bakmadığım konu kalmadı teori ağırlıklı anlatımlar mevcut hep ve barış samancının sitesinede baktım fakat çözemedim kalman filtresini algoritma olarak oluşturamıyorum yardım eden arkadaşlara şimdiden teşekkür ederim.
Kalman filtresini lowpass olarak mi kullanacaksiniz ?
Hazır kodmu istiyorsunuz. yanımda bir çalışma olacaktı
Fikir vermesi için hazır kod çok iyi olur algoritmasını anlamam lazım
kalman filitresinin elindeki aletlere göre tasarlanması gerekiyor + evet konu matematik içeriyor ve daha basitleştirmek mümkün değil.
Herkese uyan bir silver bullet yok ne yazık ki.
Muhitin_kaplan low pass dan ziyade gyro ve ivme bilgilerinin kalman ile açıya dönüştüğü algoritması lazım matematiksel formülden algoritmaya dönüşümü yani
mesaj birleştirme:: 06 Kasım 2015, 02:39:19
Icarus herkeze uyması önemli değil kalman filtresinin hep teori kısmı var algoritma olarak çözümleyebiliceğimiz bir bilgiye rastlayamadım bir tek barış samancı nın sitesinde vardı fakat net olarak anlayamadım nasıl kullanılır nasıl adapte edilir yazılıma teoriden uygulamaya geçişi şeklinde genel bir bilgi bulamadım açıklayıcı o yüzden konu açmayı gerek gördüm elimdeki alet mpu6050 gyro ve ivme ölçeri pic ile haberleştirip bilgileri alıp kalman filtresiyle birleştirip düzgün bir açı elde etmek için kullanmam gerekiyor
http://bilgin.esme.org/BitsBytes/KalmanFilterforDummies.aspx (http://bilgin.esme.org/BitsBytes/KalmanFilterforDummies.aspx)
mesaj birleştirme:: 05 Kasım 2015, 14:53:59
http://acikders.ankara.edu.tr/pluginfile.php/1324/mod_resource/content/2/K%C4%B1s%C4%B1m-3.pdf (http://acikders.ankara.edu.tr/pluginfile.php/1324/mod_resource/content/2/K%C4%B1s%C4%B1m-3.pdf)
ilk gönderdiğiniz linki incelemiştim fakat ingilizcem o kadar ileri seviyede değil ilk gönderdiğiniz linki c kodlarına nasıl dökebiliriz yardımcı olabilirseniz sevinirim
Kalman filtresi tek bir giriş için kullanılabilir mi?
ADC'den 100mS'de bir örnek alıyorum. Bu örnekleri kalman filtresinden nasıl geçiririm?
öncelikle sistemin state space modelini oluşturmanız lazım. nasıl bir modelle açı hesaplayabileceğiniz size kalmış. mesela en basit statik durumda ivme vektörünün açıları measurement olur, gyro rate'lerini dünyaya çevirirseniz(dcm diye aratın) bunlarda hız olur. sonra cov. matrislerini bulmanız lazım sensörün, sabit durumdaki ölçümlerden bulunabilir, gerisi matematik, yani bu verileri kalman denklemlerine gireceksiniz. kabaca böyle. burda asıl iş modeli oluşturmak, sistemin state space reprezentasyonunu yapabiliyorsanız kalman işi uygulamada kolay(teoriye hakim olmadan da yapabilrisinzi).
state space modelini nasıl oluşturabiliriz hiç bir bilgim yok bu konuda bir yol bulabilirsem arkası gelir diye düşünüyorum
@görkemO zaman bu konuya gelinceye kadar hatmetmen gereken dünya kadar şey var.
Şu anda nasıl bir şey istiyorsun biliyormusun?
Arkadaşın grip olmuş ve doktora gitmiş. Doktor da ona bir ilaç yazmış.
Sen de amel olmuşsun. İyileşmek için arkadaşından doktorun verdiği ilacı istiyorsun.
Birde bunu incele
http://www.ibrahimcayiroglu.com/Dokumanlar/Makale_BilgiPaylasim/2012-1-Kalman_Filtresi_Ve_Bir_Programlama_Ornegi.pdf (http://www.ibrahimcayiroglu.com/Dokumanlar/Makale_BilgiPaylasim/2012-1-Kalman_Filtresi_Ve_Bir_Programlama_Ornegi.pdf)
Şunu kesinlikle belirteyim Kalmam filtresi acılarla ilgili bir şey değildir. Sadece yapılan ölçümleri düzenler. Önce bu ayırımı yapmak lazım. Ölçümleri ani sıçrama ve parazitleri filtreler. Bunu lineer bir şekilde önceki ölçülere göre yapar.
benim ihtiyacım olan 2 veriyi tek denklemde düzenlemek ve açıya çevirmek daha sonrada kalman filtresine yönelmem gerekli sanırım
Alıntı yapılan: robomaster - 05 Kasım 2015, 20:04:59
Şunu kesinlikle belirteyim Kalmam filtresi acılarla ilgili bir şey değildir. Sadece yapılan ölçümleri düzenler. Önce bu ayırımı yapmak lazım. Ölçümleri ani sıçrama ve parazitleri filtreler. Bunu lineer bir şekilde önceki ölçülere göre yapar.
Peki filtreleme bir girişime göre yapılıyor yoksa daha fazla girişe göremi?
Ben tek kanaldan ADC okuyorum. Parazitli bir giriş. Bunu nasıl kalman ile filtrelerim?
2 veriyi tek denkleme nasıl çevirebiliriz gyro ve ivme sensöründen gelen verileri tek açı bilgimizi elde etmek için
http://www.muhittinkaplan.com/?p=29 (http://www.muhittinkaplan.com/?p=29)
buradaki K ve R sabitleriyle oynarak filtreyi yapabilirsiniz,
ivme dediğin vektörel bir bilgi. A noktasından B noktasına ne hızda hareket ettiğini verir. Eğer sen bu hızın açısını merak ediyorsan. A noktasındaki x,y,z bilgileri ile B noktasındaki xyz bilgileri arasında ivmene göre bir doğru olduğunu varsayıp 3 boyutlu analitik düzlemde doğrunun açısını bulabilirsin. Ya da ben böyle yapardım :)
Alıntı yapılan: remzi - 05 Kasım 2015, 20:28:33
Peki filtreleme bir girişime göre yapılıyor yoksa daha fazla girişe göremi?
Ben tek kanaldan ADC okuyorum. Parazitli bir giriş. Bunu nasıl kalman ile filtrelerim?
Her bir eksen için x , y , z ( yada hangilerini kullanacaksan) ayrı ayrı kalman filtren çalışacak.
Açıları bulmak filtre çıkışından gelen okumalar ile ilgili, kalman ile ilgili değil. Gyro ise ap ayrı bir mevzu. Şimdilik sadece
ivmeölçer ile statik durumda açıları bulmak ile başla bence.
Muhittin hocanın sitesindeki uygulamaları bir incele.
Arduino için örnek kod var mı acaba ...
özür dilerim cevap vermekte biraz geç kaldım. Forumda cevaplar geç gelince çekilen sıkıntıyı bilirim
kullanılan sensörler itg3200 ve adxl340 sen bunu kendi sensürüne uyarlarsın.tüm arduino kodu altta;
kodlarda Complimentary ve kalman filtresini karşılaştırmış, yani her iki filtre tipi var.Biraz uğraştıktan sonra meseleyi çözersin.
Bu kısımda başta sensörlerin kalibrasyonu yapılıyor;
for (i = 0; i < 100; i += 1) {
getGyroscopeReadings(Gyro_output);
getAccelerometerReadings(Accel_output);
Gyro_cal_x_sample += Gyro_output[0];
Gyro_cal_y_sample += Gyro_output[1];
Gyro_cal_z_sample += Gyro_output[2];
Accel_cal_x_sample += Accel_output[0];
Accel_cal_y_sample += Accel_output[1];
Accel_cal_z_sample += Accel_output[2];
delay(50);
}
Gyro_cal_x = Gyro_cal_x_sample / 100;
Gyro_cal_y = Gyro_cal_y_sample / 100;
Gyro_cal_z = Gyro_cal_z_sample / 100;
Accel_cal_x = Accel_cal_x_sample / 100;
Accel_cal_y = Accel_cal_y_sample / 100;
Accel_cal_z = (Accel_cal_z_sample / 100) - 256; // Raw Accel output in z-direction is in 256 LSB/g due to gravity
and must be off-set by approximately 256}
Yani mesela Gyro_cal_x değeri kalibrayon sonucunda bulunan ofsett miktarı.
#include <Wire.h>
int Gyro_output[3], Accel_output[3];
float dt = 0.02;
float Gyro_cal_x, Gyro_cal_y, Gyro_cal_z, Accel_cal_x, Accel_cal_y, Accel_cal_z;
float Gyro_pitch = 0; //Initialize value
float Accel_pitch = 0; //Initial Estimate
float Predicted_pitch = 0; //Initial Estimate
float Gyro_roll = 0; //Initialize value
float Accel_roll = 0; //Initialize value
float Predicted_roll = 0; //Output of Kalman filter
float Q = 0.1; // Prediction Estimate Initial Guess
float R = 5; // Prediction Estimate Initial Guess
float P00 = 0.1; // Prediction Estimate Initial Guess
float P11 = 0.1; // Prediction Estimate Initial Guess
float P01 = 0.1; // Prediction Estimate Initial Guess
float Kk0, Kk1;
float Comp_pitch;
float Comp_roll;
unsigned long timer;
unsigned long time;
void writeTo(byte device, byte toAddress, byte val) {
Wire.beginTransmission(device);
Wire.write(toAddress);
Wire.write(val);
Wire.endTransmission();
}
// Adapted from Arduino.cc/forums for reading in sensor data
void readFrom(byte device, byte fromAddress, int num, byte result[]) {
Wire.beginTransmission(device);
Wire.write(fromAddress);
Wire.endTransmission();
Wire.requestFrom((int)device, num);
int i = 0;
while(Wire.available()) {
result[i] = Wire.read();
i++;
}
}
void getGyroscopeReadings(int Gyro_output[]) {
byte buffer[6];
readFrom(0x68,0x1D,6,buffer);
Gyro_output[0] = (((int)buffer[0]) << 8 ) | buffer[1];
Gyro_output[1] = (((int)buffer[2]) << 8 ) | buffer[3];
Gyro_output[2] = (((int)buffer[4]) << 8 ) | buffer[5];
}
void getAccelerometerReadings(int Accel_output[]) {
byte buffer[6];
readFrom(0x53,0x32,6,buffer);
Accel_output[0] = (((int)buffer[1]) << 8 ) | buffer[0];
Accel_output[1] = (((int)buffer[3]) << 8 ) | buffer[2];
Accel_output[2] = (((int)buffer[5]) << 8 ) | buffer[4];
}
void setup() {
int Gyro_cal_x_sample = 0;
int Gyro_cal_y_sample = 0;
int Gyro_cal_z_sample = 0;
int Accel_cal_x_sample = 0;
int Accel_cal_y_sample = 0;
int Accel_cal_z_sample = 0;
int i;
delay(5);
Wire.begin();
Serial.begin(115200); // Registers set
writeTo(0x53,0x31,0x09); //Set accelerometer to 11bit, +/-4g
writeTo(0x53,0x2D,0x08); //Set accelerometer to measure mode
writeTo(0x68,0x16,0x1A); //Set gyro +/-2000deg/sec and 100Hz Low Pass Filter
writeTo(0x68,0x15,0x09); //Set gyro 100Hz sample rate
Serial.print("time\tGyro_pitch\tAccel_pitch\tComp_pitch\tPredicted_pitch\tGyro_roll\tAccel_roll\tComp_roll\tPre
dicted_roll\ty\tp\tr\n");
delay(100);
for (i = 0; i < 100; i += 1) {
getGyroscopeReadings(Gyro_output);
getAccelerometerReadings(Accel_output);
Gyro_cal_x_sample += Gyro_output[0];
Gyro_cal_y_sample += Gyro_output[1];
Gyro_cal_z_sample += Gyro_output[2];
Accel_cal_x_sample += Accel_output[0];
Accel_cal_y_sample += Accel_output[1];
Accel_cal_z_sample += Accel_output[2];
delay(50);
}
Gyro_cal_x = Gyro_cal_x_sample / 100;
Gyro_cal_y = Gyro_cal_y_sample / 100;
Gyro_cal_z = Gyro_cal_z_sample / 100;
Accel_cal_x = Accel_cal_x_sample / 100;
Accel_cal_y = Accel_cal_y_sample / 100;
Accel_cal_z = (Accel_cal_z_sample / 100) - 256; // Raw Accel output in z-direction is in 256 LSB/g due to gravity
and must be off-set by approximately 256
}
void loop() {
timer = millis();
getGyroscopeReadings(Gyro_output);
getAccelerometerReadings(Accel_output);
Accel_pitch = atan2((Accel_output[1] - Accel_cal_y) / 256, (Accel_output[2] - Accel_cal_z) / 256) * 180 / PI;
Gyro_pitch = Gyro_pitch + ((Gyro_output[0] - Gyro_cal_x) / 14.375) * dt;
//if(Gyro_pitch<180) Gyro_pitch+=360; // Keep within range of 0-180 deg to match Accelerometer output
//if(Gyro_pitch>=180) Gyro_pitch-=360;
Comp_pitch = Gyro_pitch;
Predicted_pitch = Predicted_pitch + ((Gyro_output[0] - Gyro_cal_x) / 14.375) * dt; // Time Update step 1
Accel_roll = atan2((Accel_output[0] - Accel_cal_x) / 256, (Accel_output[2] - Accel_cal_z) / 256) * 180 / PI;
Gyro_roll = Gyro_roll - ((Gyro_output[1] - Gyro_cal_y) / 14.375) * dt;
//if(Gyro_roll<180) Gyro_roll+=360; // Keep within range of 0-180 deg
//if(Gyro_roll>=180) Gyro_roll-=360;
Comp_roll = Gyro_roll;
Predicted_roll = Predicted_roll - ((Gyro_output[1] - Gyro_cal_y) / 14.375) * dt; // Time Update step 1
P00 += dt * (2 * P01 + dt * P11); // Projected error covariance terms from derivation result: Time Update step 2
P01 += dt * P11; // Projected error covariance terms from derivation result: Time Update step 2
P00 += dt * Q; // Projected error covariance terms from derivation result: Time Update step 2
P11 += dt * Q; // Projected error covariance terms from derivation result: Time Update step 2
Kk0 = P00 / (P00 + R); // Measurement Update step 1
Kk1 = P01 / (P01 + R); // Measurement Update step 1
Predicted_pitch += (Accel_pitch - Predicted_pitch) * Kk0; // Measurement Update step 2
Predicted_roll += (Accel_roll - Predicted_roll) * Kk0; // Measurement Update step 2
P00 *= (1 - Kk0); // Measurement Update step 3
P01 *= (1 - Kk1); // Measurement Update step 3
P11 -= Kk1 * P01; // Measurement Update step 3
float alpha = 0.98;
Comp_pitch = alpha*(Comp_pitch+Comp_pitch*dt) + (1.0 - alpha)*Accel_pitch; // Complimentary filter
Comp_roll = alpha*(Comp_roll+Comp_roll*dt) + (1.0 - alpha)*Accel_roll; // Complimentary filter
float angle_z = Gyro_output[2];
time=millis();
Serial.print(time);
Serial.print("\t");
Serial.print(Gyro_pitch);
Serial.print("\t");
Serial.print(Accel_pitch);
Serial.print("\t");
Serial.print(Comp_pitch);
Serial.print("\t");
Serial.print(Predicted_pitch);
Serial.print("\t");
Serial.print(Gyro_roll);
Serial.print("\t");
Serial.print(Accel_roll);
Serial.print("\t");
Serial.print(Comp_roll);
Serial.print("\t");
Serial.print(Predicted_roll);
Serial.print("\n");
timer = millis() - timer;
timer = (dt * 1000) - timer;
delay(timer);
}
Dualarını eksik etme ;)
@zengdai hiç önemli değil ilginiz ve alakanız için teşekkür ederim sağolun eksik etmicem :)
Arduino'da yapılmış çalışma sizin için örnek olabilir.
Buradaki kütüphaneleri ve kodları kullanacağınız derleyiciye göre uyarlarsanız çalışır.
https://github.com/TKJElectronics/Example-Sketch-for-IMU-including-Kalman-filter/tree/master/IMU/MPU6050
Teşekkür ederim ilginiz için