这个示例展示了如何从记录的车辆数据生成虚拟驾驶场景。该场景由GPS传感器记录的位置信息和激光雷达传感器处理的记录对象列表生成。
虚拟驾驶场景可用于根据记录的车辆数据重建真实场景。这些虚拟场景使您能够可视化和研究原始场景。因为您可以通过编程修改虚拟场景,所以您还可以在设计和评估自动驾驶系统时使用它们来合成场景变化。
在本例中,您通过生成drivingScenario
对象来自测试(ego)车辆和ASAM OpenDRIVE®文件记录的数据。ASAM opdrive文件描述了数据记录区域的道路网络。记录的车辆数据包括:
GPS数据:文本文件,包含ego车辆在每个时间戳的经纬度坐标。
激光雷达目标列表数据:文本文件,包含每个时间戳中非自我行为者的数量和他们的中心相对于自我载体的位置。
视频数据:从安装在自助式车辆上的正面单手套摄像头中录制的MP4文件。
要生成和模拟驾驶场景,您需要遵循以下步骤:
探索记录的车辆数据。
将ASAM opdrive道路网络导入驾驶场景。
将自我车辆数据从GPS添加到驾驶场景。
将非自我演员从LIDAR对象列表添加到驱动场景。
模拟和可视化生成的方案。
下图显示了如何在本示例中使用记录的数据。注意,您是从GPS、激光雷达对象列表和ASAM OpenDRIVE文件中创建驾驶场景的。您可以使用摄像机数据来可视化原始场景,并将该数据与生成的场景进行比较。您还可以在地图上可视化场景路线使用geoplayer
.
使用UBlox GPS NEO M8N传感器捕捉ego车辆的位置。GPS传感器被放置在“自我”汽车车顶的中央。该数据保存在文本文件中Egourban.txt.
.
使用Velodyne®VLP-16激光雷达传感器捕获非自助镜头的位置,范围为30米。将VLP-16传感器放置在自助式车辆的顶部,处于避免使传感器与自工载体的主体碰撞的位置和高度。来自LIDAR传感器的点云在车辆上处理以检测相对于自助载体的物体及其位置。该数据保存在文本文件中nonegourban.txt.
.
为了帮助理解最初的场景,我们记录了单目摄像机的视频作为参考。这个视频也可以用来视觉上比较原始和生成的场景。此录制视频的预览保存在视频文件中UrbanPreview.mp4.
.你可以下载完整的录像文件在这里.
生成此示例中使用的城市交通方案的预览。
vidObj = VideoReader (“urbanpreview.mp4”);无花果=图;集(图,“位置”,[0,0,800, 600]);movegui(图,'中央');pnl = uipanel(图,“位置”,[0 0 1 1],“标题”,“城市交通场景”);plt =轴(pnl);而hasFrame(vidObj) vidFrame = readFrame(vidObj);图像(vidFrame,“父”、plt);currAxes。可见='离开';暂停(1 / Vidobj.framerate);结束
虽然可以在整个自助车辆周围定义传感器覆盖区域,但该示例仅显示了前瞻性场景。
生成虚拟场景所需的路网数据来源于开放地图®。OpenStreetMap数据文件被转换为ASAM OpenDRIVE文件并以扩展名保存.xodr
.使用roadNetwork
命令,将此道路网络数据导入到驾驶场景中。
创建一个驾驶场景对象,将所需的ASAM opdrive路网导入生成的场景。
场景= drivingScenario;openDRIVEFile ='opendriveurban.xodr';Roadnetwork(情景,“OpenDRIVE”,opendrivefile);
从GPS传感器收集EGO车辆数据并作为文本文件存储。文本文件由三列组成,该列存储自助式车辆的纬度,经度和时间戳值。使用helperGetEgoData
函数将ego车辆数据从文本文件导入到MATLAB®工作空间中的一个结构中。该结构包含三个字段,分别指定纬度、经度和时间戳。
Egofile =“EgoUrban.txt”;egoData = helperGetEgoData (egoFile);
根据记录的GPS坐标计算ego车辆的轨迹路径点。使用latlon2local
将原始GPS坐标转换为当地东北笛卡尔坐标的功能。变换的坐标限定了自我车辆的轨迹航点。
%指定从ASAM opdrive文件的数据来源的纬度和经度。这个点也将定义本地坐标系的原点。alt = 540.0印度海得拉巴的平均海拔
ALT = 540.
来源= [17.425853702697903,78.44939480188313,ALT];%[纬度,lon,海拔]%指定自我车辆的经度和纬度lat = egoData.lat;朗= egoData.lon;%计算自我车辆的路径点[X, Y, ~] = latlon2local(纬度、经度、alt、来源);egoWaypoints (: 1) = X;egoWaypoints (:, 2) = Y;
想象自我车的GPS路径,用geoplayer
对象。
zoomlevel = 17;玩家= Geoplayer(LAT(1),Lon(1),Zoomlevel);PlotRoute(球员,拉特,Lon);为i = 1:长度(LAT)绘图(播放器,LAT(i),Lon(i));结束
使用helperComputeEgoData
计算每个传感器数据时间戳下自我飞行器的速度和航向角值。
[Egospeed,EGOANGLE] = HelpercompteeGodata(Egodata,X,Y);
将自我车辆添加到驾驶场景。
自我=车辆(场景中,“长度”,1,'宽度', 0.6,“高度”, 0.6);
从计算机的自我航点和速度从计算机集和速度创造一个轨迹。EGO车辆以指定速度遵循轨迹。
轨迹(自我,egoWaypoints egoSpeed);
非自我参与者数据从激光雷达传感器收集,并存储为文本文件。文本文件由5列组成,这些列存储了参与者id,x
- 留下,y
- 留下,z
-position和timestamp值。使用helperGetNonEgoData
从文本文件将非自我演员数据导入Matlab®工作区中的结构。输出是具有三个字段的结构:
ActorID
-场景定义的参与者标识符,指定为一个正整数。
位置- - - - - -
演员的位置,指定为[xyz】真正的向量。单位是米。
时间
—传感器记录的时间戳。
nonEgoFile =“NonEgoUrban.txt”;nonEgoData = helperGetNonEgoData (nonEgoFile);
使用Helpercomputenonegodata.
计算每个时间戳的轨迹航点和每个非自我演员的速度。轨迹航点相对于自助载体计算。
Actors =唯一(notgodata.actorid);[nonegospeed,notgowaypoints] = HelperComputenoneGodata(Egodata,egowaypoints,Notgodata,EGOAngle);
将非自我角色添加到驾驶场景中。从参与者路径点和速度的计算集为非自我参与者创建轨迹。
为i = 1:长度(演员)actor =车辆(方案,“长度”,1,'宽度', 0.6,“高度”, 0.6);轨迹(演员,NotGowayPoints {i},NotGospeed {i});结束
可视化您导入到生成场景中的自我载体和非自我参与者。同时可视化自我载体和非自我行动者的相应轨迹路径点。
%创建一个自定义图形窗口并定义一个轴对象无花果=图;集(图,“位置”,[0,0,800, 600]);movegui(图,'中央');hViewPnl = uipanel(图,“位置”,[0 0 1 1],“标题”,“自我载体和演员”);hCarPlt =轴(hViewPnl);%绘制生成的驾驶场景。情节(情景,“父”, hCarPlt);轴([270 320 80 120]);传奇(“进口道路网”,“道”,“自我车辆”,'演员1','演员2',“演员3”,“演员4”,“演员5”)传说(hCarPlt“boxoff”);
人物,情节(egoWaypoints (: 1), egoWaypoints (:, 2),“颜色”[0, 0.447 - 0.741),'行宽', 2)在cMValues = [0.85 0.325 0.098;0.929 0.694 0.125;0.494 0.184 0.556;为i = 1:长度(Actors)绘图(NONGOWayPoints {i}(:,1),NONGOWAYPOINTS {i}(:,2),“颜色”cMValues(我,:)'行宽'2)结束轴('紧的')包含(“X (m)”) ylabel (“Y (m)”) 标题('计算的自我车辆和演员轨迹') 传奇(“自我车辆”,'演员1','演员2',“演员3”,“演员4”,“演员5”,“位置”,“最佳”)举行从
绘制场景和相应的追逐图。运行模拟以可视化生成的驱动方案。自我车辆和非自我演员遵循各自的轨迹。
%创建一个自定义图形窗口来显示场景和追逐情节关闭所有;figScene =图(“名字”,“驾驶场景”,'标签',“ScenarioGenerationDemoDisplay”);集(figScene,“位置”,[0,0,1032,1032]);Movegui(Figscene,'中央');%添加了追逐图hcarviewpanel = Uipanel(FieScene,“位置”,[0.5 0 0.5 1],“标题”,“追逐相机视图”);hCarPlot =轴(hCarViewPanel);chasePlot(自我,“父”, hCarPlot);%添加生成的场景的顶部视图hviewpanel = Uipanel(FieScene,“位置”,[0 0 0.5 1],“标题”,顶视图的);hCarPlot =轴(hViewPanel);情节(情景,“父”, hCarPlot);%设置轴限制,只显示活动区域xMin = min (egoWaypoints (: 1));xMax = max (egoWaypoints (: 1));yMin = min (egoWaypoints (:, 2));yMax = max (egoWaypoints (:, 2));limit = [xMin xMax yMin yMax];轴(限制);%运行模拟而前进(方案)暂停(0.01)结束
这个例子展示了如何从GPS和激光雷达传感器记录的车辆数据自动生成虚拟驾驶场景。
helperGetEgoData
这个函数从文本文件中读取ego车辆数据并将其转换为结构。
函数[egoData] = helperGetEgoData (egoFile)从文本文件中读取ego车辆数据文件标识= fopen (egoFile);内容= textscan(文件标识,“% % f % f”);字段= {“纬度”,“朗”,“时间”};egoData = cell2struct(内容、领域、2);文件关闭(文件标识);结束
helperGetNonEgoData
这个函数从文本文件中读取处理过的激光雷达数据,并将其转换为结构。经过处理的激光雷达数据包含了关于非自我行为者的信息。
函数[nonEgoData] = helperGetNonEgoData (nonEgoFile)%从文本文件中读取非自我角色的激光雷达数据。fileid = fopen(notgofile);内容= textscan(文件标识,'%d %f %f %f');newcontent{1} ={1}的内容;Newcontent {2} = [content{2} content{3} content{4}];newcontent{3} ={5}内容;字段= {'actorid',“位置”,“时间”};nonEgoData = cell2struct (newcontent字段2);文件关闭(文件标识);结束
helperComputeEgoData
该函数根据弹道路径点和时间戳计算自我飞行器的速度和航向角。
函数[Egospeed,EGoAngle] = HelperComputeeGodata(Egodata,X,Y)Egotime = Egodata.time;timediff = diff(egotime);点= [x y];差异=差异(点,1);距离=√(sum(difference .* difference, 2));Egospeed =距离./timediff;eGoAngle = atan(差异(y)./ diff(x));eGogangle(终点+ 1)= eGoAngle(END);EGOSED(终点+ 1)= EGOSPEED(END);结束
Helpercomputenonegodata.
该函数根据轨迹航迹点和时间戳计算每个非自我行动者的速度和航向角。速度和航向角计算相对于自我车辆。
函数[nonEgoSpeed, nonEgoWaypoints] = helperComputeNonEgoData(egoData, egoWaypoints, nonEgoData, egoAngle) actors = unique(nonEgoData. actorid);numActors =长度(演员);nonEgoWaypoints = cell(numActors, 1);nonEgoSpeed = cell(numActors, 1);为i = 1:numActors id = actors(i);idx = ([nonEgoData找到。ActorID] = = id);actorXData = nonEgoData.Position (idx, 1);actorYData = nonEgoData.Position (idx 2);actorTime = nonEgoData.Time (idx);actorWaypoints = [0 0];计算非自我行动者的轨迹路径点[sharedTimeStamps, nonEgoIdx egoIdx] = (actorTime, egoData相交。时间,“稳定”);tempX = actorXData (nonEgoIdx);tempY = actorYData (nonEgoIdx);relativeX = -tempX .* cos(egoAngle(egoIdx)) + tempY .* sin(egoAngle(egoIdx));relativeY = - tempx .* sin(egoAngle(egoIdx)) - tempY .* cos(egoAngle(egoIdx));actorWaypoints(nonEgoIdx,1) = egoWaypoints(egoIdx,1) + relativeX;actorWaypoints(nonEgoIdx,2) = egoWaypoints(egoIdx,2) + relativeY;%计算非自我演员的速度值timeDiff = diff (sharedTimeStamps);差= diff(actorWaypoints, 1);距离=√(sum(difference .* difference, 2));actorSpeed =某种天体/ timeDiff;actorSpeed结束(+ 1)= actorSpeed(结束);平滑非自我行动者的轨迹点actorWaypoints = smoothdata (actorWaypoints,“sgolay”);%存储每个非自我行为者计算的轨迹路径点和速度值nonEgoWaypoints (i) = {actorWaypoints};nonEgoSpeed (i) = {actorSpeed '};结束结束