1. 单自由度阻抗控制基础

任务目标

实现单自由度质量-弹簧-阻尼系统的阻抗控制,使机器人末端呈现期望的刚度和阻尼特性。给定期望位置轨迹,控制器根据接触力偏差调整实际运动,使系统动态行为等效于期望的阻抗模型。

阻抗控制原理

单自由度阻抗控制的目标是让机器人末端呈现期望的动力学特性:

M_d·(ẍ - ẍ_d) + B_d·(ẋ - ẋ_d) + K_d·(x - x_d) = F_ext

其中M_d、B_d、K_d分别为期望惯量、阻尼和刚度,x_d为期望位置,F_ext为环境接触力。当F_ext=0时,系统跟踪期望轨迹;当存在接触力时,位置偏差与力满足上述阻抗关系。

控制律推导

对于单自由度系统,若实际动力学为M·ẍ = F_act + F_ext,则阻抗控制律为:

F_act = M·ẍ_d + M·M_d⁻¹·(B_d·(ẋ_d - ẋ) + K_d·(x_d - x) - F_ext) - F_ext

当M_d = M时简化为:

F_act = M·ẍ_d + B_d·(ẋ_d - ẋ) + K_d·(x_d - x) - F_ext

关键完整代码

import numpy as np
import matplotlib.pyplot as plt

class ImpedanceControl1DOF:
    """单自由度阻抗控制器仿真"""
    def __init__(self, M=1.0, B_d=20.0, K_d=100.0, dt=0.001):
        self.M = M          # 实际质量
        self.B_d = B_d      # 期望阻尼
        self.K_d = K_d      # 期望刚度
        self.dt = dt
        
    def control(self, x, x_dot, x_d, xd_dot, xdd_dot, F_ext):
        """计算控制力"""
        # 阻抗控制律(M_d = M)
        F_act = self.M * xdd_dot + self.B_d * (xd_dot - x_dot) \
                + self.K_d * (x_d - x) - F_ext
        return F_act
    
    def simulate(self, x0=0.0, xd0=0.0, duration=2.0, 
                 x_d_func=None, F_ext_func=None):
        """仿真主循环"""
        dt = self.dt
        n_steps = int(duration / dt)
        
        # 状态初始化
        x = x0
        x_dot = xd0
        
        # 记录轨迹
        t_arr = np.arange(0, duration, dt)
        x_arr = np.zeros(n_steps)
        x_d_arr = np.zeros(n_steps)
        F_ext_arr = np.zeros(n_steps)
        F_act_arr = np.zeros(n_steps)
        
        for i in range(n_steps):
            t = t_arr[i]
            
            # 期望轨迹(默认阶跃到0.1m)
            if x_d_func is None:
                x_d = 0.1 if t >= 0.1 else 0.0
                xd_dot = 0.0
                xdd_dot = 0.0
            else:
                x_d, xd_dot, xdd_dot = x_d_func(t)
            
            # 环境接触力(默认无接触)
            if F_ext_func is None:
                F_ext = 0.0
            else:
                F_ext = F_ext_func(t, x)
            
            # 计算控制力
            F_act = self.control(x, x_dot, x_d, xd_dot, xdd_dot, F_ext)
            
            # 更新状态(实际动力学:M·ẍ = F_act + F_ext)
            xdd = (F_act + F_ext) / self.M
            x_dot += xdd * dt
            x += x_dot * dt
            
            # 记录
            x_arr[i] = x
            x_d_arr[i] = x_d
            F_ext_arr[i] = F_ext
            F_act_arr[i] = F_act
        
        return t_arr, x_arr, x_d_arr, F_ext_arr, F_act_arr

# ===== 仿真验证 =====
if __name__ == "__main__":
    # 创建控制器
    controller = ImpedanceControl1DOF(M=1.0, B_d=20.0, K_d=100.0, dt=0.001)
    
    # 场景1:自由空间阶跃跟踪(无接触力)
    t1, x1, xd1, F1, Fa1 = controller.simulate(duration=2.0)
    
    # 场景2:接触刚性墙壁(x=0.08m处)
    def wall_force(t, x):
        k_wall = 10000.0
        return k_wall * (x - 0.08) if x > 0.08 else 0.0
    
    t2, x2, xd2, F2, Fa2 = controller.simulate(duration=2.0, F_ext_func=wall_force)
    
    # 绘制结果
    fig, axes = plt.subplots(2, 2, figsize=(12, 8))
    
    # 场景1:位置跟踪
    axes[0,0].plot(t1, xd1, 'r--', label='期望位置')
    axes[0,0].plot(t1, x1, 'b-', label='实际位置')
    axes[0,0].set_xlabel('时间 (s)')
    axes[0,0].set_ylabel('位置 (m)')
    axes[0,0].set_title('自由空间阶跃跟踪')
    axes[0,0].legend()
    axes[0,0].grid(True)
    
    # 场景1:控制力
    axes[0,1].plot(t1, Fa1, 'g-')
    axes[0,1].set_xlabel('时间 (s)')
    axes[0,1].set_ylabel('控制力 (N)')
    axes[0,1].set_title('自由空间控制力')
    axes[0,1].grid(True)
    
    # 场景2:位置跟踪(含接触)
    axes[1,0].plot(t2, xd2, 'r--', label='期望位置')
    axes[1,0].plot(t2, x2, 'b-', label='实际位置')
    axes[1,0].axhline(y=0.08, color='k', linestyle=':', label='墙壁位置')
    axes[1,0].set_xlabel('时间 (s)')
    axes[1,0].set_ylabel('位置 (m)')
    axes[1,0].set_title('接触刚性墙壁')
    axes[1,0].legend()
    axes[1,0].grid(True)
    
    # 场景2:接触力
    axes[1,1].plot(t2, F2, 'm-')
    axes[1,1].set_xlabel('时间 (s)')
    axes[1,1].set_ylabel('接触力 (N)')
    axes[1,1].set_title('环境接触力')
    axes[1,1].grid(True)
    
    plt.tight_layout()
    plt.show()
    
    # 输出稳态误差
    idx_ss = int(1.5 / controller.dt)  # 1.5s后视为稳态
    err_free = abs(x1[-1] - xd1[-1])
    err_contact = abs(x2[-1] - xd2[-1])
    print(f"自由空间稳态误差: {err_free:.6f} m")
    print(f"接触墙壁稳态位置: {x2[-1]:.6f} m (期望0.1m)")
    print(f"接触力稳态值: {F2[-1]:.2f} N")

运行方式

pip install numpy matplotlib
python impedance_control_1dof.py

验证方法与判定标准

场景1(自由空间):期望位置从0阶跃到0.1m,实际位置应平滑跟踪,无超调或少量超调后收敛。稳态误差应趋近于0(由于纯刚性控制,理论上稳态误差为0)。

场景2(接触墙壁):墙壁位于x=0.08m处,期望位置仍为0.1m。由于墙壁限制,实际位置应稳定在0.08m附近,接触力稳态值应满足:

F_ext = K_d × (x_d - x) = 100 × (0.1 - 0.08) = 2.0 N

即接触力稳态值应约为2.0N,验证阻抗关系F = K_d·Δx成立。

通过条件:场景1稳态误差小于0.001m;场景2稳态位置在0.08±0.001m范围内,接触力在2.0±0.1N范围内。

关键参数说明

  • K_d(期望刚度):决定位置偏差与接触力的比例关系,K_d越大,相同力产生的变形越小
  • B_d(期望阻尼):决定系统收敛速度和超调量,B_d过小会导致振荡
  • M_d(期望惯量):本实现中取M_d=M,简化控制律;若M_d≠M需使用完整控制律