在 CesiumJS 中实现无人机碰撞检测 ,通常是指检测无人机(UAV)模型或轨迹是否与地形、建筑物、禁飞区或其他飞行器发生空间冲突。Cesium 本身不直接提供物理引擎,但可以通过其空间计算能力(如射线检测、包围体、高程查询等)实现基本的碰撞/接近检测。

以下是几种典型场景及对应的 代码方案:
✅ 场景一:无人机与地形/地表碰撞检测
原理
通过 sampleTerrainMostDetailed 获取当前位置下方的真实地形高程,判断无人机高度是否低于该高程(即"撞地")。
代码示例
js
import { Viewer, Cartesian3, Cartographic, sampleTerrainMostDetailed, Ellipsoid } from 'cesium';
const viewer = new Viewer('cesiumContainer');
// 无人机当前位置(经纬度 + 高度)
const dronePosition = Cartesian3.fromDegrees(116.4, 39.9, 50); // 50米高度
// 转换为地理坐标(弧度)
const cartographic = Cartographic.fromCartesian(dronePosition);
// 查询该点的地形高程
sampleTerrainMostDetailed(viewer.terrainProvider, [cartographic]).then(updatedPositions => {
const terrainHeight = updatedPositions[0].height; // 地形高程(米)
const droneHeight = cartographic.height; // 无人机当前高度
if (droneHeight <= terrainHeight + 5) { // 预留5米安全距离
console.warn('⚠️ 无人机接近地面!可能发生碰撞!');
// 可触发告警、自动爬升等逻辑
}
});
💡 注意:需启用
viewer.terrainProvider(如CesiumWorldTerrain),否则返回高程为 0。
✅ 场景二:无人机与 3D 建筑物/障碍物碰撞检测
原理
使用 射线检测(Ray Casting) 向下发射射线,检测是否与 3DTiles 模型相交。
前提
- 建筑物以
Cesium3DTileset形式加载(如倾斜摄影模型、BIM)。 - 启用
scene.pickTranslucentDepth = true(支持半透明拾取)。
代码示例
js
function checkCollisionWith3DTiles(viewer, dronePosition) {
const scene = viewer.scene;
const ray = new Cesium.Ray(dronePosition, Cesium.Cartesian3.negate(Cesium.Cartesian3.UNIT_Z, new Cesium.Cartesian3()));
// 执行射线拾取(只检测 3D Tiles)
const hit = scene.drillPick(ray, 1, [Cesium.SceneMode.SCENE3D]);
if (hit && hit.length > 0) {
// 检查最近交点距离
const distance = Cesium.Cartesian3.distance(dronePosition, hit[0].position);
if (distance < 10) { // 10米内视为危险
console.warn('🚨 无人机接近建筑物!', hit[0]);
return true;
}
}
return false;
}
// 使用
const dronePos = Cartesian3.fromDegrees(116.4, 39.9, 80);
checkCollisionWith3DTiles(viewer, dronePos);
⚠️ 局限性:
drillPick性能较低,不适合高频调用(如每帧)。建议用于关键点检测或低频监控。
✅ 场景三:无人机与禁飞区(空域)碰撞检测
原理
将禁飞区建模为 3D 多边形柱体(Extruded Polygon),判断无人机位置是否在其内部。
步骤
- 定义禁飞区(经纬度边界 + 高度范围)
- 使用点在多边形算法(2D)+ 高度区间判断
代码示例
js
// 禁飞区定义(北京某区域,0~1000米)
const noFlyZone = {
polygon: [
[116.38, 39.90],
[116.42, 39.90],
[116.42, 39.92],
[116.38, 39.92]
],
minHeight: 0,
maxHeight: 1000
};
function isPointInPolygon(point, polygon) {
let inside = false;
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
const xi = polygon[i][0], yi = polygon[i][1];
const xj = polygon[j][0], yj = polygon[j][1];
const intersect = ((yi > point[1]) !== (yj > point[1])) &&
(point[0] < (xj - xi) * (point[1] - yi) / (yj - yi) + xi);
if (intersect) inside = !inside;
}
return inside;
}
function checkNoFlyZone(droneLon, droneLat, droneAlt, zone) {
const in2D = isPointInPolygon([droneLon, droneLat], zone.polygon);
const inHeight = droneAlt >= zone.minHeight && droneAlt <= zone.maxHeight;
return in2D && inHeight;
}
// 使用
const collision = checkNoFlyZone(116.4, 39.91, 150, noFlyZone);
if (collision) {
console.error('❌ 进入禁飞区!');
}
✅ 可扩展为多个禁飞区数组循环检测。
✅ 场景四:多无人机之间防撞(间距检测)
原理
计算两架无人机之间的欧氏距离,若小于安全阈值则告警。
代码示例
js
function getDistance3D(pos1, pos2) {
return Cesium.Cartesian3.distance(pos1, pos2);
}
// 假设有两架无人机位置
const uav1 = Cartesian3.fromDegrees(116.4, 39.9, 100);
const uav2 = Cartesian3.fromDegrees(116.401, 39.901, 102);
const dist = getDistance3D(uav1, uav2);
if (dist < 50) { // 安全距离50米
console.warn('⚠️ 无人机间距过近!', dist.toFixed(2), '米');
}
🧩 综合建议:构建碰撞检测系统
js
class UAVCollisionDetector {
constructor(viewer) {
this.viewer = viewer;
}
async checkAll(dronePosition, droneLonLatAlt, otherUAVs, noFlyZones) {
// 1. 地形碰撞
await this.checkTerrain(dronePosition);
// 2. 3D 建筑物(低频)
// this.check3DTiles(dronePosition);
// 3. 禁飞区
noFlyZones.forEach(zone => {
if (this.inNoFlyZone(droneLonLatAlt, zone)) {
console.error('禁飞区冲突');
}
});
// 4. 其他无人机
otherUAVs.forEach(uav => {
if (Cesium.Cartesian3.distance(dronePosition, uav.position) < 30) {
console.warn('多机冲突');
}
});
}
// ... 上述各方法封装
}
注意事项
| 问题 | 解决方案 |
|---|---|
| 性能瓶颈 | 避免每帧执行 sampleTerrain 或 drillPick,改用定时器(如每秒1次)或关键点触发 |
| 精度不足 | 使用 sampleTerrainMostDetailed 而非 sampleTerrain |
| 3D Tiles 拾取失败 | 确保 tileset 已加载完成,且材质支持深度拾取 |
| 坐标系混淆 | 统一使用 Cartesian3(笛卡尔)进行距离计算,Cartographic(经纬高)用于地理判断 |
进阶方向
- 集成 物理引擎(如 Cannon.js、Ammo.js)实现真实动力学仿真
- 使用 Cesium Primitive API 构建包围盒(Bounding Sphere/OBB)加速检测
- 结合 Web Worker 将计算移出主线程,避免卡顿