惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
Cisco Blogs
Scott Helme
Scott Helme
Know Your Adversary
Know Your Adversary
NISL@THU
NISL@THU
C
Cyber Attacks, Cyber Crime and Cyber Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Schneier on Security
I
Intezer
Spread Privacy
Spread Privacy
AWS News Blog
AWS News Blog
V
Vulnerabilities – Threatpost
Cloudbric
Cloudbric
V2EX - 技术
V2EX - 技术
Google Online Security Blog
Google Online Security Blog
L
Lohrmann on Cybersecurity
Recent Commits to openclaw:main
Recent Commits to openclaw:main
L
LINUX DO - 热门话题
S
Secure Thoughts
T
The Exploit Database - CXSecurity.com
博客园 - 【当耐特】
Recent Announcements
Recent Announcements
Security Archives - TechRepublic
Security Archives - TechRepublic
Stack Overflow Blog
Stack Overflow Blog
罗磊的独立博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
K
Kaspersky official blog
阮一峰的网络日志
阮一峰的网络日志
博客园_首页
Latest news
Latest news
B
Blog
F
Full Disclosure
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
L
LangChain Blog
GbyAI
GbyAI
Last Week in AI
Last Week in AI
S
Security Affairs
Apple Machine Learning Research
Apple Machine Learning Research
N
Netflix TechBlog - Medium
Security Latest
Security Latest
Vercel News
Vercel News
Y
Y Combinator Blog
G
GRAHAM CLULEY
S
Securelist
T
Troy Hunt's Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
雷峰网
雷峰网

博客园 - SoRoMan

Scene Management - Scene Graph MFC的一些宏的整理 (DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE) 关于STL Improve Performance of C++ Codes (2) -- 如何消除临时对象? Improve Performance of C++ Codes (1) -- 使用初始化列表还是赋值语句? 关于万向节死锁(Gimbal Lock)(续) 思考:矩阵及变换,以及矩阵在DirectX和OpenGL中的运用问题:左乘/右乘,行优先/列优先,... 读书笔记:Writing Solid Code (4) 读书笔记:Writing Solid Code (3) 读书笔记:Writing Solid Code (2) 读书笔记:Writing Solid Code A 3D Real Time Fluid Solver Demo (三维实时流体解算器) 笔记:Delaunay三角剖分(Delaunay Triangulation)相关知识 学习经验:逐步建立学习资源列表-计算机图形学 SL专题6:谈谈Second Life中的游戏制作(Game Dev in SL) SL专题4:Second Life畅销商品 SL专题3:Second Life市场分析 SL专题2:加入并熟悉Second Life世界 SL专题1:Second Life(第二生命)--迟早火爆世界的游戏与Web的集大成者
思考:矩阵的级联顺序与坐标系的关系
SoRoMan · 2009-05-15 · via 博客园 - SoRoMan

 还是关于矩阵的碎碎念,接上篇:思考:矩阵及变换,以及矩阵在DirectX和OpenGL中的运用问题:左乘/右乘,行优先/列优先,...

纯粹个人观点,欢迎探讨:

5。矩阵的级联顺序与坐标系的关系:

 

1). 变换的时候,坐标系的选取是必需的

物体的方位都是相对的,选定参考坐标系才能描述方位。一般参考坐标系可以分为两种:1.全局/固定坐标系 2.局部坐标系/物体坐标系。故名思义,前者是固定不动的,后者是随物体方位变化而变化的。

举个例子:伸出左手,手掌水平,掌心向上,大拇指向左,其余四指向前。此时选定物体的局部坐标系(Cl(Ol,Xl,Yl,Zl))为:掌心为原点(Ol),X轴(Xl)指向四指指向,Z(Zl)轴指向大拇指指向,Y轴(Yl)指向掌心向上。全局坐标系(Cg(Og,Xg,Yg,Zg))选定为和本地坐标系重合。那么,移动你的左手,局部坐标系就会随手而动。全局坐标系还是原先的方位。为什么选定坐标系对于变换重要?因为相对于哪种坐标系做变换得出的结果是不一定相同的。

还是上面那个例子:现在开始做变换,给你个指令:沿X轴旋转手掌90度使得掌心向右,然后手掌沿Y轴向+Y方向移动10厘米。

你做完后,得出的结果可能有3种:

1. 手的位置比原先高了10厘米,这部分人居多。

2. 手的位置比原先靠右10厘米,这部分人居少。

3. 还有部分数人傻在那,变换不来,这部分人其实不傻。

其实这个变换指令没有指定参考坐标系,是变换不出来的。1类的是自己选了全局坐标系,2类是选了局部坐标系,3类的没自己选。

所以,变换的时候,坐标系的选取是必需的。

