00001
00002
00003
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
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
00059
00060 meta = (start, self._port_specs)
00061
00062 if not self._fn:
00063 self._fn = 'rtlog_{0}.rtlog'.format(int(start))
00064
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
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
00084 self._set()
00085 if self._max > -1 and self._count >= self._max:
00086
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
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
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
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
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
00170 if self._start > 0:
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
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
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
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
00229
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
00256 entries = self._l.read()
00257 if len(entries) == 0:
00258 return False
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