人工势场法是局部路径规划的一种比较常用的方法。这种方法假设机器人在一种虚拟力场下运动。
如图所示,机器人在一个二维环境下运动,图中指出了机器人,障碍和目标之间的相对位置。
这个图比较清晰的说明了人工势场法的作用,物体的初始点在一个较高的“山头”上,要到达的目标点在“山脚”下,这就形成了一种势场,物体在这种势的引导下,避开障碍物,到达目标点。
人工势场包括引力场合斥力场,其中目标点对物体产生引力,引导物体朝向其运动(这一点有点类似于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)局部最优问题是一个人工势场法的一个大问题,这里可以通过加一个随机扰动,让物体跳出局部最优值。类似于梯度下降法局部最优值的解决方案。
function varargout = AFM(varargin) % AFM MATLAB code for AFM.fig % AFM, by itself, creates a new AFM or raises the existing % singleton*. % % H = AFM returns the handle to a new AFM or the handle to % the existing singleton*. % % AFM('CALLBACK',hObject,eventData,handles,...) calls the local % function named CALLBACK in AFM.M with the given input arguments. % % AFM('Property','Value',...) creates a new AFM or raises the % existing singleton*. Starting from the left, property value pairs are % applied to the GUI before AFM_OpeningFcn gets called. An % unrecognized property name or invalid value makes property application % stop. All inputs are passed to AFM_OpeningFcn via varargin. % % *See GUI Options on GUIDE's Tools out. Choose "GUI allows only one % instance to run (singleton)". % % See also: GUIDE, GUIDATA, GUIHANDLES % Edit the above text to modify the response to help AFM % Last Modified by GUIDE v2.5 28-Nov-2013 20:49:25 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; gui_State = struct('gui_Name', mfilename, ... 'gui_Singleton', gui_Singleton, ... 'gui_OpeningFcn', @AFM_OpeningFcn, ... 'gui_OutputFcn', @AFM_OutputFcn, ... 'gui_LayoutFcn', [] , ... 'gui_Callback', []); if nargin && ischar(varargin{1}) gui_State.gui_Callback = str2func(varargin{1}); end if nargout [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); else gui_mainfcn(gui_State, varargin{:}); end % End initialization code - DO NOT EDIT % --- Executes just before AFM is made visible. function AFM_OpeningFcn(hObject, eventdata, handles, varargin) % This function has no output args, see OutputFcn. % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % varargin command line arguments to AFM (see VARARGIN) % Choose default command line output for AFM handles.output = hObject; % Update handles structure guidata(hObject, handles); % UIWAIT makes AFM wait for user response (see UIRESUME) % uiwait(handles.figure1); % --- Outputs from this function are returned to the command line. function varargout = AFM_OutputFcn(hObject, eventdata, handles) % varargout cell array for returning output args (see VARARGOUT); % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % Get default command line output from handles structure varargout{1} = handles.output; % --- Executes during object creation, after setting all properties. function axes4_CreateFcn(hObject, eventdata, handles) Xo=[0 0];%起点位置 k=1;%计算引力需要的增益系数 m=1;%计算斥力的增益系数 %n=3;%障碍个数 longth=1.2;%步长 J=2000;%循环迭代次数 %如果不能实现预期目标,可能也与初始的增益系数,Po设置的不合适有关。 K=0;%初始化 %[m_Obs,m_ObsR]=Obs_Generate([5 10],[20 80],[10 80],n); Xj=Xo;%j=1循环初始,将车的起始坐标赋给Xj axis([-20 120 -20 120]); axis equal; hold on; axis off; %set(gcf,'color','y') %fill([-10,110,110,-10],[-10 -10 110 110],'w') fill([-20,120,120,-20],[-20 -20 120 120],'y') %title ('人工势场路径规划'); text(-5,-5,' Start','FontSize',12); fill([95,120,120,95],[-20 -20 10 10],'w') text(100,5,'Notes:','FontSize',12) plot(101,-5,'sb','markerfacecolor','b'); text(101,-5,' Robot','FontSize',12); plot(101,-15,'om','markerfacecolor','m'); text(101,-15,' Ball','FontSize',12); plot(0,0,'bs') car=plot(0,0,'sb','markerfacecolor','b'); %car_name=text(0,0,' ','FontSize',12); object=plot(0,100,'om','markerfacecolor','m'); %object_name=text(0,100,' Ball','FontSize',12); but=1; x_obs=1; y_obs=1; % hObject handle to axes4 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called % Hint: place code in OpeningFcn to populate axes4 % --- Executes on button press in pushbutton1. function pushbutton1_Callback(hObject, eventdata, handles) %main %%%%%%%%%%%%%%%%%%%%%初始化参数%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 Xo=[0 0];%起点位置 k=1;%计算引力需要的增益系数 m=1;%计算斥力的增益系数 %n=3;%障碍个数 longth=1.2;%步长 %循环迭代次数 J=2000; %如果不能实现预期目标,可能也与初始的增益系数,Po设置的不合适有关。 K=0;%初始化 %[m_Obs,m_ObsR]=Obs_Generate([5 10],[20 80],[10 80],n); Xj=Xo;%j=1循环初始,将车的起始坐标赋给Xj axis([-20 120 -20 120]); axis equal; hold on; axis off; %set(gcf,'color','y') %fill([-10,110,110,-10],[-10 -10 110 110],'w') fill([-20,120,120,-20],[-20 -20 120 120],'y') %title ('人工势场路径规划'); text(-5,-5,' Start','FontSize',12); fill([95,120,120,95],[-20 -20 10 10],'w') text(100,5,'Notes:','FontSize',12) plot(101,-5,'sb','markerfacecolor','b'); text(101,-5,' Robot','FontSize',12); plot(101,-15,'om','markerfacecolor','m'); text(101,-15,' Ball','FontSize',12); plot(0,0,'bs') car=plot(0,0,'sb','markerfacecolor','b'); %car_name=text(0,0,' ','FontSize',12); object=plot(0,100,'om','markerfacecolor','m'); %object_name=text(0,100,' Ball','FontSize',12); but=1; x_obs=1; y_obs=1; %pause(1); %选取障碍 %h=msgbox('单击鼠标左键选择障碍,单击右键完成选择','提示'); %uiwait(h,10); %if ishandle(h) == 1 % delete(h); %end num_obs=1; while but == 1 [x_obs,y_obs,but] = ginput(1); if but==1 m_Obs(num_obs,:)=[x_obs y_obs]; m_ObsR(num_obs)=3; %m_Obs=[0 40;20 70;60 50]; Po=min(m_ObsR)/0.5; % for i=1:n Theta=0:pi/20:pi; xx =m_Obs(num_obs,1)+cos(Theta)*m_ObsR(num_obs); yy= m_Obs(num_obs,2)+sin(Theta)*m_ObsR(num_obs); fill(xx,yy,'w') Theta=pi:pi/20:2*pi; xx =m_Obs(num_obs,1)+cos(Theta)*m_ObsR(num_obs); yy= m_Obs(num_obs,2)+sin(Theta)*m_ObsR(num_obs); fill(xx,yy,'k') num_obs=num_obs+1; end %plot(xx,yy,'LineWidth',2); % xval=floor(xval); % yval=floor(yval); % MAP(xval,yval)=-1;%Put on the closed list as well % plot(xval+.5,yval+.5,'ro'); end%End of While loop num_obs=num_obs-1; %object=plot(0,100,'om'); %car=plot(Xo(1),Xo(2),'sb'); %car_name=text(Xo(1),Xo(2),'Robot','FontSize',12); %object_name=text(0,100,'Ball','FontSize',12); %startFlag=pushbutton2_Callback(hObject, eventdata, handles); uiwait; %***************初始化结束,开始主体循环****************** for j=1:J%循环开始 % if j<200 x=j/1.5;y=100; % else % x=100;y=100; %end m_Target=[x,y]; Goal(j,1)=m_Target(1); Goal(j,2)=m_Target(2); Current(j,1)=Xj(1);%Goal保存走过的每个点的坐标。刚开始先将起点放进该向量 Current(j,2)=Xj(2); %调用计算角度模块 [angle_att,angle_rep]=compute_angle(Xj,m_Target,m_Obs,num_obs); %调用计算引力模块 [Fatt,Uatt(j)]=compute_Attract(Xj,m_Target,k,angle_att);
版本:2014a
完整代码或代写加1564658423