主要内容

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

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

概述

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

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

  • GPS数据:文本文件,包含ego车辆在每个时间戳的经纬度坐标。

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

  • 视频数据: MP4文件,由安装在ego车上的一个前向单目摄像机拍摄。

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

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

  2. 将ASAM opdrive道路网络导入驾驶场景。

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

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

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

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

探索车辆记录数据

使用UBlox GPS NEO M8N传感器捕捉ego车辆的位置。GPS传感器被放置在“自我”汽车车顶的中央。该数据保存在文本文件中EgoUrban.txt

使用Velodyne®VLP-16激光雷达传感器捕捉非自我角色的位置,距离为30米。在“ego”汽车的车顶上放置了VLP-16传感器,其位置和高度避免了传感器与车身的碰撞。对激光雷达传感器产生的点云在车辆上进行处理,以检测目标及其相对于自我车辆的位置。该数据保存在文本文件中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);结束

尽管传感器覆盖区域可以定义在整个ego车辆周围,但本示例仅展示了前瞻性场景。

将ASAM opdrive道路网络导入驾驶场景

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

创建一个驾驶场景对象,将所需的ASAM opdrive路网导入生成的场景。

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

在生成的场景中添加GPS中的Ego车辆数据

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

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

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

%指定从ASAM opdrive文件的数据来源的纬度和经度。这个点也将定义本地坐标系的原点。alt = 540.0印度海得拉巴的平均海拔
alt = 540
Origin = [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(纬度(1),经度(1)zoomLevel);plotRoute(纬度,经度);i = 1:length(lat) plotPosition(player,lat(i),lon(i));结束

使用helperComputeEgoData计算每个传感器数据时间戳下自我飞行器的速度和航向角值。

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

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

自我=车辆(场景中,“长度”, 1“宽度”, 0.6,“高度”, 0.6);

根据自我路径点和速度的计算集为自我飞行器创建一个轨迹。自我飞行器以指定的速度沿着轨道运行。

轨迹(自我,egoWaypoints egoSpeed);

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

非自我参与者数据从激光雷达传感器收集,并存储为文本文件。文本文件由5列组成,这些列存储了参与者id,x的位置,y的位置,z-position和timestamp值。使用helperGetNonEgoData函数将非自我actor数据从文本文件导入到MATLAB®工作空间中的结构中。输出是一个有三个字段的结构:

  1. ActorID-场景定义的参与者标识符,指定为一个正整数。

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

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

nonEgoFile =“NonEgoUrban.txt”;nonEgoData = helperGetNonEgoData (nonEgoFile);

使用helperComputeNonEgoData来计算轨迹路径点和每个非自我行动者在每个时间戳中的速度。计算相对于自我飞行器的轨迹路径点。

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

将非自我角色添加到驾驶场景中。从参与者路径点和速度的计算集为非自我参与者创建轨迹。

I = 1:长度(演员)演员=车辆(场景,“长度”, 1“宽度”, 0.6,“高度”, 0.6);轨迹(演员,nonEgoWaypoints {}, nonEgoSpeed{我});结束

可视化您导入到生成场景中的自我载体和非自我参与者。同时可视化自我载体和非自我行动者的相应轨迹路径点。

%创建一个自定义图形窗口并定义一个轴对象无花果=图;集(图,“位置”,[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:长度(演员)情节(nonEgoWaypoints{我}(:1),nonEgoWaypoints{我}(:,2),“颜色”cMValues(我,:)“线宽”, 2)结束轴(“紧”)包含(“X (m)”) ylabel (“Y (m)”)标题(“计算自我车辆和行动者轨迹”)传说(“自我车辆”“演员1”《演员2》“演员3”“演员4”“演员5”“位置”“最佳”)举行

模拟和可视化生成的场景

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

%创建一个自定义图形窗口来显示场景和追逐情节关闭所有;figScene =图(“名字”“驾驶场景”“标签”“ScenarioGenerationDemoDisplay”);集(figScene,“位置”,[0, 0, 1032, 1032]);movegui (figScene“中心”);%添加追逐图hCarViewPanel = uipanel (figScene,“位置”,[0.5 0 0.5 1],“标题”“追逐相机视图”);hCarPlot =轴(hCarViewPanel);chasePlot(自我,“父”, hCarPlot);%添加生成的场景的顶部视图hViewPanel = uipanel (figScene,“位置”,[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)%从文本文件中读取非自我角色的激光雷达数据。文件标识= fopen (nonEgoFile);内容= 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] = helpercomputegodata (egoData, X, Y) egoTime = egoData. time;timeDiff = diff (egoTime);积分= [X Y];差= diff(点数,1);距离=√(sum(difference .* difference, 2));egoSpeed =某种天体/ timeDiff;egoAngle =每股(diff (Y)。/ diff (X));egoAngle结束(+ 1)= egoAngle(结束);egoSpeed结束(+ 1)= egoSpeed(结束);结束

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;%计算非自我actor的速度值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 '};结束结束

另请参阅

应用程序

功能

对象

相关的例子

更多关于

外部网站