jiqiren_outdoor.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. import os
  2. import math
  3. import numpy as np
  4. import pandas as pd
  5. import subprocess
  6. import time
  7. import multiprocessing
  8. from pyproj import CRS, Transformer
  9. from scipy.spatial.transform import Rotation as R
  10. from scipy.signal import savgol_filter
  11. from datetime import datetime
  12. import xml.etree.ElementTree as ET
  13. import sys
  14. import re
  15. import json
  16. # 导入进程模块
  17. from functools import partial # 导入偏函数
  18. from openx_outdoor import Scenario, formatThree, formatTwo, change_CDATA
  19. import warnings
  20. warnings.filterwarnings("ignore")
  21. xodr_list = ['/mnt/disk001/simulation_outdoor/thq_1116.xodr', '/mnt/disk001/simulation_outdoor/anqing.xodr']
  22. map_engine = '/mnt/disk001/dcl_data_process/src/python3/pjibot_outdoor/a.out'
  23. class Batchrun:
  24. def __init__(self, path, keyFileName):
  25. """"初始化方法"""
  26. self.path = path
  27. self.keyFileName = keyFileName
  28. def getFile(self, path, keyFileName):
  29. '''
  30. 获得可以进行轨迹提取的所有片段文件夹路径
  31. Parameters
  32. ----------
  33. path : TYPE
  34. DESCRIPTION.
  35. Returns
  36. -------
  37. FileList : TYPE
  38. 可以进行轨迹提取的所有片段文件夹路径.
  39. '''
  40. files = os.listdir(path) # 得到文件夹下的所有文件,包含文件夹名称
  41. FileList = []
  42. if keyFileName not in files:
  43. for name in files:
  44. if os.path.isdir(path + '/' + name):
  45. FileList.extend(self.getFile(path + '/' + name, keyFileName)) # 回调函数,对所有子文件夹进行搜索
  46. else:
  47. FileList.append(path)
  48. FileList = list(set(FileList))
  49. return FileList
  50. # 自定义一个函数来过滤行
  51. def generateScenarios_raw(self, absPath, vehicle_type):
  52. '''
  53. 原始自然驾驶场景还原
  54. '''
  55. # 读取自车数据
  56. posObs = os.path.join(absPath, 'objects_pji.csv') # 用来生成场景中障碍物的路径
  57. posEgo = os.path.join(absPath, "ego_pji.csv")
  58. posdata_obs = pd.read_csv(posObs)
  59. posdata_ego = pd.read_csv(posEgo)
  60. timestamp_s = posdata_ego['Time'].iloc[0] / 1000
  61. dt_object = datetime.fromtimestamp(timestamp_s)
  62. hour = dt_object.hour - 8
  63. posdata_obs = posdata_obs.drop('Time', axis=1)
  64. posdata_ego = posdata_ego.drop('Time', axis=1)
  65. posdata_obs.rename(columns={'posX': 'pos_x'}, inplace=True)
  66. posdata_obs.rename(columns={'posY': 'pos_y'}, inplace=True)
  67. posdata_obs.rename(columns={'posH': 'HeadingAngle'}, inplace=True)
  68. posdata_obs.rename(columns={'speedX': 'AbsVel'}, inplace=True)
  69. posdata_obs.rename(columns={'playerId': 'ID'}, inplace=True)
  70. posdata_ego.rename(columns={'posX': 'pos_x'}, inplace=True)
  71. posdata_ego.rename(columns={'posY': 'pos_y'}, inplace=True)
  72. posdata_ego.rename(columns={'posH': 'HeadingAngle'}, inplace=True)
  73. def get_road_info(command):
  74. # 使用 subprocess.run 运行命令
  75. result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
  76. # 获取命令的输出
  77. output = result.stdout if result.stdout else result.stderr
  78. if output == "not found\n":
  79. return "不在道路范围"
  80. # 使用正则表达式提取数字
  81. track_match = re.search(r'track\s*=\s*(-?\d+)', output)
  82. lane_match = re.search(r'lane\s*=\s*(-?\d+)', output)
  83. offset_match = re.search(r'offset\s*=\s*(-?\d+\.?\d*)', output)
  84. h_match = re.search(r'h\s*=\s*(-?\d+\.?\d*)', output)
  85. # 如果匹配成功,提取对应的值
  86. track_id = int(track_match.group(1)) if track_match else None
  87. lane_id = int(lane_match.group(1)) if lane_match else None
  88. offset = float(offset_match.group(1)) if offset_match else None
  89. h_value = float(h_match.group(1)) if h_match else None
  90. return track_id, lane_id, offset, h_value
  91. def get_map_id(df):
  92. # 太和桥园区经纬度
  93. taiheqiao_latitude = 39.7286896
  94. taiheqiao_longitude = 116.4885025
  95. # 安庆经纬度
  96. anqing_latitude = 30.5585070
  97. anqing_longitude = 117.1850840
  98. points = [(taiheqiao_latitude, taiheqiao_longitude), (anqing_latitude, anqing_longitude)]
  99. if len(df.loc[(df['latitude'] != 0) & (df['longitude'] != 0), 'latitude']) == 0:
  100. nearest_index = 0
  101. else:
  102. cur_latitude = df.loc[(df['latitude'] != 0) & (df['longitude'] != 0), 'latitude'].iloc[0]
  103. cur_longitude = df.loc[(df['latitude'] != 0) & (df['longitude'] != 0), 'longitude'].iloc[0]
  104. # Calculate distances to each point
  105. distances = []
  106. for lat, lon in points:
  107. distance = np.sqrt((lon - cur_longitude) ** 2 + (lat - cur_latitude) ** 2)
  108. distances.append(distance)
  109. # Find the index of the nearest point
  110. nearest_index = np.argmin(distances)
  111. return nearest_index
  112. def trans_pos(posdata, map_id):
  113. theta_dict = {0:1.4, 1: 1.055}
  114. trans_input = {0: (39.7286896, 116.4885025), 1: (30.5585070, 117.1850840)}
  115. trans_utm = {0: (456256.260152, 4397809.886833), 1: (517696.8132810, 3380770.294203)}
  116. transformer = Transformer.from_crs("epsg:4326", "epsg:32650")
  117. utm50n_x1, utm50n_y1 = transformer.transform(trans_input[map_id][0], trans_input[map_id][1])
  118. translation = np.array([utm50n_x1 - trans_utm[map_id][0], utm50n_y1 - trans_utm[map_id][1]])
  119. rotation_matrix = R.from_euler('z', theta_dict[map_id]).as_matrix()
  120. # 提取原始坐标
  121. original_positions = posdata[['pos_x', 'pos_y']].values
  122. # 应用旋转和平移
  123. rotated_positions =original_positions @ rotation_matrix[:2,:2].T # 只应用 2D 旋转
  124. rotated_positions += translation
  125. # 更新 posdata
  126. posdata['pos_x'] = rotated_positions[:, 0]
  127. posdata['pos_y'] = rotated_positions[:, 1]
  128. posdata['HeadingAngle'] += theta_dict[map_id]
  129. return posdata
  130. map_id = get_map_id(posdata_ego)
  131. # map_id = 0
  132. posdata_ego = trans_pos(posdata_ego, map_id)
  133. ego_init_x = posdata_ego['pos_x'].iloc[0]
  134. ego_init_y = posdata_ego['pos_y'].iloc[0]
  135. # 检查自车起始位置是否在地图外,如果在地图外抛出错误信息
  136. command = [
  137. map_engine,
  138. xodr_list[map_id],
  139. f'{ego_init_x}',
  140. f'{ego_init_y}'
  141. ]
  142. if get_road_info(command) == "不在道路范围":
  143. # 定义日志文件路径
  144. log_file_path = os.path.join(absPath, "output.json") # 日志文件存储在 rootPath 下
  145. # 写入错误信息数组
  146. error_message = ["不在道路范围"]
  147. with open(log_file_path, "w") as log_file:
  148. json.dump(error_message, log_file, ensure_ascii=False) # 使用 json.dump 写入数组格式
  149. print(f"自车位置不在道路范围,已记录到 {log_file_path}")
  150. # 终止程序运行
  151. sys.exit()
  152. posdata_obs['simTime'] = np.round(posdata_obs['simTime'], decimals=1)
  153. posdata_ego['simTime'] = np.round(posdata_ego['simTime'], decimals=1)
  154. # 对障碍物数据进行处理
  155. def filter_rows(group):
  156. # 首先对x进行排序
  157. group = group.sort_values(by='pos_x')
  158. # 算出差值
  159. diffs = group['pos_x'].diff().fillna(1) # 我们填充1(或任何大于0.2的值),确保第一行不被标记为删除
  160. # 标记差值小于0.2的行为True
  161. group = group[diffs >= 0.2]
  162. return group
  163. def interpolate_missing_values(df):
  164. # 1. 生成一个完整的以0.1秒为间隔的simTime
  165. new_simTime = np.arange(df['simTime'].min(), df['simTime'].max() + 0.1, 0.1)
  166. # 2. 创建新的DataFrame,并与原始DataFrame对齐
  167. new_df = pd.DataFrame(new_simTime, columns=['simTime'])
  168. new_df['simTime'] = np.round(new_df['simTime'], decimals=1)
  169. # 3. 将原始DataFrame与新simTime进行合并
  170. new_df = pd.merge(new_df, df, on='simTime', how='left')
  171. # 4. 对列进行插值(线性插值)
  172. new_df = new_df.interpolate(method='linear')
  173. return new_df
  174. posdata_obs = trans_pos(posdata_obs, map_id)
  175. posdata_obs = posdata_obs.groupby(['simTime', 'pos_y'], group_keys=False).apply(filter_rows)
  176. posdata_obs.reset_index(drop=True, inplace=True)
  177. posdata_obs['Type'] = 10
  178. # start_time_ego = posdata_ego['Time'].iloc[0]
  179. # posdata_ego['Time'] = posdata_ego['Time'] - start_time_ego
  180. # posdata_ego['Time'] = (posdata_ego['Time'] - (posdata_ego['Time'] % 100)) / 1000
  181. posdata_ego = posdata_ego.drop_duplicates(subset='simTime', keep='first')
  182. posdata_ego = interpolate_missing_values(posdata_ego)
  183. posdata_ego['Type'] = 2
  184. posdata_ego['ID'] = -1
  185. # posdata_ego['pos_x'] = posdata_ego['pos_x'] - 88.96626
  186. # posdata_ego['pos_y'] = posdata_ego['pos_y'] - 40.55367
  187. # posdata_ego['HeadingAngle'] -= 90
  188. posdata_ego['HeadingAngle'] = np.degrees(posdata_ego['HeadingAngle'])
  189. # 将负角度值转换为正值
  190. while (posdata_ego['HeadingAngle'] < 0).any():
  191. # 将负角度值转换为正值
  192. posdata_ego['HeadingAngle'] = posdata_ego['HeadingAngle'].apply(lambda x: x + 360 if x < 0 else x)
  193. # posdata_obs['ID'] = range(len(posdata_obs))
  194. posdata_obs = posdata_obs[['simTime', 'pos_x', 'pos_y', 'HeadingAngle', 'ID', 'Type', 'AbsVel']]
  195. # posdata_obs['Time'] = posdata_obs['Time'].rank(method='dense') - 1
  196. # posdata_obs['Time'] = posdata_obs['Time'] * 1
  197. # 获取唯一时间点
  198. # unique_times = posdata_obs['simTime'].unique()
  199. #
  200. # new_rows = [] # 用于存储新行的列表
  201. #
  202. # # 遍历唯一时间点的索引,留一个空位以检查“下一组”
  203. # for i in range(len(unique_times) - 1):
  204. # current_time = unique_times[i]
  205. # next_time = unique_times[i + 1]
  206. # time_diff = next_time - current_time # 计算时间差
  207. #
  208. # # 获取当前时间点的所有行
  209. # current_group = posdata_obs[posdata_obs['simTime'] == current_time]
  210. #
  211. # # 为当前组基于时间差生成新行
  212. # # 时间差一半的新行
  213. # half_time_diff_rows = current_group.copy()
  214. # half_time_diff_rows['simTime'] = current_time + time_diff / 2
  215. #
  216. # # 与下一组时间相同的新行(保留其他数据不变)
  217. # same_time_diff_rows = current_group.copy()
  218. # same_time_diff_rows['simTime'] = next_time
  219. #
  220. # # 收集新行
  221. # new_rows.append(half_time_diff_rows)
  222. # new_rows.append(same_time_diff_rows)
  223. #
  224. # # 将新行添加到原始DataFrame
  225. # new_rows_df = pd.concat(new_rows, ignore_index=True)
  226. # posdata_obs = pd.concat([posdata_obs, new_rows_df], ignore_index=True).sort_values(by='simTime').reset_index(
  227. # drop=True)
  228. posdata = pd.concat([posdata_obs, posdata_ego], ignore_index=True)
  229. posdata = posdata.sort_values(by='simTime')
  230. altitude_dict = {0: 19.27, 1: 8.48332}
  231. posdata['altitude'] = altitude_dict[map_id]
  232. posdata['AbsVel'] = 0
  233. pos_ego = posdata.loc[posdata['ID'] == -1, ['simTime', 'pos_x', 'pos_y', 'HeadingAngle', 'altitude', 'Type']]
  234. pos_ego = pos_ego.reset_index(drop=True)
  235. # offset_x = -float(pos_ego.at[0, 'East']) # 初始East 设为0
  236. # offset_y = -float(pos_ego.at[0, 'North']) # 初始North 设为0
  237. start_time = pos_ego.at[0, 'simTime']
  238. ego_points, gps_time, ego_type = Scenario.getXoscPosition(pos_ego, 'simTime', 'pos_x', 'pos_y', 'HeadingAngle',
  239. 'altitude', 'Type', 0, 0, 0, start_time)
  240. # 读取目标数据
  241. pos_obs = posdata[posdata['Type'] != 100] # 排除非目标物的物体
  242. # pos_obs = posdata[posdata['Type'] != 10] # 排除非目标物的物体
  243. pos_obs['Type'].replace([103, 10], 7, inplace=True)
  244. pos_obs = pos_obs.loc[
  245. pos_obs['ID'] != -1, ['simTime', 'ID', 'pos_x', 'pos_y', 'HeadingAngle', 'AbsVel', 'altitude', 'Type']]
  246. pos_obs = pos_obs.reset_index(drop=True)
  247. # def calculate_heading_angle(group):
  248. # start_idx = 0
  249. # length = len(group)
  250. # prev_heading_angle = None # 用于存储上一个计算的航向角
  251. #
  252. # while start_idx < length:
  253. # start_pos_x, start_pos_y = group.iloc[start_idx]['pos_x'], group.iloc[start_idx]['pos_y']
  254. #
  255. # # 找到与当前帧距离超过1米的帧
  256. # for i in range(start_idx + 1, length):
  257. # current_pos_x, current_pos_y = group.iloc[i]['pos_x'], group.iloc[i]['pos_y']
  258. # distance = np.sqrt((current_pos_x - start_pos_x) ** 2 + (current_pos_y - start_pos_y) ** 2)
  259. #
  260. # if distance >= 1:
  261. # # 计算航向角
  262. # heading_angle = np.degrees(np.arctan2(current_pos_y - start_pos_y, current_pos_x - start_pos_x))
  263. #
  264. # # 检查航向角与前一个航向角的差值
  265. # if prev_heading_angle is not None:
  266. # angle_diff = np.abs(heading_angle - prev_heading_angle)
  267. # if angle_diff > 180:
  268. # angle_diff = 360 - angle_diff
  269. #
  270. # if angle_diff > 20:
  271. # # 如果航向角差值大于25度,跳过当前点
  272. # continue
  273. #
  274. # # 将 start_idx 到 i 之间的航向角设置为 heading_angle
  275. # group.iloc[start_idx:i, group.columns.get_loc('HeadingAngle')] = heading_angle
  276. # prev_heading_angle = heading_angle
  277. # start_idx = i
  278. # break
  279. # else:
  280. # # 如果没有找到超过1米的距离,使用最后一帧的数据计算航向角
  281. # last_pos_x, last_pos_y = group.iloc[-1]['pos_x'], group.iloc[-1]['pos_y']
  282. # heading_angle = np.degrees(np.arctan2(last_pos_y - start_pos_y, last_pos_x - start_pos_x))
  283. #
  284. # # 检查航向角与前一个航向角的差值
  285. # if prev_heading_angle is not None:
  286. # angle_diff = np.abs(heading_angle - prev_heading_angle)
  287. # if angle_diff > 180:
  288. # angle_diff = 360 - angle_diff
  289. #
  290. # if angle_diff <= 20:
  291. # group.iloc[start_idx:length - 1, group.columns.get_loc('HeadingAngle')] = heading_angle
  292. # else:
  293. # # 如果差值大于25度,跳过最后的点
  294. # group.iloc[start_idx:length - 1, group.columns.get_loc('HeadingAngle')] = prev_heading_angle
  295. # else:
  296. # group.iloc[start_idx:length - 1, group.columns.get_loc('HeadingAngle')] = heading_angle
  297. #
  298. # break
  299. #
  300. # # 确保最后一行的航向角等于倒数第二行
  301. # if length > 1:
  302. # group.iloc[-1, group.columns.get_loc('HeadingAngle')] = group.iloc[-2]['HeadingAngle']
  303. #
  304. # return group
  305. def calculate_heading_angle(group):
  306. start_idx = 0
  307. length = len(group)
  308. prev_heading_angle = None # 用于存储上一个计算的航向角
  309. while start_idx < length:
  310. start_pos_x, start_pos_y = group.iloc[start_idx]['pos_x'], group.iloc[start_idx]['pos_y']
  311. # 找到与当前帧距离超过1米的帧
  312. for i in range(start_idx + 1, length):
  313. current_pos_x, current_pos_y = group.iloc[i]['pos_x'], group.iloc[i]['pos_y']
  314. distance = np.sqrt((current_pos_x - start_pos_x) ** 2 + (current_pos_y - start_pos_y) ** 2)
  315. if distance >= 0.5:
  316. # 计算航向角
  317. heading_angle = np.degrees(np.arctan2(current_pos_y - start_pos_y, current_pos_x - start_pos_x))
  318. # 检查航向角与前一个航向角的差值
  319. if prev_heading_angle is not None:
  320. angle_diff = np.abs(heading_angle - prev_heading_angle)
  321. if angle_diff > 180:
  322. if heading_angle < 0:
  323. heading_angle += 360
  324. else:
  325. heading_angle -= 360
  326. angle_diff = 360 - angle_diff
  327. if angle_diff > 30:
  328. # 如果航向角差值大于30度,跳过当前点
  329. continue
  330. # 将 start_idx 到 i 之间的航向角设置为 heading_angle
  331. group.iloc[start_idx:i, group.columns.get_loc('HeadingAngle')] = heading_angle
  332. prev_heading_angle = heading_angle
  333. start_idx = i
  334. break
  335. else:
  336. # 如果没有找到超过1米的距离,使用最后一帧的数据计算航向角
  337. last_pos_x, last_pos_y = group.iloc[-1]['pos_x'], group.iloc[-1]['pos_y']
  338. heading_angle = np.degrees(np.arctan2(last_pos_y - start_pos_y, last_pos_x - start_pos_x))
  339. # 检查航向角与前一个航向角的差值
  340. if prev_heading_angle is not None:
  341. angle_diff = np.abs(heading_angle - prev_heading_angle)
  342. if angle_diff > 180:
  343. if heading_angle < 0:
  344. heading_angle += angle_diff
  345. else:
  346. heading_angle -= angle_diff
  347. angle_diff = 360 - angle_diff
  348. if angle_diff <= 30:
  349. group.iloc[start_idx:length - 1, group.columns.get_loc('HeadingAngle')] = heading_angle
  350. else:
  351. # 如果差值大于20度,跳过最后的点
  352. group.iloc[start_idx:length - 1, group.columns.get_loc('HeadingAngle')] = prev_heading_angle
  353. else:
  354. group.iloc[start_idx:length - 1, group.columns.get_loc('HeadingAngle')] = group.iloc[0]['HeadingAngle']
  355. break
  356. # 确保最后一行的航向角等于倒数第二行
  357. if length > 1:
  358. group.iloc[-1, group.columns.get_loc('HeadingAngle')] = group.iloc[-2]['HeadingAngle']
  359. return group
  360. def apply_savgol(row, window_size, poly_order):
  361. if len(row) < window_size:
  362. return row
  363. else:
  364. return savgol_filter(row, window_size, poly_order)
  365. # 应用到分组数据
  366. pos_obs = pos_obs.groupby('ID').apply(calculate_heading_angle).reset_index(drop=True)
  367. # while (pos_obs['HeadingAngle'] < 0).any():
  368. # # 将负角度值转换为正值
  369. # pos_obs['HeadingAngle'] = pos_obs['HeadingAngle'].apply(lambda x: x + 360 if x < 0 else x)
  370. pos_obs['HeadingAngle'] = pos_obs.groupby('ID')['HeadingAngle'].transform(lambda x: apply_savgol(x, 45, 2))
  371. groups = pos_obs.groupby('ID')
  372. object_points = []
  373. for key, value in groups:
  374. if len(value) < 5:
  375. continue
  376. # value = smooth_1(value)
  377. object_points.append(
  378. Scenario.getXoscPosition(value, 'simTime', 'pos_x', 'pos_y', 'HeadingAngle', 'altitude', 'Type', 0, 0, 0,
  379. start_time))
  380. # object_points.append(Scenario.getXoscPosition(value, 'Time', 'position_x', 'position_y', 'HeadingAngle', 'type', offset_x, offset_y, offset_h,start_time))
  381. ego_speed = 5
  382. period = math.ceil(gps_time[-1] - gps_time[0])
  383. work_mode = 0 # 0为CICV车端数据
  384. if hour + 8 >= 24:
  385. hour = hour - 16
  386. else:
  387. hour = hour + 8
  388. time_of_day = hour * 3600
  389. # 没有路灯防止天过暗
  390. if time_of_day >= 64800:
  391. time_of_day = 64800
  392. s = Scenario(ego_points, object_points, gps_time, ego_speed, work_mode, period, absPath, 0, vehicle_type, map_id)
  393. filename = absPath + '/simulation'
  394. print(filename)
  395. files = s.generate(filename)
  396. change_CDATA(files[0][0])
  397. print(files)
  398. # dynamic_path = filename + '/simulation.xosc'
  399. # combine_xosc(dynamic_path, static_path)
  400. # print("完成xosc的合并")
  401. # 生成osgb
  402. # osgbGenerator.formatTwo(filename)
  403. # 修改xosc路径
  404. # formatThree(filename)
  405. # # # 生成每个场景的描述文件 json
  406. # # getLabel(output_path, scenario_series['场景编号'], scenario_series['场景名称'])
  407. # 拷贝到vtd路径下
  408. # vtd_path = os.path.join('/home/lxj/VIRES/VTD.2021.3/Data/Projects/Current/Scenarios/myScenario', datetime.now().strftime("%Y%m%d%H%M%S"))
  409. # if not os.path.exists(vtd_path):
  410. # os.makedirs(vtd_path)
  411. # os.system('cp '+ files[0][0] + ' ' + vtd_path + '/')
  412. def multiRun(self, path, param):
  413. files = self.getFile(path, self.keyFileName)
  414. print('程序开始,%s 个数据包' % len(files))
  415. t1 = time.time()
  416. # 无参数时,使用所有cpu核; 有参数时,使用CPU核数量为参数值
  417. pool = multiprocessing.Pool(processes=10)
  418. pfunc = partial(self.generateScenarios_raw, param)
  419. pool.map(pfunc, files)
  420. # 调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束
  421. pool.close()
  422. pool.join()
  423. t2 = time.time()
  424. print("程序结束,并行执行时间:%s s" % int(t2 - t1))
  425. def batchRun(self, path, param):
  426. files = self.getFile(path, self.keyFileName)
  427. print('程序开始,%s 个数据包' % len(files))
  428. for di, absPath in enumerate(sorted(files)):
  429. print(absPath)
  430. self.generateScenarios_raw(absPath, param)
  431. # except:
  432. # print('Augmentation failed!!!!')
  433. # error = {'time':datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3],'traceback':traceback.format_exc()}
  434. # with open('error.log','a+') as f:
  435. # json.dump(error, f, indent=4)
  436. # f.write('\n')
  437. # print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
  438. return None
  439. def GenerateVideo(self, root_path):
  440. # 批量生成视频
  441. imagelist = self.getFile(root_path, 'image')
  442. for item in imagelist:
  443. strs = item.split('/')
  444. respath = os.path.join(item, "video.mp4")
  445. # respath = os.path.join(res_path,strs[-3],strs[-2],"video.mp4")
  446. print('---------------------')
  447. # os.makedirs(os.path.join(res_path,strs[-3],strs[-2]))
  448. command = "ffmpeg -f image2 -r 10 -pattern_type glob -i '" + item + "/image/*.jpg" + "' -y '" + respath + "'"
  449. print(command)
  450. process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  451. process.wait()
  452. if __name__ == "__main__":
  453. # rootPath = "/media/hancheng/Simulation5/pujin/pujin_outdoor/11_22" # 跟车
  454. # vehicle_type = "0"
  455. rootPath = sys.argv[1]
  456. vehicle_type = sys.argv[2]
  457. # 生成场景
  458. a = Batchrun(rootPath, "ego_pji.csv")
  459. a.batchRun(rootPath, vehicle_type) # 0为占位参数
  460. # a.multiRun(rootPath, 0)
  461. # 生成视频
  462. # a.GenerateVideo(rootPath)