旋量运动:机器人运动学建模与控制的统一视角
发布时间:2026/10/2 14:31:38来源:尧图网络
做机器人运动学这么多年我越来越觉得“旋量运动”screw motion是理解刚体运动最本质、也最容易被忽视的视角。螺丝钉拧进木头时每拧一圈同时向前钻一截这就是一次标准的螺旋运动而Chasles定理告诉我们三维空间中任意刚体位移都可以等价成绕某根轴的旋转叠加沿该轴的平移。旋转分量和平移分量合并成一个六维向量就是旋量。它解决的是传统DH参数和旋转矩阵描述刚体运动时的老大难问题坐标系太多、零位标定麻烦、树状结构处理繁琐。无论你是做机械臂运动学、并联机构分析还是搞机器人控制算法旋量都能让建模过程更贴近物理直觉也更适合直接进现代控制框架。1. 为什么说旋量运动是机器人运动学的“正确姿势”1.1 从一颗螺丝钉说起Chasles定理讲透了刚体运动很多教材一上来就讲旋转矩阵、欧拉角、齐次变换公式推得头头是道但学完还是不知道机器人末端到底是怎么“动”过去的。旋量运动不一样它先回答一个更基本的问题刚体从一个位形运动到另一个位形最省事的描述方式是什么Chasles定理的结论非常干脆任何刚体位移都可以看成绕某一根空间直线旋转一定角度同时沿这根直线平移一段距离。旋转和平移同时发生就是螺旋运动。一颗螺丝钉拧进木板每转一圈前进一个螺距这就是最直观的螺旋运动。机器人关节的转动、滑块平动、甚至复杂机构的空间运动本质都能拆成这种“一边转一边蹭”的形式。这个定理的价值在于它把刚体运动从“旋转矩阵加平移向量”这种分离描述统一成“一根轴加一个螺距加一个量”的整体描述。旋转矩阵加平移向量有12个参数但真正描述一个位形只需要6个自由度多余参数会带来冗余和约束麻烦。旋量坐标直接用6个数描述速度旋量或运动旋量没有冗余也不需要担心欧拉角的万向锁问题。这对机器人控制来说特别重要——控制算法里要不断计算误差、求导、做插值一个没有奇异、参数紧致的表示方法能省掉大量麻烦。1.2 和DH参数相比旋量到底赢在哪DH参数是教科书里的常客我早期做机械臂标定也是从DH入手的。DH参数的核心思想是给每个连杆都固定一个坐标系用四个参数a、alpha、d、theta描述相邻连杆之间的变换。思路简单清晰但实际用起来有几个很磨人的地方第一DH坐标系有严格的依附规则Z轴必须沿关节轴X轴必须沿公垂线方向这就导致坐标系往往不在连杆质心上也不在关节中心上物理直觉被割裂了。第二零位标定麻烦。DH参数里的theta是关节变量零位不同会直接影响a和d的取值而且相邻杆件之间的坐标系依赖关系是链式的改一个参数后面全得跟着变。第三遇到树状结构或闭链机构比如并联机器人、四足机器人腿DH的链式结构就很难受必须人为切割成多条链然后额外加约束方程。旋量方法从根本上避开了这些问题。它只需要两个坐标系基坐标系空间系和工具坐标系末端系每个关节用一个旋量表示旋转轴的位置和方向。没有中间坐标系不需要公垂线关节轴写成旋量后就是物理轴本身。我做了几个项目之后最直观的感受是调试时看到一个关节轴对应一个旋量出错的地方一眼就能看出来而DH参数出问题经常要来回翻矩阵看坐标系到底偏到哪去了。另外旋量的模块化优势很明显。DH参数改一处结构比如把某个旋转关节换成移动关节或者改变关节顺序往往要大改参数表旋量法只需要把对应关节的旋量坐标改一下或者调整指数积公式里的相乘顺序其余代码几乎不用动。对于现在常见的模块化机械臂、可重构机器人这种优势非常实在。2. 旋量运动的数学底子从螺旋定理到李代数2.1 刚体位形的李群表示SE(3)和se(3)要真正用好旋量运动绕不开李群和李代数但别被名字吓住。简单地说刚体所有可能的位形组成一个空间叫特殊欧氏群SE(3)它里面的元素就是齐次变换矩阵[ T \begin{bmatrix} R p \ 0 1 \end{bmatrix} ]SE(3)是个李群也就是“光滑流形上的群”它既保持了矩阵乘法又允许求导、插值、计算微小运动。而微小运动也就是速度旋量所在的线性空间就是李代数se(3)。换句话说SE(3)描述“刚体在哪里”se(3)描述“刚体正以什么方式运动”。se(3)里的元素可以写成六维向量[ \mathcal{V} \begin{bmatrix} v \ \omega \end{bmatrix} ]其中v是线速度(\omega)是角速度。对应到矩阵形式就是[ [\mathcal{V}] \begin{bmatrix} [\omega] v \ 0 0 \end{bmatrix} ]这里的([\omega])是三维向量(\omega)对应的反对称矩阵。好到这里其实不需要更多抽象概念只需要记住旋量坐标就是se(3)元素在某个坐标系下的坐标六个数四个字“转轴加位置加螺距”。2.2 一个关节轴怎么变成一个旋量坐标假设机器人第i个关节是一个旋转关节。旋转轴的单位方向向量是(\omega_i)轴上任意一点是(q_i)螺距是(h_i)。那么对应的单位旋量坐标是[ \xi_i \begin{bmatrix} -\omega_i \times q_i h_i \omega_i \ \omega_i \end{bmatrix} ]前三个分量是线速度部分后三个是角速度部分。对于纯旋转关节螺距h0公式变成(v_i -\omega_i \times q_i)。对于移动关节实际上没有旋转轴方向只有一个移动方向单位向量(v_i)对应旋量写成[ \xi_i \begin{bmatrix} v_i \ 0 \end{bmatrix} ]也就是说移动关节的角速度部分为零。是不是很简单这里有一个很容易忽略的细节旋转轴上的取样点(q_i)可以任意选择因为旋量坐标在这种表示下通过叉积把“轴位置”编码进了v分量同一个轴选不同q点算出的v会有差异但它们对应的物理螺旋轴是完全相同的。实操中我一般选坐标系原点在轴上的垂足或者直接选机构图纸上标注的关节中心坐标不容易出错。2.3 指数映射从旋量到齐次变换矩阵有了旋量坐标怎么得到它对应的刚体位移需要用指数映射。如果把绕第i个关节旋转的角度记为(\theta_i)那么齐次变换矩阵是[ e^{[\xi_i]\theta_i} ]这个指数映射的展开形式如果(\omega \neq 0)且(||\omega|| 1)是[ e^{[\xi]\theta} \begin{bmatrix} e^{[\omega]\theta} (I - e^{[\omega]\theta})(\omega \times v) \omega\omega^T v \theta \ 0 1 \end{bmatrix} ]其中(e^{[\omega]\theta})就是罗德里格斯公式[ e^{[\omega]\theta} I \sin\theta,[\omega] (1 - \cos\theta),[\omega]^2 ]如果(\omega 0)纯平移则[ e^{[\xi]\theta} \begin{bmatrix} I v\theta \ 0 1 \end{bmatrix} ]指数映射的意义是什么它把“关节转过的量θ”映射成“刚体实际发生的位置变化”。整个机器人末端位形就是所有关节的单位旋量指数映射按关节顺序相乘的结果[ T(\theta) e^{[\xi_1]\theta_1} e^{[\xi_2]\theta_2} \cdots e^{[\xi_n]\theta_n} T_{M0} ]其中(T_{M0})是机械臂处于零位时工具坐标系的位形。这个公式就是指数积公式英文缩写POE。它和DH参数最大的不同是DH用四个参数拼出一个变换矩阵POE直接用一个关节轴旋量和一个关节角生成一个变换矩阵物理含义一目了然。3. 实操用指数积公式搭建机械臂运动学模型3.1 亲手推一遍二连杆平面机械臂理论说多了容易飘我建议你拿一个最简单的二连杆平面机械臂走一遍完整流程。假设两杆长度都是1基座在原点所有关节轴都是z轴方向。第一步确定单位旋量。第一个关节轴过原点方向是z轴正方向所以[ \omega_1 \begin{bmatrix} 0 \ 0 \ 1 \end{bmatrix}, \quad q_1 \begin{bmatrix} 0 \ 0 \ 0 \end{bmatrix}, \quad h_1 0 ]于是[ \xi_1 \begin{bmatrix} 0 \ 0 \ 0 \ 0 \ 0 \ 1 \end{bmatrix} ]第二个关节轴经过点(q_2 \begin{bmatrix} 1 0 0 \end{bmatrix}^T)方向同样是z轴[ v_2 -\omega_2 \times q_2 -(\begin{bmatrix} 0 \ 0 \ 1 \end{bmatrix} \times \begin{bmatrix} 1 \ 0 \ 0 \end{bmatrix}) -\begin{bmatrix} 0 \ 1 \ 0 \end{bmatrix} \begin{bmatrix} 0 \ -1 \ 0 \end{bmatrix} ]所以[ \xi_2 \begin{bmatrix} 0 \ -1 \ 0 \ 0 \ 0 \ 1 \end{bmatrix} ]第二步确定零位工具系(T_{M0})。机械臂完全伸直时末端在x轴上距离原点2的位置姿态与基座一致[ T_{M0} \begin{bmatrix} 1 0 0 2 \ 0 1 0 0 \ 0 0 1 0 \ 0 0 0 1 \end{bmatrix} ]第三步代入指数积公式[ T(\theta_1, \theta_2) e^{[\xi_1]\theta_1} e^{[\xi_2]\theta_2} T_{M0} ]我建议你不要直接套库先按前面给出的指数映射公式手算一遍。取(\theta_1 30^\circ, \theta_2 30^\circ)算出来的末端位置应该是[ p_x \cos 30^\circ \cos 60^\circ 1.3660 ] [ p_y \sin 30^\circ \sin 60^\circ 1.3660 ]这和几何法算出的结果是完全一致的。亲手验证一次你对指数映射的理解会立刻从“背公式”变成“真的会了”。3.2 在代码里实现时要避开的几个小坑在Python里实现时我习惯用numpy写一个基本的旋量类核心就是两个函数一个是三维反对称矩阵一个是se(3)的指数映射。下面是一个简化版本的核心逻辑import numpy as np def skew(w): return np.array([[0, -w[2], w[1]], [w[2], 0, -w[0]], [-w[1], w[0], 0]]) def exp_se3(xi, theta): w xi[3:] v xi[:3] wn np.linalg.norm(w) if wn 1e-10: # pure translation T np.eye(4) T[:3, 3] v * theta return T w w / wn v v / wn # 注意这里的v是单位旋转对应的v sw skew(w) R np.eye(3) np.sin(theta) * sw (1 - np.cos(theta)) * sw sw coef (1 - np.cos(theta)) * (w v) theta * np.dot(w, v) - theta * np.dot(w, v) # 更准确直接用标准公式 p (np.eye(3) - R) np.cross(w, v) w * np.dot(w, v) * theta T np.eye(4) T[:3, :3] R T[:3, 3] p return T这个版本只是为了演示思路直接算(e^{[\xi]\theta})对单位旋量的处理必须把(\omega)归一化到单位长度否则旋转角度和实际弧度就对不上。这是个很隐蔽的坑很多初学的人拿着非归一化的旋量直接调库结果转角翻倍调试半天找不出原因。我实际项目中很少自己造轮子一般直接用现成库。Python推荐Peter Corke的spatialmath-python它提供了SE3、Twist3、Screw3等完整封装MATLAB则用Robotics Toolbox里的se3、twist系列函数。自己实现一遍是为了理解原理但工程上稳定性和边界情况处理成熟库比自己写的可靠得多。3.3 为什么POE法在工程里比DH法更好维护我在一个六自由度机械臂项目里早期用的是DH参数建模后来整个运动学模块切换到POE原因是这个项目经常要改末端工具也就是换不同长度的夹爪和传感器。DH参数下每换一次工具至少要动末端连杆的四个参数并且要保证和机械臂本体的坐标关系不出错POE法只需要改(T_{M0})也就是工具系在机械臂末端法兰上的初始位形其余六个关节旋量完全不动。另外POE法对代码结构也很友好。每个关节的旋量坐标写成一个常量数组放在一个配置列表里正解函数只依赖这个列表和关节角。新增一个关节比如从六轴变七轴只需要在列表里追加一个旋量坐标再调整一下循环不需要重新推导整个变换链。这种维护体验对需要频繁改机构方案的研发项目来说几乎算是刚需。4. 从旋量到雅可比与控制算法4.1 单位旋量就是雅可比的每一列旋量运动不仅用于正运动学它的更大价值在于控制算法。我们知道机器人的速度雅可比矩阵(J)把关节速度映射到末端速度旋量[ \mathcal{V} J(\theta) \dot{\theta} ]用指数积公式推导雅可比有一个非常优雅的结论空间系下雅可比矩阵的第i列正好就是第i个关节的单位旋量在空间系中的当前值。初始位置就是(\xi_i)本身当机器人运动后前面的关节旋转会“搬运”这个旋量用伴随变换更新[ J_{si} \text{Ad}{T{i-1}} \xi_i ]其中(T_{i-1} e^{[\xi_1]\theta_1} \cdots e^{[\xi_{i-1}]\theta_{i-1}})。伴随变换的矩阵形式是[ \text{Ad}_T \begin{bmatrix} R [p]R \ 0 R \end{bmatrix} ]这个式子的物理含义很直接机械臂运动过程中每个关节轴在空间中的位置和方向都会随着前面关节的运动而改变雅可比矩阵就是所有当前关节轴旋量排成的六列。所以当你看到雅可比矩阵某一列异常小或者和其他列线性相关时基本就能判断出机械臂处于奇异位形附近。我在调试爬壁机器人时经常用旋量形式的雅可比矩阵做奇异分析。传统几何法分析奇异需要逐行对末端位置求偏导式子繁琐还容易漏项旋量法直接计算六维旋量列向量的线性相关性奇异位形的几何特征比如三轴共面、四轴交于一点都能从旋量轴的位置和方向上看出来排查效率高非常多。4.2 运动旋量误差、力旋量与几何控制控制层面旋量把“位置误差”和“姿态误差”统一成了六维运动旋量误差。常规的PID控制中如果直接用欧拉角做姿态误差在大角度情况下会出现非线性耦合甚至不可微的问题。用旋量定义误差时可以从当前位形(T)到目标位形(T_d)的相对变换直接取出运动旋量[ \mathcal{V}e \text{Ad}{T^{-1}T_d} \xi_d - \xi ]也就是把位形空间中的偏差转换成速度旋量空间中的偏差再映射回关节空间。这样计算的控制律在SE(3)上做几何控制没有欧拉角的局部坐标奇异问题适合做高速高精度的轨迹跟踪。同时旋量和力旋量wrench是对偶的。力旋量由三维力和三维力矩组成[ \mathcal{F} \begin{bmatrix} f \ \tau \end{bmatrix} ]关节力矩和末端力之间的关系[ \tau J^T \mathcal{F} ]这里的(J^T)和旋量中的运动学雅可比直接对应。在做力控、阻抗控制时旋量表示让动力学和运动学使用同一套数学语言不需要在“姿态四元数位置XYZ”和“关节力矩”之间来回转换。我在做机械臂拖动示教时直接用空间力旋量作为控制输入用户在末端施加的力和力矩被投影到各关节力矩上手感比传统雅可比转置法平滑不少。4.3 与现代底层控制结合从关节电机到整机几何控制热搜词里那些FOC控制、PID控制、伺服电机控制底层负责的是“让关节角以期望力矩和期望速度动起来”但整个机器人末端该走什么轨迹、如何协调多个关节靠的是上面的几何控制层。旋量运动刚好是这两层之间最自然的接口。举个例子做麦克纳姆轮或舵轮底盘时底盘整体的运动旋量分解成各个轮子的速度旋量再通过底层电机控制实现。RoboMaster的小陀螺旋转本质上是云台和底盘两个旋转运动的差速合成用旋量计算会比分别做坐标变换直观得多。现在很多开源机器人框架比如Pinocchio、Drake动力学和运动学核心都用了李群和李代数关节状态不只是位置和速度而是一个SE(3)元素加上旋量速度。你如果要在这些框架里做二次开发不懂旋量的底层表达基本寸步难行。5. 常见问题、数值实现与实用工具5.1 五个容易踩的坑提前帮你排掉第一个坑是旋量坐标的排列顺序不统一。有的书把线速度放前面写成((v, \omega))有的放后面写成((\omega, v))。不同库的约定也不一样比如Spatial Math Toolbox的Twist3默认就是((v, \omega))而有些工程代码却用((\omega, v))。遇到报错先检查排列顺序不要急着怀疑算法。第二个坑是单位旋量的归一化。指数积公式里如果(\xi)代表旋转关节(\omega)部分必须归一化到模长为1如果代表移动关节(v)部分必须归一化。归一化做错关节转90°在矩阵里相当于转了一个奇怪的角度而且这种错误通常不报错只是末端位置漂移非常难排查。第三个坑是纯平移关节的指数映射。很多通用指数映射实现只处理了(\omega \neq 0)的情况遇到移动关节直接梯度爆炸或者返回NaN。写代码时一定要单独判断(\omega)模长接近0的情况。第四个坑是轴上的点(q)选取不一致。我见过同事用两个不同的CAD模型提取同一个关节轴一个取轴上点(q[10,0,0])一个取(q[10.1,0,0])算出的旋量v分量差了0.1虽然理论上对应同一个螺旋轴但在数值计算中微小差异会累积到末端误差。建议所有关节轴坐标都从同一个模型文件、同一个坐标系提取不要混用来源。第五个坑是空间旋量和物体旋量的混淆。指数积公式既可以写成空间系下的形式也可以写成物体系下的形式。空间系下旋量轴固定在世界坐标系中物体系下旋量轴固定在末端坐标系中。两者计算出的末端位形是相同但对应的雅可比矩阵一个是空间雅可比一个是物体雅可比。控制算法里混用这两种雅可比力矩方向会莫名其妙地反掉。5.2 快速核对正运动学结果的方法不管用什么库我建议你建立一个简单的查看器实时把正运动学算出的末端坐标画出来再叠加一个简单几何法的结果。比如二连杆臂几何法算末端点[ x L_1\cos\theta_1 L_2\cos(\theta_1\theta_2) ] [ y L_1\sin\theta_1 L_2\sin(\theta_1\theta_2) ]如果旋量结果和几何法不一致说明指数映射或旋量坐标有问题。这个方法廉价但有效适合所有机械臂模型不管是四轴还是六轴。5.3 值得常驻书桌的工具和资料我常用的组合是Pinocchio做动力学和运动学spatialmath-python用来快速验证旋量公式MATLAB的Robotics Toolbox用于快速原型验证。资料方面《Modern Robotics: Mechanics, Planning, and Control》和《A Mathematical Introduction to Robotic Manipulation》这两本把旋量讲得最透彻前者还配套了免费的在线课程和代码库我建议按顺序推进不要直接从后半部分跳读。最后分享一个小技巧学习旋量运动时优先把“速度旋量”理解透而不是一上来就抠李群李代数的抽象定义。你只要记住“刚体上任意一点的瞬时速度都可以由一个角速度向量和一个线速度向量唯一表示”后续所有公式推导都能顺着这个物理图像走。等你看得多了会发现机器人运动学里很多繁琐的坐标变换在旋量视角下其实就是一句话的事。
网站建设高端定制企业官网