多机器人协同
工业现场常有多台机器人同时工作 — 双机搬运、焊接+上下料组合、多台并联码垛等。Darra 支持在一个项目内配置和管理最多 8 台机器人, 并提供多种协调策略和干涉区管理机制。
协调策略
Darra 支持三种多机器人协调策略, 按耦合程度从高到低排列:
1. 主从协调 (Master-Slave)
一台机器人作为主机器人 (Master), 其他机器人作为从机器人 (Slave)。从机器人的目标位姿相对于主机器人定义, 随主机器人联动。
典型应用:
- 双机搬运 — 两台机器人持同一工件两端, 同步运动
- 焊接变位机 — 变位机 (从) 跟随焊接机器人 (主) 调整工件姿态
- 主手引导 — 示教主手, 从手自动镜像运动
配置:
// 配置主从关系
VAR
SlaveConfig : MASTER_SLAVE_CONFIG;
END_VAR
SlaveConfig.MasterRobot := Robot1;
SlaveConfig.SlaveRobot := Robot2;
SlaveConfig.RelativeFrame := "Part_Frame"; // 从机器人相对主机器人的工件坐标系
SlaveConfig.Mode := MS_SYNC_POSE; // 同步模式: 位姿同步
ApplyMasterSlave(SlaveConfig);
运动指令 — 只需编程主机器人, 从机器人自动跟随:
// 只需控制 Robot1, Robot2 自动跟随
MoveL(Target := PickPos, Velocity := 30); // Robot1 + Robot2 同步
MoveL(Target := PlacePos, Velocity := 20); // Robot1 + Robot2 同步
2. 平等协调 (Coordinated)
多台机器人共同完成一个任务, 但它们的目标位姿独立编程, 通过耦合约束保证协调 (如同步到达、相对速度保持)。
典型应用:
- 焊接工作站 — 焊接机器人 + 变位机各自运动, 但焊接轨迹要求两者耦合
- 装配 — 一台持工件, 另一台执行装配操作, 需要精确的相对位姿控制
配置:
VAR
CoordGroup : COORDINATED_GROUP;
END_VAR
// 创建协调组
CoordGroup := CreateCoordGroup(
Robots := [Robot1, Robot2],
Coupling := COUPLING_TIME, // 时间耦合: 同步到达路径终点
Tolerance := 5.0 // 允许的最大时间偏差 [ms]
);
// 独立编程, 系统保证同步
MoveL(Robot := Robot1, Target := WeldStart, Velocity := 20);
MoveL(Robot := Robot2, Target := PoserStart, Velocity := 30);
3. 区域划分 (Zone Partition)
每台机器人负责各自的独立工作区, 工作区之间由安全围栏或干涉区分隔。机器人之间不共享空间, 无耦合运动。
典型应用:
- 多台机器人并排码垛 — 每台负责一条传送带
- 同工位分工 — 一台负责左侧焊接, 另一台负责右侧装配
配置:
VAR
Zone1, Zone2 : WORKSPACE_ZONE;
END_VAR
// 定义机器人各自的工作区
Zone1 := DefineZone(
Robot := Robot1,
Region := {X := [-500, 0], Y := [-300, 300], Z := [0, 1000]},
Priority := 1
);
Zone2 := DefineZone(
Robot := Robot2,
Region := {X := [0, 500], Y := [-300, 300], Z := [0, 1000]},
Priority := 2
);
共享工作空间管理
当多台机器人的工作空间重叠时, 必须管理共享工作空间以避免碰撞。
共享空间分类
| 类型 | 说明 | 管理方式 |
|---|---|---|
| 全共享 | 两台机器人可达空间完全重叠 | 干涉区 + 时序控制 |
| 部分共享 | 空间有重叠区域 | 干涉区 + 动态优先级 |
| 无共享 | 空间不重叠 | 无需管理 (区域划分) |
干涉区 (Interlock Zone)
干涉区是共享工作空间中一次只允许一台机器人进入的区域。Darra 提供灵活的干涉区机制:
定义干涉区:
VAR
ILZone : INTERLOCK_ZONE;
ILZoneID : INT;
END_VAR
// 定义一个长方体干涉区
ILZone.Shape := ZONE_BOX;
ILZone.Center := {X := 200, Y := 0, Z := 500};
ILZone.Size := {X := 400, Y := 300, Z := 400};
ILZone.Robots := [Robot1, Robot2, Robot3];
ILZone.Priority := [1, 2, 3]; // Robot1 优先级最高
ILZoneID := RegisterInterlockZone(ILZone);
干涉区逻辑:
- 机器人进入干涉区前必须申请
RequestInterlock(ZoneID, RobotID) - 如果该区无人 → 立即获得许可
- 如果有人 → 按优先级排队: 高优先级可抢占, 低优先级等待
- 离开时释放
ReleaseInterlock(ZoneID, RobotID)
SCL 中的干涉区编程:
VAR
ILZone1 : INT := 1; // 干涉区 1
bGranted : BOOL;
END_VAR
// Robot1: 进入干涉区前申请
bGranted := RequestInterlock(Zone := ILZone1, Robot := Robot1, Timeout := 5000); // 5 秒超时
IF bGranted THEN
// 进入干涉区执行作业
MoveL(Target := SharedPickPos, Velocity := 30);
// ... 作业完成
ReleaseInterlock(Zone := ILZone1, Robot := Robot1);
ELSE
Log.Warn('Interlock zone 1 not granted, aborting');
// 超时未获得 → 走备选路径或报警
END_IF;
干涉区可视化
IDE 3D 视口中, 干涉区以半透明长方体 / 球体 / 自定义凸包显示:
- 绿色: 空闲, 可申请进入
- 黄色: 已占用, 正在被某机器人使用
- 红色: 被高优先级机器人占用, 申请被拒绝
- 灰色: 已禁用
同步与异步模式
同步模式 (Synchronous)
多台机器人同时执行运动指令, 所有运动在同一个 PLC 扫描周期内启动。
// 同步模式: 两台机器人同时开始运动
VAR
SyncGrp : SYNC_GROUP;
END_VAR
SyncGrp := CreateSyncGroup(Robots := [Robot1, Robot2]);
// 两台机器人各自独立轨迹, 但同一时刻开始
StartSyncGroup(SyncGrp);
MoveL(Robot := Robot1, Target := P1, Velocity := 50);
MoveL(Robot := Robot2, Target := P2, Velocity := 80);
EndSyncGroup(SyncGrp); // 等待所有机器人完成
异步模式 (Asynchronous)
每台机器人独立执行各自的运动指令, 互不等待。这是默认模式。
// 异步模式: 各自独立执行
MoveL(Robot := Robot1, Target := P1, Velocity := 50);
MoveL(Robot := Robot2, Target := P2, Velocity := 80);
// Robot2 完成时间可能远早于 Robot1, 但不等
等待同步 (WaitFor)
在异步执行中, 可以在关键点强制同步:
// 异步启动, 但在 P1 点等待对方
MoveL(Robot := Robot1, Target := P1, Velocity := 50);
MoveL(Robot := Robot2, Target := P1, Velocity := 80);
WaitForAll(Robots := [Robot1, Robot2]); // 两者都到 P1 才继续
MoveL(Robot := Robot1, Target := P2, Velocity := 50);
MoveL(Robot := Robot2, Target := P2, Velocity := 80);
多机器人编程示例
示例 1: 双机协同搬运
两台机器人共同搬运一个工件从传送带到料框。
PROGRAM CoPickPlace
VAR
bGripper1, bGripper2 : BOOL;
SyncGrp : SYNC_GROUP;
ILZone : INT := 1;
END_VAR
// 初始化
SyncGrp := CreateSyncGroup(Robots := [Robot1, Robot2]);
// 同步回到 Home
StartSyncGroup(SyncGrp);
MoveJ(Robot := Robot1, Target := Home1, Speed := 80);
MoveJ(Robot := Robot2, Target := Home2, Speed := 80);
EndSyncGroup(SyncGrp);
// 同步移动到取料上方
StartSyncGroup(SyncGrp);
MoveL(Robot := Robot1, Target := PickApproach1, Velocity := 50);
MoveL(Robot := Robot2, Target := PickApproach2, Velocity := 50);
EndSyncGroup(SyncGrp);
// 同步下降到取料位
StartSyncGroup(SyncGrp);
MoveL(Robot := Robot1, Target := Pick1, Velocity := 20);
MoveL(Robot := Robot2, Target := Pick2, Velocity := 20);
EndSyncGroup(SyncGrp);
// 夹紧工件
bGripper1 := TRUE;
bGripper2 := TRUE;
DELAY 0.3;
// 同步抬起
StartSyncGroup(SyncGrp);
MoveL(Robot := Robot1, Target := PickApproach1, Velocity := 30);
MoveL(Robot := Robot2, Target := PickApproach2, Velocity := 30);
EndSyncGroup(SyncGrp);
// 申请放料干涉区
IF RequestInterlock(Zone := ILZone, Robot := Robot1, Timeout := 3000) THEN
// 同步移动到放料位
StartSyncGroup(SyncGrp);
MoveJ(Robot := Robot1, Target := PlaceApproach1, Speed := 60);
MoveJ(Robot := Robot2, Target := PlaceApproach2, Speed := 60);
EndSyncGroup(SyncGrp);
StartSyncGroup(SyncGrp);
MoveL(Robot := Robot1, Target := Place1, Velocity := 15);
MoveL(Robot := Robot2, Target := Place2, Velocity := 15);
EndSyncGroup(SyncGrp);
// 松开工件
bGripper1 := FALSE;
bGripper2 := FALSE;
DELAY 0.3;
ReleaseInterlock(Zone := ILZone, Robot := Robot1);
END_IF;
示例 2: 焊接 + 变位机协调
焊接机器人和变位机协同工作。
PROGRAM WeldCoordinated
VAR
WeldGroup : COORDINATED_GROUP;
WeldPoses : ARRAY[1..10] OF ROBOT_POSE;
i : INT;
END_VAR
// 创建协调组 (时间耦合, 同步到达每个路径点)
WeldGroup := CreateCoordGroup(
Robots := [WeldRobot, Positioner],
Coupling := COUPLING_TIME,
Tolerance := 5.0
);
// 示教好的焊接路径
FOR i := 1 TO 10 DO
// 焊接机器人走焊接轨迹, 变位机同步调整工件姿态
MoveL(Robot := WeldRobot, Target := WeldPoses[i], Velocity := 15);
// 变位机自动计算跟随姿态
MoveL(Robot := Positioner, Target := PoserPoses[i], Velocity := 20);
END_FOR;
性能指标
| 指标 | 值 |
|---|---|
| 最大机器人数量 | 8 |
| 最大干涉区数量 | 32 |
| 同步组最大成员 | 8 |
| 协调组最大成员 | 4 |
| 干涉区切换延迟 | < 2 ms |
| 同步时间偏差 | < 1 ms |
排错清单
| 现象 | 原因 | 解决 |
|---|---|---|
| 双机搬运不同步 | 未使用同步组 | 用 CreateSyncGroup + StartSyncGroup |
| 干涉区申请超时 | 对方机器人未释放 | 检查对方程序是否有 ReleaseInterlock |
| 协调组机器人卡住 | 耦合太紧 (时间容差太小) | 增大 Tolerance 到 10~20 ms |
| 区域划分后机器人越界 | Zone 定义不完整 | 在 Zone 外再加安全围栏干涉区 |
| 干涉区视觉颜色不变 | 3D 视口未刷新 | 刷新视口或重启仿真 |
最佳实践
- 能用区域划分就不用干涉区: 区域划分无运行时耦合, 最简单可靠。
- 干涉区粒度: 一个工作站 3~5 个干涉区足够, 太多增加死锁风险。
- 超时处理: 干涉区申请必须带 Timeout, 避免死锁卡死整站。
- 优先级不要平级: 同优先级干涉区容易死锁, 每台机器人应有明确优先级差异。
- 仿真验证: 多机器人程序必须先在仿真中跑完 100+ 循环, 确认无死锁和碰撞。
- 急停互锁: 任何一台机器人触发急停, 所有关联机器人必须同时急停。