数字孪生与远程监控
一、设备简介
数字孪生把物理设备的实时状态 (关节角度、IO、温度、速度、节拍) 1:1 映射到 3D 虚拟模型上, 让工程师在虚拟环境里完成 "建模 → 仿真 → 监控 → 远程运维" 全闭环。
本案例以一个典型汽车焊接车间的孪生为例:
- 6 台焊接机器人 + 1 台变位机 + 4 台 AGV + 工件夹具, 全部在一个 Darra 工程里;
- URDF 原生导入 (ROS 社区机器人模型) + CAD 模型 STEP / STL 导入;
- 3D 视口 60FPS 渲染, 数据同步延迟 < 100ms (局域网) / < 500ms (VPN);
- 仿真 → 物理 零转换: 示教点 / 程序 / 工艺参数验证后一键部署到现场;
- 远程监控: 工程师在办公室 / 家里通过 Darra IDE 或 Web 3D 看到现场实时姿态, 可修改示教点并热加载。
软件授权 ¥9,800 (Darra IDE 专业版, 含 3D 孪生模块), 额外硬件仅需现场一台工控机 + 任意办公电脑。
二、项目模块组成
| 模块 | 职责 | 载体 |
|---|---|---|
| 3D 视口 | WebGL 渲染 + 60FPS + 支持 1000 万三角面 | IDE 3D Canvas |
| URDF 导入器 | ROS URDF / xacro / STEP / STL / OBJ / glb | Model Loader |
| 场景管理 | 机器人 / 工件 / 夹具 / 传送带 / AGV 树形管理 | Scene Graph |
| 绑定引擎 | 模型关节 ↔ PLC 变量, 1ms 刷新 | Binding FB |
| 仿真引擎 | 运动学 / 动力学 / 碰撞 / 节拍预测 | Sim Engine |
| 实时同步 | DarraSync / OPC UA / DarraIPC / MQTT 多通道 | Sync Service |
| 远程监控 | 现场 → 远程 IDE / Web 3D / 手机 实时展示 | Monitor Service |
| 反向控制 | 远程示教点 / 参数 / 配方 热下发 | Control Bridge |
| 轨迹记录 | 记录最近 10 分钟 TCP 轨迹, 支持回放 | TrajLog |
| 报警看板 | 故障叠加 3D 视口 + 推送多渠道 | Alarm Overlay |
| 多人协作 | 多工程师同屏, 不同角色不同权限 | Collab Service |
三、机械装配架构 (部署拓扑)
布局要点:
- 现场工控机跑 全功能 Runtime (EtherCAT 1ms + PLC + 机器人 + 孪生发布者);
- 远程 PC / Web / 手机只是 3D 客户端, 不承担控制逻辑;
- 推送数据走 DarraSync (低延迟 + 带宽自适应) 或 OPC UA (标准对接);
- 反向控制 (修示教点 / 参数) 走 DarraIPC, 带身份认证 + ACL;
- 安全: 所有远程连接走 TLS + 客户端证书, VPN 层面再加一道。
四、程序架构
孪生接口 FB 清单
| FB 名 | 输入 | 输出 | 说明 |
|---|---|---|---|
FB_Twin_LoadURDF | ModelPath | SceneId | 加载 URDF |
FB_Twin_LoadSTEP | ModelPath | SceneId | 加载 CAD |
FB_Twin_BindJoint | SceneId / JointName / VarId | Done | 模型关节 ↔ PLC 变量 |
FB_Twin_Publish | SceneSnapshot | Bytes | 推送到远程 |
FB_Twin_Subscribe | ClientId | SceneStream | 远程订阅 |
FB_Sim_PlayBack | StartTime / EndTime | Frame | 轨迹回放 |
FB_Sim_CollisionCheck | SceneId | Collisions[] | 碰撞检测 |
FB_Sim_RunOffline | Program / Duration | TactTime / Cycle | 离线仿真 |
FB_Remote_UpdatePoint | RobotId / PointName / Pose | Done | 远程修示教点 |
FB_Remote_HotDeploy | ProgramBlob | Done | 热部署 |
五、硬件 BOM (国产优先)
5.1 现场端 (与真实产线共用)
| 设备 | 型号 / 规格 | 数量 | 单价 (¥) | 小计 (¥) |
|---|---|---|---|---|
| 现场工控机 | 研华 IPC-610 / i7-12700 / 32GB / 独显 GTX 1650 (可选) | 1 | 10,500 | 10,500 |
| 车间大屏 | 威纶通 TK8112IP 65 寸 4K | 1 | 15,000 | 15,000 |
| 工业交换机 | 华为 S5735 千兆 | 1 | 2,800 | 2,800 |
| UPS | 山特 C1K | 1 | 1,500 | 1,500 |
| 摄像头 (视频叠加) | 海康 DS-2CD2345FWD | 2 | 800 | 1,600 |
| 现场端合计 | ¥31,400 |
5.2 远程端
| 设备 | 说明 | 单价 (¥) |
|---|---|---|
| 工程师 PC | 任意 16GB + 4GB 独显 | 自备 |
| 办公室大屏 | 创维 43G31 | 2,500 |
| 总部大屏 (可选) | 海信 M86Pro 85 寸 4K | 12,000 |
| VPN 网关 (可选) | 华为 USG6320 | 3,500 |
5.3 软件授权
| 项目 | 数量 | 单价 (¥) | 小计 (¥) |
|---|---|---|---|
| Darra IDE 专业版 (含 3D 孪生) | 3 席位 | 9,800 | 29,400 |
| Runtime 永久授权 | 1 | 9,800 | 9,800 |
| Web 客户端 / 手机 | 不限 | 0 | 0 |
| 合计 | ¥39,200 |
相比"独立离线编程软件 + 独立 SCADA + 定制二次开发"的多套拼装方案, Darra 把 3D 数字孪生、HMI 与 PLC 控制整合在同一份工程里, 大幅降低软件采购与集成成本。
六、IO 模块配置
6.1 孪生需要的 IO / 数据源
数字孪生本身不直接连 IO, 而是通过绑定 现有 PLC 变量 (这些变量已由 EtherCAT / 机器人 / 各 FB 产生)。绑定清单示例:
| 3D 模型部件 | 关节 / 属性 | 绑定 PLC 变量 | 周期 |
|---|---|---|---|
| R1 机器人 Joint1 | 角度 (度) | G_Robots[1].Actual.Joint1 | 50ms |
| R1 机器人 Joint2~6 | 角度 | G_Robots[1].Actual.Joint2..6 | 50ms |
| R1 夹爪 | 张开 0~100% | G_Robots[1].GripperPercent | 50ms |
| R2~R6 (同理) | / | / | / |
| 变位机 R 轴 | 旋转角 | G_Positioner.rAngleR | 50ms |
| 变位机 T 轴 | 翻转角 | G_Positioner.rAngleT | 50ms |
| AGV1 位置 | X/Y/Theta | G_Agvs[1].rX, rY, rTheta | 100ms |
| AGV2~4 (同理) | / | / | / |
| 工件 | 位姿 (附在变位机) | 由变位机位姿派生 | 50ms |
| 夹具 LED | 运行灯 | Q_LMP_Running | 500ms |
| 电流表 | 焊机电流 | G_Robots[i].rArcCurrent | 50ms |
6.2 绑定操作流程 (IDE 内)
- 新建 Twin 工程: Darra IDE → 新建 → "数字孪生场景";
- 导入 URDF: 从 ROS 社区下载 ER16-1950.urdf → 拖入 3D 画布 → 自动解析 6 关节 + STL 外观;
- 批量复制: 6 台机器人按实际布局摆放 → 调整位姿;
- 导入变位机: STEP 文件 → 转换为 Mesh → 设定两个旋转轴;
- 导入 AGV: URDF 或简单圆盘代表 → 4 台;
- 绑定变量: 右键每个关节 → "绑定 PLC 变量" → 选
G_Robots[i].Actual.JointX→ 设定周期; - 导入工件: CAD STEP → 作为变位机子节点 (附在变位机上);
- 摄像头叠加: 在场景中放置虚拟摄像头 → 绑定海康 RTSP 流;
- 轨迹记录配置: 选择要记录 TCP 轨迹的机器人 → 保留 10 分钟;
- 仿真 vs 监控模式切换: 场景属性里选 "Simulation" 或 "Live Monitor";
- 权限配置: 工程师 (读写示教点) / 操作工 (只读) / 领导 (大屏视角);
- 远程端部署: 把同一 Twin 工程打开在办公室 PC → 连接现场 Runtime IP → 自动同步。
七、核心数据结构
7.1 3D 场景快照 UDT
TYPE UDT_SceneSnapshot :
STRUCT
tTimestamp : LTIME;
nRobotCnt : INT;
aRobots : ARRAY[1..8] OF UDT_RobotPose;
stPositioner: UDT_PositionerPose;
nAgvCnt : INT;
aAgvs : ARRAY[1..32] OF UDT_AgvPose;
aAlarms : ARRAY[0..15] OF UDT_Alarm;
END_STRUCT
END_TYPE
TYPE UDT_RobotPose :
STRUCT
nId : INT;
aJoint : ARRAY[1..6] OF REAL; // 度
stTCP : UDT_Pose;
rGripper : REAL; // 0~100%
eState : E_RobotState;
rArcI : REAL; // 焊接电流 (可选)
rArcV : REAL;
END_STRUCT
END_TYPE
TYPE UDT_PositionerPose :
STRUCT
rAngleR : REAL;
rAngleT : REAL;
END_STRUCT
END_TYPE
TYPE UDT_AgvPose :
STRUCT
nId : INT;
rX : REAL;
rY : REAL;
rTheta : REAL;
eState : E_AgvState;
END_STRUCT
END_TYPE
7.2 绑定表 UDT
TYPE UDT_Binding :
STRUCT
sModelPath : STRING[128]; // "R1/Joint1"
sVarPath : STRING[128]; // "G_Robots[1].Actual.Joint1"
rIntervalMs: REAL; // 50
eMode : E_BindMode; // ReadOnly / Bidirectional
END_STRUCT
END_TYPE
7.3 远程命令 UDT
TYPE UDT_RemoteCmd :
STRUCT
sCmdId : STRING[32];
sClientId : STRING[32];
eType : E_CmdType; // UpdatePoint / LoadRecipe / Start / Pause / HotDeploy
sTarget : STRING[64]; // 目标对象
sPayload : STRING[512]; // JSON 参数
tSent : LTIME;
bAcked : BOOL;
END_STRUCT
END_TYPE
7.4 轨迹记录 UDT
TYPE UDT_TrajPoint :
STRUCT
nRobotId : INT;
stTCP : UDT_Pose;
rSpeed : REAL;
tAt : LTIME;
END_STRUCT
END_TYPE
7.5 全局变量
VAR_GLOBAL
G_Snapshot : UDT_SceneSnapshot;
G_Bindings : ARRAY[0..999] OF UDT_Binding;
G_Traj : ARRAY[0..99999] OF UDT_TrajPoint; // 环形 10 分钟
G_CmdQueue : ARRAY[0..99] OF UDT_RemoteCmd;
G_Clients : ARRAY[0..15] OF UDT_ClientSession;
G_Mode : E_TwinMode; // Simulation / LiveMonitor
END_VAR
八、核心程序代码
8.1 FB_ModelBinding (关节 ↔ PLC 变量)
FUNCTION_BLOCK FB_ModelBinding
VAR
i : INT;
rNow : REAL;
END_VAR
FOR i := 0 TO N_BINDINGS - 1 DO
IF (LTIME() - G_Bindings[i].tLastUpdate) / 1_000_000
>= G_Bindings[i].rIntervalMs THEN
rNow := ReadVarAsReal(G_Bindings[i].sVarPath);
// 更新 3D 模型关节 (本地快照)
SetModelJointValue(
Path := G_Bindings[i].sModelPath,
Value := rNow
);
G_Bindings[i].tLastUpdate := LTIME();
END_IF;
END_FOR;
8.2 FB_TwinPublisher (推送快照到远程)
FUNCTION_BLOCK FB_TwinPublisher
VAR
fbSend : FB_Sync_Push;
stSnap : UDT_SceneSnapshot;
END_VAR
// 收集快照
stSnap.tTimestamp := LTIME();
stSnap.nRobotCnt := 6;
FOR i := 1 TO 6 DO
stSnap.aRobots[i].nId := i;
stSnap.aRobots[i].aJoint := G_Robots[i].Actual.Joints;
stSnap.aRobots[i].stTCP := G_Robots[i].Actual.TCP;
stSnap.aRobots[i].eState := G_Robots[i].eState;
stSnap.aRobots[i].rArcI := G_Robots[i].rArcCurrent;
END_FOR;
stSnap.stPositioner := G_Positioner;
FOR i := 1 TO 4 DO
stSnap.aAgvs[i].nId := i;
stSnap.aAgvs[i].rX := G_Agvs[i].rX;
stSnap.aAgvs[i].rY := G_Agvs[i].rY;
stSnap.aAgvs[i].rTheta := G_Agvs[i].rTheta;
END_FOR;
// 推送到所有订阅客户端
fbSend(
Channel := 'TwinSnapshot',
Data := stSnap,
ToNodeList := ClientListOnline,
Compress := TRUE,
Encrypt := TRUE,
Execute := TRUE
);
8.3 FB_SimEngine (离线仿真, 节拍预测)
FUNCTION_BLOCK FB_SimEngine
VAR
fbCollision : FB_Sim_CollisionCheck;
fbKin : FB_Robot_FwdKin;
i : INT;
END_VAR
IF G_Mode = E_TwinMode.Simulation THEN
// 在仿真模式下, 关节角度由仿真引擎驱动, 不读 EtherCAT
FOR i := 1 TO 6 DO
// 按示教程序的计划轨迹前进一步
AdvanceSimRobot(i, simDeltaT);
END_FOR;
// 碰撞检测
fbCollision(SceneId := 0, Execute := TRUE);
IF fbCollision.CollisionCount > 0 THEN
LogCollisions(fbCollision.Collisions);
StopSim();
END_IF;
// 节拍预测: 模拟 500 个任务周期, 统计平均节拍
IF SimCycleCount > 500 THEN
G_PredictedCycle := AvgCycle(LastCycles);
ReportSimComplete();
END_IF;
END_IF;
8.4 FB_RemoteControl (远程命令处理)
FUNCTION_BLOCK FB_RemoteControl
VAR
stCmd : UDT_RemoteCmd;
i : INT;
END_VAR
// 从命令队列取下一条
FOR i := 0 TO 99 DO
IF G_CmdQueue[i].bAcked = FALSE
AND G_CmdQueue[i].sCmdId <> '' THEN
stCmd := G_CmdQueue[i];
// 鉴权 + 审计
IF NOT VerifyClient(stCmd.sClientId) THEN
G_CmdQueue[i].bAcked := TRUE;
CONTINUE;
END_IF;
LogAudit(stCmd);
CASE stCmd.eType OF
E_CmdType.UpdatePoint:
// 解析 JSON, 写入机器人示教点
WriteTeachPoint(stCmd.sTarget, stCmd.sPayload);
E_CmdType.LoadRecipe:
LoadRecipeToAll(stCmd.sPayload);
E_CmdType.Start:
G_LineState := E_LineState.Running;
E_CmdType.Pause:
G_LineState := E_LineState.Paused;
E_CmdType.HotDeploy:
HotDeployProgram(stCmd.sPayload);
END_CASE;
G_CmdQueue[i].bAcked := TRUE;
SendReply(stCmd.sCmdId, 'OK');
END_IF;
END_FOR;
8.5 FB_TrajRecorder (TCP 轨迹 10 分钟环形)
FUNCTION_BLOCK FB_TrajRecorder
VAR
i : INT;
idx : DINT;
END_VAR
// 每 50ms 记录一次 6 机器人 TCP
FOR i := 1 TO 6 DO
idx := G_TrajIdx MOD 99999;
G_Traj[idx].nRobotId := i;
G_Traj[idx].stTCP := G_Robots[i].Actual.TCP;
G_Traj[idx].rSpeed := G_Robots[i].Actual.Speed;
G_Traj[idx].tAt := LTIME();
G_TrajIdx := G_TrajIdx + 1;
END_FOR;
8.6 FB_CollabSession (多人协作)
FUNCTION_BLOCK FB_CollabSession
VAR
i : INT;
END_VAR
FOR i := 0 TO 15 DO
IF G_Clients[i].bOnline THEN
// 推送当前他人鼠标位置 + 当前选中部件
PublishCollabCursor(
SessionId := G_Clients[i].sSessId,
CursorXYZ := G_Clients[i].stCursor,
SelectedObj := G_Clients[i].sSelObj
);
END_IF;
END_FOR;
九、运行与调试
9.1 首次部署流程
- 现场 Runtime 安装: 工控机装 Darra Runtime, 激活 IDE 专业版;
- 产线程序就位: 焊接 / AGV 等已按各自案例部署完成;
- 新建 Twin 工程: IDE → 新建数字孪生场景;
- URDF 导入: ROS 社区 ER16-1950 URDF 导入 + 6 台摆位;
- STEP 夹具 / 工件: 3D 编辑器里对齐到机器人 TCP / 变位机;
- 绑定变量: 按绑定表 500+ 条, IDE 支持 CSV 批量导入;
- 仿真跑一遍: 切到 Simulation 模式, 跑 1 个焊接周期, 检查无碰撞;
- 切到 Live Monitor: 连现场 Runtime → 实时显示物理姿态, 验证一致性;
- 开放远程客户端: 办公室 PC / Web 浏览器 / 手机 → 登录 → 看到相同画面;
- 视频叠加: 海康相机 RTSP 配置 → 3D 视口旁显示;
- 远程修示教点: 办公室工程师选择某点 → 修改 → 热下发 → 现场 Runtime 接受;
- 集团大屏: 总部大屏打开 Web 3D → 鸟瞰多厂;
- 碰撞演练: 模拟夹具移位, 仿真发现碰撞即告警。
9.2 常见故障排查
| 现象 | 排查点 |
|---|---|
| 3D 卡顿 / 帧率低 | GPU 驱动 / 模型面数 / 发布周期 / 网络带宽 |
| 姿态与现场不一致 | 绑定路径拼写 / 单位 (度 vs 弧度) / 时间戳漂移 |
| 远程修改不生效 | 鉴权失败 / 程序未切 "允许远程" / 热部署锁 |
| VPN 下延迟高 | MTU 分片 / 压缩开关 / 发布周期 |
| URDF 导入变形 | mesh 坐标系 / scale / joint axis 方向 |
| 视频延时 | RTSP 转码 / 码率 / 客户端硬件解码 |
| 多人冲突修改示教点 | 协作锁 (同一点位同时只一人写) |
| 碰撞检测漏报 | 模型 mesh 过于简化 / 碰撞盒配置 |
9.3 日常运维
- 每周: 检查绑定清单有没有 dead 变量 (PLC 里已删除);
- 每月: 模型优化 (三角面过多的 STEP 减面);
- 每季度: 轨迹归档 (十分钟环形可导出关键段留档);
- 每次产线改造: URDF / STEP 同步更新, 保持虚实一致。
十、Darra 功能对照表
| 需求 | Darra 功能 |
|---|---|
| 3D 视口内置 | IDE 原生 WebGL 画布 |
| URDF 导入 | 原生 (无需独立离线编程软件) |
| CAD 导入 | STEP / STL / OBJ / glb |
| 模型关节 ↔ PLC 变量绑定 | FB_ModelBinding |
| 实时同步 < 100ms | FB_TwinPublisher + DarraSync |
| 仿真 → 物理零转换 | 同一份工程 + Simulation/LiveMonitor 切换 |
| 碰撞检测 | FB_Sim_CollisionCheck 60Hz |
| 节拍预测 | FB_SimEngine 离线跑 500 周期 |
| 远程修示教点 | FB_RemoteControl + 热部署 |
| 轨迹记录回放 | FB_TrajRecorder 10 分钟环形 |
| 多人协作同屏 | FB_CollabSession + 权限 |
| 视频叠加 | HMI Designer 3D 部件 + RTSP |
| 移动端 3D | HTML5 + WebGL, 免费 |
| 集团多厂鸟瞰 | 多场景合并 + DarraSync 跨厂 |
| 安全 / 鉴权 | TLS + 客户端证书 + ACL + 审计日志 |
十一、项目总结
成果指标
- 3D 帧率: 60 FPS 稳定, 大场景 (6 机器人 + 4 AGV + 工件) 1000 万面无压力;
- 数据同步延迟: 局域网 < 100ms, VPN < 500ms;
- 支持机器人: 单场景 8 台 + AGV 32 台 + 传感器 10000 点;
- 仿真精度: 与物理差 < 1% (节拍预测误差);
- 碰撞检测: 60Hz 实时;
- 软件成本: ¥3.9 万 (IDE 3 席位 + Runtime), 传统 ¥55+ 万, 省 70%+;
- 上线周期: 2~4 周, 传统 3~6 月;
- 多人协作: 16 个并发客户端 同屏, 免费。
适配场景延伸
- 设备远程监控: OEM 设备商远程查看客户现场;
- 新工艺离线验证: 先仿真再部署;
- 培训教学: 无需实物, 学员用 URDF 学;
- 预测性维护: 长期孪生对比 → 异常早发现;
- 工厂参观 / 招商: 3D 鸟瞰全厂;
- 客户演示: OEM 给终端客户远程演示;
- 碰撞分析: 新工装 / 新路径先虚拟试跑;
- 应急培训: 模拟故障场景练应急;
- 多工厂统一可视化: 集团总部鸟瞰多地。
扩展方向
- AR 眼镜叠加: 现场维修人员戴 AR 看到 3D 模型 + 参数叠加;
- 物理仿真升级: 引入动力学 (重力 / 惯量 / 摩擦), 用于高精度节拍预测;
- AI 异常检测: 基于轨迹历史识别异常模式, 预警故障;
- 场景合并多厂: DarraSync 跨厂 Twin 合并到总部;
- 大模型参与修模型: 自然语言描述 "给我一个贴标机" → AI 自动从模型库找到并摆好;
- 碰撞路径规划: 碰撞发现后 AI 自动给替代路径;
- 孪生回放 + 故障复盘: 事故发生时把 10 分钟轨迹导出给工艺师分析;
- 与工单联动: 工单切换时自动刷新虚拟场景中的工件模型。
Darra 让 数字孪生 从 "昂贵的展示项目" 变成 "每个工程师日常使用的生产力工具", 虚实一致 才是数字孪生真正落地的条件。