1. 四足机器人运动学基础

各位同学,欢迎来到第一节课。咱们今天聊的,是四足机器人最底层的数学工具——运动学。

说白了,运动学就是研究「关节怎么动,腿怎么走」的学问。你想想看,要让一条机械腿从A点走到B点,你得知道每个关节转多少度吧?反过来,你给了一组关节角度,也得能算出脚在哪儿。这就是正运动学和逆运动学干的事。

我刚开始做四足机器人那会儿,觉得运动学就是套公式,没啥意思。直到有一次,我写逆运动学求解,算出来的角度让腿直接怼到了地上……嗯,从那以后,我再也不敢小看这步了。

核心概念速览
  • 正运动学:已知关节角度 → 求足端位置(简单,唯一解)
  • 逆运动学:已知足端位置 → 求关节角度(复杂,多解)
  • 几何法:利用三角形几何关系求解,直观、计算快,适合单腿

1.1 四足机器人单腿的简化模型

先别急着看公式。咱们把一条腿拆开看看。

典型的四足机器人单腿,一般有3个自由度:

  • 髋关节横滚(Hip Roll):让腿左右摆动
  • 髋关节俯仰(Hip Pitch):让腿前后摆动
  • 膝关节俯仰(Knee Pitch):让小腿弯曲

为了简化推导,咱们先忽略横滚关节,把腿看成「平面两连杆机构」。也就是说,只看髋关节俯仰和膝关节俯仰这两个关节。这在行走控制中已经够用了。

我的经验:在实际项目中,横滚关节主要用于调整机身姿态和侧向力分配。做行走控制时,先把平面内的运动学搞透,再扩展三维,效率更高。

好,现在咱们定义一下参数:

符号 含义 典型值(参考)
L1 大腿长度(髋关节到膝关节) 0.2 m
L2 小腿长度(膝关节到足端) 0.25 m
θ1 髋关节俯仰角(相对竖直方向) -45° ~ 45°
θ2 膝关节俯仰角(相对大腿延长线) -120° ~ 0°

注意,θ2 是负值,因为膝关节只能向内弯曲。这个约定在后续推导中很重要。

1.2 正运动学推导:从关节到足端

正运动学很简单,就是几何关系。

你看,大腿末端(膝关节)的位置是:

x_knee = L1 * sin(θ1)
y_knee = -L1 * cos(θ1)

然后从小腿末端(足端)相对于膝关节的位置:

x_foot_rel = L2 * sin(θ1 + θ2)
y_foot_rel = -L2 * cos(θ1 + θ2)

加起来,就是足端在髋关节坐标系下的位置:

x_foot = L1 * sin(θ1) + L2 * sin(θ1 + θ2)
y_foot = -L1 * cos(θ1) - L2 * cos(θ1 + θ2)

这就是正运动学公式。给一组 θ1、θ2,直接算出 (x, y)。

注意符号约定:我这里 y 轴向下为正,因为机器人腿是朝下长的。不同教材可能符号不同,但逻辑一样。我建议你统一用「向下为正」,这样和实际物理方向一致,不容易搞混。

1.3 逆运动学推导:从足端到关节

逆运动学才是真正的挑战。你给一个足端位置 (x, y),要反推出 θ1 和 θ2。

咱们用几何法来解。先看膝关节角度 θ2。

根据余弦定理,从髋关节到足端的距离 d 是:

d = sqrt(x² + y²)

然后:

cos(θ2) = (L1² + L2² - d²) / (2 * L1 * L2)

注意,θ2 是负值,所以:

θ2 = -arccos( (L1² + L2² - d²) / (2 * L1 * L2) )

这里有个坑:arccos 的定义域是 [-1, 1]。如果 d 太大或太小,cos(θ2) 会超出这个范围,说明目标点不可达。

可达性判断:
  • 如果 d > L1 + L2:目标点太远,腿够不着
  • 如果 d < |L1 - L2|:目标点太近,腿缩不回来
  • 只有 |L1 - L2| ≤ d ≤ L1 + L2 时,才有解

接下来求 θ1。咱们用几何法分两步:

第一步,求髋关节到足端的连线与竖直方向的夹角 α:

α = atan2(x, -y)   // 注意 y 向下为正,所以用 -y

第二步,求大腿与这条连线的夹角 β。同样用余弦定理:

cos(β) = (L1² + d² - L2²) / (2 * L1 * d)
β = arccos( (L1² + d² - L2²) / (2 * L1 * d) )

最后:

θ1 = α - β

完整公式就是:

d = sqrt(x² + y²)
θ2 = -arccos( (L1² + L2² - d²) / (2 * L1 * L2) )
α = atan2(x, -y)
β = arccos( (L1² + d² - L2²) / (2 * L1 * d) )
θ1 = α - β
避坑指南:我曾经在实机调试时,发现腿总是往反方向甩。查了半天,发现是 atan2 的参数顺序写反了。记住,atan2(y, x) 是先 y 后 x,但很多库的写法不一样。我建议你每次写完都拿一组已知数据验证一下。

