PythonからLabVIEWにアクセスして処理した結果を受け取る | マーブルルール

PythonからLabVIEWにアクセスして処理した結果を受け取る

その他

スポンサーリンク

この記事では、LabVIEWとPythonの連携手法であるJKI Python Bridgeを使用して、Pythonから引数を渡してLabVIEWで処理し、結果をPythonで受け取るといった流れを紹介しています。

LabVIEWに標準関数としてあるPythonノードとは異なった、「他言語との連携方法」であり、これを実装するための準備や方法を具体例を交えて書いています。

(VI パッケージマネージャで見つけた面白そうなパッケージを触ってみた体験記であり、動作は確認していますが全ての機能を理解して記事作成しているわけではない点ご了承ください)

スポンサーリンク

LabVIEWとPythonを連携させる

ここ最近のLabVIEW(少なくても2020以降)では、Pythonとの連携をもっとしていこうという傾向があり、LabVIEWの関数でもPythonノードというものが用意され、LabVIEWからPythonコードを呼び出してその結果をLabVIEW側で受け取る、という使い方ができます。

Pythonノードの使用方法の基本的な内容について知りたいという場合には以下の記事が参考になるかなと思います。

今回の記事で紹介していくのは、この逆で、PythonからLabVIEWにアクセスして処理を行い、結果をPython側で受け取る、という方法になります。

この向きのデータのやり取りについても、別の方法は過去に記事にしたことがあります。

今回の記事で紹介するのはこれらとは異なる方法で、JKI Python Bridgeというものを使用し、Pythonからオブジェクトと引数を指定してLabVIEWに渡し、LabVIEWで処理された結果をPython側で受け取るという形になります。

最初からどちらか一つのプログラミング言語でプログラム書けばいいのでは?と思われるかもしれませんが、それぞれの言語には違った「得意分野」がありますし、例えば「メインでLabVIEWを使用している人の特定の処理を、メインでPythonを使用している人が自分のプログラムに組み入れたい」と考えているときに今回の記事で扱っている方法が役立つかと思います。

まずは簡単な具体例を紹介していくとこんな感じです。

以下の図では、とてもシンプルな例ですが、数値のリストを与えてその中の最大最小平均と中央値を文字列で返すという処理をしています。

あるいは、LabVIEWではハードウェアでデータを集録していて、Pythonが実行されるたびにその時の測定の最新10点の値を取得する、といった使い方もできます。

要は、LabVIEWでできることは何でも実行し、Pythonに返せる、というわけです。

このようなことができるようになるための準備とプログラムの構築の仕方について紹介していきます。

準備

今回JKI Python Bridgeというものを使用します。

これは、VIパッケージマネージャというものを使用してインストールできる機能です。

機能を使用するにあたって特にライセンスの入力などもなかったことから、無償で使用できるパッケージになっているようです。

VIパッケージマネージャは、よく似た名前の「NI パッケージマネージャ」とは異なり、LabVIEWへのアドオンなどをインストール/アンインストールするための管理ソフトです。

LabVIEWのインストール時に追加するソフトウェア項目として選択できるものでデフォルトではインストールにチェックが入っていることから、知らない間にインストールされているという方もいるかなと思います。

もしPCにインストールされていなくても、VIパッケージマネージャはNI パッケージマネージャから入手することができます。

VIパッケージマネージャを開いたら、JKI Python Bridgeを検索し、これをインストールします。

もしPCに複数のバージョンのLabVIEWがインストールされている場合、どのバージョンのLabVIEWに対してJKI Python Bridgeをインストールするかを決める必要があります。(複数バージョンにインストールはできますが、一度には一つのバージョンしか選べません)

基本的にはインストールを始めたら画面の指示に従ってインストール作業を進めるだけです。

もしVIパッケージマネージャでのインストールでエラーが起こったら、LabVIEW側の設定を変更する必要がある場合があります。

よくあるのは以下の図に示したようなエラーです。

もし上の画像と同じエラーが出た場合には、LabVIEWのオプションの設定を見直して、VIサーバのマシンアクセスとエクスポートVIの設定にアスタリスクを追加することで解決するようです。

インストールが完了したら、パッケージの準備は完了で、あとはPython側の準備を進めます。

JKI Python BridgeにはGitHubのページがあり、仮想環境(venv)を作成してこの仮想環境上のPythonとLabVIEWがアクセスする際の手順が書いてあります。

GitHub - JKISoftware/jki-labview-python-server
Contribute to JKISoftware/jki-labview-python-server development by creating an account on GitHub.

基本的にはこの資料に書いてある手順通り、仮想環境を作成してアクティベートし、Pythonを実行してjki_python_bridge_for_labviewのモジュール(pipでインストールしたもの)をインポートすれば使用できます(作成した仮想環境からjki_python_bridge_for_labviewのモジュールが見つけられるようにする必要はあります)。

ただ、私個人はAnaconda(厳密には私が試したのはminicondaですが)の仮想環境が好きなのでこちらでも試したところ、特に問題なく動作しました。

そこで、ここではanaconda仮想環境上でPythonを実行することを例に流れを紹介していきます。

