
简介本资源是一套面向机器人控制初学者与高校自动化/机械电子专业学生的MATLAB实践代码包聚焦二关节机械臂的PD阻抗控制原理实现与工程验证。通过完整闭环控制建模、动力学计算基于拉格朗日方程、虚拟环境刚度-阻尼参数映射及实时力/位置协同响应仿真帮助学习者深入理解现代机器人柔顺控制的核心机制。压缩包共12个文件449KB含4个核心M函数实现正向运动学、逆动力学、PD控制器与阻抗映射、1个Simulink仿真模型L_sim.mdl、1份PDF程序解释文档、1份Word详细注释说明以及5张关键结果图末端轨迹、位置跟踪、控制力矩、力响应与期望轨迹对比图文代码三位一体便于逐模块调试与原理对照。已有103人学习下载注释覆盖变量物理意义、控制律推导逻辑及参数整定建议显著降低动力学建模与阻抗控制入门门槛。 一年前去一家协作机器人公司面试面试官问我机械臂要抓鸡蛋怎么保证不捏碎当时我脑子里只有“力控制”三个字回来花了两周把二关节机械臂的PD阻抗控制在MATLAB里完整实现了一遍才真正想明白这门技术的门道。这篇博客就把我沉淀下来的全套源码、逐行注释和调参心得整理出来。整套仿真不依赖任何机器人工具箱从动力学建模到阻抗控制闭环全部手写适合正在学机器人控制、做毕设需要柔顺控制示例、或者想快速跑通机械臂仿真的同学参考。我会把每个函数为什么这样写、每个参数为什么这样设都讲清楚保证你能把代码拷下来直接跑也能改造出自己的控制方案。1. 阻抗控制到底在解决什么问题1.1 为什么纯位置控制不够用机械臂最常见的控制方式就是PID位置控制让关节角快速跟踪期望位置。这在搬运、码垛这类场景里非常好用机械臂基本不会和外界有太多接触。但一旦遇到需要和环境发生物理接触的任务比如打磨、抛光、装配、人机协作纯位置控制就暴露出致命问题位置环会把接触力当成误差拼命消除结果就是机械臂越推越用力轻则工件损坏重则机械臂本体受损。我之前试过拿一个刚性位置控制的机械臂去推桌子力矩一上来整个底座都在抖那个冲击力真的吓人。阻抗控制就是给机械臂加了一层“柔性”它不直接控制力而是控制“位置偏差和接触力之间的关系”。通俗理解就是让机械臂对环境表现得像一个弹簧加阻尼系统。你推它它会顺着你的力退让一点你松手它又会慢慢回到期望位置。退让多少由刚度决定回弹过程有多平缓由阻尼决定响应有多快由惯性决定。这不只是调软了位置环而是从控制律层面把力位关系显式建模进去。1.2 阻抗控制与PD控制的本质关系阻抗控制的核心方程长这样Md * (qdd - qdd_d) Bd * (qd - qd_d) Kd * (q - q_d) tau_ext其中Md、Bd、Kd分别是你期望闭环系统表现的虚拟惯量、虚拟阻尼和虚拟刚度tau_ext是外界通过接触力映射到关节上的外力矩。这个方程描述的是当外界力矩作用在机械臂上时位置误差会以怎样的轨迹发展。如果你把期望轨迹设成恒定即qdd_d、qd_d都为0q_d是常数方程就退化成Md * qdd Bd * qd Kd * (q - q_d) tau_ext这时候再配上动力学补偿本质上就是一个带重力补偿的PD控制器。所以很多人把这种关节空间阻抗控制叫PD阻抗控制就是这个原因力矩输出中确实有一个PD结构在起作用阻抗参数直接落在PD增益上。区别在于普通PD控制只关心跟踪精度阻抗控制还关心接触力作用下的位置偏差到底有多大两者目标不同设计思路也不同。2. 二关节机械臂动力学建模2.1 平面2R机械臂的动力学方程在做控制仿真前必须先有被控对象的模型。平面二关节机械臂是最经典的入门对象虽然结构简单但已经具备完整的非线性特征质量矩阵随构型变化、科氏力与离心力耦合、重力项随角度变化。用平面2R把流程跑通后面换六轴也就是矩阵维度变大逻辑完全一样。我用的是质量集中在连杆末端的简化模型两个连杆长度取1米质量各取1千克。质量矩阵、科氏力矩阵、重力项的公式分别如下质量矩阵M(q) M11 m1L1^2 m2(L1^2 L2^2 2L1L2cos(q2)) M12 m2(L2^2 L1L2cos(q2)) M21 M12 M22 m2*L2^2科氏力/离心力矩阵C(q, qd) h -m2L1L2sin(q2) C [hqd2, h*(qd1qd2); -h*qd1, 0]重力项G(q) G1 (m1m2)gL1cos(q1) m2gL2cos(q1q2) G2 m2gL2*cos(q1q2)这个模型的推导在很多机器人学教材里都有关键点在于M(q)是正定对称矩阵M(q) - 2C(q,qd)满足斜对称性质这个性质在证明阻抗控制稳定性时非常有用。实际应用中如果你的机械臂是实心连杆而非质点可以在每个连杆末端加一个惯量项M矩阵的对角线会相应增大。2.2 雅可比矩阵与末端外力映射阻抗控制里有一个环节经常被忽略外力是在末端笛卡尔空间测量的但控制律在关节空间执行两者之间需要一个映射桥梁就是雅可比矩阵。末端力F_ext作用到机械臂上产生的等效关节力矩是tau_ext J(q) * F_ext平面2R机械臂的末端雅可比矩阵是J [-L1sin(q1) - L2sin(q1q2), -L2sin(q1q2); L1cos(q1) L2cos(q1q2), L2cos(q1q2)]这里有个容易踩坑的地方如果你想看机器人在末端受到外力后的柔顺效果直接模拟这个过程需要把末端力换算到关节。但在真实系统中外力矩往往通过关节力矩传感器或者六维力传感器观测得到存在噪声和延迟。仿真中由于用的是真实值控制效果会比实物更理想这点要有心理预期。3. PD阻抗控制律设计与参数整定3.1 从目标阻抗方程推导控制律控制律的设计思路是这样的我们希望整个闭环系统满足目标阻抗方程也就是把机械臂的行为“整定”成期望的弹簧阻尼系统。机械臂的动力学方程是M(q)*qdd C(q,qd)*qd G(q) tau tau_ext其中tau是关节驱动力矩tau_ext是外部施加到关节的外力矩。注意这里的符号约定外力可能帮助运动也可能阻碍运动统一加在方程右侧。如果想让系统在理想情况下满足目标阻抗方程可以设计tau M(q)*qdd_cmd C(q,qd)*qd G(q) - tau_ext其中qdd_cmd是期望关节加速度由目标阻抗方程反解得到qdd_cmd qdd_d Md^(-1) * (-Bd*(qd - qd_d) - Kd*(q - q_d) tau_ext)把tau代入动力学方程会在理想情况下抵消掉系统自身的非线性项得到Md*(qdd - qdd_d) Bd*(qd - qd_d) Kd*(q - q_d) tau_ext这就是目标阻抗关系。整个控制律可以拆成几块来理解M(q)*qdd_cmd是惯性前馈让系统能按期望加速度运动C(q,qd)*qd是科氏力和离心力补偿消除动态耦合G(q)是重力补偿防止机械臂下坠减掉tau_ext这一项是为了避免外力被位置环当成扰动反复抵抗。实际控制中M、C、G用的是模型估计值如果模型不准确阻抗关系会有偏差但误差动力学依然是稳定的只是阻抗参数的表现会和设计值略有出入。这也是阻抗控制比直接力控制更鲁棒的一个重要原因。3.2 为什么不能省略重力补偿很多初学者做阻抗控制仿真时直接把tau Kde Bded发给系统结果发现机械臂根本停不住尤其是在竖直平面内运动的机械臂重力会把关节往下拉。我最初调试的时候也犯过这个错误当时天真的以为PD增益够大就能压住重力结果发现不但压不住还把系统搞震荡了。重力项在关节空间中是个随角度变化的大偏置PD控制器要消除这个偏置靠的是产生一个与实际重力相反的力矩但没有前馈时这个力矩要等位置误差变大之后才够大系统性稳态误差根本无法消除。加了G(q)前馈之后即使PD增益不大系统也能在期望位置停得稳稳的。这就像你用手提一桶水前馈是你预先知道重量开始就用力纯PD是先让桶沉下去一点再拉回来。在仿真里可以做一个对比实验把控制律里的G(q)项注释掉你会发现两个关节的角度最终都会偏离期望值偏多少取决于Kd和重力的大小。3.3 参数整定的经验参考阻抗参数的整定是这个控制方案的核心难点我给出的初始值是经过反复试错得到的经验值Md diag([1; 1])目标惯量影响系统的响应速度取得太大系统迟钝太小则容易对高频干扰敏感Kd diag([50; 30])目标刚度决定位置跟踪精度刚度越大跟踪越紧但接触力也越大Bd diag([14; 11])目标阻尼我按照临界阻尼公式B 2sqrt(KdMd)来取Md1时就是B2*sqrt(Kd)。临界阻尼这个概念很实用。阻尼太小接触后机械臂会来回振荡好几下阻尼太大虽然不振荡了但机械臂的响应会显得很“肉”推一下要半天才回到位。按临界阻尼取系统刚好不超调且响应最快这是比较稳妥的底线选择。实际产品中如果需要快速收敛可以把B取到临界阻尼的0.7到1.0倍之间。4. MATLAB仿真代码逐段拆解4.1 主程序与期望轨迹设计仿真主程序包含几个部分参数初始化、RK4积分器、结果存储和绘图。我选择用RK4而不是MATLAB自带的ode45主要原因是RK4的分步求解逻辑清晰每一步的期望轨迹和外部力都能精确控制非常适合教学演示。步长取0.001秒在刚度50的情况下这个步长已经足够稳定。期望轨迹这里用了余弦平滑函数s(t) 0.5 - 0.5cos(pit/Tf)t Tf时 s(t) 1t Tf时这个函数的好处是位置的一阶导和二阶导也能解析表达不需要做数值微分。期望位置从初始角度平滑过渡到期望终点整个过渡时间Tf设为1.5秒。有人可能会问为什么不直接设一个阶跃信号那是因为阶跃的加速度无穷大会让控制力矩瞬间顶到饱和而且很容易激发机械臂的高频振荡调参时会区分不清是控制律的问题还是输入信号的问题。外部力我设置成了一个时变方案在1.0秒到1.3秒之间在末端施加一个[5; -10]牛顿的接触力其他时间为零。这样既能观察跟踪状态又能看到外力扰动后的柔顺退让和恢复过程。4.2 核心函数动力学、雅可比与阻抗控制律动力学函数用前面给出的公式实现。代码里用params结构体传递所有参数可以避免到处定义全局变量这是一个编程习惯建议直接学习。这里有一个细节要特别注意C矩阵乘的是当前关节速度qd不是期望速度很多新手会把这两者搞混导致补偿力矩方向错误。雅可比函数本身不复杂但它的使用场景值得强调。它既用于把末端外力换算成关节力矩也是后续如果要做末端笛卡尔空间阻抗控制时的核心工具。如果你想扩展成六轴机械臂只需要把雅可比换成6x6或者6xN的形式。阻抗控制律函数是整个程序的核心它的输入包括当前状态、期望轨迹、模型矩阵和外力力矩输出是控制力矩。我用的是向量化写法最后用矩阵左除Md \ 来求期望加速度避免手动求逆矩阵带来的潜在数值问题。MATLAB的矩阵左除在求解线性方程组时比直接inv(Md)*向量更稳定这一点在矩阵条件数较大时尤其明显。控制律中qdd_cmd的物理含义是为了满足目标阻抗关系当前时刻关节需要达到的加速度。它把位置误差、速度误差和外力三项信息融合在一起再交给位置前馈去执行。每当我在调试中看到某一个方向振荡特别明显第一反应就是先检查这个方向上的Bd和Kd是否匹配。4.3 完整可运行MATLAB源码下面给出完整的仿真脚本包含主程序和所有子函数。在MATLAB R2019b及以上版本可以直接运行不需要任何工具箱。建议先原样跑一遍然后再修改参数观察变化。% 二关节机械臂PD阻抗控制仿真完整源码自带详细注释 % 功能平面2R机械臂在关节空间的阻抗控制 % 特点全手写动力学与RK4积分器不依赖机器人工具箱 % 用法直接运行输出关节角跟踪曲线、控制力矩曲线与接触力曲线 clear; clc; close all; %% 1. 模型与控制参数 % 平面2R机械臂模型参数质量集中到末端 params.L1 1.0; % 连杆1长度单位m params.L2 1.0; % 连杆2长度单位m params.m1 1.0; % 连杆1质量单位kg params.m2 1.0; % 连杆2质量单位kg params.g 9.81; % 重力加速度假设机械臂在竖直平面内工作 % 阻抗控制参数目标阻抗 params.Md diag([1; 1]); % 目标惯量矩阵 params.Kd diag([50; 30]); % 目标刚度矩阵 params.Bd diag(2*sqrt([50;30])); % 目标阻尼矩阵按临界阻尼取B2*sqrt(K*M) % 期望轨迹参数 params.q_d0 [0.5; 0.8]; % 初始期望关节角单位rad params.q_d1 [0.8; 1.0]; % 终点期望关节角单位rad params.Tf 1.5; % 期望轨迹过渡时间单位s % 末端接触力参数 params.F_amp [5; -10]; % 接触力幅值[N]方向为末端笛卡尔坐标 params.F_start 1.0; % 接触力开始时间 params.F_end 1.3; % 接触力结束时间 % 仿真步长与时长 dt 0.001; % 积分步长RK4要求步长足够小 T_total 3.0; % 总仿真时长单位s N round(T_total / dt); % 总步数 % 机械臂初始状态 q [0.5; 0.8]; % 初始关节角 qd [0; 0]; % 初始关节角速度 %% 2. 预分配存储数组 time (0:N-1) * dt; % 时间序列 q_hist zeros(2, N); % 关节角历史 qd_hist zeros(2, N); % 关节角速度历史 q_d_hist zeros(2, N); % 期望关节角历史 tau_hist zeros(2, N); % 控制力矩历史 F_hist zeros(2, N); % 末端外力历史 %% 3. 主仿真RK4循环 for k 1:N t time(k); % 当前时刻期望轨迹 [q_d, qd_d, qdd_d] desired_trajectory(t, params); q_d_hist(:, k) q_d; % 当前时刻末端外力 F_ext external_force(t, params); F_hist(:, k) F_ext; % 状态向量x [q1; q2; qd1; qd2] x [q; qd]; % RK4四阶龙格库塔积分 k1 state_derivative(t, x, params); k2 state_derivative(t 0.5*dt, x 0.5*dt*k1, params); k3 state_derivative(t 0.5*dt, x 0.5*dt*k2, params); k4 state_derivative(t dt, x dt*k3, params); x_new x (dt/6) * (k1 2*k2 2*k3 k4); % 更新状态 q x_new(1:2); qd x_new(3:4); % 记录当前时刻控制力矩用当前状态的k1来算 [~, ~, ~, tau] state_with_torque(t, x, params); tau_hist(:, k) tau; q_hist(:, k) q; qd_hist(:, k) qd; end %% 4. 绘图 % 4.1 关节角跟踪曲线 figure(Name, 关节角跟踪, Color, w); for i 1:2 subplot(2, 1, i); plot(time, q_hist(i,:), b-, LineWidth, 1.5); hold on; plot(time, q_d_hist(i,:), r--, LineWidth, 1.5); ylabel(sprintf(关节%d角 [rad], i)); xlabel(时间 [s]); legend(实际, 期望, Location, best); grid on; end sgtitle(二关节机械臂PD阻抗控制关节角跟踪); % 4.2 控制力矩曲线 figure(Name, 控制力矩, Color, w); plot(time, tau_hist(1,:), b-, LineWidth, 1.5); hold on; plot(time, tau_hist(2,:), r-, LineWidth, 1.5); ylabel(控制力矩 [Nm]); xlabel(时间 [s]); legend(关节1力矩, 关节2力矩, Location, best); grid on; title(PD阻抗控制关节控制力矩); % 4.3 末端接触力曲线 figure(Name, 末端接触力, Color, w); plot(time, F_hist(1,:), b-, LineWidth, 1.5); hold on; plot(time, F_hist(2,:), r-, LineWidth, 1.5); ylabel(末端力 [N]); xlabel(时间 [s]); legend(Fx, Fy, Location, best); grid on; title(末端施加的接触力); %% 子函数1期望轨迹 function [q_d, qd_d, qdd_d] desired_trajectory(t, params) % 余弦平滑期望轨迹 % 输入当前时间t参数结构体params % 输出期望关节角、期望角速度、期望角加速度 q0 params.q_d0; q1 params.q_d1; Tf params.Tf; if t Tf s 1; ds 0; dds 0; else s 0.5 - 0.5*cos(pi*t/Tf); ds 0.5*pi/Tf*sin(pi*t/Tf); dds 0.5*(pi/Tf)^2*cos(pi*t/Tf); end q_d q0 (q1 - q0) * s; qd_d (q1 - q0) * ds; qdd_d (q1 - q0) * dds; end %% 子函数2外部接触力 function F_ext external_force(t, params) % 模拟末端接触力在指定时间窗口内施加恒定力 F_ext zeros(2, 1); if t params.F_start t params.F_end F_ext params.F_amp; end end %% 子函数3机械臂动力学 function [M, C, G] manipulator_dynamics(q, qd, params) % 平面2R机械臂动力学 % 输入关节角q[q1;q2]关节角速度qd[qd1;qd2]参数结构体 % 输出质量矩阵M科氏力矩阵C重力向量G L1 params.L1; L2 params.L2; m1 params.m1; m2 params.m2; g params.g; q1 q(1); q2 q(2); dq1 qd(1); dq2 qd(2); % 质量矩阵 M11 m1*L1^2 m2*(L1^2 L2^2 2*L1*L2*cos(q2)); M12 m2*(L2^2 L1*L2*cos(q2)); M22 m2*L2^2; M [M11, M12; M12, M22]; % 科氏力/离心力矩阵 h -m2 * L1 * L2 * sin(q2); C [h*dq2, h*(dq1dq2); -h*dq1, 0]; % 重力项 G [(m1m2)*g*L1*cos(q1) m2*g*L2*cos(q1q2); m2*g*L2*cos(q1q2)]; end %% 子函数4雅可比矩阵 function J manipulator_jacobian(q, params) % 平面2R机械臂末端雅可比矩阵 % 用于将末端笛卡尔力映射为关节空间力矩tau_ext J * F_ext L1 params.L1; L2 params.L2; q1 q(1); q2 q(2); J [-L1*sin(q1) - L2*sin(q1q2), -L2*sin(q1q2); L1*cos(q1) L2*cos(q1q2), L2*cos(q1q2)]; end %% 子函数5阻抗控制律 function tau impedance_control_law(q, qd, q_d, qd_d, qdd_d, M, C, G, tau_ext, params) % PD阻抗控制律 % 输入当前关节状态、期望轨迹、模型矩阵、外力矩 % 输出关节控制力矩tau Md params.Md; Bd params.Bd; Kd params.Kd; % 位置误差和速度误差 e q - q_d; ed qd - qd_d; % 由目标阻抗方程解出期望关节加速度 % Md*(qdd - qdd_d) Bd*ed Kd*e tau_ext % qdd_cmd qdd_d Md^{-1}*(-Bd*ed - Kd*e tau_ext) qdd_cmd qdd_d Md \ (-Bd*ed - Kd*e tau_ext); % 控制力矩非线性补偿 阻抗闭环 tau M*qdd_cmd C*qd G - tau_ext; end %% 子函数6状态导数 function dx state_derivative(t, x, params) % 计算状态导数 dx [qd; qdd] % 这是RK4被积分的核心函数 q x(1:2); qd x(3:4); % 期望轨迹 [q_d, qd_d, qdd_d] desired_trajectory(t, params); % 末端外力 F_ext external_force(t, params); % 模型矩阵 [M, C, G] manipulator_dynamics(q, qd, params); J manipulator_jacobian(q, params); % 外力映射到关节 tau_ext J * F_ext; % 阻抗控制力矩 tau impedance_control_law(q, qd, q_d, qd_d, qdd_d, M, C, G, tau_ext, params); % 机械臂动力学方程M*qdd C*qd G tau tau_ext qdd M \ (tau tau_ext - C*qd - G); dx [qd; qdd]; end %% 子函数7用于记录力矩的状态导数变体 function [dx, q_d_out, tau_out] state_with_torque(t, x, params) % 与state_derivative相同但额外返回期望轨迹和控制力矩用于记录 q x(1:2); qd x(3:4); [q_d, qd_d, qdd_d] desired_trajectory(t, params); F_ext external_force(t, params); [M, C, G] manipulator_dynamics(q, qd, params); J manipulator_jacobian(q, params); tau_ext J * F_ext; tau impedance_control_law(q, qd, q_d, qd_d, qdd_d, M, C, G, tau_ext, params); qdd M \ (tau tau_ext - C*qd - G); dx [qd; qdd]; q_d_out q_d; tau_out tau; end代码里有一个我在调试过程中加的小设计为了记录每一步的实际控制力矩我额外写了一个state_with_torque函数它和state_derivative几乎一样只是多返回了期望轨迹和控制力矩。实际上这个函数的计算量与RK4中的k1重复但代码可读性更好。如果你是想追求极致效率可以把k1计算时的tau值保存下来复用但教学版本这样写更容易理解。5. 仿真结果解读与实际效果5.1 无外力下的轨迹跟踪表现先看没有接触力的前1秒。期望轨迹从[0.5;0.8]平滑过渡到[1.4;1.0]注意我这里虽然用余弦规划但机械臂的实际响应不会立刻跟上期望值而是在前几毫秒内存在一个很小的滞后。这个滞后的大小由Md和Bd决定Md越大系统响应越慢误差峰值越大。用默认参数跑完关节1的跟踪误差峰值大概在0.05弧度左右稳态后误差趋近于零。关节2因为刚度是30比关节1的50小跟踪误差会稍大一点。刚度本质上决定了跟踪的紧度刚度越大同样的偏差会产生更大的纠正力矩所以跟踪越“紧”。但刚度不是越大越好原因在下一节说。轨迹规划用了1.5秒的过渡时间在0到1.5秒内期望速度不为零阻抗控制的跟踪误差主要集中在这段时间。1.5秒之后期望速度和加速度都为零系统进入纯PD调节阶段误差会快速衰减到接近零。如果看到稳态误差一直不收敛优先检查重力补偿项G(q)是否写对。5.2 加入末端接触力后的柔顺行为在1.0秒到1.3秒之间末端受到一个[5;-10]牛顿的接触力。如果你用同样的代码但把控制律换成纯位置跟踪机械臂会强力抵抗这个外力导致关节力矩瞬间飙升。而阻抗控制下机械臂会在受力方向上产生一个位置偏差偏差大小约等于外力等效的关节力矩除以刚度。比如关节1方向外力等效关节力矩大约是-10Nm量级Kd1是50所以位置偏差大约会到0.2弧度左右。这个偏差不是故障而是阻抗控制设计出来的“退让”。1.3秒后外力消失机械臂在弹簧力作用下会慢慢回到期望位置回程的快慢和是否振荡由阻尼决定。我在实际仿真中观察到一个很有说服力的画面外力作用期间关节角曲线出现一个明显的“小平台”代表着机械臂在接触力下保持了一个受力平衡位置外力撤掉后曲线平滑回到期望轨迹。这正是柔顺控制的核心价值既不像纯位置控制那样硬顶也不像纯力控制那样完全放弃位置。5.3 调整参数时容易观察到的现象如果在调参时把刚度Kd提高一倍到100和60最直观的变化是同样的外力下位置偏差几乎减半但控制力矩的峰值会明显增加并且系统可能在高频段出现轻微的振荡趋势。把阻尼Bd调小后外力撤除后的回弹会有明显的超调来回弹好几下才稳定这在实际机械臂上是很危险的现象可能导致末端工具碰撞工件。阻尼调大的效果则相反系统变得非常“沉稳”但响应速度变慢外力消失后需要更长的时间回到期望位置。从我个人的经验看阻抗参数的选择本质上就是在刚度和柔顺性之间寻找平衡不可能又不退让又不产生大力。工程上通常根据任务需求来定打磨抛光任务希望刚度低一些避免工具压坏工件而搬运刚性物体的任务希望刚度高一些保证轨迹精度。6. 调试中的常见问题与避坑记录6.1 常见问题速查表我把调试踩过的坑整理成一个速查表按现象查找原因会快很多。现象可能原因排查方法仿真直接发散积分步长过大或刚度Kd过大把dt降到0.0005试一次或将Kd缩小为原来的1/10跟踪存在稳态误差重力补偿G(q)缺失或公式写错检查重力项符号特别是joint1中q1q2的余弦项外力撤除后持续振荡阻尼Bd过小按B2sqrt(KdMd)补足阻尼控制力矩突然巨大期望轨迹加速度不连续检查轨迹函数尽量用带解析导数的平滑曲线关节2误差比关节1大很多两个方向的Kd不一致导致跟踪带宽不同根据负载需求单独调每个方向的刚度外力作用期间完全不退让控制律里减去了tau_ext本文还有配套的精品资源点击获取