news 2026/8/20 11:35:47

OpenTwins数字孪生平台实战:用一天时间跑通组合式数字孪生的完整手记

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenTwins数字孪生平台实战:用一天时间跑通组合式数字孪生的完整手记

OpenTwins数字孪生平台实战:用一天时间跑通组合式数字孪生的完整手记

【免费下载链接】opentwinsInnovative open-source platform that specializes in developing next-gen compositional digital twins项目地址: https://gitcode.com/gh_mirrors/op/opentwins

假设你面前有一台随时可能罢工的机器:传感器在响、PLC 在跑、历史数据散落在三张 Excel 表里,而领导明天要看"可视化大屏"。你需要的不是一个新报表工具,而是一个能把物理资产、实时数据、历史曲线和预警逻辑统一装进同一套体系的东西。这就是 OpenTwins 要解决的问题——它是一个专为组合式数字孪生设计的开源平台,让你用类型定义、实例化、数据接入、可视化四步,把任意物理系统"镜像"成可查询、可监控、可演进的数字实体。下文以"项目从 0 到 1 落地的一天"为主线,带你走完全程。

清晨:先想清楚——你要的到底是仪表板,还是数字孪生?

很多团队的第一反应是"先上个 Grafana"。但仪表板只能回答"现在什么状态",回答不了三个更难的问题:这台设备的"身份"是什么?它和上下游设备的"关系"是什么?数据断了之后,系统能不能自己意识到?

OpenTwins 的定位正是补上这三块。它的核心是 Eclipse Ditto——一个用 JSON 描述孪生实体(叫 "Thing")的开源框架,静态信息放attributes,动态数据放features。平台在此基础上做了一层"扩展 API",让你能以**类型(type)为单位批量管理实体,并定义实体之间的组合(composition)**关系。举个例子,定义一个"汽车"类型,声明它由 4 个"车轮"组成,之后每次实例化汽车,系统会自动生成 4 个车轮孪生——这比手动复制粘贴 JSON 高效得多,也正是"组合式数字孪生"这个名字的由来。

蓝色为核心功能(Ditto、Hono、存储、消息中间件、Grafana),绿色支持类型组合,黄色接入机器学习,红色提供 3D 可视化。

一句话概括能力清单,每一条都值得你在选型时对照自己的需求:

能力它解决什么通俗理解
多协议接入MQTT / AMQP / Kafka / HTTP 共存设备用什么协议都行,平台统一收口
类型 + 组合批量建孪生、自动生成子实体像面向对象编程,定义类再实例化
时序存储InfluxDB v2 存历史曲线数据进来自动落库,Grafana 直接查
可视化Grafana 插件 + Unity 3D2D 面板与 3D 模型可互相联动
可插拔扩展Kafka-ML / FMI 仿真预测数据、仿真数据可与真实数据同屏

顺带一提,如果你只想跑在树莓派这类边缘设备上,OpenTwins 还维护了一个轻量级版本(OpenTwins-Lightweight),用 Mosquitto 替代 Kafka、去掉历史库和可视化组件,把资源占用压到很低。架构对比见 docs/docs/overview/architecture.md。

上午:一条 Helm 命令,把平台请上你的机器

先交代前提:你需要 Docker、Kubernetes(本地开发可用 Minikube)和 Helm v3。建议给 Minikube 留出至少 4 核、8GB 内存、40GB 磁盘,官方推荐配置如下:

minikube start --cpus 4 --disk-size 40gb --memory 8192 kubectl config use-context minikube

接着添加官方 Helm 仓库并一键部署:

helm repo add ertis https://ertis-research.github.io/Helm-charts/ helm upgrade --install opentwins ertis/OpenTwins --wait --dependency-update

