当前位置:首页 > 工业控制 > 电路设计项目集锦
[导读]如果你小时候玩过《过山车大亨》,你一定知道那种感觉:你建造一座过山车,向游客开放,然后屏住呼吸,等待游戏计算出刺激度、紧张度和恶心值。太刺激?没人坐。太无聊?也没人坐。准确地获得全部三个数值,才是整个游戏的全部重点。

如果你小时候玩过《过山车大亨》,你一定知道那种感觉:你建造一座过山车,向游客开放,然后屏住呼吸,等待游戏计算出刺激度、紧张度和恶心值。太刺激?没人坐。太无聊?也没人坐。准确地获得全部三个数值,才是整个游戏的全部重点。

我一直好奇真正的 coaster 会得到怎样的评分。我想制作一个可穿戴设备,帮助你揭晓答案。

幸运的是,1962年,梅尔巴·斯通在观察袋鼠时意外发明了这种可穿戴设备的终极收纳装置——臀包。将一个Arduino UNO Q和一个IMU装进臀包里,骑上真正的滑板车,就能在手机上以RCT风格的界面显示你的兴奋度、强度和恶心值。然后像分享你最酷滑板车搭建的截图一样,把结果分享到社交媒体上。

看看这些来自冒险乐园的真实脚垫效果如何!

工作原理

该系统分为三个阶段,其计算评分的方式与原版游戏相同:

记录:你在排队时,手机上按下了开始键。SparkFun ICM-20948 加速度计/陀螺仪以 200Hz 的频率开始采样加速度和旋转信息,并通过内部桥接器将数据从 Arduino UNO Q 的 STM322 微控制器传输至高通 Dragonwing MPU。

流程:骑行结束后,按下停止键。在高通端运行的Python代码会从原始传感器数据中提取骑行的物理指标,例如峰值加速度、横向力、飞行时长等。前几秒的数据(当你站在队列中静止时)用于校准“向下”方向,因此防丢包中IMU的方向并不重要。

预测:提取出的特征将输入三个Edge Impulse回归模型,分别用于兴奋度、强度和恶心感,这些模型均基于实际《过山车大亨2》游戏数据训练。各模型输出0到10分的经典评分,结果以一个看起来直接来自游戏的Web界面进行展示。

入门指南

完整项目可在Arduino项目中心以可直接导入的包形式获取:

RollerCoasterTestMeter 是 Arduino 项目中心

下载 ZIP 文件,然后在 Arduino App Lab 中进入“我的应用”→“创建新应用+”,导入 ZIP 文件。该文件包包含代码、Python 代码、WebUI、第三方库以及预训练的 Edge Impulseulse 模型,您所需的一切内容均已包含在内。

导入后,如果尚未安装,请安装以下草图库:

SparkFun 9轴IMU扩展板 - ICM 20948 - Arduino库

Arduino_RouterBridge(通常已预装)

硬件

是时候收集你的材料了。

组装简单,无需任何工具!UNO Q 采用双脑架构,轻松完成所有复杂任务。STM3222 负责实时传感器采样,而高通 MPU MPU 同时运行 Python、机器学习推理和一个 Web 服务器。无需在公园里携带笔记本电脑。

线路只有一根线缆。SparkFun扩展板连接到UNO Q的Qwiic接口,插入后即可完成。请确保连接到SparkFun板的Qwiic一侧,而不是I2C一侧。

为了固定“外壳”,我使用了3M命令贴片将IMU固定在电池组上,以防止骑行过程中晃动。当然,你也可以使用任何你喜欢的紧固件!整个结构安装在电池顶部,通过一根短USB-C线缆连接。

首先,将魔术贴固定好。然后将USB线连接到Arduino和电池上。

训练模型

这里就变得有趣了。过山车大亨的评分系统并非随机,而是由游乐设施的物理特性决定的确定性函数。克里斯·索耶的原始代码会将最大G力、过山车坡道数量、飞行时间、速度和翻转次数等参数映射为兴奋度、强度和恶心度评分。

得益于诺兰·康奈威(Nolan Conaway)整理的一组数据集(可在GitHub和Kaggle上获取),我们获得了游戏中189种过山车设计的输入特征和输出评分,这便是我们的训练数据。

选择可靠的功能

RCT2数据集包含11个骑行特征,但惯性测量单元(IMU)无法同等准确地测量所有特征。这是项目中最重要的设计决策:我们究竟应该信任哪些特征?

