机器人学课后练习:吃透齐次变换与雅可比,比找答案更有效

📅 发布时间:2026/9/18 0:59:25
机器人学课后练习:吃透齐次变换与雅可比,比找答案更有效
简介这份文档是配套蔡自兴《机器人学》教材的课后习题解答资料供高校相关专业学生、考研备考者及自学者对照练习、检验解题思路之用。文档围绕机器人学核心知识点展开集中讲解了坐标系变换、旋转矩阵与平移矩阵的构建、3自由度机械手运动学建模、D-H连杆参数求解以及微分变换和齐次变换矩阵的应用对多个典型题目按不同坐标系建法给出多种解题方案并配有推导过程与矩阵结果便于读者理解相对变换、动系旋转和右乘规则等易混淆概念。资源为1个doc文档体积约592KB可直接阅读或打印。已有843人学习下载适合正在学习机器人学基础、需要课后习题参考与解题方法梳理的读者。1. 当你不满足于“抄答案”机器人学课后练习的真正打开方式任何一个在期末周刷过《机器人学》课后题的人大概率都干过一件事在网盘或文档站里搜“蔡自兴 机器人学 课后答案”然后下载一个排版混乱的 .doc对着题目把数字抄上去。这确实是“机器人学蔡自兴课后练习题答案.doc”这个标题下最常见的行为但你会发现一个残酷的事实抄完所有题目你依然不会算一个六轴机械臂的逆解依然搞不清齐次变换矩阵的左上角为什么是旋转矩阵而不是位置矢量。原因在于蔡自兴版的课后练习几乎不考“记忆”它考的是“坐标变换的直觉”和“对运动学链条的建模能力”。这篇文章不讲某个文档的下载路径而是把这张试卷背后真正会反复出现的五类问题拆开——齐次变换、DH参数、正逆运动学、雅可比与奇异性、动力学基础——每一类都配一套可以直接上手复现的计算路径和参数选择逻辑让你即便没有答案文件也能自己推导出每一道题的结论。读完你会获得一种比“答案”更稳定的东西看穿题目的能力。2. 位姿描述与齐次变换矩阵课后题的第一道坎2.1 为什么几乎所有题都从“坐标系”开始蔡自兴教材的前两章花了大量篇幅讲刚体的位姿描述而习题里最典型的设问方式是“已知坐标系 {B} 相对于 {A} 的描述求某点在 {B} 中的坐标在 {A} 中的表示”。这类题看上去像矩阵乘法练习但实际上它考察的是你对“旋转矩阵的列向量含义”的理解——旋转矩阵的三列分别是坐标系 {B} 的三个主轴在 {A} 中的方向余弦。以课后最常见的绕固定轴旋转为例绕 X 轴旋转 90 度再绕 Y 轴旋转 90 度与先绕 Y 后绕 X得到的结果完全不同。这里的关键在于旋转的“中间状态”是否参与叠加绕固定轴旋转采用左乘绕当前轴旋转采用右乘。很多答案文档在这里只给结果矩阵不解释为什么顺序不能交换导致读者换一个角度就懵。做题时应建立惯性思维把旋转矩阵每一列当作“目标轴在当前坐标系中的投影”同时注意旋转矩阵的正交性逆等于转置是验算的第一步。2.2 用一个最小案例练通齐次矩阵先看一道课后练习中反复出现的变体题坐标系 {B} 与 {A} 初始重合{B} 先绕 {A} 的 X 轴旋转 60 度再沿 {A} 的 X 轴平移 5 个单位。求齐次变换矩阵 T_A_B并计算点 p_B [3, 2, 1]^T 在 {A} 中的坐标。计算过程是两步矩阵连乘但多数人栽在“平移与旋转谁先谁后”的语义混淆上。import numpy as np def rotx(theta_deg): t np.radians(theta_deg) ct, st np.cos(t), np.sin(t) return np.array([ [1, 0, 0], [0, ct, -st], [0, st, ct] ]) T_rot np.eye(4) T_rot[:3, :3] rotx(60) T_trans np.eye(4) T_trans[:3, 3] [5, 0, 0] # {B} 先旋转相对 {A} 的固定轴再平移故左乘平移变换 T_AB T_trans T_rot p_B np.array([3, 2, 1, 1]) p_A T_AB p_B print(T_AB:\n, T_AB) print(p_A:, p_A[:3])代码顺序体现了固定轴旋转的核心规则先发生的变换放在矩阵连乘的右侧后发生的变换放在左侧因为后续变换作用在“已经被改变”的坐标系上。参数上需要注意的是旋转角度单位用弧度而人习惯用度所以函数内部做了转换平移量直接放入第四列齐次坐标最后一维固定为 1。这道题做完后做一个反向验算把 p_A 乘上 T_AB 的逆矩阵应当回到 [3, 2, 1]。由于旋转矩阵正交逆矩阵可以拆成先平移的逆再旋转的逆这也是课后题里“求逆变换”的标准做法。2.3 欧拉角与 RPY 角答案文档里最容易抄错的地方蔡自兴课后题里有一类题专考“给定欧拉角求旋转矩阵”或反过来“给定旋转矩阵求欧拉角”。这里必须严格区分是 ZYZ 欧拉角还是 RPY 角也叫 X-Y-Z 固定角。以 RPY 角为例它等价于绕固定坐标系的 XRoll、YPitch、ZYaw依次旋转所以组合矩阵是 R Rz(yaw) Ry(pitch) Rx(roll)注意连乘顺序与直觉相反。当题目给出旋转矩阵要求反解欧拉角时推荐用 atan2 而不是 acos 或 asin以避免角度象限丢失。具体做法是先读出矩阵元素用 Pitch atan2(-R[2,0], sqrt(R[0,0]^2 R[1,0]^2)) 求出俯仰角再回代求 Roll 和 Yaw。这一步是无数 .doc 答案里出错的高发区因为当 Pitch 接近 ±90 度时会出现万向锁此时 Roll 和 Yaw 无法唯一分离必须按退化情况单独讨论。你可以把这一条直接记成解题 checklist凡遇到反解欧拉角优先检查是否处于奇异位形。3. DH 参数与正运动学从题目文字到矩阵链条的建模3.1 标准 DH 与修正 DH 的选择陷阱蔡自兴教材里同时出现过标准 DHDenavit-Hartenberg和修正 DHModified DH的表述而课后题里最常见的坑是题目给的参数表究竟是按哪种约定列出来的。标准 DH 的变换顺序是“绕 X 旋转 alpha、沿 X 平移 a、绕 Z 旋转 theta、沿 Z 平移 d”修正 DH 的变换则是“沿 Z 平移 d、绕 Z 旋转 theta、沿 X 平移 a、绕 X 旋转 alpha”。两者对于同一个机械臂a、d、alpha 的分配可能完全不一致。做题时判断依据只有一个看题目里对关节坐标系的定义方式。如果第 i 个坐标系固定在关节 i 的末端且下一个变换是“绕 X 旋转 alpha_i”则大概率是标准 DH如果坐标系固定在关节 i1 上则可能采用修正 DH。建议做题前先写一行注释标明你采用的是哪种约定然后用正运动学结果反向验证——大部分课后题会给出末端位姿的答案不匹配就检查约定。3.2 用三连杆平面臂把 DH 表变成代码以一个课后题常见的三连杆平面机械臂为例各关节均为旋转关节杆长分别为 l1、l2、l3求末端在基座标系中的位置。先列 DH 参数表关节 itheta_id_ia_ialpha_i1q10l102q20l203q30l30可以看到平面臂的 alpha 全为 0a 即杆长d 为 0。建立每个关节的变换矩阵 T_i RotZ(theta_i) * TransX(a_i) 是标准 DH 的简化形式。连乘顺序T_03 T_01 T_12 T_23最终取第四列前三行即为末端位置。import numpy as np def dh_transform(theta_deg, d, a, alpha_deg): t np.radians(theta_deg) al np.radians(alpha_deg) ct, st np.cos(t), np.sin(t) ca, sa np.cos(al), np.sin(al) return np.array([ [ct, -st*ca, st*sa, a*ct], [st, ct*ca, -ct*sa, a*st], [0, sa, ca, d], [0, 0, 0, 1] ]) l1, l2, l3 1.0, 1.0, 1.0 q [30, 45, -60] # 角度 T01 dh_transform(q[0], 0, l1, 0) T12 dh_transform(q[1], 0, l2, 0) T23 dh_transform(q[2], 0, l3, 0) T03 T01 T12 T23 pos T03[:3, 3] print(末端位置:, pos)参数说明theta 对应关节变量a 对应连杆长度alpha 对应连杆扭转角d 是连杆偏距。对平面臂来说 d 与 alpha 都为 0矩阵简化为二维旋转和平移的组合。这个代码框架可以横向扩展到六轴机械臂——只要 DH 表正确正运动学就是四个矩阵的循环连乘这是机器人学课后练习里最“机械”但最不能错的部分。验证时可以用几何法末端 x l1cos(q1) l2cos(q1q2) l3*cos(q1q2q3)代码结果必须与之完全一致。3.3 逆运动学解析法与数值法的边界判断课后练习中逆运动学题目一般限定在可解析求解的构型最常见的是“满足 Pieper 准则——三个相邻关节轴交于一点”的六轴臂或平面二/三连杆臂。解题策略是先看题目给的末端位姿能否分解出腕心位置能分解则用解析法不能分解或关节带限位才考虑数值迭代。这里必须强调一个文档答案不谈的问题解析法求出的是多组解课后题通常只要求“求出一组”但你可以把多组解全部列出肘上、肘下、腕部翻转并与关节限位做交集——这既是得分点也是真实工程里选解的第一步。以平面二连杆为例逆向求解需要先算末端到基座的距离 r sqrt(x^2 y^2)再通过余弦定理算 q2 acos((r^2 - l1^2 - l2^2)/(2l1l2))然后 q1 atan2(y, x) - atan2(l2sin(q2), l1 l2cos(q2))。q2 取正负得到两种构型。代码很简单但真正的理解在于为什么 q2 的符号会影响 q1 的补偿方向因为 q1 的表达式里包含了 q2 带来的末端偏转肘关节下沉时肩关节必须额外抬高才能让末端到达同一点。把这个几何关系画出来比记住任何公式都重要。4. 雅可比矩阵、静力传递与奇异性课后题拉开差距的地方4.1 从速度传递推导雅可比而不是背公式蔡自兴课后题在雅可比部分常出的题型是“给定各关节速度求末端速度”或者反过来“给定末端笛卡尔速度求关节速度”。很多答案文档直接写出一个 3x3 雅可比矩阵然后代入数字。但更稳妥的做法是先理解几何雅可比Geometric Jacobian的构造对旋转关节雅可比的每一列由两部分组成——角速度部分等于关节轴方向向量线速度部分等于关节轴方向向量与末端到关节轴的叉积即 J_i [z_i × (p_n - p_i); z_i]。这个公式需要三个量关节轴单位方向向量 z_i、末端位置 p_n、该关节坐标系原点位置 p_i。这些量全部来自正运动学计算的中间结果T_0i 的第三列和第四列所以一个完整的雅可比求解流程是先用 DH 表算出所有 T_0i再逐列构造雅可比。这样做的好处是即便题目给的机械臂不是常见的六轴构型你依然能算出雅可比而不是对着背好的公式发呆。import numpy as np def geometric_jacobian(T_list, joint_axes): T_list: 每个关节坐标系相对基座系的齐次变换矩阵列表T_list[i] 为 T_0(i1) joint_axes: 每个关节的旋转轴相对基座系通常取 T_list[i][:3, 2] n len(T_list) p_n T_list[-1][:3, 3] J np.zeros((6, n)) for i in range(n): z_i T_list[i][:3, 2] p_i T_list[i][:3, 3] J[:3, i] np.cross(z_i, p_n - p_i) J[3:, i] z_i return J这段代码中 joint_axes 参数其实可以直接从 T_list 中取第三列不必单独传入。注释里体现的是旋转关节的情况如果是移动关节则线速度部分等于 z_i角速度部分为 0。参数判断的要点在于当前关节是旋转还是移动决定了雅可比对应列的内容这在一道混合关节题目中是最高频的失分点。算完雅可比之后可以顺便检查矩阵条件数。如果条件数远大于 1说明机械臂接近奇异位形关节速度会被放大。课后题偶尔会问“该位形是否为奇异位形”标准的做法是令 J 的行列式为 0 或者检查秩是否小于行数。对平面三连杆机械臂J 是 3x3行列式等于 0 的几何含义是“三个关节轴的瞬时运动方向共面且相关”此时机械臂末端在某个方向上无法运动。4.2 静力传递与力雅可比一道综合题的完整解法另一类高难课后题是“已知末端承受外力 F求各关节力矩”这需要用到力雅可比的对偶关系 tau J^T F。这里要注意J^T 的符号约定与 J 的定义方式严格绑定如果 J 把关节速度映射到末端速度v J * q_dot那么关节力矩 J^T 乘以末端力中间不需要任何系数。这一点看起来简单但很多人会在多关节机器人的复合运动中搞混 J 与 J^T 的维度方向。做这类题时验证手段是检查量纲一致性F 的单位是 NJ^T 的线速度行对应 N·m角速度行对应 N·m/rad乘出来的结果确实是力矩。另一个验证手段是能量守恒F^T * v tau^T * q_dot代入 v J q_dot得到 F^T J q_dot tau^T q_dot从而 tau J^T F。如果你算出来的关节力矩无法同时满足这个能量关系说明前面某一步的雅可比构造有误。在答案文档中这一部分常常被压缩成一行“tau J^T F代入得”但真正的解题顺序是先求各关节的 T_0i再构造 J再做转置与力相乘最后检查是否有奇异导致力矩过大。奇异位形附近的静力传递也会出现力矩剧增这与速度域里的关节速度剧增是同一现象的两个侧写。4.3 奇异性判断的 3 个实操参数处理奇异相关的课后题时建议把以下三个参数作为固定检查项第一是雅可比矩阵的条件数 cond(J)它衡量雅可比在给定方向上对误差的放大倍数。条件数超过 100 时通常可以认为机械臂已进入奇异敏感区即使行列式没有严格为 0数值解也已不可靠。第二是奇异值分解中最小奇异值 sigma_min它直接告诉你“在这个位形下末端在哪个方向上的运动能力最弱”其对应右奇异向量就是不可动方向。第三是行列式的绝对值适合平面臂这种方阵雅可比但六轴臂的雅可比是 6x6行列式的数值范围可能很不直观这时看最小奇异值更稳定。实际习题里给的数据往往是理想的几何模型不存在测量噪声所以用行列式判定奇异是可行的。但如果你用同一套代码去处理实验数据或仿真数据就必须切换到条件数或奇异值阈值否则会出现“行列式接近 0 但机械臂明明还能动”的反直觉现象。这个差异本身就是一道不错的附加题为什么一个距离奇异位形 0.01 弧度的位形行列式可能已经小到 1e-4但末端的实际速度能力还很正常因为雅可比的量纲混合了长度与角度行列式的绝对值跟臂长尺度强相关没法跨构型比较。5. 动力学初探拉格朗日法与课后题的关键套路5.1 拉格朗日法的标准四步推导蔡自兴的动力学章节课后题通常集中在拉格朗日法因为牛顿-欧拉递推需要大量向量叉乘手算复杂度太高。拉格朗日法的标准解题流程是四步第一步写出各连杆质心在基座坐标系中的位置表达式第二步对时间求导得到质心速度进而写出系统动能 T Σ(1/2 * m_i * v_ci^2 1/2 * I_i * ω_i^2)第三步写出势能 V Σ m_i * g * h_i第四步代入拉格朗日方程 d/dt(∂L/∂q_dot) - ∂L/∂q τ其中 L T - V。课后题里最容易出错的是动能表达式中的转动项。很多初学者只算平移速度带来的动能忘记连杆自身绕质心的旋转导致最终动力学方程里缺了与角速度相关的惯性项。以二连杆平面臂为例连杆 1 和连杆 2 的角速度分别是 q1_dot 与 q1_dot q2_dot必须体现在动能里否则由离心力和科氏力导致的耦合项完全丢失。5.2 二连杆平面臂动力学方程的逐步推导代码import sympy as sp q1, q2 sp.symbols(q1 q2, realTrue) q1d, q2d sp.symbols(q1_dot q2_dot, realTrue) l1, l2 sp.symbols(l1 l2, positiveTrue) m1, m2 sp.symbols(m1 m2, positiveTrue) g sp.symbols(g, positiveTrue) # 质心位置假设每个连杆的质心在其几何中心 x1 (l1/2) * sp.cos(q1) y1 (l1/2) * sp.sin(q1) x2 l1 * sp.cos(q1) (l2/2) * sp.cos(q1 q2) y2 l1 * sp.sin(q1) (l2/2) * sp.sin(q1 q2) # 质心速度 v1x2 sp.diff(x1, q1)*q1d v1y2 sp.diff(y1, q1)*q1d v1_sq v1x2**2 v1y2**2 v2x sp.diff(x2, q1)*q1d sp.diff(x2, q2)*q2d v2y sp.diff(y2, q1)*q1d sp.diff(y2, q2)*q2d v2_sq v2x**2 v2y**2 I1 m1 * l1**2 / 12 I2 m2 * l2**2 / 12 T sp.Rational(1,2)*m1*v1_sq sp.Rational(1,2)*m2*v2_sq sp.Rational(1,2)*I1*q1d**2 sp.Rational(1,2)*I2*(q1d q2d)**2 V m1*g*y1 m2*g*y2 L T - V def lagrange(L, q, qd): dL_dqd sp.diff(L, qd) d_dt_dL_dqd sum(sp.diff(dL_dqd, var)*dvar for var, dvar in zip([q1, q2], [q1d, q2d])) dL_dq sp.diff(L, q) return sp.simplify(d_dt_dL_dqd - dL_dq) tau1 lagrange(L, q1, q1d) tau2 lagrange(L, q2, q2d) print(sp.simplify(tau1)) print(sp.simplify(tau2))代码里用 sympy 做符号推导核心逻辑是先把位置对广义坐标求偏导再乘以广义速度得到质心速度避免手算链式法则时漏项。拉格朗日方程中 d/dt(∂L/∂q_dot) 一项需要把 ∂L/∂q_dot 分别对 q1、q2 求偏导再乘上对应的广义速度代码里用循环实现了这个功能。参数说明l1、l2 是连杆长度质心假设在几何中心所以取 l/2转动惯量按细杆绕质心的公式 m*l^2/12势能取质心高度方向为正向上。这个推导结果与教材附录里的动力学方程对比时重点看两个耦合项包含 l1l2cos(q2) 的项对应科氏力包含 sin(q2) 的项对应向心力。如果这些项缺失或符号反了说明某个速度项的链式法则出了问题。用符号计算的好处是能把这项错误精确锁定到具体表达式而不是翻半天手算草稿也找不到错在哪一行。5.3 课后题中的简化假设与适用条件动力学课后题往往给出简化条件忽略连杆质量、只考虑末端负载、假设关节直接驱动、忽略摩擦等。这些假设不是随意产生的它们的目的是让动力学方程能在一张 A4 纸内写完。做题时要先审视题目给了哪些简化条件再决定拉格朗日方程里保留哪些项。如果题目没提摩擦就用拉格朗日法如果题目给了关节摩擦系数则要在方程右侧加入摩擦力项 tau_fric b * q_dot其中 b 是粘滞摩擦系数。另一个常被忽略的参数是重力方向。标准设置是重力沿负 Y 方向也就是竖直向下。如果题目把基座坐标系的 Z 轴设为竖直向上工业机器人很常见势能表达式要相应改为 V m * g * z而不是负号混乱导致最终方程符号错误。做题时可以约定一个统一的书写顺序先画坐标系和重力方向再列势能表达式最后检查当 q 增加时势能是增大还是减小这个符号判断能避免大量低级错误。6. 用“答案验证闭环”自查每一道课后练习与其依赖 .doc 答案文档不如建立一套可重复的验证闭环让你的推导结果在提交前自我确认。这套闭环保底三件事正运动学与几何直觉的一致性、逆解回代的重构精度、雅可比矩阵与数值微分的匹配。首先说正运动学验证随机生成若干组关节角用 DH 参数算出末端位置再用几何法平面臂的三角公式独立计算一遍两者误差应小于 1e-9。如果误差超过这个量级优先怀疑角度单位混用或 DH 参数中的 a 与 d 位置对调。这个验证可以直接写成 Python 断言np.allclose(pos_dh, pos_geo, atol1e-9)。其次是逆运动学验证将求出的关节解重新代入正运动学计算末端位置与给定目标之间的欧氏距离容差取 1e-6 米以内。如果逆解是多组解对所有候选解都做一次回代再把满足关节限位的那组作为最终答案。写代码时注意把逆解模块设计成入参为目标位姿、出参为候选关节角列表这样后续做轨迹规划时可以直接复用。最后是雅可比验证取一组关节角先用几何雅可比计算末端速度再用数值微分法——给每个关节角加一个微小增量如 1e-6 弧度重新做正运动学得到末端位姿两点的位置差除以增量得到线速度的一列。与解析雅可比对每个关节方向逐一比对误差小于 1e-4 就说明雅可比构造正确。这个验证尤其适合六轴机械臂因为六轴的雅可比矩阵手算极易出错而数值微分不依赖任何额外推导是独立验证的黄金标准。def numerical_jacobian_column(kin_func, q, joint_idx, delta1e-6): q_plus q.copy() q_plus[joint_idx] delta p_plus kin_func(q_plus) p_base kin_func(q) return (p_plus - p_base) / deltakin_func 是一个由 DH 参数生成的正运动学函数返回末端位置或完整位姿。把这个数值列与解析 J 的对应列做差如果最大值超过 1e-4说明解析雅可比的对应列有误需要检查 z_i 和 p_i 的提取是否来自正确的 T_0i 变换矩阵。注意数值微分对 delta 的取值敏感delta 太大会产生截断误差太小会因浮点精度产生舍入误差1e-6 弧度在绝大多数机械臂尺度下是安全折中。这套验证闭环不是某个标准答案文档的替代品而是比答案更严格的形式答案只告诉你“结果是什么”验证过程逼你直面“为什么是这个结果”。当你把课后题全部用这个闭环过一遍之后再去看网上下载的那些 .doc 文档你反而能一眼发现其中某几步的跳跃或符号错误——那时候你的推导本身就是最可靠的答案。本文还有配套的精品资源点击获取