00001 #!/usr/bin/env python 00002 # -*- coding: euc-jp -*- 00003 00004 ## 00005 # @file InPort.py 00006 # @brief InPort template class 00007 # @date $Date: 2007/09/20 $ 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 from omniORB import * 00018 from omniORB import any 00019 import sys 00020 import copy 00021 import time 00022 00023 import OpenRTM_aist 00024 00025 ## 00026 # @if jp 00027 # 00028 # @class InPort 00029 # 00030 # @brief InPort クラス 00031 # 00032 # InPort の実装クラス。 00033 # InPort は内部にリングバッファを持ち、外部から送信されたデータを順次 00034 # このリングバッファに格納する。リングバッファのサイズはデフォルトで64と 00035 # なっているが、コンストラクタ引数によりサイズを指定することができる。 00036 # データはフラグによって未読、既読状態が管理され、isNew(), getNewDataLen() 00037 # getNewList(), getNewListReverse() 等のメソッドによりハンドリングすることが 00038 # できる。 00039 # 00040 # @since 0.2.0 00041 # 00042 # @else 00043 # 00044 # @class InPort 00045 # 00046 # @brief InPort template class 00047 # 00048 # This class template provides interfaces to input port. 00049 # Component developer can define input value, which act as input 00050 # port from other components, using this template. 00051 # This is class template. This class have to be incarnated class as port 00052 # value types. This value types are previously define RtComponent IDL. 00053 # ex. type T: TimedFload, TimedLong etc... 00054 # 00055 # @since 0.2.0 00056 # 00057 # @endif 00058 class InPort(OpenRTM_aist.InPortBase): 00059 """ 00060 """ 00061 00062 00063 00064 ## 00065 # @if jp 00066 # 00067 # @brief コンストラクタ 00068 # 00069 # コンストラクタ。 00070 # 00071 # @param self 00072 # @param name InPort 名。InPortBase:name() により参照される。 00073 # @param value この InPort にバインドされる変数 00074 # @param read_block 読込ブロックフラグ。 00075 # データ読込時に未読データがない場合、次のデータ受信までブロックする 00076 # かどうかを設定(デフォルト値:False) 00077 # @param write_block 書込ブロックフラグ。 00078 # データ書込時にバッファがフルであった場合、バッファに空きができる 00079 # までブロックするかどうかを設定(デフォルト値:False) 00080 # @param read_timeout 読込ブロックを指定していない場合の、データ読取タイム 00081 # アウト時間(ミリ秒)(デフォルト値:0) 00082 # @param write_timeout 書込ブロックを指定していない場合の、データ書込タイム 00083 # アウト時間(ミリ秒)(デフォルト値:0) 00084 # 00085 # @else 00086 # 00087 # @brief A constructor. 00088 # 00089 # Setting channel name and registering channel value. 00090 # 00091 # @param self 00092 # @param name A name of the InPort. This name is referred by 00093 # InPortBase::name(). 00094 # @param value A channel value related with the channel. 00095 # @param read_block 00096 # @param write_block 00097 # @param read_timeout 00098 # @param write_timeout 00099 # 00100 # @endif 00101 def __init__(self, name, value, buffer=None, 00102 read_block=False, write_block=False, 00103 read_timeout=0, write_timeout = 0): 00104 OpenRTM_aist.InPortBase.__init__(self, name, OpenRTM_aist.toTypename(value)) 00105 self._name = name 00106 self._value = value 00107 self._OnRead = None 00108 self._OnReadConvert = None 00109 00110 00111 def __del__(self, InPortBase=OpenRTM_aist.InPortBase): 00112 InPortBase.__del__(self) 00113 return 00114 00115 ## 00116 # @if jp 00117 # @brief ポート名称を取得する。 00118 # 00119 # ポート名称を取得する。 00120 # 00121 # @param self 00122 # 00123 # @return ポート名称 00124 # 00125 # @else 00126 # 00127 # @endif 00128 # 00129 # const char* name() 00130 def name(self): 00131 return self._name 00132 00133 00134 ## 00135 # @if jp 00136 # @brief 最新データか確認 00137 # 00138 # 現在のバッファ位置に格納されているデータが最新データか確認する。 00139 # 00140 # @param self 00141 # 00142 # @return 最新データ確認結果 00143 # ( true:最新データ.データはまだ読み出されていない 00144 # false:過去のデータ.データは既に読み出されている) 00145 # 00146 # @else 00147 # 00148 # @endif 00149 # 00150 # bool isNew() 00151 def isNew(self): 00152 self._rtcout.RTC_TRACE("isNew()") 00153 00154 if len(self._connectors) == 0: 00155 self._rtcout.RTC_DEBUG("no connectors") 00156 return False 00157 00158 r = self._connectors[0].getBuffer().readable() 00159 if r > 0: 00160 self._rtcout.RTC_DEBUG("isNew() = True, readable data: %d",r) 00161 return True 00162 00163 self._rtcout.RTC_DEBUG("isNew() = False, no readable data") 00164 return False 00165 00166 00167 ## 00168 # @if jp 00169 # 00170 # @brief バッファが空かどうか確認する 00171 # 00172 # InPortのバッファが空かどうかを bool 値で返す。 00173 # 空の場合は true, 未読データがある場合は false を返す。 00174 # 00175 # @return true バッファは空 00176 # false バッファに未読データがある 00177 # 00178 # @else 00179 # 00180 # @brief Check whether the data is newest 00181 # 00182 # Check whether the data stored at a current buffer position is newest. 00183 # 00184 # @return Newest data check result 00185 # ( true:Newest data. Data has not been readout yet. 00186 # false:Past data.Data has already been readout.) 00187 # 00188 # @endif 00189 # 00190 # bool isEmpty() 00191 def isEmpty(self): 00192 self._rtcout.RTC_TRACE("isEmpty()") 00193 00194 if len(self._connectors) == 0: 00195 self._rtcout.RTC_DEBUG("no connectors") 00196 return True 00197 00198 r = self._connectors[0].getBuffer().readable() 00199 if r == 0: 00200 self._rtcout.RTC_DEBUG("isEmpty() = true, buffer is empty") 00201 return True 00202 00203 self._rtcout.RTC_DEBUG("isEmpty() = false, data exists in the buffer") 00204 return False 00205 00206 00207 ## 00208 # @if jp 00209 # 00210 # @brief DataPort から値を読み出す 00211 # 00212 # InPortに書き込まれたデータを読みだす。接続数が0、またはバッファに 00213 # データが書き込まれていない状態で読みだした場合の戻り値は不定である。 00214 # バッファが空の状態のとき、 00215 # 事前に設定されたモード (readback, do_nothing, block) に応じて、 00216 # 以下のような動作をする。 00217 # 00218 # - readback: 最後の値を読みなおす。 00219 # 00220 # - do_nothing: 何もしない 00221 # 00222 # - block: ブロックする。タイムアウトが設定されている場合は、 00223 # タイムアウトするまで待つ。 00224 # 00225 # バッファが空の状態では、InPortにバインドされた変数の値が返される。 00226 # したがって、初回読み出し時には不定値を返す可能性がある。 00227 # この関数を利用する際には、 00228 # 00229 # - isNew(), isEmpty() と併用し、事前にバッファ状態をチェックする。 00230 # 00231 # - 初回読み出し時に不定値を返さないようにバインド変数を事前に初期化する 00232 # 00233 # 00234 # 各コールバック関数は以下のように呼び出される。 00235 # - OnRead: read() 関数が呼ばれる際に必ず呼ばれる。 00236 # 00237 # - OnReadConvert: データの読み出しが成功した場合、読みだしたデータを 00238 # 引数としてOnReadConvertが呼び出され、戻り値をread()が戻り値 00239 # として返す。 00240 # 00241 # - OnEmpty: バッファが空のためデータの読み出しに失敗した場合呼び出される。 00242 # OnEmpty の戻り値を read() の戻り値として返す。 00243 # 00244 # - OnBufferTimeout: データフロー型がPush型の場合に、読み出し 00245 # タイムアウトのためにデータの読み出しに失敗した場合に呼ばれる。 00246 # 00247 # - OnRecvTimeout: データフロー型がPull型の場合に、読み出しタイムアウト 00248 # のためにデータ読み出しに失敗した場合に呼ばれる。 00249 # 00250 # - OnReadError: 上記以外の理由で読みだしに失敗した場合に呼ばれる。 00251 # 理由としては、バッファ設定の不整合、例外の発生などが考えられる 00252 # が通常は起こりえないためバグの可能性がある。 00253 # 00254 # @return 読み出したデータ 00255 # 00256 # @else 00257 # 00258 # @brief Readout the value from DataPort 00259 # 00260 # Readout the value from DataPort 00261 # 00262 # - When Callback functor OnRead is already set, OnRead will be invoked 00263 # before reading from the buffer held by DataPort. 00264 # - When the buffer held by DataPort can detect the underflow, 00265 # and when it detected the underflow at reading, callback functor 00266 # OnUnderflow will be invoked. 00267 # - When callback functor OnReadConvert is already set, the return value of 00268 # operator() of OnReadConvert will be the return value of read(). 00269 # - When timeout of reading is already set by setReadTimeout(), 00270 # it waits for only timeout time until the state of the buffer underflow 00271 # is reset, and if OnUnderflow is already set, this will be invoked to 00272 # return. 00273 # 00274 # @return Readout data 00275 # 00276 # @endif 00277 # 00278 # DataType read() 00279 def read(self): 00280 self._rtcout.RTC_TRACE("DataType read()") 00281 00282 if self._OnRead is not None: 00283 self._OnRead() 00284 self._rtcout.RTC_TRACE("OnRead called") 00285 00286 if len(self._connectors) == 0: 00287 self._rtcout.RTC_DEBUG("no connectors") 00288 return self._value 00289 00290 _val = copy.deepcopy(self._value) 00291 cdr = [_val] 00292 ret = self._connectors[0].read(cdr) 00293 00294 00295 if ret == OpenRTM_aist.DataPortStatus.PORT_OK: 00296 self._rtcout.RTC_DEBUG("data read succeeded") 00297 self._value = cdr[0] 00298 00299 if self._OnReadConvert is not None: 00300 self._value = self._OnReadConvert(self._value) 00301 self._rtcout.RTC_DEBUG("OnReadConvert called") 00302 return self._value 00303 return self._value 00304 00305 elif ret == OpenRTM_aist.DataPortStatus.BUFFER_EMPTY: 00306 self._rtcout.RTC_WARN("buffer empty") 00307 return self._value 00308 00309 elif ret == OpenRTM_aist.DataPortStatus.BUFFER_TIMEOUT: 00310 self._rtcout.RTC_WARN("buffer read timeout") 00311 return self._value 00312 00313 self._rtcout.RTC_ERROR("unknown retern value from buffer.read()") 00314 return self._value 00315 00316 00317 ## 00318 # @if jp 00319 # 00320 # @brief バインドされた変数に InPort バッファの最新値を読み込む 00321 # 00322 # バインドされたデータに InPort の最新値を読み込む。 00323 # コンストラクタで変数と InPort がバインドされていなければならない。 00324 # このメソッドはポリモーフィックに使用される事を前提としているため、 00325 # 型に依存しない引数、戻り値となっている。 00326 # 00327 # @param self 00328 # 00329 # @else 00330 # 00331 # @brief Read into bound T-type data from current InPort 00332 # 00333 # @endif 00334 def update(self): 00335 self.read() 00336 00337 00338 ## 00339 # @if jp 00340 # 00341 # @brief InPort バッファへデータ読み込み時のコールバックの設定 00342 # 00343 # InPort が持つバッファからデータが読み込まれる直前に呼ばれるコールバック 00344 # オブジェクトを設定する。 00345 # 00346 # @param self 00347 # @param on_read 設定対象コールバックオブジェクト 00348 # 00349 # @else 00350 # 00351 # @endif 00352 def setOnRead(self, on_read): 00353 self._OnRead = on_read 00354 00355 00356 ## 00357 # @if jp 00358 # 00359 # @brief InPort バッファへデータ読み出し時のコールバックの設定 00360 # 00361 # InPort が持つバッファからデータが読み出される際に呼ばれるコールバック 00362 # オブジェクトを設定する。コールバックオブジェクトの戻り値がread()メソッド 00363 # の呼出結果となる。 00364 # 00365 # @param self 00366 # @param on_rconvert 設定対象コールバックオブジェクト 00367 # 00368 # @else 00369 # 00370 # @endif 00371 def setOnReadConvert(self, on_rconvert): 00372 self._OnReadConvert = on_rconvert