gl-opendrive插件(车俩3D仿真模拟自动驾驶)
简介
本插件基于免费opendrive开源插件、Threejs和Webgl三维技术、vue前端框架,blender开源建模工具等进行二次开发。该插件由本人独立开发以及负责,目前处于demo阶段,功能还需待完善,由于开发仓促代码还需优化。
因此,使用和阅读者需要具备 :
- opendrive源码基础,xodr文件格式理解
- threejs三维渲染引擎
- webgl三维协议以及相关着色器知识
- 会使用blender,具备一定的建模基础
- javaScript技术
- vue框架
- echarts数据可视化图表库
- 熟悉各种坐标系,如 世界坐标系,st坐标系,uv坐标系,xyz惯性坐标系,物体坐标系,
- 数学知识基础(极坐标,微分,向量)等
- 离屏渲染思想、webgl着色器(vertexShader、fragmentShader)
- glsl语法
核心功能
- xodr文件解析
- 地图渲染
- 车辆三视图(算法优化)
- 道路追踪
- 全局路径规划展示
- 自定义打点
- 车辆运行
- 车轮旋转
- 鼠标定位(三维)
- GPU颜色拾取
- 支持远程或者本地数据文件加载
- 其他
xodr文件解析
该功能由opendrive插件实现,具体的文件格式可查阅opendrive官方
或者推荐网址
自动驾驶场景仿真标准(一)- OpenDRIVE - 知乎
《OpenDRIVE1.6规格文档》1_opendrive官方文档-CSDN博客
《OpenDRIVE1.6规格文档》3_opendrive 1.6_YMWM_的博客-CSDN博客
道路追踪
利用离屏渲染技术以及定位功能实现
gpu拾取颜色获取车道ID
//跟踪屏幕中间位置(近似跟踪车的位置)
camera.setViewOffset(
renderer.domElement.width, //画布的宽度
renderer.domElement.height, //画布的高度
renderer.domElement.width/2 | 0, //画布坐标系中,相机的x坐标位置
renderer.domElement.height/2 | 0, //画布坐标系中,相机的y坐标位置
1, //副相机的宽度
1 //副相机的高度
);
//离屏渲染
renderer.setRenderTarget(lane_picking_texture);
renderer.render(lane_picking_scene, camera);
renderer.setRenderTarget(roadmark_picking_texture);
renderer.render(roadmark_picking_scene, camera);
renderer.setRenderTarget(xyz_texture);
renderer.render(xyz_scene, camera);
renderer.setRenderTarget(st_texture);
renderer.render(st_scene, camera);
const lane_id_pixel_buffer = new Float32Array(4);
//拾取颜色
//console.log(mouse.x, window.innerHeight - mouse.y)
renderer.readRenderTargetPixels(
lane_picking_texture,
0, //相机截图左上角为坐标原点,相对于截图左上角而言的渲染起始点x坐标
0, //相机截图左上角为坐标原点,相对于截图左上角而言的渲染起始点y坐标
1, //渲染宽度范围
1, //渲染高度范围
lane_id_pixel_buffer
);
获取车道进行颜色渲染
if (isValid(lane_id_pixel_buffer)) {
//根据颜色值解码成车道ID
const decoded_lane_id = decodeUInt32(lane_id_pixel_buffer);
//自定义数据中获取所有车段中的所有车道数据
const odr_lanes_mesh =
road_network_mesh.userData.odr_road_network_mesh.lanes_mesh;
//本次选中的区域车道ID是否和上次一样
if (INTERSECTED_LANE_ID != decoded_lane_id) {
//当前是否是初始化状态,如果不是则进行初始化,防止重复初始化
if (INTERSECTED_LANE_ID != 0xffffffff) {
//根据车道ID索引获取车道信息
road_network_mesh.geometry.attributes.color.array.fill(
COLORS.road
);
}
//保存选中车道ID
INTERSECTED_LANE_ID = decoded_lane_id;
//根据车道ID获取车道信息
const lane_vert_idx_interval =
odr_lanes_mesh.get_idx_interval_lane(INTERSECTED_LANE_ID);
//获取该车道长度
const vert_count =
lane_vert_idx_interval[1] - lane_vert_idx_interval[0];
//修改离屏渲染场景中该车道的背景颜色
applyVertexColors(
road_network_mesh.geometry.attributes.color,
new THREE.Color(COLORS.lane_highlight),
lane_vert_idx_interval[0],
vert_count
);
//手动更新颜色值
road_network_mesh.geometry.attributes.color.needsUpdate = true;
//显示左上角信息展示
spotlight_info.style.display = "block";
}
//使用过后删除数据冗余,避免造成内存泄漏
odr_lanes_mesh.delete();
} else {
//鼠标拾取无效色素
//恢复初始化数据
//当前是否已经是初始化状态如果不是则进行初始化
if (INTERSECTED_LANE_ID != 0xffffffff) {
const odr_lanes_mesh =
road_network_mesh.userData.odr_road_network_mesh.lanes_mesh;
const lane_vert_idx_interval =
odr_lanes_mesh.get_idx_interval_lane(INTERSECTED_LANE_ID);
road_network_mesh.geometry.attributes.color.array.fill(COLORS.road);
road_network_mesh.geometry.attributes.color.needsUpdate = true;
odr_lanes_mesh.delete();
INTERSECTED_LANE_ID = 0xffffffff;
spotlight_info.style.display = "none";
}
}
地图渲染
利用opendrive开源插件对xodr文件的加载和解析,使用threejs框架对数据进行渲染
车辆三视图(算法优化)
优点:避免了点过于分散和间距过大造成的视图摇晃和颠簸问题
正视图
效果图
侧视图
效果图:
俯视图
效果图
全局路径规划展示
车轮旋转
非车辆原地不动,车轮旋转,地图动的方式(录制软件掉帧问题,效果不太明显)
三维定位
左上角webgl坐标
自定义打点
点击开始打点,可在地图上进行自定义路径,点击启动,将展示路径和启动模型运行
中间红色线则为路线
其他
转弯
直行
变道