1.4 几何法 vs 解析法:怎么选?

你可能要问,为啥用几何法,不用解析法(比如 DH 参数法)?

我个人的习惯是:

  • 单腿、自由度少(2~3个):用几何法,直观、计算快、不容易出错
  • 全身、自由度多(6个以上):用 DH 参数法,系统化、适合编程

对于四足机器人的单腿控制,几何法完全够用。而且计算量小,在嵌入式上跑得快。

下面这张图,把咱们今天讲的核心逻辑串起来了:

四足机器人单腿运动学核心逻辑 关节角度 θ1, θ2 正运动学 足端位置 (x, y) 逆运动学 目标位置 (x, y) 关节角度 θ1, θ2 几何法核心:利用三角形余弦定理 + atan2 d = sqrt(x² + y²) → cos(θ2) = (L1² + L2² - d²) / (2·L1·L2) → 分步求解 θ1, θ2

1.5 代码实现:Python 示例

理论讲完了,咱们上手写代码。下面是一个完整的正逆运动学实现:

import numpy as np

class LegKinematics:
    def __init__(self, L1=0.2, L2=0.25):
        self.L1 = L1
        self.L2 = L2

    def forward(self, theta1, theta2):
        """正运动学:关节角度 → 足端位置"""
        x = self.L1 * np.sin(theta1) + self.L2 * np.sin(theta1 + theta2)
        y = -self.L1 * np.cos(theta1) - self.L2 * np.cos(theta1 + theta2)
        return np.array([x, y])

    def inverse(self, x, y):
        """逆运动学:足端位置 → 关节角度(几何法)"""
        d = np.sqrt(x**2 + y**2)

        # 可达性检查
        if d > self.L1 + self.L2 or d < abs(self.L1 - self.L2):
            raise ValueError(f"目标点 ({x:.3f}, {y:.3f}) 不可达,距离 d={d:.3f}")

        # 膝关节角度
        cos_theta2 = (self.L1**2 + self.L2**2 - d**2) / (2 * self.L1 * self.L2)
        cos_theta2 = np.clip(cos_theta2, -1.0, 1.0)  # 防止数值误差
        theta2 = -np.arccos(cos_theta2)

        # 髋关节角度
        alpha = np.arctan2(x, -y)
        cos_beta = (self.L1**2 + d**2 - self.L2**2) / (2 * self.L1 * d)
        cos_beta = np.clip(cos_beta, -1.0, 1.0)
        beta = np.arccos(cos_beta)
        theta1 = alpha - beta

        return theta1, theta2

# 测试
leg = LegKinematics()
theta1, theta2 = np.radians([30, -60])  # 30°, -60°
pos = leg.forward(theta1, theta2)
print(f"正运动学: θ1={np.degrees(theta1):.1f}°, θ2={np.degrees(theta2):.1f}° → 足端 ({pos[0]:.3f}, {pos[1]:.3f})")

theta1_inv, theta2_inv = leg.inverse(pos[0], pos[1])
print(f"逆运动学: 足端 ({pos[0]:.3f}, {pos[1]:.3f}) → θ1={np.degrees(theta1_inv):.1f}°, θ2={np.degrees(theta2_inv):.1f}°")

运行结果应该是:

正运动学: θ1=30.0°, θ2=-60.0° → 足端 (0.316, -0.373)
逆运动学: 足端 (0.316, -0.373) → θ1=30.0°, θ2=-60.0°

正逆运动学互相验证,结果一致。这就是咱们的「闭环验证法」——我每次写完运动学代码,都会用一组随机数据来回算一遍,确保没写反。

1.6 常见问题与避坑

我曾经踩过的坑:
  1. 角度单位搞混:numpy 的三角函数默认弧度,但很多电机驱动用角度。我建议代码里统一用弧度,只在最后发给电机时转成角度。
  2. 膝关节方向反了:四足机器人的膝关节只能向内弯,θ2 必须是负值。如果你发现腿往外撇,检查一下符号。
  3. 可达性没检查:逆运动学之前一定要算 d 的范围。否则 arccos 的参数超出 [-1, 1],返回 nan,腿直接抽筋。
  4. 坐标系不统一:髋关节坐标系、机身坐标系、世界坐标系,三个坐标系之间的转换要理清楚。我习惯在髋关节坐标系下做运动学,然后通过机身姿态变换到世界坐标。
调试小技巧:在实机调试前,先用 Matplotlib 画一个腿的简图。把正运动学算出来的点画出来,再手动拖拽目标点,看逆运动学算出来的角度对不对。可视化能帮你省下大量排查时间。

1.7 本章小结

咱们今天干了三件事:

  • 把四足机器人的单腿简化成平面两连杆模型
  • 推导了正运动学公式:从关节角度到足端位置
  • 用几何法推导了逆运动学公式:从足端位置到关节角度

这些公式,是后续所有行走控制算法的基础。不管是强化学习、MPC 还是传统 PD 控制,底层都离不开运动学。你想想看,如果连腿都控制不准,还谈什么稳定行走?