前回の記事では,Subprocess モジュールのCall関数とPopen関数を使用して
ROSのノードをPythonスクリプト内で起動する方法について述べました.
PythonによるROSノードコントロール - MY ENIGMA
この Popen 関数は,
起動したノードをマルチプロセスで起動したまま,
次の処理を行います.
従って,起動したノードを終了させるためには,
ノードを終了させるための命令を送らなければなりません.
通常,Subprocess モジュールの関数を利用すれば,
Popen 関数で起動したプロセスを終了させることができますが,
ROSシステムのノードは単一のプロセスで構成させているわけではないため,
通常のSubprocessモジュールの関数では,
任意のROSノードを完璧に終了させることが
難しいという問題がありました.
従って,今回,
ROSシステムにおいて,
起動したノードを
任意のタイミングで終了させるために
ROSにデフォルトで実装されている関数である
rosnode kill を利用して,
ノードを終了させる方法について説明します.
rosnode kill コマンドは,
正確なROSノードの名前を使用することが必要です[1].
しかし,ROSのノードの名前は,
起動ノード名の後にプロセス番号と思われる番号が
割り振られる仕様になっているようです.
(例: fakelocalization 10982982728288).
しかしこの番号は,
ノードが起動した時に自動的に割り振られるため,
事前に正確なノード名を知ることが出来ず,
rosnode killコマンドを使用して
ノードを終了させることが難しいという問題がありました.
従って今回は,
こちらもROSにデフォルトで実装されている関数である,
現在起動しているノード名を取得する
rosnode list 関数を利用し,
その標準出力結果を,文字解析することにより,
正確なノード名を取得する方法を利用します.
そして,取得された正確なノード名を使用して,
rosnode kill 関数からそのノードを終了させるという方法を用いるのです.
以上の,一連のROSノードを終了させるシステムを
1つの関数にまとめたのが,以下の関数です.
def kill_node(nodename): p2=Popen([’rosnode’,’list’],stdout=PIPE) p2.wait() nodelist=p2.communicate() nd=nodelist[0] nd=nd.split("\n") for i in range(len(nd)): tmp=nd[i] ind=tmp.find(nodename) if ind==1: call([’rosnode’,’kill’,nd[i]]) break
この kill node という関数は,
引数に起動ノード名を入力すれば,
その名前の文字列を含むノード名を
rosnode list 関数の出力結果から検索します.
そして見つかった正確なノード名を使用して
rosnode kill 関数を利用してノードを終了させることができるのです.
例えば infant ddf という起動ノード名をしたノードを終了させたい時には,
以下のように Pythonスクリプト内でこの関数を利用すれば大丈夫です.
kill_node(’infant_ddf’)
以上のように,
Call関数とPopen関数,
そしてこのkill_node関数を利用することにより,
Pythonスクリプト内において,
どのようなノードであっても,
任意の時間に起動し,
終了させることが可能になります.
めでたしめでたし.
参考文献