a × b = [ 0 − a 3 a 2 a 3 0 − a 1 − a 2 a 1 0 ] b a\times b= \begin{bmatrix} 0 && -a_3 && a_2 \\ a_3 && 0 && -a_1 \\ -a_2 && a_1 && 0 \end{bmatrix} b a×b=⎣⎡0a3−a2−a30a1a2−a10⎦⎤b
记作a^b,其中 ^是反对称符号。
向量的内外积即使在不谈论它们的坐标时也可以计算,例如内积可以通过长度和夹角来计算。
两个坐标系之间的运动由旋转加上平移组成,称为刚体运动
对于两个坐标系下的两组坐标表示的同一个向量,有
[ e 1 e 2 e 3 ] [ a 1 a 2 a 3 ] = [ e 1 ′ e 2 ′ e 3 ′ ] [ a 1 ′ a 2 ′ a 3 ′ ] \begin{bmatrix} e_1 && e_2 && e_3 \end{bmatrix} \begin{bmatrix} a_1 \\ a_2 \\ a_3 \end{bmatrix}= \begin{bmatrix} e_1' && e_2' && e_3' \end{bmatrix} \begin{bmatrix} a_1' \\ a_2' \\ a_3' \end{bmatrix} [e1e2e3]⎣⎡a1a2a3⎦⎤=[e1′e2′e3′]⎣⎡a1′a2′a3′⎦⎤
左右两边同时左乘 [ e 1 e 2 e 3 ] T \begin{bmatrix}e_1 && e_2 && e_3\end{bmatrix}^T [e1e2e3]T得
[ a 1 a 2 a 3 ] = [ e 1 T e 1 ′ e 1 T e 2 ′ e 1 T e 3 ′ e 2 T e 1 ′ e 2 T e 2 ′ e 2 T e 3 ′ e 3 T e 1 ′ e 3 T e 2 ′ e 3 T e 3 ′ ] [ a 1 ′ a 2 ′ a 3 ′ ] = R a ′ \begin{bmatrix} a_1 \\ a_2 \\ a_3 \end{bmatrix}= \begin{bmatrix} e_1^Te_1' && e_1^Te_2' && e_1^Te_3' \\ e_2^Te_1' && e_2^Te_2' && e_2^Te_3' \\ e_3^Te_1' && e_3^Te_2' && e_3^Te_3' \end{bmatrix} \begin{bmatrix} a_1' \\ a_2' \\ a_3' \end{bmatrix}= Ra' ⎣⎡a1a2a3⎦⎤=⎣⎡e1Te1′e2Te1′e3Te1′e1Te2′e2Te2′e3Te2′e1Te3′e2Te3′e3Te3′⎦⎤⎣⎡a1′a2′a3′⎦⎤=Ra′
R的各分量是两个坐标系基的内积,由于基向量的长度为一,因此每个分量其实是基向量夹角的余弦值。
行列式为1的正交矩阵,可以将n维旋转矩阵的集合定义如下:
S O ( n ) = { R ∈ R n × n ∣ R R T = I , det ( R ) = 1 } SO(n)=\{R\in \R^{n\times n}|RR^T=I,\det(R)=1\} SO(n)={R∈Rn×n∣RRT=I,det(R)=1}
SO(n)称为特殊正交群
进而有 a ′ = R − 1 a = R T a a'=R^{-1}a=R^Ta a′=R−1a=RTa
a ′ = R a + t a'=Ra+t a′=Ra+t
考虑坐标系1,2,a在两个坐标系下的坐标分别为 a 1 a_1 a1, a 2 a_2 a2:
a 1 = R 12 a 2 + t 12 a_1=R_{12}a_2+t_{12} a1=R12a2+t12
其中, R 12 R_{12} R12表示把坐标系2的向量变换到坐标系1中。
t 12 t_{12} t12对应的是坐标系1原点指向坐标系2原点的向量,在坐标系1下取的坐标。
注: t 12 ≠ t 21 t_{12}\neq t_{21} t12=t21
变换关系不是线性关系
b = R 1 a + t 1 c = R 2 b + t 2 b=R_1a+t_1 \qquad c=R_2b+t_2 b=R1a+t1c=R2b+t2
则有 c = R 2 ( R 1 a + t 1 ) + t 2 c=R_2(R_1a+t_1)+t_2 c=R2(R1a+t1)+t2
[ a ′ 1 ] = [ R t 0 T 1 ] [ a 1 ] = T [ a 1 ] \begin{bmatrix}a' \\ 1\end{bmatrix}= \begin{bmatrix} R && t\\0^T && 1 \end{bmatrix}\begin{bmatrix}a\\ 1\end{bmatrix}= T\begin{bmatrix}a\\ 1\end{bmatrix} [a′1]=[R0Tt1][a1]=T[a1]
T称为变换矩阵
S E ( 3 ) = { T = [ R t 0 T 1 ] ∈ R 4 × 4 ∣ R ∈ S O ( 3 ) , t ∈ R 3 } SE(3)=\{T=\begin{bmatrix}R&&t\\0^T&&1\end{bmatrix}\in R^{4\times 4}|R\in SO(3),t\in R^3\} SE(3)={T=[R0Tt1]∈R4×4∣R∈SO(3),t∈R3}
T − 1 = [ R T − R T t 0 T 1 ] T^{-1}= \begin{bmatrix} R^T && -R^Tt \\ 0^T && 1 \end{bmatrix} T−1=[RT0T−RTt1]
用 T 12 T_{12} T12表示从坐标系1到坐标系2的变换。
Matrix<数据类型,行,列>;
//内置类型
//Vector3d实质上是Eigen::Matrix
Vector3d v_3d;
//Matrix3d实质上是Eigen::Matrix
Matrix3d matrix_33;
//动态大小的矩阵
Matrix matrix_dynamic;
//更简单的
MatrixXd matrix_x;
//初始化为零
Matrix3d::Zero();
//输入数据
//按行输入
matrix_23 << 1,2,3,4,5,6
//直接输出
cout << "..." << matrix_23 << endl;
//用()访问矩阵中的元素
for (int i = 0; i < 2 ; i++) {
for (int j = 0; j < 3 ; j++) cout << matrix_23(i,j) << "\t";
cout << endl;
}
//矩阵和向量相乘
//注意数据类型匹配,需要用.cast<数据类型>()进行显示转换
Matrix result = matrix_23.cast() * V_3d;
//随机数矩阵
matrix_33 = Matrix3d::Random();
/*
转置:.transpose()
各元素和:.sum()
迹:.trace()
逆:.inverse()
行列式:.determinant()
*/
//特征值
//实对称矩阵可以保证对角化成功
SelfAdjointEigenSolver eigen_solver(matrix_33.transpose()*matrix_33);
//特征值
eigen_solver.eigenvalues()
//特征向量
eigen_solver.eigenvectors()
//解方程
//1. 直接求逆
Matrix x = matrix_NN.inverse() * V_Nd;
//2. 矩阵分解
Matrix x = matrix_NN.colPivHouseHolderQr().solve(v_Nd);
//3. 对于正定矩阵,还可以用cholesky分解来解方程
Matrix x = matrix_NN.ldlt().solve(v_Nd)
include_directories("/usr/include/eigen3")
由于Eigen库只有头文件,所以不需要再用target_link_libraries语句将程序链接到库上。
用一种方式紧凑地描述旋转和平移
R = c o s θ I + ( 1 − c o s θ ) n n T + s i n θ n ∧ R=cos\theta I + (1-cos\theta)nn^T+sin\theta n^\wedge R=cosθI+(1−cosθ)nnT+sinθn∧
t r ( R ) = c o s θ t r ( I ) + ( 1 − c o s θ ) t r ( n n T ) + s i n θ t r ( n ⋅ ) = 3 c o s θ + ( 1 − c o s θ ) = 1 + 2 c o s θ \begin{aligned} tr(R)&=cos\theta tr(I) + (1-cos\theta)tr(nn^T)+sin\theta tr(n^\cdot) \\ &=3cos\theta+(1-cos\theta) \\ &=1+2cos\theta \end{aligned} tr(R)=cosθtr(I)+(1−cosθ)tr(nnT)+sinθtr(n⋅)=3cosθ+(1−cosθ)=1+2cosθ
进而有
θ = arccos t r ( R ) − 1 2 \theta=\arccos \frac{tr(R)-1}2 θ=arccos2tr(R)−1
关于转轴n,旋转轴上的向量在旋转后不发生改变,即
R n = n Rn=n Rn=n
因此,n是矩阵R特征值1对应的特征向量对应的单位向量。
即有两个转换公式
{ θ = arccos t r ( R ) − 1 2 R n = n \begin{cases} \theta=\arccos \frac{tr(R)-1}2 \\ Rn = n \end{cases} {θ=arccos2tr(R)−1Rn=n
旋转矩阵和旋转向量不够直观。
使用3个分离的转角,把一个旋转分解成3次绕不同轴的旋转。
假设一个刚体的前方为X轴,右侧为Y轴,上方为Z轴。ZYX转角相当于把任意旋转分解成以下3个轴上的转角:
俯仰角为 ± 9 0 ∘ \pm90^\circ ±90∘时,第一次旋转与第三次旋转将使用同一个轴,使得系统丢失了一个自由度。
也就是说,第三次旋转可以被包含进第一次旋转中,从而丢失了一个自由度。
从理论角度:
当 θ = π 2 \theta=\dfrac{\pi}{2} θ=2π时,公式变为:
可以看到,改变 ϕ \phi ϕ和 ψ \psi ψ的效果相同,而旋转轴始终是z轴。
从旋转表示方式角度:
一次旋转应当由4个变量表示:3个角度和1个旋转顺序
若只用3个变量表示,在特定情况下会丢失旋转顺序。
这使得欧拉角不适用于插值和迭代,往往只用于人机交互中。
一个四元数拥有一个实部和三个虚部
q = q 0 + q 1 i + q 2 j + q 3 k q = q_0 + q_1i + q_2j + q_3k q=q0+q1i+q2j+q3k
这三个虚部满足以下关系式:
{ i 2 = j 2 = k 2 = − 1 i j = k , j i = − k j k = i , k j = − i k i = j , i k = − j \begin{cases} i^2=j^2=k^2=-1 \\ ij=k,ji=-k \\ jk=i,kj=-i \\ ki=j,ik=-j \end{cases} ⎩⎪⎪⎪⎨⎪⎪⎪⎧i2=j2=k2=−1ij=k,ji=−kjk=i,kj=−iki=j,ik=−j
可以用一个标量和一个向量来表达四元数
q = [ s , v ] T , s = q 0 ∈ R , v = [ q 1 , q 2 , q 3 ] ∈ R 3 q=[s,v]^T,s=q_0\in R,v=[q_1,q_2,q_3]\in R^3 q=[s,v]T,s=q0∈R,v=[q1,q2,q3]∈R3
现有两个四元数 q a , q b q_a,q_b qa,qb,它们的向量表示为 [ s a , v a ] T , [ s b , v b ] T [s_a,v_a]^T,[s_b,v_b]^T [sa,va]T,[sb,vb]T,或者原始四元数表示为
q a = s a + x a i + y a j + z a k , q b = s b + x b i + y b j + z b k q_a=s_a+x_ai+y_aj+z_ak,\qquad q_b=s_b+x_bi+y_bj+z_bk qa=sa+xai+yaj+zak,qb=sb+xbi+ybj+zbk
设 q = [ s , v ] q=[s,v] q=[s,v],定义
q + = [ s − v T v s I + v ⋅ ] , q ∘ = [ s − v T v s I − v ⋅ ] q^+=\begin{bmatrix}s&&-v^T\\v&&sI+v^\cdot\end{bmatrix}, \quad q^\circ=\begin{bmatrix}s&&-v^T\\v&&sI-v^\cdot\end{bmatrix} q+=[sv−vTsI+v⋅],q∘=[sv−vTsI−v⋅]
易得 q 1 q 2 = q 1 + q 2 = q 2 ∘ q 1 q_1q_2=q_1^+q_2=q_2^\circ q_1 q1q2=q1+q2=q2∘q1
进而有
p ′ = q p q − 1 = q + p + q − 1 = q + q − 1 ∘ p p'=qpq^{-1}=q^+p^+q^{-1}=q^+{q^{-1}}^\circ p p′=qpq−1=q+p+q−1=q+q−1∘p
即有
R = q + q − 1 ∘ = [ 1 0 0 T v v T + s 2 I + 2 s v ⋅ + ( v ⋅ ) 2 ] R=q^+{q^{-1}}^\circ= \begin{bmatrix} 1 && 0 \\ 0^T && vv^T+s^2I+2sv^\cdot+(v^\cdot)^2 \end{bmatrix} R=q+q−1∘=[10T0vvT+s2I+2sv⋅+(v⋅)2]
由于p是虚四元数,有
R = v v T + s 2 I + 2 s v ⋅ + ( v ⋅ ) 2 R=vv^T+s^2I+2sv^\cdot+(v^\cdot)^2 R=vvT+s2I+2sv⋅+(v⋅)2
进而有
t r ( R ) = 4 s 2 − 1 tr(R)=4s^2-1 tr(R)=4s2−1
带入上文结论可得
θ = arccos ( 2 s 2 − 1 ) \theta=\arccos(2s^2-1) θ=arccos(2s2−1)
即
θ = 2 arccos s \theta=2\arccos s θ=2arccoss
在四元数旋转公式中,用q的虚部代替p,可得该向量在旋转中不动,即构成旋转轴,则有
{ θ = 2 arccos q 0 [ n x , n y , n z ] T = [ q 1 , q 2 , q 3 ] / s i n ( θ 2 ) \begin{cases} \theta=2\arccos q_0 \\ [n_x,n_y,n_z]^T=[q_1,q_2,q_3]/sin(\frac{\theta}2) \end{cases} {θ=2arccosq0[nx,ny,nz]T=[q1,q2,q3]/sin(2θ)
多了一个缩放自由度
T S = [ s R t 0 T 1 ] 三 维 相 似 变 换 的 集 合 又 叫 相 似 变 换 群 , 记 作 S i m ( 3 ) T_S= \begin{bmatrix} sR && t \\ 0^T && 1 \end{bmatrix} 三维相似变换的集合又叫相似变换群,记作Sim(3) TS=[sR0Tt1]三维相似变换的集合又叫相似变换群,记作Sim(3)
T S = [ A t 0 T 1 ] T_S= \begin{bmatrix} A && t \\ 0^T && 1 \end{bmatrix} TS=[A0Tt1]
仿射变换只要求A是一个可逆矩阵,而不必是正交矩阵
T S = [ A t a T v ] T_S= \begin{bmatrix} A && t \\ a^T && v \end{bmatrix} TS=[AaTtv]
见书上代码