忍者ブログ
ロボット、千葉ロッテマリーンズについていいかげんなことを書きます。
[6]  [7]  [8]  [9]  [10]  [11]  [12]  [13]  [14]  [15]  [16
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

F#とIronPythonのRTCのプログラムですが、色々おかしかったので修正しました。

F#やIronPythonで実装した方がいい時もあるかもしれないです。

C++、Python、Java、C#、VB.net、C++/CLI、Scala、Erlang、Jython、F#、IronPythonで
動くRTCは見たことがありますけど、それ以外にも何かあるかもしれないです。






さっき気付いたのですけど、InPortPushConnectorクラスとOutPortPushConnectorクラスのコンストラクタでプロバイダ(例:InPortCorbaCdrProvider)とコンシュマー(例:InPortCorbaCdrConsumer)のinit関数が呼び出されているのですが、何故かInPortPullConnectorクラスとOutPortPullConnectorクラスのコンストラクタではプロバイダ(例:OutPortCorbaCdrProvider)とコンシュマー(例:OutPortCorbaCdrConsumer)のinit関数は呼び出されていません。

Push型に設定したときにInPortCorbaCdrProviderクラスやInPortCorbaCdrConsumerクラスのinit関数は、InPortBaseクラスのcreateConsumer関数とcreateProvider関数で呼び出す分も含めて2回実行するわけですが、Pull型に設定したときにOutPortCorbaCdrProviderクラスやOutPortPullConnectorクラスのinit関数は何故か1回しか呼び出されていないのでかなり混乱しました。

C++版でもPython版でもこうなっているので仕様かもしれないです。



文字数が多くなったので簡単に言うと、Push型の場合はプロバイダ、コンシュマーのinit関数が2回呼ばれますけど、Pull型では1回しか呼び出されないというだけです。





それから独自の通信を実装してプロバイダ、コンシュマーのファクトリへの登録を行うと、RTシステムエディタで接続するときに何故かInterface_typeの選択肢が増殖します。

これはOutPortBaseクラスのinitProviders関数、initConsumers関数でappendProperty関数を使ってプロパティを追加するわけですが、appendProperty関数内部ではNVUtilのappendStringValue関数を使用しています。

initProviders関数、initConsumers関数でappendProperty関数の引数には、

corba_cdr, shared_memory, direct

のようにコンマで区切った文字列が渡されるわけですが、これがそのままappendStringValue関数に渡されています。
appendStringValue関数内部では現在のプロパティの値をコンマで分割した各文字列と新規に追加する文字列を比較するわけですが、上記のような文字列を直接入力すると正常に比較ができません。

例えば、

事前にあるプロパティにこういう値が入力されているとします。


test1, test2, test3


そして、新たに以下の要素を追加しようとします。


test1, test4, test3


すると以下の文字列同士の比較を行って、一致した場合は追加しないようにします。
  1. "test1"と"test1, test4, test3"
  2. "test2"と"test1, test4, test3"
  3. "test3"と"test1, test4, test3"
何故かコンマで区切ったそれぞれの要素と比較したいのに文字列全体を比較してしまっているみたいですね。
まあ別にこの現象が起こっても困るわけではないので、あまり気にする事もないかもしれないです。








にほんブログ村 科学ブログ ロボットへ
にほんブログ村のロボットのカテゴリから
全然人が来ない・・・

人気ブログランキングへ
PR
登録するマスターマネージャが存在する場合、スレーブマネージャ起動時に自動的に登録できるわけですが、プロセスが強制終了したとかでスレーブマネージャに通信ができなくなった場合でもマスターマネージャのget_slave_managers関数で取得できるスレーブマネージャにはゾンビが残ってしまっています。

なのでスレーブマネージャがゾンビかどうかを判定するプログラムは自分で作る必要があるので注意してください。





RTCのコンフィギュレーションパラメータは通常は、

rtc.confに、


Category.Test.config_file: Test.conf
(カテゴリ名.RTC名.config_file: ファイル名)


コンフィギュレーションパラメータ設定ファイルに、


conf.default.param: 100
(conf.コンフィギュレーションセット名.パラメータ名:パラメータ)


と記述して設定しますが、直接rtc.confに


Category.Test.conf.default.param: 100
(カテゴリ名.RTC名.conf.コンフィギュレーションセット名.パラメータ名:パラメータ)


と記述しても反映されます。

知っておけば役立つかもしれないです。
実行に必要なファイル数が増えるだけで少し面倒なので、rtc.confに直接記述したほうが楽ができる事もあるかもしれないです。






あまり書くことがなかったので、IronPython+OpenRTM.NETで動作するRTCを作ってみました。
IronPythonでは属性は付加できないらしいので、OpenRTM.NETのOldTypeComponentというサンプルを参考にしながら作成しました。

何故かコンフィギュレーションパラメータが設定できません。詳しい人は教えてください。

けど個人的にはOldTypeComponentの古い形式の方がOpenRTM-aistの記述に近いので分かりやすいけれどなあと思います。

よく分かりませんが、IronPython+OpenRTM.NETで使えない関数があります。SetCurrentTime関数やisNew関数が使えないようですが、どうにも拡張メソッドで追加した関数が駄目みたいです。IronPythonでRTCを作るときには注意しましょう。そんな人が果たしているのかどうかは分かりませんけど。


それからF#+OpenRTM.NETで動作するRTCも作りました。だいぶ前に作ったけど、データポートもコンフィギュレーションパラメータも設定してなかったので作り直しました。
こっちは普通にカスタム属性が使えます。F#でRTCを作る人なんて見たことないので需要があるかどうかは知りませんけど。


IronRubyとかJScript.NETでも多分動くとは思いますけど、誰かやった人はいるのでしょうかね?










にほんブログ村 科学ブログ ロボットへ
にほんブログ村のロボットのカテゴリから
全然人が来ない・・・

人気ブログランキングへ
今回はいくつか用語について説明します。
間違っていたらコメントで指摘してください。



まずRTCをexitではなくプロセスを強制終了したりするとゾンビが出てきますが、これがどういう状態なのか説明します。
まずRTCは起動時にネームサーバーにオブジェクトの参照を登録します。
この参照を使ってRTCの各種操作ができるようになるわけですが、当然のことながらRTCのプロセスが消えると操作はできなくなります。
これで参照だけは消えずに残っている状態がゾンビという事にはなると思います。
要はこの図のサーバーが消えた状態です。
ただプロセスが終了した以外にもファイアーウォール等で通信できなくなっている状態もあるかもしれないです。





マスターマネージャ、スレーブマネージャについて説明します。

まずマネージャは基本的に1つのプロセスで1つ起動されるわけですが、大きく分けて以下の3つの状態で起動するのだとは思います。
  1. マスターマネージャとして起動
  2. スレーブマネージャとして起動(登録するマスターマネージャが存在する)
  3. スレーブマネージャとして起動(登録するマスターマネージャが存在しない)
まず1ですが、マスターマネージャとして起動する事でcorbaloc形式、もしくはネームサーバーからマネージャのオブジェクトリファレンスを取得することができます。マネージャのオブジェクトリファレンスを取得するコードは以前の記事の通りです。

2ですが、登録するマスターマネージャが存在する場合は起動時に自動的にマスターマネージャにスレーブマネージャのオブジェクトリファレンスを登録します。スレーブマネージャはマスターマネージャのオブジェクトリファレンスからget_slave_managers関数を使えば取得できます。つまりマスターマネージャからスレーブマネージャを操作できるようになります。

3ですが、マネージャを外部から操作する事はできなくなります。





修正されているのかどうかは知りませんが、RTシステムエディタでマスターマネージャを選択すると固まります。
マネージャのget_loadable_modules関数でロード可能なモジュールを取得しようとする時に発生するみたいです。
まずrtc.confでどのような設定をしているかにもよりますが、C++はrtcprof.exe、Pythonはrtcprof_python.bat、Javaはrtcprof_java.batでRTCのプロファイル(ソースコードの~_specの部分)を読み込みます。

そもそも
rtcprof.exe、rtcprof_python.bat(rtcprof.py)、rtcprof_java.bat(rtcprof.jar)を使うとどうなるかと言うと、

> rtcprof test.dll


implementation_id: test
type_name: test
description: test Component
version: 1.0
vendor: Sample
category: Sample
activity_type: PERIODIC
kind: DataFlowComponent
max_instance: 0
language: C++
lang_type: compile

こんな感じでプロファイルが出力されます。
要するにC++版のOpenRTM-aistのマネージャではrtcprof.exe、rtcprof_python.bat、rtcprof_java.batを実行して出力を受け取ることで各言語のRTCのプロファイルを取得できるわけですが、この時にRTシステムエディタが固まることもあるらしい。

まずRTCではないDLLがモジュールの探索パスに存在する場合に少し固まりますが、これは別に大して気にならないと思います。

ただrtcprof_python.batはプロファイルを出力してもプロセスが終了しないらしく、ここで固まって動かなくなります。しかもおそらくrtc.confはプロセスを起動したディレクトリのものを読み込むので、manager.is_masterがYESになっているかmanager.shutdown_autoがNOになっていれば永久に終わらないという事になります。
一応ですがrtcprof.pyのマネージャ初期化直後にマネージャの終了処理をすればプロセスは終了するのでそうしてください。


  OpenRTM_aist.Manager.init(opts)
  mgr = OpenRTM_aist.Manager.instance()
  mgr.shutdown()   ←追加

ここでマネージャの終了処理をしても特に問題はないようです。

(追記)上の方法は根本的な解決にはなっていないような気がするので、気になる人はC:\Python27\Lib\site-packages\OpenRTM_aistあたりにあるManager.pyを編集してください。


self._timer = OpenRTM_aist.Timer(tm)
self._timer._thread.setDaemon(True)  ←追加
self._timer.start()






ただPythonのOpenRTM-aistでマネージャを起動してもこの現象は起きません。
Python版ではrtcprof.pyを使っておらず、ModuleManagerの__getRtcProfile関数で処理しているので問題ないようです。
なのでPython版でrtc.confのmanager.modules.<lang>.suffixesやmanager.modules.<lang>.profile_cmdは設定しても全く意味がないみたいです。






あまり知られていない機能だと思いますが、マネージャのcreate_component関数で、




test&manager=localhost:2810(コンポーネント名&manager=マスターマネージャのアドレス:ポート番号)




のような形式で入力すると指定したマスターマネージャ上でRTCを起動してくれます。
指定したマスターマネージャが起動していない場合は新たにプロセスを起動してくれるみたいです。
ただ、一体何が正しい動作なのかがよく分かっていません。
ManagerServant.cppのマスターマネージャ起動のところのソースコードを見てみると、

std::string cmd("rtcd -p ");
cmd += mgrvstr[1];
int ret(coil::launch_shell(cmd.c_str()));


となっているのでrtc.confはプロセスを起動したディレクトリのものを読み込むことになると思います。つまりそのrtc.confでマスターマネージャを起動するように設定していなければマスターマネージャは起動する事はありません。

何が正しい使い方なのかは謎ですが、使う機会もあるかもしれないので豆知識程度に覚えておいてもいいかもしれないです。













にほんブログ村 科学ブログ ロボットへ
にほんブログ村のロボットのカテゴリから
全然人が来ない・・・

  • 人気ブログランキングへ
corbaloc形式でCORBAオブジェクトにアクセスする方法を説明しましたが、一応アクセスできるようにする方法についても説明します。

このコードの通りに、


poa = orb.resolve_initial_references("omniINSPOA")
poa._get_the_POAManager().activate()
id = "test"
poa.activate_object_with_id(id, ei)


みたいな感じにすればアクセスできるようになっています。
後は前回説明した手順でcorbaloc:iiop:localhost:2810/testのURLでオブジェクトリファレンスを取得できます。







役に立つことは少ないような気がしますが、データポートやサービスポートのテストをするプログラムを最短で書いてみるとこんな感じになるとは思います。意外に面倒くさいです。

まずRTCは起動しません。
マネージャを起動後、データポートを初期化します。
接続先のRTCのオブジェクトリファレンス、さらにそこからget_ports関数でポートを取得します。
後はconnect関数で接続して、適当にデータの入出力をするだけです。


このプログラムで初期化したデータポートは基本的には外からアクセスはできないので、IORを表示するようにしてやるか、ネーミングサービスに登録するか、あるいは上の手順でcorbaloc形式でアクセスできるようにするかしてやれば外部から操作はできるようにはなります。





まあ普通にテスト用のRTCを作成するか、rtshellとか使った方が楽なので、豆知識程度に覚えておくと役立つこともあるかもしれないです。








にほんブログ村 科学ブログ ロボットへ
にほんブログ村のロボットのカテゴリから
全然人が来ない・・・

人気ブログランキングへ
ものすごい今更ですが、RTC起動時のコマンドライン引数について説明します。

まずコマンドラインオプションには以下のようなものがあります。



-f コンフィギュレーションファイル(rtc.conf)の指定
-l ロードするモジュールの指定(未実装らしい)
-o その他のオプション(何でも設定可能)
-d マスターマネージャに設定(ソースコードには「デフォルトのコンフィギュレーションを使う。」と書いてあるが、実際にはマスターマネージャに設定しているだけなので最終的にどうなるかは不明)
-p ポート番号設定(corba.endpoint)
-a マネージャのCORBAサーバントを起動しないようにする(外部からマネージャの操作はできなくなる)


よく使うのは-fだと思います。


testComp.exe -f rtc.conf




-oは何でも設定できるので使いこなせれば便利です。


testComp.exe  -o "manager.modules.preload: test2.dll" -o "manager.components.precreate: test2"










次にこれも基本的な話らしいのですが、corbaloc形式でマスターマネージャにアクセスする方法を説明します。

#!/usr/bin/env python
# -*- coding: euc-jp -*-
from omniORB import CORBA
import RTM
orb = CORBA.ORB_init([], CORBA.ORB_ID)
mgrloc = "corbaloc:iiop:localhost:2810/manager"
mobj = orb.string_to_object(mgrloc)
mgr = mobj._narrow(RTM.Manager)

ソースコードとしてはこれだけです。
CORBAのstring_to_objectにURLを渡してオブジェクトリファレンスを取得するだけです。

以下のような形式でURLを記述する事でアクセスできます。


corbaloc:iiop:ホスト名:ポート番号/マネージャ名



ホスト名、ポート番号はrtc.confのcorba.master_managerで設定できます。
マネージャ名はmanger.nameで設定してください。

後はrtc.confにはmaanger_naming_formatsという項目があるわけですが、これはネームサーバに登録するフォーマットの指定なのでcorbaloc形式でアクセスする場合には関係ありません。





corbaname形式を使えばネームサーバーに登録された名前からオブジェクトリファレンスを取得できます。


(省略)
mgrname = "corbaname::localhost:2809/NameService#manager.mgr"
mobj = orb.string_to_object(mgrname)
mgr = mobj._narrow(RTM.Manager)






後はCORBAでは一番基本的なIOR形式です。


mgrior = "IOR:010000001400000049444c3a52544d2f4d616e616765723a312e300001000000000000005c000000010102000c0000003139322e3136382e302e3200fa0a0000070000006d616e61676572000200000000000000080000000100000000545441010000001c00000001000000010001000100000001000105090101000100000009010100"
mobj = orb.string_to_object(mgrior)
mgr = mobj._narrow(RTM.Manager)



とは言ってもマネージャを操作するのにIORを使う人はあまりいないかもしれないです。そもそもIORを取得する手段があるかどうか不明です。





まあでも実際にマネージャやRTCを操作するプログラムを作ろうと思ったら、ルートコンテキストから登録されたオブジェクトを検索するプログラムを組む事が多いし、あまりcorbaloc形式を使ったことはありません。


from omniORB import CORBA
import OpenRTM_aist
import RTM
orb = CORBA.ORB_init([], CORBA.ORB_ID)
address = "localhost:2809"
ns = OpenRTM_aist.CorbaNaming(orb, address)
name_cxt = ns.getRootContext()
bl,bi = name_cxt.list(100)
for b in bl:
    
    if b.binding_name[0].kind == "mgr":
        mobj = OpenRTM_aist.CorbaConsumer()
        mobj.setObject(name_cxt.resolve(b.binding_name))
        mgr = mobj.getObject()._narrow(RTM.Manager)






まあでも実際にマネージャを操作する場合はrtshellとかRTシステムエディタみたいな何らかのツールを使うだろうから、知っていてもあまり役には立たないかもしれないです。














にほんブログ村 科学ブログ ロボットへ
にほんブログ村のロボットのカテゴリから
全然人が来ない・・・

人気ブログランキングへ
カレンダー
03 2024/04 05
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
フリーエリア
最新CM
[08/31 ysuga]
[08/31 Nobu]
[08/31 ysuga]
[12/11 Nobu]
[12/11 Kanamura]
最新TB
プロフィール
HN:
Nobu
年齢:
35
性別:
男性
誕生日:
1988/09/22
職業:
あれ
趣味:
妄想、自堕落
バーコード
ブログ内検索
P R
カウンター
忍者ブログ [PR]