机械臂MDH正解齐次变换推算过程及python示例
机械臂正解(MDH)推导过程及python示例
一、Modified DH 参数简介(Khalil-Breteler 版本)
Modified DH 参数(MDH)与标准 Denavit-Hartenberg 参数(SDH)不同,它的连杆坐标系是按照如下规则建立的:
- zi−1z_{i-1}zi−1 轴:沿第 i−1i-1i−1 个关节轴方向。
- xix_ixi 轴:沿从 zi−1z_{i-1}zi−1 到 ziz_izi 的公垂线方向。
- 原点:位于 xix_ixi 与 zi−1z_{i-1}zi−1 的交点。
- 参数定义如下:
| 参数 | 含义 |
|---|---|
| θi\theta_iθi | 绕 zi−1z_{i-1}zi−1 轴旋转,从 xi−1x_{i-1}xi−1 到 xix_ixi 的角度 |
| did_idi | 沿 zi−1z_{i-1}zi−1 轴从 xi−1x_{i-1}xi−1 到 xix_ixi 的平移 |
| aia_iai | 沿 xix_ixi 轴从 zi−1z_{i-1}zi−1 到 ziz_izi 的平移 |
| αi\alpha_iαi | 绕 xix_ixi 轴旋转,从 zi−1z_{i-1}zi−1 到 ziz_izi 的角度 |
二、MDH 变换的分解
MDH 的变换矩阵可以分解为如下四个基本变换步骤(按顺序):
-
绕 zi−1z_{i-1}zi−1 轴旋转 θi\theta_iθi
Rot(zi−1,θi) \text{Rot}(z_{i-1}, \theta_i) Rot(zi−1,θi) -
沿 zi−1z_{i-1}zi−1 轴平移 did_idi
Trans(zi−1,di) \text{Trans}(z_{i-1}, d_i) Trans(zi−1,di) -
绕 xix_ixi 轴旋转 αi\alpha_iαi
Rot(xi,αi) \text{Rot}(x_i, \alpha_i) Rot(xi,αi) -
沿 xix_ixi 轴平移 aia_iai
Trans(xi,ai) \text{Trans}(x_i, a_i) Trans(xi,ai)
注意:这里的顺序是 Khalil-Breteler 版本的 MDH 定义。
三、逐个写出变换矩阵
1. 绕 zi−1z_{i-1}zi−1 轴旋转 θi\theta_iθi
Rot(z,θ)=[cosθ−sinθ00sinθcosθ0000100001] \text{Rot}(z, \theta) = \begin{bmatrix} \cos\theta & -\sin\theta & 0 & 0 \\ \sin\theta & \cos\theta & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} Rot(z,θ)=cosθsinθ00−sinθcosθ0000100001
2. 沿 zi−1z_{i-1}zi−1 轴平移 did_idi
Trans(z,d)=[10000100001d0001] \text{Trans}(z, d) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & d \\ 0 & 0 & 0 & 1 \end{bmatrix} Trans(z,d)=10000100001000d1
3. 绕 xix_ixi 轴旋转 αi\alpha_iαi
Rot(x,α)=[10000cosα−sinα00sinαcosα00001] \text{Rot}(x, \alpha) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos\alpha & -\sin\alpha & 0 \\ 0 & \sin\alpha & \cos\alpha & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} Rot(x,α)=10000cosαsinα00−sinαcosα00001
4. 沿 xix_ixi 轴平移 aia_iai
Trans(x,a)=[100a010000100001] \text{Trans}(x, a) = \begin{bmatrix} 1 & 0 & 0 & a \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} Trans(x,a)=100001000010a001
四、矩阵乘法合成变换矩阵
将以上四个变换按顺序相乘:
Tii−1=Trans(x,a)⋅Rot(x,α)⋅Trans(z,d)⋅Rot(z,θ) T_i^{i-1} = \text{Trans}(x, a) \cdot \text{Rot}(x, \alpha) \cdot \text{Trans}(z, d) \cdot \text{Rot}(z, \theta) Tii−1=Trans(x,a)⋅Rot(x,α)⋅Trans(z,d)⋅Rot(z,θ)
逐个相乘:
步骤 1:先乘 Rot(z) 和 Trans(z)
T12=Trans(z,d)⋅Rot(z,θ)=[cosθ−sinθ00sinθcosθ00001d0001] T_{12} = \text{Trans}(z, d) \cdot \text{Rot}(z, \theta) = \begin{bmatrix} \cos\theta & -\sin\theta & 0 & 0 \\ \sin\theta & \cos\theta & 0 & 0 \\ 0 & 0 & 1 & d \\ 0 & 0 & 0 & 1 \end{bmatrix} T12=Trans(z,d)⋅Rot(z,θ)=cosθsinθ00−sinθcosθ00001000d1
步骤 2:乘 Rot(x, α)
T123=Rot(x,α)⋅T12=[cosθ−sinθ00sinθcosαcosθcosα−sinα−dsinαsinθsinαcosθsinαcosαdcosα0001] T_{123} = \text{Rot}(x, \alpha) \cdot T_{12} = \begin{bmatrix} \cos\theta & -\sin\theta & 0 & 0 \\ \sin\theta \cos\alpha & \cos\theta \cos\alpha & -\sin\alpha & -d \sin\alpha \\ \sin\theta \sin\alpha & \cos\theta \sin\alpha & \cos\alpha & d \cos\alpha \\ 0 & 0 & 0 & 1 \end{bmatrix} T123=Rot(x,α)⋅T12=cosθsinθcosαsinθsinα0−sinθcosθcosαcosθsinα00−sinαcosα00−dsinαdcosα1
步骤 3:乘 Trans(x, a)
Tii−1=Trans(x,a)⋅T123=[cosθ−sinθ0asinθcosαcosθcosα−sinα−dsinαsinθsinαcosθsinαcosαdcosα0001] T_i^{i-1} = \text{Trans}(x, a) \cdot T_{123} = \begin{bmatrix} \cos\theta & -\sin\theta & 0 & a \\ \sin\theta \cos\alpha & \cos\theta \cos\alpha & -\sin\alpha & -d \sin\alpha \\ \sin\theta \sin\alpha & \cos\theta \sin\alpha & \cos\alpha & d \cos\alpha \\ 0 & 0 & 0 & 1 \end{bmatrix} Tii−1=Trans(x,a)⋅T123=cosθsinθcosαsinθsinα0−sinθcosθcosαcosθsinα00−sinαcosα0a−dsinαdcosα1
五、最终 MDH 矩阵表达式
这就是你函数中返回的变换矩阵:
Tii−1=[cosθ−sinθ0asinθcosαcosθcosα−sinα−dsinαsinθsinαcosθsinαcosαdcosα0001] T_i^{i-1} = \begin{bmatrix} \cos\theta & -\sin\theta & 0 & a \\ \sin\theta \cos\alpha & \cos\theta \cos\alpha & -\sin\alpha & -d \sin\alpha \\ \sin\theta \sin\alpha & \cos\theta \sin\alpha & \cos\alpha & d \cos\alpha \\ 0 & 0 & 0 & 1 \end{bmatrix} Tii−1=cosθsinθcosαsinθsinα0−sinθcosθcosαcosθsinα00−sinαcosα0a−dsinαdcosα1
六、Python 实现
import numpy as np
from typing import List, Tuple, Optional
from dataclasses import dataclass
def mdh_matrix_khalil(alpha: float, a: float, d: float, theta: float) -> np.ndarray:
"""
计算 Khalil-Breteler 版本的 Modified DH 变换矩阵。
参数:
alpha: 扭转角 (弧度)
a: 连杆长度
d: 偏移量
theta: 关节角 (弧度)
返回:
T: 4x4 齐次变换矩阵
"""
ca, sa = np.cos(alpha), np.sin(alpha)
ct, st = np.cos(theta), np.sin(theta)
return np.array([
[ct, -st, 0, a ],
[st * ca, ct * ca, -sa, -sa * d ],
[st * sa, ct * sa, ca, ca * d ],
[0, 0, 0, 1 ]
], dtype=np.float64)
def forward_kinematics_mdh_khalil(
dh_params: List[Tuple[float, float, float, float]],
joint_angles: List[float]
) -> List[np.ndarray]:
"""
使用 Khalil 版本的 Modified DH 参数计算正向运动学。
返回所有中间关节的变换矩阵。
参数:
dh_params: 每个连杆的 MDH 参数列表 [(alpha, a, d, theta_offset), ...]
joint_angles: 各关节角度列表 [theta1, theta2, ...]
返回:
transforms: 每个关节相对于基坐标系的变换矩阵列表
"""
if len(dh_params) != len(joint_angles):
raise ValueError("DH 参数与关节角度数量不一致")
T = np.eye(4)
transforms = [T.copy()] # 初始为基坐标系 {0}
for i, (alpha, a, d, theta_offset) in enumerate(dh_params):
theta = theta_offset + joint_angles[i] # 添加关节角度
T_i = mdh_matrix_khalil(alpha, a, d, theta)
T = T @ T_i # 累乘变换矩阵
transforms.append(T)
return transforms
# ======================
# 示例部分
# ======================
if __name__ == "__main__":
np.set_printoptions(precision=4, suppress=True)
# # 示例 DH 参数(3自由度机械臂,MDH格式)
# dh_params = [
# (0, 0, 0, 0), # 连杆1
# (0, 1, 0, 0), # 连杆2
# (0, 1, 0, 0), # 连杆3
# (0, 1, 0, 0) # 连杆3
# ]
# # 关节角度输入(弧度值)
# joint_angles = [np.pi/2, np.pi/2, np.pi/2,-np.pi/2]
# 示例 DH 参数(3自由度机械臂,MDH格式)
dh_params = [
(0, 0, 265, 0), # 连杆1
(-np.pi/2, 0, 0, 0), # 连杆2
(0, 444, 0, 0) # 连杆3
# (-np.pi/2, 110, 470, 0) # 连杆3
]
# 关节角度输入(弧度值)
joint_angles = [0, -np.pi/2, 0]
# 计算所有关节的变换矩阵
transforms = forward_kinematics_mdh_khalil(dh_params, joint_angles)
# 提取末端执行器(最后一个关节)的变换矩阵
T_end_effector = transforms[-1]
# 提取位置和姿态
position = T_end_effector[:3, 3]
x, y, z = position
rotation_matrix = T_end_effector[:3, :3]
print("末端执行器在基坐标系 x0y0z0 下的位姿:")
print(f"\n位置 (x, y, z): x={x:.4f}, y={y:.4f}, z={z:.4f}")
print("\n姿态(旋转矩阵 R):")
print(rotation_matrix)
注意:dh_params 为MDH的参数,joint_angles为各个关节的角度(弧度)。
更多推荐



所有评论(0)