主要内容

根据记录的车辆数据生成场景

这个例子展示了如何从记录的车辆数据生成虚拟驾驶场景。该场景是由GPS传感器记录的位置信息和激光雷达传感器处理的记录对象列表生成的。

概述

虚拟驾驶场景可用于从记录的车辆数据中重建真实的场景。这些虚拟场景使您能够可视化和研究原始场景。因为可以通过编程方式修改虚拟场景,所以在设计和评估自动驾驶系统时,也可以使用它们来合成场景变化。

在本例中,您将通过生成drivingScenario对象从测试(自我)车辆记录的数据和ASAM OpenDRIVE®文件。ASAM OpenDRIVE文件描述了数据被记录的区域的路网。记录的车辆数据包括:

  • GPS数据:包含自我载具在每个时间戳处的经纬度坐标的文本文件。

  • 激光雷达对象列表数据:文本文件,包含非自我行动者的数量和他们的中心相对于自我载体的位置,在每个时间戳。

  • 视频数据:由安装在自我车辆上的前置单眼摄影机录下的MP4文件。

要生成和模拟驾驶场景,请遵循以下步骤:

  1. 探索记录的车辆数据。

  2. 在驾驶场景中导入ASAM OpenDRIVE路网。

  3. 在驾驶场景中添加来自GPS的自我车辆数据。

  4. 从激光雷达对象列表中添加非自我角色到驾驶场景中。

  5. 模拟和可视化生成的场景。

下面的图表显示了在这个示例中如何使用记录的数据。注意,您从GPS、激光雷达对象列表和ASAM OpenDRIVE文件创建了驾驶场景。您可以使用相机数据来可视化原始场景,并将该数据与生成的场景进行比较。您还可以在地图上使用geoplayer

查看已记录车辆数据

自我车辆的位置是用UBlox GPS NEO M8N传感器捕捉到的。GPS传感器被放置在自我车辆的车顶中心。该数据保存在文本文件中EgoUrban.txt

非自我演员的位置是用距离为30米的Velodyne®VLP-16激光雷达传感器捕获的。VLP-16传感器被放置在自我车的车顶上,位置和高度避免传感器与自我车的车身相撞。在车辆上处理来自激光雷达传感器的点云,以检测物体及其相对于自我车辆的位置。该数据保存在文本文件中NonEgoUrban.txt

为了帮助理解最初的场景,记录了单目摄像机的视频作为参考。这个视频还可以用来直观地比较原始和生成的场景。这个录制的视频的预览保存在视频文件中urbanpreview.mp4.您可以从以下网站下载完整的视频文件在这里

生成本例中使用的城市交通场景的预览。

vidObj = VideoReader (“urbanpreview.mp4”);无花果=图;set(fig,Position=[0,0,800, 600]);movegui(图,“中心”);pnl = uipanel(图,位置=[0 0 1 1],...Title =“城市交通场景”);plt =轴(pnl);hasFrame(vidObj) vidFrame = readFrame(vidObj);图像(vidFrame、家长= plt);plt。可见=“关闭”;暂停(1 / vidObj.FrameRate);结束

虽然传感器覆盖区域可以在整个自我车辆周围定义,但这个示例只展示了前瞻场景。

在驾驶场景中导入ASAM OpenDRIVE路网

生成虚拟场景所需的路网数据开放地图®。OpenStreetMap数据文件被转换为ASAM OpenDRIVE文件并使用扩展名保存.xodr.使用roadNetwork函数将路网数据导入到驾驶场景中。

创建一个驾驶场景对象并将所需的ASAM OpenDRIVE道路网络导入到生成的场景中。

场景= drivingScenario;openDRIVEFile =“OpenDRIVEUrban.xodr”;roadNetwork(场景中,“OpenDRIVE”, openDRIVEFile);

在生成的场景中添加来自GPS的自我车辆数据

自我车辆的数据从GPS传感器收集,并存储为文本文件。文本文件由三列组成,用于存储自我载具的纬度、经度和时间戳值。使用helperGetEgoData函数将自我车辆数据从文本文件导入到MATLAB®工作区的结构中。该结构包含三个字段,指定纬度、经度和时间戳。

egoFile =“EgoUrban.txt”;egoData = helperGetEgoData (egoFile);

根据记录的GPS坐标计算自我飞行器的轨迹路径点。使用latlon2local函数将原始GPS坐标转换为本地自东自北向上的笛卡尔坐标。转换后的坐标定义了自我载体的轨迹路径点。

指定ASAM OpenDRIVE文件中数据来源的经纬度。这个点还将定义局部坐标系的原点。alt = 540.0印度海得拉巴的平均海拔
alt = 540
Origin = [17.425853702697903, 78.44939480188313, alt];%[纬度,隆,高度]指定自我车辆的经纬度。lat = egoData.lat;朗= egoData.lon;计算自我载具的路径点[X, Y, ~] = latlon2local(纬度、经度、alt、来源);egoWaypoints (: 1) = X;egoWaypoints (:, 2) = Y;

