gen_comp.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- Python -*-
00003 # -*- coding: utf-8 -*-
00004 
00005 '''rtshell
00006 
00007 Copyright (C) 2009-2014
00008     Geoffrey Biggs
00009     RT-Synthesis Research Group
00010     Intelligent Systems Research Institute,
00011     National Institute of Advanced Industrial Science and Technology (AIST),
00012     Japan
00013     All rights reserved.
00014 Licensed under the Eclipse Public License -v 1.0 (EPL)
00015 http://www.opensource.org/licenses/eclipse-1.0.txt
00016 
00017 Base class for generated-on-demand components.
00018 
00019 '''
00020 
00021 
00022 import inspect
00023 import OpenRTM_aist
00024 import RTC
00025 import sys
00026 import traceback
00027 
00028 
00029 ###############################################################################
00030 ## Port class
00031 
00032 class Port(object):
00033     '''Class to store the objects used for a port.'''
00034     def __init__(self, data, port, formatter=None, raw_spec=None, *args,
00035             **kwargs):
00036         super(Port, self).__init__()
00037         self._data = data
00038         self._port = port
00039         self._formatter = formatter
00040         self._raw = raw_spec
00041         members = [m for m in dir(self.data) if not m.startswith('_')]
00042         if len(members) == 2 and 'tm' in members and \
00043                 'data' in members and self.data.tm.__class__ == RTC.Time:
00044             self._standard_type = True
00045         else:
00046             self._standard_type = False
00047 
00048     @property
00049     def data(self):
00050         '''Get the port's data reference.'''
00051         return self._data
00052 
00053     @property
00054     def port(self):
00055         '''Get the port object.'''
00056         return self._port
00057 
00058     @property
00059     def formatter(self):
00060         '''Get the formatter function for the port, if any.'''
00061         return self._formatter
00062 
00063     @property
00064     def name(self):
00065         '''Get the port's name.'''
00066         return self._port.getName()
00067 
00068     @property
00069     def raw(self):
00070         '''Get the raw port spec for this port, if any.'''
00071         return self._raw
00072 
00073     @property
00074     def standard_type(self):
00075         '''Check if the port's data type is an RTC standard type.
00076 
00077         RTC standard types have a tm member (the timestamp) and a data member
00078         (the data).
00079 
00080         '''
00081         return self._standard_type
00082 
00083     def read(self):
00084         '''Read the next value from the port into self.data.'''
00085         self._data = self._port.read()
00086 
00087     def format(self):
00088         '''Return a string representation of the value of self.data.
00089 
00090         If self.formatter is not None, that function will be called to create
00091         the string representation. Otherwise, str() will be used except in the
00092         cases of data that contains a .tm member of type RTC.Time and a .data
00093         member. In that case, the time will be pretty-printed, followed by the
00094         data member, printed using str().
00095 
00096         '''
00097         if self.formatter:
00098             return self.formatter(self.data)
00099         else:
00100             members = [m for m in dir(self.data) if not m.startswith('_')]
00101             if len(members) == 2 and 'tm' in members and \
00102                     'data' in members and self.data.tm.__class__ == RTC.Time:
00103                 return '[{0}.{1:09}] {2}'.format(self.data.tm.sec,
00104                         self.data.tm.nsec, self.data.data)
00105             else:
00106                 return str(self.data)
00107 
00108 
00109 ###############################################################################
00110 ## Generated-on-demand component class
00111 
00112 class GenComp(OpenRTM_aist.DataFlowComponentBase):
00113     def __init__(self, mgr, port_specs, event=None, max=-1, *args, **kwargs):
00114         '''Constructor.
00115 
00116         @param mgr Reference to the manager that created this component.
00117         @param port_spec The port layout of the component. This must be
00118                          a list of port_types.PortSpec objects.
00119         @param event An event object that can be .set() to indicate
00120                      that the component has finished its assigned task
00121                      and should be shut down.
00122         @param max The maximum number of times this component should
00123                    perform its onExecute function before setting the
00124                    event to request a shutdown. Defaults to -1, for
00125                    unlimited.
00126 
00127         '''
00128         OpenRTM_aist.DataFlowComponentBase.__init__(self, mgr)
00129         self._port_specs = port_specs
00130         self._event = event
00131         self._max = max
00132         self._count = 0
00133 
00134     def onInitialize(self):
00135         try:
00136             self._ports = {}
00137             for p in self._port_specs:
00138                 args, varargs, varkw, defaults = \
00139                     inspect.getargspec(p.type.__init__)
00140                 if defaults:
00141                     init_args = tuple([None \
00142                             for ii in range(len(args) - len(defaults) - 1)])
00143                 else:
00144                     init_args = [None for ii in range(len(args) - 1)]
00145                 if p.input:
00146                     port_con = OpenRTM_aist.InPort
00147                     port_reg = self.registerInPort
00148                 else:
00149                     port_con = OpenRTM_aist.OutPort
00150                     port_reg = self.registerOutPort
00151                 p_data = p.type(*init_args)
00152                 p_port = port_con(p.name, p_data)
00153                 port_reg(p.name, p_port)
00154                 self._ports[p.name] = Port(p_data, p_port,
00155                         formatter=p.formatter, raw_spec=p)
00156         except:
00157             print >>sys.stderr, traceback.format_exc()
00158             return RTC.RTC_ERROR
00159         return RTC.RTC_OK
00160 
00161     def onExecute(self, ec_id):
00162         # Call the component behaviour
00163         res = RTC.RTC_OK
00164         if self._count < self._max or self._max < 0:
00165             res, executed = self._behv(ec_id)
00166             if executed > 0:
00167                 self._count += executed
00168                 if self._max > -1 and self._count >= self._max:
00169                     self._set()
00170         return res
00171 
00172     def _behv(self, ec_id):
00173         '''Behaviour function for derived components.
00174 
00175         Deriving classes must implement this function. It will be called by
00176         onExecute. It must return a tuple of (RTC result code, _behv result
00177         value). The RTC result code is used to create the result of onExecute;
00178         if no errors occur, it must be RTC.RTC_OK. The _behv result code is
00179         used to tell the component if the behaviour was able to execute
00180         (whether it succeeded or not), for the purposes of execution counting.
00181         It should be the number of iterations executed.
00182 
00183         '''
00184         pass
00185 
00186     def _set(self):
00187         '''Call set() on the event object to notify waiters.'''
00188         if self._event:
00189             self._event.set()
00190 
00191 
00192 def make_factory(cons, port_specs, event=None, max=-1, **kwargs):
00193     def fact_fun(mgr):
00194         return cons(mgr, port_specs, event=event, max=max, **kwargs)
00195     return fact_fun
00196 
00197 
00198 def make_init(name, cons, port_specs, event=None, rate=1.0, max=-1, **kwargs):
00199     def init_fun(mgr):
00200         spec= ['implementation_id', name,
00201             'type_name', name,
00202             'description', 'rtshell generated-on-demand component.',
00203             'version', '3.0',
00204             'vendor', 'rtshell',
00205             'category', 'Generated',
00206             'activity_type', 'DataFlowComponent',
00207             'max_instance', '1',
00208             'language', 'Python',
00209             'lang_type', 'SCRIPT',
00210             '']
00211         profile = OpenRTM_aist.Properties(defaults_str=spec)
00212         mgr.registerFactory(profile,
00213                 make_factory(cons, port_specs, event=event, max=max, **kwargs),
00214                 OpenRTM_aist.Delete)
00215         comp = mgr.createComponent(name +
00216             '?exec_cxt.periodic.type=PeriodicExecutionContext&'
00217             'exec_cxt.periodic.rate={0}'.format(rate))
00218     return init_fun
00219 


rtshell
Author(s): Geoffrey Biggs
autogenerated on Fri Aug 28 2015 12:55:12