MPU6050のサンプルプログラム2

Dependencies:   ConfigFile SDFileSystem mbed

Fork of LAURUS_program by LAURUS

Files at this revision

API Documentation at this revision

Comitter:
ojan
Date:
Sat May 30 18:08:34 2015 +0000
Parent:
2:d2b60a1d0cd9
Child:
4:45dc5590abc0
Commit message:
estimate geomagnetism vector with Kalman Filter

Changed in this revision

LPS25H/LPS25H.h Show annotated file Show diff for this revision Revisions of this file
LPS25H/typedef.h Show annotated file Show diff for this revision Revisions of this file
Log/Log.cpp Show annotated file Show diff for this revision Revisions of this file
Log/Log.h Show annotated file Show diff for this revision Revisions of this file
Matrix/Matrix.cpp Show annotated file Show diff for this revision Revisions of this file
Matrix/Matrix.h Show annotated file Show diff for this revision Revisions of this file
RingBuffer/RingBuffer.cpp Show annotated file Show diff for this revision Revisions of this file
RingBuffer/RingBuffer.h Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
Vector/Vector.cpp Show annotated file Show diff for this revision Revisions of this file
Vector/Vector_Matrix_operator.cpp Show annotated file Show diff for this revision Revisions of this file
Vector/Vector_Matrix_operator.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
myConstants.h Show annotated file Show diff for this revision Revisions of this file
--- a/LPS25H/LPS25H.h	Sun May 24 17:44:11 2015 +0000
+++ b/LPS25H/LPS25H.h	Sat May 30 18:08:34 2015 +0000
@@ -36,6 +36,8 @@
 #include "mbed.h"
 #include "typedef.h"
 
+
+
 class LPS25H{
 public:
     LPS25H (PinName sda, PinName scl);
@@ -51,8 +53,8 @@
     
     I2C* _i2c;
 
-    DWORD_VAL press;
-    WORD_VAL temp;
+    LPS_Typedef::DWORD_VAL press;
+    LPS_Typedef::WORD_VAL temp;
     char buf[2];
 
 };
--- a/LPS25H/typedef.h	Sun May 24 17:44:11 2015 +0000
+++ b/LPS25H/typedef.h	Sat May 30 18:08:34 2015 +0000
@@ -9,47 +9,51 @@
 #ifndef TYPEDEF_H
 #define TYPEDEF_H
 
-typedef unsigned char       BYTE;                           /* 8-bit unsigned  */
-typedef unsigned short int  WORD;                           /* 16-bit unsigned */
-typedef unsigned int        DWORD;                          /* 32-bit unsigned */
-typedef unsigned long long  QWORD;                          /* 64-bit unsigned */
-
-
-typedef union
-{
-    WORD Val;
-    BYTE v[2];
-    short S;
-    struct
-    {
-        BYTE LB;
-        BYTE HB;
-    } byte;
-} WORD_VAL;
+namespace LPS_Typedef {
 
-typedef union
-{
-    DWORD Val;
-    WORD w[2];
-    BYTE v[4];
-    struct
+    typedef unsigned char       BYTE;                           /* 8-bit unsigned  */
+    typedef unsigned short int  WORD;                           /* 16-bit unsigned */
+    typedef unsigned int        DWORD;                          /* 32-bit unsigned */
+    typedef unsigned long long  QWORD;                          /* 64-bit unsigned */
+    
+    
+    typedef union
     {
-        WORD LW;
-        WORD HW;
-    } word;
-    struct
+        WORD Val;
+        BYTE v[2];
+        short S;
+        struct
+        {
+            BYTE LB;
+            BYTE HB;
+        } byte;
+    } WORD_VAL;
+    
+    typedef union
     {
-        BYTE LB;
-        BYTE HB;
-        BYTE UB;
-        BYTE MB;
-    } byte;
-    struct
-    {
-        WORD_VAL low;
-        WORD_VAL high;
-    }wordUnion;
+        DWORD Val;
+        WORD w[2];
+        BYTE v[4];
+        struct
+        {
+            WORD LW;
+            WORD HW;
+        } word;
+        struct
+        {
+            BYTE LB;
+            BYTE HB;
+            BYTE UB;
+            BYTE MB;
+        } byte;
+        struct
+        {
+            WORD_VAL low;
+            WORD_VAL high;
+        }wordUnion;
+    
+    } DWORD_VAL;
 
-} DWORD_VAL;
+}
 
 #endif /* TYPEDEF_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Log/Log.cpp	Sat May 30 18:08:34 2015 +0000
