坐标变换学习笔记—代码篇Matlab

在Matlab中,旋转量间的变换类不止一个,在 “C:\Program Files\Polyspace\R2020a\toolbox\aero\aero\” 和 “C:\Program Files\Polyspace\R2020a\mcr\toolbox\aero\aero\” 两个目录下均有关于四元数,旋转矩阵,欧拉角间变换的函数文件:

  • 四元数 → \to 旋转矩阵:quat2dcm.m (×,得到式 ( 2.1.2 ) (2.1.2) (2.1.2)对应矩阵的转置)
  • 四元数 → \to 欧拉角:quat2angle.m (√)
  • 旋转矩阵 → \to 四元数:dcm2quat.m(√)
  • 旋转矩阵 → \to 欧拉角:dcm2angle.m(×)
  • 欧拉角 → \to 旋转矩阵:angle2dcm.m(×)
  • 欧拉角 → \to 四元数:angle2quat.m(√)
    而在 “C:\Program Files\Polyspace\R2020a\mcr\toolbox\shared\robotics\robotcore” 目录中,也有这些旋转量之间的转换函数(下面的旋转向量,在Matlab中不展开讨论):
  • 旋转向量 → \to 四元数:axang2quat.m (√)
  • 旋转向量 → \to 旋转矩阵:axang2rotm.m (看不太明白)
  • 四元数 → \to 旋转向量:quat2axang.m (√)
  • 四元数 → \to 旋转矩阵:quat2rotm.m (√)
  • 四元数 → \to 欧拉角:quat2eul.m (√)
  • 旋转矩阵 → \to 旋转向量:rotm2axang.m (√)
  • 旋转矩阵 → \to 四元数:rotm2quat.m (new method)
  • 旋转矩阵 → \to 欧拉角:rotm2eul.m (√)
  • 欧拉角 → \to 旋转矩阵:eul2rotm.m (√)
  • 欧拉角 → \to 四元数:eul2quat.m (√)
    在Matlab中,旋转矩阵,四元数,欧拉角均没有什么特定类型,四元数可用一个1x4的向量表示,旋转矩阵可用3x3的矩阵表示。与Eigen和ROS相比Matlab的优势在于它可以批量将四元数组成的数组批量转换成旋转矩阵或欧拉角数组。

axang2rotm.m中旋转向量转旋转矩阵的实现方式:

% For a single axis-angle vector [ax ay az theta] the output rotation
% matrix R can be computed as follows:
% R = [txx + c txy - zs txz + ys
% txy + zs tyy + c tyz - xs
% txz - ys tyz + xs tzz + c]
% where,
% c = cos(theta)
% s = sin(theta)
% t = 1 - c
% x = normalized axis ax coordinate
% y = normalized axis ay coordinate
% z = normalized axis az coordinate

rotm2axang.m中,旋转矩阵转旋转向量实现方式如下:

theta = real(acos(complex((1/2)(R(1,1,:)+R(2,2,:)+R(3,3,:)-1))));

% Determine initial axis vectors from theta
v = [ R(3,2,:)-R(2,3,:),…
R(1,3,:)-R(3,1,:),…
R(2,1,:)-R(1,2,:)] ./ (repmat(2
sin(theta),[1,3]));

实际上上面是基于理论篇的式 ( 1.2 ) (1.2) (1.2)求欧拉角,式 ( 2.1 ) 和 ( 3.2 ) (2.1)和(3.2) (2.1)(3.2) 来求旋转轴,即:
v = [ 4 q 0 q 1   4 q 0 q 2   4 q 0 q 3 ] T 4 q 0 s i n ( θ 2 ) = [ 4 q 0 q 1   4 q 0 q 2   4 q 0 q 3 ] T 2 s i n ( θ ) v = \frac{[4q_0q_1~4q_0q_2~4q_0q_3]^T}{4q_0 sin(\frac{\theta}{2})} = \frac{[4q_0q_1~4q_0q_2~4q_0q_3]^T}{2sin(\theta)} v=4q0sin(2θ)[4q0q1 4q0q2 4q0q3]T=2sin(θ)[4q0q1 4q0q2 4q0q3]T

