【UAV】UAV Scenario 仿真教程:无人机飞行与激光雷达点云生成【含matlab代码】
UAV Scenario 仿真教程:无人机飞行与激光雷达点云生成
摘要
在无人机自主算法开发中,仿真环境是验证算法有效性的重要一环。MATLAB 的 UAV Toolbox 提供了uavScenario对象,能够帮助我们快速搭建包含静态障碍物(如建筑物)和运动平台(如无人机)的 3D 场景,并支持挂载多种传感器(如 INS、GPS、激光雷达)生成仿真数据。本文将基于官方示例,一步步演示如何创建一个城市建筑场景,让无人机沿预定轨迹飞行,并通过机载激光雷达实时采集点云数据,用于后续的建图或定位算法测试。
1. 引言
无人机仿真场景能够:
- 定义静态障碍物(建筑、地面等)和动态平台(无人机);
- 支持全局坐标系下的轨迹定义和坐标系转换;
- 提供可视化功能,便于观察飞行过程;
- 集成传感器模型,生成逼真的感知数据。
本教程将构建一个包含 11 栋建筑物的场景,无人机搭载激光雷达,沿预设路径飞行,并同步采集点云。
2. 创建 UAV 场景
首先,我们创建一个uavScenario对象,指定更新频率和参考位置(经纬高)。
% 创建 UAV 场景,更新频率 2Hz,参考位置 [75 -46 0]scene=uavScenario(UpdateRate=2,ReferenceLocation=[75-460]);添加一个地面平面,颜色设为灰色。
% 定义颜色color.Gray=0.651*ones(1,3);color.Green=[0.39220.83140.0745];color.Red=[100];% 添加地面(多边形范围 + 高度范围)addMesh(scene,"polygon",{[-250-150;200-150;200180;-250180],[-40]},color.Gray);3. 添加建筑物网格
我们加载预定义的建筑物多边形数据buildingData.mat,该文件包含了 11 组多边形顶点。利用addMesh函数以“多边形拉伸”方式生成三维建筑,高度从 10 米到 30 米不等。
load("buildingData.mat");% 逐个添加建筑(每组多边形和高度范围)addMesh(scene,"polygon",{buildingData{1}(1:4,:),[030]},color.Green);addMesh(scene,"polygon",{buildingData{2}(2:5,:),[030]},color.Green);addMesh(scene,"polygon",{buildingData{3}(2:10,:),[030]},color.Green);addMesh(scene,"polygon",{buildingData{4}(2:9,:),[030]},color.Green);addMesh(scene,"polygon",{buildingData{5}(1:end-1,:),[030]},color.Green);addMesh(scene,"polygon",{buildingData{6}(1:end-1,:),[015]},color.Green);addMesh(scene,"polygon",{buildingData{7}(1:end-1,:),[030]},color.Green);addMesh(scene,"polygon",{buildingData{8}(2:end-1,:),[010]},color.Green);addMesh(scene,"polygon",{buildingData{9}(1:end-1,:),[015]},color.Green);addMesh(scene,"polygon",{buildingData{10}(1:end-1,:),[030]},color.Green);addMesh(scene,"polygon",{buildingData{11}(1:end-2,:),[030]},color.Green);使用show3D显示场景,并调整坐标轴范围。
show3D(scene);xlim([-250200]);ylim([-150180]);zlim([050]);运行后,您将看到一个包含绿色建筑和灰色地面的三维场景。
4. 定义无人机平台
无人机平台(uavPlatform)是传感器的载体。我们使用 NED(北-东-下)参考系,初始位置和姿态从飞行日志数据flightData.mat中加载。
load("flightData.mat");% 创建平台,指定参考系、初始位置和姿态(欧拉角转四元数)plat=uavPlatform("UAV",scene,...ReferenceFrame="NED",...InitialPosition=position(:,:,1),...InitialOrientation=eul2quat(orientation(:,:,1)));% 设置平台外观(四旋翼模型,红色,并旋转180度使方向正确)updateMesh(plat,"quadrotor",{10},color.Red,[000],eul2quat([00pi]));注意:position和orientation是从flightData.mat中读取的三维数组,分别表示每个时刻的位置(x,y,z)和欧拉角(roll,pitch,yaw)。
5. 安装激光雷达传感器
在无人机上挂载一个激光雷达点云生成器(uavLidarPointCloudGenerator),并用uavSensor封装。安装位置相对于无人机机体坐标系为[0,0,-1](即无人机下方 1 米)。
% 创建激光雷达模型lidarmodel=uavLidarPointCloudGenerator(...AzimuthResolution=0.3324099,...ElevationLimits=[-2020],...ElevationResolution=1.25,...MaxRange=90,...UpdateRate=2,...HasOrganizedOutput=true);% 挂载到平台lidar=uavSensor("Lidar",plat,lidarmodel,MountingLocation=[0,0,-1]);6. 沿预定轨迹飞行并采集点云
现在我们让无人机按预定义的轨迹运动,并在每个激光雷达更新时刻读取点云数据。为了可视化,我们预先创建轨迹线图和点云散点图,并利用数据源动态刷新。
6.1 场景可视化与绘图初始化
[ax,plotFrames]=show3D(scene);xlim([-250200]);ylim([-150180]);zlim([050]);view([-11030]);axis equal;hold on;创建轨迹线(白色)和点云散点图(青色)。注意调整数据源属性以提高绘图效率。
% 轨迹线traj=plot3(nan,nan,nan,Color=[111],LineWidth=2);traj.XDataSource="position(:,2,1:idx+1)";traj.YDataSource="position(:,1,1:idx+1)";traj.ZDataSource="-position(:,3,1:idx+1)";% 点云散点图colormap("jet");pt=pointCloud(nan(1,1,3));scatterplot=scatter3(nan,nan,nan,1,[0.30200.74510.9333],Parent=plotFrames.UAV.Lidar);scatterplot.XDataSource="reshape(pt.Location(:,:,1),[],1)";scatterplot.YDataSource="reshape(pt.Location(:,:,2),[],1)";scatterplot.ZDataSource="reshape(pt.Location(:,:,3),[],1)";scatterplot.CDataSource="reshape(pt.Location(:,:,3),[],1)-min(reshape(pt.Location(:,:,3),[],1))";6.2 仿真循环
初始化场景,然后逐帧推进时间。每次读取激光雷达数据,若更新成功则刷新可视化。
setup(scene);foridx=0:size(position,3)-1% 读取当前激光雷达数据[isupdated,lidarSampleTime,pt]=read(lidar);ifisupdated% 快速更新场景视图show3D(scene,"Time",lidarSampleTime,FastUpdate=true,Parent=ax);% 刷新所有数据源refreshdata;drawnow limitrate;end% 推进仿真时间advance(scene);% 移动平台到下一个位置(位置+姿态)move(plat,[position(:,:,idx+1),zeros(1,6),eul2quat(orientation(:,:,idx+1)),zeros(1,3)]);% 更新所有传感器updateSensors(scene);endhold off;在此循环中,move函数的参数向量包含:位置(3个)、速度(3个)、角速度(3个)、四元数(4个)、加速度(3个)等,此处我们仅指定位置和姿态,其余置零。
7. 运行结果与可视化
仿真过程中,您将看到无人机在建筑群间飞行,同时激光雷达实时扫描周围环境,生成的点云以彩色散点图形式显示在场景中(颜色代表高度)。轨迹线则记录飞行路径。
(实际运行时会动态更新)
8. 总结
本教程演示了如何使用 MATLAB UAV Toolbox 构建一个包含建筑障碍物的三维场景,让无人机沿预定轨迹飞行,并挂载激光雷达采集点云数据。该框架可以轻松扩展至更多传感器(如 GPS、IMU)和更复杂的轨迹,适用于 SLAM、路径规划、避障等算法的快速原型验证。
参考资料
- MATLAB UAV Scenario 文档
- uavLidarPointCloudGenerator 文档
完整代码整合如下(您可以复制到 MATLAB 中直接运行):
% 创建场景scene=uavScenario(UpdateRate=2,ReferenceLocation=[75-460]);% 添加地面和颜色定义color.Gray=0.651*ones(1,3);color.Green=[0.39220.83140.0745];color.Red=[100];addMesh(scene,"polygon",{[-250-150;200-150;200180;-250180],[-40]},color.Gray);% 加载建筑数据load("buildingData.mat");addMesh(scene,"polygon",{buildingData{1}(1:4,:),[030]},color.Green);addMesh(scene,"polygon",{buildingData{2}(2:5,:),[030]},color.Green);addMesh(scene,"polygon",{buildingData{3}(2:10,:),[030]},color.Green);addMesh(scene,"polygon",{buildingData{4}(2:9,:),[030]},color.Green);addMesh(scene,"polygon",{buildingData{5}(1:end-1,:),[030]},color.Green);addMesh(scene,"polygon",{buildingData{6}(1:end-1,:),[015]},color.Green);addMesh(scene,"polygon",{buildingData{7}(1:end-1,:),[030]},color.Green);addMesh(scene,"polygon",{buildingData{8}(2:end-1,:),[010]},color.Green);addMesh(scene,"polygon",{buildingData{9}(1:end-1,:),[015]},color.Green);addMesh(scene,"polygon",{buildingData{10}(1:end-1,:),[030]},color.Green);addMesh(scene,"polygon",{buildingData{11}(1:end-2,:),[030]},color.Green);% 显示场景show3D(scene);xlim([-250200]);ylim([-150180]);zlim([050]);% 加载飞行数据load("flightData.mat");% 创建无人机平台plat=uavPlatform("UAV",scene,ReferenceFrame="NED",...InitialPosition=position(:,:,1),InitialOrientation=eul2quat(orientation(:,:,1)));updateMesh(plat,"quadrotor",{10},color.Red,[000],eul2quat([00pi]));% 创建激光雷达传感器lidarmodel=uavLidarPointCloudGenerator(AzimuthResolution=0.3324099,...ElevationLimits=[-2020],ElevationResolution=1.25,...MaxRange=90,UpdateRate=2,HasOrganizedOutput=true);lidar=uavSensor("Lidar",plat,lidarmodel,MountingLocation=[0,0,-1]);% 可视化准备[ax,plotFrames]=show3D(scene);xlim([-250200]);ylim([-150180]);zlim([050]);view([-11030]);axis equal;hold on;% 轨迹和点云绘图traj=plot3(nan,nan,nan,Color=[111],LineWidth=2);traj.XDataSource="position(:,2,1:idx+1)";traj.YDataSource="position(:,1,1:idx+1)";traj.ZDataSource="-position(:,3,1:idx+1)";colormap("jet");pt=pointCloud(nan(1,1,3));scatterplot=scatter3(nan,nan,nan,1,[0.30200.74510.9333],Parent=plotFrames.UAV.Lidar);scatterplot.XDataSource="reshape(pt.Location(:,:,1),[],1)";scatterplot.YDataSource="reshape(pt.Location(:,:,2),[],1)";scatterplot.ZDataSource="reshape(pt.Location(:,:,3),[],1)";scatterplot.CDataSource="reshape(pt.Location(:,:,3),[],1)-min(reshape(pt.Location(:,:,3),[],1))";% 仿真主循环setup(scene);foridx=0:size(position,3)-1[isupdated,lidarSampleTime,pt]=read(lidar);ifisupdatedshow3D(scene,"Time",lidarSampleTime,FastUpdate=true,Parent=ax);refreshdata;drawnow limitrate;endadvance(scene);move(plat,[position(:,:,idx+1),zeros(1,6),eul2quat(orientation(:,:,idx+1)),zeros(1,3)]);updateSensors(scene);endhold off;本博客基于 MATLAB R2024a 编写,不同版本可能略有差异。欢迎交流讨论!
