00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 import roslib
00039 import rosbag
00040 import diagnostic_msgs.msg
00041 import time, sys, os
00042 import operator, tempfile, subprocess
00043
00044
00045
00046
00047 class LogExporter:
00048
00049
00050 def __init__(self, output_dir, logfile):
00051 self._temp = False
00052 self._stats = {}
00053 self.logfile = logfile
00054
00055 self.output_dir = output_dir
00056 if self.output_dir is None:
00057 self.output_dir = tempfile.mkdtemp()
00058 self._temp = True
00059
00060 if not os.path.isdir(self.output_dir):
00061 os.makedirs(self.output_dir)
00062
00063
00064 def remove_files(self):
00065 for name in self._stats:
00066 file = self._stats[name]['file_name']
00067 os.remove(file)
00068 if self._temp:
00069 os.rmdir(self.output_dir)
00070
00071
00072
00073 def get_filename(self, name):
00074 if not self._stats.has_key(name):
00075 return None
00076 return self._stats[name]['file_name']
00077
00078
00079 def process_log(self):
00080 bag = rosbag.Bag(self.logfile)
00081 for (topic, msg, t) in bag.read_messages():
00082 self._update(topic, msg)
00083
00084
00085 def _update(self, topic, msg):
00086 if (not (topic == '/diagnostics')):
00087 print "Discarding message on topic: %s" % topic
00088 return
00089
00090 t = time.localtime(float(str(msg.header.stamp)) / 1000000000.0)
00091
00092 for status in msg.status:
00093 name = status.name
00094
00095 if (not self._stats.has_key(name)):
00096 self._stats[name] = {}
00097
00098 fields = {}
00099 for index, s in enumerate(status.values):
00100 fields[s.key] = index
00101
00102 self._stats[name]['fields'] = fields
00103
00104 self._stats[name]['level'] = status.level
00105 self._stats[name]['message'] = status.message
00106 self._stats[name]['hardware_id'] = status.hardware_id
00107
00108
00109 datafile, tmp_name = tempfile.mkstemp()
00110 self._stats[name]['data_file'] = os.fdopen(datafile, 'w')
00111 self._stats[name]['data_name'] = tmp_name
00112
00113
00114
00115 if (not [s.key for s in status.values] == self._stats[name]['fields'].keys()):
00116 for s in status.values:
00117 if not self._stats[name]['fields'].has_key(s.key):
00118 self._stats[name]['fields'][s.key] = len(self._stats[name]['fields'])
00119
00120
00121
00122
00123 vals = []
00124 for key, val in self._stats[name]['fields'].iteritems():
00125 vals.append('')
00126 for s in status.values:
00127 vals[self._stats[name]['fields'][s.key]] = s.value.replace('\n',' ').replace(',',' ')
00128
00129 msg = status.message.replace(',',' ').strip()
00130 hw_id = status.hardware_id.replace(',', ' ')
00131
00132 self._stats[name]['data_file'].write(','.join([time.strftime("%Y/%m/%d %H:%M:%S", t)] +
00133 [str(status.level), msg, hw_id] + vals) + '\n')
00134
00135
00136 def finish_logfile(self):
00137 for name in self._stats:
00138
00139 field_dict = sorted(self._stats[name]['fields'].iteritems(), key=operator.itemgetter(1))
00140 fields = map(operator.itemgetter(0), field_dict)
00141
00142 header_line = ','.join(['Timestamp'] + ['Level', 'Message', 'Hardware ID'] +
00143 [f.replace(',','').replace('\n', ' ') for f in fields]) + '\n'
00144
00145 file_name = os.path.join(self.output_dir, name.replace(' ', '_').replace('(', '').replace(')', '').replace('/', '__').replace('.', '').replace('#', '') + '.csv')
00146
00147 output_file = file(file_name, 'w')
00148 output_file.write(header_line)
00149 output_file.close()
00150
00151
00152 self._stats[name]['data_file'].close()
00153
00154
00155 subprocess.call("cat %s >> %s" % (self._stats[name]['data_name'], file_name), shell=True)
00156
00157 os.remove(self._stats[name]['data_name'])
00158
00159 self._stats[name]['file_name'] = file_name
00160