
1. 给无人机搭载激光雷达在unity给无人机quadcopter上面添加一个空的empty对象命名为LIDAR并编写雷达脚本挂载在上面。脚本LidarSensor.cs如下using System.Collections.Generic; using UnityEngine; public class LidarSensor : MonoBehaviour { public int horizontalResolution 180; public int verticalChannels 16; public float verticalFOV 30f; public float maxDistance 50f; public LayerMask obstacleLayer; public bool isScanning false; public ListVector3 Scan() { ListVector3 points new ListVector3(); if (!isScanning) return points; for (int v 0; v verticalChannels; v) { float vAngle -verticalFOV / 2 v * (verticalFOV / (verticalChannels - 1)); for (int h 0; h horizontalResolution; h) { float hAngle h * (360f / horizontalResolution); Vector3 dir Quaternion.Euler(vAngle, hAngle, 0) * transform.forward; RaycastHit hit; if (Physics.Raycast(transform.position, dir, out hit, maxDistance, obstacleLayer)) { // 世界坐标点 points.Add(hit.point); Debug.DrawLine(transform.position, hit.point, Color.red, 0.1f); } } } return points; } }注意要在unity里选择obstacle layer选择到所有需要扫描的场景。没选择的层就扫不到。2. 其他脚本创建一个empty命名为PonitCloudSystem用来挂载雷达相关的脚本。脚本PointCloudManager.csusing System.Collections.Generic; using UnityEngine; public class PointCloudManager : MonoBehaviour { public LidarSensor lidar; // 全局地图 public ListVector3 globalMap new ListVector3(); // 控制扫描频率 public float scanInterval 0.5f; private float timer 0f; public bool enableScanning false; void Update() { if (!enableScanning) return; timer Time.deltaTime; if (timer scanInterval) { timer 0f; ScanAndAccumulate(); } } void ScanAndAccumulate() { ListVector3 framePoints lidar.Scan(); // 直接加入因为已经是 world 坐标 globalMap.AddRange(framePoints); Debug.Log(当前地图点数: globalMap.Count); } }脚本PLYExporter.cs用来生成点云文件。using System.Collections.Generic; using UnityEngine; public class PointCloudManager : MonoBehaviour { public LidarSensor lidar; // 全局地图 public ListVector3 globalMap new ListVector3(); // 控制扫描频率 public float scanInterval 0.5f; private float timer 0f; public bool enableScanning false; void Update() { if (!enableScanning) return; timer Time.deltaTime; if (timer scanInterval) { timer 0f; ScanAndAccumulate(); } } void ScanAndAccumulate() { ListVector3 framePoints lidar.Scan(); // 直接加入因为已经是 world 坐标 globalMap.AddRange(framePoints); Debug.Log(当前地图点数: globalMap.Count); } }脚本LidarControlAPI.CSusing UnityEngine; public class LidarControlAPI : MonoBehaviour { public LidarSensor lidar; public PointCloudManager manager; // 开启雷达 public void StartLidar() { lidar.isScanning true; manager.enableScanning true; Debug.Log(Lidar Started); } // 关闭雷达 public void StopLidar() { lidar.isScanning false; manager.enableScanning false; Debug.Log(Lidar Stopped); } }脚本LidarCOmmandListener.csusing UnityEngine; using System.IO; public class LidarCommandListener : MonoBehaviour { public LidarControlAPI lidarAPI; public PLYExporter exporter; string commandPath /yourpath/lidar_cmd.txt; void Update() { if (File.Exists(commandPath)) { string cmd File.ReadAllText(commandPath).Trim(); if (cmd start) { lidarAPI.StartLidar(); } else if (cmd stop) { lidarAPI.StopLidar(); } else if (cmd export) { exporter.ExportPLY(); } File.Delete(commandPath); } } }3. 通过python调用运行python脚本控制雷达开关和点云文件的获取.蛇形扫描全局环境。注意修改自己环境地图的坐标范围。import airsim import time import os # # 配置 # CMD_PATH /home/xwh/Desktop/Sim-Env/TryAIrSim/drone_fly_try/airsim_drone/lidar_cmd.txt # 目标位置NED坐标单位米 TARGET_X 0 TARGET_Y 0 TARGET_Z -5 # 注意负数表示向上飞NED坐标系 # # 雷达控制函数 # def start_lidar(): with open(CMD_PATH, w) as f: f.write(start) print(✅ Lidar Started) def stop_lidar(): with open(CMD_PATH, w) as f: f.write(stop) print( Lidar Stopped) def export_ply(): # 你可以再加一个命令给Unity触发导出 with open(CMD_PATH, w) as f: f.write(export) print( Export Triggered) # # 主流程 # def main(): # 1️⃣ 连接 AirSim client airsim.MultirotorClient() client.confirmConnection() # 2️⃣ 控制权 client.enableApiControl(True) client.armDisarm(True) print( 起飞中...) client.takeoffAsync().join() time.sleep(1) x_min, x_max -50, 50 y_min, y_max -50, 50 z_min, z_max -11, -1 y_step 20 # y轴每次移动距离 z_step 10 # 3️⃣ 开启雷达 start_lidar() # 等一会让雷达开始扫 time.sleep(1) z z_min while z z_max: y y_min direction 1 while y y_max: if direction 1: client.moveToPositionAsync(x_min, y, z, velocity6).join() time.sleep(0.5) # 停留收集点云 client.moveToPositionAsync(x_max, y, z, velocity6).join() else: client.moveToPositionAsync(x_max, y, z, velocity6).join() time.sleep(0.5) # 停留收集点云 client.moveToPositionAsync(x_min, y, z, velocity6).join() y y_step direction * -1 time.sleep(0.5) z z_step time.sleep(1) stop_lidar() time.sleep(1) export_ply() time.sleep(2) # 8️⃣ 降落 print( 降落中...) client.landAsync().join() client.armDisarm(False) client.enableApiControl(False) print(✅ 任务完成) # if __name__ __main__: main()4. 点云可视化import open3d as o3d # 1. 读取点云文件 pcd o3d.io.read_point_cloud(global_map.ply) # 支持 .ply, .pcd, .xyz 等格式 # 3. 可视化点云 o3d.visualization.draw_geometries([pcd], window_name点云可视化, width800, height600, point_show_normalFalse, mesh_show_wireframeFalse, mesh_show_back_faceFalse)