Jythonは、Java VM 上で実装された Python です。
Jython RTコンポーネント自体は Python で実装しますが、実際に動作するのは Java VM 上ということになって、OpenRTM-aist-Python は使えません。
RTCビルダを使って Java用の RT コンポーネントのスケルトンを作成して、これを Jython スクリプトから操作することになります。
さらに、jythonスクリプトも、RTCビルダでPython用のRTコンポーネントを作成し、Juthonで動かすための修正を加えることになります。
ここでは、Java RTC と Python RTC のサンプルプログラム、SimpleService/MyServiceConsumer について、Jythonバージョンを作成してみます。
非常にややこしいので、頭を整理しながら作業してください。
作業ディレクトリとして、JythonRTCを作成し、その下に RTMExamples を作成します。
% mkdir -p JythonRTC/RTMExamples % cd JythonRTC/RTMExamples
% cp -pr /usr/local/lib/OpenRTM-aist/1.0/examples/RTMExamples/SimpleService/ .
% cp /usr/share/OpenRTM-aist/examples/python/SimpleService/MyServiceConsumer.py SimpleService
.class ファイルがあったらそれも削除します。
また、以下のファイルについてはエンコーディングを Shift_JIS から UTF-8 に変更します。まず、shebang と マジックコメントを python から jython に変更します。
myserviceconsumer_spec の、languageに対応する値も Python から Jythonにしておきましょう。
「OpenRTM_aist.」と書いてある部分はすべて削除します。
また、RTC.RTC_OKを返しているreturn 文は、スーパークラスメソッドを返すように変更します。
Jythonの場合、スーパークラスメソッドは self.super__#メソッド名# となります。
元の import 文は、以下のようになっています。
import sys import string import RTC import SimpleService import OpenRTM_aist from omniORB import CORBA
from RTMExamples.SimpleService import MyService from jp.go.aist.rtm.RTC.util import Properties from jp.go.aist.rtm.RTC import Manager,ModuleInitProc,DataFlowComponentBase from jp.go.aist.rtm.RTC import RtcNewFunc, RtcDeleteFunc from jp.go.aist.rtm.RTC.port import CorbaPort, CorbaConsumer
今回は利用しませんが、残しておくことにします。
MyServiceNewFunc, MyServiceDeleteFunc の二つのクラスを追加します。registerFactory に与えるためのクラスです。
# constructor def __init__(self, manager): OpenRTM_aist.DataFlowComponentBase.__init__(self, manager) self._async_echo = None self._result = [None] return
onInitialize の中に、次のような行があります。
self._myservice0 = OpenRTM_aist.CorbaConsumer(interfaceType=SimpleService.MyService)
self._myservice0 = CorbaConsumer(interfaceType=SimpleService.MyService)
self._myservice0 = CorbaConsumer(MyService)
最後の return RTC.RTC_OK は、原則どおり
return self.super__onInitialize()
随所に return RTC.RTC_OK があるので、原則どおり
return self.super__onExecute(ec_id)
今回、非同期通信は行わないので、
echo コマンドまわり、echo 終了判定の
# if self._async_echo and self._async_echo.finished(): # print "echo() finished: ", self._result[0] # self._async_echo = None
if argv[0] == "echo" and len(argv) > 1:
retmsg = self._myservice0._ptr().echo(argv[1]) print "echo() return: ", retmsg
# if not self._async_echo: # retmsg = "" # func = echo_functor(argv[1],self._result) # self._async_echo = OpenRTM_aist.Async_tInvoker(self._myservice0._ptr(), # func) # self._async_echo.invoke() # else: # print "echo() still invoking"
OpenRTM_aist.CORBA_SeqUtil.for_each(self._myservice0._ptr().get_echo_history(), self.seq_print())
echo_history = self._myservice0._ptr().get_echo_history() for i in range(len(echo_history)): print repr(i) + ": " + echo_history[i]
value_history = self._myservice0._ptr().get_value_history() for i in range(len(value_history)): print repr(i) + ": " + repr(value_history[i])
profile = Properties(defaults_str=myserviceconsumer_spec) manager.registerFactory(profile, MyServiceConsumer, Delete)
MyServiceNewFunc(), MyServiceDeleteFunc())
def MyServiceConsumerInit(manager): profile = Properties(myserviceconsumer_spec) manager.registerFactory(profile, MyServiceNewFunc(), MyServiceDeleteFunc())
Jython2.2 でも動かすために、MyModuleInit 関数を、MyModuleInitProc クラスの myModuleInit メソッドに修正します。
まず、関数名の頭文字を大文字から小文字に修正し、第一引数 self を追加します。
def myModuleInit(self, manager):
class MyModuleInitProc(ModuleInitProc):
修正後の全体は以下のようになります。
class MyModuleInitProc(ModuleInitProc): def myModuleInit(self, manager): MyServiceConsumerInit(manager) # Create a component comp = manager.createComponent("MyServiceConsumer") return
TypeError: myModuleInit() too many arguments; expected 1 got 2
mgr = OpenRTM_aist.Manager.init(sys.argv)
mgr = Manager.init(sys.argv)
また、先に MyModuleInit 関数を MyModuleInitProc クラスの myModuleInit メソッドに修正したのに合わせて、以下の行
mgr.setModuleInitProc(MyModuleInit)
mgr.setModuleInitProc(MyModuleInitProc())
今修正したソースファイルがあるのは、 JythonRTC/RTMexamples/SimpleService です。
これを実行するためには、まずJythonRTC ディレクトリに上がります。
% cd ../..
% jython RTMexamples/SimpleService/MyServiceConsumer.py
RTコンポーネントを実際に動かすには、対応する MyServiceProvider が必要です。別の端末から python 版または Java 版を起動して、RTシステムエディタで双方を接続、アクティベートします。
MyServiceConsumer.py を実行している端末から、echoやget_value, set_value などのコマンドを打ち込んでみましょう。
import SimpleService, SimpleService__POA
from RTMExamples.SimpleService import MyServicePOA