2

2D アッセイで動物の x 位置と y 位置を経時的に記録したデータが、matlab マトリックスに格納されています。これらの座標を経時的にプロットし、速度情報を抽出して、クラインを使用してこれをプロットできます。

私が現在抱えている問題は、進行方向の角度を計算することです。それは些細な三角法の質問であるべきですが、私は始めるのに最善の方法で空白を描いています.

データは、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 の範囲にするにはどうすればよいですか?

4

2 に答える 2

3

関数を使用して、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);

私がそこで行ったこと: 変数の 1 つ (dDegまたはdDeg2) は位相ラップを認識せず、min関数はどれを見つけます (絶対差が小さくなります)。はそのsub2ind数値を検索し (正または負のいずれかですが、2 つのうちの小さい方です)、その値が になりますresult

于 2013-09-27T21:21:31.170 に答える
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)];

以下が得られます。

プロット例 1

そして、あなたがあなたのことをすれば、あなたは得る

プロット例 2

小さな赤い線が元のデータ ポイントから始まり、次のポイントの方向に移動していることに注意してください。これは、ポイントを結ぶ元の青い線と同じです。

diffまた、コード内で を使用して、すべてのポイントを一度に適切に区別することにも注意してください。これはより高速で、方向に関する問題を回避します。あなたの場合、それが交換されたように見えます。

于 2013-09-27T21:37:05.813 に答える