rtlog_comps.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 Log recording and playing components used by rtlog
00018 
00019 '''
00020 
00021 
00022 import OpenRTM_aist
00023 import os.path
00024 import RTC
00025 import sys
00026 import time
00027 import traceback
00028 
00029 import gen_comp
00030 import ilog
00031 import rts_exceptions
00032 
00033 
00034 ###############################################################################
00035 ## Recorder component for rtlog
00036 
00037 class Recorder(gen_comp.GenComp):
00038     def __init__(self, mgr, port_specs, logger_type=None, filename='',
00039             lims_are_ind=False, end=-1, verbose=False, *args, **kwargs):
00040         if lims_are_ind:
00041             max = end
00042             self._end = -1
00043         else:
00044             max = -1
00045             self._end = end
00046         try:
00047             del kwargs['max']
00048         except KeyError:
00049             pass
00050         gen_comp.GenComp.__init__(self, mgr, port_specs, max=max, *args,
00051                 **kwargs)
00052         self._logger_type = logger_type
00053         self._fn = filename
00054         self._verb = verbose
00055 
00056     def onActivated(self, ec_id):
00057         start = time.time()
00058         # Add activated time to meta data
00059         # Add port specs to meta data (include names)
00060         meta = (start, self._port_specs)
00061         # Make file name from activated time
00062         if not self._fn:
00063             self._fn = 'rtlog_{0}.rtlog'.format(int(start))
00064         # Create log, record meta data
00065         self._l = self._logger_type(filename=self._fn, mode='w', meta=meta, verbose=self._verb)
00066         return RTC.RTC_OK
00067 
00068     def onFinalize(self):
00069         # Finalise and close log
00070         self._l.close()
00071         return RTC.RTC_OK
00072 
00073     def _behv(self, ec_id):
00074         execed = 0
00075         result = RTC.RTC_OK
00076         for name in self._ports:
00077             p = self._ports[name]
00078             if p.port.isNew():
00079                 execed += 1
00080                 p.read()
00081                 ts = self._log(p, name)
00082                 if self._end > -1 and ts >= self._end:
00083                     # Reached the end time
00084                     self._set()
00085             if self._max > -1 and self._count >= self._max:
00086                 # Reached the max entries
00087                 return result, execed
00088         return result, execed
00089 
00090     def _log(self, port, port_name):
00091         if port.standard_type:
00092             ts = ilog.EntryTS(sec=port.data.tm.sec, nsec=port.data.tm.nsec)
00093         else:
00094             ts = ilog.EntryTS(time=time.time())
00095         self._l.write(ts, (port_name, port.data))
00096         return ts
00097 
00098 
00099 ###############################################################################
00100 ## Player component for rtlog
00101 
00102 class Player(gen_comp.GenComp):
00103     def __init__(self, mgr, port_specs, logger_type=None, filename='',
00104             lims_are_ind=False, start=0, end=-1, scale_rate=1.0, abs_times=False,
00105             ignore_times=False, verbose=False, *args, **kwargs):
00106         if end >= 0:
00107             if lims_are_ind:
00108                 if start == 0:
00109                     max = end
00110                 else:
00111                     max = end - (start - 1)
00112                 self._end = -1
00113             else:
00114                 max = -1
00115                 self._end = end
00116         else:
00117             self._end = -1
00118             max = -1
00119         self._lims_ind = lims_are_ind
00120         self._start = start
00121         try:
00122             del kwargs['max']
00123         except KeyError:
00124             pass
00125         gen_comp.GenComp.__init__(self, mgr, port_specs, max=max, *args,
00126                 **kwargs)
00127         self._logger_type = logger_type
00128         self._fn = filename
00129         self._rate = scale_rate
00130         self._abs = abs_times
00131         self._ig_times = ignore_times
00132         self._verb = verbose
00133 
00134     def onActivated(self, ec_id):
00135         try:
00136             self._l = self._logger_type(filename=self._fn, mode='r',
00137                     verbose=self._verb)
00138             # Read the metadata block
00139             start, log_port_specs = self._l.metadata
00140             self._vprint('Log started at {0}'.format(start))
00141             self._vprint('Log port specs are {0}'.format(
00142                 [str(s) for s in log_port_specs]))
00143 
00144             # Check ports match
00145             for name in self._ports:
00146                 matches = [s for s in log_port_specs if s.name == name]
00147                 if len(matches) == 0:
00148                     print >>sys.stderr, 'WARNING: Port {0} not found in '\
00149                             'log.'.format(name)
00150                     continue
00151                 elif len(matches) != 1:
00152                     print >>sys.stderr, 'WARNING: Port {0} occurs multiple '\
00153                             'times in the log.'.format(name)
00154                     continue
00155                 m = matches[0]
00156                 if m.type != self._ports[name].raw.type:
00157                     print >>sys.stderr, 'ERROR: Port {0} is incorrect data '\
00158                             'type; should be {1}.'.format(name,
00159                                     type(self._ports[name].data))
00160                     self._set()
00161                     return RTC.RTC_ERROR
00162 
00163             # Sanity-check the end time
00164             if self._end >= 0 and self._end < self._l.start[1]:
00165                 print >>sys.stderr, 'WARNING: Specified end time is before '\
00166                         'the first entry time.'
00167 
00168             self._start_time = time.time()
00169             # Fast-forward to the start time (with a sanity-check)
00170             if self._start > 0: # If 0 index, already there; if 0 time... hmm
00171                 if self._lims_ind:
00172                     if self._start > self._l.end[0]:
00173                         print >>sys.stderr, 'ERROR: Specified start index is '\
00174                                 'after the last entry index.'
00175                         self._set()
00176                         return RTC.RTC_ERROR
00177                     self._l.seek(index=self._start)
00178                     self._log_start = self._l.pos[1].float
00179                 else:
00180                     if self._start > self._l.end[1]:
00181                         print >>sys.stderr, 'ERROR: Specified start time is '\
00182                                 'after the last entry time.'
00183                         self._set()
00184                         return RTC.RTC_ERROR
00185                     self._l.seek(timestamp=self._start)
00186                     self._log_start = self._l.pos[1].float
00187             else:
00188                 self._log_start = start
00189             self._offset = self._start_time - self._log_start
00190             self._vprint('Play start time is {0}, log start time is {1}'.format(
00191                 self._start_time, self._log_start))
00192             self._vprint('Time offset is {0}'.format(self._offset))
00193         except:
00194             traceback.print_exc()
00195             return RTC.RTC_ERROR
00196         return RTC.RTC_OK
00197 
00198     def onDeactivated(self, ec_id):
00199         # Close log
00200         self._l.close()
00201         return RTC.RTC_OK
00202 
00203     def _behv(self, ec_id):
00204         execed = 0
00205         result = RTC.RTC_OK
00206         try:
00207             if self._ig_times:
00208                 # Read self._rate items from the log and write them
00209                 for ii in range(int(self._rate)):
00210                     self._vprint('Playing {0} entries.'.format(int(self._rate)))
00211                     if not self._pub_log_item():
00212                         print >>sys.stderr, '{0}: End of log reached.'.format(
00213                                 os.path.basename(sys.argv[0]))
00214                         self._set()
00215                         result = RTC.RTC_ERROR
00216                     else:
00217                         execed += 1
00218             else:
00219                 # Calculate the current time in log-time
00220                 now = (((time.time() - self._start_time) * self._rate) +
00221                         self._log_start)
00222                 self._vprint('Current time in logspace is {0}'.format(now))
00223                 if self._end >= 0 and now > self._end:
00224                     self._vprint('Reached end time (current position: '\
00225                             '{0}).'.format(self._l.pos))
00226                     self._set()
00227                     return RTC.RTC_OK, 0
00228                 # Read until past it - read one at a time to avoid huge memory
00229                 # spikes if the log contains large-sized data
00230                 while self._l.pos[1] <= now:
00231                     if self._max > -1 and execed >= self._max:
00232                         self._vprint(
00233                                 'Reached maximum number of results to play.')
00234                         self._set()
00235                         break
00236                     if self._end >= 0 and self._l.pos[1] > self._end:
00237                         self._vprint('Reached end time (current position: '\
00238                                 '{0}).'.format(self._l.pos))
00239                         self._set()
00240                         break
00241                     if not self._pub_log_item():
00242                         print >>sys.stderr, '{0}: End of log reached.'.format(
00243                                 os.path.basename(sys.argv[0]))
00244                         self._set()
00245                         result = RTC.RTC_ERROR
00246                         break
00247                     else:
00248                         execed += 1
00249         except:
00250             traceback.print_exc()
00251             return RTC.RTC_ERROR, 0
00252         return result, execed
00253 
00254     def _pub_log_item(self):
00255         # Read an item from the log file
00256         entries = self._l.read()
00257         if len(entries) == 0:
00258             return False # End of file
00259         index, ts, entry = entries[0]
00260         p_name, data = entry
00261         if p_name in self._ports:
00262             if not self._abs and self._ports[p_name].standard_type:
00263                 data.tm.sec += int(self._offset)
00264                 data.tm.nsec += int((self._offset % 1) * 1000000000)
00265             self._ports[p_name].port.write(data)
00266         return True
00267 
00268     def _vprint(self, text):
00269         if self._verb:
00270             print >>sys.stderr, text
00271 


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