rosbag_always.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 import rospy
4 import time
5 import subprocess
6 import signal
7 import os
8 import sys
9 import argparse
10 import re
11 import shutil
12 try:
13  import colorama
14 except:
15  print "Please install colorama by pip install colorama"
16  sys.exit(1)
17 from colorama import Fore, Style
18 from jsk_topic_tools.master_util import isMasterAlive
19 
20 
21 def runROSBag(topics, size, save_dir):
22  """
23  run rosbag and return Popen object
24  """
25  cmd = 'roslaunch jsk_data rosbag_always_run_rosbag.launch'
26  formatted_topics = [t for t in topics.split(' ') if t]
27  args = cmd.split(' ') + ["TOPICS:=" + topics + ""] + ["SIZE:=" + size] + ["OUTPUT:=" + save_dir + '/rosbag']
28  print args
29  return subprocess.Popen(args)
30 
31 def parseBagFile(bag):
32  # bag file name is ...
33  # 'rosbag_YYYY-MM-DD-HH-mm-SS_i.bag'
34  regexp = 'rosbag_(\d\d\d\d)-(\d\d)-(\d\d)-(\d\d)-(\d\d)-(\d\d)_([\d]+).bag'
35  result = re.match(regexp, bag)
36  if not result:
37  return None
38  else:
39  return [result.group(f) for f in range(1, 8)]
40 
41 def mkdirForBag(root_dir, bag):
42  # mkdir like ${root_dir}/${YYYY}/${MM}/${DD}/${HH}
43  parse = parseBagFile(bag)
44  YYYY = parse[0]
45  MM = parse[1]
46  DD = parse[2]
47  HH = parse[3]
48  directory = os.path.join(root_dir, YYYY, MM, DD, HH)
49  if not os.path.exists(directory):
50  os.makedirs(directory)
51  return directory
52 
53 def moveBagFiles(save_dir, bags):
54  for bag in bags:
55  move_dir = mkdirForBag(save_dir, bag)
56  from_file = os.path.join(save_dir, bag)
57  to_file = os.path.join(move_dir, bag)
58  print 'moving file %s -> %s' % (from_file, to_file)
59  shutil.move(from_file, to_file)
60 
61 def watchFileSystem(save_dir, max_size):
62  files = os.listdir(save_dir)
63  target_bags = [f for f in files
64  if f.startswith('rosbag')
65  and f.endswith('.bag')]
66  moveBagFiles(save_dir, target_bags)
67  # check size of directory
68  checkDirectorySize(save_dir, int(max_size))
69 
70 def getDirectorySize(start_path = '.'):
71  "size unit is Mega bytes"
72  total_size = 0
73  for dirpath, dirnames, filenames in os.walk(start_path):
74  for f in filenames:
75  fp = os.path.join(dirpath, f)
76  try:
77  total_size += os.path.getsize(fp)
78  except:
79  pass
80  return total_size / 1000.0 / 1000.0
81 
83  parse = parseBagFile(os.path.basename(bag))
84  parse[len(parse) - 1] = str(int(parse[len(parse) - 1])).zfill(4)
85  concatenated_string = reduce(lambda x, y: x + y, parse)
86  return int(concatenated_string)
87 
88 def listBagsSortedByDate(save_dir):
89  bags = []
90  for dirpath, dirnames, filenames in os.walk(save_dir):
91  for f in filenames:
92  if f.startswith('rosbag') and (f.endswith('.bag') or f.endswith('.active')):
93  bags.append(os.path.join(dirpath, f))
94  return sorted(bags, key=keyFuncToSortBag)
95 
96 def removeOldFiles(save_dir, max_size, current_size):
97  files = listBagsSortedByDate(save_dir)
98  remove_size = current_size - max_size
99  for f in files:
100  the_size = os.path.getsize(f)
101  print Fore.GREEN + 'removing %s (%d)' % (f, the_size / 1000 / 1000) + Fore.RESET
102  os.remove(f)
103  # Send desktop notification
104  subprocess.check_output(['notify-send', "Removed %s (%d)" % (f, the_size / 1000 / 1000)])
105  remove_size = remove_size - the_size / 1000.0 / 1000.0
106  if remove_size < 0:
107  return
108 
109 def checkDirectorySize(save_dir, max_size):
110  size = getDirectorySize(save_dir)
111  # print 'current directory size is %fM (max is %dM)' % (size, int(max_size))
112  if size > max_size:
113  removeOldFiles(save_dir, max_size, size)
114 
115 g_rosbag_process = False
116 
117 def restartROSBag(topics, size, save_dir):
118  global g_rosbag_process
119  print 'Running rosbag...'
120  g_rosbag_process = runROSBag(topics, size, save_dir)
121 
123  output = subprocess.check_output(['ps', '--ppid=' + str(ppid), '--no-headers'])
124  for process_line in output.split('\n'):
125  strip_process_line = process_line.strip()
126  if strip_process_line:
127  pid = strip_process_line.split(' ')[0]
128  name = strip_process_line.split(' ')[-1]
129  print 'killing %s' % (name)
130  os.kill(int(pid), signal.SIGINT)
131 
133  global g_rosbag_process
134  if g_rosbag_process:
135  print 'Killing rosbag ...'
136  rosbag_pid = g_rosbag_process.pid
137  try:
138  killChildProcesses(rosbag_pid)
139  g_rosbag_process.send_signal(subprocess.signal.SIGINT)
140  except:
141  pass
142 
143 def main(topics, size, save_dir, max_size, rate = 1):
144  if not os.path.exists(save_dir):
145  os.makedirs(save_dir)
146  previous_master_state = None
147  try:
148  while True:
149  master_state = isMasterAlive()
150  if not master_state and previous_master_state:
151  print "kill rosbag"
152  killROSBag()
153  elif master_state and not previous_master_state:
154  print "restart rosbag"
155  restartROSBag(topics, size, save_dir)
156  watchFileSystem(save_dir, max_size)
157  previous_master_state = master_state
158  time.sleep(1.0 / rate)
159  except Exception, e:
160  time.sleep(1)
161  watchFileSystem(save_dir, max_size)
162  finally:
163  killROSBag()
164 
165 
166 
167 if __name__ == "__main__":
168  parser = argparse.ArgumentParser(description='rosbag record regardless of rosmaster status')
169  parser.add_argument('--topics', help="topics to record", required=True)
170  parser.add_argument('--size', help="size of each rosbag", required=True)
171  parser.add_argument('--save-dir', help="directory to store rosbag", required=True)
172  parser.add_argument('--max-size', help="maximum size of rosbags in save_dir", required=True, type=int)
173  args = parser.parse_args()
174  main(args.topics, args.size, args.save_dir, args.max_size)
def main(topics, size, save_dir, max_size, rate=1)
def parseBagFile(bag)
def killChildProcesses(ppid)
def listBagsSortedByDate(save_dir)
def checkDirectorySize(save_dir, max_size)
def removeOldFiles(save_dir, max_size, current_size)
def watchFileSystem(save_dir, max_size)
def moveBagFiles(save_dir, bags)
def restartROSBag(topics, size, save_dir)
def mkdirForBag(root_dir, bag)
def keyFuncToSortBag(bag)
def getDirectorySize(start_path='.')
def runROSBag(topics, size, save_dir)


jsk_data
Author(s):
autogenerated on Tue Feb 6 2018 03:45:36