MyEnigma

とある自律移動システムエンジニアのブログです。#Robotics #Programing #C++ #Python #MATLAB #Vim #Mathematics #Book #Movie #Traveling #Mac #iPhone

PythonによるROSノードコントロール 2

前回の記事では,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スクリプト内において,

どのようなノードであっても,

任意の時間に起動し,

終了させることが可能になります.



めでたしめでたし.


参考文献

[1]
rosnode - ROS Wiki