Matlab这篇总结的稍微有点粗糙,将就看吧。先说本篇博客基本结论:
(1)在Matlab中,关于旋转量间的变换,强烈建议使用eul, rotm这一类的转换函数,它们默认的欧拉角顺序是ZYX,与ROS中的顺序是一致的,而且符合大多数情况下默认使用方式。
(2)注意点1,Matlab中的欧拉角,不管是eul还是angle相关的方法,对应输入输出的rpy顺序均是:yaw, pitch, roll
(3)注意点2,Matlab中使用的四元数顺序是:w,x,y,z
,与Eigen使用的四元数顺序一致(w,x,y,z), 与ROS使用的四元数顺序相反(x,y,z,w)。

四元数 → \to 旋转矩阵

quat2dcm

quat2dcm.m 中的 m = quat2dcm( q ) 函数用于将四元数转换成旋转矩阵,这里的输入参数q是Mx4的向量,表示M个四元数,而返回值m是一个3x3xM的矩阵,表示M个对应的旋转矩阵。注意,在Matlab中,四元数的顺序是w,x,y,z

function dcm = quat2dcm( q )
%  QUAT2DCM Convert quaternion to direction cosine matrix.
%   N = QUAT2DCM( Q ) calculates the direction cosine matrix, N, for a
%   given quaternion, Q.  Input Q is an M-by-4 matrix containing M
%   quaternions.  N returns a 3-by-3-by-M matrix of direction cosine 
%   matrices.  The direction cosine matrix performs the coordinate
%   transformation of a vector in inertial axes to a vector in body axes.
%   Each element of Q must be a real number.  Additionally, Q has its
%   scalar number as the first column. 
%
%   Examples:
%
%   Determine the direction cosine matrix from q = [1 0 1 0]:
%      dcm = quat2dcm([1 0 1 0])
%
%   Determine the direction cosine matrices from multiple quaternions:
%      q = [1 0 1 0; 1 0.5 0.3 0.1];
%      dcm = quat2dcm(q)
%
%   See also ANGLE2DCM, DCM2ANGLE, DCM2QUAT, ANGLE2QUAT, QUAT2ANGLE, QUATROTATE. 

%   Copyright 2000-2007 The MathWorks, Inc.

qin = quatnormalize( q );  %% quatnormalize 将多维四元数归一化;

dcm = zeros(3,3,size(qin,1));  %% 预先分配内存,加快运行速度;

dcm(1,1,:) = qin(:,1).^2 + qin(:,2).^2 - qin(:,3).^2 - qin(:,4).^2;  %% q_w^2 + q_x^2 - q_y^2 - q_z^2;
dcm(1,2,:) = 2.*(qin(:,2).*qin(:,3) + qin(:,1).*qin(:,4));           %% 2(q_xq_y + q_wq_z);
dcm(1,3,:) = 2.*(qin(:,2).*qin(:,4) - qin(:,1).*qin(:,3));           %% 2(q_xq_z - q_wq_y);
dcm(2,1,:) = 2.*(qin(:,2).*qin(:,3) - qin(:,1).*qin(:,4));           %% 2(q_xq_y - q_wq_z);
dcm(2,2,:) = qin(:,1).^2 - qin(:,2).^2 + qin(:,3).^2 - qin(:,4).^2;  %% q_w^2 - q_x^2 + q_y^2 - q_z^2;
dcm(2,3,:) = 2.*(qin(:,3).*qin(:,4) + qin(:,1).*qin(:,2));           %% 2(q_yq_z + q_wq_x);
dcm(3,1,:) = 2.*(qin(:,2).*qin(:,4) + qin(:,1).*qin(:,3));           %% 2(q_xq_z + q_wq_y);
dcm(3,2,:) = 2.*(qin(:,3).*qin(:,4) - qin(:,1).*qin(:,2));           %% 2(q_yq_z - q_wq_x);
dcm(3,3,:) = qin(:,1).^2 - qin(:,2).^2 - qin(:,3).^2 + qin(:,4).^2;  %% q_w^2 - q_x^2 - q_y^2 + q_z^2;

