根据x和y信息计算航向角

时间:2013-09-27 19:36:27

标签: matlab

我有数据记录存储在matlab矩阵中的动物在2D测定中随时间的x和y位置。我可以随着时间的推移绘制这些坐标,并提取速度信息并使用cline进行绘图。

我目前遇到的问题是计算航向角。这应该是一个微不足道的三角学问题,但我在最好的开始方式上画了一个空白。

数据存储在表示x和y坐标的矩阵xy中:

    796.995391705069    151.755760368664
    794.490825688073    150.036697247706
    788.098591549296    145.854460093897
    786.617021276596    144.327659574468
    781.125000000000    140.093750000000
    779.297872340426    138.072340425532
    775.294642857143    133.879464285714

我希望能够知道从(796.995,151.755)到(794.490,150.036)绘制的线的角度,依此类推。我的研究表明atan2将是适当的功能,但我不确定如何正确地调用它来提供有用的信息。

    difx = xy(1,1) - xy(2,1);
    dify = xy(1,2) - xy(2,2);
    angle = atan2(dify,difx);
    angle = angle*180/pi % convert to degrees

结果是34.4646。这是对的吗?

如果正确,我如何让该值在0-360范围内?

2 个答案:

答案 0 :(得分:2)

您可以使用diff功能一次性获取所有差异:

dxy = diff(xy); % will contain [xy(2,1)-xy(1,1) xy(2,2)-xy(1,2); ...

然后使用atan2函数计算角度:

a = atan2(dxy(:,2), dxy(:,1)); 

您使用

转换为度数
aDeg = 180 * a / pi;

最后取模360的角度使其在0到360之间:

aDeg = mod(aDeg, 360);

所以 - 你几乎做对了,是的。除了你已经计算了从第2点到第1点的航向,我怀疑你想从1开始向2方向移动。这会给你一个负数 - 或模360,一个大约325度的角度。

此外,使用diff函数可以同时获得整个标题数组,这比代码略有改进。 [rc mi] = 编辑“阶段包装”的问题 - 当标题从359变为0时 - 是一个非常常见的问题。如果您有兴趣知道何时发生大的变化,您可以尝试以下技巧(使用上面的aDeg - 度数角度)。

dDeg1 = diff(aDeg);  % the change in angle
dDeg2 = diff(mod(aDeg + 90, 360)); % we moved the phase wrap point by 180 degrees
dDeg12 = [dDeg1(:) dDeg2(:)]';
[rc mi]= min(abs(dDeg12));
indx = sub2ind(size(dDeg12), mi, 1:size(dDeg12, 2));
result = dDeg12(ii);

我在那里做了什么:其中一个变量(dDegdDeg2)没有看到相位换行,min函数找出哪一个(它会有一个更小的变量)绝对差异)。 sub2ind查找该数字(它是正数还是负数 - 但它是两者中较小的一个),这是result中结束的值。

答案 1 :(得分:1)

您可以通过绘制从第一个点开始并在标题方向结束的小线来验证角度。如果角度正确,它将指向xy中下一个点的方向。一切都取决于你在哪里定义0度(直线向上,比方说),以及正度是逆时针(我做)还是顺时针旋转。在MATLAB中,你可以得到0到360之间的数字,但是使用模数---或者你可以只为你的结果加180,但这将改变0度标记所在的定义。

我制作了以下有点复杂的脚本,但展示了如何计算矢量格式中所有点的标题/角度,然后显示它们。

xy =[ 796.995391705069    151.755760368664
    794.490825688073    150.036697247706
    788.098591549296    145.854460093897
    786.617021276596    144.327659574468
    781.125000000000    140.093750000000
    779.297872340426    138.072340425532
    775.294642857143    133.879464285714];
% t = linspace(0,3/2*pi, 14)';
% xy = [sin(t), cos(t)];

% calculate the angle:
myDiff = diff(xy);
myAngle = mod(atan2(myDiff(:,1), myDiff(:,2))*180/pi, 360);

% Plot the original Data:
figure(1);
clf;
subplot(1,3,1);
plot(xy(:,1), xy(:,2), '-bx', 'markersize', 12);
hold all
axis equal;grid on;
title('Original Data');

% Plot the calculated angle:
subplot(1,3,2);
plot(myAngle);
axis tight; grid on;
title('Heading');

% Now plot the result with little lines pointing int he heading:
subplot(1,3,3);
plot(xy(:,1), xy(:,2), '-bx', 'markersize', 12);
hold all

% Just for visualization:
vectorLength = max(.8, norm(xy(1,:)- xy(2,:)));

for ind = 1:length(xy)-1
    startPoint = xy(ind,:)';
    endPoint = startPoint + vectorLength*[sind(myAngle(ind)); cosd(myAngle(ind))];
    myLine = [startPoint, endPoint];
    plot(myLine(1,:), myLine(2, :), ':r ', 'linewidth', 2)
end

axis equal;grid on;
title('Original Data with Heading Drawn On');

例如,如果您使用我的测试数据

t = linspace(0,3/2*pi, 14)';
xy = [sin(t), cos(t)];

您将获得以下内容:

example plot 1

如果你做了你的话,你会得到

example plot 2

注意小红线是如何从原始数据点开始并沿着下一个点的方向移动---就像连接点的原始蓝线一样。

另请注意,在代码中使用diff可以立即正确区分所有点。这样更快,避免了方向的任何问题 - 看起来像你的情况,它被交换。