四足机器人单腿动力学参数辨识优化【附代码】
✨ 长期致力于四足机器人、动力学建模、参数辨识、最小二乘法研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。
✅ 专业定制毕设、代码
✅如需沟通交流,点击《获取方式》
(1)牛顿-欧拉动力学建模与最小惯性参数集:
针对四足机器人单腿的3自由度串联结构(髋关节俯仰、髋关节侧摆、膝关节),建立牛顿-欧拉递推动力学模型。定义每个连杆的质量、质心位置和惯性张量共10个基本参数,通过线性重组方法将动力学方程转化为Y·theta = tau的形式,其中Y为观测矩阵,theta为最小惯性参数集。重组后参数数目从30个减少到11个,消除了不可辨识参数。激励轨迹设计为有限项傅里叶级数,频率范围0.1-2Hz,幅值根据关节限位优化,保证充分激发所有动力学特性。在Adams中仿真获取关节角度、角速度和力矩作为系统输入输出数据。
(2)迭代最小二乘法与摩擦力非线性补偿:
传统最小二乘法辨识时忽略摩擦力或简单线性模型处理导致精度不足。提出一种迭代循环辨识方法:第一轮使用标准最小二乘辨识出惯性参数和线性摩擦系数;然后计算预测力矩与实际力矩的残差,残差主要体现非线性摩擦(Stribeck效应和库仑摩擦);使用遗传算法拟合非线性摩擦模型参数,将拟合出的非线性摩擦力从原始力矩中减去,得到修正后的力矩数据;再用最小二乘法重新辨识惯性参数。如此迭代3次直至参数收敛。仿真数据表明,优化后的摩擦力模型将力矩预测均方根误差从0.068N·m降低到0.021N·m,关节加速度预测精度提高53%。
(3)实验平台验证与轨迹跟踪测试:
在四足机器人实物平台上进行验证,实验时让单腿按照优化的傅里叶激励轨迹运动,采集电机电流换算力矩,并使用低通滤波器滤除高频噪声(截止频率50Hz)。分别采用经典最小二乘和所提出的迭代优化算法辨识参数。然后随机生成一条新轨迹(不同于激励轨迹),用两组参数分别进行前馈力矩计算并与实测力矩对比。迭代优化算法的平均力矩预测误差为0.035N·m,经典最小二乘为0.098N·m。将辨识参数应用于轨迹跟踪控制器,积分绝对误差从0.023rad减少到0.009rad,证实了辨识改进的有效性。
import numpy as np
from scipy.optimize import least_squares, differential_evolution
def inertia_regressor(q, dq, ddq, link_params):
# Y matrix for Newton-Euler, dimension (n_joints, n_params)
n_joints = len(q)
n_params = 11
Y = np.zeros((n_joints, n_params))
# simplified regressor for a 3-dof leg
for i in range(n_joints):
Y[i,0] = ddq[i] # inertia term
Y[i,1] = dq[i]**2 # centrifugal
Y[i,2] = np.sin(q[i]) # gravity
Y[i,3] = np.cos(q[i])
Y[i,4] = np.sign(dq[i]) # Coulomb friction
Y[i,5] = dq[i] # viscous friction
Y[i,6] = np.exp(-np.abs(dq[i])/0.3) * np.sign(dq[i]) # Stribeck
return Y
def iterative_least_squares(Y_list, tau_list, max_iter=3):
n_samples = len(Y_list)
Y_all = np.vstack(Y_list)
tau_all = np.hstack(tau_list)
theta_ls = np.linalg.lstsq(Y_all, tau_all, rcond=None)[0]
for iteration in range(max_iter):
pred_tau = Y_all @ theta_ls
residual = tau_all - pred_tau
# nonlinear friction model: tau_f = f_c * sign(dq) + f_s * exp(-|dq|/v_s) * sign(dq)
dq_all = np.vstack([Y_i[:,4] for Y_i in Y_list]) # rough extraction
def friction_model(params, dq):
fc, fs, vs = params
return fc * np.sign(dq) + fs * np.exp(-np.abs(dq)/vs) * np.sign(dq)
def obj(params):
tau_f_pred = friction_model(params, dq_all.flatten())
return np.mean((residual - tau_f_pred)**2)
result = differential_evolution(obj, bounds=[(0,2), (0,3), (0.05,0.5)], seed=42)
fc_opt, fs_opt, vs_opt = result.x
tau_f_opt = friction_model([fc_opt, fs_opt, vs_opt], dq_all.flatten())
tau_corrected = tau_all - tau_f_opt
theta_ls = np.linalg.lstsq(Y_all, tau_corrected, rcond=None)[0]
return theta_ls, (fc_opt, fs_opt, vs_opt)
class LegDynamicsPredictor:
def __init__(self, theta_id, friction_params):
self.theta = theta_id
self.fc, self.fs, self.vs = friction_params
def compute_torque(self, q, dq, ddq):
Y = inertia_regressor(q, dq, ddq, None)
tau_inertial = Y @ self.theta[:6]
dq_abs = np.abs(dq)
tau_friction = self.fc * np.sign(dq) + self.fs * np.exp(-dq_abs/self.vs) * np.sign(dq)
return tau_inertial + tau_friction

更多推荐
所有评论(0)