符号梯度与分析梯度差别很大

时间:2014-11-27 12:20:31

标签: matlab matlab-figure

我正在尝试模拟移动机器人网络,该网络使用人工潜在字段进行移动规划到共享目标xd。这是通过从符号表达式生成一系列m文件(每个机器人一个)来完成的,因为这似乎是计算时间和准确性方面的最佳方式。但是,我无法弄清楚我的梯度计算出了什么问题:正在计算的分析梯度似乎有问题,而数值梯度计算正确(参见下面的图片)。我写了一个下面列出的MWE,它也表现出这个问题。我检查了生成部分代码的文件,它确实返回了一个正确的梯度函数文件。但我无法弄清楚为何分析和数值梯度如此不同。

(可以找到下面图片的更大版本here

Faulty gradient computation

% create symbolic variables
xd = sym('xd',[1 2]);
x = sym('x',[2 2]);

% create a potential function and a gradient function for both (x,y) pairs
% in x
for 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 to allow for gradient computation
grad = gradient(phi,xvector(2*i-1:2*i));            % compute the gradient
gradx = grad(1);grady=grad(2);                      % split the gradient in two components

% create function file names
gradfun = strcat('GradTester',int2str(i),'.m');     
phifun = strcat('PotTester',int2str(i),'.m');       

% generate two output files
matlabFunction(gradx, grady,'file',gradfun,'outputs',{'gradx','grady'},'vars',{xvector, xd});
matlabFunction(phi,'file',phifun,'vars',{xvector, xd});

end

clear all               % make sure the workspace is empty: the functions are in the files

pause(0.1)              % ensure the function file has been generated before it is called

% these are later overwritten by a specific case, but they can be used for
% debugging
x = 0.5*rand(2);
xd = 0.5*rand(1,2);

% values for the Stackoverflow case
x = [0.0533    0.0023;
     0.4809    0.3875];
xd = [0.4087    0.4343];

xp = x;     % dummy variable to keep x intact

% compute potential field and gradient for both (x,y) pairs
for i=1:size(x,1)

    % create a grid centered on the 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 the gradient and 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 and potential for each position in the xGrid and
    % yGrid vectors
    for ii = 1:length(yGrid)
        for jj = 1:length(xGrid)

            xp(i,:) = [xGrid(ii) yGrid(jj)];                % select the position
            Xvec = reshape(xp.',1,size(x,1)*size(x,2));     % turn the input into a 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 the NUMERICAL gradient for comparison

    %scale the numerical gradient
    FX = FX/0.005;
    FY = FY/0.005;

    % plot analytic result
    subplot(2,2,2*i-1)
    hold all
    xlim([xGrid(1) xGrid(end)]);
    ylim([yGrid(1) yGrid(end)]);
    quiver(xGrid,yGrid,-gradx,-grady)
    contour(xGrid,yGrid,phi)
    title(strcat('Analytic result for position ',int2str(i)));
    xlabel('x');
    ylabel('y');

    subplot(2,2,2*i)
    hold all
    xlim([xGrid(1) xGrid(end)]);
    ylim([yGrid(1) yGrid(end)]);
    quiver(xGrid,yGrid,-FX,-FY)
    contour(xGrid,yGrid,phi)
    title(strcat('Numerical result for position ',int2str(i)));
    xlabel('x');
    ylabel('y');

end

我想要生成的潜在字段由我的代码xd中的(x,y)位置定义。 x是维度N x 2的位置矩阵,其中第一列表示x1,x2,依此类推,第二列表示y1,y2,依此类推。 Xvec只是将这个向量重新整形为x1,y1,x2,y2,x3,y3等等,因为我生成的matlab函数只接受向量输入。

机器人i的梯度是通过取导数w.r.t来计算的。 x_i和y_i,这两个组件一起产生单个导数'向量'在箭袋图中显示。导数应该看起来像this,我检查了[gradx,grady]的符号表达式确实看起来像之前生成了一个m文件。

1 个答案:

答案 0 :(得分:2)

要解决问题中给出的特定问题,您实际上是以这样的方式计算phi,这意味着您执行gradient(phi)与符号渐变相比没有给出正确的结果。我试着解释一下。以下是您创建xGridyGrid的方式:

% create a grid centered on the 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);

但是在for循环中,iijj被用作phi(jj,ii)gradx(ii,jj),但对应于相同的物理位置。这就是你的结果不同的原因。您遇到的另一个问题是您错误地使用了gradient。 Matlab假设[FX,FY]=gradient(phi)表示phi是根据phi=f(x,y)计算的,其中xy是使用meshgrid创建的矩阵。您有效地将phi的元素排列为不同的元素,因此gradient(phi)给出了错误的答案。在撤消jjii之间以及错误的渐变之间,错误被取消了(我怀疑您在尝试phi(jj,ii)之后尝试phi(ii,jj)并且发现它没有“{1}}。工作)。

无论如何,要在创建xGridyGrid后的行中对其进行排序,请将其放入:

[X,Y]=meshgrid(xGrid,yGrid);

然后在将funfun2加载到

后更改代码
for ii = 1:length(xGrid) %// x loop
    for jj = 1:length(yGrid) %// y loop
        xp(i,:) = [X(ii,jj);Y(ii,jj)]; %// using X and Y not xGrid and 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 the second argument of gradient to set spacing

subplot(2,2,2*i-1)
hold all
axis([min(X(:)) max(X(:)) min(Y(:)) max(Y(:))]) %// use axis rather than xlim/ylim
quiver(X,Y,gradx,grady)
contour(X,Y,phi)
title(strcat('Analytic result for position ',int2str(i)));
xlabel('x');
ylabel('y');

subplot(2,2,2*i)
hold all
axis([min(X(:)) max(X(:)) min(Y(:)) max(Y(:))])
quiver(X,Y,FX,FY)
contour(X,Y,phi)
title(strcat('Numerical result for position ',int2str(i)));
xlabel('x');
ylabel('y');

我对您的代码有其他一些评论。我认为你的潜在功能是不明确的,这会导致各种各样的问题。你在问题中说x是一个Nx2矩阵,但你的潜在函数被定义为

norm(x(i,:)-xd)/norm(x(1,:)-x(2,:));

这意味着如果N为3,则您有以下三种潜力:

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,:));

我并不认为第三个是有道理的。我认为这可能会导致与渐变的混淆。

另外,我不确定是否有理由在您的实际代码中创建.m文件函数,但对于您发布的代码,它们不是必需的。