1. 逆解问题的本质与方案选型
1.1 正解与逆解在工程里到底是个什么关系
先把这个基础问题说透。六轴机器人的正运动学,就是从六个关节角算出末端执行器在基坐标系里的位置和姿态,一条路走到黑,用DH参数把相邻连杆的齐次变换矩阵一个个乘起来,最后得到一个4x4的位姿矩阵T06。这个过程没有歧义,给定一组确定的角度,末端位姿就是唯一的。
逆解则是反过来:给定目标位姿T_goal,反推出能让机械臂末端到达这个位姿的六个关节角。这个问题的难度在于正解是一对一的映射,逆解却是一对多的映射——同一组末端位姿,可能对应着好几组不同的关节角组合。加上三角函数方程的非线性耦合,直接硬解六个方程是不现实的。我经常用一句话跟新人解释:正解是你手上拿着遥控器,按一下就看见手到了哪;逆解是你看见手要去的那个点,得自己去反想每一个关节该转多少,而且这答案往往不止一个。
在实际工程里,逆解的意义怎么强调都不过分。轨迹规划要逆解,视觉抓取要逆解,离线编程要逆解,力控和柔顺控制也要逆解。可以这么说,一个六轴机器人控制系统里,逆解算法直接决定了机器人能不能跑、跑得顺不顺、精度到底够不够。很多新手一上来就照着论文抄代码,结果装到自己的机器人上怎么算都不对,十有八九是没搞懂逆解推导过程中的几何意义和坐标变换细节。
1.2 为什么解析解法是第一选择
解六轴逆解,常规思路有三个:解析法、数值迭代法、以及离线查表法。我个人的建议是,只要机器人结构能用解析法解,就一定用解析法,不要拿数值法硬上。
解析法的核心优势在于速度和确定性。一次解析求解,无非是一堆atan2、sqrt、cos和sin的运算,在普通嵌入式控制器上跑一遍耗时在微秒级到亚毫秒级,而且每次解出来的解都是确定的——同样的输入永远是同样的输出,不会像牛顿迭代那样受到初值选取的影响。但需要注意一个前提条件:不是所有六轴机器人都能解析求解。能解析求解的关键在于结构是否满足Pieper准则,也就是后三个关节的旋转轴线是否交于一点,或者说机械臂是否具备球形腕部结构。
我手头这台六轴关节型机器人,就是一个典型的球形腕结构:关节4、5、6的轴线交于腕心。这样的结构让位置问题和姿态问题解耦了——腕心的位置只由前三个关节决定,末端姿态在腕心位置确定后由后三个关节补齐。这是整个解析推导的灵魂,只要抓住这一点,整套推导就有了一条清晰的线索。
数值迭代法(比如经典的Jacobian转置法、阻尼最小二乘法)当然也有它的用处。它的优点是不依赖机械臂的具体结构,几乎任何构型都能算,代价是慢、依赖初值、不稳定,而且每一次运算都需要多轮迭代。在某些奇异位形附近,迭代性能会严重恶化。查表法更是只在特定场景用,一般是预先离线把工作空间离散化,把解存成表,运行时查表加插值,适合那些实时性要求极高但精度需求不苛刻的场合,而且配置起来比较麻烦。所以,对于六轴关节型机器人这种主流结构,老老实实推解析解,是性价比最高的路线。
1.3 数值方法的适用场景
我不会把数值法一棍子打死。场景切换到七轴冗余机械臂或者某些非球形腕的特殊构型时,解析法基本失效,数值迭代法就成了必须的手段。还有一种混合思路,先解析求出靠近的几个解,再用这些解作为初值做局部数值优化,把精度进一步打磨上去。这种思路在标定和离线编程里很常用,既能保证初值稳定,又能补偿模型参数误差。
理解了这些背景,下面进入正题。我会用我一直在用的那台模拟六轴机器人作为例子,把DH参数、推导、代码、验算完整过一遍。整个流程你在自己的机型上复现时,只需要替换对应的DH参数和核实坐标系定义即可。
2. 基于腕部分离的解析逆解推导
2.1 DH参数建模与位姿矩阵
推导之前,先把模型立起来。这台模拟六轴机器人采用标准DH约定,参数如下:
| 关节i | θi | di (m) | ai (m) | αi |
|---|---|---|---|---|
| 1 | θ1 | 0.33 | 0 | -90° |
| 2 | θ2 | 0 | 0.40 | 0 |
| 3 | θ3 | 0 | 0.05 | -90° |
| 4 | θ4 | 0.38 | 0 | 90° |
| 5 | θ5 | 0 | 0 | -90° |
| 6 | θ6 | 0 | 0 | 0 |
末端还有一个工具长度d6 = 0.10m,扣在关节6的坐标系下面。
标准DH约定下,相邻连杆的齐次变换矩阵是:
T_i^{i-1} = Rz(θi) · Tz(di) · Tx(ai) · Rx(αi)
展开写就是:
T_i^{i-1} = [ cosθi, -sinθi·cosαi, sinθi·sinαi, ai·cosθi; sinθi, cosθi·cosαi, -cosθi·sinαi, ai·sinθi; 0, sinαi, cosαi, di; 0, 0, 0, 1 ]
这里每一个字母的含义都不复杂,真正容易犯的错在于αi的符号。我记得最早自己推公式时,因为一个α3的正负号和别人代码里差了个负号,结果θ2和θ3的求解公式看起来完全对不上,排查了一整个下午。后来学乖了,每推一步都用符号计算先验算一次,再往下走。
正解就是六个变换矩阵连乘:
T06 = T1^0 · T2^1 · T3^2 · T4^3 · T5^4 · T6^5 · T_工具
其中T_工具是末端工具的变换矩阵。对于本章讨论的逆解推导,工具只沿z轴偏置d6,所以可以在目标位姿中先把工具长度扣除,把目标位姿换算到关节6坐标系的原点(也就是腕心附近)再求解。
2.2 腕心坐标与前三关节的位置反解
球形腕结构的核心思想是这样的:末端位姿由位置和姿态两部分组成,但腕心位置完全由前三个关节决定。只要找到腕心在基坐标系里的坐标,前三个关节角就可以用几何法解出来,跟后三个关节完全无关。
腕心的坐标计算非常直接:已知目标位姿矩阵T_goal,它包含末端坐标p_end和姿态矩阵R_goal。腕心坐标就是:
p_w = p_end - d6 · R_goal · [0, 0, 1]^T
这段的几何意义是:从末端点沿工具坐标系的z轴反方向退回一个工具长度。
接下来分三步求θ1、θ2、θ3。
第一步求θ1。把腕心位置p_w = [px, py, pz]^T投影到基坐标系xy平面,θ1就是投影点相对x轴的方位角:
θ1 = atan2(py, px)
这一步有两组解,对应肩关节左右两个配置(righty/lefty),另一组解是θ1 + π。
第二步求θ2和θ3。这里要用到一个平面几何模型。把腕心位置换算成相对于关节2原点(也就是肩部)的位置,记为[x_w', y_w', z_w'],其中水平距离:
r = sqrt(px^2 + py^2) - a1
这个式子中的偏移项a1在这个模型里比较小,很多推导里会直接忽略,但在精度要求高的场合不能省。然后竖直方向的高度是:
h = pz - d1
接下来的核心就是已知r和h,加上大臂长度a2和小臂长度a3,在由肩、肘、腕三点构成的三角形里用余弦定理求θ2和θ3。
设从肩到腕的距离为:
L = sqrt(r^2 + h^2)
在三角形中,大臂a2、小臂a3与连线L构成一个三角形。由余弦定理:
cos(φ) = (a2^2 + L^2 - a3^2) / (2·a2·L)
其中φ是a2与L之间的夹角。由此得到:
θ2 = atan2(h, r) - φ
注意这里atan2(h, r)是连线L相对水平面的夹角。θ2有两组候选,对应肘部的上/下配置,取决于φ的正负号。
θ3则根据三角形内角求:
cos(ψ) = (a2^2 + a3^2 - L^2) / (2·a2·a3)
θ3 = π - ψ
同样,ψ的符号决定肘部配置。两组θ2和两组θ3组合起来,加上前面θ1的两组,前三个关节一共能组合出8种结构上不同的构型。这一步的推导极其依赖几何直觉,我建议你拿一张纸,画一个简单的肩-肘-腕俯视图,把r、h、a2、a3标上去,对照来看比直接记公式有效得多。
2.3 后三关节的姿态反解
前三个关节角确定后,前三个关节的姿态旋转矩阵R03就完全确定了。目标姿态是R_goal,那么腕部姿态矩阵R36就是:
R36 = (R03)^T · R_goal
这个R36表示的是由关节4、5、6绕各自轴线旋转合成的姿态。在球形腕结构下,这个姿态可以理解为ZYZ欧拉角序列。也就是说,θ4、θ5、θ6可以通过从R36中提取欧拉角得到。
这里有一个关键细节:提取公式的形式跟你的DH参数定义下的坐标系朝向强相关。在我这种标准DH定义的构型下,常用的提取公式是:
θ4 = atan2(R36(2,3), R36(1,3)) θ5 = atan2(sqrt(R36(1,3)^2 + R36(2,3)^2), R36(3,3)) θ6 = atan2(-R36(3,2), R36(3,1))
但如果你的机器人α4、α5的符号跟我的不一样,这里元素下标很可能要对调,甚至要改负号。我强烈建议不要把公式死记硬背,而是用符号计算工具把R36的符号表达式写出来,看着每个元素是哪些三角函数的组合,再反推提取公式。这个过程我第一次做花了差不多一天,但做完之后再也不会混淆了。
后三个关节同样存在多解,主要是腕部翻转(wrist flip)带来的:当θ5为正和θ5为负时,θ4和θ6的组合会不同。具体来说,如果θ5取另一组解(π - θ5或-θ5),θ4和θ6要相应加π来保持最终姿态不变。
2.4 多解的组成与几何意义
把前三个关节的8种组合和后三个关节的2种翻转组合乘起来,理论上最多有16组逆解。但实际计算会发现,因为关节限位和奇异位形的存在,真正可用的解往往远少于理论值。另外,某些特殊位形下,不同组合的解会退化到同一个构型,这在θ5 = 0时尤其明显。理解多解不是坏事,反而是逆解价值所在:给了你选择的空间,你可以挑一组最平滑、最省力、或者最安全的角度组合来驱动机器人。
3. Matlab解算的完整实现细节
3.1 用符号计算验证正解正确性
真正动手写逆解代码之前,我强烈建议先用Matlab的Symbolic Math Toolbox把正解推一遍并验证一次。这一步看似多余,但能杜绝大量低级错误。我的做法是先把六个齐次变换矩阵写成符号函数,然后连乘得到T06,把其中旋转部分的九个元素提取出来,和手推的公式逐一对比。
syms theta1 theta2 theta3 theta4 theta5 theta6 real syms d1 a2 a3 d4 d6 real % 标准DH变换函数 function T = dh_transform(theta, d, a, alpha) T = [cos(theta), -sin(theta)*cos(alpha), sin(theta)*sin(alpha), a*cos(theta); sin(theta), cos(theta)*cos(alpha), -cos(theta)*sin(alpha), a*sin(theta); 0, sin(alpha), cos(alpha), d; 0, 0, 0, 1]; end % 正解连乘 T01 = dh_transform(theta1, 0.33, 0, -pi/2); T12 = dh_transform(theta2, 0, 0.40, 0); T23 = dh_transform(theta3, 0, 0.05, -pi/2); T34 = dh_transform(theta4, 0.38, 0, pi/2); T45 = dh_transform(theta5, 0, 0, -pi/2); T56 = dh_transform(theta6, 0, 0, 0); T06 = simplify(T01*T12*T23*T34*T45*T56);符号表达式算出来之后,用一个简单的测例做数值验证:随便给一组关节角,比如[30°, 45°, 60°, 90°, 120°, 45°],用这个符号函数代出数值,再跟用数值矩阵手算的T06对比。两个结果逐元素相等,就说明正解模型没错。正解没错,逆解的验算才有意义。
3.2 逆解函数的结构与核心代码
逆解函数我一般设计成一个输入目标位姿、输出所有候选解的接口。这样无论是单个点位求解,还是批量轨迹解算,都可以复用同一个核心函数。
核心代码大致长这样:
function solutions = ik_6dof(T_goal, dh, tool_length) % 从目标位姿扣除工具长度,得到腕心位置 R_goal = T_goal(1:3,1:3); p_goal = T_goal(1:3,4); p_w = p_goal - tool_length * R_goal * [0; 0; 1]; px = p_w(1); py = p_w(2); pz = p_w(3); d1 = dh.d1; a2 = dh.a2; a3 = dh.a3; d4 = dh.d4; solutions = []; % 第1组:theta1 主解,lefty 配置 for shoulder = [0, 1] % 0 = 左, 1 = 右 if shoulder == 0 theta1 = atan2(py, px); else theta1 = atan2(py, px) + pi; end r = sqrt(px^2 + py^2) - 0; % 本例 a1=0,若有偏移则减去 h = pz - d1; L = sqrt(r^2 + h^2); % 检查可达性 if L > (a2 + a3) || L < abs(a2 - a3) continue; end phi = acos((a2^2 + L^2 - a3^2) / (2*a2*L)); psi = acos((a2^2 + a3^2 - L^2) / (2*a2*a3)); for elbow = [0, 1] % 0 = 肘上, 1 = 肘下 if elbow == 0 theta2 = atan2(h, r) - phi; theta3 = pi - psi; else theta2 = atan2(h, r) + phi; theta3 = pi + psi; end % 计算前三个关节的姿态矩阵 R03,进而求 R36 T01 = dh_transform(theta1, d1, 0, -pi/2); T12 = dh_transform(theta2, 0, a2, 0); T23 = dh_transform(theta3, 0, a3, -pi/2); R03 = (T01*T12*T23) * [1 0 0; 0 1 0; 0 0 1]; R03 = T01(1:3,1:3) * T12(1:3,1:3) * T23(1:3,1:3); R36 = R03.' * R_goal; % 从 R36 提取 theta4, theta5, theta6 theta5 = atan2(sqrt(R36(1,3)^2 + R36(2,3)^2), R36(3,3)); if abs(theta5) > 1e-6 % 非奇异 theta4 = atan2(R36(2,3), R36(1,3)); theta6 = atan2(-R36(3,2), R36(3,1)); solutions = [solutions; theta1 theta2 theta3 theta4 theta5 theta6]; % 腕部翻转解 theta5_alt = -theta5; theta4_alt = theta4 + pi; theta6_alt = theta6 + pi; solutions = [solutions; theta1 theta2 theta3 theta4_alt theta5_alt theta6_alt]; else % 奇异位形:theta5约等于0,theta4/theta6退化,令theta4=0 theta4 = 0; theta6 = atan2(R36(2,1), R36(1,1)); solutions = [solutions; theta1 theta2 theta3 theta4 0 theta6]; end end end % 对角度做标准化到 [-pi, pi] 或你设置的关节限位范围 solutions = wrapToPi(solutions); end这段代码里每一个变量都有明确的作用。theta1区分左右肩,elbow区分肘部上下,theta5的正负区分腕部翻转。每次把找到的解append到solutions矩阵里,最后统一做角度标准化。要注意,我在腕部奇异时固定θ4 = 0来解θ6,这是一种常见的工程处理,称为奇异退化解。
3.3 最优解选择:不光要解出来还要解得好
解出来只是第一步,真正工程中难点在于从若干候选解里挑一个最合适的。我常用的选解策略有三个维度。
第一是关节限位过滤。所有解先过一遍限位检查,θi必须在[min_i, max_i]范围内,越界的直接丢弃。这个过滤能删掉一大批候选。
第二是平滑性优先。在连续轨迹中,我会让当前时刻选的解跟上一时刻实际使用的关节角变化量最小。具体实现就是计算每个候选解与上个解的每个关节差的绝对值加权求和,取总和最小的那一个。这里的加权系数可以按关节的重要性设置,通常大臂和小臂的权重略大,腕部关节可以小一点。
第三是避障约束。如果机器人工作空间里有障碍物,可以在选解阶段加入额外的碰撞检测,或者用代价函数惩罚靠近障碍物的构型。这一步在纯几何逆解代码里不会体现,但工程应用时通常绕不开。
3.4 边界条件与奇异位形的处理
写逆解函数,最难的不是公式,而是各种边界情况。首先要判断目标位姿是否在工作空间内:如果腕心到基座的距离超出大臂加小臂的总长,或者小于两者之差,这个点位就是不可达的,直接返回空解。这个判断我在算L的时候一并做了,避免了后面acos出现复数。
其次是θ5接近0的腕部奇异。此时腕部三个关节的轴线近似共线,θ4和θ6的解不唯一,单独求某个角没有意义。工程上的标准做法是让其中一个关节取当前值或固定值,再算另一个,从而保证解的连续性。在代码里我用θ4 = 0,然后计算θ6。
还有一个细节容易被忽视:角度标准化。关节角动不动就从179度跳到-179度,这在数值上虽然是相邻值,但对控制器来说是一次大角度回绕。所以我统一用wrapToPi把所有解标准化到[-π, π],选解时再配合回绕判断,避免无故的跳变。
4. 验算的完整步骤与结果评判
4.1 正解回代法:最直接的验证
逆解写完之后,第一件事是用正解回代验证。方法很简单:把逆解求出的某个关节角组合代回正运动学函数,计算末端位姿T_check,然后和原始目标位姿T_goal对比。位置误差取三个平移分量的欧氏距离,姿态误差可以用旋转矩阵的差值范数,或者转成轴角误差来度量。
theta_sol = solutions(1, :); T_check = fk_6dof(theta_sol, dh, tool_length); pos_err = norm(T_check(1:3,4) - T_goal(1:3,4)); rot_err = norm(T_check(1:3,1:3) - T_goal(1:3,1:3), 'fro');一般来说,位置误差在1e-9量级、旋转部分误差在1e-8量级都是正常的,这基本上是浮点数精度问题。如果你的误差是1e-3甚至更大,说明推导或代码里某个环节有bug,不要以为差一点点没关系,这种误差在累积后会被轨迹规划进一步放大。
我每次迭代改完代码,都会把回代验证固定成回归测试:保存一批随机目标位姿,每次跑完代码自动算一遍,确保没有破坏已有的求解能力。这样做有一个额外的好处:我会不断积累测试用例,其中包含了一些特殊位形(腕部附近、工作空间边界、奇异点附近),对后续调试特别有帮助。
4.2 随机位姿批量测试与误差统计
单个点位验证通过后,还要做批量测试,覆盖整个可达工作空间。我习惯的做法是,在工作空间内随机生成大量目标位姿,逐个求解逆解,然后对每个解做正解回代,统计误差分布。如果误差分布全部落在1e-7量级以内,基本可以确认推导过程没问题。
% 随机生成1000个目标位姿做批量验证 for k = 1:1000 % 随机生成一组关节角,代入正解得到目标位姿 theta_random = rand(1,6) * [2*pi, 2*pi, 2*pi, 2*pi, 2*pi, 2*pi]; T_goal = fk_6dof(theta_random, dh, tool_length); sols = ik_6dof(T_goal, dh, tool_length); if isempty(sols) error('存在不可达位姿,需要检查模型'); end % 对每组解回代验算 min_pos_err = inf; for j = 1:size(sols, 1) T_check = fk_6dof(sols(j,:), dh, tool_length); err = norm(T_check(1:3,4) - T_goal(1:3,4)); min_pos_err = min(min_pos_err, err); end if min_pos_err > 1e-6 error('第%d个随机位姿验算失败,误差%.2e', k, min_pos_err); end end为什么要用随机正解生成的位姿来测试?因为这样生成的目标位姿永远是可达的,避免了把"不可达"误诊为"逆解失败"的情况。这个测试思路我每次换机型、换DH参数都会跑一遍,省心省力。
4.3 轨迹连续性与动态验证
点位验证只是静态的,机器人实际运行时是走轨迹的,所以还需要验证动态连续性。我通常在关节空间规划一条简单轨迹,比如从A点直线插补到B点,在中间插值成一系列目标位姿,然后解析求解每个中间点的逆解,同时观察相邻解之间的关节角差异。
这条轨迹测试最常暴露的问题就是多解跳变。明明机器人上一时刻还在某个构型,下一时刻由于选解策略没有考虑平滑性,突然跳到另一个等效构型,结果关节角发生大幅突变。这时候就需要用我之前说的"变化量最小"选解策略来解决。
还有一个常见的动态问题是关节角回绕。角度从179度变到-179度,差值看是358度,但实际只需转2度。所以在计算相邻解差值时,一定要先用wrapToPi把差值包络到[-π, π],再求绝对值。这个坑我踩过,轨迹跑起来以后机械臂会莫名其妙地狂转,一开始还以为是电机有问题,最后发现是选解逻辑没有处理回绕。
4.4 可视化验证
验证的最后一道保险是可视化。用Matlab画一个简单的3D机械臂模型,把DH参数和关节角传进去,画出连杆的线段和末端位置。然后把逆解得到的关节角代入,观察机械臂是否真的到达了目标位姿。这一步直观高效,一看到机械臂的姿势不对,基本就能猜到是哪个环节出了错。
我习惯把随机批量测试和可视化结合:随机生成目标点,画出目标末端位置和实际末端位置,两者应该完全重合。再在轨迹测试里,把机械臂的动画保存成视频回放,观察运动过程是否平滑。可视化的好处是能发现那些数值上正确但几何上明显不对的解——比如某个解虽然回代误差是1e-12,但构型看起来就别扭,这时候八成是选取了错误的解分支,需要检查θ2和θ3的符号处理。
5. 常见问题与排查心得
5.1 解不出来或解不连续
新手最常见的现象是某些目标点位下,逆解函数返回空数组。这大概率不是算法问题,而是目标点位压根不可达,或者接近工作空间边界。我排查时先检查L是否超出可达范围,再把目标点位打印出来看是否接近边界。如果点位在边界上,比如腕心距离恰好等于a2+a3,这时候acos的参数接近1或者-1,数值上容易有微小误差导致被误判为不可达,解决方法是给可达性判断加一个很小的容差,比如1e-6。
还有一种"解不存在"的情况更加隐蔽:前三个关节解出来了,但后三个关节提取欧拉角时,sqrt根号下的式子出现了负数。由于数值误差,R36(1,3)和R36(2,3)的平方和理论上是非负的,但极端情况下可能因为浮点误差变成-1e-18,取sqrt就变成NaN。这种问题用max(0, ...)夹紧一下根号内值就能解决。
5.2 角度越界与限位冲突
实体机器人每个关节都有机械限位,逆解算出的角度可能在数学上合理,但物理上根本走不到。这就需要在选解阶段有一个"限位感知"的过程。我一般在解出所有候选解后,用一个布尔向量记录哪些解越界了,再在选解时从未越界的解里挑。如果所有解都越界,说明目标位姿需要从另一侧绕路,或者根本是无法到达的姿态。
限位还会引出一个有意思的现象:某些位姿在理论上有解,但实际机构受限于限位无法到达,这个时候只有两条路——一是改变末端路径,绕过限位死角;二是调整机器人基座的安装朝向,把整个工作空间旋转一个角度。这个问题经常在产线调试时才暴露出来,所以做逆解选型时一定要把限位信息提前处理好,不要等设备装好了才发现。
5.3 符号计算与数值计算精度
Matlab符号计算得到的大表达式直接用于数值计算往往效率很低,而且可能引入不必要的复杂度。我的经验是:符号计算用于推导验证,数值计算用等效的简化公式。前期用符号计算确认了公式形式正确,之后把公式手动化简到最简形式,再用数值代码实现。两者结果对照无误后,正式版本就只保留数值实现。
另外,凡是涉及反三角函数的运算,一律用atan2代替acos或asin。atan2天然处理四个象限,输入在分母接近0时也不会崩。acos和asin的返回值区间有限,且对误差敏感,尤其在多解选择时容易给出错误分支。这个细节能大幅度减少调试时间。
5.4 工程落地的经验总结
最后聊几个工程落地的细节。第一,逆解函数要跟具体的机器人控制周期匹配。如果控制周期是1kHz,一次逆解运算必须控制在0.1ms量级,这时候就不能在选解里加太重的碰撞检测,需要把几何验证和避障判断放到单独的线程或降低频次。第二,一定要把DH参数和工具长度作为外部参数传入,而不是写死在代码里——换工具是经常发生的事,写死了就得改代码,容易出错。
第三,逆解结果要跟关节角度反馈闭环配合。我见过不少案例,逆解算法没问题,但实际运行还是偏差大,最后发现是编码器零点偏移导致实际关节角跟指令角对不上。逆解只是整个控制链条里的一环,前面标定、零点、传动比、后面前馈、闭环,每一项都会影响最终精度。
我个人最深的体会是,逆解推导这件事,越是想绕过去,越会被它卡住。很多做上位机的工程师觉得直接用现成库就行,不用管内部怎么算。但如果遇到库解决不了的特殊需求——比如指定构型、避障选解、奇异规避——你就必须自己掌握整套计算逻辑。把推导、实现、验算这三点走通一遍之后,后面不管换什么结构的新设备,心里都有底。