ControlDeskでPython実行

## 1. はじめに
ControlDesk 4.3以降からPythonが標準で使えるようになっています．
アプリケーション内では以下の2通りの実行方法があります．
- Pythonスクリプトを直接実行
- Instrumentに紐づけたイベント駆動

今回は前者のPythonスクリプトを直接実行する方法を解説します．

## 2. 前提知識
- [イベント駆動とVariablesの記述方法](https://qiita.com/3084LAB/items/dde3d70fe5f84cd0dedc)
Variableの呼び出し方法はこちらでまとめています．

## 3. 記述方法
### (1) ファイル新規作成
新規で作成する場合の作成方法は2通りあります．
(1) `Automationタブ > Insert Script`
(2) `Automationタブ > Script File > New`

![python_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654082/90cc814f-0665-ce67-6408-a55587ffb67b.png)

今回は(1)の手法を説明します．
`Insert Script`を押すとファイル名を入力する画面が出現します．
`Insert info`でスクリプトをどこに格納するか選べますが，基本的にはデフォルトのExperimentで問題ないと思います．

![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654082/7468f6cc-f37c-e539-5ec6-31816a15076e.png)

適当な名前を入力し，OKボタンを押します．
`Projectパネル > Project名 > Experiment名 > Python`の中に項目が出現します．

![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654082/92d90763-afb1-de01-4214-b779f5a8af71.png)

### (2) 編集
新規で作成するとそのままLayoutパネルに新しいタブで出現します．
Layoutと同じように`Ctrl+s`で保存します．

![file.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654082/41ffe1eb-45e9-4e4c-8c84-7a210acca175.png)

※タブとして存在しない場合
`Projectパネル > Project名 > Experiment名 > Python Scripts`の対象のファイルをダブルクリックすれば開けます．

### (3) 実行
`Automation > Run Script`で実行します．
ちなみにControlDeskプロジェクトフォルダ外のプログラムも動作しますが，紐づいていたほうが何かと便利なので上記の方法がおすすめです．

### (4) 外部ファイル
例えば，他のプロジェクトで使用しているファイルや拾ってきたファイルを取り込みたい場合は`Automationタブ > Import Script`でインポートできます．
※バージョン互換性とかあったような...(後ほど追記)

## 5. 具体例
センサ値を1秒ごとに5点計測し平均値を出力するプログラムで説明します．

※時間経過はOSのシステム時間に依存してしまうため，厳密に計測する必要がある場合はSimulink上でアルゴリズムを組みことをおすすめします．
エクスポートしたCSVのデータをマージするとき，時間幅が同一でON時の振幅（計測条件）を変えたデータ同士では視覚的には問題なく重なるのでご安心ください．

### プログラム
```python
# -*- coding:UTF-8 -*-
# ControlDeskのバージョンが古くPython2.X系列の場合，
# コメントに日本語を使うときは文字コードを明示しましょう．

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++
# 数点の平均値を計算するプログラム
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Python modules
import time

# Platform object
MyPlatform = Application.ActiveExperiment.Platforms["Platform"]

# Check the state of application calibration (Go Online).
# 0: Offline, 1: Online
if Application.CalibrationManagement.State == 0:
    print("[error] Please Go Online!")
    exit()

# Define
ScopeVar = MyPlatform.ActiveVariableDescription.Variables["Platform()://Model Root/Scope/In1"]

# Wait for actuator response time.
time.sleep(2)

# Calculate average.
print ("[sys] Calculate average.")
n = 5
list = []
sum = 0.0
ave = 0.0
for i =  in range(0,n):
    sum = sum + ScopeVar.ValueConverted
    time.sleep(1)
ave = sum / n

print(ave)
print("[sys] Finished.")
```


### 解説
10秒弱time.sleep()によりControlDesk画面がフリーズしますが，仕様なので問題ありません．
この状態を回避するためのスレッドの使い方は[次の記事](https://qiita.com/3084LAB/items/eeb5c12760a36410136d)にて紹介します．

- よくある平均値を算出するアルゴリズム
- Application.CalibrationManagement.State
Online状態かOffline状態かを取得することができます．
- MyPlatform.MeasurementDataManagement.Start() (Stop())
呼び出すとStart(Stop) Measuringと同じ動作をします．

### 実行結果
Start Measuringを押している状態でプログラムを実行します．
フリーズしている間にボリュームをいじるなりセンサ値を変動させると，
フリーズが解けた瞬間，Time Plotterにその間のデータが一気に表示されます．


## 6. 注意事項
### 無限ループ
無限ループから抜け出せなくなったらタスクマネージャを開いて`バックグラウンド プロセス`の中のPythonを右クリック`タスクの終了`で終了しましょう．

### Python自体の問題
Python自体がうまく動作しない場合，何かしらの原因でdSPACE用のPythonを構成するファイルが破損している可能性があります．
[1] dSPACE, "FAQ 094: Pythonの再インストール",
https://www.dspace.com/shared/support/faqpdf/faq094jp.pdf

パッケージをインストールしたのに未インストールエラーが出た場合は，pipインストールの対象のバージョンがdSPACEにリンクしているものと異なる可能性があります．（他のバージョンのPythonが共存している場合など）
その場合はPythonのバージョンを明示してpipを呼び出しましょう．

```bash
python3.x -m pip install <package_name>
```
※dSPACEで使用しているPythonにパッケージをインストールする方法は[こちら(未)]()