从上述代码实现可以看到,这里四元数转换旋转矩阵与理论篇中的式 ( 2.1.2 ) (2.1.2) (2.1.2)基本一致。但是,得到的旋转矩阵是 ( 2.1.2 ) (2.1.2) (2.1.2)对应旋转矩阵的转置,这里需要注意

quat2rotm

quat2rotm.m中的quat2rotm函数,输入q为Nx4的四元数,返回值为3x3xN的N维旋转矩阵。q的顺序是:w,x,y,z

function R = quat2rotm( q )
%QUAT2ROTM Convert quaternion to rotation matrix
%   R = QUAT2ROTM(QOBJ) converts a quaternion object, QOBJ, into an orthonormal
%   rotation matrix, R. Each quaternion represents a 3D rotation. 
%   QOBJ is an N-element vector of quaternion objects.
%   The output, R, is an 3-by-3-by-N matrix containing N rotation matrices.
%
%   R = QUAT2ROTM(Q) converts a unit quaternion, Q, into an orthonormal
%   rotation matrix, R. The input, Q, is an N-by-4 matrix containing N quaternions. 
%   Each quaternion represents a 3D rotation and is of the form q = [w x y z], 
%   with w as the scalar number. Each element of Q must be a real number.
%
%   Example:
%      % Convert a quaternion to rotation matrix
%      q = [0.7071 0.7071 0 0];
%      R = quat2rotm(q)
%
%      % Convert a quaternion object
%      qobj = quaternion([sqrt(2)/2 0 sqrt(2)/2 0]);
%      R = quat2rotm(qobj);
%
%   See also rotm2quat, quaternion

%   Copyright 2014-2018 The MathWorks, Inc.

%#codegen

% Validate the quaternions
q = robotics.internal.validation.validateQuaternion(q, 'quat2rotm', 'q');

% Normalize and transpose the quaternions
q = robotics.internal.normalizeRows(q).';

% Reshape the quaternions in the depth dimension
q2 = reshape(q,[4 1 size(q,2)]);

s = q2(1,1,:);
x = q2(2,1,:);
y = q2(3,1,:);
z = q2(4,1,:);

% Explicitly define concatenation dimension for codegen
tempR = cat(1, 1 - 2*(y.^2 + z.^2),   2*(x.*y - s.*z),   2*(x.*z + s.*y),...
2*(x.*y + s.*z), 1 - 2*(x.^2 + z.^2),   2*(y.*z - s.*x),...
2*(x.*z - s.*y),   2*(y.*z + s.*x), 1 - 2*(x.^2 + y.^2) );

R = reshape(tempR, [3, 3, length(s)]);
R = permute(R, [2 1 3]);

end

quat2rotm中的代码实现与里四元数转换旋转矩阵与理论篇中的式 ( 2.1.2 ) (2.1.2) (2.1.2)完全一致。

注意: Matlab中四元数顺序式(w,x,y,z)与Eigen中的四元数顺序(w,x,y,z)一致,它们与ROS中的四元数顺序(x,y,z,w)相反。

四元数 → \to 欧拉角

quat2angle