anacondaのインストール自体は今回の記事の趣旨から離れた内容になるためググって調べてもらえればと思います。

インストール後Anaconda promptを開いたら、仮想環境を作成していきます。

仮想環境の構築は

conda create -n (仮想環境名) python=(バージョン)

で進められます(以下の図では仮想環境名はbridgeenvという名前にしています)。

仮想環境をアクティベートし、ここでjki_python_bridge_for_labviewをインストールしておきます。

GitHubのページに書いてある注意書きの通り、このときインストールするjki_python_bridge_for_labviewのバージョンは、VIパッケージマネージャでインストールしたバージョンと近いものである必要があります。

例えば私が試したときにはVIパッケージマネージャ上でJKI Python Bridgeは5.0.1というバージョンだったため、jki_python_bridge_for_labviewは5.0.1をインストールしました。

インストールの際には

pip install jki-python-bridge-for-labview==5.0.1

などとすることで進められます。

この時点で今アクティベートしている仮想環境でどのようなソフト、モジュールが使用できるかは

conda list

で一覧を出せます。

Pythonでよく使用するnumpy等のモジュールは必要に応じてインストールしてください(ここでは割愛します)。

あとはPythonを開いてこのモジュールをインポートすればひとまず準備は完了です。

モジュールのインポートには、Pythonを実行している状態で

from jki_python_bridge_for_labview import labview as lv

などとします。

サンプルの使い方

この段階で、LabVIEW側の準備であるJKI Python Bridgeのインストール、Python側の準備である仮想環境の作成とjki_python_bridge_for_labviewのインストールが終わっている状態かと思います。

LabVIEW側ではサンプルが見えるようになっているはずなので、サンプルを確認してみます。

サンプルはサンプルファインダにあるのではなく関数パレットからアクセスできます。

サンプルviを一つ、適当な新規viに配置して、ダブルクリックすることで中身を開くことができます。

JKI Python Bridge – Example.viにはフロントパネルにいくつか制御器がありますが、以下で使用するのはExitのボタンと、Client Connectedの表示器のみです。

GitHubのページにも説明はありますが、基本的には

  • PythonからLabVIEWにconnectする
  • Pythonから、オブジェクトとメソッドを指定して実行する(引数が必要なものはそれも指定する)
  • LabVIEW側で引数を受け取って処理し結果をPythonに送る
  • Pythonが結果を受け取る

という流れでこのサンプルを使っていくことになります。

PythonからLabVIEWにconnectする際には、LabVIEW VIは実行している必要があります。

サンプルでも、もしPythonが正常にサンプルプログラムに接続で来た場合にはブール表示器がTrueになります。

サンプルのブロックダイアグラムを確認すると、3つのメソッド(add、echo、hello_world)が用意されていることがわかります。

これらは、全て「example」という名前のオブジェクトに対して定義されています。

それぞれのメソッドで何個の引数が必要かについては、viの左下で定義されています。

もう少し細かく見ると一つのメソッドの定義には

  • メソッド名
  • 引数の数(文字列配列の要素の数が引数の数に対応。引数を必要としない場合には初期化していない文字列配列を指定)
  • メソッドのヘルプに表示する文字

がクラスタとなっており、このクラスタをメソッドの数だけ作成、配列連結追加で合体させています。

それぞれのメソッドに対してイベントストラクチャでユーザイベント中のケースストラクチャが割り当てられています。

自分でオリジナルのメソッドを作る時にも、基本的にはこの形を踏襲すればOKです。

注意点としては、引数を受け取るためのGet Argumentsはなくてもいいですが、Pythonに値を返すSend Return Valueは必須(これがないとPython側でその後の操作ができなくなる)である点です。

このサンプルを踏襲すればいいと言いつつ、そもそもこのサンプルとPythonとで実行時にどのような関係があるかを見てみるために、このサンプルで定義されているメソッドをそれぞれ実行したときの結果例を紹介していきます。

まず、hello_worldメソッドです。

これはLabVIEWのサンプルのブロックダイアグラムを見ると、Hello World!という文字列がSend Return Valueに渡っているだけであり、メソッドの定義でも特に引数は何も指定されていない(文字列配列で要素が一つも初期化されていない)ことがわかります。

実際に実行すると、Python側でhello world!という文字列を受け取るだけです。

次にaddメソッドです。

二つの整数を入力してその和を出力するものとなっています。

二つの整数を受け取るためにはGet Argumentsの入力として二つの数をクラスタとした定数を与えており、これによりこのGet Argumentsの出力としても同じクラスタを得ることができます。

サンプルではクラスタを配列にして配列要素の和の処理を実行しSend Retrun Valueに渡しています。

最後にechoメソッドです。

これは入力した文字列をそのまま返す、文字通りやまびこの動作をします。

今度はPythonから受け取るのは単に文字列だけなので、Get Argumentsには文字列を指定しているだけですね。

使い方としてはどれもそんなに理解するのに難しくはないと思います。

上で書きましたが、引数が無くてもいいものの、戻り値は必ず必要となるので、Send Return Valueは必須です。