@@ -0,0 +1,114 @@
+#include "Log.h"
+
+Log::Log(PinName rx, PinName tx, PinName mosi, PinName miso, PinName sck, PinName cs, const char* name) :
+    _device(rx, tx), _sd(mosi, miso, sck, cs, name){
+    buf_send.initialize_buffer();
+    _device.attach(this, &Log::int_serial_tx, Serial::TxIrq);
+}
+
+int Log::initialize_sdlog(const char* str){
+    char filename[15];
+    int n = find_last();
+    if(n < 0) return 0;
+    
+    //ログ番号を+1してファイルを新規作成
+    //ファイル名は"logXXX.csv"
+    sprintf(filename, "/sd/log%03d.csv", n+1);
+    fp = fopen(filename, "w");
+    
+    _device.printf(str);
+    fprintf(fp, str);
+    return 1;
+}
+
+void Log::close(){
+    wait(0.5);
+    fclose(fp);
+}
+
+//SDカード内からログ番号の最大値を取得する関数
+int Log::find_last() {
+    int i, n = 0;
+    char c;
+    DIR *dp;
+    struct dirent *dirst;
+    dp = opendir("/sd/");
+    if (!dp){
+        printf("Could not open directry\n");
+        return -1;
+    }
+    while((dirst = readdir(dp)) != NULL) {
+        if(sscanf(dirst->d_name, "log%03d.csv%c", &i, &c) == 1 && i>n) {
+            n = i;
+        }
+    }
+    closedir(dp);
+    return n;
+}
+
+void Log::puts(const char* str){
+    int16_t len=strlen(str);
+    int16_t capa=buf_send.buffer_capacity();
+    bool empty=buf_send.is_buffer_empty();
+    char ch;
+    if(len>capa){
+        len=capa;
+    }
+    buf_send.write_buffer((const uint8_t*)str, 0, len);
+    if((_device.writeable()) && (empty)){
+        ch=buf_send.read_buffer_byte();
+        _device.putc(ch);
+        fputc(ch, fp);
+    } 
+}
+
+void Log::putc(char ch){
+    int16_t capa=buf_send.buffer_capacity();
+    if(capa==0) return;
+    buf_send.write_buffer_byte(ch);
+}
+
+void Log::write_data(uint8_t* buf, int16_t size){
+    int capa=buf_send.buffer_capacity();
+    if(size>capa){
+        size=capa;
+    }
+    buf_send.write_buffer(buf, 0, size);
+}
+
+bool Log::is_empty(){
+    return buf_send.is_buffer_empty();
+}
+
+int16_t Log::recieve_buffer_size(){
+    return buf_recieve.buffer_size();
+}
+
+int16_t Log::getc(){
+    if(buf_recieve.is_buffer_empty()){
+        return -1;
+    }
+    return buf_recieve.read_buffer_byte();
+}
+
+int16_t Log::read_data(uint8_t* buf, int16_t size){
+    int len=buf_recieve.buffer_size();
+    if(size>len){
+        size=len;
+    }
+    buf_recieve.read_buffer(buf, 0, size);
+    return size;
+}
+
+char Log::int_tx(){
+    return buf_send.read_buffer_byte();
+}
+
+void Log::int_serial_tx(){
+    char ch;
+    while((_device.writeable()) && (buf_send.is_buffer_empty()==false)){
+        ch=buf_send.read_buffer_byte();
+        _device.putc(ch);
+        fputc(ch, fp);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Log/Log.h	Sat May 30 18:08:34 2015 +0000
@@ -0,0 +1,37 @@
+//**** Log.h ****
+//ログをリングバッファを用いて、
+//シリアル送信、SDカード出力を行う
+//***************
+
+#ifndef LOG_H_ 
+#define LOG_H_ 
+
+#include "mbed.h"
+#include "SDFileSystem.h"
+#include "RingBuffer.h"
+
+class Log{
+public:
+    Log(PinName rx, PinName tx, PinName mosi, PinName miso, PinName sck, PinName cs, const char* name);
+    int initialize_sdlog(const char* str);
+    void close();
+    int find_last();
+    void puts(const char *str);
+    void putc(char ch);
+    void write_data(uint8_t* buf, int16_t size);
+    bool is_empty();
+    int16_t recieve_buffer_size();
+    int16_t getc();
+    int16_t read_data(uint8_t* buf, int16_t size);
+    char int_tx();
+    void int_serial_tx();
+
+protected:
+    SDFileSystem _sd;
+    FILE *fp;
+    Serial _device;
+    RingBuffer buf_send;
+    RingBuffer buf_recieve;
+};
+
+#endif /* LOG_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Matrix/Matrix.cpp	Sat May 30 18:08:34 2015 +0000
@@ -0,0 +1,389 @@
+#include "mbed.h"
+#include "myConstants.h"
+#include "Matrix.h"
+
+
+
+Matrix::Matrix(int row, int col) : row(row), col(col), components(0) {
+    components = new float[row*col];
+    if (!components) AbortWithMsg("Memory Allocation Error");
+    for(int i=0; i<row*col; i++) components[i] = 0.0f;
+    if (row == col) {
+        for (int i = 0; i < row; i++) {
+            components[i * col + i] = 1.0f;
+        }
+    }
+}
+
+Matrix::Matrix(int row, int col, float* comps) : row(row), col(col), components(0) {
+    components = new float[row*col];
+    if (!components) AbortWithMsg("Memory Allocation Error");
+    memcpy(components, comps, sizeof(float)*row*col);
+}
+
+
+Matrix::~Matrix() {
+    delete[] components;
+}
+
+Matrix::Matrix(const Matrix& m) : row(m.row), col(m.col), components(0) {
+    components = new float[row*col];
+    if (!components) AbortWithMsg("Memory Allocation Error");
+    memcpy(components, m.GetpComponents(), sizeof(float)*row*col);
+}
+
+Matrix Matrix::operator-() const{
+    Matrix retMat(*this);
+
+    for (int i = 0; i < row * col; i++) {
+        retMat.components[i] = - this->components[i];
+    }
+
+    return retMat;
+}
+
+Matrix& Matrix::operator=(const Matrix& m) {
+    if (this == &m) return *this;
+    row = m.row;
+    col = m.col;
+    delete[] components;
+    components = new float[row*col];
+    if (!components) AbortWithMsg("Memory Allocation Error");
+    memcpy(components, m.GetpComponents(), sizeof(float)*row*col);
+
+    return *this;
+}
+
+Matrix& Matrix::operator+=(const Matrix& m) {
+    if (row != m.GetRow() || col != m.GetCol()) AbortWithMsg("Irregular Dimention");
+    
+    for (int i = 0; i < row; i++) {
+        for (int j = 0; j < col; j++) {
+            components[i * col + j] += m.components[i * col + j];
+        }
+    }
+
+    this->CleanUp();
+
+    return *this;
+}
+
+Matrix& Matrix::operator-=(const Matrix& m) {
+    if (row != m.GetRow() || col != m.GetCol()) AbortWithMsg("Irregular Dimention");
+
+    for (int i = 0; i < row; i++) {
+        for (int j = 0; j < col; j++) {
+            components[i * col + j] -= m.components[i * col + j];
+        }
+    }
+
+    this->CleanUp();
+
+    return *this;
+}
+/*
+Matrix& Matrix::operator*=(const Matrix& m) {
+    if (col != m.GetRow()) AbortWithMsg("Irregular Dimention");
+    Matrix temp = Matrix(*this);
+    
+    col = m.GetCol();
+    delete[] components;
+    components = new float[row*col];
+
+    for (int i = 0; i < row; i++) {
+        for (int j = 0; j < col; j++) {
+            components[i*col + j] = 0.0f;
+            for (int k = 0; k < m.GetRow(); k++) {
+                components[i * col + j] += temp.components[i * col + k] * m.components[k * col + j];
+            }
+        }
+    }
+
+    this->CleanUp();
+
+    return *this;
+}
+*/
+
+Matrix& Matrix::operator*=(float c) {
+    for (int i = 0; i < row; i++) {
+        for (int j = 0; j < col; j++) {
+            components[i*col + j] *= c;
+        }
+    }
+
+    return *this;
+}
+
+Matrix& Matrix::operator/=(float c) {
+    if (fabs(c) < NEARLY_ZERO) AbortWithMsg("Division by Zero");
+    for (int i = 0; i < row; i++) {
+        for (int j = 0; j < col; j++) {
+            components[i*col + j] /= c;
+        }
+    }
+
+    return *this;
+}
+
+void Matrix::SetComp(int rowNo, int colNo, float val) {
+    if (rowNo > row || colNo > col) AbortWithMsg("Index Out of Bounds Error");
+    components[(rowNo-1)*col + (colNo-1)] = val;
+}
+
+void Matrix::SetComps(float* pComps) {
+    memcpy(components, pComps, sizeof(float) * row * col);
+}
+
+float Matrix::Determinant() const{
+    if (row != col) AbortWithMsg("failed to calculate det. : matrix is not square");
+    int decSign = 0;
+    float retVal = 1.0f;
+
+    // 行列のLU分解
+    Matrix LU(this->LU_Decompose(&decSign));
+
+    for (int i = 0; i < LU.row; i++) {
+        retVal *= LU.components[i * LU.col + i];
+    }
+
+    return retVal*decSign;
+}
+
+float Matrix::det() const {
+    if (row != col) AbortWithMsg("failed to calculate det : matrix is not square");
+    
+    Matrix temp(*this);
+    int decSign = 1;
+
+    for (int j = 0; j < col - 1; j++) {
+
+        // 列内のみで最大の要素を探す
+        int maxNo = j;
+        for (int k = j; k < row; k++) {
+            if (temp.components[maxNo * col + j] < temp.components[k * col + j]) maxNo = k;
+        }
+        if (maxNo != j) {
+            temp.SwapRow(j + 1, maxNo + 1);
+            decSign *= -1;
+        }
+        // 列内の最大要素が小さ過ぎる場合、行内の最大要素も探す
+        if (fabs(temp.components[j * col + j]) < NEARLY_ZERO) {
+            maxNo = j;
+            for (int k = j; k < col; k++) {
+                if (temp.components[j * col + maxNo] < temp.components[j * col + k])maxNo = k;
+            }
+            if (maxNo != j) {
+                temp.SwapCol(j + 1, maxNo + 1);
+                decSign *= -1;
+            }
+
+            // 列内、行内の最大要素を選んでも小さすぎる場合はエラー
+            if (fabs(temp.components[j * col + j]) < NEARLY_ZERO) {
+                if (row != col) AbortWithMsg("failed to calculate det : Division by Zero");
+            }
+        }
+
+        float c1 = 1.0f / temp.components[j * col + j];
+
+        for (int i = j + 1; i < row; i++) {
+            float c2 = temp.components[i * col + j] * c1;
+            for (int k = j; k < col; k++) {
+                temp.components[i * col + k] = temp.components[i * col + k] - c2 * temp.components[j * col + k];
+            }
+        }
+        
+    }
+
+    if (fabs(temp.components[(row - 1) * col + (col - 1)]) < NEARLY_ZERO) return 0.0f;
+
+    float retVal = 1.0f;
+    for (int i = 0; i < row; i++) {
+        retVal *= temp.components[i * col + i];
+    }
+
+    return retVal * decSign;
+}
+
+Matrix Matrix::LU_Decompose(int* sign, Matrix* p) const{
+    if (row != col) AbortWithMsg("failed to LU decomposition: matrix is not square");
+    if (sign != 0) *sign = 1;
+    if (p != 0) {
+        if (p->row != row || p->row != p->col) AbortWithMsg("failed to LU decomposition: permitation matrix is incorrect");
+        // 置換行列は最初に単位行列にしておく
+        memset(p->components, 0, sizeof(float) * row * col);
+        for (int i = 0; i < row; i++) {
+            p->components[i * col + i] = 1.0f;
+        }
+    }
+    Matrix retVal(*this);
+
+    for (int d = 0; d < row - 1; d++) { // 1行1列ずつ分解を行う
+        // d列目の最大の要素を探索し、見つけた要素の行とd行目を交換する
+        int maxNo = d;
+        for (int i = d; i < row; i++) {
+            if (retVal.components[i * col + d] > retVal.components[maxNo * col + d]) maxNo = i;
+        }
+        if (maxNo != d) {
+            retVal.SwapRow(d + 1, maxNo + 1);
+            if (sign != 0) *sign *= -1;
+            if (p != 0) {
+                p->SwapRow(d + 1, maxNo + 1);
+            }
+        }
+        float c = retVal.components[d * col + d];
+        if (fabs(c) < NEARLY_ZERO) AbortWithMsg("failed to LU decomposition: Division by Zero");
+
+        // d行d列目以降の行列について計算
+        for (int i = d+1; i < row; i++) {
+            retVal.components[i * col + d] /= c;
+            for (int j = d+1; j < col; j++) {
+                retVal.components[i * col + j] -= retVal.components[d * col + j] * retVal.components[i * col + d];
+            }
+        }
+    }
+
+    retVal.CleanUp();
+
+    return retVal;
+}
+
+float Matrix::Inverse(Matrix& invm) const{
+    if (row != col) AbortWithMsg("failed to get Inv. : matrix is not square");
+
+    Matrix P(*this);
+    Matrix LU(LU_Decompose(0, &P));
+
+    // 分解した行列の対角成分の積から行列式を求める
+    // det = 0 ならfalse
+    float det = 1.0f;
+    for (int i = 0; i < row; i++) {
+        det *= LU.components[i * col + i];
+    }
+    if (fabs(det) < NEARLY_ZERO) {
+        return fabs(det);
+    }
+
+    // U、Lそれぞれの逆行列を計算する
+    Matrix U_inv = Matrix(row, col);
+    Matrix L_inv = Matrix(row, col);
+
+    for (int j = 0; j < col; j++) {
+        for (int i = 0; i <= j; i++) {
+            int i_U = j - i;        // U行列の逆行列は対角成分から上へ向かって
+                                    // 左から順番に値を計算する
+
+            int j_L = col - 1 - j;  // L行列の逆行列は右から順番に
+            int i_L = j_L + i;      // 対角成分から下へ向かって計算する
+
+            if (i_U != j) { // 非対角成分
+                float temp_U = 0.0f;
+                float temp_L = 0.0f;
+
+                for (int k = 0; k < i; k++) {
+
+                    temp_U -= U_inv.components[(j - k) * col + j] * LU.components[i_U * col + (j - k)];
+                    
+                    if (k == 0) {
+                        temp_L -= LU.components[i_L * col + j_L];
+                    } else {
+                        temp_L -= L_inv.components[(j_L + k) * col + j_L] * LU.components[i_L * col + j_L + k];
+                    }
+                    
+                }
+
+                U_inv.components[i_U * col + j] = temp_U / LU.components[i_U * col + i_U];
+                L_inv.components[i_L * col + j_L] = temp_L;
+
+            } else {    // 対角成分
+                if (fabs(LU.components[i_U * col + i_U]) >= NEARLY_ZERO) {
+                    U_inv.components[i_U * col + i_U] = 1.0f / LU.components[i_U * col + i_U];
+                }
+            }
+        }
+    }
+
+    invm = U_inv * L_inv * P;
+
+    return -1.0f;
+}
+
+Matrix Matrix::Transpose() const{
+    //if (row != col) AbortWithMsg("failed to get Trans. : matrix is not square");
+    Matrix retVal(col, row);
+
+    for (int i = 0; i < row; i++) {
+        for (int j = 0; j < col; j++) {
+            retVal.components[j * row + i] = this->components[i * col + j];        
+        }
+    }
+
+    return retVal;
+}
+
+Matrix operator+(const Matrix& lhm, const Matrix& rhm) {
+    Matrix temp = Matrix(lhm);
+    temp += rhm;
+    return temp;
+}
+
+Matrix operator-(const Matrix& lhm, const Matrix& rhm) {
+    Matrix temp = Matrix(lhm);
+    temp -= rhm;
+    return temp;
+}
+
+Matrix operator*(const Matrix& lhm, const Matrix& rhm) {
+    if(lhm.GetCol() != rhm.GetRow()) AbortWithMsg("Matrix product Error: Irregular Dimention.");
+    int row = lhm.GetRow();
+    int col = rhm.GetCol();
+    int sum = lhm.GetCol();
+    Matrix temp(row, col);
+    
+    for (int i = 1; i <= row; i++) {
+        for (int j = 1; j <= col; j++) {
+            float temp_c = 0.0f;
+            for (int k = 1; k <= sum; k++) {
+                temp_c += lhm.GetComp(i, k) * rhm.GetComp(k, j);
+            }
+            temp.SetComp(i, j, temp_c);
+        }
+    }
+    
+    return temp;
+}
+
+void Matrix::CleanUp() {
+    int num = row*col;
+    float maxComp = 0.0f;
+    for (int i = 0; i < num; i++) {
+        if (maxComp < fabs(components[i])) maxComp = fabs(components[i]);
+    }
+    if (maxComp > NEARLY_ZERO) {
+        for (int i = 0; i < num; i++) {
+            if (fabs(components[i]) / maxComp < ZERO_TOLERANCE) components[i] = 0.0f;
+        }
+    }
+}
+
+void Matrix::SwapRow(int rowNo1, int rowNo2) {
+    if (rowNo1 > row || rowNo2 > row) AbortWithMsg("Index Out of Bounds Error !!");
+    float* temp = new float[col];
+
+    memcpy(temp, components + (rowNo1 - 1) * col, sizeof(float) * col);
+    memcpy(components + (rowNo1 - 1) * col, components + (rowNo2 - 1) * col, sizeof(float) * col);
+    memcpy(components + (rowNo2 - 1) * col, temp, sizeof(float) * col);
+
+    delete[] temp;
+}
+
+void Matrix::SwapCol(int colNo1, int colNo2) {
+    if (colNo1 > col || colNo2 > col) AbortWithMsg("Index Out of Bounds Error !!");
+    float temp = 0.0f;
+
+    for (int i = 0; i < row; i++) {
+        temp = components[i * col + colNo1];
+        components[i * col + colNo1] = components[i * col + colNo2];
+        components[i * col + colNo2] = temp;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Matrix/Matrix.h	Sat May 30 18:08:34 2015 +0000
@@ -0,0 +1,115 @@
+#pragma once
+#include "ErrorLogger.h"
+
+class Matrix
+{
+public:
+    /********** コンストラクタ デストラクタ **********/
+    Matrix(int row, int col);
+    Matrix(int row, int col, float* comps);
+    ~Matrix();
+    Matrix(const Matrix& m);
+
+    /********** メンバ演算子 **********/
+    Matrix operator-() const;
+    Matrix& operator=(const Matrix& m);
+    Matrix& operator+=(const Matrix& m);
+    Matrix& operator-=(const Matrix& m);
+    //Matrix& operator*=(const Matrix& m);
+    Matrix& operator*=(float c);
+    Matrix& operator/=(float c);
+
+    /********** その他関数 **********/
+    /*
+        行列の成分を設定
+        引数:rowNo 行番号
+              colNo 列番号
+              val 設定値
+    */
+    void SetComp(int rowNo, int colNo, float val);
+
+    /*
+        行列の成分を全て設定。全成分を一度に指定する必要がある。
+        引数:pComps 設定値の入ったfloat配列。
+    */
+    void SetComps(float* pComps);
+    /*
+        行列式を計算する。行列が正方行列で無い場合にはエラー。
+    */
+    float Determinant() const;
+    
+    /*
+        行列式を計算する。行列が正方行列で無い場合にはエラー。
+    */
+    float det() const;
+
+    /*
+        行列をLU分解する
+        引数:sign (省略可)置換操作の符号を格納するポインタ
+             p (省略可)置換行列を格納する行列のポインタ。(分解する行列と同じ列数の正方行列)
+        返り値:LU分解後の行列。下三角要素がL、対角・上三角要素がUに対応する。
+    */
+    Matrix LU_Decompose(int* sign = 0, Matrix * p = 0) const;
+    
+    /*
+        逆行列を生成する
+        返り値で逆行列が存在するか否かを判断
+        引数:逆行列を格納する行列
+        返り値:逆行列が存在するか否か
+    */
+    float Inverse(Matrix& invm) const;
+    
+    /*
+        転置行列を生成する
+        返り値:転置行列
+    */
+    Matrix Transpose() const;
+    
+    /*
+        行列の行の入れ替えを行う
+        引数:rowNo1 行番号1
+             rowNo2 行番号2
+    */
+    void SwapRow(int rowNo1, int rowNo2);
+    /*
+        行列の列の入れ替えを行う
+        引数:colNo1 列番号1
+             colNo2 列番号2
+    */
+    void SwapCol(int colNo1, int colNo2);
+    
+    /********** インライン関数 **********/
+    inline int GetRow() const {
+        return row;
+    }
+
+    inline int GetCol() const {
+        return col;
+    }
+
+    inline const float* GetpComponents() const {
+        return (const float*)components;
+    }
+
+    inline float GetComp(int rowNo, int colNo) const {
+        if (rowNo > row || colNo > col) AbortWithMsg("Index Out of Bounds Error !!");
+        return components[(rowNo-1)*col + (colNo-1)];
+    }
+
+private:
+    int row;
+    int col;
+    float* components;
+
+    /*
+        行列の成分の中で無視できるほど小さい値を0と置き換える(掃除する)
+    */
+    void CleanUp();
+
+};
+
+// グローバル演算子
+Matrix operator+(const Matrix& lhm, const Matrix& rhm);
+Matrix operator-(const Matrix& lhm, const Matrix& rhm);
+Matrix operator*(const Matrix& lhm, const Matrix& rhm);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RingBuffer/RingBuffer.cpp	Sat May 30 18:08:34 2015 +0000
@@ -0,0 +1,63 @@
+#include "RingBuffer.h"
+
+void RingBuffer::initialize_buffer(){
+    start=0;
+    end=0;
+}
+
+int16_t RingBuffer::buffer_size(){
+    if(end >= start){
+        return end - start;
+    }
+    return RING_BUFFER_SIZE - (start - end);
+}
+
+uint8_t RingBuffer::read_buffer_byte(){
+    uint8_t a;
+    a=buffer[start];
+    start=(start+1)%RING_BUFFER_SIZE;
+    return a;
+}
+
+int16_t RingBuffer::read_buffer_short(){
+    int16_t a, b;
+    a=buffer[start];
+    b=buffer[(start+1)%RING_BUFFER_SIZE];
+    start=(start+2)%RING_BUFFER_SIZE;
+    return (a&0xff)|(b<<8);
+}
+
+void RingBuffer::read_buffer(uint8_t buf[], int16_t offset, int16_t size){
+    int16_t i;
+    uint8_t* p=buf+offset;
+    
+    for(i=0; i<size; i++){
+        *(p++)=buffer[start];
+        start=(start+1)%RING_BUFFER_SIZE;
+    }
+}
+
+int16_t RingBuffer::buffer_capacity(){
+    if(end >= start){
+        return RING_BUFFER_SIZE-(end-start)-1;
+    }
+    return (start-end)-1;
+}
+
+void RingBuffer::write_buffer_byte(uint8_t ch){
+    buffer[end]=ch;
+    end=(end+1)%RING_BUFFER_SIZE;
+}
+
+void RingBuffer::write_buffer(const uint8_t buf[], int16_t offset, int16_t size){
+    int16_t i;
+    const uint8_t* p=buf+offset;
+    for(i=0; i<size; i++){
+        buffer[end]=*(p++);
+        end=(end+1)%RING_BUFFER_SIZE;
+    }
+}
+
+bool RingBuffer::is_buffer_empty(){
+    return (start==end);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RingBuffer/RingBuffer.h	Sat May 30 18:08:34 2015 +0000
@@ -0,0 +1,26 @@
+#ifndef RING_BUFFER_H_
+#define RING_BUFFER_H_
+
+#include "mbed.h"
+
+#define RING_BUFFER_SIZE 512
+
+class RingBuffer{
+public:
+    void initialize_buffer();
+    int16_t buffer_size();
+    uint8_t read_buffer_byte();
+    int16_t read_buffer_short();
+    void read_buffer(uint8_t buf[], int16_t offset, int16_t size); 
+    int16_t buffer_capacity();
+    void write_buffer_byte(uint8_t ch);
+    void write_buffer(const uint8_t buf[], int16_t offset, int16_t size);
+    bool is_buffer_empty();
+
+protected:
+    uint8_t buffer[RING_BUFFER_SIZE];
+    int16_t start;
+    int16_t end;
+};
+
+#endif /* RING_BUFFER_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.lib	Sat May 30 18:08:34 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/mbed/code/SDFileSystem/#7b35d1709458
--- a/Vector/Vector.cpp	Sun May 24 17:44:11 2015 +0000
+++ b/Vector/Vector.cpp	Sat May 30 18:08:34 2015 +0000
@@ -6,9 +6,7 @@
 Vector::Vector(int dim) : dim(dim), components(0){
     components = new float[dim];
     if (!components) AbortWithMsg("Memory Allocation Error");
-    for(int i=0; i<dim; i++) {
-        components[i] = 0.0f;
-    }
+    for(int i=0; i<dim; i++) components[i] = 0.0f;
 }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vector/Vector_Matrix_operator.cpp	Sat May 30 18:08:34 2015 +0000
@@ -0,0 +1,35 @@
+#include "Vector_Matrix_operator.h"
+
+Vector operator*(const Matrix& lhm, const Vector& rhv) {
+    if (lhm.GetCol() != rhv.GetDim()) AbortWithMsg("Irregular Dimention");
+    Vector retVec(lhm.GetRow());
+
+    for (int i = 1; i <= lhm.GetRow(); i++) {
+        float temp = 0.0f;
+        for (int j = 1; j <= rhv.GetDim(); j++) {
+            temp += lhm.GetComp(i, j)*rhv.GetComp(j);
+        }
+        retVec.SetComp(i, temp);
+    }
+
+    retVec.CleanUp();
+
+    return retVec;
+}
+
+Vector operator*(const Vector& lhv, const Matrix& rhm) {
+    if (lhv.GetDim() != rhm.GetRow()) AbortWithMsg("Irregular Dimention");
+    Vector retVec(rhm.GetCol());
+
+    for (int i = 1; i <= rhm.GetCol(); i++) {
+        float temp = 0.0f;
+        for (int j = 1; j <= lhv.GetDim(); j++) {
+            temp += lhv.GetComp(j) * rhm.GetComp(j, i);
+        }
+        retVec.SetComp(i, temp);
+    }
+
+    retVec.CleanUp();
+
+    return retVec;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vector/Vector_Matrix_operator.h	Sat May 30 18:08:34 2015 +0000
@@ -0,0 +1,5 @@
+#include "Matrix.h"
+#include "Vector.h"
+
+Vector operator*(const Matrix& lhm, const Vector& rhv);
+Vector operator*(const Vector& lhv, const Matrix& rhm);
\ No newline at end of file
--- a/main.cpp	Sun May 24 17:44:11 2015 +0000
+++ b/main.cpp	Sat May 30 18:08:34 2015 +0000
@@ -5,7 +5,10 @@
 #include "GMS6_CR6.h"
 #include "ErrorLogger.h"
 #include "Vector.h"
+#include "Matrix.h"
+#include "Vector_Matrix_operator.h"
 #include "myConstants.h"
+#include "Log.h"
 
 /********** private define    **********/
 #define TRUE    1
@@ -15,30 +18,50 @@
 /********** private typedef   **********/
 
 /********** private variables **********/
-I2C         i2c(I2C_SDA, I2C_SCL);      // I2Cポート
+I2C         i2c(PB_9, PB_8);      // I2Cポート
 MPU6050     mpu(&i2c);                  // 加速度・角速度センサ
 HMC5883L    hmc(&i2c);                  // 地磁気センサ
 LPS25H      lps(&i2c);                  // 気圧センサ
-Serial      gps(D8, D2);             // GPS通信用シリアルポート
+Serial      gps(PA_11, PA_12);                // GPS通信用シリアルポート
 Serial      pc(SERIAL_TX, SERIAL_RX);   // PC通信用シリアルポート
 GMS6_CR6    gms(&gps, &pc);             // GPS
-Ticker      timer;                      // 割り込みタイマー
+Ticker      INT_timer;                      // 割り込みタイマー
+//Log         logger(PA_9, PA_10, PB_5, PB_4, PB_3, PB_10, "sd");    // ロガー(microSD、XBee)
 
-const float Freq = 0.01f;           // 割り込み周期(s)
+const float dt = 0.1f;           // 割り込み周期(s)
 
 int lps_cnt = 0;                    // 気圧センサ読み取りカウント
-uint8_t INT_flag = FALSE;            // 割り込み可否フラグ
+uint8_t INT_flag = TRUE;            // 割り込み可否フラグ
 Vector acc(3);                       // 加速度(m/s^2)
 Vector gyro(3);                      // 角速度(deg/s)
 Vector geomag(3);                    // 地磁気(?)
 float press;                        // 気圧(hPa)
 
 Vector g(3);                        // 重力ベクトル
-Vector n(3);                        // 地磁気ベクトル
-Vector bias(3);                     // 地磁気センサのバイアスベクトル
+//Vector n(3);                        // 地磁気ベクトル
+
+/* ----- Kalman Filter ----- */
+Vector pri_x(6);
+Matrix pri_P(6, 6);
+Vector post_x(6);
+Matrix post_P(6, 6);
+Matrix F(6, 6), H(3, 6);
+Matrix R(6, 6), Q(3, 3);
+Matrix I(6, 6);
+Matrix K(6, 3);
+Matrix S(3, 3), inv(3, 3);
+/* ----- ------------- ----- */
+
+Timer timer;
+
+char data[1024] = {};
 
 /********** private functions **********/
+void KalmanInit();
+void KalmanUpdate();
 void INT_func();                    // 割り込み用関数
+void toString(Matrix& m);
+void toString(Vector& v);
 
 /********** main function     **********/
 
@@ -49,7 +72,12 @@
     if(!mpu.init()) AbortWithMsg("mpu6050 Initialize Error !!");        // mpu6050初期化
     if(!hmc.init()) AbortWithMsg("hmc5883l Initialize Error !!");       // hmc5883l初期化
     
-    timer.attach(&INT_func, Freq);  // 割り込み有効化(Freq = 0.01fなので、10msおきの割り込み)
+    //char* title = "log data\r\n";                                       // ログのタイトル行
+    //if(!logger.initialize_sdlog(title)) return 0;                       // ログファイル初期設定
+    
+    KalmanInit();
+    
+    INT_timer.attach(&INT_func, dt);  // 割り込み有効化(Freq = 0.01fなので、10msおきの割り込み)
     
     //重力ベクトルの初期化
     g.SetComp(1, 0.0f);
@@ -59,23 +87,40 @@
     /* ---------- ↓↓↓ ここからメインループ ↓↓↓ ---------- */
     while(1) {
         
-        // 1秒おきにセンサーの出力をpcへ出力
-        wait(1.0f);
+        // 0.1秒おきにセンサーの出力をpcへ出力
+        wait(0.1f);
         
         INT_flag = FALSE;           // 割り込みによる変数書き換えを阻止
         
         // センサ類の全出力値をPCに送信
-        pc.printf("%f,", acc.GetComp(1));
-        pc.printf("%f,", acc.GetComp(2));
-        pc.printf("%f,", acc.GetComp(3));
-        pc.printf("%f,", gyro.GetComp(1));
-        pc.printf("%f,", gyro.GetComp(2));
-        pc.printf("%f,", gyro.GetComp(3));
-        pc.printf("%f,", geomag.GetComp(1));
-        pc.printf("%f,", geomag.GetComp(2));
-        pc.printf("%f,", geomag.GetComp(3));
-        pc.printf("%f\r\n", press);
+        /*
+        pc.printf("%.3f,", acc.GetComp(1));
+        pc.printf("%.3f,", acc.GetComp(2));
+        pc.printf("%.3f,", acc.GetComp(3));
+        pc.printf("%.3f,", gyro.GetComp(1));
+        pc.printf("%.3f,", gyro.GetComp(2));
+        pc.printf("%.3f,", gyro.GetComp(3));
+        pc.printf("%.3f,", geomag.GetComp(1));
+        pc.printf("%.3f,", geomag.GetComp(2));
+        pc.printf("%.3f\r\n", geomag.GetComp(3));
+        */
+        //pc.printf("%.3f\r\n", press);
+        
         
+        pc.printf("%.3f,", geomag.GetComp(1));
+        pc.printf("%.3f,", geomag.GetComp(2));
+        pc.printf("%.3f,", geomag.GetComp(3));
+        pc.printf("%.3f,", post_x.GetComp(1));
+        pc.printf("%.3f,", post_x.GetComp(2));
+        pc.printf("%.3f\r\n", post_x.GetComp(3));
+        
+        /*
+        sprintf(data, "%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f\r\n", 
+                acc.GetComp(1), acc.GetComp(2), acc.GetComp(3), 
+                gyro.GetComp(1), gyro.GetComp(2), gyro.GetComp(3), 
+                geomag.GetComp(1), geomag.GetComp(2), geomag.GetComp(3), press);
+        logger.puts(data);
+        */
         INT_flag = TRUE;            // 割り込み許可
         
     }
@@ -83,9 +128,74 @@
     /* ---------- ↑↑↑ ここまでメインループ ↑↑↑ ---------- */
 }
 
+void KalmanInit() {
+    
+    // 誤差共分散行列の値を決める(対角成分のみ)
+    float alpha_R = 60.0f;
+    float alpha_Q = 100.0f;
+    R *= alpha_R;
+    Q *= alpha_Q;
+    
+    // 状態方程式のヤコビアンの初期値を代入(時間変化あり)
+    float f[36] = {
+        1.0f, gyro.GetComp(3)*dt, -gyro.GetComp(2)*dt, 0.0f, 0.0f, 0.0f, 
+        -gyro.GetComp(3)*dt, 1.0f, gyro.GetComp(1)*dt, 0.0f, 0.0f, 0.0f, 
+        gyro.GetComp(2)*dt, -gyro.GetComp(1)*dt, 1.0f, 0.0f, 0.0f, 0.0f, 
+        0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 
+        0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,  
+        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
+    };
+    
+    F.SetComps(f);
+    
+    // 観測方程式のヤコビアンの値を設定(時間変化無し)
+    float h[18] = {
+        1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,  
+        0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,  
+        0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
+    };
+    
+    H.SetComps(h);
+}
+
+void KalmanUpdate() {
+    // ヤコビアンの更新
+    float f[36] = {
+        1.0f, gyro.GetComp(3)*dt, -gyro.GetComp(2)*dt, 0.0f, 0.0f, 0.0f, 
+        -gyro.GetComp(3)*dt, 1.0f, gyro.GetComp(1)*dt, 0.0f, 0.0f, 0.0f, 
+        gyro.GetComp(2)*dt, -gyro.GetComp(1)*dt, 1.0f, 0.0f, 0.0f, 0.0f, 
+        0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 
+        0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,  
+        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
+    };
+    
+    F.SetComps(f);
+    
+    // 事前推定値の更新
+    pri_x = F * post_x;
+    // 事前誤差分散行列の更新
+    pri_P = F * post_P * F.Transpose() + R;
+    
+    // カルマンゲインの計算
+    S = Q + H * pri_P * H.Transpose();
+    float det;
+    if((det = S.Inverse(inv)) >= 0.0f) {
+        pc.printf("E:%.3f\r\n", det);
+        return;     // 万が一、逆行列が見つからなかった場合は前回の推定値を保持して終了
+    }
+    K = pri_P * H.Transpose() * inv;    
+    
+    // 事後推定値の更新
+    post_x = pri_x + K * (geomag - H * pri_x);
+    // 事後誤差分散行列の更新
+    post_P = (I - K * H) * pri_P;
+}
+
 void INT_func() {
-    if(INT_flag == FALSE) {
+    if(INT_flag != FALSE) {
         
+        timer.reset();
+        timer.start();
         // センサーの値を更新
         mpu.read();
         hmc.read();
@@ -97,17 +207,40 @@
         }
         
         Vector delta_g = Cross(gyro, g);                            // Δg = ω × g
-        g = 0.9f * (g - delta_g * Freq) + 0.1f * acc.Normalize();   // 相補フィルタ
+        g = 0.9f * (g - delta_g * dt) + 0.1f * acc.Normalize();   // 相補フィルタ
         g = g.Normalize();
         
-        Vector delta_n = Cross(gyro,n);
-        n = 0.9f * (n - delta_n * Freq) + 0.1f * geomag.Normalize();
-        n = n.Normalize();
+        
+        KalmanUpdate();
+        
         
         // LPS25Hによる気圧の取得は10Hz
         lps_cnt = (lps_cnt+1)%10;
         if(lps_cnt == 0) {
             press = (float)lps.pressure() * PRES_LSB_TO_HPA;
         }
+        
+        timer.stop();
+        //pc.printf("%d(us)\r\n", timer.read_us());
     }
+}
+
+void toString(Matrix& m) {
+    
+    for(int i=0; i<m.GetRow(); i++) {
+        for(int j=0; j<m.GetCol(); j++) {
+            pc.printf("%.6f\t", m.GetComp(i+1, j+1));
+        }
+        pc.printf("\r\n");
+    }
+    
+}
+
+void toString(Vector& v) {
+    
+    for(int i=0; i<v.GetDim(); i++) {
+        pc.printf("%.6f\t", v.GetComp(i+1));
+    }
+    pc.printf("\r\n");
+    
 }
\ No newline at end of file
--- a/myConstants.h	Sun May 24 17:44:11 2015 +0000
+++ b/myConstants.h	Sat May 30 18:08:34 2015 +0000
@@ -1,7 +1,7 @@
 #pragma once
 
-#define NEARLY_ZERO         0.000001f
-#define ZERO_TOLERANCE      0.001f
+#define NEARLY_ZERO         0.000000001f
+#define ZERO_TOLERANCE      0.000001f
 #define RAD_TO_DEG          57.2957795f             // 180 / π
 #define DEG_TO_RAD          0.0174532925f           // π / 180
 #define ACC_LSB_TO_G        0.0000610351562f        // g/LSB (1/2^14