simulation_new.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. import os
  2. import math
  3. import sys
  4. import pandas as pd
  5. import subprocess
  6. import time
  7. import multiprocessing # 导入进程模块
  8. from functools import partial # 导入偏函数
  9. import warnings
  10. warnings.filterwarnings("ignore")
  11. from openx import Scenario, change_CDATA
  12. from utils import get_coordinate_cow, get_map_name, reverse_gyb_gps
  13. class Batchrun:
  14. def __init__(self, path, keyFileName):
  15. """"初始化方法"""
  16. self.path = path
  17. self.keyFileName = keyFileName
  18. def getFile(self, path, keyFileName):
  19. '''
  20. 获得可以进行轨迹提取的所有片段文件夹路径
  21. Parameters
  22. ----------
  23. path : TYPE
  24. DESCRIPTION.
  25. Returns
  26. -------
  27. FileList : TYPE
  28. 可以进行轨迹提取的所有片段文件夹路径.
  29. '''
  30. files = os.listdir(path) # 得到文件夹下的所有文件,包含文件夹名称
  31. FileList = []
  32. if keyFileName not in files:
  33. for name in files:
  34. if os.path.isdir(path + '/' + name):
  35. FileList.extend(self.getFile(path + '/' + name, keyFileName)) # 回调函数,对所有子文件夹进行搜索
  36. else:
  37. FileList.append(path)
  38. FileList = list(set(FileList))
  39. return FileList
  40. def generateScenarios_raw(self, absPath, param):
  41. '''
  42. 原始自然驾驶场景还原
  43. '''
  44. # 读取自车数据
  45. posPath = os.path.join(absPath, 'pos.csv') # 用来生成场景中自车和他车的路径
  46. posdata = pd.read_csv(posPath)
  47. # 读取仿真地图数据
  48. offset_x_gyb = -446403.548
  49. offset_y_gyb = -4403799.286
  50. offset_x_thq = -456256.260152
  51. offset_y_thq = -4397809.886833
  52. offset_x_glyt = -457000
  53. offset_y_glyt = -4400000
  54. # offset_h = 90 # 初始headinga 和 VTD 有 90偏角
  55. offset_h = 0
  56. thqPath = '/root/rosmerge/resource/thq_path.csv'
  57. thqdata = pd.read_csv(thqPath)
  58. thqdata['posX'] -= offset_x_thq
  59. thqdata['posY'] -= offset_y_thq
  60. gybPath = '/root/rosmerge/resource/gybhl_path.csv'
  61. gybdata = pd.read_csv(gybPath)
  62. gybdata['posX'] -= offset_x_gyb
  63. gybdata['posY'] -= offset_y_gyb
  64. reverse_east, reverse_north = reverse_gyb_gps(gybdata)
  65. gybdata['East'] = reverse_east
  66. gybdata['North'] = reverse_north
  67. glytPath = '/root/rosmerge/resource/glyt_path.csv'
  68. glytdata = pd.read_csv(glytPath)
  69. glytdata['posX'] -= offset_x_glyt
  70. glytdata['posY'] -= offset_y_glyt
  71. init_x = posdata.iloc[0]['East']
  72. init_y = posdata.iloc[0]['North']
  73. map_id = get_map_name(init_x, init_y, thqdata, gybdata, glytdata)
  74. # 对感知数据进行后处理
  75. # 对公园北环路进行坐标转换
  76. if map_id == 0:
  77. offset_x = offset_x_thq
  78. offset_y = offset_y_thq
  79. elif map_id == 1:
  80. new_east, new_north = get_coordinate_cow(posdata)
  81. posdata['East'] = new_east
  82. posdata['North'] = new_north
  83. offset_x = offset_x_gyb
  84. offset_y = offset_y_gyb
  85. else:
  86. offset_x = offset_x_glyt
  87. offset_y = offset_y_glyt
  88. # 根据pos文件规范时间戳
  89. posdata['Time'] = posdata['Time'].apply(lambda x: (x // 100) * 100)
  90. # 绝对高程与相对高程的差值
  91. posdata['altitude'] = posdata['altitude'] - 9.1
  92. pos_ego = posdata.loc[posdata['ID'] == -1, ['Time', 'East', 'North', 'HeadingAngle', 'altitude', 'Type']]
  93. # pos_ego[['East', 'North']] = pos_ego.apply(get_coordinate_cow, axis=1)
  94. # pos_ego = posdata.loc[posdata['ID'] == -1, ['Time', 'position_x', 'position_y', 'HeadingAngle', 'Type']]
  95. pos_ego = pos_ego.reset_index(drop=True)
  96. # offset_x = -float(pos_ego.at[0, 'East']) # 初始East 设为0
  97. # offset_y = -float(pos_ego.at[0, 'North']) # 初始North 设为0
  98. start_time = pos_ego.at[0, 'Time']
  99. ego_points, gps_time, ego_type = Scenario.getXoscPosition(pos_ego, 'Time', 'East', 'North', 'HeadingAngle',
  100. 'altitude', 'Type', offset_x, offset_y, offset_h,
  101. start_time)
  102. # ego_points, gps_time, ego_type = Scenario.getXoscPosition(pos_ego, 'Time', 'position_x', 'position_y', 'HeadingAngle', 'Type', offset_x, offset_y, offset_h, start_time)
  103. # 读取目标数据
  104. # pos_obs = posdata[posdata['Type'] != 10] # 排除非目标物的物体
  105. # pos_obs = posdata[posdata['Type'] != 10] # 排除非目标物的物体
  106. posdata['Type'].replace([103, 10], 7, inplace=True)
  107. pos_obs = posdata.copy()
  108. pos_obs = pos_obs.loc[
  109. pos_obs['ID'] != -1, ['Time', 'ID', 'East', 'North', 'HeadingAngle', 'AbsVel', 'altitude', 'Type']]
  110. # pos_obs = pos_obs.loc[pos_obs['ID'] != -1, ['Time', 'ID', 'position_x', 'position_y', 'HeadingAngle', 'Type']]
  111. # !!!!自定义修改
  112. # pos_obs.loc[pos_obs['ID'] == 1200, 'type'] = 7
  113. # pos_obs.loc[pos_obs['ID'] == 1197, 'type'] = 7
  114. # pos_obs.loc[pos_obs['ID'] == 1200, 'position_x'] += 1
  115. # pos_obs.loc[pos_obs['ID'] == 1200, 'position_y'] -= 2
  116. # pos_obs.loc[pos_obs['ID'] == 1197, 'position_x'] += 1
  117. # pos_obs.loc[pos_obs['ID'] == 1197, 'position_y'] -= 1
  118. # pos_obs.loc[pos_obs['ID'] == 1203, 'type'] = 4
  119. # pos_obs.loc[pos_obs['ID'] == 1203, 'position_x'] = 456319
  120. # pos_obs.loc[pos_obs['ID'] == 1203, 'position_y'] = 4397979
  121. # pos_obs.loc[pos_obs['ID'] == 1203, 'HeadingAngle'] = 1
  122. # offset_h = 30
  123. # pos_obs.loc[pos_obs['ID'] == 1194, 'type'] = 7
  124. # pos_obs.loc[pos_obs['ID'] == 1188, 'type'] = 2
  125. # pos_obs.loc[pos_obs['ID'] == 1189, 'type'] = 2
  126. # pos_obs.loc[pos_obs['ID'] == 1195, 'type'] = 2
  127. # obsPath = os.path.join(absPath, 'obs.csv') # 用来筛选场景中不需要的他车
  128. # obsdata = pd.read_csv(obsPath)
  129. # obsdata = obsdata[(obsdata['ObjectPosY'] < 5) & (obsdata['ObjectPosY'] > -5) & (obsdata['ObjectPosX'] > -10) & (obsdata['ObjectPosX'] < 100)] # 排除车道线范围外且前向距离较远的目标物
  130. # idlist = obsdata['ObjectID'].tolist() # 筛选出符合条件的的目标物ID
  131. # pos_obs = pos_obs[(pos_obs['ID'].isin(idlist))]
  132. pos_obs = pos_obs.reset_index(drop=True)
  133. groups = pos_obs.groupby('ID')
  134. object_points = []
  135. for key, value in groups:
  136. if len(value) < 1:
  137. continue
  138. # value = smooth_1(value)
  139. object_points.append(
  140. Scenario.getXoscPosition(value, 'Time', 'East', 'North', 'HeadingAngle', 'altitude', 'Type', offset_x,
  141. offset_y, offset_h, start_time))
  142. # object_points.append(Scenario.getXoscPosition(value, 'Time', 'position_x', 'position_y', 'HeadingAngle', 'type', offset_x, offset_y, offset_h,start_time))
  143. ego_speed = 5
  144. period = math.ceil(gps_time[-1] - gps_time[0])
  145. work_mode = 0 # 0为CICV车端数据
  146. hour = int(absPath.split('/')[-1].split('-')[3])
  147. if hour + 8 >= 24:
  148. hour = hour - 16
  149. else:
  150. hour = hour + 8
  151. time_of_day = hour * 3600
  152. # 没有路灯防止天过暗
  153. if time_of_day >= 64800:
  154. time_of_day = 64800
  155. s = Scenario(ego_points, object_points, gps_time, ego_speed, work_mode, period, absPath, time_of_day, map_id)
  156. filename = absPath + '/simulation'
  157. print(filename)
  158. files = s.generate(filename)
  159. change_CDATA(files[0][0])
  160. print(files)
  161. # 生成osgb
  162. # osgbGenerator.formatTwo(filename)
  163. # 修改xosc路径
  164. # formatThree(filename)
  165. # # # 生成每个场景的描述文件 json
  166. # # getLabel(output_path, scenario_series['场景编号'], scenario_series['场景名称'])
  167. # 拷贝到vtd路径下
  168. # 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"))
  169. # if not os.path.exists(vtd_path):
  170. # os.makedirs(vtd_path)
  171. # os.system('cp '+ files[0][0] + ' ' + vtd_path + '/')
  172. def multiRun(self, path, param):
  173. files = self.getFile(path, self.keyFileName)
  174. print('程序开始,%s 个数据包' % len(files))
  175. t1 = time.time()
  176. # 无参数时,使用所有cpu核; 有参数时,使用CPU核数量为参数值
  177. pool = multiprocessing.Pool(processes=10)
  178. pfunc = partial(self.generateScenarios_raw, param)
  179. pool.map(pfunc, files)
  180. # 调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束
  181. pool.close()
  182. pool.join()
  183. t2 = time.time()
  184. print("程序结束,并行执行时间:%s s" % int(t2 - t1))
  185. def batchRun(self, path, param):
  186. files = self.getFile(path, self.keyFileName)
  187. print('程序开始,%s 个数据包' % len(files))
  188. for di, absPath in enumerate(sorted(files)):
  189. print(absPath)
  190. # try:
  191. self.generateScenarios_raw(absPath, param)
  192. # except:
  193. # print('Augmentation failed!!!!')
  194. # error = {'time':datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3],'traceback':traceback.format_exc()}
  195. # with open('error.log','a+') as f:
  196. # json.dump(error, f, indent=4)
  197. # f.write('\n')
  198. # print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
  199. return None
  200. def GenerateVideo(self, root_path):
  201. # 批量生成视频
  202. imagelist = self.getFile(root_path, 'image')
  203. for item in imagelist:
  204. strs = item.split('/')
  205. respath = os.path.join(item, "video.mp4")
  206. # respath = os.path.join(res_path,strs[-3],strs[-2],"video.mp4")
  207. print('---------------------')
  208. # os.makedirs(os.path.join(res_path,strs[-3],strs[-2]))
  209. command = "ffmpeg -f image2 -r 10 -pattern_type glob -i '" + item + "/image/*.jpg" + "' -y '" + respath + "'"
  210. print(command)
  211. process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  212. process.wait()
  213. if __name__ == "__main__":
  214. rootPath = sys.argv[1] # 跟车
  215. # 生成场景
  216. a = Batchrun(rootPath, "pos.csv")
  217. a.batchRun(rootPath, 0) # 0为占位参数
  218. # a.multiRun(rootPath, 0)
  219. # 生成视频
  220. # a.GenerateVideo(rootPath)
  221. # -*-ing:utf-8-*-