CorbaPort.py

説明を見る。
00001 #!/usr/bin/env python
00002 # -*- coding: euc-jp -*-
00003 
00004 ##
00005 #  \file  CorbaPort.py
00006 #  \brief CorbaPort class
00007 #  \date  $Date: 2007/09/26 $
00008 #  \author Noriaki Ando <n-ando@aist.go.jp> and Shinji Kurihara
00009 # 
00010 #  Copyright (C) 2006-2008
00011 #      Noriaki Ando
00012 #      Task-intelligence Research Group,
00013 #      Intelligent Systems Research Institute,
00014 #      National Institute of
00015 #          Advanced Industrial Science and Technology (AIST), Japan
00016 #      All rights reserved.
00017 
00018 from omniORB import any
00019 import traceback
00020 import sys
00021 
00022 import OpenRTM
00023 import RTC, RTC__POA
00024 
00025 
00026 
00027 ##
00028 # @if jp
00029 # @class CorbaPort
00030 # @brief RT コンポーネント CORBA provider/consumer 用 Port
00031 #
00032 # CorbaPort は RT コンポーネントにおいて、ユーザ定義の CORBA オブジェクト
00033 # サービスおよびコンシューマを提供する Port 実装である。
00034 # <p>
00035 # RT コンポーネントは、Port を介してユーザが定義した CORBA サービスを提供
00036 # することができ、これを RT Service (Provider) と呼ぶ。
00037 # また、他の RT コンポーネントのサービスを利用するための CORBA オブジェクト
00038 # のプレースホルダを提供することができ、これを RT Service Consumer と呼ぶ。
00039 # <p>
00040 # CorbaPort は任意の数の Provider および Consumer を管理することができ、
00041 # Port 同士を接続する際に対応する Provider と Consumer を適切に関連付ける
00042 # ことができる。
00043 # <p>
00044 # CorbaPort は通常以下のように利用される。
00045 #
00046 # <pre>
00047 # # CORBAポートの初期化
00048 # self._myServicePort = OpenRTM.CorbaPort("MyService")
00049 #
00050 # // Provider側
00051 # # この Port が提供する Serivce Provider の初期化
00052 # self._mpros = MyServiceSVC_impl()
00053 # # Service Provider を Port に登録
00054 # self._myServicePort.registerProvider("myservice0", "MyService", self._mpros)
00055 #
00056 # // Consumer側
00057 # # この Port が提供する Serivce Consumer の初期化
00058 # self._mycons = OpenRTM.CorbaConsumer(interfaceType=_GlobalIDL.MyService)
00059 # # Service Consumer を Port に登録
00060 # self._myServicePort.registerConsumer("myservice0", "MyService", self._mycons)
00061 #
00062 #
00063 # # CORBAポートへの登録
00064 # self.registerPort(self._myServicePort)
00065 #
00066 # // connect が行われた後
00067 # self.my_cons._ptr().your_service_function(); // YourService の関数をコール
00068 #
00069 # // connect された 別のコンポーネントにおいて
00070 # self.m_cons1._ptr().my_service_function(); // MyService の関数をコール
00071 # </pre>
00072 #
00073 # このように、提供したい Service Provider を registerProvider() で登録
00074 # することにより、他のコンポーネントから利用可能にし、他方、
00075 # 利用したい Service Consumer を registerConsumer() で登録することにより
00076 # 他のコンポーネントの Service をコンポーネント内で利用可能にすることが
00077 # できる。
00078 #
00079 # @since 0.4.0
00080 #
00081 # @else
00082 # @class CorbaPort
00083 # @brief RT Conponent CORBA service/consumer Port
00084 #
00085 # CorbaPort is an implementation of the Port of RT-Component's that provides
00086 # user-defined CORBA Object Service and Consumer.
00087 # <p>
00088 # RT-Component can provide user-defined CORBA serivces, which is called
00089 # RT-Serivce (Provider), through the Ports.
00090 # RT-Component can also provide place-holder, which is called RT-Serivce
00091 # Consumer, to use other RT-Component's service.
00092 # <p>
00093 # The CorbaPort can manage any number of Providers and Consumers, can
00094 # associate Consumers with correspondent Providers when establishing
00095 # connection among Ports.
00096 # <p>
00097 # Usually, CorbaPort is used like the following.
00098 #
00099 # <pre>
00100 # RTC::CorbaPort m_port0; // declaration of Port
00101 #
00102 # MyService_impl m_mysvc0; // Serivce Provider that is provided by the Port
00103 # RTC::CorbaConsumer<YourService> m_cons0; // Consumer of the Port
00104 #
00105 # // register Service Provider to the Port
00106 # m_port0.registerProvider("MyService0", "Generic", m_mysvc0);
00107 # // register Service Consumer to the Port
00108 # m_port0.registerConsumer("YourService0", "Generic", m_cons0 );
00109 #
00110 # // after connect established
00111 #
00112 # m_cons0->your_service_function(); // call a YourService's function
00113 #
00114 # // in another component that is connected with the Port
00115 # m_cons1->my_service_function(); // call a MyService's function
00116 # </pre>
00117 #
00118 # Registering Service Provider by registerProvider(), it can be used from
00119 # other RT-Components.
00120 # Registering Service Consumer by registerConsumer(), other RT-Component's
00121 # services can be used through the consumer object.
00122 #
00123 # @since 0.4.0
00124 #
00125 # @endif
00126 class CorbaPort(OpenRTM.PortBase):
00127   """
00128   """
00129 
00130 
00131 
00132   ##
00133   # @if jp
00134   # @brief コンストラクタ
00135   #
00136   # @param self
00137   # @param name Port の名前
00138   #
00139   # @else
00140   #
00141   # @brief Constructor
00142   #
00143   # @param name The name of Port 
00144   #
00145   # @endif
00146   def __init__(self, name):
00147     OpenRTM.PortBase.__init__(self, name)
00148     self.addProperty("port.port_type", "CorbaPort")
00149     self._providers = []
00150     self._consumers = []
00151 
00152 
00153   ##
00154   # @if jp
00155   #
00156   # @brief Provider を登録する
00157   #
00158   # この Port において提供したいサーバントをこの Port に対して登録する。
00159   # サーバントは、引数で与えられる instance_name, type_name を、
00160   # サーバント自身のインスタンス名およびタイプ名として、サーバントに
00161   # 関連付けられる。
00162   #
00163   # @param self
00164   # @param instance_name サーバントのインスタンス名
00165   # @param type_name サーバントのタイプ名
00166   # @param provider CORBA サーバント
00167   #
00168   # @return 既に同名の instance_name が登録されていれば false を返す。
00169   #
00170   # @else
00171   #
00172   # @brief Register provider
00173   #
00174   # This operation registers a servant, which is provided in this Port,
00175   # to the Port. The servant is associated with "instance_name" and
00176   # "type_name" as the instance name of the servant and as the type name
00177   # of the servant.
00178   #
00179   # @param self
00180   # @param instance_name Servant instance name
00181   # @param type_name Servant type name
00182   # @param provider CORBA Servant
00183   #
00184   # @return if same instance_name is registered, this will return False
00185   #
00186   # @endif
00187   def registerProvider(self, instance_name, type_name, provider):
00188     if not self.appendInterface(instance_name, type_name, RTC.PROVIDED):
00189       return False
00190 
00191     oid = self._default_POA().activate_object(provider)
00192     obj = self._default_POA().id_to_reference(oid)
00193 
00194     key = "port"
00195     key = key + "." + str(type_name) + "." + str(instance_name)
00196 
00197     OpenRTM.CORBA_SeqUtil.push_back(self._providers,
00198                     OpenRTM.NVUtil.newNV(key, obj))
00199 
00200     return True
00201 
00202 
00203   ##
00204   # @if jp
00205   #
00206   # @brief Consumer を登録する
00207   #
00208   # この Port が要求するサービスのプレースホルダであるコンシューマ
00209   # (Consumer) を登録する。
00210   # Consumer が関連付けられるサービスのインスタンス名およびタイプ名として、
00211   # 引数に instance_name, type_name および Consumer 自身を与えることにより、
00212   # 内部でこれらが関連付けられる。
00213   # Port 間の接続 (connect) 時 には、同一の instance_name, type_name を持つ
00214   # サービスが他の Port から提供 (Provide) されている場合、そのサービスの
00215   # オブジェクト参照が自動的に Consumer にセットされる。
00216   #
00217   # @param self
00218   # @param instance_name Consumer が要求するサービスのインスタンス名
00219   # @param type_name Consumer が要求するサービスのタイプ名
00220   # @param consumer CORBA サービスコンシューマ
00221   #
00222   # @return 既に同名の instance_name が登録されていれば false を返す。
00223   #
00224   # @else
00225   #
00226   # @brief Register consumer
00227   #
00228   # This operation registers a consumer, which requiers a service,
00229   # to the other Port. The consumer is associated with "instance_name" and
00230   # "type_name" as the instance name of the service and as the type name
00231   # of the service that is required.
00232   #
00233   # @param self
00234   # @param instance_name An instance name of the service required
00235   # @param type_name An type name of the service required
00236   # @param consumer CORBA service consumer
00237   #
00238   # @return False would be returned if the same instance_name is registered
00239   #
00240   # @endif
00241   def registerConsumer(self, instance_name, type_name, consumer):
00242     if not self.appendInterface(instance_name, type_name, RTC.REQUIRED):
00243       return False
00244 
00245     cons = self.Consumer(instance_name, type_name, consumer)
00246     self._consumers.append(cons)
00247 
00248     return True
00249 
00250 
00251   ##
00252   # @if jp
00253   #
00254   # @brief Interface 情報を公開する
00255   #
00256   # この Portが所有する Provider に関する情報を ConnectorProfile::properties
00257   # に代入する。
00258   # 代入する情報は、NVListの name と value として以下のものが格納される。
00259   #
00260   # - port.<type_name>.<instance_name>: <CORBA::Object_ptr>
00261   #
00262   # ここで、
00263   # - <type_name>: PortInterfaceProfile::type_name
00264   # - <instance_name>: PortInterfaceProfile::instance_name<br>
00265   # である。<br>
00266   # ConnectorProfile::properties では、これらを .(ドット)表記で、
00267   # NameValue のキーとしている。したがって、
00268   #
00269   # <pre>
00270   #  PortInterfaceProfile
00271   #  {
00272   #    instance_name = "PA10_0";
00273   #    type_name     = "Manipulator";
00274   #    polarity      = PROVIDED;
00275   #  }
00276   #</pre>
00277   #
00278   # ならば、
00279   #
00280   # <pre>
00281   # NameValue = { "port.Manipulator.PA10_0": <Object reference> }
00282   # </pre>
00283   #
00284   # といった値が ConnectorProfile::properties に格納され、他のポートに対して
00285   # 伝達される。他の Port でこのインターフェースを使用する Consumer が
00286   # 存在すれば、ConnectorProfile からこのキーからオブジェクトリファレンスを
00287   # 取得し何らかの形で使用される。
00288   #
00289   # @param self
00290   # @param connector_profile コネクタプロファイル
00291   #
00292   # @return ReturnCode_t 型のリターンコード
00293   #
00294   # @else
00295   #
00296   # @brief Publish interface information
00297   #
00298   # @endif
00299   def publishInterfaces(self, connector_profile):
00300     OpenRTM.CORBA_SeqUtil.push_back_list(connector_profile.properties,
00301                        self._providers)
00302     return RTC.RTC_OK
00303 
00304 
00305   ##
00306   # @if jp
00307   #
00308   # @brief Interface に接続する
00309   #
00310   # この Portが所有する Consumer に適合する Provider に関する情報を
00311   # ConnectorProfile::properties から抽出し Consumer にオブジェクト参照
00312   # をセットする。
00313   #
00314   # 今、Consumer が
00315   # <pre>
00316   #  PortInterfaceProfile
00317   #  {
00318   #    instance_name = "PA10_0";
00319   #    type_name     = "Manipulator";
00320   #    polarity      = REQUIRED;
00321   #  }
00322   # </pre>
00323   # として登録されていれば、他の Port の
00324   # <pre>
00325   #  PortInterfaceProfile
00326   #  {
00327   #    instance_name = "PA10_0";
00328   #    type_name     = "Manipulator";
00329   #    polarity      = PROVIDED;
00330   #  }
00331   # </pre> 
00332   # として登録されている Serivce Provider のオブジェクト参照を探し、
00333   # Consumer にセットする。
00334   # 実際には、ConnectorProfile::properties に
00335   # <pre>
00336   # NameValue = { "port.Manipulator.PA10_0": <Object reference> }
00337   # </pre>
00338   # として登録されている NameValue を探し、そのオブジェクト参照を
00339   # Consumer にセットする。
00340   #
00341   # @param self
00342   # @param connector_profile コネクタプロファイル
00343   #
00344   # @return ReturnCode_t 型のリターンコード
00345   #
00346   # @else
00347   #
00348   # @brief Subscribe interfaces
00349   #
00350   # @endif
00351   def subscribeInterfaces(self, connector_profile):
00352     nv = connector_profile.properties
00353     OpenRTM.CORBA_SeqUtil.for_each(nv, self.subscribe(self._consumers))
00354     return RTC.RTC_OK
00355 
00356 
00357   ##
00358   # @if jp
00359   #
00360   # @brief Interface への接続を解除する
00361   #
00362   # 与えられた ConnectorProfile に関連する Consumer にセットされた
00363   # すべての Object を解放し接続を解除する。
00364   #
00365   # @param self
00366   # @param connector_profile コネクタプロファイル
00367   #
00368   # @else
00369   #
00370   # @brief Unsubscribe interfaces
00371   #
00372   # @endif
00373   def unsubscribeInterfaces(self, connector_profile):
00374     nv = connector_profile.properties
00375 
00376     OpenRTM.CORBA_SeqUtil.for_each(nv, self.unsubscribe(self._consumers))
00377 
00378 
00379 
00380   ##
00381   # @if jp
00382   # @brief Consumer の情報を格納する構造体
00383   # @else
00384   # @brief Consumer inforamtion struct
00385   # @endif
00386   class Consumer:
00387     def __init__(self, _instance_name, _type_name, _cons, _consumer=None):
00388       if _consumer:
00389         self.name = _consumer.name
00390         self.consumer = _consumer.consumer
00391         return
00392       
00393       self.name = "port."+str(_type_name)+"."+str(_instance_name)
00394       self.consumer = _cons
00395 
00396 
00397 
00398   ##
00399   # @if jp
00400   # @brief ConnectorProfile と Consuemr の比較をしオブジェクト参照を
00401   #        セットするための Functor
00402   # @else
00403   # @brief Subscription mutching functor for Consumer
00404   # @endif
00405   class subscribe:
00406     def __init__(self, cons):
00407       self._cons = cons
00408       self._len  = len(cons)
00409 
00410     def __call__(self, nv):
00411       for i in range(self._len):
00412         name_ = nv.name
00413         if self._cons[i].name == name_:
00414           try:
00415             obj = any.from_any(nv.value, keep_structs=True)
00416             self._cons[i].consumer.setObject(obj)
00417           except:
00418             traceback.print_exception(*sis.exc_info())
00419 
00420 
00421 
00422   ##
00423   # @if jp
00424   # @brief Consumer のオブジェクトを解放するための Functor
00425   # @else
00426   # @brief Unsubscription functor for Consumer
00427   # @endif
00428   class unsubscribe:
00429     def __init__(self, cons):
00430       self._cons = cons
00431 
00432     def __call__(self, nv):
00433       for i in range(len(self._cons)):
00434         name_ = nv.name
00435         if self._cons[i].name == name_:
00436           self._cons[i].consumer.releaseObject()

OpenRTMに対してMon Mar 17 15:11:05 2008に生成されました。  doxygen 1.5.4