このプロットどうやって描いたの？：複数プロット、アニメーション編

# こんな感じのプロット描きたい

と @motorcontrolman さんとの話の中で挙がったのがこちら。
<img width="300" alt="sampleImage" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/7558f29e-c931-cbe9-8f3f-5a68b09b21b1.png">
引用：[「モデル予測制御（MPC）による軌道追従制御」](https://qiita.com/taka_horibe/items/47f86e02e2db83b0c570) by @taka_horibe さん

引用元では GIF 動画になっているのですが、簡潔＋綺麗な可視化ですね。動いている小さな長方形はどうやって描いているんだろう・・。

ということで必要な要素の解説を入れながらちょっとづつやってみましょう。@motorcontrolman さんならサクッとできてしまいそうですが（笑


# まずは subplot[^1]

大枠から攻めていきます。Figure 上にプロットを複数作る定番は `subplot` ([公式 doc: subplot](https://jp.mathworks.com/help/matlab/ref/subplot.html?s_eid=PSM_29435)) ですね。

[^1]: 実は R2019b からより柔軟に使える `tiledlayout` ([公式 doc](https://jp.mathworks.com/help/matlab/ref/tiledlayout.html?s_eid=PSM_29435)) というものも入っているんですが、これまはたの機会に。Figure の大きさ変更すると流動的にサブプロットの位置が変わります。

例えば `subplot(3,1,2)` とすると Figure 画面上を 3 x 1 に分割して 2 個目（左から右、上から下に数えます）の位置に axes (座標軸) を作ります（下図左側）。2 つ以上の枠にまたがることも OK なので、例えば `subplot(3,1,[1,2])`（下図右側）として大きめの図を作ります。

<img width="300" alt="fig1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/beabd0fb-de6e-b09b-6f4a-27d448caadba.png"><img width="50" alt="space" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/21d66077-ac5e-cc96-f0c9-7763f9a0c550.png"><img width="300" alt="fig1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/5f47e2a7-52e5-f5d2-1acb-54bbf61d9801.png">


こんな感じ。組み合わせればとりあえずの形ができそう。

```matlab
subplot(5,1,1:3) % subplot(5,1,[1,2,3]) と同じ 
subplot(5,1,4)
subplot(5,1,5)
```

<img width="400" alt="fig2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/6ec254c8-b8ef-40a5-373c-b925acf2d32e.png">

データは適当なもので描いてみました。

<details><summary>実際のコードはこちら</summary><div>

```matlab

% ダミーデータ
Ndata = 200;
t = linspace(0,4*pi, Ndata);
x = sin(3*t);
y = cos(t);

% プロット
subplot(5,1,1:3)
plot(x,y), title('x vs y')
subplot(5,1,4)
plot(t,x), title('x')
subplot(5,1,5)
plot(t,y), title('y')
```

</div></details>

# 動きを加えてみる：アニメーション作成

あと欠かせない要素は動く部分。MATLAB のドキュメンテーション：[アニメーション手法](https://jp.mathworks.com/help/matlab/creating_plots/animation-techniques-1.html?s_eid=PSM_29435) によると

1. 関数 [animatedline](https://jp.mathworks.com/help/matlab/ref/animatedline.html?s_eid=PSM_29435) を使用してストリーミング データのライン アニメーションを作成する。
2. 新規のグラフィックス オブジェクトを作成する代わりに、既存のオブジェクトのプロパティを更新する。

という 2 択のようです。[公式 doc ：アニメーション、プロットのアニメーション化]
(https://jp.mathworks.com/help/matlab/animation-1.html?s_eid=PSM_29435) には他にも情報がまとまっています。ちなみに 1 を使った方法は [Qiita: グラフ背景色をデータの追加とともに変化させるアニメーション作成](https://qiita.com/eigs/items/51194d8232d0ceb68d6b) でも紹介しました。
<img width="300" alt="animation_sampleFinal.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/89506afd-7bc4-c073-afa5-88f117688c13.gif">


## ラインに沿ったマーカーのトレース

ここではとりあえず 2 つ目の「既存のオブジェクトのプロパティを更新する」方法を使ってみます。

- [公式 doc ：ラインに沿ったマーカーのトレース](https://jp.mathworks.com/help/matlab/creating_plots/trace-marker-along-line.html?s_eid=PSM_29435)

このサンプル使ってみましょう。先ほど描いた線上をマーカーを動かします。ポイントは `drawnow`。**一番重要なことなのでもう一度言います。ポイントは [`drawnow`](https://jp.mathworks.com/help/matlab/ref/drawnow.html?s_eid=PSM_29435) です。**

コードの実行中はこのコマンドを実行しないと描画を更新しません（処理速度を下げないため）ので、ループの内で `drawnow` を実行して、逐次描画が更新されるようにします。

<details><summary>実際のコードはこちら</summary><div>

```matlab

Ndata = 200;
t = linspace(0,4*pi, Ndata);
x = sin(3*t);
y = cos(t);

subplot(5,1,1:3)
plot(x,y), title('x vs y')
hold on
p1 = plot(x(1),y(1),'o','MarkerFaceColor','red'); % 逐次更新するオブジェクト１
hold off

subplot(5,1,4)
plot(t,x), title('x')
hold on
p2 = plot(t(1),x(1),'o','MarkerFaceColor','red'); % 逐次更新するオブジェクト２
hold off

subplot(5,1,5)
plot(t,y), title('y')
hold on
p3 = plot(t(1),y(1),'o','MarkerFaceColor','red'); % 逐次更新するオブジェクト３
hold off

filename = 'animation_sample.gif'; % Specify the output file name
frame = getframe(gcf); % Figure 画面をムービーフレーム（構造体）としてキャプチャ
tmp = frame2im(frame); % 画像に変更
[A,map] = rgb2ind(tmp,256); % RGB -> インデックス画像に
imwrite(A,map,filename,'gif','LoopCount',Inf,'DelayTime',0.1);
        
for k = 2:length(x)
    % オブジェクト１のデータ更新
    p1.XData = x(k);
    p1.YData = y(k);
    % オブジェクト２のデータ更新
    p2.XData = t(k);
    p2.YData = x(k);
    % オブジェクト３のデータ更新
    p3.XData = t(k);
    p3.YData = y(k);

    drawnow % 描画更新
    
    frame = getframe(gcf); % Figure 画面をムービーフレーム（構造体）としてキャプチャ
    tmp = frame2im(frame); % 画像に変更
    [A,map] = rgb2ind(tmp,256); % RGB -> インデックス画像に
    imwrite(A,map,filename,'gif','WriteMode','append','DelayTime',0.1);% 画像をアペンド
    
end
```

</div></details>

`imwrite` を使って gif ファイルに出力するコードも入れています。結果は
<img width="500" alt="animation1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/d6653d13-04fa-94fa-6e27-6b26bdd06b85.gif">

こんな感じ。

# ひとまずまとめ

基本的なところを実装してみました。
他にも追加したい要素あればやってみますのでなんなりとコメントください。