加速度计直接给出的是加速度,而不是速度。要得到速度,必须对加速度进行时间积分,而这种积分会严重漂移。在测试中,一次4分钟的过山车体验估计出的速度高达每小时512英里。再进行距离积分则效果更差。计算下坡、估算下坡高度以及追踪颠簸路段,都需要任意调整阈值,或者依赖陀螺仪积分,而这会导致累积误差。

因此,我们将IMU可测量的特征集缩小为五项,无需进行任何积分或估计:

•最大正向垂直加速度:即你被推入座椅时的极限。直接加速峰值,完全可靠。

•最大负垂直加速度:你感受到的最轻重状态。相同——直接加速度计读数。

•最大侧向G值:转弯时你承受的最大横向加速度。直接读取。

•总时长:处于近失重状态(垂直加速度低于0.5)所花费的秒数。这只是直接读数乘以采样率后的阈值,无需积分。

•骑行时间:骑行持续多久。一个钟表。这一点绝不能搞错。

其他所有内容——速度、距离、掉落次数、掉落高度和翻转次数都被删除了。这带来了一个不错的副作用:原本包含11个特征的数据集有42行缺失翻转数据,我们不得不将其删除。现在仅剩5个特征,全部189行数据均可使用。从更少但更好的特征中获得了更多的训练数据。

准备数据

PythonPythonPython 脚本会清理原始 CSV 文件,并输出三个文件,每个文件对应一个目标分数,格式符合 Edge Impulse 的 CSV Wizard Wizard Wizard 要求。每个文件包含五个特征列以及一个标签列,用于存储数值评分(兴奋度、强度或恶心感)。需要注意的是:强度数据集中有一个异常值,为 44.94,而其他所有数值均低于 10,这很可能是故意设计的糟糕过山车体验。脚本会自动移除该异常值,因为单个极端异常值将彻底破坏基于 189 个样本训练的回归模型。

以下是剧本:

Edge Impulse 设置

由于 Edge Impulse 的回归块每个样本只接受一个数值标签,因此我创建了三个独立的 Edge Impulse 项目(一个用于兴奋感,一个用于强度,一个用于恶心)。

每个流程的工作方式都完全相同:

•通过CSV向导上传CSV文件(不要使用常规上传器,后者需要带有时间戳的时间序列数据)

•使用扁平化处理块和回归学习块创建一个冲动

•在“展开”块中,取消勾选除“平均值”之外的所有选项(因为每个“轴”本身就是一个单一值,而非时间序列),并启用标准缩放(StandardScaler)归一化。

•使用36→16神经元架构训练300个周期

对于关注此事的人,有几点值得说明:

为什么只使用“平均”?Flattenatten 模块专为时间序列数据设计,用于在样本窗口内计算统计量(均值、最小值、最大值、均方根、标准差、偏度、峰度)。但我们的数据已经是表格形式:每一行是一组预计算好的数值,而非时间序列。当 max_speed 是单个数值时,计算“max_speed 的平均值”只会得到……那个数值本身。因此我们只检查 Average,它起到的是直接通过的作用。如果没有这个操作,第一次训练时有 35 个输入特征(5 个轴 × 7 个统计量),其中大部分是冗余的副本或零值。

为什么需要使用StandardScaler归一化?我们的特征尺度差异很大。骑行时间最高可达186秒,而最大横向偏移量max_lateral_gs则最高仅为3.32。如果不进行归一化,网络的梯度更新将主要受幅度最大的特征主导。StandardScaler能将所有特征置于同等水平(均值为0,标准差为1)。这种差异非常显著:未进行归一化的第一个兴奋模型损失为8.32,甚至比猜测均值还要差。而经过归一化后,损失降至0.92。

为什么是36个神经元?由于仅有5个输入特征和189个样本,网络需要保持较小规模,以避免数据记忆。36个神经元的初级层提供了足够的容量来学习特征之间的交互(例如,“高侧向G值结合长时间骑行预测兴奋度高”),而16个神经元的次级层则将这些交互压缩为单一输出。

为什么恶心的损失设为0.001?恶心是学习过程中最难掌握的目标。在默认的学习率0.005下,验证损失持续上升,而训练损失却下降(典型的过拟合现象)。将学习率降至0.001后,模型能够收敛且不会过度拟合。原游戏中恶心与横向加速度和翻转动作高度相关,但由于我们去除了翻转动作,模型可用的信号就减少了。

