用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/JohnNuwan/EVA_CORE --skill robot-kinematics命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Concevoir et maintenir un watchdog auto-correcteur pour services HTTP — checks de santé, auto-restart, état persistant, rapports et pièges bash.
Serveur de messagerie sécurisé auto-hébergé (Signal-like) avec Flask + WebSocket + AES-256-GCM + pont EVA
ADAM-SENTINEL — Veilleur technologique 24h/24h. Scanne 10 domaines, cree des rapports, met a jour les skills, alerte sur les CVE et breaking changes.
基于 SOC 职业分类
正在显示 SKILL.md
| name | robot-kinematics |
| description | Cinématique des robots — paramètres DH, forward/inverse kinematics, Jacobien, singularités, workspace |
Quand l'utilisateur demande de calculer la cinématique directe/inverse, de modéliser un bras robotique, de paramétrer DH, d'analyser les singularités, ou de générer un espace de travail.
Paramètres pour chaque joint i :
θ_i : angle autour de l'axe z_{i-1}
d_i : translation le long de z_{i-1}
a_i : translation le long de x_i
α_i : angle autour de x_i
Matrice de transformation homogène T_i^{i-1} :
T = | cosθ -sinθ·cosα sinθ·sinα a·cosθ |
| sinθ cosθ·cosα -cosθ·sinα a·sinθ |
| 0 sinα cosα d |
| 0 0 0 1 |
Paramètres :
α_{i-1} : angle autour de x_{i-1}
a_{i-1} : translation le long de x_{i-1}
θ_i : angle autour de z_i
d_i : translation le long de z_i
Calcul séquentiel des matrices homogènes du repère base au repère effecteur.
import numpy as np
def dh_transform(theta, d, a, alpha):
"""Matrice de transformation DH standard (Craig)"""
ct, st = np.cos(theta), np.sin(theta)
ca, sa = np.cos(alpha), np.sin(alpha)
return np.array([
[ct, -st*ca, st*sa, a*ct],
[st, ct*ca, -ct*sa, a*st],
[0, sa, ca, d ],
[0, 0, 0, 1 ]
])
def forward_kinematics(joint_angles, dh_params):
"""
dh_params : liste de tuples (theta_offset, d, a, alpha, joint_type)
joint_angles : configuration angulaire des joints
"""
T = np.eye(4)
for i, (theta_off, d, a, alpha, jtype) in enumerate(dh_params):
theta = joint_angles[i] + theta_off
Ti = dh_transform(theta, d, a, alpha)
T = T @ Ti
return T # T^0_n : pose de l'effecteur dans le repère base
# Exemple : robot 6-DOF type Fanuc/KUKA
DH_FANUC = [
(0, 0.3425, 0.075, -np.pi/2, 'R'), # J1
(np.pi/2, 0, 0.300, 0, 'R'), # J2
(0, 0, 0.075, -np.pi/2, 'R'), # J3
(0, 0.320, 0, np.pi/2, 'R'), # J4
(0, 0, 0, -np.pi/2, 'R'), # J5
(0, 0.080, 0, 0, 'R') # J6
]
# Cinématique directe
angles = np.array([0.0, -1.57, 1.57, 0.0, 0.0, 0.0])
T_ee = forward_kinematics(angles, DH_FANUC)
position = T_ee[:3, 3]
rotation = T_ee[:3, :3] # matrice de rotation
Problème : trouver q (angles joints) telle que FK(q) = T_desired (pose désirée).
def ik_jacobian(dh_params, T_target, q0, max_iter=100, tol=1e-6, lambda_=0.1):
"""IK par Jacobien pseudo-inverse avec damping"""
q = q0.copy()
for _ in range(max_iter):
# Cinématique directe
T_curr = forward_kinematics(q, dh_params)
# Erreur de pose (translational + rotational)
pos_err = T_target[:3, 3] - T_curr[:3, 3]
# Erreur rotationnelle (axis-angle)
R_err = T_target[:3, :3] @ T_curr[:3, :3].T
axis_angle = np.array([
R_err[2, 1] - R_err[1, 2],
R_err[0, 2] - R_err[2, 0],
R_err[1, 0] - R_err[0, 1]
]) / 2.0
e = np.concatenate([pos_err, axis_angle])
if np.linalg.norm(e) < tol:
return q
# Jacobien à la configuration courante
J = compute_jacobian(q, dh_params)
# Damped LS : q_dot = J^T (J J^T + λ²I)^{-1} e
JJT = J @ J.T
damped = JJT + lambda_**2 * np.eye(6)
dq = J.T @ np.linalg.solve(damped, e)
q = q + dq * 0.5 # step size
return q
from scipy.optimize import minimize
def ik_numerique(T_target, q0, dh_params):
def f(q):
T = forward_kinematics(q, dh_params)
# Erreur = position + rotation (quaternion)
pos_err = np.linalg.norm(T_target[:3, 3] - T[:3, 3])
# Frobenius norm sur rotation
rot_err = np.linalg.norm(T_target[:3, :3] - T[:3, :3], 'fro')
return pos_err + 0.1 * rot_err
res = minimize(f, q0, method='BFGS', options={'maxiter': 200})
return res.x if res.success else None
Pour robots avec sphère de poignet (3 derniers axes concourants, ex: PUMA 560, KUKA KR, ABB IRB).
def ik_pieper(dh_params, T_target):
"""
Solution IK analytique pour robots avec poignet sphérique
(3 derniers axes concourants - Pieper's solution)
"""
# Étape 1 : Extraire position poignet = T_06 * [0,0,0,1]^T
# Pour poignet sphérique : position poignet déterminée par J1,J2,J3
# J4,J5,J6 : orientent seulement l'effecteur
# Position du poignet dans repère base
d6 = dh_params[5][1] # d dernier joint
d = T_target[:3, :3] @ np.array([0, 0, -d6]) + T_target[:3, 3]
# J1 : projection dans plan xy
theta1_1 = np.arctan2(d[1], d[0])
theta1_2 = np.arctan2(-d[1], -d[0])
solutions = []
for theta1 in [theta1_1, theta1_2]:
# J2, J3 : géométrie du plan sagittal
# ... (géométrie du triangle formé par base-épaule-coude-poignet)
pass
return solutions
Le Jacobien J(q) relie vitesses articulaires aux vitesses cartésiennes :
v = J(q) · q_dot
où v = [v_x, v_y, v_z, ω_x, ω_y, ω_z]^T
def compute_jacobian(q, dh_params):
"""Jacobien géométrique (6 × n)"""
n = len(q)
J = np.zeros((6, n))
T = np.eye(4)
for i in range(n):
# Transformation jusqu'au joint i
theta = q[i] + dh_params[i][0]
Ti = dh_transform(theta, dh_params[i][1],
dh_params[i][2], dh_params[i][3])
T = T @ Ti
# Axe z_i dans repère base
z_i = T[:3, 2]
# Origine O_i dans repère base
o_i = T[:3, 3]
# Position de l'effecteur
T_ee = forward_kinematics(q, dh_params)
o_n = T_ee[:3, 3]
# Pour joint prismatique (P) : v = z_i, ω = 0
# Pour joint rotoïde (R) : v = z_i × (o_n - o_i), ω = z_i
J[:3, i] = np.cross(z_i, o_n - o_i) # translation
J[3:, i] = z_i # rotation
return J
# Singularités : det(J(q)) = 0
def check_singularity(J, threshold=1e-6):
JTJ = J.T @ J
if np.linalg.matrix_rank(J) < min(J.shape):
return True
# Condition number
cond = np.linalg.cond(J)
return cond > 1.0 / threshold # mal conditionné → proche singularité
# Manipulabilité (Yoshikawa)
def manipulability(J):
JTJ = J @ J.T
return np.sqrt(np.linalg.det(JTJ))
# Élasticité du Jacobien
# Plus manipulabilité → grande, plus le robot est agile à cette configuration
def workspace_monte_carlo(dh_params, N=10000):
"""Échantillonne aléatoirement l'espace de configuration"""
points = []
for _ in range(N):
q_random = np.random.uniform(
[-np.pi]*6, [np.pi]*6
)
T = forward_kinematics(q_random, dh_params)
points.append(T[:3, 3]) # position x,y,z
points = np.array(points)
# Bounding box
bb_min = points.min(axis=0)
bb_max = points.max(axis=0)
# Volume (enveloppe convexe)
from scipy.spatial import ConvexHull
hull = ConvexHull(points)
volume = hull.volume
return points, bb_min, bb_max, volume
| Type | Cause | Cartographie |
|---|---|---|
| Singularité de bord | Bras complètement étendu | J1,J2,J3 : rang perdu |
| Singularité intérieure | Axes alignés (ex: J4 = 0 → J6 coaxial J4) | Alignement z_i |
| Singularité d'épaule | Centre poignet dans axe J1 | Dégénérescence sphérique |
| Singularité de coude | Épaule-coude aligné (J3 = 0) | Perte de mobilité radiale |
# DLS (Damped Least Squares) — préféré
def damped_pseudo_inverse(J, lambda_=0.1):
"""Pseudo-inverse amortie"""
U, s, Vt = np.linalg.svd(J, full_matrices=False)
s_damped = s / (s**2 + lambda_**2)
J_dls = Vt.T @ np.diag(s_damped) @ U.T
return J_dls
# SVD with task-priority framework
def svd_nullspace(J, J_nullspace_priority=True):
U, s, Vt = np.linalg.svd(J, full_matrices=True)
rank = np.sum(s > 1e-6)
return U, s, Vt, rank
from scipy.spatial.transform import Rotation as R
# Matrice de rotation → quaternion
r = R.from_matrix(T_ee[:3, :3])
quat = r.as_quat() # [x, y, z, w]
euler = r.as_euler('zyx') # roulis, tangage, lacet
rotvec = r.as_rotvec() # rotation axis-angle
# Angle-axis (θ, u) où θ = angle, u = axe unitaire
theta = np.linalg.norm(rotvec)
axis = rotvec / theta if theta > 0 else np.array([1, 0, 0])
# Composition de translations + rotations
# T = | R t |
# | 0 1 |
lower ≤ q_i ≤ upper). Utiliser des fonctions de coût quadratiques dans l'optimisation.