C++とEigenで状態方程式を解いてopenFrameworksで表示する。

#目的
C++言語＋Eigenとで、バネ～マス～ダンパ系の状態方程式の応答を求め、
openFrameworksのaddon ofxGraphで応答波形をリアルタイムに表示する。
また、ofxGuiでバネ～マス～ダンパのパラメータをリアルタイムに変更できるようにする。

参考：[C++とEigenで状態方程式を解く。](https://qiita.com/nnn112358/items/0ad933a53d7ec8248862)


　![新規.gif](https://qiita-image-store.s3.amazonaws.com/0/73020/0da22387-086a-1039-a026-b2834ae109e7.gif)


#事前準備
以下をインストールしておく。
・[openFrameworks](http://qiita.com/nnn112358/items/b6834379e2eeeeae6793)
 　→上記ページからファイルをダウンロードし、任意のフォルダに展開する。
・[ofxGraph](https://github.com/TetsuakiBaba/ofxGraph)
 　→上記ページからファイルをダウンロードし、openFrameworksのaddonディレクトリ以下に配置する。
・[Eigen](http://eigen.tuxfamily.org/index.php?title=Main_Page)
 →上記ページからヘッダファイルをダウンロードし、openFrameworksのプロジェクトのsrcディレクトリ以下に配置する。


#実装

以下のバネ～マス～ダンパ系の状態方程式を解くとする。
u(t)には外乱としてホワイトノイズを注入する。

```math
\dot{x}(t)=Ax(t)+Bu(t) \\
y(t)=Cx(t)+Du(t)
```

```math
x(t)=
\begin{bmatrix}
x_{1}  \\
x_{2}  
\end{bmatrix}

,
u(t)=f
,

A=
\begin{bmatrix}
0 & 1 \\
-k/m & -c/m
\end{bmatrix}
,
B=
\begin{bmatrix}
0 \\
1/m 
\end{bmatrix}
,
C=
\begin{bmatrix}
1 & 0 
\end{bmatrix}
,
D=[0]
```



#サンプルソース
ofApp.cpp

```c
#include "ofApp.h"

void RungeKutta(MatrixXd dX, MatrixXd &X, MatrixXd u, double tt, double dt, MatrixXd A, MatrixXd B, MatrixXd C, MatrixXd D) {
	MatrixXd k1 = A*X + B*u;
	MatrixXd k2 = A*(X + 0.5*k1*dt) + B*u;
	MatrixXd k3 = A*(X + 0.5*k2*dt) + B*u;
	MatrixXd k4 = A*(X + k3*dt) + B*u;
	MatrixXd k = (k1 + 2.0*k2 + 2.0*k3 + k4)*dt / 6.0;
	X = X + k;
}
void ofApp::setup(){
	ofSetVerticalSync(true); 
	ofxGuiSetFont(ofToDataPath("ofxGraph/DIN Alternate Bold.ttf"), 10);
	graph.setup(100, 100, 800, 400);
	graph.setName("spring-mass-damper system wave"); 
	graph.setDx(2.0);
	graph.setColor(ofColor::white); 
	graph.setBufSize(1000);  
	graph.setLabel({ "y0","u" });
	frame = 0;

	gui.setup("parametor");
	gui.add(kk.setup("K", 1.0, 0.0, 5.0));
	gui.add(mm.setup("M", 0.1, 0.0, 1.0));
	gui.add(cc.setup("C", 0.1, 0.0, 1.0));

	AA.resize(2, 2);
	AA << 0, 1, -kk / mm, -cc / mm;
	BB.resize(2, 1);
	BB << 1, 1 / mm;
	CC.resize(1, 2);
	CC << 1, 0;
	DD.resize(1, 1);
	DD << 1;

	XX.resize(2, 1);
	XX(0, 0) = 0;
	XX(1, 0) = 0;
	dXX.resize(2, 1);
	dXX(0, 0) = 0;
	dXX(1, 0) = 0;

	uu.resize(1, 1);
	uu << 0;
	YY.resize(1, 1);
	YY(0, 0) = 0;

	dt = 0.01;
	tt = 0.0;
}

//--------------------------------------------------------------
void ofApp::update() {
	frame++;

	AA << 0, 1, -kk / mm, -cc / mm;
	BB << 1, 1 / mm;

	double TT = 100.0;
	uu(0, 0) = ofRandom(-1,1);

	RungeKutta(dXX, XX, uu, tt, dt, AA, BB, CC, DD);
	YY = CC*XX;
	tt += dt;

	vector<float>value;
	value.push_back(YY(0, 0));
	value.push_back(uu(0,0));
	graph.add(value);

}

void ofApp::draw(){
	ofBackground(50, 50, 50);
	gui.draw();
	graph.draw();
}

```


ofApp.h

```c
#include "ofMain.h"
#include "ofxGraph.h"
#include "ofxGui.h"

#define _USE_MATH_DEFINES
#include <math.h>

#include "Eigen/Dense"
#include "Eigen/Core"
#include <iostream>
#include <fstream>

using namespace Eigen;
using namespace std;

class ofApp : public ofBaseApp{
	public:
		void setup();
		void update();
		void draw();
		ofxGraph graph;
		long frame;
		ofxPanel gui;
		ofxFloatSlider kk,mm,cc;
		MatrixXd AA;
		MatrixXd BB; 
		MatrixXd CC;
		MatrixXd DD;
		MatrixXd XX;
		MatrixXd dXX;
		MatrixXd uu;
		MatrixXd YY;
		double dt ;
		double tt ;
};
```

ソースは以下にも格納済み。
https://github.com/nnn112358/180217_system_control