simulation_new.py 11 KB

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