等命令跑完,用kubectl get pods应该能看到 ditto、hono、grafana、influxdb 等一串 Pod 处于 Running 状态。之后只剩一步"接线":OpenTwins 的界面是作为Grafana 插件存在的,你需要把插件指向 Ditto 的两个服务。

  • 先用kubectl get services找到opentwins-grafanaopentwins-ditto-nginxopentwins-ditto-extended-api三个服务的对外地址(Minikube 下用minikube service <服务名> --url获取);
  • 浏览器打开 Grafana(默认账号密码是admin/admin),进入Administration → Plugins,启用 OpenTwins 插件;
  • 在插件的 Configuration 标签页填入 Ditto 与 Extended API 的 URL,凭据填ditto/ditto(默认值),保存。

至此,左侧菜单出现App → OpenTwins,平台就绪。部署细节可随时回查 docs/docs/installation/using-helm.mdx。

午后:用"类型"画出你的系统,再让它自动长出实例

下面进入今天的核心实验:给一辆车建数字孪生,监控它的 GPS 和四个车轮的速度、方向。一共五步,每一步都有明确产出。

第 1 步,定义"汽车"类型。进入Types页,点Create new type,在表单里填命名空间example、类型名car,把基本信息(名称、描述、图片)和动态特征gps填进去。表单右侧会实时生成对应的 Ditto Thing JSON,大致长这样:

{ "thingId": "example:car", "policyId": "default:basic_policy", "attributes": { "name": "Car", "description": "Digital twin example" }, "features": { "gps": { "properties": { "value": null } } } }

第 2 步,定义"车轮"类型并挂到汽车下。进入car类型的详情页,切到children标签,点Create new type创建wheel,特征填velocity(速度)和direction(方向)。关键一步在表单下方:实例数量填 4,表示每实例化一辆车就自动创建 4 个车轮。

第 3 步,实例化。进入Twins页,点Create a new twin,指定标识为mycar,选择car类型提交。系统会自动生成 5 个孪生:example:mycar和它的 4 个车轮子孪生example:mycar:wheel_1~wheel_4

提醒一下:类型不是必选项——你也可以从零直接建孪生。但有了类型,批量创建、数据一致性、后续维护都会轻松一个量级,强烈推荐为重复性实体建类型。

黄昏:给孪生接上"心跳",数据是怎么流进来的

孪生建好时是空壳,接下来注入数据。OpenTwins 安装时会自动建好一条名为mosquitto-source-connection的 MQTT 连接,订阅telemetry/#下的所有主题,所以最快的方式就是把数据发布到 MQTT。数据格式必须遵守 Ditto Protocol——它是一层 JSON 信封,告诉 Ditto"要改哪个孪生的哪段内容、怎么改"。

先装依赖,然后跑一个 Python 脚本模拟传感器:

pip install paho-mqtt typing_extensions
import paho.mqtt.client as mqtt import random, time, json # MQTT 连接信息:改为你实际的 Mosquitto 地址和端口(NodePort 默认 30511) broker, port = "localhost", 1883 username, password = "your_user", "your_pass" # 按需填写,无认证则删掉下一行 client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2) client.username_pw_set(username, password) client.connect(broker, port, 60) def build_msg(name, value): # Ditto Protocol 信封:merge 命令,合并写入 /features return { "topic": "example/{}/things/twin/commands/merge".format(name), "headers": {"content-type": "application/merge-patch+json"}, "path": "/features", "value": value, } while True: t = round(time.time() * 1000) # 毫秒时间戳 # 汽车孪生:随机 GPS 位置 gps = {"gps": {"properties": { "latitude": random.uniform(-90, 90), "longitude": random.uniform(-180, 180), "time": t}}} client.publish("telemetry/example/mycar", json.dumps(build_msg("mycar", gps))) # 四个车轮孪生:速度 + 方向 for i in range(1, 5): wheel = { "velocity": {"properties": {"value": random.uniform(0, 100), "time": t}}, "direction": {"properties": {"value": random.uniform(-45, 45), "time": t}}} client.publish("telemetry/example/mycar:wheel_{}".format(i), json.dumps(build_msg("mycar:wheel_{}".format(i), wheel))) time.sleep(5) # 每 5 秒发一轮