结果

训练后,三个模型的表现如下:

•兴奋度:MAE 0.71,可解释方差 0.34

•强度:MAE 0.96,可解释方差 0.22

•Nausea:MAE 1.06,可解释方差 -0.57

低于1的MAE表示预测值通常在0到10分的尺度上相差不超过1分。兴奋度和强度表现良好。恶心感较弱,但仍能区分不同游乐项目。

每个模型都是为 Linux(AARCH64,搭载高通 QNN)构建的,生成的 .eim 文件非常小:推理时间仅 111 毫秒,占用 1.22 千字节 RAM 和 10.88 千字节闪存。在 UNO Q 上同时运行这三个模型几乎完全免费。

夹紧真实世界数据

我在公园里发现了一件事:真正的过山车速度比RCT2游戏数据中的数值更极端。一辆名为“怪物”的游乐设施达到了6.71g的垂直加速度和41秒的飞行时间,远超训练数据中记录的最高值6.26g和13.68秒。如果没有安全护栏,模型会严重外推,预测出超过20秒的成绩。

修复方法很简单:在运行推理前,将每个输入特征限制在训练数据中观察到的范围内。这意味着超过游戏物理限制的骑行行为会有效使该特征达到上限。虽然评分在区分极端剧烈骑行时的能力有所下降,但分数仍保持在0到10的范围内,骑行之间的排名也依然合理。

在《过山车大亨》中,只有极少数人的兴奋值超过10,因此这是一种合理的方式,将游戏中的得分映射到真实的过山车上。

构建应用程序

该应用程序使用三个组件在Arduino App Lab中运行。如果你从Arduino项目中心导入了ZIP文件,这些组件已经全部准备就绪,本节将说明各组件如何组合在一起。

草图(STM32 侧)

ArduinoArduinoArduino 软件运行在 STM322 微控制器上,负责实时处理 IMU 采样。它通过 I2C 以 200Hz 的频率读取 ICM-20948,配置为 ±8G 加速度(滑行时可达到 5-6G)和 ±1000°/ss 角速度。采样数据以每 1000 次为一组进行批量处理,并通过桥接器发送,以降低 RPC 的开销。

录制由 Python Python Python 端控制。草图会一直空闲,直到收到 set_recording(true))) 调用,然后开始数据流传输。

PythonPythonPython 端(高通 MPU)

这是操作的核心部分。它通过桥接回调从草图接收IMU数据,运行信号处理以提取5个特征,将这些特征输入到三个.eim模型中,并提供WebUI和API端点服务。

信号处理是其中最有趣的部分。前约20个样本(在骑行者静止时记录)用于建立重力校准向量。之后的每个样本都会投影到该向量上,以确定垂直和横向加速度,无论IMU在腰包中的安装方向如何。这意味着你无需担心安装方向的问题,只需将设备放入腰包中即可使用。

根据校准后的数据,代码提取了五个特征:峰值垂直和横向加速度(直接来自加速度计)、飞行时间(垂直加速度低于0.5的时段)以及飞行时长。

还有一个最低运动阈值:如果最大G力从未超过1.5,且骑行时间少于30秒,应用程序会提示你没有足够的骑行数据,而不是给出静坐评分。当我第一次测试到可用版本时,它竟然愉快地将一张静止的办公桌评为6.21分刺激度,我才真正体会到这一点。

WebUI

界面是对RCT用户界面的致敬。游戏标志性的棕红色调、倒角窗框,以及来自游戏的骑行数据窗口布局。三个评分既以带标签的文字形式(例如“8.51(非常高)”)显示,也以动态进度条的形式呈现。

分享按钮使用 html2canvascanvas 抓取结果面板并保存,以便您可以在喜爱的社交媒体平台上分享。

带它去公园

在 App Lab 中,为应用启用自动启动选项,使其在开机时自动运行。然后将热点设置为自动连接。UNO Q Q 可独立运行 WiFi WiFi WiFi 热点,无需手机 tethering 或路由器。只需一条命令即可完成设置:

通过 systemd 服务实现自动启动,且热点设置为开机自动连接,公园工作流程如下:

•插入电池

•请等待60秒

•将您的手机连接到“RCT-IRL”WiFi

