田里跑自主机器人,路径规划是块硬骨头。几种常用算法试下来,我觉得这五种必须知道:A*、Dijkstra、DWA、RRT 和人工势场。各有各的脾气,用好了才稳。
先把地图和定位弄对
路径算得再好,基础数据差也没用。普通 GPS 在田里晃个几米太常见,RTK 几乎是刚需。写一个 Go 的客户端从基准站拉差分数据,移动站就可以把定位干到厘米级。
client.Connect("ntrip.base.com:2101")
client.Auth("user", "pass")
client.MountPoint("/RTCM3")
go func() {
for data := range client.Stream() {
rover.ApplyCorrection(data)
}
}()
有了高精度坐标,再融合 IMU 的姿态补偿和卡尔曼滤波,能输出稳定的位姿。至于地图,常规就两种:栅格地图把田切成小格子,标记可走、不可走,适合播种喷洒这类精细活;拓扑地图只留关键节点和道路连接,存得少,适合大范围快速导航。我一般全局用拓扑,局部再转成栅格去避障。各有各的适用场合:
| 指标 | 栅格地图 | 拓扑地图 |
|---|---|---|
| 存储开销 | 高 | 低 |
| 更新频率 | 实时动态 | 周期性 |
判定一个格子是不是障碍,有时还得动态调阈值,比如作物高了就把栅格值上调,用下面这个小函数就行:
def is_obstacle(grid_map, x, y, threshold=0.8):
return grid_map[x][y] > threshold

这张图是感知到执行的闭环:传感器、摄像头把数据送到边缘端处理,再汇总到云端规划,最后指令下到行走机构。说起来简单,做起来坑不少。
整个导航过程基本循环就是:
graph TD
A[开始] --> B{获取传感器数据}
B --> C[执行 SLAM 建图]
C --> D[调用路径规划算法]
D --> E[生成控制指令]
E --> F[驱动电机执行]
F --> G[实时修正位置]
G --> B
五种算法逐个看
A*:全局规划的标配
A* 的灵魂是 f(n)=g(n)+h(n),用一个优先队列挑 f 最小的节点扩展,出来的就是最短路径。实现起来并不复杂:
def a_star(grid, start, goal):
open_set = PriorityQueue()
open_set.put((0, start))
came_from = {}
g_score = {start: }
open_set.empty():
current = open_set.get()[]
current == goal:
reconstruct_path(came_from, current)
neighbor get_neighbors(current, grid):
tentative_g = g_score[current] + cost(current, neighbor)
tentative_g < g_score.get(neighbor, ()):
came_from[neighbor] = current
g_score[neighbor] = tentative_g
f_score = tentative_g + heuristic(neighbor, goal)
open_set.put((f_score, neighbor))
[]
