腿部与步态 第2课/共30课

🤖 腿机构学

理解四足机器人腿部连杆的运动学原理

🔧 腿部机构概述

四足机器人的腿部机构是其运动能力的基础。最常见的设计是2连杆串联机构(大腿+小腿),由髋关节和膝关节驱动。这种结构简单、可靠,且运动学计算方便。

典型的3-DOF腿配置:

📐 正向运动学

正向运动学(Forward Kinematics, FK)解决的问题是:已知关节角度,求足端位置。

对于2连杆平面机构(忽略Hip Roll):

x = L1·sin(θ1) + L2·sin(θ1 + θ2)
z = -(L1·cos(θ1) + L2·cos(θ1 + θ2))

其中:

🔄 逆向运动学

逆向运动学(Inverse Kinematics, IK)是更常用的方向:已知期望足端位置,求关节角度。

使用余弦定理求解:

cos(θ2) = (x² + z² - L1² - L2²) / (2·L1·L2)
θ2 = arccos(cos θ2)
θ1 = atan2(x, -z) - atan2(L2·sin θ2, L1 + L2·cos θ2)
⚠️ 多解问题:IK通常有两组解(肘上/肘下构型)。四足机器人一般选择"膝向前弯"构型(θ2 > 0),因为这更符合生物力学。

📊 雅可比矩阵

雅可比矩阵描述关节速度到足端速度的映射:

[x_dot] [dx/dth1 dx/dth2] [th1_dot]
[z_dot] = [dz/dth1 dz/dth2] [th2_dot]

det(J) = 0 时,机构处于奇异位形,失去某个方向的运动能力。在实际控制中必须避免奇异位形。

🎯 工作空间

工作空间是足端可以到达的所有位置集合。对于2连杆机构:

🧮 仿真:腿部运动学

以下代码实现了腿部正/逆运动学、雅可比矩阵和工作空间分析:

import math class LegMechanism: def __init__(self, L1=0.15, L2=0.15, hip_offset=0.04): self.L1 = L1 self.L2 = L2 self.hip_offset = hip_offset def forward_kinematics(self, theta1, theta2): x = self.L1 * math.sin(theta1) + self.L2 * math.sin(theta1 + theta2) z = -(self.L1 * math.cos(theta1) + self.L2 * math.cos(theta1 + theta2)) return x, z def inverse_kinematics(self, x, z): d = math.sqrt(x**2 + z**2) if d > self.L1 + self.L2: d = self.L1 + self.L2 - 0.001 if d < abs(self.L1 - self.L2): d = abs(self.L1 - self.L2) + 0.001 cos_theta2 = (d**2 - self.L1**2 - self.L2**2) / (2 * self.L1 * self.L2) cos_theta2 = max(-1, min(1, cos_theta2)) theta2 = math.acos(cos_theta2) alpha = math.atan2(x, -z) beta = math.atan2(self.L2 * math.sin(theta2), self.L1 + self.L2 * math.cos(theta2)) theta1 = alpha - beta return theta1, theta2 def jacobian(self, theta1, theta2): j11 = self.L1 * math.cos(theta1) + self.L2 * math.cos(theta1 + theta2) j12 = self.L2 * math.cos(theta1 + theta2) j21 = self.L1 * math.sin(theta1) + self.L2 * math.sin(theta1 + theta2) j22 = self.L2 * math.sin(theta1 + theta2) return [[j11, j12], [j21, j22]] def workspace_analysis(self, n_samples=360): points = [] for i in range(n_samples): theta1 = math.radians(-90 + 180 * i / n_samples) for j in range(n_samples): theta2 = math.radians(180 * j / n_samples) x, z = self.forward_kinematics(theta1, theta2) if z < 0: points.append((x, z)) xs = [p[0] for p in points] zs = [p[1] for p in points] return { 'x_range': (min(xs), max(xs)), 'z_range': (min(zs), max(zs)), 'area_approx': (max(xs)-min(xs)) * abs(min(zs)-max(zs)), 'n_points': len(points) } leg = LegMechanism(L1=0.15, L2=0.15) print("=" * 55) print(" 腿机构学仿真") print("=" * 55) print(f" 大腿长度 L1 = {leg.L1} m") print(f" 小腿长度 L2 = {leg.L2} m") print() print(" 【正运动学测试】") test_angles = [ (0, 0), (0.3, 0.5), (-0.3, 0.8), (0.5, 1.2), (math.pi/4, math.pi/3), ] for t1, t2 in test_angles: x, z = leg.forward_kinematics(t1, t2) print(f" th1={t1:.2f}, th2={t2:.2f} -> foot({x:.4f}, {z:.4f}) m") print() print(" 【逆运动学验证(FK->IK->FK闭环)】") for t1, t2 in test_angles: x, z = leg.forward_kinematics(t1, t2) t1_r, t2_r = leg.inverse_kinematics(x, z) x_r, z_r = leg.forward_kinematics(t1_r, t2_r) err = math.sqrt((x-x_r)**2 + (z-z_r)**2) ok = "OK" if err < 1e-6 else "FAIL" print(f" ({t1:.2f},{t2:.2f}) -> IK -> ({t1_r:.4f},{t2_r:.4f}) err={err:.6f}m [{ok}]") print() print(" 【雅可比矩阵分析】") t1, t2 = 0.0, 0.5 J = leg.jacobian(t1, t2) det_J = J[0][0]*J[1][1] - J[0][1]*J[1][0] print(f" th1={t1:.2f}, th2={t2:.2f}") print(f" J = [[{J[0][0]:.4f}, {J[0][1]:.4f}],") print(f" [{J[1][0]:.4f}, {J[1][1]:.4f}]]") print(f" det(J) = {det_J:.4f}") sing = "non-singular" if abs(det_J) > 0.001 else "NEAR SINGULAR" print(f" status: {sing}") print() print(" 【工作空间分析】") ws = leg.workspace_analysis() print(f" X range: [{ws['x_range'][0]:.3f}, {ws['x_range'][1]:.3f}] m") print(f" Z range: [{ws['z_range'][0]:.3f}, {ws['z_range'][1]:.3f}] m") print(f" Approx area: {ws['area_approx']*1e4:.1f} cm^2") print() print(" OK - Leg mechanism simulation complete, FK/IK loopback verified")

