AirSim 场景网格(Mesh)访问指南:simGetMeshPositionVertexBuffers API 原理与实战
自动驾驶人工智能深度学习强化学习计算机视觉科研【免费下载链接】AirSimOpen source simulator for autonomous vehicles built on Unreal Engine / Unity, from Microsoft AI Research项目地址https://gitcode.com/gh_mirrors/ai/AirSim点击查看免费下载本文以 AirSim 官方文档 docs/meshes.md 为骨架系统讲解如何通过simGetMeshPositionVertexBuffersAPI 获取仿真场景中的全部静态网格Static Mesh数据包括网格数据结构定义、Unreal 引擎端的底层实现原理、RPC 调用链以及基于 Python libigl 的完整可视化实战。读完本文你将掌握从 AirSim 场景中提取带全局位姿的三角网格顶点 索引缓冲并接入任意第三方网格处理库libigl、Open3D、Trimesh 等进行重建、碰撞检测、路径规划或点云研究的具体方法。一、为什么需要访问场景网格AirSim 是一个基于 Unreal Engine / Unity 构建的自动驾驶仿真平台仿真环境本身由大量静态网格Static Mesh组成——地面、建筑、路障、植被等。大多数场景级任务如基于网格的碰撞检测、占据栅格构建、体积重建、SLAM 回环验证都需要直接拿到这些网格的几何数据而不只是依赖相机图像或激光雷达点云。AirSim 为此在World 级 API中提供了simGetMeshPositionVertexBuffers接口一次性返回场景中所有静态网格的名称、位姿与三角形几何缓冲。该接口在 WorldSimApiBase.hpp 中声明为 World 仿真 API 的纯虚函数virtual vectorMeshPositionVertexBuffersResponse getMeshPositionVertexBuffers() const 0;二、网格数据结构MeshPositionVertexBuffersResponse每个网格由MeshPositionVertexBuffersResponse结构体表示其定义位于 CommonStructs.hppstruct MeshPositionVertexBuffersResponse { Vector3r position; Quaternionr orientation; std::vectorfloat vertices; std::vectoruint32_t indices; std::string name; };字段含义与关键约定如下字段类型说明positionVector3r网格组件在Unreal 坐标系下的全局位置orientationQuaternionr网格组件在Unreal 坐标系下的全局朝向四元数verticesstd::vectorfloat顶点坐标的扁平数组Nx3排列N 为顶点数indicesstd::vectoruint32_t三角形索引数组每 3 个为一组构成一个三角面namestd::string网格名称小写化后返回关于数据组织方式原文档给出了三点必须牢记的约定坐标系position与orientation均使用 Unreal 坐标系Z 轴朝上、左手系。后续对顶点做任何变换、或与其他传感器数据如激光雷达点云融合时都需要先做坐标系换算AirSim 的 NED 坐标系与 Unreal 坐标系的转换逻辑可参考 CommonStructs.hpp 中的 Pose 相关定义。Face-Vertex 网格indices中每三个连续的索引构成一个三角形/面即典型的 Face-Vertex Mesh 表示。索引指向vertices数组中的对应顶点下标。全局顶点坐标vertices中的 x、y、z 坐标以单一阵列平铺存储长度为N*3并且是已经过 position 与 orientation 变换后的全局坐标——也就是说你拿到的顶点直接就是世界坐标系下的坐标无需再自行叠加组件位姿。Python 客户端侧的对应结构在 types.py 中以 msgpack 消息类形式定义字段与 C 结构一一对应class MeshPositionVertexBuffersResponse(MsgpackMixin): position Vector3r() orientation Quaternionr() vertices 0.0 indices 0.0 name 三、API 调用方式3.1 Python 客户端Python API 封装在 client.pydef simGetMeshPositionVertexBuffers(self): Returns the static meshes that make up the scene See https://microsoft.github.io/AirSim/meshes/ for details and how to use this Returns: list[MeshPositionVertexBuffersResponse]: responses_raw self.client.call(simGetMeshPositionVertexBuffers) return [MeshPositionVertexBuffersResponse.from_msgpack(response_raw) for response_raw in responses_raw]调用它不需要任何参数返回值是MeshPositionVertexBuffersResponse对象列表每个对象代表场景中的一个静态网格组件。3.2 C 客户端C 客户端对应方法在 RpcLibClientBase.cppvectorMeshPositionVertexBuffersResponse RpcLibClientBase::simGetMeshPositionVertexBuffers() { const auto response_adaptor pimpl_-client.call(simGetMeshPositionVertexBuffers).asvectorRpcLibAdaptorsBase::MeshPositionVertexBuffersResponse(); return RpcLibAdaptorsBase::MeshPositionVertexBuffersResponse::to(response_adaptor); }3.3 完整调用链从客户端到引擎端的调用链如下Python/C 客户端发起 RPC 调用simGetMeshPositionVertexBuffersRPC 服务端在 RpcLibServerBase.cpp 中绑定该远程方法将结果通过 RpcLibAdaptorsBase.hpp 中的适配器结构体序列化后返回Unreal 引擎端在 WorldSimApi.cpp 中实现getMeshPositionVertexBuffers()通过UAirBlueprintLib::RunCommandOnGameThread把收集工作派发到游戏线程执行避免在 RPC 线程上直接触碰渲染资源std::vectorWorldSimApi::MeshPositionVertexBuffersResponse WorldSimApi::getMeshPositionVertexBuffers() const { std::vectorWorldSimApi::MeshPositionVertexBuffersResponse responses; UAirBlueprintLib::RunCommandOnGameThread([responses]() { responses UAirBlueprintLib::GetStaticMeshComponents(); }, true); return responses; }四、Unreal 引擎端实现原理GetStaticMeshComponents真正的网格收集逻辑在 AirBlueprintLib.cpp 的UAirBlueprintLib::GetStaticMeshComponents()中实现。理解这段代码能帮你弄清楚返回的网格为什么是这些、顶点坐标从哪来、为什么接口昂贵。4.1 场景遍历与过滤规则实现使用TObjectIteratorUStaticMeshComponent遍历场景中所有UStaticMeshComponent实例并依次过滤组件名为空无法解析出网格名的跳过以default_、sky、camera开头的组件被跳过——源码注释明确指出skybox天空盒体量巨大且通常对用户无用因此被排除相机相关的网格也同样被排除无GetStaticMesh()、无有效渲染数据HasValidRenderData()、LOD 资源为空LODResources.Num() 0的组件直接跳过网格名称统一经common_utils::Utils::toLower转为小写后存入mesh.name。这就是原文档示例代码中可以用cube in m.name在 Blocks 环境中筛选出立方体网格的原因——名称已经过小写化处理。4.2 位姿与顶点数据的提取对于每个有效组件通过GetComponentLocation()/GetComponentQuat()取出组件在 Unreal 世界坐标系下的位置与旋转分别写入mesh.position与mesh.orientation通过渲染线程命令ENQUEUE_RENDER_COMMAND锁定顶点缓冲RHILockVertexBuffer读取 LOD 0 的顶点位置存入vertices数组读取FRawStaticIndexBuffer索引缓冲按索引缓冲的步长stride区分uint16_t与uint32_t两种格式统一转换为uint32_t存入indices数组。从源码结构可以推断代码同时兼容 UE 4.27 前后的渲染数据访问 APIGetRenderData()与RenderData说明该实现覆盖了较广的 Unreal 版本范围。4.3 Unity 端支持情况该 API 在 Unity 端同样有对应的WorldSimApi实现见 Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h 与 WorldSimApi.cppUnity 版本的 API 支持明细可参考 docs/unity_api_support.md。五、性能注意事项务必先读原文档特别强调该函数调用代价非常昂贵very expensive应当极少调用。原因从上一节源码可以清楚地看到它要遍历场景中全部UStaticMeshComponent每个组件都要通过渲染线程命令锁定并拷贝顶点/索引缓冲结果要整体序列化并经 RPC 传回客户端。对于大型场景一次调用可能涉及数万到数十万个组件、上千万个顶点耗时可达数秒甚至更久。之所以昂贵也没关系是因为该接口只访问静态网格——它们在程序运行期间几乎不变化。因此正确的使用姿势是在程序启动或场景加载后只调用一次把结果缓存到本地内存后续所有基于网格的计算碰撞检测、占据栅格、路径规划都复用缓存数据除非场景内容确实发生变更如通过simAddVehicle、simSetObjectPose等 API 动态改变环境否则不要重复调用。六、实战用 Python libigl 可视化场景网格拿到网格数据后AirSim 本身不提供网格渲染能力需要借助第三方网格库或自写代码来交互。原文档给出了一个完整的 Python 示例——使用 libigl 的 Python 绑定pyigl可视化 Blocks 环境中的立方体网格。libigl 是基于 Eigen 的 C 几何处理库其 Python 绑定通过 pybind11 生成通常需要自行编译得到pyigl.so并放在与脚本相同的目录。完整代码如下与官方文档一致并补充了必要的导入与注释import airsim import numpy as np AIRSIM_HOST_IP127.0.0.1 client airsim.VehicleClient(ipAIRSIM_HOST_IP) client.confirmConnection() # List of returned meshes are received via this function meshesclient.simGetMeshPositionVertexBuffers() index0 for m in meshes: # Finds one of the cube meshes in the Blocks environment if cube in m.name: # Code from here on relies on libigl. Libigl uses pybind11 to wrap C code. So here the built pyigl.so # library is in the same directory as this example code. # This is here as code for your own mesh library should require something similar from pyigl import * from iglhelpers import * # Convert the lists to numpy arrays vertex_listnp.array(m.vertices,dtypenp.float32) indicesnp.array(m.indices,dtypenp.uint32) num_verticesint(len(vertex_list)/3) num_indiceslen(indices) # Libigl requires the shape to be Nx3 where N is number of vertices or indices # It also requires the actual type to be double(float64) for vertices and int64 for the triangles/indices vertices_reshapedvertex_list.reshape((num_vertices,3)) indices_reshapedindices.reshape((int(num_indices/3),3)) vertices_reshapedvertices_reshaped.astype(np.float64) indices_reshapedindices_reshaped.astype(np.int64) # Libigl function to convert to internal Eigen format v_eigp2e(vertices_reshaped) i_eigp2e(indices_reshaped) # View the mesh viewer igl.glfw.Viewer() viewer.data().set_mesh(v_eig,i_eig) viewer.launch() break关键步骤拆解连接仿真器airsim.VehicleClient(ipAIRSIM_HOST_IP)默认连接127.0.0.1上的 AirSim 仿真进程confirmConnection()确保 RPC 通道就绪拉取全部网格client.simGetMeshPositionVertexBuffers()返回全部静态网格建议只调用一次并缓存筛选目标网格按小写名称cube在 Blocks 场景中定位立方体数据重塑与类型转换vertices是长度N*3的扁平数组需reshape((N, 3))indices长度是三角形数的 3 倍需reshape((N_tri, 3))。libigl 要求顶点为float64、索引为int64所以还要做astype转换送入 libigl 可视化p2e将 numpy 数组转为 Eigen 矩阵igl.glfw.Viewer弹窗显示三角网格。适配其他网格库的通用模式示例中转 numpy → reshape → 类型转换 → 送入第三方库的模式不限于 libigl。例如接入 trimesh 只需import trimesh v np.array(m.vertices, dtypenp.float64).reshape((-1, 3)) f np.array(m.indices, dtypenp.int64).reshape((-1, 3)) mesh trimesh.Trimesh(verticesv, facesf) mesh.show()由于顶点已是全局坐标得到的网格可以直接与车辆位姿、相机位姿统一到同一世界坐标系中使用无需额外变换。七、使用限制与注意事项小结仅限静态网格接口返回的是UStaticMeshComponent级别的静态几何骨骼网格Skeletal Mesh、程序化生成的动态几何、粒子等不在返回范围内排除项天空盒、相机相关组件、无有效渲染数据的组件被引擎端主动过滤见 AirBlueprintLib.cpp名称小写化返回的name一律为小写做字符串匹配时注意大小写调用频率昂贵接口务必低频调用 结果缓存渲染线程数据拷贝顶点数据通过渲染线程命令同步读取调用会阻塞直至数据拷贝完成进一步印证昂贵的结论Unreal 坐标系position/orientation/ 顶点坐标均为 Unreal 坐标系Z 轴向上与 AirSim 的 NED 坐标系Z 轴向下不同做多传感器融合时需先转换AirSim 的坐标变换工具可参考 CommonStructs.hpp 与 VectorMath.hpp。八、进一步探索如果你希望深入本 API 的更多细节可在当前仓库中继续阅读结构体定义AirLib/include/common/CommonStructs.hppWorld API 接口声明AirLib/include/api/WorldSimApiBase.hppRPC 序列化适配AirLib/include/api/RpcLibAdaptorsBase.hppRPC 服务端绑定AirLib/src/api/RpcLibServerBase.cppUnreal 端实现Unreal/Plugins/AirSim/Source/WorldSimApi.cpp 与 Unreal/Plugins/AirSim/Source/AirBlueprintLib.cppPython 封装PythonClient/airsim/client.py结合 docs/point_clouds.md点云获取与 docs/voxel_grid.md体素网格可以构建网格 → 点云 → 体素的完整环境几何感知流水线。赞分享自动驾驶人工智能深度学习强化学习计算机视觉科研【免费下载链接】AirSimOpen source simulator for autonomous vehicles built on Unreal Engine / Unity, from Microsoft AI Research项目地址https://gitcode.com/gh_mirrors/ai/AirSim点击查看免费下载相关推荐PixiJS v8 场景 Mesh 完全指南MeshGeometry 与 MeshSimple / MeshPlane / MeshRope / PerspectiveMesh 实战PixiJS v8 场景 Mesh 完全指南MeshGeometry 与 MeshSimple / MeshPlane / MeshRope / Perspe前端图形学Recorder.js与Lame.js结合轻松实现MP3格式转换Recorder.js与Lame.js结合轻松实现MP3格式转换 Recorder.js是一款强大的前端音频录制工具而Lame.js则是优秀的MP3编码库。WebdriverIO 网络原语实战用 browser.mock 拦截 REST API、模拟弱网与离线场景WebdriverIO 网络原语实战用 browser.mock 拦截 REST API、模拟弱网与离线场景 WebdriverIO 在 v6.3 版本中引入测试质量保障上一篇GitHub_Trending/vi/videos项目代码质量分析静态检查与代码重构实践下一篇BiSheng主题开发完整教程从零构建自定义React主题创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考