运行后回到 Twins 列表打开example:mycar,会发现gps特征里已经出现实时经纬度,四个车轮的数据也在滚动更新。如果你想看消息是否真的到达了 MQTT 这一环,用 MQTT Explorer 订阅telemetry/#即可一目了然。

如果你的设备不能改报文格式,也没关系——Ditto 连接支持JavaScript 映射:在连接的 Source/Target 里挂一段mapToDittoProtocolMsg函数,就能把任意自定义 JSON 自动翻译成 Ditto Protocol。生产线的非标设备常用这招,例子可参考 docs/docs/examples/string-example.mdx。

傍晚上线:把数据变成能读懂的仪表板

数据进来了,最后一步是让它"看得见"。孪生数据通过 Telegraf 落进 InfluxDB v2(bucket 名为opentwins),Helm 默认已配好 Grafana 数据源,你只需新建面板并写 Flux 查询。比如"四个车轮速度对比":

import "strings" from(bucket: "opentwins") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r["_measurement"] == "mqtt_consumer") |> filter(fn: (r) => strings.hasPrefix(v: r["thingId"], prefix: "example:mycar:wheel_")) |> filter(fn: (r) => r["_field"] == "value_velocity_properties_value") |> map(fn: (r) => ({ r with thingId: strings.replace(v: r["thingId"], t: "example:mycar:", u: "", i: 2) })) |> keep (columns: ["thingId", "_value", "_time"])

同样的思路可以拼出"当前 GPS 位置""GPS 轨迹""车轮当前方向"等面板。完成后你会得到一张类似下图的驾驶舱式仪表板——到这里,你的第一个数字孪生就算真正"活"了。

夜里复盘:三个最容易卡住的地方

孪生数据不更新,卡在哪一环?用 MQTT Explorer 订阅telemetry/#验证消息是否到达 Mosquitto。若消息根本发不出去,多半是地址/端口配错(注意集群环境下 Mosquitto 默认 NodePort 是 30511)。若消息在但孪生不变,问题出在 Ditto 连接本身,去查看连接日志:http://<ditto-ip>:<ditto-port>/api/2/connections/mosquitto-source-connection/logs(Ditto 的地址要查 nginx 服务)。

Pod 一直 CrashLoopBackOff?大概率是内存不够。kubectl logs <pod-name> --previous看日志确认后,用kubectl edit deployment <名称>调大 resources 限制即可,官方 Helm values 里也给了各组件建议值。

Grafana 连不上 InfluxDB 数据源?kubectl get svc influxdb确认服务在跑,再检查网络策略——数据源地址要用集群内地址(ClusterIP)而不是 localhost,端口是 8086。

把同一套玩法复制到别的行业

这套"类型 → 实例 → 接入 → 可视化"的流水线,换个场景就是换一层皮。比如:

  • 智能制造:把"机器人臂"建模为类型,stateconsumption做特征,PLC 网关数据经 MQTT 流入,Grafana 上搭产线级监控墙;异常时还能用 Kafka-ML 接预测模型做故障预警。
  • 智慧能源:光伏电站按"逆变器"建类型,电量、温度、故障码入 InfluxDB,叠加天气预报数据做发电预测,数据流是"传感器 → MQTT → Ditto → InfluxDB → Grafana/报警系统"。
  • 3D 可视化场景:Unity 把模型导出为 WebGL,借助官方 Grafana 插件嵌入面板,点 3D 模型上的部件就能联动刷新其他面板数据,适合设备拆解演示或运维培训。

接下来该往哪儿走

