OBDから取得した車両データをDashとPlotly Expressで可視化する  その1

#この記事の内容#
・OBDを使った車両データの取得方法
・車両データの整形についての事例
・DashとPlotly Expressを使った車両データの可視化方法

#実行環境#
macOS Mojave version10.14.5
Python 3.7.2
dash 1.0.0a1
dash-core-components 1.0.0a4
dash-html-components 1.0.0a2
plotly-express 0.3.0
pandas 0.24.2 

#OBDとは#
オン・ボード・ダイアグノーシス（On-board diagnostics; OBD）とは、自動車各部に取り付けられたECU（Electrical Controll Unit）にプログラミングされている自己診断機能である。
例えばエンジンの燃料噴射システムを構成する各センサー、および各アクチュエータに、なんらかの異常が発生した場合、エンジンのECUは異常の発生を記憶し、計器盤の警告ランプを点灯させるなりして、ドライバーに異常の発生を知らせる。　
出典: フリー百科事典『ウィキペディア（Wikipedia）』

**要はOBDにアクセスすることで、ECUにある車両の様々なデータを取り出せるということです。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/bb14d9d0-97f5-7a2a-fdad-b6edbc070798.png)



#Dashとは#
Pythonの可視化ライブラリの一つで、Flask、React、Plotlyが組み合わされて作られています。
Herokuなどのサーバーを利用して簡単にウェブアプリケーションが作れることが特長です。

＊公式ドキュメント
[Dash by Plotly - Plotly]
(https://plot.ly/products/dash/)

＊使い方はこちらを参考にさせていただきました
[Pythonの可視化ライブラリDashを使う](https://qiita.com/OgawaHideyuki/items/6df65fbbc688f52eb82c)

#Plotly Expressとは#
Pythonの可視化ライブラリPlotlyのwrapperで、簡単にjupyter notebook上でデータを可視化
できます。アニメーションを使って時系列データを動かすのが容易いのが特長です。

＊ギャラリー
[Plotly Express Gallery]
(https://www.plotly.express/)


#OBDを使った車両データの取得方法#
まず以下の物を用意しました。

|   | 名称                                     | 説明                                                    | 価格      | URL                                                                    |
|---|------------------------------------------|---------------------------------------------------------|-----------|------------------------------------------------------------------------|
| 1 | ELM327 WiFi OBDii インターフェイス       | OBDから取ったデータをWiFiで飛ばす機器                   | ¥１８００ | https://www.youtube.com/watch?v=8VVkRBo5j1E                            |
| 2 | Stanislav Svistunov Car Scanner ELM OBD2 | 1で飛ばしたデータをiphone上で可視化&CSVに変換するアプリ | ¥５００   | https://itunes.apple.com/jp/app/car-scanner-elm-obd2/id1259933623?mt=8 |
| 3 | iPhone7                                  | ２をインストール。データを可視化するモニター            | ー        |                                                                        |
 
ELM327 WiFi OBDii インターフェイス 
![ELM327.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/36cc009f-3db5-3130-bc83-67d8d27fbedc.png)

Stanislav Svistunov Car Scanner ELM OBD2
![Car Scanner.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/d3a8ef2d-b726-aac7-a9cb-ccb34195fa43.png)


       
OBDポートはハンドルの下あたりに有ることが多いです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/20e92d85-b7d4-ea3c-08cb-560df6a6f870.png)

ここに、1の機器を挿してiPhoneで2のアプリを起動してWiFi接続します。
そして、イグニッションをONすると速度や加速度、馬力などがモニターできます。
また、各物理量を時系列にCSVで保存することができます。

＊車両データの取得方法はこちらを参考にさせていただきました
[OBD2 データ(車両情報)を csv で取得する方法]
(https://qiita.com/naohikowatanabe/items/39f14aacb06d04253d17)

#データの整形
さて、上記方法で取得したCSVの中身を見てみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/a21b77de-db71-e7a8-7ce4-eb909b3e8d53.png)

かなり厳しい状況です（笑）
**物理量（PID)によって記録のタイミングがバラバラ（記録点数が物理量によってまちまち）です。**
可視化する際に問題になりそうです。
そこで、これをpandasを駆使して「整然データ」に変形します。


＊整然データについては以下が参考になります。
[整然データとは何か]
(https://id.fnshr.info/2017/01/09/tidy-data-intro/)

データの整形は主に以下を行いました。細部まで記述できませんが、使ったメソッドを記載します。

**１.「SECOND」列から「日時」列を作る（1行目を2019-05-04 13:00:00とする）
　（pd.to_datetime）
２.「日時」列と「PID」列の各値を列に取るDataFrameを作る
３.上記DataFrameを「日時」列の1s間ごとの平均にする（groupby()）
４.「PID」列の各値ごとに作ったDataFrameを内部結合する（df1.join(df2,how="inner"))
５.「PID」列の各値の名称を日本語に変更する（df.rename(columns={"A":"B"},inplace=True))**

