一、简介
如图所示,机器人在一个二维环境下运动,图中指出了机器人,障碍和目标之间的相对位置。
这个图比较清晰的说明了人工势场法的作用,物体的初始点在一个较高的“山头”上,要到达的目标点在“山脚”下,这就形成了一种势场,物体在这种势的引导下,避开障碍物,到达目标点。
人工势场包括引力场合斥力场,其中目标点对物体产生引力,引导物体朝向其运动(这一点有点类似于A*算法中的启发函数h)。障碍物对物体产生斥力,避免物体与之发生碰撞。物体在路径上每一点所受的合力等于这一点所有斥力和引力的和。这里的关键是如何构建引力场和斥力场。下面我们分别讨论一下:
引力场:
常用的引力函数:
这里的ε是尺度因子.ρ(q,q_goal)表示物体当前状态与目标的距离。引力场有了,那么引力就是引力场对距离的导数(类比物理里面W=FX):
关于梯度的算法可以参考相关资料,简单提一下,二元函数梯度是酱紫的[δx,δy],这个符号是偏导数,不太对,见谅。
Fig .引力场模型
斥力场:
公式(3)是传统的斥力场公式,现在还没有搞清楚是怎么推导出来的。公式中η是斥力尺度因子,ρ(q,q_obs)代表物体和障碍物之间的距离。ρ_0代表每个障碍物的影响半径。换言之,离开一定的距离,障碍物就对物体没有斥力影响。
斥力就是斥力场的梯度
Fig 斥力场模型
总的场就是斥力场合引力场的叠加,也就是U=U_att+U_rep,总的力也是对对应的分力的叠加,如下图所示:
二、存在的问题
(a) 当物体离目标点比较远时,引力将变的特别大,相对较小的斥力在甚至可以忽略的情况下,物体路径上可能会碰到障碍物
(b)当目标点附近有障碍物时,斥力将非常大,引力相对较小,物体很难到达目标点
(c)在某个点,引力和斥力刚好大小相等,方向想反,则物体容易陷入局部最优解或震荡
三、各种改进版本的人工势场法
(a)对于可能会碰到障碍物的问题,可以通过修正引力函数来解决,避免由于离目标点太远导致引力过大
和(1)式相比,(5)式增加了范围限定。d*_goal 给定了一个阈值限定了目标和物体之间的距离。对应的梯度也就是引力相应变成:
(b)目标点附近有障碍物导致目标不可达的问题,引入一种新的斥力函数
这里在原有斥力场的基础上,加上了目标和物体距离的影响,(n是正数,我看到有篇文献上n=2)。直观上来说,物体靠近目标时,虽然斥力场要增大,但是距离在减少,所以在一定程度上可以起到对斥力场的拖拽作用
相应斥力变成:
所以可以看到这里引力分为两个部分,编程时要格外注意
(c)局部最优问题是一个人工势场法的一个大问题,这里可以通过加一个随机扰动,让物体跳出局部最优值。类似于梯度下降法局部最优值的解决方案。
%% Test Swarm Trajectory % 测试群轨迹
clear all;
false = 0;
true = 1;
%% Setup the movie stuff %设置视频资料
make_movie = false;
writerObj = [];
if( make_movie )
writerObj = VideoWriter('test_gradient0.avi');
writerObj.FrameRate = 15;
open(writerObj);
end
%% Parameter specifications for drones 无人机的参数设置
Nd = 5; % number of drones in swarm 集群中无人机的数量
ind_c = -1; % index for center/lead drone 指数中心/引导无人机
radius = 2; % radius for drones and possibly obstacles 无人机的半径和可能障碍物的半径
dims = [0, 100; 0, 100; 0, 100]; % first row is lower and upper x bounds
% second row is lower and upper y bounds
%% Start updating the drones 开始更新无人机
close all;
h = figure('Position', [10, 10, 800, 400]);
% Do the initial drawing
i = 1;
hold on
while( i <=Nd ) % loop through drones
drawObject(drones(i));
i = i + 1;
end
i = 1;
while( i <= No ) % loop through obstacles
drawObject(obst(i));
i = i + 1;
end
hold off
axis([ dims(1,1),dims(1,2),dims(2,1),dims(2,2) ])
xpos = [];
% Do iterations
it = 1;
count = 0;
done = 0;
%% Close movie file, if you are recording a movie
if( make_movie )
close(writerObj);
end