ドローン用計測制御基板の作り方vol.2で使用したピッチ制御プログラムです。

Dependencies:   mbed MPU6050_alter SDFileSystem

Files at this revision

API Documentation at this revision

Comitter:
Joeatsumi
Date:
Fri Mar 06 15:03:57 2020 +0000
Commit message:
An software for autopilot(ver2)

Changed in this revision

MPU6050.lib 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
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.h 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
mbed.bld 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MPU6050.lib	Fri Mar 06 15:03:57 2020 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/Joeatsumi/code/MPU6050_alter/#44c458576810
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Matrix/Matrix.cpp	Fri Mar 06 15:03:57 2020 +0000
@@ -0,0 +1,388 @@
+#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) error("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) error("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) error("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) error("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()) error("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()) error("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()) error("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) error("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) error("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) error("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) error("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) error("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) error("failed to LU decomposition: matrix is not square");
+    if (sign != 0) *sign = 1;
+    if (p != 0) {
+        if (p->row != row || p->row != p->col) error("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) error("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) error("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) error("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()) error("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) error("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) error("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	Fri Mar 06 15:03:57 2020 +0000
@@ -0,0 +1,115 @@
+#pragma once
+#include "mbed.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) error("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/SDFileSystem.lib	Fri Mar 06 15:03:57 2020 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/SDFileSystem/#8db0d3b02cec
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vector/Vector.cpp	Fri Mar 06 15:03:57 2020 +0000
@@ -0,0 +1,177 @@
+#include "myConstants.h"
+#include "Vector.h"
+
+
+Vector::Vector(int dim) : dim(dim), components(0){
+    components = new float[dim];
+    if (!components) error("Memory Allocation Error");
+    for(int i=0; i<dim; i++) components[i] = 0.0f;
+}
+
+
+Vector::~Vector() {
+    delete[] components;
+}
+
+Vector::Vector(const Vector& v) : dim(v.dim), components(0) {
+    components = new float[dim];
+    if (!components) error("Memory Allocation Error");
+    memcpy(components, v.GetpComponents(), sizeof(float)*dim);
+}
+
+Vector& Vector::operator=(const Vector& v) {
+    if (this == &v) return *this;
+    dim = v.dim;
+    delete[] components;
+    components = new float[dim];
+    if (!components) error("Memory Allocation Error");
+    memcpy(components, v.GetpComponents(), sizeof(float)*dim);
+
+    return *this;
+}
+
+Vector Vector::operator+() {
+    return *this;
+}
+
+Vector Vector::operator-() {
+    Vector retVec(*this);
+    retVec *= -1;
+    return retVec;
+}
+
+Vector& Vector::operator*=(float c) {
+    for (int i = 0; i < dim; i++) {
+        components[i] *= c;
+    }
+
+    return *this;
+}
+
+Vector& Vector::operator/=(float c) {
+    if (fabs(c) < NEARLY_ZERO) error("Division by Zero");
+    for (int i = 0; i < dim; i++) {
+        components[i] /= c;
+    }
+
+    return *this;
+}
+
+Vector& Vector::operator+=(const Vector& v) {
+    if (dim != v.dim) error("failed to add: Irregular Dimention");
+    for (int i = 0; i < dim; i++) {
+        components[i] += v.components[i];
+    }
+
+    this->CleanUp();
+
+    return *this;
+}
+
+Vector& Vector::operator-=(const Vector& v) {
+    if (dim != v.dim) error("failed to subtract: Irregular Dimention");
+    for (int i = 0; i < dim; i++) {
+        components[i] -= v.components[i];
+    }
+
+    this->CleanUp();
+
+    return *this;
+}
+
+void Vector::SetComp(int dimNo, float val) {
+    if (dimNo > dim) error("Index Out of Bounds Error");
+    components[dimNo-1] = val;
+}
+
+void Vector::SetComps(float* pComps) {
+    memcpy(components, pComps, sizeof(float) * dim);
+}
+
+float Vector::GetNorm() const {
+    float norm = 0.0f;
+    for (int i = 0; i < dim; i++) {
+        norm += components[i] * components[i];
+    }
+    return sqrt(norm);
+}
+
+Vector Vector::Normalize() const {
+    float norm = GetNorm();
+    Vector temp(*this);
+    for (int i = 0; i < dim; i++) {
+        temp.components[i] /= norm;
+    }
+    temp.CleanUp();
+    return temp;
+}
+
+Vector Vector::GetParaCompTo(Vector v) {
+    Vector norm_v = v.Normalize();
+    return (*this * norm_v) * norm_v;
+}
+
+Vector Vector::GetPerpCompTo(Vector v) {
+    return (*this - this->GetParaCompTo(v));
+}
+
+void Vector::CleanUp() {
+    float maxComp = 0.0f;
+    for (int i = 0; i < dim; i++) {
+        if (fabs(components[i]) > maxComp) maxComp = fabs(components[i]);
+    }
+    if (maxComp > NEARLY_ZERO) {
+        for (int i = 0; i < dim; i++) {
+            if (fabs(components[i]) / maxComp < ZERO_TOLERANCE) components[i] = 0.0f;
+        }
+    }
+}
+
+Vector operator+(const Vector& lhv, const Vector& rhv) {
+    Vector retVec(lhv);
+    retVec += rhv;
+    return retVec;
+}
+
+Vector operator-(const Vector& lhv, const Vector& rhv) {
+    Vector retVec(lhv);
+    retVec -= rhv;
+    return retVec;
+}
+
+Vector Cross(const Vector& lhv, const Vector& rhv) {
+    if (lhv.GetDim() != 3) error("failed to cross: variable 'dim' must be 3");
+    if (lhv.GetDim() != rhv.GetDim()) error("failed to cross: Irregular Dimention");
+
+    Vector retVec(lhv.GetDim());
+
+    for (int i = 0; i < lhv.GetDim(); i++) {
+        retVec.SetComp(i + 1, lhv.GetComp((i + 1) % 3 + 1) * rhv.GetComp((i + 2) % 3 + 1)
+            - lhv.GetComp((i + 2) % 3 + 1) * rhv.GetComp((i + 1) % 3 + 1));
+    }
+
+    return retVec;
+}
+
+Vector operator*(const float c, const Vector& rhv) {
+    Vector retVec(rhv);
+    retVec *= c;
+    return retVec;
+}
+
+Vector operator*(const Vector& lhv, const float c) {
+    Vector retVec(lhv);
+    retVec *= c;
+    return retVec;
+}
+
+float operator*(const Vector& lhv, const Vector& rhv) {
+    if (lhv.GetDim() != rhv.GetDim()) error("Irregular Dimention");
+    float retVal = 0.0f;
+
+    for (int i = 1; i <= lhv.GetDim(); i++) {
+        retVal += lhv.GetComp(i) * rhv.GetComp(i);
+    }
+
+    return retVal;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vector/Vector.h	Fri Mar 06 15:03:57 2020 +0000
@@ -0,0 +1,56 @@
+#pragma once
+#include "mbed.h"
+
+class Matrix;
+
+class Vector {
+public:
+    Vector(int dim);
+    ~Vector();
+    Vector(const Vector& v);
+
+    Vector& operator=(const Vector& v);
+    Vector operator+();
+    Vector operator-();
+    Vector& operator*=(float c);
+    Vector& operator/=(float c);
+    Vector& operator+=(const Vector& v);
+    Vector& operator-=(const Vector& v);
+
+    void SetComp(int dimNo, float val);
+    void SetComps(float* vals);
+    float GetNorm() const;
+    Vector Normalize() const;
+    Vector GetParaCompTo(Vector v);
+    Vector GetPerpCompTo(Vector v);
+
+    inline int GetDim() const {
+        return dim;
+    }
+
+    inline const float* GetpComponents() const {
+        return (const float*)components;
+    }
+
+    inline float GetComp(int dimNo) const {
+        if (dimNo > dim) error("Index Out of Bounds Error !!");
+        return components[dimNo-1];
+    }
+
+    void CleanUp();
+
+private:
+    int dim;
+    float* components;
+
+    Vector& operator*=(const Matrix& m);
+    Vector& operator*=(const Vector& m);
+};
+
+Vector operator+(const Vector& lhv, const Vector& rhv);
+Vector operator-(const Vector& lhv, const Vector& rhv);
+Vector Cross(const Vector& lhv, const Vector& rhv);
+Vector operator*(const float c, const Vector& rhv);
+Vector operator*(const Vector& lhv, const float c);
+float operator*(const Vector& lhv, const Vector& rhv);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vector/Vector_Matrix_operator.cpp	Fri Mar 06 15:03:57 2020 +0000
@@ -0,0 +1,35 @@
+#include "Vector_Matrix_operator.h"
+
+Vector operator*(const Matrix& lhm, const Vector& rhv) {
+    if (lhm.GetCol() != rhv.GetDim()) error("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()) error("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	Fri Mar 06 15:03:57 2020 +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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Mar 06 15:03:57 2020 +0000
@@ -0,0 +1,505 @@
+//==================================================
+//Auto pilot(prototype2)
+//
+//MPU board: mbed LPC1768
+//Multiplexer TC74HC157AP
+//Accelerometer +Gyro sensor : GY-521
+//2019/11/17 A.Toda
+//==================================================
+#include "mbed.h"
+#include "MPU6050.h"
+#include "SDFileSystem.h"
+
+#include "Vector.h"
+#include "Matrix.h"
+#include "Vector_Matrix_operator.h"
+
+#include "math.h"
+
+//==================================================
+#define RAD_TO_DEG          57.2957795f             // 180 / π
+#define MAX_MEAN_COUNTER 500
+
+#define ACC_X -1.205178682//offset of x-axi accelerometer
+#define ACC_Y -0.141728488//offset of y-axi accelerometer
+#define ACC_Z -0.339272785//offset of z-axi accelerometer
+
+#define ACC_GAIN_X 1.0
+#define ACC_GAIN_Y 0.995906146
+#define ACC_GAIN_Z 1.017766039
+
+#define THRESHOLD_PWM 0.0015
+#define M_A_PWM 0.0017
+#define SERVO_PERIOD  0.020
+
+#define PITCH_TARGET 0.0
+
+/*
+8/2/2020でのゲイン
+#define P_P_GAIN 3.0
+#define P_I_GAIN 0.5
+#define P_D_GAIN 1.0
+*/
+
+#define OFFSET_PWM_ELE 0.0015
+#define MAX_PWM_ELE 0.00175
+#define MIN_PWM_ELE 0.00125
+
+#define LPF_ELE_K 0.110//この値が小さいとローパスフィルタが強くなる 0.050は小さすぎる
+                        //0.200は動きが機敏過ぎる。
+//==================================================
+
+//Port Setting
+SDFileSystem sd(p5, p6, p7, p8, "sd");//pins for sd slot 
+MPU6050 mpu(p9, p10);  //Accelerometer + Gyro
+                        //(SDA,SCLK)
+DigitalIn logging_terminater(p16);
+InterruptIn reading_port(p18); 
+DigitalOut mux_switch(p19);
+PwmOut ELE(p21);
+
+Serial pc(USBTX, USBRX);    //UART
+
+//Pointer of sd card
+FILE *fp;
+
+//==================================================
+//Accelerometer and gyro data
+//==================================================
+double acc[3]; //variables for accelerometer
+double gyro[3]; //variables for gyro
+
+double offset_gyro_x=0.0;
+double offset_gyro_y=0.0;
+
+double sum_gyro_x=0.0;
+double sum_gyro_y=0.0;
+
+double threshold_acc,threshold_acc_ini;
+
+double dev  =0.0;
+double i_dev=0.0;
+double d_dev=0.0;
+
+double old_i_dev=0.0;
+//==================================================
+//Atitude data
+//==================================================
+double roll_and_pitch_acc[2];//atitude from acceleromter
+double roll_and_pitch[2];//atitude from gyro and acceleromter
+
+/*--------------------------行列、ベクトル-----------------------------*/
+Matrix rate_angle_matrix(4,4);//角速度行列 クォータニオンの更新に使う
+Vector quaternion(4),pre_quaternion(4),dump_1(4);;//クォータニオン
+/*-------------------------------------------------------------------*/
+
+//==================================================
+//Timer valiables
+//==================================================
+Timer ch_time;//timer for calculate pulse width
+Timer passed_time;//timer for calculate atitude
+
+double measured_pre_pulse=0.0;
+double measured_pulse=0.0;
+
+double time_new;
+double time_old;
+
+double pulse_width_ele,deflection_ele,old_deflection_ele;
+
+//=================================================
+//PID Gain
+//==================================================
+float P_P_GAIN,P_I_GAIN,P_D_GAIN;
+int P_GAIN,I_GAIN,D_GAIN;
+
+//=================================================
+//エレベータの舵角
+//=================================================
+double pitch_command;
+
+//=================================================
+//手動か自動かのインジケータ0なら手動、1なら自動
+//=================================================
+int m_a_indicater;
+//=================================================
+//Functions for rising and falind edge interrution
+//=================================================
+//rise edge
+void rising_edge(){
+    ch_time.reset();//reset timer counter
+    measured_pre_pulse=ch_time.read();
+    
+}
+
+//falling edge
+void falling_edge(){
+    
+    measured_pre_pulse=(ch_time.read()-measured_pre_pulse);
+    //pc.printf("The pulse width=%f\r\n",measured_pre_pulse);
+    if(measured_pre_pulse>M_A_PWM){
+        mux_switch=1;
+        m_a_indicater=1;//set indicater as auto
+        }else{
+            mux_switch=0;
+            m_a_indicater=0;//set indicater as manual
+            }
+}
+
+//terminate logging
+void end_of_log(){
+     //flipper.detach();
+     fclose(fp);//close "Atitude_angles.csv"
+     pc.printf("Logging was terminated.");
+     
+    }
+//==================================================
+//Gyro and accelerometer functions
+//==================================================
+//get data
+void  aquisition_sensor_values(double *a,double *g){
+    
+    float ac[3],gy[3];
+    
+    mpu.getAccelero(ac);//get acceleration (Accelerometer)
+                                //x_axis acc[0]
+                                //y_axis acc[1]
+                                //z_axis acc[2]
+    mpu.getGyro(gy);   //get rate of angle(Gyro)
+                      //x_axis gyro[0]
+                      //y_axis gyro[1]
+                      //z_axis gyro[2]
+                      
+    //Invertion for direction of Accelerometer axis
+    ac[0]*=(-1.0);
+    ac[2]*=(-1.0);
+    
+    ac[0]=(ac[0]-ACC_X)/ACC_GAIN_X;
+    ac[1]=(ac[1]-ACC_Y)/ACC_GAIN_Y;
+    ac[2]=(ac[2]-ACC_Z)/ACC_GAIN_Z;
+            
+    //Unit convertion of rate of angle(radian to degree)
+    gy[0]*=RAD_TO_DEG;
+    gy[0]*=(-1.0);
+        
+    gy[1]*=RAD_TO_DEG;        
+    gy[2]*=RAD_TO_DEG;
+    gy[2]*=(-1.0);
+  
+    for(int i=0;i<3;i++){
+        a[i]=double(ac[i]);
+        g[i]=double(gy[i]);
+        }
+    g[0]-=offset_gyro_x;//offset rejection
+    g[1]-=offset_gyro_y;//offset rejection
+    
+    return;
+    
+}
+
+//calculate offset of gyro
+void offset_calculation_for_gyro(){
+    
+    //Accelerometer and gyro setting 
+    mpu.setAcceleroRange(0);//acceleration range is +-2G
+    mpu.setGyroRange(1);//gyro rate is +-500degree per second(dps)
+    
+    //calculate offset of gyro
+    for(int mean_counter=0; mean_counter<MAX_MEAN_COUNTER ;mean_counter++){
+        aquisition_sensor_values(acc,gyro);
+        sum_gyro_x+=gyro[0];
+        sum_gyro_y+=gyro[1];
+        wait(0.01);
+        }
+    
+    offset_gyro_x=sum_gyro_x/MAX_MEAN_COUNTER;
+    offset_gyro_y=sum_gyro_y/MAX_MEAN_COUNTER;
+    
+    return;
+}
+
+//atitude calculation from acceleromter
+void atitude_estimation_from_accelerometer(double *a,double *roll_and_pitch){
+    
+    roll_and_pitch[0] = atan(a[1]/a[2])*RAD_TO_DEG;//roll
+    roll_and_pitch[1] = atan(a[0]/sqrt( (a[1]*a[1]+a[2]*a[2]) ) )*RAD_TO_DEG;//pitch
+    
+    return;
+}
+
+//quaternion to euler
+void quaternion_to_euler(Vector& qua,double *roll_and_pitch ){
+    
+    double q0=double (qua.GetComp(1));
+    double q1=double (qua.GetComp(2));
+    double q2=double (qua.GetComp(3));
+    double q3=double (qua.GetComp(4));
+    
+    roll_and_pitch[0]=atan((q2*q3+q0*q1)/(q0*q0-q1*q1-q2*q2+q3*q3)) ;//roll
+    roll_and_pitch[1]=-asin(2*(q1*q3-q0*q2));
+    
+    return;
+    }
+
+//quaternion to euler
+void euler_to_quaternion(Vector& qua,double *roll_and_pitch ){
+    
+    double roll_rad_2=(roll_and_pitch[0]/57.3)/2.0;
+    double pitch_rad_2=(roll_and_pitch[1]/57.3)/2.0;
+    double yaw_rad_2=0.0;
+    
+    float q0= cos(roll_rad_2)*cos(pitch_rad_2)*cos(yaw_rad_2)
+                +sin(roll_rad_2)*sin(pitch_rad_2)*sin(yaw_rad_2);
+                
+    float q1= sin(roll_rad_2)*cos(pitch_rad_2)*cos(yaw_rad_2)
+                -cos(roll_rad_2)*sin(pitch_rad_2)*sin(yaw_rad_2);
+                
+    float q2= cos(roll_rad_2)*sin(pitch_rad_2)*cos(yaw_rad_2)
+                +sin(roll_rad_2)*cos(pitch_rad_2)*sin(yaw_rad_2);
+
+    float q3= cos(roll_rad_2)*cos(pitch_rad_2)*sin(yaw_rad_2)
+                -sin(roll_rad_2)*sin(pitch_rad_2)*cos(yaw_rad_2);
+
+    //クォータニオン行列の作成(クォータニオンの演算に用いる)
+    float quaternion_elements[4]={q0,q1,q2,q3}; 
+    qua.SetComps(quaternion_elements);
+    
+    
+    return;
+    }
+
+//atitude calculation
+void atitude_update(){
+    
+    //慣性センサの計測
+    aquisition_sensor_values(acc,gyro);
+    //角速度行列の作成(クォータニオンの演算に用いる)
+    float rate_angles[16]={0.0,-float(gyro[0]),-float(gyro[1]),-float(gyro[2])
+                          ,float(gyro[0]),0.0,float(gyro[2]),-float(gyro[1])
+                          ,float(gyro[1]),-float(gyro[2]),0.0,float(gyro[0])
+                          ,float(gyro[0]),float(gyro[1]),-float(gyro[2]),0.0}; 
+                          
+    rate_angle_matrix.SetComps(rate_angles);
+    //クォータニオンの演算
+    //pc.printf("クォータニオンの演算\r\n");
+    float coefficents=0.5*(time_new-time_old);
+    float coefficents_elements[16]={coefficents,0.0,0.0,0.0
+                                      ,0.0,coefficents,0.0,0.0
+                                      ,0.0,0.0,coefficents,0.0
+                                      ,0.0,0.0,0.0,coefficents};
+    Vector coefficents_vector(4);
+    coefficents_vector.SetComps(coefficents_elements);
+    
+    dump_1=rate_angle_matrix*coefficents_vector;
+    quaternion=dump_1+pre_quaternion;
+    
+    //正規化
+    //pc.printf("正規化\r\n");
+    quaternion=quaternion.Normalize();
+    //クォータニオンからオイラー角への変換
+    quaternion_to_euler(quaternion,roll_and_pitch_acc );
+    
+    threshold_acc=sqrt(acc[0]*acc[0]+acc[1]*acc[1]+acc[2]*acc[2]);
+    
+    if((threshold_acc>=0.9*threshold_acc_ini)
+          &&(threshold_acc<=1.1*threshold_acc_ini)){
+        
+        atitude_estimation_from_accelerometer(acc,roll_and_pitch_acc);
+        roll_and_pitch[0] = 0.98*roll_and_pitch[0] + 0.02*roll_and_pitch_acc[0];
+        roll_and_pitch[1] = 0.98*roll_and_pitch[1] + 0.02*roll_and_pitch_acc[1];
+        
+        }else{}
+    //補正したオイラー角をクォータニオンへ変換
+    euler_to_quaternion(pre_quaternion,roll_and_pitch_acc );
+    
+    //microSDに記録する
+    //経過時間,ロール角,ピッチ角,操縦方式,慣性センサの値
+    fprintf(fp, "%f,%f,%f,%d,%f,%f,%f,%f,%f,%f\r\n"
+        ,time_new,roll_and_pitch[0],roll_and_pitch[1],m_a_indicater,gyro[0],gyro[1],acc[0],acc[1],acc[2],pitch_command);
+    
+    return;
+
+}
+
+//elevation commnad to PWM
+double elevation_to_PWM(double elevation_command){
+    
+    /*
+    PWM信号0.25msが舵角の16.45度に相当する.
+    */
+    
+    double PWM_pitch = (elevation_command*1.519)/100000+ OFFSET_PWM_ELE;
+    //double PWM_pitch = ( ((elevation_command)*6.0/1000.0)/1000.0  )+ OFFSET_PWM_ELE;
+    
+    /*PWMコマンドの上限と下限の設定*/
+    if(PWM_pitch>MAX_PWM_ELE){
+        PWM_pitch=MAX_PWM_ELE;
+        
+        }else if(PWM_pitch<MIN_PWM_ELE){
+            PWM_pitch=MIN_PWM_ELE;
+            }
+    
+    return PWM_pitch;
+    
+    }
+
+double deflection_of_ele(double pitch){
+    
+    double add_deflection=((pitch-PITCH_TARGET)*6.0/1000.0)/1000.0;
+    
+    return add_deflection;
+    }
+
+//PID controller
+double pitch_PID_controller(double pitch,double target,double gyro_pitch){
+    
+    dev=target-pitch;
+    
+    //アンチワインドアップ
+    i_dev=old_i_dev+dev*(time_new-time_old);
+    if(i_dev>=25.0){
+        i_dev=25.0;
+    }else if(i_dev<=-25.0){
+        i_dev=-25.0;
+    }
+    //アンチワインドアップ終わり
+            
+    old_i_dev=i_dev;
+    
+    d_dev=-gyro_pitch;
+    
+    pitch_command = double(P_P_GAIN*dev+P_I_GAIN*i_dev+P_D_GAIN*d_dev);
+    
+    double pwm_command = elevation_to_PWM(pitch_command);//pwm信号に変換
+    
+    return pwm_command;
+
+    }
+
+//LPF
+
+double LPF_pitch(double c_com,double old_com){
+    
+    double lpf_output=(1-LPF_ELE_K)*old_com+LPF_ELE_K*c_com;
+    
+    return lpf_output;
+    }
+
+//==================================================
+//Main
+//==================================================
+int main() {
+
+    wait(5.0);
+    
+    //UART initialization
+    pc.baud(115200);
+    
+    //define servo period
+    ELE.period(SERVO_PERIOD);  // servo requires a 20ms period
+    pulse_width_ele=0.0015;
+    
+    //timer starts
+    ch_time.start();
+    passed_time.start();
+    
+    time_old=0.0;
+    
+    //declare interrupitons
+    reading_port.rise(rising_edge);
+    reading_port.fall(falling_edge);
+    
+    /*
+    mux_switch=0;//set circit as manual mode
+    m_a_indicater=0;//set indicater as manual
+    */
+    
+    //gyro and accelerometer initialization
+    offset_calculation_for_gyro();
+    
+    //determine initilal atitude
+    aquisition_sensor_values(acc,gyro);
+    atitude_estimation_from_accelerometer(acc,roll_and_pitch);
+    euler_to_quaternion(pre_quaternion,roll_and_pitch);
+    
+    threshold_acc_ini=sqrt(acc[0]*acc[0]+acc[1]*acc[1]+acc[2]*acc[2]);
+    
+    /*
+    PIDゲインをsdカードのテキストファイルから読み取る
+    int型しか読みとれないので、希望する値の10倍をテキストファイルに書き込んでいる。
+    Pゲインを3.0,Iゲインを0.5,Dゲインを1.0とする場合
+    
+    30,5,10
+    
+    のようにテキストデータをsdカードに用意する。  
+    */
+    //open PID gain file in sd card 
+    FILE*ga = fopen("/sd/Gain_data.txt", "r");
+    if(ga == NULL) {
+        error("Could not open file for write\n");
+    }
+    
+    while (!feof(ga)) {
+        int n = fscanf(ga, "%d,%d,%d",&P_GAIN, &I_GAIN, &D_GAIN);
+        
+        if(n!= 3){
+            error("Could not read 3 elements");
+            }
+    }
+    
+    P_P_GAIN=P_GAIN/10.0;
+    P_I_GAIN=I_GAIN/10.0;
+    P_D_GAIN=D_GAIN/10.0;
+    
+    fclose(ga);
+    
+    //create folder(sd) in sd card
+    mkdir("/sd", 0777);
+    //create "Atitude_angles.csv" in folder(sd)
+    fp = fopen("/sd/Atitude_angles.csv", "a");//ファイルがある場合は追加で書き込み
+        
+    if(fp == NULL) {
+        error("Could not open file for write\n");
+    }
+    
+    //Logging starts
+    pc.printf("Logging starts.");
+    
+    //write PID gain on sd card 
+    fprintf(fp,"%f,%f,%f\r\n",P_P_GAIN,P_I_GAIN,P_D_GAIN);
+    
+    //while
+    while(1){
+         
+         if(logging_terminater==1){
+             end_of_log();
+             }else{}
+         
+         time_new=passed_time.read();
+         
+         atitude_update();
+        
+         time_old=time_new;
+         
+         /*
+         ここから先でサーボの操舵角を姿勢角に応じて変化させる。関数pitch_PID_controller
+         はpitch角とpitch角速度に応じてサーボのパルス幅を返す関数である。
+         */
+         
+         deflection_ele = pitch_PID_controller(roll_and_pitch[1],PITCH_TARGET,gyro[1]);
+         
+         //LPF
+         deflection_ele = LPF_pitch(deflection_ele,old_deflection_ele);
+         old_deflection_ele = deflection_ele;
+         
+         //servo output
+         ELE.pulsewidth(deflection_ele);
+         
+         //PCにつないでデバッグを行う際に表示する
+         pc.printf("%f,%f,%f,%f,%d\r\n",time_new,deflection_ele,roll_and_pitch[0],roll_and_pitch[1],m_a_indicater);
+         
+         wait(0.002);
+        
+    }//while ends
+    
+}//main ends
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Mar 06 15:03:57 2020 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/e1686b8d5b90
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myConstants.h	Fri Mar 06 15:03:57 2020 +0000
@@ -0,0 +1,37 @@
+#pragma once
+
+/* Math Constants */
+#define NEARLY_ZERO         0.000000001f
+#define ZERO_TOLERANCE      0.000001f
+#define RAD_TO_DEG          57.2957795f             // 180 / π
+#define DEG_TO_RAD          0.0174532925f           // π / 180
+
+/* Accelerometer */
+#define ACC_LSB_TO_G        0.0000610351562f        // g/LSB (1/2^14
+#define G_TO_MPSS           9.8f                    // (m/s^2)/g
+
+/* Gyro Sensor */
+//#define GYRO_LSB_TO_DEG     0.0304878048f           // deg/LSB (1/32.8
+#define GYRO_LSB_TO_DEG     0.0152671755f           // deg/LSB (1/65.5
+//#define GYRO_LSB_TO_DEG     0.00763358778f          // deg/LSB (1/131
+
+/* Pressure Sensor */
+#define PRES_LSB_TO_HPA     0.000244140625f         // hPa/LSB (1/4096
+
+inline float TempLsbToDeg(short int temp) {
+    return (42.5f + (float)temp * 0.00208333333f);  // degree_C = 42.5 + temp / 480;
+}
+
+/* GPS */
+#define GPS_SQ_E                0.00669437999f      // (第一離心率)^2
+#define GPS_A                   6378137.0f          // 長半径(赤道半径)(m)
+#define GPS_B                   6356752.3f          // 短半径(極半径)(m)
+
+/* Geomagnetic Sensor */
+#define MAG_LSB_TO_GAUSS    0.00092f                // Gauss/LSB
+#define MAG_MAGNITUDE       0.46f                   // Magnitude of GeoMagnetism (Gauss)
+#define MAG_SIN             -0.754709580f           // Sin-Value of Inclination
+#define MAG_DECLINATION     7.5f                    // declination (deg)
+
+/* ADC */
+#define ADC_LSB_TO_V        0.000050354f            // 3.3(V)/65535(LSB)
\ No newline at end of file