ここまでで作業時間の8割を使いました（笑）。
下がCSVをpandasに読み込んだ直後の状態

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/8f5bce9a-2cc2-dc94-f094-2db788caae82.png)

下が整形が終わった後の状態です。整然データになりました。
一旦CSVに保存しておき、後でDashの中で読み込みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/656ae378-dfe7-42bb-9535-3c4cc5551f18.png)

#DashとPlotly Expressを使った可視化#
ようやく可視化のためのコードを書けます。

Dashの中でPlotly Expressを動かします。
callbackの下に書いたmake_figure関数に、x軸、y軸、colorに取る物理量（DataFrameの列に相当）を渡します。そして、```return px.scatter（...)```でPlotly Expressで作図した散布図を返すようにしました。

なぜDashとPlotly Expressを組み合わせたかと言うと、
Plotly Expressでアニメーションを簡単に作り、Dashで簡単にウェブに上げることを狙ったためです。しかし、現時点でDashの中でPlotly Expressのアニメーション機能を使えていません。。

```python

import plotly_express as px
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import pandas as pd

OBD2=pd.read_csv("上で整形したCSVのパスを書きます")

col_options = [dict(label=x, value=x) for x in OBD2.columns]
dimensions = ["x", "y", "color"]

app = dash.Dash(__name__, external_stylesheets=["https://codepen.io/chriddyp/pen/bWLwgP.css"])

app.layout = html.Div(
    [
        html.H1("Visualization of OBD by Dash"),
        html.Div(
            [
                html.P([d + ":", dcc.Dropdown(id=d, options=col_options)])
                for d in dimensions
            ],
            style={"width": "25%", "float": "left"},
        ),
        dcc.Graph(id="graph", style={"width": "75%", "display": "inline-block"})
    ])

@app.callback(Output("graph", "figure"), [Input(d, "value") for d in dimensions])
def make_figure(x, y, color):
    return px.scatter(
        OBD2,
        x=x,
        y=y,
        color=color,
        height=700)

#px.scatter()はplotly_expressの描画部分

if __name__ == '__main__':
    app.run_server(debug=True)

```
上のコードを実行すると、ブラウザ上で以下のアプリケーションが立ち上がります。
まず、x軸に「日時」、y軸に「速度(km/h)」、colorに「燃費(km/l)」を選んでみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/dc95464b-36be-b204-f6d0-db3d8e3b8d11.png)

速度の時系列データが表示されました。なんとなく、速度が大きい点で燃費が高いように見えます。
そこで、x軸を「速度(km/h)」、y軸を「燃費(km/l)」に変更します。すると以下のようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/0afc9374-ea1b-58f7-3222-41a3cefb35a9.png)

速度が極端に小さい（10km/h以下）では燃費も低く、速度と燃費に相関が有りそうです。
しかし、速度が大きい場合には同一速度であっても燃費のばらつきが大きく、明確な相関はなさそうです。

色々やってみます（笑）。x軸を「エンジン回転数(rmp)」、y軸を「速度(km/h)」、colorを「燃費(km/l)」にすると、以下のようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/bbb6311e-d9d0-8392-5318-4152edb7e9c9.png)

散布図の中に傾きの異なる7つの直線が現れました。これは、おそらく1速〜7速に該当する直線だと思います。上4本の直線上に燃費の良い点が現れてくることが分かります。
1〜3速（下3本の直線）は燃費悪そうです。

変数を色々変えながら、燃費の良い運転を思考しましたが、よく分かりませんでしたw　
3変数では整理できない複雑な現象なのだと思います。（詳しい方いたら教えてください）

以下にアプリケーションを上げていますので、触っていただいて何か発見があれば連絡いただければ幸いです。
[Visualization of OBD by Dash]
(https://obd-visualization.herokuapp.com/)

#その１終了#

その1では、OBDから取得した車両データをDashとPlotly Expressで可視化し、
燃費の良い運転を思考しました。
その2では、車両データとGPSデータを紐付けて地図上にプロットしてみたいと思います。