OutPortBase.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- coding: euc-jp -*-
00003 
00004 ##
00005 # @file OutPortBase.py
00006 # @brief OutPortBase base class
00007 # @date $Date: 2007/09/19 $
00008 # @author Noriaki Ando <n-ando@aist.go.jp> and Shinji Kurihara
00009 # 
00010 # Copyright (C) 2003-2008
00011 #     Task-intelligence Research Group,
00012 #     Intelligent Systems Research Institute,
00013 #     National Institute of
00014 #         Advanced Industrial Science and Technology (AIST), Japan
00015 #     All rights reserved.
00016 
00017 import copy
00018 import threading
00019 import OpenRTM_aist
00020 import RTC
00021 
00022 ##
00023 # @if jp
00024 #
00025 # @class OutPortBase
00026 #
00027 # @brief OutPort 基底クラス
00028 # 
00029 # OutPort の基底クラス。
00030 #
00031 #
00032 #
00033 # Properties: port.outport
00034 # プロパティは
00035 #
00036 # - port.outport
00037 # - port.outport.[name]
00038 # ConnectorProfile.properties の場合は
00039 # - dataport.outport
00040 #
00041 # 以下に指定したものが渡される。
00042 # (port.outport.[name]が優先される)
00043 # さらに、一部のプロパティは接続時に ConnectorProfile により
00044 # 渡される場合があり、その場合は ConnectorProfile が優先される。
00045 #
00046 # - input.throughput.profile: enable
00047 # - input.throughput.update_rate: count [n/count]
00048 # - input.throughput.total_bytes: [bytes]
00049 # - input.throughput.total_count: [n]
00050 # - input.throughput.max_size: [bytes]
00051 # - input.throughput.min_size: [bytes]
00052 # - input.throughput.avg_size: [bytes]
00053 # - input.throughput.byte_sec: [bytes/sec]
00054 #
00055 # - output.throughput.profile: enable
00056 # - output.throughput.update_rate: count [n/count]
00057 # - output.throughput.total_bytes: [bytes]
00058 # - output.throughput.total_count:[n]
00059 # - output.throughput.max_size: [bytes]
00060 # - output.throughput.min_size: [bytes]
00061 # - output.throughput.avg_size: [bytes]
00062 # - output.throughput.max_sendtime: [sec]
00063 # - output.throughput.min_sendtime: [sec]
00064 # - output.throughput.avg_sendtime: [sec]
00065 # - output.throughput.byte_sec: [bytes/sec]
00066 #
00067 # dataport.dataflow_type
00068 # dataport.interface_type
00069 # dataport.subscription_type
00070 #
00071 # [buffer]
00072 #
00073 # - buffer.type:
00074 #     利用可能なバッファのタイプ
00075 #     ConnectorProfile の場合は利用するバッファのタイプ
00076 #     無指定の場合はデフォルトの ringbuffer が使用される。
00077 #     ex. ringbuffer, shmbuffer, doublebuffer, etc.
00078 #     正し、Consumer, Publisher のタイプによっては特定のバッファ型を
00079 #     要求するがあるための、その場合は指定は無効となる。
00080 #
00081 # - buffer.length:
00082 #     バッファの長さ
00083 #
00084 # - buffer.write.full_policy:
00085 #     上書きするかどうかのポリシー
00086 #     overwrite (上書き), do_nothing (何もしない), block (ブロックする)
00087 #     block を指定した場合、次の timeout 値を指定すれば、指定時間後
00088 #     書き込み不可能であればタイムアウトする。
00089 #
00090 # - buffer.write.timeout:
00091 #     タイムアウト時間を [sec] で指定する。
00092 #     1 sec -> 1.0, 1 ms -> 0.001, タイムアウトしない -> 0.0
00093 #
00094 # - buffer.read.empty_policy:
00095 #     バッファが空のときの読み出しポリシー
00096 #     last (最後の要素), do_nothing (何もしない), block (ブロックする)
00097 #     block を指定した場合、次の timeout 値を指定すれば、指定時間後
00098 #     読み出し不可能であればタイムアウトする。
00099 #
00100 # - buffer.read.timeout:
00101 #     タイムアウト時間 [sec] で指定する。
00102 #     1sec -> 1.0, 1ms -> 0.001, タイムアウトしない -> 0.0
00103 #
00104 # - その他バッファ毎に固有なオプション
00105 #
00106 #
00107 # [publihser]
00108 #
00109 # - publisher.types:
00110 #      利用可能な Publisher のタイプ
00111 #      new, periodic, flush, etc..
00112 #
00113 # - publisher.push.policy:
00114 #      InPortへデータを送信するポリシー
00115 #      all: バッファにたまっているすべて送信
00116 #      fifo: バッファをFIFOとみなして送信
00117 #      skip: 古いデータから一定数を間引いて送信
00118 #      new: 常に新しいデータのみを送信
00119 #
00120 # - publisher.push.skip_rate:
00121 #      push.policy=skip のときのスキップ率
00122 #      n: n要素毎にひとつ送信
00123 #
00124 # - publisher.periodic.rate:
00125 #
00126 # - publisher.thread.type:
00127 #       Publisher のスレッドのタイプ
00128 # - publisher.thread.measurement.exec_time: yes/no
00129 # - publisher.thread.measurement.exec_count: number
00130 # - publisher.thread.measurement.period_time: yes/no
00131 # - publisher.thread.measurement.period_count: number
00132 #
00133 # [interface]
00134 #
00135 # - interface.types:
00136 #     OutPort interfaceのタイプ
00137 #     ex. corba_cdr, corba_any, raw_tcp などカンマ区切りで指定。何も
00138 #     指定しなければ利用可能なすべてのプロバイダが使用される
00139 #
00140 #
00141 #
00142 #   
00143 # OutPort 側の connect() では以下のシーケンスで処理が行われる。
00144 #
00145 # 1. OutPort に関連する connector 情報の生成およびセット
00146 #
00147 # 2. InPortに関連する connector 情報の取得
00148 #  - ConnectorProfile::properties["dataport.corba_any.inport_ref"]に
00149 #    OutPortAny のオブジェクトリファレンスが設定されている場合、
00150 #    リファレンスを取得してConsumerオブジェクトにセットする。
00151 #    リファレンスがセットされていなければ無視して継続。
00152 #    (OutPortがconnect() 呼び出しのエントリポイントの場合は、
00153 #    InPortのオブジェクトリファレンスはセットされていないはずである。)
00154 # 3. PortBase::connect() をコール
00155 #    Portの接続の基本処理が行われる。
00156 # 4. 上記2.でInPortのリファレンスが取得できなければ、再度InPortに
00157 #    関連する connector 情報を取得する。
00158 #
00159 # 5. ConnectorProfile::properties で与えられた情報から、
00160 #    OutPort側の初期化処理を行う。
00161 #
00162 # - [dataport.interface_type]
00163 # -- CORBA_Any の場合: 
00164 #    InPortAny を通してデータ交換される。
00165 #    ConnectorProfile::properties["dataport.corba_any.inport_ref"]に
00166 #    InPortAny のオブジェクトリファレンスをセットする。
00167 # -- RawTCP の場合: Raw TCP socket を通してデータ交換される。
00168 #    ConnectorProfile::properties["dataport.raw_tcp.server_addr"]
00169 #    にInPort側のサーバアドレスをセットする。
00170 #
00171 # - [dataport.dataflow_type]
00172 # -- Pushの場合: Subscriberを生成する。Subscriberのタイプは、
00173 #    dataport.subscription_type に設定されている。
00174 # -- Pullの場合: InPort側がデータをPull型で取得するため、
00175 #    特に何もする必要が無い。
00176 #
00177 # - [dataport.subscription_type]
00178 # -- Onceの場合: SubscriberOnceを生成する。
00179 # -- Newの場合: SubscriberNewを生成する。
00180 # -- Periodicの場合: SubscriberPeriodicを生成する。
00181 #
00182 # - [dataport.push_interval]
00183 # -- dataport.subscription_type=Periodicの場合周期を設定する。
00184 #
00185 # 6. 上記の処理のうち一つでもエラーであれば、エラーリターンする。
00186 #    正常に処理が行われた場合はRTC::RTC_OKでリターンする。
00187 #
00188 # @since 0.2.0
00189 #
00190 # @else
00191 #
00192 # @class OutPortBase
00193 #
00194 # @brief Output base class.
00195 #
00196 # The base class of OutPort<T> which are implementations of OutPort
00197 #
00198 # Form a kind of Observer pattern with OutPortBase and PublisherBase.
00199 # attach(), detach(), notify() of OutPortBase and
00200 # push() of PublisherBase are methods associated with the Observer pattern.
00201 #
00202 # @since 0.2.0
00203 #
00204 # @endif
00205 #
00206 class OutPortBase(OpenRTM_aist.PortBase,OpenRTM_aist.DataPortStatus):
00207   """
00208   """
00209 
00210   ##
00211   # @if jp
00212   # @brief Provider を削除するための Functor
00213   # @else
00214   # @brief Functor to delete Providers
00215   # @endif
00216   #
00217   class provider_cleanup:
00218     def __init__(self):
00219       self._factory = OpenRTM_aist.OutPortProviderFactory.instance()
00220 
00221     def __call__(self, p):
00222       self._factory.deleteObject(p)
00223 
00224   ##
00225   # @if jp
00226   # @brief Connector を削除するための Functor
00227   # @else
00228   # @brief Functor to delete Connectors
00229   # @endif
00230   #
00231   class connector_cleanup:
00232     def __init__(self):
00233       pass
00234 
00235     def __call__(self, c):
00236       del c
00237 
00238 
00239   ##
00240   # @if jp
00241   # @brief コンストラクタ
00242   #
00243   # コンストラクタ。
00244   #
00245   # @param self
00246   # @param name ポート名
00247   #
00248   # @else
00249   #
00250   # @brief A constructor of OutPortBase class.
00251   #
00252   # Constructor of OutPortBase.
00253   #
00254   # @endif
00255   # OutPortBase::OutPortBase(const char* name, const char* data_type)
00256   def __init__(self, name, data_type):
00257     OpenRTM_aist.PortBase.__init__(self,name)
00258     self._rtcout.RTC_DEBUG("Port name: %s", name)
00259 
00260     self._rtcout.RTC_DEBUG("setting port.port_type: DataOutPort")
00261     self.addProperty("port.port_type", "DataOutPort")
00262 
00263     self._rtcout.RTC_DEBUG("setting dataport.data_type: %s", data_type)
00264     self.addProperty("dataport.data_type", data_type)
00265 
00266     # publisher list
00267     factory = OpenRTM_aist.PublisherFactory.instance()
00268     pubs = OpenRTM_aist.flatten(factory.getIdentifiers())
00269 
00270     # blank characters are deleted for RTSE's bug
00271     pubs = pubs.lstrip()
00272 
00273     self._rtcout.RTC_DEBUG("available subscription_type: %s",  pubs)
00274     self.addProperty("dataport.subscription_type", pubs)
00275 
00276     self._properties    = OpenRTM_aist.Properties()
00277     self._name          = name
00278     self._connectors    = []
00279     self._consumers     = []
00280     self._providerTypes = ""
00281     self._consumerTypes = ""
00282     self._connector_mutex = threading.RLock()
00283 
00284     self._listeners = OpenRTM_aist.ConnectorListeners()
00285     return
00286 
00287 
00288   ##
00289   # @if jp
00290   # @brief デストラクタ
00291   #
00292   # デストラクタ。
00293   # 登録された全ての Publisher を削除する。
00294   #
00295   # @param self
00296   #
00297   # @else
00298   #
00299   # @brief destructor
00300   #
00301   # Destructor
00302   #
00303   # @endif
00304   def __del__(self, PortBase=OpenRTM_aist.PortBase):
00305     self._rtcout.RTC_TRACE("OutPortBase destructor")
00306     # connector のクリーンナップ
00307     OpenRTM_aist.CORBA_SeqUtil.for_each(self._connectors,
00308                                         self.connector_cleanup())
00309     PortBase.__del__(self)
00310     return
00311 
00312 
00313   ##
00314   # @if jp
00315   # @brief プロパティの初期化
00316   #
00317   # OutPortのプロパティを初期化する
00318   #
00319   # @else
00320   #
00321   # @brief Initializing properties
00322   #
00323   # This operation initializes outport's properties
00324   #
00325   # @endif
00326   #
00327   # void init(coil::Properties& prop);
00328   def init(self, prop):
00329     self._rtcout.RTC_TRACE("init()")
00330 
00331     self._properties.mergeProperties(prop)
00332 
00333     self.configure()
00334 
00335     self.initConsumers()
00336     self.initProviders()
00337 
00338     num = [-1]
00339     if not OpenRTM_aist.stringTo(num, self._properties.getProperty("connection_limit","-1")):
00340       self._rtcout.RTC_ERROR("invalid connection_limit value: %s",
00341                              self._properties.getProperty("connection_limit"))
00342 
00343     self.setConnectionLimit(num[0])
00344     return
00345 
00346   ##
00347   # @if jp
00348   #
00349   # @brief データ書き込み
00350   #
00351   # ポートへデータを書き込む。
00352   # バインドされた変数に設定された値をポートに書き込む。
00353   #
00354   # @return 書き込み処理結果(書き込み成功:true、書き込み失敗:false)
00355   #
00356   # @else
00357   #
00358   # @brief Write data
00359   #
00360   # Write data to the port.
00361   # Write the value, which was set to the bound variable, to the port.
00362   #
00363   # @return Writing result (Successful:true, Failed:false)
00364   #
00365   # @endif
00366   #
00367   # virtual bool write() = 0;
00368   def write(self):
00369     pass
00370 
00371 
00372   ##
00373   # @if jp
00374   #
00375   # @brief [CORBA interface] Port の接続を行う
00376   #
00377   # 与えられた ConnectoionProfile の情報に基づき、Port間の接続を確立
00378   # する。この関数は主にアプリケーションプログラムやツールから呼び出
00379   # すことを前提としている。
00380   # 
00381   # @param connector_profile ConnectorProfile
00382   # @return ReturnCode_t 型のリターンコード
00383   #
00384   # @else
00385   #
00386   # @brief [CORBA interface] Connect the Port
00387   #
00388   # This operation establishes connection according to the given
00389   # ConnectionProfile inforamtion. This function is premised on
00390   # calling from mainly application program or tools.
00391   #
00392   # @param connector_profile The ConnectorProfile.
00393   # @return ReturnCode_t The return code of ReturnCode_t type.
00394   #
00395   # @endif
00396   #
00397   def connect(self, connector_profile):
00398     self._rtcout.RTC_TRACE("OutPortBase.connect()")
00399         
00400     if OpenRTM_aist.NVUtil.find_index(connector_profile.properties,
00401                                       "dataport.serializer.cdr.endian") is -1:
00402       self._rtcout.RTC_TRACE("ConnectorProfile dataport.serializer.cdr.endian set.")
00403       connector_profile.properties.append(OpenRTM_aist.NVUtil.newNV("dataport.serializer.cdr.endian","little,big"))
00404 
00405     return OpenRTM_aist.PortBase.connect(self, connector_profile)
00406         
00407 
00408   ##
00409   # @if jp
00410   # @brief プロパティを取得する
00411   #
00412   # OutPortのプロパティを取得する。
00413   #
00414   # @return プロパティ
00415   #
00416   # @else
00417   #
00418   # @brief Get properties
00419   #
00420   # Getting properties of this OutPort
00421   #
00422   # @return OutPort's properties
00423   #
00424   # @endif
00425   #
00426   # coil::Properties& OutPortBase::properties()
00427   def properties(self):
00428     self._rtcout.RTC_TRACE("properties()")
00429     return self._properties
00430 
00431 
00432   ##
00433   # @if jp
00434   # @brief Connector を取得
00435   # @else
00436   # @brief Connector list
00437   # @endif
00438   #
00439   # const std::vector<OutPortConnector*>& OutPortBase::connectors()
00440   def connectors(self):
00441     self._rtcout.RTC_TRACE("connectors(): size = %d", len(self._connectors))
00442     return self._connectors
00443 
00444 
00445   ##
00446   # @if jp
00447   # @brief ConnectorProfile を取得
00448   # @else
00449   # @brief ConnectorProfile list
00450   # @endif
00451   #
00452   # ConnectorBase::ConnectorInfoList OutPortBase::getConnectorProfiles()
00453   def getConnectorProfiles(self):
00454     self._rtcout.RTC_TRACE("getConnectorProfiles(): size = %d", len(self._connectors))
00455     profs = []
00456     for con in self._connectors:
00457       profs.append(con.profile())
00458 
00459     return profs
00460 
00461 
00462   ##
00463   # @if jp
00464   # @brief ConnectorId を取得
00465   # @else
00466   # @brief ConnectorId list
00467   # @endif
00468   #
00469   # coil::vstring OutPortBase::getConnectorIds()
00470   def getConnectorIds(self):
00471     ids = []
00472 
00473     for con in self._connectors:
00474       ids.append(con.id())
00475 
00476     self._rtcout.RTC_TRACE("getConnectorIds(): %s", OpenRTM_aist.flatten(ids))
00477     return ids
00478 
00479 
00480   ##
00481   # @if jp
00482   # @brief Connectorの名前を取得
00483   # @else
00484   # @brief Connector name list
00485   # @endif
00486   #
00487   # coil::vstring OutPortBase::getConnectorNames()
00488   def getConnectorNames(self):
00489     names = []
00490     for con in self._connectors:
00491       names.append(con.name())
00492 
00493     self._rtcout.RTC_TRACE("getConnectorNames(): %s", OpenRTM_aist.flatten(names))
00494     return names
00495 
00496 
00497   ##
00498   # @if jp
00499   # @brief ConnectorProfileをIDで取得
00500   #
00501   # 現在所有しているコネクタをIDで取得する。
00502   #
00503   # @param id Connector ID
00504   # @return コネクタへのポインタ
00505   #
00506   # @else
00507   #
00508   # @brief Getting ConnectorProfile by ID
00509   #
00510   # This operation returns Connector specified by ID.
00511   #
00512   # @param id Connector ID
00513   # @return A pointer to connector
00514   #
00515   # @endif
00516   #
00517   # OutPortConnector* getConnectorById(const char* id);
00518   def getConnectorById(self, id):
00519     self._rtcout.RTC_TRACE("getConnectorById(id = %s)", id)
00520 
00521     for (i,con) in enumerate(self._connectors):
00522       if id == con.id():
00523         return self._connectors[i]
00524 
00525     self._rtcout.RTC_WARN("ConnectorProfile with the id(%s) not found.", id)
00526     return 0
00527 
00528   ##
00529   # @if jp
00530   # @brief ConnectorProfileを名前で取得
00531   #
00532   # 現在所有しているコネクタを名前で取得する。
00533   #
00534   # @param name Connector name
00535   # @return コネクタへのポインタ
00536   #
00537   # @else
00538   #
00539   # @brief Getting Connector by name
00540   #
00541   # This operation returns Connector specified by name.
00542   #
00543   # @param id Connector ID
00544   # @return A pointer to connector
00545   #
00546   # @endif
00547   #
00548   # OutPortConnector* getConnectorByName(const char* name);
00549   def getConnectorByName(self, name):
00550     self._rtcout.RTC_TRACE("getConnectorByName(name = %s)", name)
00551     
00552     for (i,con) in enumerate(self._connectors):
00553       if name == con.name():
00554         return self._connectors[i]
00555 
00556     self._rtcout.RTC_WARN("ConnectorProfile with the name(%s) not found.", name)
00557     return 0
00558 
00559 
00560   ##
00561   # @if jp
00562   # @brief ConnectorProfileをIDで取得
00563   # @else
00564   # @brief Getting ConnectorProfile by name
00565   # @endif
00566   #
00567   # bool OutPortBase::getConnectorProfileById(const char* id,
00568   #                                           ConnectorInfo& prof)
00569   def getConnectorProfileById(self, id, prof):
00570     self._rtcout.RTC_TRACE("getConnectorProfileById(id = %s)", id)
00571 
00572     conn = self.getConnectorById(id)
00573 
00574     if not conn:
00575       return False
00576 
00577     prof[0] = conn.profile()
00578     return True
00579 
00580 
00581   ##
00582   # @if jp
00583   # @brief ConnectorProfileを名前で取得
00584   # @else
00585   # @brief Getting ConnectorProfile by name
00586   # @endif
00587   #
00588   # bool OutPortBase::getConnectorProfileByName(const char* name,
00589   #                                             ConnectorInfo& prof)
00590   def getConnectorProfileByName(self, name, prof):
00591     self._rtcout.RTC_TRACE("getConnectorProfileByName(name = %s)", name)
00592 
00593     conn = self.getConnectorByName(name)
00594 
00595     if not conn:
00596       return False
00597 
00598     prof[0] = conn.profile()
00599     return True
00600 
00601 
00602   ##
00603   # @if jp
00604   # @brief OutPortを activates する
00605   # @else
00606   # @brief Activate all Port interfaces
00607   # @endif
00608   #
00609   # void OutPortBase::activateInterfaces()
00610   def activateInterfaces(self):
00611     self._rtcout.RTC_TRACE("activateInterfaces()")
00612     for con in self._connectors:
00613       con.activate()
00614 
00615   
00616   ##
00617   # @if jp
00618   # @brief 全ての Port のインターフェースを deactivates する
00619   # @else
00620   # @brief Deactivate all Port interfaces
00621   # @endif
00622   #
00623   # void OutPortBase::deactivateInterfaces()
00624   def deactivateInterfaces(self):
00625     self._rtcout.RTC_TRACE("deactivateInterfaces()")
00626     for con in self._connectors:
00627       con.deactivate()
00628   
00629 
00630   ##
00631   # @if jp
00632   # @brief ConnectorDataListener リスナを追加する
00633   #
00634   # バッファ書き込みまたは読み出しイベントに関連する各種リスナを設定する。
00635   #
00636   # 設定できるリスナのタイプとコールバックイベントは以下の通り
00637   #
00638   # - ON_BUFFER_WRITE:          バッファ書き込み時
00639   # - ON_BUFFER_FULL:           バッファフル時
00640   # - ON_BUFFER_WRITE_TIMEOUT:  バッファ書き込みタイムアウト時
00641   # - ON_BUFFER_OVERWRITE:      バッファ上書き時
00642   # - ON_BUFFER_READ:           バッファ読み出し時
00643   # - ON_SEND:                  InProtへの送信時
00644   # - ON_RECEIVED:              InProtへの送信完了時
00645   # - ON_SEND_ERTIMEOUT:        OutPort側タイムアウト時
00646   # - ON_SEND_ERERROR:          OutPort側エラー時
00647   # - ON_RECEIVER_FULL:         InProt側バッファフル時
00648   # - ON_RECEIVER_TIMEOUT:      InProt側バッファタイムアウト時
00649   # - ON_RECEIVER_ERROR:        InProt側エラー時
00650   #
00651   # リスナは ConnectorDataListener を継承し、以下のシグニチャを持つ
00652   # operator() を実装している必要がある。
00653   #
00654   # ConnectorDataListener::
00655   #         operator()(const ConnectorProfile&, const cdrStream&)
00656   #
00657   # デフォルトでは、この関数に与えたリスナオブジェクトの所有権は
00658   # OutPortに移り、OutPort解体時もしくは、
00659   # removeConnectorDataListener() により削除時に自動的に解体される。
00660   # リスナオブジェクトの所有権を呼び出し側で維持したい場合は、第3引
00661   # 数に false を指定し、自動的な解体を抑制することができる。
00662   #
00663   # @param listener_type リスナタイプ
00664   # @param listener リスナオブジェクトへのポインタ
00665   # @param autoclean リスナオブジェクトの自動的解体を行うかどうかのフラグ
00666   #
00667   # @else
00668   # @brief Adding BufferDataListener type listener
00669   #
00670   # This operation adds certain listeners related to buffer writing and
00671   # reading events.
00672   # The following listener types are available.
00673   #
00674   # - ON_BUFFER_WRITE:          At the time of buffer write
00675   # - ON_BUFFER_FULL:           At the time of buffer full
00676   # - ON_BUFFER_WRITE_TIMEOUT:  At the time of buffer write timeout
00677   # - ON_BUFFER_OVERWRITE:      At the time of buffer overwrite
00678   # - ON_BUFFER_READ:           At the time of buffer read
00679   # - ON_SEND:                  At the time of sending to InPort
00680   # - ON_RECEIVED:              At the time of finishing sending to InPort
00681   # - ON_SENDER_TIMEOUT:        At the time of timeout of OutPort
00682   # - ON_SENDER_ERROR:          At the time of error of OutPort
00683   # - ON_RECEIVER_FULL:         At the time of bufferfull of InPort
00684   # - ON_RECEIVER_TIMEOUT:      At the time of timeout of InPort
00685   # - ON_RECEIVER_ERROR:        At the time of error of InPort
00686   #
00687   # Listeners should have the following function operator().
00688   #
00689   # ConnectorDataListener::
00690   #         operator()(const ConnectorProfile&, const cdrStream&)
00691   #
00692   # The ownership of the given listener object is transferred to
00693   # this OutPort object in default.  The given listener object will
00694   # be destroied automatically in the OutPort's dtor or if the
00695   # listener is deleted by removeConnectorDataListener() function.
00696   # If you want to keep ownership of the listener object, give
00697   # "false" value to 3rd argument to inhibit automatic destruction.
00698   #
00699   # @param listener_type A listener type
00700   # @param listener A pointer to a listener object
00701   # @param autoclean A flag for automatic listener destruction
00702   #
00703   # @endif
00704   #
00705   # void addConnectorDataListener(ConnectorDataListenerType listener_type,
00706   #                               ConnectorDataListener* listener,
00707   #                               bool autoclean = true);
00708   def addConnectorDataListener(self, listener_type, listener, autoclean = True):
00709     self._rtcout.RTC_TRACE("addConnectorDataListener()")
00710     if listener_type < OpenRTM_aist.ConnectorDataListenerType.CONNECTOR_DATA_LISTENER_NUM:
00711       self._rtcout.RTC_TRACE("addConnectorDataListener(%s)",
00712                              OpenRTM_aist.ConnectorDataListener.toString(listener_type))
00713       self._listeners.connectorData_[listener_type].addListener(listener, autoclean)
00714       return
00715 
00716     self._rtcout.RTC_ERROR("addConnectorDataListener(): Unknown Listener Type")
00717     return
00718 
00719 
00720   ##
00721   # @if jp
00722   # @brief ConnectorDataListener リスナを削除する
00723   #
00724   # 設定した各種リスナを削除する。
00725   # 
00726   # @param listener_type リスナタイプ
00727   # @param listener リスナオブジェクトへのポインタ
00728   #
00729   # @else
00730   # @brief Removing BufferDataListener type listener
00731   #
00732   # This operation removes a specified listener.
00733   #     
00734   # @param listener_type A listener type
00735   # @param listener A pointer to a listener object
00736   #
00737   # @endif
00738   #
00739   # void removeConnectorDataListener(ConnectorDataListenerType listener_type,
00740   #                                  ConnectorDataListener* listener);
00741   def removeConnectorDataListener(self, listener_type, listener):
00742     self._rtcout.RTC_TRACE("removeConnectorDataListener()")
00743 
00744     if listener_type < OpenRTM_aist.ConnectorDataListenerType.CONNECTOR_DATA_LISTENER_NUM:
00745       self._rtcout.RTC_TRACE("removeConnectorDataListener(%s)",
00746                              OpenRTM_aist.ConnectorDataListener.toString(listener_type))
00747       self._listeners.connectorData_[listener_type].removeListener(listener)
00748       return
00749 
00750     self._rtcout.RTC_ERROR("removeConnectorDataListener(): Unknown Listener Type")
00751     return
00752     
00753 
00754   ##
00755   # @if jp
00756   # @brief ConnectorListener リスナを追加する
00757   #
00758   # バッファ書き込みまたは読み出しイベントに関連する各種リスナを設定する。
00759   #
00760   # 設定できるリスナのタイプは
00761   #
00762   # - ON_BUFFER_EMPTY:       バッファが空の場合
00763   # - ON_BUFFER_READTIMEOUT: バッファが空でタイムアウトした場合
00764   #
00765   # リスナは以下のシグニチャを持つ operator() を実装している必要がある。
00766   #
00767   # ConnectorListener::operator()(const ConnectorProfile&)
00768   #
00769   # デフォルトでは、この関数に与えたリスナオブジェクトの所有権は
00770   # OutPortに移り、OutPort解体時もしくは、
00771   # removeConnectorListener() により削除時に自動的に解体される。
00772   # リスナオブジェクトの所有権を呼び出し側で維持したい場合は、第3引
00773   # 数に false を指定し、自動的な解体を抑制することができる。
00774   #
00775   # @param listener_type リスナタイプ
00776   # @param listener リスナオブジェクトへのポインタ
00777   # @param autoclean リスナオブジェクトの自動的解体を行うかどうかのフラグ
00778   #
00779   # @else
00780   # @brief Adding ConnectorListener type listener
00781   #
00782   # This operation adds certain listeners related to buffer writing and
00783   # reading events.
00784   # The following listener types are available.
00785   #
00786   # - ON_BUFFER_EMPTY:       At the time of buffer empty
00787   # - ON_BUFFER_READTIMEOUT: At the time of buffer read timeout
00788   #
00789   # Listeners should have the following function operator().
00790   #
00791   # ConnectorListener::operator()(const ConnectorProfile&)
00792   #  
00793   # The ownership of the given listener object is transferred to
00794   # this OutPort object in default.  The given listener object will
00795   # be destroied automatically in the OutPort's dtor or if the
00796   # listener is deleted by removeConnectorListener() function.
00797   # If you want to keep ownership of the listener object, give
00798   # "false" value to 3rd argument to inhibit automatic destruction.
00799   #
00800   # @param listener_type A listener type
00801   # @param listener A pointer to a listener object
00802   # @param autoclean A flag for automatic listener destruction
00803   #
00804   # @endif
00805   #
00806   # void addConnectorListener(ConnectorListenerType callback_type,
00807   #                           ConnectorListener* listener,
00808   #                           bool autoclean = true);
00809   def addConnectorListener(self, callback_type, listener, autoclean = True):
00810     self._rtcout.RTC_TRACE("addConnectorListener()")
00811 
00812     if callback_type < OpenRTM_aist.ConnectorListenerType.CONNECTOR_LISTENER_NUM:
00813       self._rtcout.RTC_TRACE("addConnectorListener(%s)",
00814                              OpenRTM_aist.ConnectorListener.toString(callback_type))
00815       self._listeners.connector_[callback_type].addListener(listener, autoclean)
00816       return
00817     self._rtcout.RTC_ERROR("addConnectorListener(): Unknown Listener Type")
00818     return
00819 
00820 
00821   ##
00822   # @if jp
00823   # @brief ConnectorDataListener リスナを削除する
00824   #
00825   # 設定した各種リスナを削除する。
00826   # 
00827   # @param listener_type リスナタイプ
00828   # @param listener リスナオブジェクトへのポインタ
00829   #
00830   # @else
00831   # @brief Removing BufferDataListener type listener
00832   #
00833   # This operation removes a specified listener.
00834   #     
00835   # @param listener_type A listener type
00836   # @param listener A pointer to a listener object
00837   #
00838   # @endif
00839   #
00840   # void removeConnectorListener(ConnectorListenerType callback_type,
00841   #                              ConnectorListener* listener);
00842   def removeConnectorListener(self, callback_type, listener):
00843     self._rtcout.RTC_TRACE("removeConnectorListener()")
00844         
00845     if callback_type < OpenRTM_aist.ConnectorListenerType.CONNECTOR_LISTENER_NUM:
00846       self._rtcout.RTC_TRACE("removeConnectorListener(%s)",
00847                              OpenRTM_aist.ConnectorListener.toString(callback_type))
00848       self._listeners.connector_[callback_type].removeListener(listener)
00849       return
00850     self._rtcout.RTC_ERROR("removeConnectorListener(): Unknown Listener Type")
00851     return
00852 
00853 
00854   ##
00855   # @if jp
00856   # @brief OutPortの設定を行う
00857   # @else
00858   # @brief Configureing outport
00859   # @endif
00860   #
00861   #void OutPortBase::configure()
00862   def configure(self):
00863     pass
00864 
00865 
00866   ##
00867   # @if jp
00868   # @brief Interface情報を公開する
00869   # @else
00870   # @brief Publish interface information
00871   # @endif
00872   #
00873   # ReturnCode_t OutPortBase::publishInterfaces(ConnectorProfile& cprof)
00874   def publishInterfaces(self, cprof):
00875     self._rtcout.RTC_TRACE("publishInterfaces()")
00876     
00877     retval = self._publishInterfaces()
00878     if retval != RTC.RTC_OK:
00879       return retval
00880 
00881     # prop: [port.outport].
00882     prop = copy.deepcopy(self._properties)
00883 
00884     conn_prop = OpenRTM_aist.Properties()
00885 
00886     OpenRTM_aist.NVUtil.copyToProperties(conn_prop, cprof.properties)
00887     prop.mergeProperties(conn_prop.getNode("dataport")) # marge ConnectorProfile
00888 
00889     """
00890     #  marge ConnectorProfile for buffer property.
00891     #  e.g.
00892     #      prof[buffer.write.full_policy]
00893     #           << cprof[dataport.outport.buffer.write.full_policy]
00894     #    
00895     """
00896     prop.mergeProperties(conn_prop.getNode("dataport.outport"))
00897 
00898 
00899     #
00900     # ここで, ConnectorProfile からの properties がマージされたため、
00901     # prop["dataflow_type"]: データフロータイプ
00902     # prop["interface_type"]: インターフェースタイプ
00903     # などがアクセス可能になる。
00904     dflow_type = OpenRTM_aist.normalize([prop.getProperty("dataflow_type")])
00905 
00906     if dflow_type == "push":
00907       self._rtcout.RTC_PARANOID("dataflow_type = push .... do nothing")
00908       return RTC.RTC_OK
00909 
00910     elif dflow_type == "pull":
00911       self._rtcout.RTC_PARANOID("dataflow_type = pull .... create PullConnector")
00912 
00913       provider = self.createProvider(cprof, prop)
00914       if not provider:
00915         return RTC.BAD_PARAMETER
00916         
00917       # create InPortPushConnector
00918       connector = self.createConnector(cprof, prop, provider_ = provider)
00919       if not connector:
00920         return RTC.RTC_ERROR
00921 
00922       # connector set
00923       provider.setConnector(connector)
00924 
00925       self._rtcout.RTC_DEBUG("publishInterface() successfully finished.")
00926       return RTC.RTC_OK
00927 
00928     self._rtcout.RTC_ERROR("unsupported dataflow_type")
00929 
00930     return RTC.BAD_PARAMETER
00931 
00932 
00933   ##
00934   # @if jp
00935   # @brief Interface情報を取得する
00936   # @else
00937   # @brief Subscribe interface
00938   # @endif
00939   #
00940   # ReturnCode_t OutPortBase::subscribeInterfaces(const ConnectorProfile& cprof)
00941   def subscribeInterfaces(self, cprof):
00942     self._rtcout.RTC_TRACE("subscribeInterfaces()")
00943 
00944     # prop: [port.outport].
00945     prop = copy.deepcopy(self._properties)
00946 
00947     conn_prop = OpenRTM_aist.Properties()
00948     OpenRTM_aist.NVUtil.copyToProperties(conn_prop, cprof.properties)
00949     prop.mergeProperties(conn_prop.getNode("dataport")) # marge ConnectorProfile
00950     """
00951     #  marge ConnectorProfile for buffer property.
00952     #   e.g.
00953     #     prof[buffer.write.full_policy]
00954     #          << cprof[dataport.outport.buffer.write.full_policy]
00955     """
00956     prop.mergeProperties(conn_prop.getNode("dataport.outport"))
00957 
00958     #
00959     # ここで, ConnectorProfile からの properties がマージされたため、
00960     # prop["dataflow_type"]: データフロータイプ
00961     # prop["interface_type"]: インターフェースタイプ
00962     # などがアクセス可能になる。
00963     #
00964     dflow_type = OpenRTM_aist.normalize([prop.getProperty("dataflow_type")])
00965     
00966     profile = OpenRTM_aist.ConnectorInfo(cprof.name,
00967                                          cprof.connector_id,
00968                                          OpenRTM_aist.CORBA_SeqUtil.refToVstring(cprof.ports),
00969                                          prop)
00970     if dflow_type == "push":
00971       self._rtcout.RTC_PARANOID("dataflow_type = push .... create PushConnector")
00972 
00973       # interface
00974       consumer = self.createConsumer(cprof, prop)
00975       if not consumer:
00976         return RTC.BAD_PARAMETER
00977 
00978       # create OutPortPushConnector
00979       connector = self.createConnector(cprof, prop, consumer_ = consumer)
00980       if not connector:
00981         return RTC.RTC_ERROR
00982 
00983       ret = connector.setConnectorInfo(profile)
00984 
00985       if ret == RTC.RTC_OK:
00986         self._rtcout.RTC_DEBUG("subscribeInterfaces() successfully finished.")
00987 
00988       return ret
00989 
00990     elif dflow_type == "pull":
00991       self._rtcout.RTC_PARANOID("dataflow_type = pull.")
00992 
00993       conn = self.getConnectorById(cprof.connector_id)
00994       if not conn:
00995         self._rtcout.RTC_ERROR("specified connector not found: %s",
00996                                cprof.connector_id)
00997         return RTC.RTC_ERROR
00998 
00999       ret = conn.setConnectorInfo(profile)
01000 
01001       if ret == RTC.RTC_OK:
01002         self._rtcout.RTC_DEBUG("subscribeInterfaces() successfully finished.")
01003 
01004       return ret
01005 
01006     self._rtcout.RTC_ERROR("unsupported dataflow_type")
01007     return RTC.BAD_PARAMETER
01008 
01009 
01010   ##
01011   # @if jp
01012   # @brief 登録されているInterface情報を解除する
01013   # @else
01014   # @brief Unsubscribe interface
01015   # @endif
01016   #
01017   # void
01018   # OutPortBase::unsubscribeInterfaces(const ConnectorProfile& connector_profile)
01019   def unsubscribeInterfaces(self, connector_profile):
01020     self._rtcout.RTC_TRACE("unsubscribeInterfaces()")
01021 
01022     id = connector_profile.connector_id
01023     self._rtcout.RTC_PARANOID("connector_id: %s", id)
01024 
01025     len_ = len(self._connectors)
01026     for i in range(len_):
01027       idx = (len_ - 1) - i
01028       if id == self._connectors[idx].id():
01029         # Connector's dtor must call disconnect()
01030         self._connectors[idx].deactivate()
01031         self._connectors[idx].disconnect()
01032         del self._connectors[idx]
01033         self._rtcout.RTC_TRACE("delete connector: %s", id)
01034         return
01035 
01036     self._rtcout.RTC_ERROR("specified connector not found: %s", id)
01037     return
01038 
01039 
01040   ##
01041   # @if jp
01042   # @brief OutPort provider の初期化
01043   # @else
01044   # @brief OutPort provider initialization
01045   # @endif
01046   #
01047   # void OutPortBase::initProviders()
01048   def initProviders(self):
01049     self._rtcout.RTC_TRACE("initProviders()")
01050 
01051     # create OutPort providers
01052     factory = OpenRTM_aist.OutPortProviderFactory.instance()
01053     provider_types = factory.getIdentifiers()
01054     self._rtcout.RTC_PARANOID("available OutPortProviders: %s",
01055                               OpenRTM_aist.flatten(provider_types))
01056 
01057     if self._properties.hasKey("provider_types") and \
01058           OpenRTM_aist.normalize(self._properties.getProperty("provider_types")) != "all":
01059       self._rtcout.RTC_DEBUG("allowed providers: %s",
01060                              self._properties.getProperty("provider_types"))
01061 
01062       temp_types = provider_types
01063       provider_types = []
01064       active_types = OpenRTM_aist.split(self._properties.getProperty("provider_types"), ",")
01065 
01066       temp_types.sort()
01067       active_types.sort()
01068 
01069       set_ptypes = set(temp_types).intersection(set(active_types))
01070       provider_types = provider_types + list(set_ptypes)
01071 
01072     # OutPortProvider supports "pull" dataflow type
01073     if len(provider_types) > 0:
01074       self._rtcout.RTC_DEBUG("dataflow_type pull is supported")
01075       self.appendProperty("dataport.dataflow_type", "pull")
01076       self.appendProperty("dataport.interface_type",
01077                           OpenRTM_aist.flatten(provider_types))
01078 
01079     self._providerTypes = provider_types
01080 
01081 
01082   ##
01083   # @if jp
01084   # @brief InPort consumer の初期化
01085   # @else
01086   # @brief InPort consumer initialization
01087   # @endif
01088   #
01089   # void OutPortBase::initConsumers()
01090   def initConsumers(self):
01091     self._rtcout.RTC_TRACE("initConsumers()")
01092 
01093     # create InPort consumers
01094     factory = OpenRTM_aist.InPortConsumerFactory.instance()
01095     consumer_types = factory.getIdentifiers()
01096     self._rtcout.RTC_PARANOID("available InPortConsumer: %s",
01097                               OpenRTM_aist.flatten(consumer_types))
01098 
01099     if self._properties.hasKey("consumer_types") and \
01100           OpenRTM_aist.normalize(self._properties.getProperty("consumer_types")) != "all":
01101       self._rtcout.RTC_DEBUG("allowed consumers: %s",
01102                              self._properties.getProperty("consumer_types"))
01103 
01104       temp_types = consumer_types
01105       consumer_types = []
01106       active_types = OpenRTM_aist.split(self._properties.getProperty("consumer_types"), ",")
01107 
01108       temp_types.sort()
01109       active_types.sort()
01110 
01111       set_ctypes = set(temp_types).intersection(set(active_types))
01112       consumer_types = consumer_types + list(set_ctypes)
01113 
01114     # InPortConsumer supports "push" dataflow type
01115     if len(consumer_types) > 0:
01116       self._rtcout.RTC_PARANOID("dataflow_type push is supported")
01117       self.appendProperty("dataport.dataflow_type", "push")
01118       self.appendProperty("dataport.interface_type",
01119                           OpenRTM_aist.flatten(consumer_types))
01120     
01121     self._consumerTypes = consumer_types
01122 
01123 
01124   ##
01125   # @if jp
01126   # @brief OutPort provider の生成
01127   # @else
01128   # @brief OutPort provider creation
01129   # @endif
01130   #
01131   # OutPortProvider*
01132   # OutPortBase::createProvider(ConnectorProfile& cprof, coil::Properties& prop)
01133   def createProvider(self, cprof, prop):
01134     if prop.getProperty("interface_type") and \
01135           not OpenRTM_aist.includes(self._providerTypes, prop.getProperty("interface_type")):
01136       self._rtcout.RTC_ERROR("no provider found")
01137       self._rtcout.RTC_DEBUG("interface_type:  %s", prop.getProperty("interface_type"))
01138       self._rtcout.RTC_DEBUG("interface_types: %s",
01139                              OpenRTM_aist.flatten(self._providerTypes))
01140       return 0
01141 
01142     self._rtcout.RTC_DEBUG("interface_type: %s", prop.getProperty("interface_type"))
01143     provider = OpenRTM_aist.OutPortProviderFactory.instance().createObject(prop.getProperty("interface_type"))
01144     
01145     if provider != 0:
01146       self._rtcout.RTC_DEBUG("provider created")
01147       provider.init(prop.getNode("provider"))
01148 
01149       if not provider.publishInterface(cprof.properties):
01150         self._rtcout.RTC_ERROR("publishing interface information error")
01151         OpenRTM_aist.OutPortProviderFactory.instance().deleteObject(provider)
01152         return 0
01153 
01154       return provider
01155 
01156     self._rtcout.RTC_ERROR("provider creation failed")
01157     return 0
01158 
01159 
01160   ##
01161   # @if jp
01162   # @brief InPort consumer の生成
01163   # @else
01164   # @brief InPort consumer creation
01165   # @endif
01166   #
01167   # InPortConsumer* OutPortBase::createConsumer(const ConnectorProfile& cprof,
01168   #                                             coil::Properties& prop)
01169   def createConsumer(self, cprof, prop):
01170     if prop.getProperty("interface_type") and \
01171           not self._consumerTypes.count(prop.getProperty("interface_type")):
01172       self._rtcout.RTC_ERROR("no consumer found")
01173       self._rtcout.RTC_DEBUG("interface_type:  %s", prop.getProperty("interface_type"))
01174       self._rtcout.RTC_DEBUG("interface_types: %s",
01175                              OpenRTM_aist.flatten(self._consumerTypes))
01176       return 0
01177     
01178     self._rtcout.RTC_DEBUG("interface_type: %s", prop.getProperty("interface_type"))
01179     consumer = OpenRTM_aist.InPortConsumerFactory.instance().createObject(prop.getProperty("interface_type"))
01180     
01181     if consumer != 0:
01182       self._rtcout.RTC_DEBUG("consumer created")
01183       consumer.init(prop.getNode("consumer"))
01184 
01185       if not consumer.subscribeInterface(cprof.properties):
01186         self._rtcout.RTC_ERROR("interface subscription failed.")
01187         OpenRTM_aist.InPortConsumerFactory.instance().deleteObject(consumer)
01188         return 0
01189 
01190       return consumer
01191 
01192     self._rtcout.RTC_ERROR("consumer creation failed")
01193     return 0
01194 
01195 
01196   ##
01197   # @if jp
01198   # @brief OutPortPushConnector の生成
01199   # @else
01200   # @brief OutPortPushConnector creation
01201   # @endif
01202   #
01203   # OutPortConnector*
01204   # OutPortBase::createConnector(const ConnectorProfile& cprof,
01205   #                              coil::Properties& prop,
01206   #                              InPortConsumer* consumer)
01207   def createConnector(self, cprof, prop, provider_ = None, consumer_ = None):
01208     profile = OpenRTM_aist.ConnectorInfo(cprof.name,
01209                                          cprof.connector_id,
01210                                          OpenRTM_aist.CORBA_SeqUtil.refToVstring(cprof.ports),
01211                                          prop)
01212 
01213     connector = None
01214     try:
01215 
01216       if consumer_ is not None:
01217         connector = OpenRTM_aist.OutPortPushConnector(profile, consumer_, self._listeners)
01218       elif provider_ is not None:
01219         connector = OpenRTM_aist.OutPortPullConnector(profile, provider_, self._listeners)
01220 
01221       else:
01222         self._rtcout.RTC_ERROR("provider or consumer is not passed. returned 0;")
01223         return 0
01224 
01225       if connector is None:
01226         self._rtcout.RTC_ERROR("OutPortConnector creation failed")
01227         return 0
01228 
01229       if consumer_ is not None:
01230         self._rtcout.RTC_TRACE("OutPortPushConnector created")
01231       elif provider_ is not None:
01232         self._rtcout.RTC_TRACE("OutPortPullConnector created")
01233 
01234       self._connectors.append(connector)
01235       self._rtcout.RTC_PARANOID("connector push backed: %d", len(self._connectors))
01236       return connector
01237 
01238     except:
01239       self._rtcout.RTC_ERROR("Exeption: OutPortPushConnector creation failed")
01240       self._rtcout.RTC_ERROR(OpenRTM_aist.Logger.print_exception())
01241       return 0
01242 
01243 
01244     self._rtcout.RTC_FATAL("never comes here: createConnector()")
01245     return 0


openrtm_aist_python
Author(s): Shinji Kurihara
autogenerated on Thu Aug 27 2015 14:17:28