自動尋路是機器人導航的核心技術,其原理主要涉及機器人與環境之間的複雜資訊互動與處理。在自動尋路過程中,機器人依靠先進的感測器系統,如高畫質攝像頭、精密鐳射雷達和靈敏超聲波裝置,全方位感知周圍環境。這些感測器能夠實時捕捉並分析環境中的障礙物、地形變化和關鍵路標,為機器人提供精確的導航資料。
自動尋路在多個領域發揮著關鍵作用,從圖撲的資料中心機房的自動化巡檢系統,到智慧機器人的導航系統,再到智慧碼頭堆場的智慧化管理,自動尋路技術無處不在。該功能不僅能規劃出最優路線,還能實時考慮障礙物避讓等複雜的實際因素,靈活調整路徑以確保安全和效率。
乍聽之下,自動尋路功能略顯複雜,實現過程中也確實涉及了一些演算法。在具體實施之前,我們需要先解決兩個關鍵問題:
- 如何避開場景中的障礙物?
- 如何計算最佳路徑?
針對這兩處問題,我們可以利用圖撲軟體自研 HT for Web 提供的 ht-astar.js 外掛。該外掛具備初始化網格和自動搜尋路徑等功能,高效簡化了自動尋路的實現過程。
系統分析
場景網格化
先將場景劃分成二維網格,障礙物分佈於不同的網格單元上,部分較大的障礙物可能會佔據多個網格單元。路徑計算實際上是分析網格的佔用情況,當平臺監測到某個網格被佔用時,系統會自動尋找擇優生成一條繞行路徑。
在開發時,首先需要去例項化 ht.Astar.Finder(view, params)。其中 view 可以是 ht.graph.GraphView 或者 ht.graph3d.Graph3dView。params 是一個包含基礎屬性設定的物件。以下列舉了一些 params 的常用引數:
✧simplify:是否啟用路徑簡化。
✧closest:是否啟用最近路徑最佳化。
✧nodeRectExtend:擴充套件節點範圍。
✧gridSizeY:網格在 Y 方向上的大小。
✧gridSizeX:網格在 X 方向上的大小。
✧diagonal:是否允許沿對角線方向移動。
✧fastOverlap:是否啟用快速監測重疊演算法。
✧filter:過濾函式用於在路徑計算過程中過濾特定節點。
✧turnPunish:轉彎懲罰係數,數值越高表示越傾向於直線路徑。
具體程式碼實現:
const hindrance = dm.getDataByTag(‘hindrance’);
const astar = new ht.Astar.Finder(view, {
gridSizeX: 50, // 網格
gridSizeY: 50,
nodeRectExtend: 50,
fastOverlap: false,
filter: function (data) {
return data.isDescendantOf(hindrance);
}
});
路徑計算
在路徑計算過程中,系統需要實時監測每個網格單元的佔用狀態。若規劃的路徑遇到被障礙物佔用的網格,系統會自動尋找繞行路徑,以動態避開障礙物。
在開發過程中,我們需要監聽場景背景的點選事件,獲取點選位置的座標。然後,結合起點座標,透過 astar.findPath(pFrom, pTo) 函式計算出具體路徑。計算得到的路徑是一組點位資料,可以利用這些資料在場景中繪製出一條路徑管道。具體程式碼實現:
view.mi(function (e) {
const { kind, data, event } = e;
if (kind === 'clickBackground') {
const animOb = view.dm().getDataByTag('people'); // 獲取人物節點
let pFrom = animOb.p3(); // 獲取人物節點的座標(起點座標)
pFrom = { x: pFrom[0], y: pFrom[2] };
let position = view.getHitPosition(event); // 根據滑鼠事件獲取場景中的邏輯座標
const pTo = { x: position[0], y: position[2] };
const path = astar.findPath(pFrom, pTo); // 獲取路徑
createPloyline(path); // 生成管道
}
})
// 生成管道
createPloyline(){
const points: any = [];
path.forEach((p: any, i: number) => {
points.push({ x: p.x, y: p.y, e: 0 });
})
const polyline = new ht.Polyline();
polyline.s({
"shape3d": false,
});
polyline.setPoints(points);
view.dm().add(polyline);
}
路徑動畫
在場景中生成管道後,人物節點可沿此管道移動。人物節點沿管道運動的程式碼如下:
const animOb = dm.getDataByTag('people');
animOb.playAnimation('walk'); // 示例中人物模型使用的是 fbx 模型,可播放節點上的動畫
const length = view.getLineLength(polyline);
let moveAnim = null;
const params = {
delay: 100,
duration: 1000 * (length / 200), // 根據管道的長度設定動畫週期
easing: function (t) { return t },
action: function (v, t) {
var offset = view.getLineOffset(polyline, length * v);
if (offset) {
var point = offset.point,
px = point.x,
py = point.y,
pz = point.z,
tangent = offset.tangent,
tx = tangent.x,
ty = tangent.y,
tz = tangent.z;
animOb.lookAt([px + tx, py + ty, pz + tz], 'front');
animOb.p3(px, py, pz);
}
// 人物運動時,視角始終跟隨
view.setCenter([px, py, pz]);
view.setEye([px + 400, py + 800, pz + 400]);
},
finishFunc: () => {
moveAnim = null;
// 切換場景視角
view.moveCamera([-84, 3435, 3142], [-28, -821, -160], {
duration: 1000
})
animOb.pauseAnimation(); // 暫停人物模型動畫
}
};
moveAnim = ht.Default.startAnim(params);
最佳化視覺效果
基於上述,我們已實現了基本的自動尋路功能。在實際專案中仍需提升一定的視覺效果,讓展示頁面足夠美觀,我們可以採取以下策略:
- 首先,將管道路徑隱藏(使用 polyline.s('transparent.mask', true));
- 隨後,利用 ht.Shape 節點並設定貼圖來呈現人物的運動軌跡。這樣不僅能實現功能,還能大幅增強視覺吸引力。
具體實現程式碼如下:
createShape(points) {
if(uvAnim) uvAnim.pause(); // 建立新的 shape 前將舊shape 的 uv 偏移動畫移除
const shape = this.shape = new ht.Shape();
shape.s({
"shape.border.color": "rgb(255,0,0)",
"all.visible": false,
"all.transparent": true,
"top.visible": true,
"top.image": "assets/arrow.png",
"top.uv.scale": [
length / 500,
1
],
"texture.cache": true,
"3d.selectable": true,
"3d.editable": false,
"3d.movable": false,
"3d.visible": true
})
dm.add(shape);
shape.setThickness(30);
shape.setPoints(points);
return shape;
}
// ht.Shape 的 uv 偏移動畫
playShapeAnim(shape) {
if (!shape) return;
const params = {
duration: 2000,
easing: function (t: number) {
return t;
},
action: function (v: number, t: number) {
shape.s("all.uv.offset", [v, 0]);
},
finishFunc: () => {
uvAnim = null;
uvAnim = ht.Default.startAnim(params);
}
};
uvAnim = ht.Default.startAnim(params);
}
const points: any = [];
path.forEach((p: any, i: number) => {
points.push({ x: p.x, y: p.y, e: 0 });
})
const shape = createShape(points);
let uvAnim = null;
playShapeAnim(shape); // 執行shape 的 uv 偏移動畫
總結
作為開發者的我們,將繼續探索和最佳化自動尋路技術,利用圖撲 HT 提供的外掛工具,不斷提升演算法效率和使用者體驗。透過合理的引數設定、精確的網格劃分和智慧的路徑規劃,為各種應用場景提供更加出色的自動尋路解決方案。
您可以至圖撲軟體官網檢視更多案例及效果:
https://www.hightopo.com/demos/index.html