可视化自我交通工具的GPS路径使用geoplayer对象。

zoomLevel = 17;球员= geoplayer(纬度(1),经度(1)zoomLevel);plotRoute(纬度,经度);i = 1:size(lat,1) plotPosition(player,lat(i),lon(i));结束

使用helperComputeEgoData计算自我车辆在每个传感器数据时间戳处的速度和航向角度值。

[egoSpeed, egoAngle] = helperComputeEgoData (egoData, X, Y);

在驾驶场景中添加自我车辆。

自我=车辆(场景,ClassID = 1,名字=“自我”...长度= 3.6、宽= 1.55,高= 1.6,...网= driving.scenario.carMesh);

根据自我路径点和速度的计算集为自我载具创建一个轨迹。自我交通工具以指定的速度沿着轨道行驶。

轨迹(自我,egoWaypoints egoSpeed);

从激光雷达对象列表中添加非自我角色到生成的场景

非自我行为体数据从激光雷达传感器收集并存储为文本文件。文本文件由五列组成,用于存储演员id,x的位置,y的位置,z-position和时间戳值。使用helperGetNonEgoData函数将非自我行为者数据从文本文件导入到MATLAB®工作区的结构中。输出是一个包含三个字段的结构:

  1. ActorID—场景自定义的角色标识符,以正整数形式指定。

  2. 位置- - - - - -演员的位置,指定为[xyz】真正的向量。单位是米。

  3. 时间—传感器记录的时间戳。

nonEgoPosFile =“NonEgoUrban.txt”;nonEgoPropertiesFile =“NonEgoProperties.txt”;[nonEgoData, nonEgoProperties] =...helperGetNonEgoData (nonEgoPosFile nonEgoPropertiesFile);

使用helperComputeNonEgoData计算每个非自我行为人在每个时间戳上的轨迹路径点和速度。轨道路径点是相对于自我载体计算的。

演员=独特(nonEgoData (1) .ActorID);[nonEgoSpeed, nonEgoWaypoints] =...helperComputeNonEgoData (egoData...egoWaypoints、nonEgoData egoAngle);

根据非自我行动者的类ID确定其网格。

i = 1:尺寸(nonEgoProperties.ClassID, 1)开关nonEgoProperties.ClassID(我)情况下3 nonEgoProperties.Mesh(i,1) = driving.scenario.bicycleMesh;情况下2 nonEgoProperties.Mesh(i,1) = driving. scene . truckmesh;否则nonEgoProperties.Mesh(我,1)= driving.scenario.carMesh;结束结束

在驾驶场景中加入非自我的演员。您可以用适当的类ID、维度、颜色和网格填充非自我角色。根据计算出的行为者路径点和速度为非自我行为者创建轨迹。

i =1:size(actors,1) actor = vehicle(scenario,ClassID=1,...长度= nonEgoProperties.Length(我),...宽度= nonEgoProperties.Width(我),...身高= nonEgoProperties.Height(我),...PlotColor = nonEgoProperties.Color(我),...网= nonEgoProperties.Mesh (i));轨迹(演员,nonEgoWaypoints {}, nonEgoSpeed{我});结束

将导入生成的场景中的自我载体和非自我角色形象化。也可视化自我载具和非自我行为人的相应轨迹路径点。

创建一个自定义图形窗口并定义一个轴线对象无花果=图;set(fig,Position=[0,0,800, 600]);movegui(图,“中心”);hViewPnl = uipanel(图,位置=[0 0 1 1],...Title =“自我载体和演员”);hCarPlt =轴(hViewPnl);绘制生成的驾驶场景。情节(场景中,“父”, hCarPlt);轴([270 320 80 120]);传奇(“进口道路网”“道”“自我车辆”...“演员1”“演员2”“演员3”“演员4”“演员5”)传说(hCarPlt“boxoff”);

人物,情节(egoWaypoints (: 1), egoWaypoints (:, 2),...Color=[0 0.447 0.741],LineWidth=2)保持i = 1:尺寸(演员、1)情节(nonEgoWaypoints{我}(:1),...nonEgoWaypoints{我}(:,2),...颜色= nonEgoProperties.Color(我:),线宽= 2)结束轴(“紧”)包含(“X”(m)) ylabel (“Y (m)”)标题(计算自我载体和行动者轨迹)传说(“自我车辆”“演员1”“演员2”“演员3”...“演员4”“演员5”“位置”“最佳”)举行

模拟和可视化生成的场景

绘制场景和相应的追逐情节。运行模拟以可视化生成的驾驶场景。自我载体和非自我行为者遵循各自的轨迹。

创建一个自定义图形窗口来显示场景和追逐情节。figScene图(Name = =“驾驶场景”...标签=“ScenarioGenerationDemoDisplay”);set(figScene,Position=[0,0,1000, 400]);movegui (figScene“中心”);添加追逐情节hCarViewPanel = uipanel (figScene,...Position=[0.5 0 0.5 1],Title=“追逐相机视图”);hCarPlot =轴(hCarViewPanel);chasePlot(自我,父母= hCarPlot网格=“上”);添加生成的场景的俯视图hViewPanel = uipanel (figScene,...Position=[0 0 0.5 1],Title=“视图”);hCarPlot =轴(hViewPanel);chasePlot(自我,父母= hCarPlot网格=“上”...viewwheight =120, ViewPitch=90, ViewLocation=[0,0]);%运行模拟推进(场景)暂停(0.01)结束

导出到ASAM OpenSCENARIO

还可以将场景导出到ASAM OpenSCENARIO文件。

警告(“关闭”“开车:场景:ExportOpenScenarioODWarning”);出口(场景中,“OpenSCENARIO”“PlaybackScenarioExample.xosc”);警告(“上”“开车:场景:ExportOpenScenarioODWarning”);

ASAM OpenSCENARIO文件可以导入到其他工具中,以可视化添加使用相同的场景。

总结

这个例子展示了如何根据使用GPS和激光雷达传感器记录的车辆数据自动生成虚拟驾驶场景。

辅助函数

helperGetEgoData

此函数从文本文件读取自我载具数据并转换为结构。

函数[egoData] = helperGetEgoData (egoFile)从文本文件中读取自我车辆数据文件标识= fopen (egoFile);内容= textscan(文件标识,“% % f % f”);字段= {“纬度”“朗”“时间”};egoData = cell2struct(内容、领域、2);文件关闭(文件标识);结束

helperGetNonEgoData

这个函数读取经过处理的激光雷达数据和from文本文件中的非自我行动者属性。你可以把它转换成一个结构。处理后的激光雷达数据包含非自我行为者的位置信息,非自我行为者属性包含各自非自我行为者的类型、尺寸和颜色信息。

函数[nonEgoPos, nonEgoProperties] =...helperGetNonEgoData (nonEgoPosFile nonEgoPropertiesFile)从文本文件中读取经过处理的非自我行动者的激光雷达数据。fileID1 = fopen (nonEgoPosFile);内容= textscan (fileID1'%d %f %f %f %f');newcontent{1} ={1}的内容;Newcontent {2} = [content{2} content{3} content{4}];newcontent{3} ={5}内容;字段= {“ActorID”“位置”“时间”};nonEgoPos = cell2struct (newcontent字段2);文件关闭(fileID1);fileID2 = fopen (nonEgoPropertiesFile);内容= textscan (fileID2'%d %f %f %f %f %f');newcontent{1} ={1}的内容;newcontent{2} ={2}内容;newcontent{3} ={3}内容;newcontent{4} ={4}内容;Newcontent {5} = [content{5} content{6} content{7}];字段= {“ClassID”“长度”“宽度”“高度”“颜色”};nonEgoProperties = cell2struct (newcontent字段2);文件关闭(fileID2);结束

helperComputeEgoData

该函数根据轨道路径点和时间戳计算自我车辆的速度和航向角度。

函数[egoSpeed, egoAngle] =...helperComputeEgoData(egoData, X, Y) egoTime = egoData. time;timeDiff = diff (egoTime);点数= [X Y];差= diff(points, 1);距离=√(sum(difference .* difference, 2));egoSpeed =某种天体/ timeDiff;egoAngle =每股(diff (Y)。/ diff (X));egoAngle结束(+ 1)= egoAngle(结束);egoSpeed结束(+ 1)= egoSpeed(结束);结束

helperComputeNonEgoData

该函数根据轨迹路径点和时间戳计算每个非自我角色的速度和航向角度。速度和航向角度是相对于自我车辆计算的。

函数[nonEgoSpeed, nonEgoWaypoints] =...helperComputeNonEgoData (...(nonEgoData. actorid);numActors =大小(演员、1);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);difference = diff(actorWaypoints, 1);距离=√(sum(difference .* difference, 2));actorSpeed =某种天体/ timeDiff;actorSpeed结束(+ 1)= actorSpeed(结束);平滑非自我行动者的轨迹路径点。actorWaypoints = smoothdata (actorWaypoints,“sgolay”);存储每个非自我行为体计算的轨迹路径点和速度值。nonEgoWaypoints (i) = {actorWaypoints};nonEgoSpeed (i) = {actorSpeed '};结束结束

另请参阅

应用程序

功能

对象

相关的例子

更多关于

外部网站

Baidu
map