PeriodicExecutionContext.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- coding: euc-jp -*-
00003 
00004 ##
00005 # @file PeriodicExecutionContext.py
00006 # @brief PeriodicExecutionContext class
00007 # @date $Date: 2007/08/29$
00008 # @author Noriaki Ando <n-ando@aist.go.jp> and Shinji Kurihara
00009 #
00010 # Copyright (C) 2006-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 sys
00018 import copy
00019 import threading
00020 import time
00021 from omniORB import CORBA, PortableServer
00022 
00023 import OpenRTM_aist
00024 import OpenRTM
00025 import RTC
00026 
00027 DEFAULT_PERIOD = 0.000001
00028 
00029 ##
00030 # @if jp
00031 # @class PeriodicExecutionContext
00032 # @brief PeriodicExecutionContext クラス
00033 #
00034 # Periodic Sampled Data Processing(周期実行用)ExecutionContextクラス。
00035 #
00036 # @since 0.4.0
00037 #
00038 # @else
00039 # @class PeriodicExecutionContext
00040 # @brief PeriodicExecutionContext class
00041 # @endif
00042 class PeriodicExecutionContext(OpenRTM_aist.ExecutionContextBase,
00043                                OpenRTM_aist.Task):
00044   """
00045   """
00046 
00047 
00048 
00049   ##
00050   # @if jp
00051   # @class DFP
00052   # @brief DFP クラス
00053   #
00054   # 参加者リストに登録された DataFlowParticipant の関数を起動するための
00055   # 内部クラス。
00056   #
00057   # @param Object 管理対象コンポーネントの型
00058   #
00059   # @else
00060   #
00061   # @endif
00062   class DFP:
00063     """
00064     """
00065 
00066     ##
00067     # @if jp
00068     # @brief デフォルトコンストラクタ
00069     #
00070     # デフォルトコンストラクタ
00071     #
00072     # @param self
00073     # @param obj 管理対象コンポーネント
00074     # @param id_ 所属する ExecutionContext のID
00075     #
00076     # @else
00077     # @brief Constructor
00078     # @endif
00079     def __init__(self, obj, id_):
00080       self._obj = obj
00081       self._active = True
00082       self.ec_id = id_
00083       self._sm = OpenRTM_aist.StateMachine(4)
00084       self._sm.setListener(self)
00085       self._sm.setEntryAction (RTC.ACTIVE_STATE,
00086                                self.on_activated)
00087       self._sm.setDoAction    (RTC.ACTIVE_STATE,
00088                                self.on_execute)
00089       self._sm.setPostDoAction(RTC.ACTIVE_STATE,
00090                                self.on_state_update)
00091       self._sm.setExitAction  (RTC.ACTIVE_STATE,
00092                                self.on_deactivated)
00093       self._sm.setEntryAction (RTC.ERROR_STATE,
00094                                self.on_aborting)
00095       self._sm.setDoAction    (RTC.ERROR_STATE,
00096                                self.on_error)
00097       self._sm.setExitAction  (RTC.ERROR_STATE,
00098                                self.on_reset)
00099       st = OpenRTM_aist.StateHolder()
00100       st.prev = RTC.INACTIVE_STATE
00101       st.curr = RTC.INACTIVE_STATE
00102       st.next = RTC.INACTIVE_STATE
00103       self._sm.setStartState(st)
00104       self._sm.goTo(RTC.INACTIVE_STATE)
00105 
00106 
00107     ##
00108     # @if jp
00109     # @brief ExecutionContext 実行開始時に呼ばれる関数
00110     #
00111     # 参加している ExecutionContext が実行を開始する時(Running状態へ遷移時)
00112     # に、管理対象コンポーネントの on_startup を呼びだす。
00113     #
00114     # @param self
00115     #
00116     # @else
00117     #
00118     # @brief
00119     #
00120     # @endif
00121     def on_startup(self):
00122       return self._obj.on_startup(self.ec_id)
00123 
00124 
00125     ##
00126     # @if jp
00127     # @brief ExecutionContext 停止時に呼ばれる関数
00128     #
00129     # 参加している ExecutionContext が実行を停止する時(Stopped状態へ遷移時)
00130     # に、管理対象コンポーネントの on_shutdown を呼びだす。
00131     #
00132     # @param self
00133     #
00134     # @else
00135     #
00136     # @endif
00137     def on_shutdown(self):
00138       return self._obj.on_shutdown(self.ec_id)
00139 
00140 
00141     ##
00142     # @if jp
00143     # @brief RTコンポーネントがアクティブ化された時に呼ばれる関数
00144     #
00145     # 管理対象のRTコンポーネントがアクティブ化された時(Active状態へ遷移時)
00146     # に、管理対象コンポーネントの on_activated を呼びだす。
00147     # 管理対象コンポーネントのアクティブ化が失敗した場合には、ステートマシン
00148     # を Error 状態に遷移させる。
00149     #
00150     # @param self
00151     # @param st 対象RTコンポーネントの現在の状態
00152     #
00153     # @else
00154     #
00155     # @endif
00156     def on_activated(self, st):
00157       if self._obj.on_activated(self.ec_id) != RTC.RTC_OK:
00158         self._sm.goTo(RTC.ERROR_STATE)
00159         return
00160       return
00161 
00162 
00163     ##
00164     # @if jp
00165     # @brief RTコンポーネントが非アクティブ化された時に呼ばれる関数
00166     #
00167     # 管理対象のRTコンポーネントが非アクティブ化された時
00168     # (Deactive状態へ遷移時)に、管理対象コンポーネントの on_deactivated を
00169     # 呼びだす。
00170     #
00171     # @param self
00172     # @param st 対象RTコンポーネントの現在の状態
00173     #
00174     # @else
00175     #
00176     # @endif
00177     def on_deactivated(self, st):
00178       self._obj.on_deactivated(self.ec_id)
00179 
00180 
00181     ##
00182     # @if jp
00183     # @brief RTコンポーネントでエラーが発生した時に呼ばれる関数
00184     #
00185     # 管理対象のRTコンポーネントにエラーが発生した時(Error状態へ遷移時)
00186     # に管理対象コンポーネントの on_aborting を呼びだす。
00187     #
00188     # @param self
00189     # @param st 対象RTコンポーネントの現在の状態
00190     #
00191     # @else
00192     #
00193     # @brief
00194     #
00195     # @endif
00196     def on_aborting(self, st):
00197       self._obj.on_aborting(self.ec_id)
00198 
00199 
00200     ##
00201     # @if jp
00202     # @brief RTコンポーネントがエラー状態の時に呼ばれる関数
00203     #
00204     # 管理対象のRTコンポーネントがエラー状態にいる間、 
00205     # 管理対象コンポーネントの on_error を定期的に呼びだす。
00206     #
00207     # @param self
00208     # @param st 対象RTコンポーネントの現在の状態
00209     #
00210     # @else
00211     #
00212     # @brief
00213     #
00214     # @endif
00215     def on_error(self, st):
00216       self._obj.on_error(self.ec_id)
00217 
00218 
00219     ##
00220     # @if jp
00221     # @brief RTコンポーネントをリセットする時に呼ばれる関数
00222     #
00223     # 管理対象のRTコンポーネントをリセットする際に、管理対象コンポーネント
00224     # の on_reset を呼びだす。
00225     #
00226     # @param self
00227     # @param st 対象RTコンポーネントの現在の状態
00228     #
00229     # @else
00230     #
00231     # @endif
00232     def on_reset(self, st):
00233       if self._obj.on_reset(self.ec_id) != RTC.RTC_OK:
00234         self._sm.goTo(RTC.ERROR_STATE)
00235         return
00236       return
00237 
00238 
00239     ##
00240     # @if jp
00241     # @brief RTコンポーネント実行時に定期的に呼ばれる関数
00242     #
00243     # 管理対象のRTコンポーネントが Active 状態であるとともに、
00244     # ExecutionContext が Running 状態の場合に、設定された動作周期で定期的に
00245     # 管理対象コンポーネントの on_execute を呼びだす。
00246     # 関数の実行に失敗した場合(返値が RTC_OK 以外)、管理対象コンポーネントの
00247     # 状態を Error 状態に遷移させる。
00248     #
00249     # @param self
00250     # @param st 対象RTコンポーネントの現在の状態
00251     #
00252     # @else
00253     #
00254     # @endif
00255     def on_execute(self, st):
00256       if self._obj.on_execute(self.ec_id) != RTC.RTC_OK:
00257         self._sm.goTo(RTC.ERROR_STATE)
00258         return
00259       return
00260 
00261 
00262     ##
00263     # @if jp
00264     # @brief RTコンポーネント実行時に定期的に呼ばれる関数
00265     #
00266     # 管理対象のRTコンポーネントが Active 状態であるとともに、
00267     # ExecutionContext が Running 状態の場合に、設定された動作周期で定期的に
00268     # 管理対象コンポーネントの on_state_update を呼びだす。
00269     # 関数の実行に失敗した場合(返値が RTC_OK 以外)、管理対象コンポーネントの
00270     # 状態を Error 状態に遷移させる。
00271     #
00272     # @param self
00273     # @param st 対象RTコンポーネントの現在の状態
00274     #
00275     # @else
00276     #
00277     # @endif
00278     def on_state_update(self, st):
00279       if self._obj.on_state_update(self.ec_id) != RTC.RTC_OK:
00280         self._sm.goTo(RTC.ERROR_STATE)
00281         return
00282       return
00283 
00284 
00285     ##
00286     # @if jp
00287     # @brief ExecutionContext の実行周期変更時に呼ばれる関数
00288     #
00289     # 参加している ExecutionContext の実行周期が変更となった場合に、
00290     # 管理対象コンポーネントの on_rate_changed を呼びだす。
00291     #
00292     # @param self
00293     #
00294     # @else
00295     #
00296     # @endif
00297     def on_rate_changed(self):
00298       self._obj.on_rate_changed(self.ec_id)
00299 
00300 
00301     ##
00302     # @if jp
00303     # @brief 状態遷移を実行するワーカーを取得する
00304     #
00305     # 管理対象RTコンポーネントの状態遷移を実行するワーカーを取得する。
00306     #
00307     # @param self
00308     #
00309     # @return ワーカー
00310     #
00311     # @else
00312     #
00313     # @brief
00314     #
00315     # @endif
00316     def worker(self):
00317       return self._sm.worker()
00318 
00319 
00320     ##
00321     # @if jp
00322     # @brief 現在の状態を取得する
00323     #
00324     # 管理対象RTコンポーネントの現在の状態を取得する。
00325     #
00326     # @param self
00327     #
00328     # @return 現在状態
00329     #
00330     # @else
00331     #
00332     # @brief
00333     #
00334     # @endif
00335     def get_state(self):
00336       return self._sm.getState()
00337 
00338 
00339   ##
00340   # @if jp
00341   # @brief コンストラクタ
00342   #
00343   # コンストラクタ
00344   # 設定された値をプロファイルに設定する。
00345   #
00346   # @param self
00347   # @param owner 当該 Executioncontext の owner(デフォルト値:None)
00348   # @param rate 動作周期(Hz)(デフォルト値:None)
00349   #
00350   # @else
00351   # @brief Constructor
00352   # @endif
00353   def __init__(self, owner=None, rate=None):
00354     self._rtcout = OpenRTM_aist.Manager.instance().getLogbuf("rtobject.periodic_ec")
00355     self._rtcout.RTC_TRACE("PeriodicExecutionContext()")
00356 
00357     OpenRTM_aist.Task.__init__(self)
00358 
00359     self._nowait = False
00360     self._running = False
00361 
00362     self._worker = self.Worker()
00363 
00364     global DEFAULT_PERIOD
00365 
00366     if rate is None:
00367       self._period = OpenRTM_aist.TimeValue(DEFAULT_PERIOD)
00368     else:
00369       if rate == 0:
00370         rate = 1.0 / DEFAULT_PERIOD
00371       self._period = OpenRTM_aist.TimeValue(1.0 / rate)
00372 
00373       if self._period.sec() == 0  and self._period.usec() < 0.000001:
00374         self._nowait = True
00375 
00376     self._rtcout.RTC_DEBUG("Actual rate: %d [sec], %d [usec]",
00377                            (self._period.sec(), self._period.usec()))    
00378 
00379     self._comps = []
00380     self._profile = RTC.ExecutionContextProfile(RTC.PERIODIC, (1.0/self._period.toDouble()), None, [], [])
00381     self._ref = self._this()
00382     self._mutex_del = threading.RLock()
00383     return
00384 
00385 
00386   def __del__(self, Task=OpenRTM_aist.Task):
00387     self._rtcout.RTC_TRACE("~PeriodicExecutionContext()")
00388     self._worker._cond.acquire()
00389     self._worker._running = True
00390     self._worker._cond.notify()
00391     self._worker._cond.release()
00392     self._running = False
00393     #self.wait()
00394 
00395     self._profile.owner = None
00396     self._profile.paarticipants = []
00397     self._profile.properties = []
00398     guard = OpenRTM_aist.ScopedLock(self._mutex_del)
00399     Task.__del__(self)
00400     del guard
00401 
00402   ##
00403   # @if jp
00404   # @brief CORBA オブジェクト参照の取得
00405   #
00406   # 本オブジェクトの ExecutioncontextService としての CORBA オブジェクト参照
00407   # を取得する。
00408   #
00409   # @return CORBA オブジェクト参照
00410   #
00411   # @param self
00412   #
00413   # @else
00414   #
00415   # @endif
00416   def getObjRef(self):
00417     return self._ref
00418 
00419 
00420   ##
00421   # @if jp
00422   # @brief コンポーネントのアクティビティスレッド関数
00423   #
00424   # コンポーネントの内部アクティビティスレッドの実行関数。
00425   # ACE_Task サービスクラスメソッドのオーバーライド。
00426   #
00427   # @else
00428   #
00429   # @brief Create internal activity thread
00430   #
00431   # Run by a daemon thread to handle deferred processing.
00432   # ACE_Task class method override.
00433   #
00434   # @endif
00435   def svc(self):
00436     self._rtcout.RTC_TRACE("svc()")
00437     flag = True
00438     count_ = 0
00439     
00440     guard = OpenRTM_aist.ScopedLock(self._mutex_del)
00441     while flag:
00442       self._worker._cond.acquire()
00443       while not self._worker._running:
00444         self._worker._cond.wait()
00445 
00446       t0_ = OpenRTM_aist.Time()
00447 
00448       if self._worker._running:
00449         for comp in self._comps:
00450           comp._sm.worker()
00451 
00452       self._worker._cond.release()
00453 
00454       t1_ = OpenRTM_aist.Time()
00455 
00456       if count_ > 1000:
00457         exctm_ = (t1_ - t0_).getTime().toDouble()
00458         slptm_ = self._period.toDouble() - exctm_
00459         self._rtcout.RTC_PARANOID("Period:    %f [s]", self._period.toDouble())
00460         self._rtcout.RTC_PARANOID("Execution: %f [s]", exctm_)
00461         self._rtcout.RTC_PARANOID("Sleep:     %f [s]", slptm_)
00462 
00463       t2_ = OpenRTM_aist.Time()
00464 
00465       if not self._nowait and self._period.toDouble() > ((t1_ - t0_).getTime().toDouble()):
00466         if count_ > 1000:
00467           self._rtcout.RTC_PARANOID("sleeping...")
00468         slptm_ = self._period.toDouble() - (t1_ - t0_).getTime().toDouble()
00469         time.sleep(slptm_)
00470 
00471       if count_ > 1000:
00472         t3_ = OpenRTM_aist.Time()
00473         self._rtcout.RTC_PARANOID("Slept:     %f [s]", (t3_ - t2_).getTime().toDouble())
00474         count_ = 0
00475       count_ += 1
00476       flag = self._running
00477     del guard
00478     return 0
00479 
00480 
00481   ##
00482   # @if jp
00483   # @brief ExecutionContext 用のスレッド実行関数
00484   #
00485   # ExecutionContext 用のスレッド終了時に呼ばれる。
00486   # コンポーネントオブジェクトの非アクティブ化、マネージャへの通知を行う。
00487   # これは ACE_Task サービスクラスメソッドのオーバーライド。
00488   #
00489   # @param self
00490   # @param flags 終了処理フラグ
00491   #
00492   # @return 終了処理結果
00493   #
00494   # @else
00495   #
00496   # @brief Close activity thread
00497   #
00498   # close() method is called when activity thread svc() is returned.
00499   # This method deactivate this object and notify it to manager.
00500   # ACE_Task class method override.
00501   #
00502   # @endif
00503   def close(self, flags):
00504     self._rtcout.RTC_TRACE("close()")
00505     return 0
00506 
00507 
00508   ##
00509   # @if jp
00510   # @brief ExecutionContext 実行状態確認関数
00511   #
00512   # この操作は ExecutionContext が Runnning 状態の場合に true を返す。
00513   # Executioncontext が Running の間、当該 Executioncontext に参加している
00514   # 全てのアクティブRTコンポーネントが、 ExecutionContext の実行種類に応じて
00515   # 実行される。
00516   #
00517   # @param self
00518   #
00519   # @return 状態確認関数(動作中:true、停止中:false)
00520   #
00521   # @else
00522   #
00523   # @brief Check for ExecutionContext running state
00524   #
00525   # This operation shall return true if the context is in the Running state.
00526   # While the context is Running, all Active RTCs participating
00527   # in the context shall be executed according to the context’s execution
00528   # kind.
00529   #
00530   # @endif
00531   def is_running(self):
00532     self._rtcout.RTC_TRACE("is_running()")
00533     return self._running
00534 
00535 
00536   ##
00537   # @if jp
00538   # @brief ExecutionContext の実行を開始
00539   #
00540   # ExecutionContext の実行状態を Runnning とするためのリクエストを発行する。
00541   # ExecutionContext の状態が遷移すると ComponentAction::on_startup が
00542   # 呼び出される。
00543   # 参加しているRTコンポーネントが、初期化されるまで ExecutionContext を開始
00544   # することはできない。
00545   # ExecutionContext は複数回開始/停止を繰り返すことができる。
00546   #
00547   # @param self
00548   #
00549   # @return ReturnCode_t 型のリターンコード
00550   #
00551   # @else
00552   #
00553   # @brief Start ExecutionContext
00554   #
00555   # Request that the context enter the Running state. 
00556   # Once the state transition occurs, the ComponentAction::on_startup 
00557   # operation will be invoked.
00558   # An execution context may not be started until the RT components that
00559   # participate in it have been initialized.
00560   # An execution context may be started and stopped multiple times.
00561   #
00562   # @endif
00563   def start(self):
00564     self._rtcout.RTC_TRACE("start()")
00565     if self._running:
00566       return RTC.PRECONDITION_NOT_MET
00567 
00568     for comp in self._comps:
00569       comp._sm.on_startup()
00570 
00571     self._running = True
00572 
00573     self._worker._cond.acquire()
00574     self._worker._running = True
00575     self._worker._cond.notify()
00576     self._worker._cond.release()
00577 
00578     try:
00579       self.activate()
00580     except:
00581       self._running = False
00582 
00583       self._worker._cond.acquire()
00584       self._worker._running = False
00585       self._worker._cond.notify()
00586       self._worker._cond.release()
00587       self._rtcout.RTC_ERROR(OpenRTM_aist.Logger.print_exception())
00588 
00589     return RTC.RTC_OK
00590 
00591 
00592   ##
00593   # @if jp
00594   # @brief ExecutionContext の実行を停止
00595   #
00596   # ExecutionContext の状態を Stopped とするためのリクエストを発行する。
00597   # 遷移が発生した場合は、 ComponentAction::on_shutdown が呼び出される。
00598   # 参加しているRTコンポーネントが終了する前に ExecutionContext を停止する
00599   # 必要がある。
00600   # ExecutionContext は複数回開始/停止を繰り返すことができる。
00601   #
00602   # @param self
00603   #
00604   # @return ReturnCode_t 型のリターンコード
00605   #
00606   # @else
00607   #
00608   # @brief Stop ExecutionContext
00609   #
00610   # Request that the context enter the Stopped state. 
00611   # Once the transition occurs, the ComponentAction::on_shutdown operation
00612   # will be invoked.
00613   # An execution context must be stopped before the RT components that
00614   # participate in it are finalized.
00615   # An execution context may be started and stopped multiple times.
00616   #
00617   # @endif
00618   def stop(self):
00619     self._rtcout.RTC_TRACE("stop()")
00620     if not self._running:
00621       return RTC.PRECONDITION_NOT_MET
00622 
00623     self._running = False
00624     self._worker._cond.acquire()
00625     self._worker._running = False
00626     self._worker._cond.release()
00627 
00628     for comp in self._comps:
00629       comp._sm.on_shutdown()
00630 
00631     #self.wait()
00632     return RTC.RTC_OK
00633 
00634 
00635   ##
00636   # @if jp
00637   # @brief ExecutionContext の実行周期(Hz)を取得する
00638   #
00639   # Active 状態にてRTコンポーネントが実行される周期(単位:Hz)を取得する。
00640   #
00641   # @param self
00642   #
00643   # @return 処理周期(単位:Hz)
00644   #
00645   # @else
00646   #
00647   # @brief Get ExecutionRate
00648   #
00649   # This operation shall return the rate (in hertz) at which its Active
00650   # participating RTCs are being invoked.
00651   #
00652   # @endif
00653   def get_rate(self):
00654     self._rtcout.RTC_TRACE("get_rate()")
00655     return self._profile.rate
00656 
00657 
00658   ##
00659   # @if jp
00660   # @brief ExecutionContext の実行周期(Hz)を設定する
00661   #
00662   # Active 状態にてRTコンポーネントが実行される周期(単位:Hz)を設定する。
00663   # 実行周期の変更は、 DataFlowComponentAction の on_rate_changed によって
00664   # 各RTコンポーネントに伝達される。
00665   #
00666   # @param self
00667   # @param rate 処理周期(単位:Hz)
00668   #
00669   # @return ReturnCode_t 型のリターンコード
00670   #
00671   # @else
00672   #
00673   # @brief Set ExecutionRate
00674   #
00675   # This operation shall set the rate (in hertz) at which this context’s 
00676   # Active participating RTCs are being called.
00677   # If the execution kind of the context is PERIODIC, a rate change shall
00678   # result in the invocation of on_rate_changed on any RTCs realizing
00679   # DataFlowComponentAction that are registered with any RTCs participating
00680   # in the context.
00681   #
00682   # @endif
00683   def set_rate(self, rate):
00684     self._rtcout.RTC_TRACE("set_rate(%f)", rate)
00685     if rate > 0.0:
00686       self._profile.rate = rate
00687       self._period.set_time(1.0/rate)
00688       if self._period.toDouble() == 0.0:
00689         self._nowait = True
00690 
00691       for comp in self._comps:
00692         comp._sm.on_rate_changed()
00693       return RTC.RTC_OK
00694     return RTC.BAD_PARAMETER
00695 
00696 
00697   ##
00698   # @if jp
00699   # @brief RTコンポーネントをアクティブ化する
00700   #
00701   # Inactive 状態にあるRTコンポーネントをActive に遷移させ、アクティブ化する。
00702   # この操作が呼ばれた結果、 on_activate が呼び出される。
00703   # 指定したRTコンポーネントが参加者リストに含まれない場合は、 BAD_PARAMETER 
00704   # が返される。
00705   # 指定したRTコンポーネントの状態が Inactive 以外の場合は、
00706   #  PRECONDITION_NOT_MET が返される。
00707   #
00708   # @param self
00709   # @param comp アクティブ化対象RTコンポーネント
00710   #
00711   # @return ReturnCode_t 型のリターンコード
00712   #
00713   # @else
00714   #
00715   # @brief Activate a RT-component
00716   #
00717   # The given participant RTC is Inactive and is therefore not being invoked
00718   # according to the execution context’s execution kind. This operation
00719   # shall cause the RTC to transition to the Active state such that it may
00720   # subsequently be invoked in this execution context.
00721   # The callback on_activate shall be called as a result of calling this
00722   # operation. This operation shall not return until the callback has
00723   # returned, and shall result in an error if the callback does.
00724   #
00725   # @endif
00726   def activate_component(self, comp):
00727     self._rtcout.RTC_TRACE("activate_component()")
00728     for compIn in self._comps:
00729       if compIn._ref._is_equivalent(comp):
00730         if not compIn._sm._sm.isIn(RTC.INACTIVE_STATE):
00731           return RTC.PRECONDITION_NOT_MET
00732         compIn._sm._sm.goTo(RTC.ACTIVE_STATE)
00733         return RTC.RTC_OK
00734 
00735     return RTC.BAD_PARAMETER
00736 
00737 
00738   ##
00739   # @if jp
00740   # @brief RTコンポーネントを非アクティブ化する
00741   #
00742   # Inactive 状態にあるRTコンポーネントを非アクティブ化し、
00743   # Inactive に遷移させる。
00744   # この操作が呼ばれた結果、 on_deactivate が呼び出される。
00745   # 指定したRTコンポーネントが参加者リストに含まれない場合は、 BAD_PARAMETER 
00746   # が返される。
00747   # 指定したRTコンポーネントの状態が Active 以外の場合は、
00748   # PRECONDITION_NOT_MET が返される。
00749   #
00750   # @param self
00751   # @param comp 非アクティブ化対象RTコンポーネント
00752   #
00753   # @return ReturnCode_t 型のリターンコード
00754   #
00755   # @else
00756   #
00757   # @brief Deactivate a RT-component
00758   #
00759   # The given RTC is Active in the execution context. Cause it to transition 
00760   # to the Inactive state such that it will not be subsequently invoked from
00761   # the context unless and until it is activated again.
00762   # The callback on_deactivate shall be called as a result of calling this
00763   # operation. This operation shall not return until the callback has 
00764   # returned, and shall result in an error if the callback does.
00765   #
00766   # @endif
00767   def deactivate_component(self, comp):
00768     self._rtcout.RTC_TRACE("deactivate_component()")
00769     for compIn in self._comps:
00770       if compIn._ref._is_equivalent(comp):
00771         if not compIn._sm._sm.isIn(RTC.ACTIVE_STATE):
00772           return RTC.PRECONDITION_NOT_MET
00773         compIn._sm._sm.goTo(RTC.INACTIVE_STATE)
00774         count_ = 0
00775         usec_per_sec_ = 1.0e6
00776         sleeptime_ = 10.0 * usec_per_sec_ / float(self.get_rate())
00777         self._rtcout.RTC_PARANOID("Sleep time is %f [us]", sleeptime_)
00778         while compIn._sm._sm.isIn(RTC.ACTIVE_STATE):
00779           self._rtcout.RTC_TRACE("Waiting to be the INACTIVE state %d %f", (count_, float(time.time())))
00780           time.sleep(sleeptime_/usec_per_sec_)
00781           if count_ > 1000:
00782             self._rtcout.RTC_ERROR("The component is not responding.")
00783             break
00784           count_ += 1
00785         if compIn._sm._sm.isIn(RTC.INACTIVE_STATE):
00786           self._rtcout.RTC_TRACE("The component has been properly deactivated.")
00787           return RTC.RTC_OK
00788         self._rtcout.RTC_ERROR("The component could not be deactivated.")
00789         return RTC.RTC_ERROR
00790 
00791     return RTC.BAD_PARAMETER
00792 
00793 
00794   ##
00795   # @if jp
00796   # @brief RTコンポーネントをリセットする
00797   #
00798   # Error 状態のRTコンポーネントの復帰を試みる。
00799   # この操作が呼ばれた結果、 on_reset が呼び出される。
00800   # 指定したRTコンポーネントが参加者リストに含まれない場合は、 BAD_PARAMETER
00801   # が返される。
00802   # 指定したRTコンポーネントの状態が Error 以外の場合は、 PRECONDITION_NOT_MET
00803   # が返される。
00804   #
00805   # @param self
00806   # @param comp リセット対象RTコンポーネント
00807   #
00808   # @return ReturnCode_t 型のリターンコード
00809   #
00810   # @else
00811   #
00812   # @brief Reset a RT-component
00813   #
00814   # Attempt to recover the RTC when it is in Error.
00815   # The ComponentAction::on_reset callback shall be invoked. This operation
00816   # shall not return until the callback has returned, and shall result in an
00817   # error if the callback does. If possible, the RTC developer should
00818   # implement that callback such that the RTC may be returned to a valid
00819   # state.
00820   #
00821   # @endif
00822   def reset_component(self, comp):
00823     self._rtcout.RTC_TRACE("reset_component()")
00824     for compIn in self._comps:
00825       if compIn._ref._is_equivalent(comp):
00826         if not compIn._sm._sm.isIn(RTC.ERROR_STATE):
00827           return RTC.PRECONDITION_NOT_MET
00828         compIn._sm._sm.goTo(RTC.INACTIVE_STATE)
00829         return RTC.RTC_OK
00830 
00831     return RTC.BAD_PARAMETER
00832 
00833 
00834   ##
00835   # @if jp
00836   # @brief RTコンポーネントの状態を取得する
00837   #
00838   # 指定したRTコンポーネントの状態(LifeCycleState)を取得する。
00839   # 指定したRTコンポーネントが参加者リストに含まれない場合は、 CREATED_STATE 
00840   # が返される。
00841   #
00842   # @param self
00843   # @param comp 状態取得対象RTコンポーネント
00844   #
00845   # @return 現在の状態(LifeCycleState)
00846   #
00847   # @else
00848   #
00849   # @brief Get RT-component's state
00850   #
00851   # This operation shall report the LifeCycleState of the given participant
00852   # RTC.
00853   #
00854   # @endif
00855   def get_component_state(self, comp):
00856     self._rtcout.RTC_TRACE("get_component_state()")
00857     for compIn in self._comps:
00858       if compIn._ref._is_equivalent(comp):
00859         return compIn._sm._sm.getState()
00860 
00861     return RTC.CREATED_STATE
00862 
00863 
00864   ##
00865   # @if jp
00866   # @brief ExecutionKind を取得する
00867   #
00868   # 本 ExecutionContext の ExecutionKind を取得する
00869   #
00870   # @param self
00871   #
00872   # @return ExecutionKind
00873   #
00874   # @else
00875   #
00876   # @brief Get the ExecutionKind
00877   #
00878   # This operation shall report the execution kind of the execution context.
00879   #
00880   # @endif
00881   def get_kind(self):
00882     self._rtcout.RTC_TRACE("get_kind()")
00883     return self._profile.kind
00884 
00885 
00886   ##
00887   # @if jp
00888   # @brief RTコンポーネントを追加する
00889   #
00890   # 指定したRTコンポーネントを参加者リストに追加する。
00891   # 追加されたRTコンポーネントは attach_context が呼ばれ、Inactive 状態に遷移
00892   # する。
00893   # 指定されたRTコンポーネントがnullの場合は、BAD_PARAMETER が返される。
00894   # 指定されたRTコンポーネントが DataFlowComponent 以外の場合は、
00895   # BAD_PARAMETER が返される。
00896   #
00897   # @param self
00898   # @param comp 追加対象RTコンポーネント
00899   #
00900   # @return ReturnCode_t 型のリターンコード
00901   #
00902   # @else
00903   #
00904   # @brief Add a RT-component
00905   #
00906   # The operation causes the given RTC to begin participating in the
00907   # execution context.
00908   # The newly added RTC will receive a call to 
00909   # LightweightRTComponent::attach_context and then enter the Inactive state.
00910   #
00911   # @endif
00912   def add_component(self, comp):
00913     self._rtcout.RTC_TRACE("add_component()")
00914     if CORBA.is_nil(comp):
00915       return RTC.BAD_PARAMETER
00916     try:
00917       dfp_  = comp._narrow(OpenRTM.DataFlowComponent)
00918       rtc_  = comp._narrow(RTC.RTObject)
00919       if CORBA.is_nil(dfp_) or CORBA.is_nil(rtc_):
00920         return RTC.BAD_PARAMETER
00921 
00922       id_   = dfp_.attach_context(self._ref)
00923       comp_ = self.Comp(ref=comp, dfp=dfp_, id=id_)
00924       self._comps.append(comp_)
00925       self._profile.participants.append(rtc_)
00926       return RTC.RTC_OK
00927     except CORBA.Exception:
00928       self._rtcout.RTC_ERROR(OpenRTM_aist.Logger.print_exception())
00929       return RTC.BAD_PARAMETER
00930 
00931     return RTC.RTC_OK
00932 
00933 
00934   def bindComponent(self, rtc):
00935     self._rtcout.RTC_TRACE("bindComponent()")
00936     if rtc is None:
00937       return RTC.BAD_PARAMETER
00938 
00939     comp_ = rtc.getObjRef()
00940     dfp_  = comp_._narrow(OpenRTM.DataFlowComponent)
00941     id_   = rtc.bindContext(self._ref)
00942     if id_ < 0 or id_ > OpenRTM_aist.ECOTHER_OFFSET:
00943       self._rtcout.RTC_ERROR("bindContext returns invalid id: %d", id_)
00944       return RTC.RTC_ERROR
00945 
00946     self._rtcout.RTC_DEBUG("bindContext returns id = %d", id_)
00947     # rtc is owner of this EC
00948     self._comps.append(self.Comp(ref=comp_, dfp=dfp_, id=id_))
00949     self._profile.owner = dfp_
00950     return RTC.RTC_OK
00951 
00952 
00953   ##
00954   # @if jp
00955   # @brief RTコンポーネントを参加者リストから削除する
00956   #
00957   # 指定したRTコンポーネントを参加者リストから削除する。
00958   # 削除されたRTコンポーネントは detach_context が呼ばれる。
00959   # 指定されたRTコンポーネントが参加者リストに登録されていない場合は、
00960   # BAD_PARAMETER が返される。
00961   #
00962   # @param self
00963   # @param comp 削除対象RTコンポーネント
00964   #
00965   # @return ReturnCode_t 型のリターンコード
00966   #
00967   # @else
00968   #
00969   # @brief Remove the RT-component from participant list
00970   #
00971   # This operation causes a participant RTC to stop participating in the
00972   # execution context.
00973   # The removed RTC will receive a call to
00974   # LightweightRTComponent::detach_context.
00975   #
00976   # @endif
00977   def remove_component(self, comp):
00978     self._rtcout.RTC_TRACE("remove_component()")
00979     len_ = len(self._comps)
00980     for i in range(len_):
00981       idx = (len_ - 1) - i
00982       if self._comps[idx]._ref._is_equivalent(comp):
00983         self._comps[idx]._ref.detach_context(self._comps[idx]._sm.ec_id)
00984         del self._comps[idx]
00985         rtcomp = comp._narrow(RTC.RTObject)
00986         if CORBA.is_nil(rtcomp):
00987           self._rtcout.RTC_ERROR("Invalid object reference.")
00988           return RTC.RTC_ERROR
00989         OpenRTM_aist.CORBA_SeqUtil.erase_if(self._profile.participants,
00990                                             self.find_participant(rtcomp))
00991         return RTC.RTC_OK
00992 
00993     return RTC.BAD_PARAMETER
00994 
00995 
00996   ##
00997   # @if jp
00998   # @brief ExecutionContextProfile を取得する
00999   #
01000   # 本 ExecutionContext のプロファイルを取得する。
01001   #
01002   # @param self
01003   #
01004   # @return ExecutionContextProfile
01005   #
01006   # @else
01007   #
01008   # @brief Get the ExecutionContextProfile
01009   #
01010   # This operation provides a profile “descriptor” for the execution 
01011   # context.
01012   #
01013   # @endif
01014   def get_profile(self):
01015     self._rtcout.RTC_TRACE("get_profile()")
01016     return self._profile
01017 
01018 
01019   class find_participant:
01020     def __init__(self, comp):
01021       self._comp = comp
01022       return
01023 
01024     def __call__(self, comp):
01025       return self._comp._is_equivalent(comp)
01026 
01027       
01028   ##
01029   # @if jp
01030   # @class Comp
01031   # @brief コンポーネント管理用内部クラス
01032   # @else
01033   # @endif
01034   class Comp:
01035     def __init__(self, ref=None, dfp=None, id=None, comp=None):
01036       if comp is None:
01037         self._ref = ref
01038         self._sm = PeriodicExecutionContext.DFP(dfp,id)
01039       else:
01040         self._ref = comp._ref
01041         self._sm  = PeriodicExecutionContext.DFP(comp._sm._obj,comp._sm.ec_id)
01042 
01043   ##
01044   # @if jp
01045   # @class Worker
01046   # @brief ExecutionContext 駆動クラス
01047   #
01048   # 実行処理に関する排他制御など、実際の処理を監視・制御するためのクラス。
01049   #
01050   # @since 0.4.0
01051   #
01052   # @else
01053   #
01054   # @endif
01055   class Worker:
01056     
01057     ##
01058     # @if jp
01059     # @brief コンストラクタ
01060     #
01061     # コンストラクタ
01062     #
01063     # @param self
01064     #
01065     # @else
01066     # @brief Constructor
01067     # @endif
01068     def __init__(self):
01069       self._mutex = threading.RLock()
01070       self._cond = threading.Condition(self._mutex)
01071       self._running = False
01072 
01073 ##
01074 # @if jp
01075 # @brief ExecutionContext を初期化する
01076 #
01077 # ExecutionContext 起動用ファクトリを登録する。
01078 #
01079 # @param manager マネージャオブジェクト
01080 #
01081 # @else
01082 #
01083 # @endif
01084 def PeriodicExecutionContextInit(manager):
01085   manager.registerECFactory("PeriodicExecutionContext",
01086                             OpenRTM_aist.PeriodicExecutionContext,
01087                             OpenRTM_aist.ECDelete)


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