2). 级联顺序与坐标系选取的关系

回到矩阵变换,一般我们说的对物体X进行M1变换,即X’= X*M1 (使用Column Matrix约定),隐含了选取全局坐标系的约定。单一变换的没有级联顺序的问题。如果再进行一个M2变换,此时,X’= X*M1*M2 还是X’= X*M2*M1呢?我们可能都知道是X’= X*M1*M2。显然嘛,先做的变换先乘,但深层的原因是什么呢?答案是隐含的全局坐标系的选定,如果选定的是局部坐标系,那么X’= X*M2’*M1’。后面一个变换反而要先进行。不信,看例子:

还是手掌例子,先旋转后平移, 给你个指令:沿Xg轴旋转手掌90度使得掌心向右,然后手掌沿Yg轴向+Yg方向移动10厘米。

这下清楚不过了,完成后手掌比原先高了10厘米。此时变换公式:X’= X*R(Xg)*T(Yg)

现在,指令是参考局部坐标系,变换顺序是反向的,先平移后旋转:

手掌沿Yl轴向+Yl方向移动10厘米,然后沿Xl轴旋转手掌90度使得掌心向右。

看看完成后的结果,手是不是和上面的方位一样?此时变换公式:X’= X*T(Yl)*R(Xl)

 正序级联是相对于全局坐标系,逆序级联相对于局部坐标系,殊途同归。下次有变换矩阵需要级联的时候,先看看变换的矩阵是相对于全局还是局部的坐标系。

一般规律:假定对物体X施加M1变换和M2变换,两个变换矩阵均为相对于全局坐标系。有:

X’ = X*M1(g)*M2(g)

可以看作是将X先经过M1(g)变换,再进行M2(g)变换,得到X’

由矩阵的结合律,上面等式等价于:

X’ = X*M2(g)*(M2(g)-1*M1(g)*M2(g))     M2(g)-1M2(g)的逆矩阵)

所以,这个过程也可以这么看,先对X进行M2(g)(也即M2(l))变换(M2(g)为相对于全局坐标系,但此时全局和局部坐标系的重合,所以M2(g)=M2(l)),再对X进行M2(g)-1*M1(g)*M2(g)变换(也即M1(l)变换),这个变换实际上相当于先将物体退回到原方位(此刻局部坐标系退回到原始方位,也就是全局坐标系方位)进行M1(g)变换后,再进行M2(g)变换回来。M2(g)-1*M1(g)*M2(g)整体的效果就是相对于此时的局部坐标系的进行M1(l)变换。故:

X’ = X*M2(l)*M1(l)

即,如果将变换认为是相对于局部坐标系而进行的,那么矩阵级联顺序正好相反。

(注:上面推导有个这样的前提:即初始变换时,选定局部坐标系和全局坐标系重合。如果局部坐标系是一般选取,即局部坐标系相对于全局坐标系的变换M(l/g) != Identity呢,答案是结论一样。因为M(l/g)可以认作是对于物体的变换。将X换成X(new)=X*M(l/g)而已。)

3). 如何选取,如何级联

碰到的场景:

 l 人手的运动

手有很多关节,每个关节的一端可以绕着关节处运动,关节本身也可以运动,要表达手指尖相对于人体的运动,使用相对于局部坐标系(关节)的变换比选取全局坐标系(人体)的变换要简单清晰得多。

比如:一个从手臂下垂到做出向上抬手手的动作之间,现在用矩阵变换来表达手掌的变换(X->X’)。

如果你选定局部坐标系(各个关节)做变换,那么其表达就是:

上手臂绕肩关节旋转90度(M1()),下手臂绕肘关节转45度(M2()),手掌绕踝关节转30度(M3()),那么:

X’ = X*M3()*M2()*M1()

(注意和X’ = X*M1()*M2()*M3()的不同)

如果你选定全局坐标系(人体/肩关节)做变换,那么其表达就是:

上手臂绕肩关节旋转90度(M1()),下手臂绕肩关节(M2()), 手掌绕肩关节(M3())。。绕不过来了吧(M2(), M3()很难表示出来)

X’ = X*M1()*M2()*M3()

   l 矩阵分解与 级联顺序

  |R 0|

  |T 1|

  = R*T (先进行旋转变换,后进行平移变换, 基于global坐标系)
  = T*R (先进行平移变换,后进行旋转变换, 基于local坐标系)

  = R*T' (先进行旋转变换,后进行平移变换, 基于local坐标系, T'= R-1*T*R)

  = T*R' (先进行平移变换,后进行旋转变换, 基于global坐标系, R' = T-1*R*T)

 4). 结论

注意矩阵级联顺序和坐标系选取的关系。在整体/部分相对运动较多的地方,选取局部坐标系描述变换。