仿真结果:

======================================================= 腿机构学仿真 ======================================================= 大腿长度 L1 = 0.15 m 小腿长度 L2 = 0.15 m 【正运动学测试】 th1=0.00, th2=0.00 -> foot(0.0000, -0.3000) m th1=0.30, th2=0.50 -> foot(0.1519, -0.2478) m th1=-0.30, th2=0.80 -> foot(0.0276, -0.2749) m th1=0.50, th2=1.20 -> foot(0.2207, -0.1123) m th1=0.79, th2=1.05 -> foot(0.2510, -0.0672) m 【逆运动学验证(FK->IK->FK闭环)】 (0.00,0.00) -> IK -> (0.0000,0.0000) err=0.000000m [OK] (0.30,0.50) -> IK -> (0.3000,0.5000) err=0.000000m [OK] (-0.30,0.80) -> IK -> (-0.3000,0.8000) err=0.000000m [OK] (0.50,1.20) -> IK -> (0.5000,1.2000) err=0.000000m [OK] (0.79,1.05) -> IK -> (0.7854,1.0472) err=0.000000m [OK] 【雅可比矩阵分析】 th1=0.00, th2=0.50 J = [[0.2816, 0.1316], [0.0719, 0.0719]] det(J) = 0.0108 status: non-singular 【工作空间分析】 X range: [-0.300, 0.300] m Z range: [-0.300, -0.000] m Approx area: 1800.0 cm^2 OK - Leg mechanism simulation complete, FK/IK loopback verified

💻 力矩-力映射

雅可比矩阵还建立了关节力矩和足端力的关系:

F = J-T · τ

这是力控的基础:通过控制关节力矩来产生期望的足端力。在支撑相中,我们需要精确控制足端力来维持平衡和推进。

📝 练习

  1. 验证FK-IK闭环:用任意关节角计算足端位置,再用IK反算,检查误差是否<1e-6。
  2. 画出L1=0.15, L2=0.10时的工作空间边界,与等腿长情况比较。
  3. 计算θ1=0, θ2=0时的雅可比矩阵,解释为什么这个位形是奇异的。
  4. 当足端施加100N竖直力时,计算不同膝关节角度下的关节力矩。
  5. 设计腿长比例使工作空间面积最大(提示:L1/L2=?时最优)。

🔧 力矩-力映射详解

雅可比矩阵不仅建立速度映射,还建立力矩-力映射。这在力控中至关重要:

τ = JT · F
F = J-T · τ

物理含义:当足端施加力F时,关节需要提供的力矩为 τ = JTF。反之,给定关节力矩,足端产生的力为 F = J-Tτ。

实例计算

当机器人站立时,足端承受竖直重力。计算各关节力矩:

📊 奇异位形分析

奇异位形是机器人运动学的"死角",必须避免:

伸直奇异(Leg Fully Extended)

当 θ2 = 0 时,腿完全伸直,det(J) = 0。此时无法产生径向力,只能产生切向力。

折叠奇异(Leg Fully Folded)

当 θ2 = π 时,腿完全折叠,det(J) = 0。机构退化。

避免策略

💡 腿部设计优化

腿长比例 L1/L2 影响多个性能指标:

比例工作空间力矩需求推荐场景
L1/L2 = 0.8偏小膝关节力矩低重载
L1/L2 = 1.0最大均衡通用(推荐)
L1/L2 = 1.2偏大髋关节力矩低快速运动

大多数四足机器人选择 L1 = L2,因为等长配置工作空间最大,且关节力矩分配均衡。

🏆
运动学大师

掌握腿部正/逆运动学、雅可比矩阵和工作空间分析

四足机器人课程 · 第2课/30 · 返回目录