我正在尝试模拟移动机器人网络,该网络使用人工潜在字段进行移动规划到共享目标xd。这是通过从符号表达式生成一系列m文件(每个机器人一个)来完成的,因为这似乎是计算时间和准确性方面的最佳方式。但是,我无法弄清楚我的梯度计算出了什么问题:正在计算的分析梯度似乎有问题,而数值梯度计算正确(参见下面的图片)。我写了一个下面列出的MWE,它也表现出这个问题。我检查了生成部分代码的文件,它确实返回了一个正确的梯度函数文件。但我无法弄清楚为何分析和数值梯度如此不同。
(可以找到下面图片的更大版本here)
% 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文件。
答案 0 :(得分:2)
要解决问题中给出的特定问题,您实际上是以这样的方式计算phi
,这意味着您执行gradient(phi)
与符号渐变相比没有给出正确的结果。我试着解释一下。以下是您创建xGrid
和yGrid
的方式:
% 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
循环中,ii
和jj
被用作phi(jj,ii)
或gradx(ii,jj)
,但对应于相同的物理位置。这就是你的结果不同的原因。您遇到的另一个问题是您错误地使用了gradient
。 Matlab假设[FX,FY]=gradient(phi)
表示phi
是根据phi=f(x,y)
计算的,其中x
和y
是使用meshgrid
创建的矩阵。您有效地将phi
的元素排列为不同的元素,因此gradient(phi)
给出了错误的答案。在撤消jj
和ii
之间以及错误的渐变之间,错误被取消了(我怀疑您在尝试phi(jj,ii)
之后尝试phi(ii,jj)
并且发现它没有“{1}}。工作)。
无论如何,要在创建xGrid
和yGrid
后的行中对其进行排序,请将其放入:
[X,Y]=meshgrid(xGrid,yGrid);
然后在将fun
和fun2
加载到
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
文件函数,但对于您发布的代码,它们不是必需的。