ただし、もし戻り値を戻す必要がない処理の場合には、この関数にバリアントの定数を渡せば戻り値のない処理として実装できます(下に例をいくつか出しています)。

もう一つあるサンプルでは、オブジェクトを二つ定義した場合のLabVIEWとPythonの連携の方法の例があります。

いくつか実行した際の例を以下に紹介していきますが、要は複数のオブジェクトがあってもそれぞれに対してメソッドを持たせることができる、ということですね。

データの渡し方、受け取り方

基本的には、サンプルにあるプログラムをベースとして、必要な処理が行えるようにメソッドの名前や中身を変えてやるのが一番簡単な実装方法となります。

全体のイメージとしてはサンプルに従って、Pythonから受け取った引数をLabVIEW側で正しく受け取り、LabVIEWで任意の処理を実行、その結果をPython側に渡す、というメソッドを用意していくことになります。

ただし、Pythonから引数として指定した値をLabVIEWがどう受け取るか、LabVIEWから返した戻り値をPython側でどのように受け取れるかについてがわからないと実装できないので、私がいくつか試した際の結果を載せておきます。

Pythonから引数として指定した値をLabVIEWが受け取る場合

Pythonからは、複数の引数を渡す場合には、カンマ区切りで値を書いていくことになります。

例えば、LabVIEW側では二つの引数を受け取るように定義しておいて、Python側から「5」という数値と「Hello」という文字列を渡す場合には以下のようになります。

なお、引数の指示としてmynumとかmystrなどとしていますが、別に文字はtekitoでもaiueoでも特に問題ないようです。

これらは、Python側からこれらのメソッドを呼び出す際に引数が足りないと表示される際の引数の名前として表示されます。

ちなみに、Documentationはそのメソッドのヘルプを表示する際に表れる文字列を決めています。

もう一つ別の例を見せていきます。

今度は引数を3つにして、「3.14」という数値とブールのTrue、そして文字列で「Test」という文字列を渡す場合は以下のようにします。

また、もし特定のデータ型の集まりをLabVIEWに渡す場合には、Python側からはリストで渡すことになります。

単一種類のデータ型の集まりであればLabVIEW側では配列として受け取ることになります。

(「リスト」としては引数は1つと数えます)

例えば、数値のリストと文字列を渡す場合には以下のようにします。

LabVIEWでは異なるデータタイプのかたまりはクラスタで表現するので、クラスタで受け取ることになります。

これは、リスト中のデータ型が異なる場合にはLabVIEWとしてはクラスタで対応するしかないので、クラスタを用意しておきます。

もちろん、「クラスタが複数入ったクラスタ」として以下のような指定もできます。

これらを踏まえて、わざと複雑な形でデータを渡した場合の例を以下の図に示しています。

LabVIEWから返した戻り値をPython側で受け取る場合

LabVIEWから返した戻り値は、もし単一のデータタイプのみであれば、Python側でもそのデータタイプで受け取ることができます。

もしLabVIEWから配列を戻り値として渡した場合、Python側ではリストとして受け取ることができます。

(PythonからLabVIEWにブール値を渡す場合にはTrueやFalseという指定でしたが、LabVIEWからPythonへブール値を渡す場合にはPython側では0か1かで受け取っています)

LabVIEWからクラスタを戻り値として渡した場合でも、Python側では引き続きリストとして受け取ることができます。

なお、LabVIEWの波形データはPython側に渡してもうまく扱うことができません。

そのため、波形データを渡したい場合には、波形データの要素(t0、dt、Y)を分解してそれぞれ渡す方法しかないようです。

こちらもまた、わざと複雑なデータ型をLabVIEWから渡してどのようにPython側で受け取れるかの例を以下の図で紹介します。

ここまでわかれば、だいたいデータの受け渡し時の指定の仕方は分かったかなと思うので、あとはLabVIEWでしたい処理を組んで、思いのままPythonとの連携を活用してみてください。

最後に、記事冒頭で例に出した、二つの処理の実装例を紹介して終わります。

統計処理を行う場合には数値の配列をPythonから受け取ることになるので、引数の定義はシンプルに数値の配列のみです。

受け取った値に対してLabVIEWのいくつかの関数を使用して処理し、これらをまとめて文字列に変換するために文字列にフォーマット関数を使用してその結果をPythonに返しています。

測定の結果をPythonで取得する場合には、測定して得られた値をPython側に返すだけです。

以下の例ではNI社のDAQデバイスで適当にデータ集録を行っている想定とし、得られた値をローカル変数を介してPythonに渡すようにしています。

当然、ローカル変数を使用する必要はないですし、ハードウェアだってNI社のDAQデバイスである必要はありません。

仕組みさえわかれば色々と応用ができると思います。

本記事では、JKI Python Bridgeを使用して、PythonからLabVIEWのプログラムにアクセスし、与えた引数を基に処理した結果をPythonで受け取る方法の準備と実装例を紹介しました。

Pythonノード然り、色々な方法で連携をする術を知っているのはプログラムの選択の幅を広げられると思うので、この記事で紹介した方法が参考になるとうれしいです。

ここまで読んでいただきありがとうございました。

コメント

タイトルとURLをコピーしました