首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >两个三维矢量夹角的Matlab atan2

两个三维矢量夹角的Matlab atan2
EN

Stack Overflow用户
提问于 2017-07-19 15:55:38
回答 1查看 1.6K关注 0票数 1

我需要计算两架飞机之间的角度。一个平面是手平面,第二个平面是前臂平面。我计算了该平面的法线,并在MATLAB中使用了公式atan2(norm(cross(var.n1,var.n2)),dot(var.n1,var.n2));。我想看看手腕的弯曲/伸展角,它的特征是正的和负的峰值,但是用这个公式,我只能得到正的峰值。

代码语言:javascript
复制
%% Script to compute the angles of wrist flexion/extension and adduction/abduction based on Vicon data
% REF: Cheryl et al., March 2008
% Order of the markers: 1.WRR 2.WRU 3.FAU 4.FAR 5.CMC2 6.CMC5 7.MCP5 8.MCP2

clc
close all
clear all

%% Initialization
% dir_kinematic = input('Path of the folder containing the kinematic files: ','s');
dir_kinematic = 'C:\Users\Utente\Desktop\TESI\Vicon\test.mat';
cd(dir_kinematic);

fileList = getAllFiles(dir_kinematic,0); % Get names of all kinematic files
f=1;
%% Conversion to angles
 for f = 1:length(fileList)
    if ~isempty(strfind(fileList{f},'mat')) % Take only mat files


        % 0. Loading
        load(fileList{f});

        % 1. Filtering
        frameRate = kinematic.framerate;
        n = 9; 
        Wn = 2/(frameRate/2);
        ftype = 'low';
        [b,a] = butter(n,Wn,ftype);
        kinematic.x = filtfilt(b,a,kinematic.x);
        kinematic.y = filtfilt(b,a,kinematic.y);
        kinematic.z = filtfilt(b,a,kinematic.z);


        % 2. Create vectors
        var.n=length(kinematic.x);

        % Forearm plane
        var.FAU_WRU=[kinematic.x(:,2)-kinematic.x(:,3),kinematic.y(:,2)-kinematic.y(:,3),kinematic.z(:,2)-kinematic.z(:,3)];
        var.WRR_WRU=[kinematic.x(:,2)-kinematic.x(:,1),kinematic.y(:,2)-kinematic.y(:,1),kinematic.z(:,2)-kinematic.z(:,1)];

        % Hand plane
        var.CMC5_MCP5=[kinematic.x(:,7)-kinematic.x(:,6),kinematic.y(:,7)-kinematic.y(:,6),kinematic.z(:,7)-kinematic.z(:,6)];
        var.MCP2_MCP5=[kinematic.x(:,7)-kinematic.x(:,8),kinematic.y(:,7)-kinematic.y(:,8),kinematic.z(:,7)-kinematic.z(:,8)];

        % Transpose
        var.FAU_WRU = var.FAU_WRU';
        var.WRR_WRU = var.WRR_WRU';
        var.CMC5_MCP5 = var.CMC5_MCP5';
        var.MCP2_MCP5 = var.MCP2_MCP5';

        % 3. Calculate angle of wrist flexion/extension
        % Cross vector function for all time => create normal vector plane
        var.forearm_n=[];
        var.hand_n=[];
        var.theta_rad=[];

        for i = 1:var.n % Loop through experiment

            % vector x and y of the forearm plane
            var.v1=var.FAU_WRU(:,i); % take x,y,z of the vector for every time
            var.v2=var.WRR_WRU(:,i);

            % vector x and y of the hand plane
            var.v3=var.CMC5_MCP5(:,i);
            var.v4=var.MCP2_MCP5(:,i);

            var.forearm_n= [var.forearm_n, cross(var.v1,var.v2)];  
            var.hand_n=[var.hand_n, cross(var.v3,var.v4)];

        end

        % Calculate angle  
        for i = 1:var.n

            var.n1=(var.forearm_n(:,i)); 
            var.n2=var.hand_n(:,i);

            var.scalar_product(i) = dot(var.n1,var.n2); 

            %Equation (2) of the paper
            var.theta_rad=[var.theta_rad, atan2(norm(cross(var.n1,var.n2)),dot(var.n1,var.n2))]; % result in radian

            angle.flex_deflex_wrist{f}=(var.theta_rad*180)/pi;

        end

        % 4. Calculate angle of wrist adduction/abduction

        % Projection vector onto plane 

        var.MCP2_MCP5_forearmproj=[];
        var.WRR_WRU_forearmproj=[];
        var.rad_ul_angle_rad=[];

        for i=1:var.n

            %take x,y,z of the vector for each time
            var.v1=var.MCP2_MCP5(:,i);
            var.v2=var.WRR_WRU(:,i);

            % vector x and y of the forearm plane
            var.vfx=var.FAU_WRU(:,i); % take x,y,z of the vector for every time
            var.vfy=var.WRR_WRU(:,i);

            %projection of vector MCP2_MCP5 and WRR_WRU onto forearm plane
            var.squNorm1=(norm(var.vfx)*norm(var.vfx));
            var.squNorm2=(norm(var.vfy)*norm(var.vfy));

            var.MCP2_MCP5_forearmproj=[var.MCP2_MCP5_forearmproj,((((var.v1')*var.vfx)*var.vfx/var.squNorm1)+(((var.v1')*var.vfy)*var.vfy/var.squNorm2))];
            var.WRR_WRU_forearmproj=[var.WRR_WRU_forearmproj,((var.vfx*((var.v2')*var.vfx/var.squNorm1))+(var.vfy*((var.v2')*var.vfy/var.squNorm2)))];
        end

        % Calculate angle

        for i=1:var.n

            var.n1=var.MCP2_MCP5_forearmproj(:,i)';
            var.n2=var.WRR_WRU_forearmproj(:,i);
            var.product=var.n1*var.n2;

            var.rad_ul_angle_rad=[var.rad_ul_angle_rad, atan2(norm(cross(var.n1,var.n2)),dot(var.n1,var.n2))];% en rad
            angle.rad_ul_wrist{f}=(var.rad_ul_angle_rad*180)/pi;
        end

    end
end

我想知道为什么我的角度总是正面的?我要看到正负两峰..。谢谢你的帮助!

EN

回答 1

Stack Overflow用户

发布于 2017-07-19 17:33:33

由于两个平面之间的角度和法线之间的角度是相同的,我将把讨论限制在两个向量之间的角度上。

我们知道,两个向量(ab)之间的交叉积是另一个垂直于它们的向量。

我们正在讨论区分角-T和+T的问题,其中T是某个角度。

使用您使用的公式,这两个角度将得到相同的结果,因为使用的基本公式本身: atan2 (a,x,b,a.b)

这是因为,虽然a.b在两种情况下都是相同的,但a.b完全不同,完全不同于这两个向量的法向符号,而没有其他任何东西(用手工规则验证自己)。当我们计算这个向量的范数时,它的符号信息就会丢失,因此函数总是返回正值。

你能做些什么

您需要跟踪a x b的符号,以确定角度是正的还是负的。

注意:由于我正在回复我的手机,我无法添加更好的格式或代码,将很快更新答案。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45195534

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档