00001 #!/usr/bin/env python 00002 # -*- coding: euc-jp -*- 00003 00004 00005 ## 00006 # @file OutPortPushConnector.py 00007 # @brief Push type connector class 00008 # @date $Date$ 00009 # @author Noriaki Ando <n-ando@aist.go.jp> and Shinji Kurihara 00010 # 00011 # Copyright (C) 2009 00012 # Noriaki Ando 00013 # Task-intelligence Research Group, 00014 # Intelligent Systems Research Institute, 00015 # National Institute of 00016 # Advanced Industrial Science and Technology (AIST), Japan 00017 # All rights reserved. 00018 # 00019 00020 from omniORB import * 00021 from omniORB import any 00022 00023 import OpenRTM_aist 00024 00025 00026 ## 00027 # @if jp 00028 # @class OutPortPushConnector 00029 # @brief OutPortPushConnector クラス 00030 # 00031 # OutPort の push 型データフローのための Connector クラス。このオブ 00032 # ジェクトは、接続時に dataflow_type に push が指定された場合、 00033 # OutPort によって生成・所有され、InPortPushConnector と対になって、 00034 # データポートの push 型のデータフローを実現する。一つの接続に対して、 00035 # 一つのデータストリームを提供する唯一の Connector が対応する。 00036 # Connector は 接続時に生成される UUID 形式の ID により区別される。 00037 # 00038 # OutPortPushConnector は以下の三つのオブジェクトを所有し管理する。 00039 # 00040 # - InPortConsumer 00041 # - Buffer 00042 # - Publisher 00043 # 00044 # OutPort に書き込まれたデータは OutPortPushConnector::write() に渡 00045 # され、Connector は Publisher にデータを書き込む。Publisher はその 00046 # 特性に従ってデータを Buffer から取得し InPortConsumer に対して 00047 # push することで InPort にデータが転送される。 00048 # 00049 # @since 1.0.0 00050 # 00051 # @else 00052 # @class OutPortPushConnector 00053 # @brief OutPortPushConnector class 00054 # 00055 # Connector class of OutPort for push type dataflow. When "push" 00056 # is specified as dataflow_type at the time of establishing 00057 # connection, this object is generated and owned by the OutPort. 00058 # This connector and InPortPushConnector make a pair and realize 00059 # push type dataflow of data ports. One connector corresponds to 00060 # one connection which provides a data stream. Connector is 00061 # distinguished by ID of the UUID that is generated at establishing 00062 # connection. 00063 # 00064 # OutPortPushConnector owns and manages the following objects. 00065 # 00066 # - InPortConsumer 00067 # - Buffer 00068 # - Publisher 00069 # 00070 # @since 1.0.0 00071 # 00072 # Data written into the OutPort is passed to 00073 # OutPortPushConnector::write(), and the connector writes into the 00074 # publisher. The publisher gets data from the buffer based on the 00075 # policy and it is transferred to InPort by pushing it into the 00076 # InPortConsumer. 00077 # 00078 # @endif 00079 # 00080 class OutPortPushConnector(OpenRTM_aist.OutPortConnector): 00081 """ 00082 """ 00083 00084 ## 00085 # @if jp 00086 # @brief コンストラクタ 00087 # 00088 # OutPortPushConnector のコンストラクタはオブジェクト生成時に下記 00089 # を引数にとる。ConnectorInfo は接続情報を含み、この情報に従いパブ 00090 # リッシャやバッファ等を生成する。InPort インターフェースに対する 00091 # コンシューマオブジェクトへのポインタを取り、所有権を持つので、 00092 # OutPortPushConnector は InPortConsumer の解体責任を持つ。各種イ 00093 # ベントに対するコールバック機構を提供する ConnectorListeners を持 00094 # ち、適切なタイミングでコールバックを呼び出す。データバッファがも 00095 # し OutPortBase から提供される場合はそのポインタを取る。 00096 # 00097 # @param info ConnectorInfo 00098 # @param consumer InPortConsumer 00099 # @param listeners ConnectorListeners 型のリスナオブジェクトリスト 00100 # @param buffer CdrBufferBase 型のバッファ 00101 # 00102 # @else 00103 # @brief Constructor 00104 # 00105 # OutPortPushConnector's constructor is given the following 00106 # arguments. According to ConnectorInfo which includes 00107 # connection information, a publisher and a buffer are created. 00108 # It is also given a pointer to the consumer object for the 00109 # InPort interface. The owner-ship of the pointer is owned by 00110 # this OutPortPushConnector, it has responsibility to destruct 00111 # the InPortConsumer. OutPortPushConnector also has 00112 # ConnectorListeners to provide event callback mechanisms, and 00113 # they would be called at the proper timing. If data buffer is 00114 # given by OutPortBase, the pointer to the buffer is also given 00115 # as arguments. 00116 # 00117 # @param info ConnectorInfo 00118 # @param consumer InPortConsumer 00119 # @param listeners ConnectorListeners type lsitener object list 00120 # @param buffer CdrBufferBase type buffer 00121 # 00122 # @endif 00123 # 00124 # OutPortPushConnector(ConnectorInfo info, 00125 # InPortConsumer* consumer, 00126 # ConnectorListeners& listeners, 00127 # CdrBufferBase* buffer = 0); 00128 def __init__(self, info, consumer, listeners, buffer = 0): 00129 OpenRTM_aist.OutPortConnector.__init__(self, info) 00130 00131 self._buffer = buffer 00132 self._consumer = consumer 00133 self._listeners = listeners 00134 00135 # publisher/buffer creation. This may throw std::bad_alloc; 00136 self._publisher = self.createPublisher(info) 00137 if not self._buffer: 00138 self._buffer = self.createBuffer(info) 00139 00140 00141 if not self._publisher or not self._buffer or not self._consumer: 00142 raise 00143 00144 if self._publisher.init(info.properties) != self.PORT_OK: 00145 raise 00146 00147 if self._profile.properties.hasKey("serializer"): 00148 endian = self._profile.properties.getProperty("serializer.cdr.endian") 00149 if not endian: 00150 self._rtcout.RTC_ERROR("write(): endian is not set.") 00151 raise 00152 00153 endian = OpenRTM_aist.split(endian, ",") # Maybe endian is ["little","big"] 00154 endian = OpenRTM_aist.normalize(endian) # Maybe self._endian is "little" or "big" 00155 if endian == "little": 00156 self._endian = True 00157 elif endian == "big": 00158 self._endian = False 00159 else: 00160 self._endian = None 00161 00162 else: 00163 self._endian = True # little endian 00164 00165 self._buffer.init(info.properties.getNode("buffer")) 00166 self._consumer.init(info.properties) 00167 self._publisher.setConsumer(self._consumer) 00168 self._publisher.setBuffer(self._buffer) 00169 self._publisher.setListener(self._profile, self._listeners) 00170 00171 self.onConnect() 00172 return 00173 00174 00175 ## 00176 # @if jp 00177 # @brief デストラクタ 00178 # 00179 # disconnect() が呼ばれ、consumer, publisher, buffer が解体・削除される。 00180 # 00181 # @else 00182 # 00183 # @brief Destructor 00184 # 00185 # This operation calls disconnect(), which destructs and deletes 00186 # the consumer, the publisher and the buffer. 00187 # 00188 # @endif 00189 # 00190 def __del__(self): 00191 return 00192 00193 ## 00194 # @if jp 00195 # @brief データの書き込み 00196 # 00197 # Publisherに対してデータを書き込み、これにより対応するInPortへデー 00198 # タが転送される。正常終了した場合 PORT_OK が返される。それ以外の 00199 # 場合、エラー値として、CONNECTION_LOST, BUFFER_FULL, 00200 # BUFFER_ERROR, PORT_ERROR, BUFFER_TIMEOUT, PRECONDITION_NO_MET が 00201 # 返される。 00202 # 00203 # @return PORT_OK 正常終了 00204 # CONNECTION_LOST 接続がロストした 00205 # BUFFER_FULL バッファが一杯である 00206 # BUFFER_ERROR バッファエラー 00207 # BUFFER_TIMEOUT バッファへの書き込みがタイムアウトした 00208 # PRECONDITION_NOT_MET 事前条件を満たさない 00209 # PORT_ERROR その他のエラー 00210 # 00211 # @else 00212 # 00213 # @brief Writing data 00214 # 00215 # This operation writes data into publisher and then the data 00216 # will be transferred to correspondent InPort. If data is written 00217 # properly, this function will return PORT_OK return code. Except 00218 # normal return, CONNECTION_LOST, BUFFER_FULL, BUFFER_ERROR, 00219 # PORT_ERROR, BUFFER_TIMEOUT and PRECONDITION_NO_MET will be 00220 # returned as error codes. 00221 # 00222 # @return PORT_OK Normal return 00223 # CONNECTION_LOST Connectin lost 00224 # BUFFER_FULL Buffer full 00225 # BUFFER_ERROR Buffer error 00226 # BUFFER_TIMEOUT Timeout 00227 # PRECONDITION_NOT_MET Precondition not met 00228 # PORT_ERROR Other error 00229 # 00230 # @endif 00231 # 00232 # template<class DataType> 00233 # virtual ReturnCode write(const DataType& data); 00234 def write(self, data): 00235 self._rtcout.RTC_TRACE("write()") 00236 00237 # data -> (conversion) -> CDR stream 00238 cdr_data = None 00239 if self._endian is not None: 00240 cdr_data = cdrMarshal(any.to_any(data).typecode(), data, self._endian) 00241 else: 00242 self._rtcout.RTC_ERROR("write(): endian %s is not support.",self._endian) 00243 return self.UNKNOWN_ERROR 00244 00245 return self._publisher.write(cdr_data, 0, 0) 00246 00247 00248 ## 00249 # @if jp 00250 # @brief 接続解除 00251 # 00252 # consumer, publisher, buffer が解体・削除される。 00253 # 00254 # @else 00255 # 00256 # @brief disconnect 00257 # 00258 # This operation destruct and delete the consumer, the publisher 00259 # and the buffer. 00260 # 00261 # @endif 00262 # 00263 # virtual ReturnCode disconnect(); 00264 def disconnect(self): 00265 self._rtcout.RTC_TRACE("disconnect()") 00266 self.onDisconnect() 00267 # delete publisher 00268 if self._publisher: 00269 self._rtcout.RTC_DEBUG("delete publisher") 00270 pfactory = OpenRTM_aist.PublisherFactory.instance() 00271 pfactory.deleteObject(self._publisher) 00272 00273 self._publisher = 0 00274 00275 # delete consumer 00276 if self._consumer: 00277 self._rtcout.RTC_DEBUG("delete consumer") 00278 cfactory = OpenRTM_aist.InPortConsumerFactory.instance() 00279 cfactory.deleteObject(self._consumer) 00280 00281 self._consumer = 0 00282 00283 # delete buffer 00284 if self._buffer: 00285 self._rtcout.RTC_DEBUG("delete buffer") 00286 bfactory = OpenRTM_aist.CdrBufferFactory.instance() 00287 bfactory.deleteObject(self._buffer) 00288 00289 self._buffer = 0 00290 self._rtcout.RTC_TRACE("disconnect() done") 00291 00292 return self.PORT_OK 00293 00294 00295 ## 00296 # @if jp 00297 # @brief アクティブ化 00298 # 00299 # このコネクタをアクティブ化する 00300 # 00301 # @else 00302 # 00303 # @brief Connector activation 00304 # 00305 # This operation activates this connector 00306 # 00307 # @endif 00308 # 00309 # virtual void activate(); 00310 def activate(self): 00311 self._publisher.activate() 00312 return 00313 00314 00315 ## 00316 # @if jp 00317 # @brief 非アクティブ化 00318 # 00319 # このコネクタを非アクティブ化する 00320 # 00321 # @else 00322 # 00323 # @brief Connector deactivation 00324 # 00325 # This operation deactivates this connector 00326 # 00327 # @endif 00328 # 00329 # virtual void deactivate(); 00330 def deactivate(self): 00331 self._publisher.deactivate() 00332 return 00333 00334 00335 ## 00336 # @if jp 00337 # @brief Buffer を取得する 00338 # 00339 # Connector が保持している Buffer を返す 00340 # 00341 # @else 00342 # @brief Getting Buffer 00343 # 00344 # This operation returns this connector's buffer 00345 # 00346 # @endif 00347 # 00348 # virtual CdrBufferBase* getBuffer(); 00349 def getBuffer(self): 00350 return self._buffer 00351 00352 00353 ## 00354 # @if jp 00355 # @brief Publisherの生成 00356 # 00357 # 与えられた接続情報に基づきパブリッシャを生成する。 00358 # 00359 # @param info 接続情報 00360 # @return パブリッシャへのポインタ 00361 # 00362 # @else 00363 # @brief create buffer 00364 # 00365 # This function creates a publisher based on given information. 00366 # 00367 # @param info Connector information 00368 # @return The poitner to the publisher 00369 # 00370 # @endif 00371 # 00372 # virtual PublisherBase* createPublisher(ConnectorInfo& info); 00373 def createPublisher(self, info): 00374 pub_type = info.properties.getProperty("subscription_type","flush") 00375 pub_type = OpenRTM_aist.normalize([pub_type]) 00376 return OpenRTM_aist.PublisherFactory.instance().createObject(pub_type) 00377 00378 00379 ## 00380 # @if jp 00381 # @brief Bufferの生成 00382 # 00383 # 与えられた接続情報に基づきバッファを生成する。 00384 # 00385 # @param info 接続情報 00386 # @return バッファへのポインタ 00387 # 00388 # @else 00389 # @brief create buffer 00390 # 00391 # This function creates a buffer based on given information. 00392 # 00393 # @param info Connector information 00394 # @return The poitner to the buffer 00395 # 00396 # @endif 00397 # 00398 # virtual CdrBufferBase* createBuffer(ConnectorInfo& info); 00399 def createBuffer(self, info): 00400 buf_type = info.properties.getProperty("buffer_type", 00401 "ring_buffer") 00402 00403 return OpenRTM_aist.CdrBufferFactory.instance().createObject(buf_type) 00404 00405 00406 ## 00407 # @if jp 00408 # @brief 接続確立時にコールバックを呼ぶ 00409 # @else 00410 # @brief Invoke callback when connection is established 00411 # @endif 00412 # void onConnect() 00413 def onConnect(self): 00414 if self._listeners and self._profile: 00415 self._listeners.connector_[OpenRTM_aist.ConnectorListenerType.ON_CONNECT].notify(self._profile) 00416 return 00417 00418 ## 00419 # @if jp 00420 # @brief 接続切断時にコールバックを呼ぶ 00421 # @else 00422 # @brief Invoke callback when connection is destroied 00423 # @endif 00424 # void onDisconnect() 00425 def onDisconnect(self): 00426 if self._listeners and self._profile: 00427 self._listeners.connector_[OpenRTM_aist.ConnectorListenerType.ON_DISCONNECT].notify(self._profile) 00428 return