返回 BIM 与 IFC 博客
公交总站很适合检验数字孪生,因为它的状态每分钟都在变化:十七个停靠位,公交车进进出出,车门开开合合。如果模型能用公开数据实时展示这些,它就能展示大多数东西。
这个场景在 Elielinaukio(埃利尔广场)实现了这一点,这是位于赫尔辛基中央火车站西侧的公交总站。真实的公交车停靠时,IFC 模型中对应的停靠位就会亮起,上方悬浮显示线路号。位置数据来自赫尔辛基地区交通局(HSL),它通过 MQTT 大约每秒发布一次每辆车的位置,浏览器直接订阅。
要点
- 只要 broker 允许,MQTT over WebSocket 就能让网页接收实时车辆位置,中间无需自建服务器。HSL 的 broker 允许这样做。
- 订阅范围要窄。只订阅主题树中的一个地理切片,到达浏览器的就只有这个总站的公交车。
- 停靠位绑定到交通部门的站点 ID,颜色根据消息中的字段按规则变化:车门打开、停靠、行驶中或无车。
- 只要其他每个模型都按各自的地理配准旋转,整合模型就能保持对齐。这里大教堂的坐标框架与总站相差 3°。
试一试:此刻赫尔辛基的公交车
在地图上打开公交总站、火车站和大教堂。真实公交车到站时,停靠位就会亮起。夜间车很少,停靠位会长时间保持灰色。

打开交互式 IFC 查看器
你看到的是什么
三个经过地理配准的 IFC 模型(ETRS89 / GK25,EPSG:3879),位于 OpenStreetMap 生成的城市之中:Eliel Saarinen 设计的中央火车站及其站台、议会广场上的大教堂,以及拥有 17 个停靠位(20 至 36 号)、站杆、标牌和雨棚的公交总站。芬兰气象研究所的两个实时图层显示空气质量和天气。
公交车来来往往时的停靠位:每根站杆和每块标牌都会显示该站点公交车当前状态所对应的颜色。
| 停靠位颜色 | 针对 HSL 消息的规则 | 含义 |
|---|
| 绿色 | 车门打开(drst = 1) | 上客 |
| 蓝色 | 速度低于 0.5 m/s | 停在停靠位上 |
| 琥珀色 | 该站点的其他任何读数 | 正在进站或出站 |
| 灰色 | 45 秒内没有读数 | 无车 |
第一条匹配的规则生效。线路号(desi)悬浮在停靠位上方。
为什么用 MQTT,而不是 GTFS-Realtime
GTFS-Realtime 是实时公交数据的常用格式,HSL 也有发布。但这个数据源不发送浏览器跨站读取所需的 CORS 头,用它就意味着要运行一个代理。高频定位数据源则不同:它是 MQTT over WebSocket,公开、无需密钥,任何网页都能访问。
就这个用途而言,它的信息也更丰富。每条消息对应一辆公交车,大约每秒一条,包含线路、速度、车门状态和所在站点[hfp]。主题本身就说明了公交车的位置,因此订阅可以只截取城市的一个切片:
/hfp/v2/journey/ongoing/vp/bus/+/+/+/+/+/+/+/+/60;24/19/73/#
逐级拆解的订阅主题:每个 + 匹配任意值,geohash 则把数据流缩小到总站周围的单元格。
最后一段 60;24/19/73 是 HSL 地理网格中覆盖总站的一个单元格。浏览器只接收该单元格内的公交车,其余一概不收。它每秒读取一次消息,并为每个站点保留最新的一条。行驶在站点之间、消息中没有站点的公交车会被跳过。
从站点 ID 到停靠位
HSL 用编号标识站点,IFC 模型用名称。HSL 公布的站点列表把两者联系起来:十七个停靠位中目前有九个对应 HSL 站点,每个对应一个绑定。构件按名称查找,如“Bay 20”等,这样就能找到每个停靠位的站杆和三块标牌。
| 停靠位 | HSL 站点 ID |
|---|
| 20 | 1020128 |
| 22 | 1020131 |
| 23 | 1020133 |
| 24 | 1020135 |
| 25 | 1020132 |
| 26 | 1020239 |
| 28 | 1020243 |
| 29 | 1020245 |
| 30 | 1020130 |
取自 HSL 的 GTFS 站点列表,在编写场景时读取一次。其余八个停靠位没有对应站点,始终保持灰色。
夜间停靠位的详情卡片:停靠位没有公交车时,实时区域会如实显示,而不是展示旧读数,并与站杆的 IFC 数据并列。
{
"id": "hsl-hfp-elielinaukio",
"url": "wss://mqtt.hsl.fi:443/",
"topics": ["/hfp/v2/journey/ongoing/vp/bus/+/+/+/+/+/+/+/+/60;24/19/73/#"],
"mapping": { "idField": "VP.stop", "timeField": "VP.tst" }
}
要读取另一支车队或另一个区域,只需改动这个设备数据源:一个支持 MQTT over WebSocket 的 broker、主题,以及消息中用来识别设备的字段。场景的其余部分保持不变。
空气质量与天气
两个地图图层来自芬兰气象研究所的开放数据[fmi],在浏览器中以简单 WFS 要素的形式读取:我们查看时,城市周边有 11 个空气质量监测站和 7 个气象站。空气质量每小时更新,最多可能延迟 40 分钟;天气每 10 分钟更新一次。
三个模型,一张地图
火车站、大教堂和公交总站是三个独立的文件,各自带有自己的地理配准。大教堂的局部坐标轴与作为地图锚点的公交总站相差 3°。如果查看器只把其他模型平移到位而不旋转,大教堂就会歪斜 3°,其角部偏离约 2 m。
查看器会让每个模型绕自身中心旋转到各自的坐标框架。与 OpenStreetMap 中大教堂的轮廓比对,现在墙体与轮廓相距 0.56 m,角度偏差 0.37°。这点残差反映的是模型和 OSM 各自绘制这座建筑的精度。
需要明说的局限
- 这些模型是根据公开资料绘制的示意模型,不是测绘成果。
- 只有九个停靠位对应 HSL 站点,其余八个永远不会亮起。
- 夜间运营的公交车很少,停靠位会长时间保持灰色。
- 这里使用的全球地形数据比芬兰高程系统高出约 18 m,因此模型立在地形表面上,而不是位于其标注的高程。模型之间的相对高度保持不变。
- 后台标签页接收消息的频率较低,因为浏览器会放慢隐藏标签页中的计时器。
同样的场景格式还在巴塞罗那开放数据孪生中用共享单车和充电数据驱动一座城市广场,在基于 ODPT 的东京交通孪生中用列车和有轨电车数据驱动两座东京车站。如果孪生的数据来自传感器而不是交通数据源,请参阅 Web 数字孪生中的实时 LiDAR。
IFC 模型上的实时公交:基于 MQTT 的公交总站数字孪生