matlab - Symbolic gradient differing wildly from analytic gradient -
i trying simulate network of mobile robots uses artificial potential fields movement planning shared destination xd. done generating series of m-files (one each robot) symbolic expression, seems best way in terms of computational time , accuracy. however, can't figure out going wrong gradient computation: analytical gradient being computed seems faulty, while numerical gradient calculated correctly (see image posted below). have written mwe listed below, exhibits problem. have checked file generating part of code, , return correct function file correct gradient. can't figure out why analytic , numerical gradient different.
(a larger version of image below can found here)
% create symbolic variables xd = sym('xd',[1 2]); x = sym('x',[2 2]); % create potential function , gradient function both (x,y) pairs % in x i=1:size(x,1) phi = norm(x(i,:)-xd)/norm(x(1,:)-x(2,:)); % potential field function xvector = reshape(x.',1,size(x,1)*size(x,2)); % reshape x allow gradient computation grad = gradient(phi,xvector(2*i-1:2*i)); % compute gradient gradx = grad(1);grady=grad(2); % split gradient in 2 components % create function file names gradfun = strcat('gradtester',int2str(i),'.m'); phifun = strcat('pottester',int2str(i),'.m'); % generate 2 output files matlabfunction(gradx, grady,'file',gradfun,'outputs',{'gradx','grady'},'vars',{xvector, xd}); matlabfunction(phi,'file',phifun,'vars',{xvector, xd}); end clear % make sure workspace empty: functions in files pause(0.1) % ensure function file has been generated before called % these later overwritten specific case, can used % debugging x = 0.5*rand(2); xd = 0.5*rand(1,2); % values stackoverflow case x = [0.0533 0.0023; 0.4809 0.3875]; xd = [0.4087 0.4343]; xp = x; % dummy variable keep x intact % compute potential field , gradient both (x,y) pairs i=1:size(x,1) % create grid centered on selected (x,y) pair xgrid = (x(i,1)-0.1):0.005:(x(i,1)+0.1); ygrid = (x(i,2)-0.1):0.005:(x(i,2)+0.1); % preallocate gradient , potential matrices gradx = zeros(length(xgrid),length(ygrid)); grady = zeros(length(xgrid),length(ygrid)); phi = zeros(length(xgrid),length(ygrid)); % generate appropriate function handles fun = str2func(strcat('gradtester',int2str(i))); fun2 = str2func(strcat('pottester',int2str(i))); % compute analytic gradient , potential each position in xgrid , % ygrid vectors ii = 1:length(ygrid) jj = 1:length(xgrid) xp(i,:) = [xgrid(ii) ygrid(jj)]; % select position xvec = reshape(xp.',1,size(x,1)*size(x,2)); % turn input vector [gradx(ii,jj),grady(ii,jj)] = fun(xvec,xd); % compute gradients phi(jj,ii) = fun2(xvec,xd); % compute potential value end end [fx,fy] = gradient(phi); % compute numerical gradient comparison %scale numerical gradient fx = fx/0.005; fy = fy/0.005; % plot analytic result subplot(2,2,2*i-1) hold xlim([xgrid(1) xgrid(end)]); ylim([ygrid(1) ygrid(end)]); quiver(xgrid,ygrid,-gradx,-grady) contour(xgrid,ygrid,phi) title(strcat('analytic result position ',int2str(i))); xlabel('x'); ylabel('y'); subplot(2,2,2*i) hold xlim([xgrid(1) xgrid(end)]); ylim([ygrid(1) ygrid(end)]); quiver(xgrid,ygrid,-fx,-fy) contour(xgrid,ygrid,phi) title(strcat('numerical result position ',int2str(i))); xlabel('x'); ylabel('y'); end
the potential field trying generate defined (x,y) position, in code called xd
. x
position matrix of dimension n x 2, first column represents x1, x2, , on, , second column represents y1, y2, , on. xvec reshaping of vector x1,y1,x2,y2,x3,y3 , on, matlabfunction generating accepts vector inputs.
the gradient robot being calculated taking derivative w.r.t. x_i , y_i, these 2 components yield single derivative 'vector' shown in quiver plots. derivative should this, , checked symbolic expression [gradx,grady] indeed looks before m-file generated.
to fix particular problem given in question, calculating phi
in such way meant doing gradient(phi)
not giving correct results compared symbolic gradient. i'll try , explain. here how created xgrid
, ygrid
:
% create grid centered on selected (x,y) pair xgrid = (x(i,1)-0.1):0.005:(x(i,1)+0.1); ygrid = (x(i,2)-0.1):0.005:(x(i,2)+0.1);
but in for
loop, ii
, jj
used phi(jj,ii)
or gradx(ii,jj)
, corresponding same physical position. why results different. problem had used gradient
incorrectly. matlab assumes [fx,fy]=gradient(phi)
means phi
calculated phi=f(x,y)
x
, y
matrices created using meshgrid
. had elements of phi
arranged differently that, gradient(phi)
gave wrong answer. between reversing jj
, ii
, , incorrect gradient, errors cancelled out (i suspect tried doing phi(jj,ii)
after trying phi(ii,jj)
first , finding didn't work).
anyway, sort out, on line after create xgrid
, ygrid
, put in:
[x,y]=meshgrid(xgrid,ygrid);
then change code after load fun
, fun2
to:
for ii = 1:length(xgrid) %// x loop jj = 1:length(ygrid) %// y loop xp(i,:) = [x(ii,jj);y(ii,jj)]; %// using x , y not xgrid , ygrid xvec = reshape(xp.',1,size(x,1)*size(x,2)); [gradx(ii,jj),grady(ii,jj)] = fun(xvec,xd); phi(ii,jj) = fun2(xvec,xd); end end [fx,fy] = gradient(phi,0.005); %// use second argument of gradient set spacing subplot(2,2,2*i-1) hold axis([min(x(:)) max(x(:)) min(y(:)) max(y(:))]) %// use axis rather xlim/ylim quiver(x,y,gradx,grady) contour(x,y,phi) title(strcat('analytic result position ',int2str(i))); xlabel('x'); ylabel('y'); subplot(2,2,2*i) hold axis([min(x(:)) max(x(:)) min(y(:)) max(y(:))]) quiver(x,y,fx,fy) contour(x,y,phi) title(strcat('numerical result position ',int2str(i))); xlabel('x'); ylabel('y');
i have other comments code. think potential function ill-defined, causing sorts of problems. in question x
nx2 matrix, potential function defined as
norm(x(i,:)-xd)/norm(x(1,:)-x(2,:));
which means if n
three, you'd have following 3 potentials:
norm(x(1,:)-xd)/norm(x(1,:)-x(2,:)); norm(x(2,:)-xd)/norm(x(1,:)-x(2,:)); norm(x(3,:)-xd)/norm(x(1,:)-x(2,:));
and don't think third 1 makes sense. think causing confusion gradients.
also, i'm not sure if there reason create .m
file functions in real code, not necessary code posted.
Comments
Post a Comment