整合运动学、动力学和控制,构建完整的2自由度平面臂系统。
import numpy as np
print("="*60); print("2DOF平面臂完整系统"); print("="*60)
L1,L2,m1,m2,lc1,lc2,I1,I2,g=1.,.8,5.,3.,.5,.4,.5,.2,9.81
def fk(q): return np.array([L1*np.cos(q[0])+L2*np.cos(q[0]+q[1]),L1*np.sin(q[0])+L2*np.sin(q[0]+q[1])])
def ik(x,y):
d2=x**2+y**2; c2=np.clip((d2-L1**2-L2**2)/(2*L1*L2),-1,1); s2=np.sqrt(1-c2**2)
t2=np.arctan2(s2,c2); t1=np.arctan2(y,x)-np.arctan2(L2*s2,L1+L2*c2); return t1,t2
def jac(q): return np.array([[-L1*np.sin(q[0])-L2*np.sin(q[0]+q[1]),-L2*np.sin(q[0]+q[1])],[L1*np.cos(q[0])+L2*np.cos(q[0]+q[1]),L2*np.cos(q[0]+q[1])]])
def dyn(q,qd,tau):
c2,s2=np.cos(q[1]),np.sin(q[1])
M=np.array([[m1*lc1**2+I1+m2*(L1**2+lc2**2+2*L1*lc2*c2)+I2,m2*(lc2**2+L1*lc2*c2)+I2],[m2*(lc2**2+L1*lc2*c2)+I2,m2*lc2**2+I2]])
h=m2*L1*lc2*s2; C=np.array([[-h*qd[1],-h*(qd[0]+qd[1])],[h*qd[0],0]])
G=np.array([(m1*lc1+m2*L1)*g*np.cos(q[0])+m2*lc2*g*np.cos(q[0]+q[1]),m2*lc2*g*np.cos(q[0]+q[1])])
return np.linalg.solve(M,tau-C@qd-G)
# 轨迹:画圆
center=np.array([1.0,0.5]); R=0.3; T_total=5.0; dt=0.001
q=np.array(ik(*center+np.array([R,0]))); qd=np.zeros(2)
max_pos_err=0; max_vel_err=0; n_steps=int(T_total/dt)
for i in range(n_steps):
t=i*dt; phi=2*np.pi*t/T_total
x_des=center+R*np.array([np.cos(phi),np.sin(phi)])
xd_des=R*2*np.pi/T_total*np.array([-np.sin(phi),np.cos(phi)])
q_des=np.array(ik(*x_des)); J=jac(q); x=fk(q); xd=J@qd
tau=500*(q_des-q)+80*(0-qd)
G=np.array([(m1*lc1+m2*L1)*g*np.cos(q[0])+m2*lc2*g*np.cos(q[0]+q[1]),m2*lc2*g*np.cos(q[0]+q[1])])
tau+=G
qdd=dyn(q,qd,tau); qd+=qdd*dt; q+=qd*dt
pe=np.linalg.norm(x-x_des); max_pos_err=max(max_pos_err,pe)
print(f"圆形轨迹跟踪: T={T_total}s, R={R}m")
print(f"最大位置误差: {max_pos_err*1000:.2f}mm")
# 点到点运动
q_start=np.array([0.,0.]); q_end=np.array([np.pi/2,np.pi/4])
q2=q_start.copy(); qd2=np.zeros(2); T2=2.0
for i in range(int(T2/dt)):
tau=200*(q_end-q2)+50*(0-qd2)
G=np.array([(m1*lc1+m2*L1)*g*np.cos(q2[0])+m2*lc2*g*np.cos(q2[0]+q2[1]),m2*lc2*g*np.cos(q2[0]+q2[1])])
tau+=G; qdd=dyn(q2,qd2,tau); qd2+=qdd*dt; q2+=qd2*dt
print(f"\n点到点运动: 误差={np.degrees(np.linalg.norm(q2-q_end)):.3f}°")import numpy as np, time
print("系统性能基准测试")
N=10000
start=time.time()
for _ in range(N):
q=np.random.randn(2); c,s=np.cos(q),np.sin(q)
x=1*c[0]+0.8*c[0+1]; y=1*s[0]+0.8*s[0+1]
fk_t=(time.time()-start)/N*1e6
start=time.time()
for _ in range(N):
x,y=np.random.rand(2)*2-1; d2=x**2+y**2
c2=np.clip((d2-1-0.64)/1.6,-1,1); s2=np.sqrt(1-c2**2)
ik_t=(time.time()-start)/N*1e6
print(f" FK: {fk_t:.1f}μs IK: {ik_t:.1f}μs")
print(f" 控制周期1000μs, 余量: {1000/max(fk_t,ik_t):.0f}x")
print(" ✅ 满足实时要求")实时控制要求计算在1ms内完成。Python原型验证后,生产代码用C++重写可获得10-100x加速。
本课程按"运动学→动力学→力控制→感知规划→实战项目"组织,每课都建立在前面知识基础上。理解本课后,你将:
完成本课后,你应该能够:
完成练习后,继续下一课的学习。本课内容将在后续课程中被反复使用和扩展。
一个完整的机器人系统通常包含以下层次:
各层之间通过明确定义的接口通信,通常使用实时操作系统(RTOS)保证时序。
机器人软件开发的常用框架:
机器人安全设计遵循纵深防御原则:
安全不是可选功能,而是系统设计的首要约束。
本课涉及的技术在以下场景中有重要应用:
理解理论与实践的差距,是成为优秀机器人工程师的关键。
仿真验证的算法通常需要以下适配才能部署到实际机器人:参数标定、实时性优化、异常处理、安全保护。仿真与现实的差距(sim-to-real gap)是机器人领域的重要挑战。
Python适合算法验证和原型开发,但生产级控制器通常用C++实现。Python的NumPy/SciPy计算效率约为C++的1/10到1/100,对于1kHz控制频率可能不够。可以使用Cython、Numba或直接C++重写来加速。
推荐步骤:(1) Python仿真验证算法正确性;(2) 添加传感器噪声和延迟模型测试鲁棒性;(3) 用C++重写核心计算模块;(4) 在低速度下实际测试;(5) 逐步提高速度和负载。安全永远是第一位的。
| 术语 | 英文 | 定义 |
|---|---|---|
| 正运动学 | Forward Kinematics | 已知关节角求末端位姿 |
| 逆运动学 | Inverse Kinematics | 已知末端位姿求关节角 |
| 雅可比矩阵 | Jacobian Matrix | 关节速度到末端速度的映射 |
| 奇异位形 | Singularity | 末端失去某些方向运动能力的位形 |
| 工作空间 | Workspace | 末端可达的空间区域 |
| 自由度 | Degrees of Freedom | 独立运动变量的数量 |
| 齐次变换 | Homogeneous Transform | 4x4矩阵表示位姿 |
| 阻抗控制 | Impedance Control | 控制力与位移的动态关系 |
| 导纳控制 | Admittance Control | 输入力输出位移修正 |
| 轨迹规划 | Trajectory Planning | 生成平滑的运动时间函数 |
| 力封闭 | Force Closure | 接触力可抵抗任意外力 |
| 碰撞检测 | Collision Detection | 判断几何体是否相交 |
| 路径规划 | Path Planning | 在障碍物间找到安全路径 |
| 视觉伺服 | Visual Servoing | 基于视觉反馈的运动控制 |
| 手眼标定 | Hand-Eye Calibration | 确定相机与机器人坐标系的变换 |
整合全部知识构建了第一个完整的机械臂系统!