quat2angle.m 中的 [r1, r2, r3] = quat2dcm( q ) 函数用于将四元数转换成欧拉角,这里的输入参数q是Mx4的向量,表示M个四元数,而返回值r1, r2, r3则是M维的数组,表示从四元数转换回来的欧拉角。quat2dcm(q, s) 函数中的s表示对应的欧拉角的旋转顺序,它的值为: ′ Z Y X ′ , ′ Z Y Z ′ , ′ Z X Y ′ , ′ Z X Z ′ , ′ Y X Z ′ , ′ Y X Y ′ , ′ Y Z X ′ , ′ Y Z Y ′ , ′ X Y Z ′ , ′ X Y X ′ , ′ X Z Y ′ , ′ X Z X ′ . 'ZYX', 'ZYZ', 'ZXY', 'ZXZ', 'YXZ', 'YXY', 'YZX', 'YZY', 'XYZ', 'XYX', 'XZY', 'XZX'. ZYX,ZYZ,ZXY,ZXZ,YXZ,YXY,YZX,YZY,XYZ,XYX,XZY,XZX. 中的一个(默认值为:ZYX),代表依次按照该轴的顺序旋转。(目前对为什么有ZYZ, YZY, XYX,…, 这种某个轴转两次的情况不太清楚(欢迎知道原因的大佬解答),存疑,后面知道再补充)。
对于顺序: ′ Z Y X ′ , ′ Z X Y ′ , ′ Y X Z ′ , ′ Y Z X ′ , ′ X Y Z ′ , ′ X Z Y ′ 'ZYX', 'ZXY', 'YXZ', 'YZX', 'XYZ', 'XZY' ZYX,ZXY,YXZ,YZX,XYZ,XZY,r1,r3角度范围为 − π ∼ π -\pi \thicksim \pi ππ; 而r2的范围为: − π 2 ∼ π 2 -\frac{\pi}{2} \thicksim \frac{\pi}{2} 2π

  • 9
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: MATLAB中的点云坐标变换代码主要使用MATLAB中内置的函数来实现。以下是一个示例代码,用于将一个点云从坐标系A转换到坐标系B。 ```matlab % 假设点云数据已经加载到变量pointCloudA中,每一行是一个点的坐标 % 假设坐标系变换矩阵已经定义为变量transformationMatrix % 将点云A转换到点云B的坐标系 pointCloudB = pointCloudA * transformationMatrix; % 显示点云B figure; scatter3(pointCloudB(:,1), pointCloudB(:,2), pointCloudB(:,3), 'filled'); xlabel('X'); ylabel('Y'); zlabel('Z'); ``` 在上述代码中,`pointCloudA`是表示点云的矩阵,每一行包含一个点的坐标,共有N个点。`transformationMatrix`是一个4x4的变换矩阵,它定义了坐标系A到坐标系B的转换关系。 通过将点云矩阵`pointCloudA`与变换矩阵`transformationMatrix`相乘,就可以得到转换后的点云矩阵`pointCloudB`,其中每个点的坐标都已经在新的坐标系B中。 最后,使用`scatter3`函数将点云B的坐标进行可视化,其中`pointCloudB(:,1)`,`pointCloudB(:,2)`和`pointCloudB(:,3)`分别表示x、y和z坐标。 ### 回答2: 在Matlab中,可以使用PointCloud对象和相应的内置函数来进行点云坐标变换。 首先,需要导入点云数据。可以通过readPcd函数从PCD文件中读取点云数据。例如,假设我们要读取名为"pointcloud.pcd"的文件,可以使用以下代码进行读取: ``` ptCloud = pcread('pointcloud.pcd'); ``` 接下来,可以使用pcshow函数来显示点云。例如,以下代码将显示ptCloud对象中的点云数据: ``` pcshow(ptCloud); ``` 坐标变换的常见操作之一是平移。假设我们要将点云在x轴上平移1个单位,可以使用以下代码进行操作: ``` translationVector = [1, 0, 0]; % 平移向量 ptCloud = pctransform(ptCloud, affine3d(translationVector)); ``` 另一个常见的操作是旋转。假设我们要将点云绕z轴旋转90度,可以使用以下代码进行操作: ``` rotationAngle = 90; % 旋转角度(度) rotationMatrix = [cosd(rotationAngle), -sind(rotationAngle), 0; sind(rotationAngle), cosd(rotationAngle), 0; 0, 0, 1]; % 旋转矩阵 ptCloud = pctransform(ptCloud, affine3d(rotationMatrix)); ``` 其他常见的坐标变换操作包括缩放、镜像和剪切,可以使用相应的功能函数和矩阵完成。 完成坐标变换后,可以使用pcshow函数显示变换后的点云: ``` pcshow(ptCloud); ``` 最后,可以通过writePcd函数将变换后的点云保存到PCD文件中。以下代码将保存ptCloud对象为名为"transformed_pointcloud.pcd"的文件: ``` pctoolspath('change','1.0'); pcwrite(ptCloud, 'transformed_pointcloud.pcd'); ``` 综上所述,以上是使用Matlab进行点云坐标变换代码示例。当然,具体的实现会根据具体的坐标变换需求和点云数据格式而有所不同。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值