•打开书签

•点击队列中的开始按钮,静止2-3秒进行校准

•乘坐过山车

•开始步行或爬楼梯前,请先在应用中点击停止。

•查看并分享你的成绩

公园日比赛结果

我带着设备去了冒险乐园,骑了三辆过山车。以下是模型们的看法:

怪物:兴奋度8.51,强度10.00,恶心感6.20。当天最刺激的体验,也是我绝对最爱的一次!

Outlaw:兴奋度9.01,强度10.00,恶心感5.64。这是所有过山车中横向G值最高的,达到5.18g——每转一次都让你感受到强烈的冲击。兴奋度略高于Monster,强度相当,但恶心感更轻。

龙卷风:兴奋度10.00,强度9.32,恶心5.64。尽管正向加速度(Gs)最低(2.43),但负向加速度(Gs)最强(-2.17),且骑行时间长达5分钟,堪称经典之作!

这些模型在骑行体验上有着明显差异:Monster 最具身体强度,Outlaw 在刺激感与强度之间达到了最佳平衡,而 Tornadoornado 则凭借持续的飞行时间和负重力加速度,在纯粹的刺激感方面表现最出色。

本文编译自hackster.io

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
换一批
延伸阅读

这是一个DIY手持式Arduino游戏机,由Arduino UNO R4 WiFi驱动。它在一块0.96英寸的SSD1306 OLED显示屏(128×64像素)上运行10款复古风格的街机游戏,通过四个触控按钮进行控制。配...

关键字: Arduino Wi-Fi 升压转换器

创建一个安全且自动化的门锁与解锁机制,通常通过密码等输入方式来控制。

关键字: 伺服电机 LCD Arduino

风力涡轮机的安全高效运行至关重要,但其人工监控并不实用。本项目开发了一套智能风力涡轮机监控系统,可根据风况自动控制涡轮机的伺服位置,并实时感知风暴、野生动物、振动等环境风险,通过手机向您发送电子邮件,及时通知您。

关键字: 风力涡轮机 Arduino 传感器

过去几个月里,我一直在设计自己的开发板,以充分发挥其性能。如今,我正在使用WCH的CH32V003F4P6芯片,对这款微控制器所提供的功能和性能感到非常惊叹。我之所以从Arduino转而选择它,是因为这是一款32位RIS...

关键字: 开发板 Arduino CH32V003F4P6

空气污染是全球日益严峻的问题,细颗粒物(PM2.5)因其能够深入肺部并进入血液,成为最危险的污染物之一。无论您担心的是室内空气质量、野火烟雾还是城市污染,掌握实时数据都能让您采取有效行动。

关键字: PM2.5 传感器 Arduino

该项目提供了一套高效、远程遥测记录系统,用于跟踪离网太阳能系统的发电与耗电情况。通过利用Arduino Pro Mini 3.3V的超低静止电流特性,该记录器最大限度地降低了系统开销,确保监控硬件本身不会耗尽电池储备。

关键字: 太阳能 Arduino INA219

在搭建显示屏(使用Arduino和硬件)时,我常常感到沮丧:需要刷写程序、线缆可能损坏、导线松脱,或者板子突然烧坏。最终我可能只能花10到20秒(如果运气好)来测试一下,把字体向左移动三个像素是否“感觉正确”。

关键字: 显示屏 Arduino Python

我从事电能计量IC的研发已有段时间。在尝试了接口较为简单的BL0937之后,今天终于拿到了BL0940。两者在结构上相似,都是单相电能计量IC,但最让我感到意外的是其功能特性。与BL系列中较为简单的BL0937不同,BL...

关键字: Arduino 交流电能 BL0937

DS18B20 是一种数字温度传感器,有两种版本:小型 TO-922 包装版和防水型,后者通常被金属管封装,并配有长电缆。两者均能提供数字温度读数,适用于多种室内外项目。DS18B20 采用了一种称为“单线通信”(1-W...

关键字: Arduino DS18B200 温度传感器

作为创客,我们常常会看到满堆的损坏电子设备,等待着被重新利用。与其直接丢弃这些废弃物品,我决定将一部旧的、损坏的智能手表改造成一个功能齐全、小巧如钥匙扣的游戏主机。我的目标是打造一个体积微小却极具娱乐性的装置,同时通过回...

关键字: 智能手表 ESP32 Arduino
关闭