今天这套最小闭环(部署、类型、实例、数据、面板)对应的官方资料都在项目里可以直接翻:快速开始 docs/docs/quickstart.mdx、架构与概念 docs/docs/overview/architecture.md 与 docs/docs/overview/concepts.md、连接配置 docs/docs/guides/connection-creation.mdx,还有树莓派示例 docs/docs/examples/raspberry-example/raspberry-example.mdx。

想拿到全部源码和文档,克隆仓库即可:git clone https://gitcode.com/gh_mirrors/op/opentwins

建议你按这样的顺序落地:先在本机用今天的五步跑通一个假想设备;再挑一台真实设备把 Ditto Protocol 换成 JavaScript 映射接入;最后才考虑加 ML 预测或 Unity 3D。别一上来就追求大而全——数字孪生的价值是在一次次数据闭环中长出来的,而 OpenTwins 恰好把这条闭环的路修得足够短。

【免费下载链接】opentwinsInnovative open-source platform that specializes in developing next-gen compositional digital twins项目地址: https://gitcode.com/gh_mirrors/op/opentwins

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/20 11:34:02

3 步注册,让 Windows 免费显示 HEIC 缩略图

3 步注册&#xff0c;让 Windows 免费显示 HEIC 缩略图 【免费下载链接】windows-heic-thumbnails Enable Windows Explorer to display thumbnails for HEIC/HEIF files 项目地址: https://gitcode.com/gh_mirrors/wi/windows-heic-thumbnails windows-heic-thumbnails…

作者头像 李华
网站建设 2026/8/20 11:31:02

从84%到38%:中美AI公众态度差异下的技术生态与本地化部署实践

斯坦福AI指数报告最新数据显示&#xff0c;中国公众对人工智能的积极态度高达84%&#xff0c;而美国仅为38%。这一显著差异不仅反映了不同文化背景下对技术发展的认知差异&#xff0c;更揭示了全球AI发展格局中&#xff0c;公众接受度如何成为影响技术落地、产业投资和政策制定…

作者头像 李华
网站建设 2026/8/20 11:29:58

从模糊需求到Web服务:基于Flask与Jieba的文本过滤与标签生成实战

在实际内容创作和技术分享领域&#xff0c;我们经常遇到一种情况&#xff1a;项目或文章的原始输入材料可能非常零散、不完整&#xff0c;甚至包含大量与核心主题无关的“噪音”信息。例如&#xff0c;一个标题可能混杂了粉丝圈用语、免责声明和随机生成的图片描述&#xff0c;…

作者头像 李华
网站建设 2026/8/20 11:25:02

SAP Gateway 与 GenIL 集成中的默认 Query 路由机制,从 Model Provider Class 增强讲透运行时查询选择

在一个已经通过 SAP Gateway 暴露出来的 GenIL 服务里,最容易让开发人员产生错觉的地方,并不是 OData 的 Entity、EntitySet,也不是 $filter 本身,而是后台究竟拿哪一个 GenIL Query 去执行这次查询。 从 OData 消费端观察,一次请求可能只是访问某个 EntitySet,再附带几…

作者头像 李华
网站建设 2026/8/20 11:24:41

2026年三维动画制作费用概览

行业普遍采用按秒计价的方式。以下是不同等级的服务内容和价格区间&#xff1a;等级单价 (元/秒)每分钟总价 (估算)核心特征与应用场景基础演示级150 - 5000.9万 - 3万简模、基础运动、1080P。适合内部培训、简单产品演示、概念沟通。标准商用级500 - 1,5003万 - 9万精细建模、…

作者头像 李华
网站建设 2026/8/20 11:24:32

滤筒除尘器适合什么工况?什么情况下不该用?

在焊接、打磨、激光切割、粉体加工等产尘场景中&#xff0c;滤筒除尘器凭借过滤精度高、占地小、维护便捷等优势&#xff0c;应用越来越广。但任何设备都有适用边界——选对了是高效治理&#xff0c;选错了就是频繁故障、成本失控。本文从适用场景和禁忌工况两个维度&#xff0…

作者头像 李华