写在开始之前:为什么会有这篇文章
最近的工作中,我实际使用了一段时间 JAKA(节卡)六轴机械臂。
在现场的常规用法是:
-
安装节卡官方软件
-
使用平板作为示教器
-
通过触摸、拖动完成示教和调试
在交互层面,主要只有两类操作方式:
-
关节运动(单轴 / 多轴角度控制)
-
空间坐标运动(末端在笛卡尔空间的移动)
同时,节卡提供的是一种模块化、拖拽式的编程方式。在实际使用中,这种方式对调试人员是友好的:
-
平板便于携带
-
操作直观,上手快
-
不需要编程背景
-
中文界面,可读性很好
但在使用一段时间后,我也逐渐感受到一些明显的限制:
-
拖拽式逻辑在流程复杂时不够清晰
-
程序整体的可读性和可维护性较差
-
很难像代码一样进行版本管理和复用
-
对于做二次开发或系统级理解并不友好
简单来说:
它非常适合"用机器人",但不太适合"理解机器人"。
于是我开始思考一个问题:
如果抛开示教器,用"写代码"的方式去理解六轴机械臂,会不会更清楚?
在查阅节卡官方资料时,我发现他们其实提供了底层 SDK 和接口示例,但基本都是 C++ 实现。
考虑到学习和验证效率,我把其中一部分结构用 Python 重新抽象了一遍,并不追求功能完整,而是希望:
-
用代码把机械臂的系统结构拆清楚
-
理解真实工业机械臂的软件组织方式
-
为后续的运动学、控制和仿真打下基础
这篇文章,就是从这个背景开始的。
接下来,我们不从公式出发,而是从一份最小可理解的机械臂控制代码骨架开始,一步步展开。
本文以ZU12六轴机器人驱动代码为例,系统解析工业级机器人驱动的核心架构设计。代码聚焦于状态管理、模块解耦与安全边界构建,适用于六轴/SCARA等多关节机器人控制系统开发。
一、整体架构概览
python
class ZU12Driver:
def __init__(self):
self.robot_state = RobotState.DISABLED # 状态机
self.kinematics = Kinematics() # 运动学
self.dynamics = Dynamics() # 动力学
self.safety = Safety() # 安全监控
self.connected = False # 通信状态
该架构采用四层解耦设计:
- 状态管理层:统一管理机器人操作状态流转
- 运动学层:负责正/逆运动学解算、轨迹规划
- 动力学层:处理力矩计算、重力补偿、振动抑制
- 安全层:独立的安全监控与响应机制
各模块通过组合(Composition)方式集成,避免继承导致的紧耦合,符合SOLID原则中的单一职责原则(SRP)。
二、状态机设计:操作安全的基石
python
class RobotState:
DISABLED = 0 # 伺服未使能/断电
ENABLED = 1 # 伺服使能,可接收指令
ERROR = 2 # 安全事件触发,需人工复位
RUNNING = 3 # 运动执行中
状态流转约束
| 当前状态 | 允许操作 | 目标状态 | 校验条件 |
|---|---|---|---|
| DISABLED | power_on() |
DISABLED | 仅上电,未使能伺服 |
| DISABLED | enable_robot() |
ENABLED | 需先connect() + power_on() |
| ENABLED | 发送运动指令 | RUNNING | 安全模块检测通过 |
| ANY | 安全事件触发 | ERROR | 立即锁定所有操作 |
| ERROR | reset_error() |
DISABLED | 需人工确认后复位 |
实现要点
- 所有操作方法(
enable_robot(),power_off()等)前置校验self.connected - 状态变更集中管理,避免分散赋值导致状态不一致
ERROR状态设计为终端状态,必须显式复位才能恢复,符合ISO 10218安全规范
三、模块解耦设计分析
1. 运动学与动力学分离
python
self.kinematics = Kinematics() # 位置/速度级计算
self.dynamics = Dynamics() # 力/力矩级计算
分离价值:
- 运动学计算频率高(1-2ms周期),需轻量级实现
- 动力学计算可降频执行(5-10ms),避免实时性压力
- 便于独立测试:运动学可用DH参数验证,动力学可用仿真数据标定
典型调用链:
python
# 轨迹规划
joint_pos = kinematics.inverse(xyz, rpy) # 逆解
torque = dynamics.calculate_torque(joint_pos, velocity) # 力矩补偿
driver.send_command(joint_pos, torque) # 下发指令
2. 安全模块独立化
python
from safety import Safety, CollisionLevel
self.safety = Safety()
安全层级设计(CollisionLevel):
python
class CollisionLevel:
WARNING = 1 # 降速运行(软限位)
PROTECT = 2 # 停止运动,保持伺服使能
EMERGENCY = 3 # 触发急停,切断伺服电源
关键实现要求:
- 安全检测必须在运动指令下发前执行(前置校验)
- 安全事件触发后应异步通知上层,同时同步阻断运动链
- 硬件安全回路(安全继电器)必须与软件安全形成双冗余
四、通信抽象与扩展性
当前代码中connect()/disconnect()为模拟实现,实际工程需扩展通信抽象层:
python
class CommunicationInterface(ABC):
@abstractmethod
def connect(self) -> bool: pass
@abstractmethod
def send(self, cmd: bytes) -> bool: pass
@abstractmethod
def receive(self) -> Optional[bytes]: pass
@abstractmethod
def is_alive(self) -> bool: pass
class EtherCATDriver(CommunicationInterface): ...
class ModbusTCPDriver(CommunicationInterface): ...
集成建议:
python
class ZU12Driver:
def __init__(self, comm: CommunicationInterface):
self.comm = comm # 依赖注入,便于测试与替换
优势:
- 支持协议热切换(开发用Modbus,量产用EtherCAT)
- 单元测试时可注入Mock通信层,无需真机
- 符合依赖倒置原则(DIP)
五、工程实践建议
1. 状态持久化
python
def _persist_state(self):
state_data = {
'timestamp': time.time(),
'state': self.robot_state,
'joints': self.kinematics.get_current_joints()
}
with open('/var/lib/robot/state.json', 'w') as f:
json.dump(state_data, f)
- 断电恢复时可快速重建状态
- 便于故障后根因分析
2. 安全监控增强
python
def enable_robot(self) -> bool:
# 使能前安全自检
if not self.safety.check_joint_limits():
return False
if self.safety.collision_level != CollisionLevel.NONE:
return False
# ... 使能逻辑
3. 错误码标准化
建议将print()替换为结构化日志+错误码:
python
class ErrorCode:
NOT_CONNECTED = 0x1001
SAFETY_CHECK_FAILED = 0x1002
POWER_OFF_REQUIRED = 0x1003
def enable_robot(self) -> Tuple[bool, int]:
if not self.connected:
return False, ErrorCode.NOT_CONNECTED
六、架构适用性分析
| 机器人类型 | 适配要点 | 修改建议 |
|---|---|---|
| 六轴关节型 | 原生支持 | 无需修改 |
| SCARA | 运动学模型差异 | 替换Kinematics实现,保留驱动接口 |
| Delta | 工作空间约束强 | 在Safety中增强工作空间校验 |
| 协作机器人 | 需力控安全 | 扩展Safety增加力/力矩阈值监控 |
七、总结
该驱动架构的核心价值在于:
- 状态机驱动操作流:通过有限状态机约束操作顺序,从架构层面杜绝非法操作
- 垂直分层解耦:运动学/动力学/安全各司其职,支持独立开发与测试
- 安全前置设计:安全校验嵌入操作链路,而非事后补救
- 接口抽象预留:通信层、安全等级等均预留扩展点,适应不同硬件平台
完整代码结构建议:
python
zu12_driver/
├── __init__.py
├── driver.py # ZU12Driver主类
├── kinematics.py # Kinematics实现
├── dynamics.py # Dynamics实现
├── safety.py # Safety + CollisionLevel
└── communication/ # 协议抽象层(可选)