4. 硬件抽象层与设备驱动集成
手术机器人软件栈中,硬件抽象层(HAL)位于应用逻辑与物理设备之间,承担“把不同厂商、不同总线、不同数据格式的设备,统一成一套可被上层调用的接口”的职责。没有 HAL 时,主控程序会直接依赖某个机械臂 SDK、某个电机驱动库或某个力传感器串口协议,一旦更换型号或增加设备,上层代码就要大范围修改。HAL 的目标是让上层只关心“我要让关节运动到某个位置”“我要读取末端六维力”“我要知道脚踏是否被踩下”,而不关心底层是 CANopen、EtherCAT、RS-485 还是 USB HID。
一、统一接口的分层与对象模型
一个可落地的 HAL 通常分为三层:设备抽象接口层、设备驱动实现层、设备管理器层。设备抽象接口层定义纯虚接口,例如 IArm、IMotor、IEncoder、IForceSensor、IPedal、IEStop;设备驱动实现层针对具体硬件实现这些接口;设备管理器层负责设备注册、查找、生命周期与热插拔事件分发。上层通过设备 ID 或角色名获取接口指针,而不是直接持有具体驱动对象。
以机械臂为例,抽象接口可定义为:connect()、disconnect()、enable()、disable()、getJointPositions()、setJointTargets()、getStatus()。电机接口则更底层:setCurrent()、setVelocity()、getPosition()、getFaultCode()。编码器接口提供 readRaw() 与 readCalibrated(),力传感器提供 readWrench() 返回六维力/力矩,脚踏提供 getPedalState() 返回按下、松开、比例值,急停提供 isTriggered() 与 reset()。所有接口的返回值统一使用 SI 单位与右手坐标系,角度用弧度,力用牛顿,力矩用牛·米,避免上层做单位换算。
二、设备驱动集成的关键实现
驱动实现层要解决三类问题:通信、时序、错误处理。以 CANopen 电机驱动为例,初始化流程通常包括:设置节点 ID 与波特率、进入 Pre-operational 状态、配置 PDO 映射(将控制字、目标位置、状态字、实际位置映射到过程数据对象)、切换到 Operational 状态。控制周期一般设为 1 ms 或 2 ms,每个周期发送 RPDO、接收 TPDO,并检查状态字中的故障位。若使用 EtherCAT,则需处理分布式时钟同步与从站扫描。
编码器集成要注意零点标定与多圈计数。增量式编码器上电后需要寻找 Z 相或机械限位来建立绝对零点;绝对式编码器可直接读取多圈位置,但仍需与机械零位做偏移标定。力传感器集成要处理零点漂移与温度补偿,通常在上电后执行一次空载归零,并在运行中定期检查偏置是否超过阈值。脚踏与急停属于安全相关设备,急停信号应同时接入硬件安全回路与软件 HAL,软件层只做状态读取与日志记录,不得用软件逻辑替代硬件急停。
示例:统一接口调用片段(伪代码)
auto arm = deviceManager.get<IArm>("arm_main");
auto force = deviceManager.get<IForceSensor>("force_tip");
auto pedal = deviceManager.get<IPedal>("pedal_left");
arm->enable();
while (running) {
auto wrench = force->readWrench(); // N, N·m
auto pedalState = pedal->getPedalState(); // 0.0 ~ 1.0
if (pedalState > 0.1 && !estop->isTriggered()) {
arm->setJointTargets(nextTargets);
}
std::this_thread::sleep_for(1ms);
}
三、热插拔管理机制
热插拔要求设备在运行中插入或拔出时,系统不崩溃、不误动作,并能正确恢复。实现上通常采用“设备管理器 + 事件队列 + 状态机”的组合。设备管理器周期性扫描总线或监听系统设备事件;发现新设备后,根据 VID/PID 或节点 ID 匹配驱动,创建实例并注册到接口表;发现设备消失后,将对应接口标记为失效,通知上层停止使用,并释放资源。每个设备维护一个状态机:Disconnected → Connecting → Connected → Ready → Fault → Disconnected。
热插拔过程中最危险的是“设备已拔出但上层仍在发送控制指令”。因此 HAL 必须在接口层做保护:当设备状态不是 Ready 时,setJointTargets() 等写操作直接返回错误码,读操作返回上一次有效值或安全默认值。对于机械臂,拔出后应自动进入阻尼或抱闸状态;对于脚踏,拔出后应视为松开;对于急停,拔出应视为触发。设备重新插入后,需重新执行初始化、零点标定与使能流程,不能直接复用旧状态。
四、热插拔状态迁移与安全策略
热插拔状态机是 HAL 的核心。以力传感器为例:设备插入后进入 Connecting,驱动尝试打开串口或网络端口并读取设备 ID;成功后进入 Connected,执行空载归零与量程检查;归零成功进入 Ready,上层可正常读取。若归零时读数超过阈值,进入 Fault,上层收到故障事件并停止力控。设备拔出时,从任意状态直接进入 Disconnected,接口返回安全默认值。重新插入后,状态机从 Connecting 重新开始,不复用旧标定数据。
对于机械臂,热插拔后的重新使能必须经过“抱闸释放 → 使能 → 回零或保持当前位置”的流程,且需要确认急停未触发、脚踏未踩下。对于脚踏,拔出后应视为松开,避免上层误判为持续踩下。对于急停,拔出应视为触发,因为急停回路断开本身就是安全状态。所有热插拔事件都应写入日志,包含时间戳、设备 ID、事件类型、前后状态,便于术后复盘与故障定位。
五、集成验证要点
验证 HAL 是否合格,可以从四个维度检查:接口一致性、单位一致性、状态一致性、热插拔鲁棒性。接口一致性指所有驱动都实现同一套纯虚接口,上层不出现 dynamic_cast 到具体类型;单位一致性指所有物理量在接口层已统一为 SI 单位;状态一致性指设备状态与上层可见状态始终同步;热插拔鲁棒性指在运行中反复插拔设备,系统不崩溃、不误动作、能自动恢复。建议在集成测试中至少执行 50 次插拔循环,并记录每次恢复时间与错误码,作为验收依据。
实践提示:热插拔测试时,先用假负载或仿真设备验证状态机逻辑,再接入真实硬件。急停与脚踏的插拔测试必须在安全回路断电或机械臂抱闸状态下进行,禁止在机械臂运动过程中直接拔插安全相关设备。