加速度计是一种测量设备正确加速度的设备。
我正在尝试使用在单轴上来回移动的加速度计的输出来计算其当前位置。 我尝试过使用欧拉积分,但是速度和位置呃......
有一个 C 函数,获取加速度传感器(MEMS IMU)的 x,y,z 加速度值作为输入,并以 z 轴与重力对齐的方式计算旋转矩阵...
您知道我在哪里可以找到根据 IMU(惯性测量单元,加速度计 + 陀螺仪 + 磁力计)数据进行速度估计的代码/示例吗? 我根据 IMU 所在的数据计算了偏差
陀螺仪和加速计传感器有缺陷。因此,需要这些传感器的功能无法工作,例如自动旋转、指南针、翻转嘘声、翻转相机自拍和游戏
我正在尝试结合加速度计和陀螺仪的数据来精确测量物体的俯仰角和偏航角。在研究了互补滤波器并尝试实现之后......
我正在开发一个个人项目,该项目通过 Android 手机控制汽车。 我想让用户只需倾斜手机就可以控制汽车,所以我选择使用 Sen...
在我的iPhone游戏中(我使用的是cocos2d,应该不会产生很大的差异)我想像这样: 您使用加速度计在屏幕上移动精灵/玩家,加速度为您...
我想知道如何使用加速度计计算步数。实际上我计算加速度并使用此代码来计算步数 长度 = sqrt(x * x + y * y + z * z); 如果(长度>=2){
我的项目使用的是 mpu 6050 芯片,到目前为止效果很好。我读取四元数并通过蓝牙将其数据发送到我的电脑。 我现在需要的是震动检测。在mpu的数据表中...
我正在制作一个游戏,我需要知道手机在横向时是否向上倾斜(朝向天空)或向下倾斜(朝向地面)。 我已使用此答案答案链接作为我的起点...
我正在通过 openFrameworks 和 ofxKinect 访问 c++ 中的 Kinect 加速计,并且在某些角度上遇到一些问题。如果我将 kinect 向下倾斜 90 度,我会得到 nan 值。我有一个...
我正在执行一项任务,需要检测手机跌落。下面是我正在使用的代码,但它不符合标准。它仅检测到十分之一。有什么办法可以优化下面的代码吗? @
我试图将加速度计数据(以 100Hz 的频率采样)分类为 4 种不同的运输模式(0、1、2、3)。我有 41 个不同的 CSV 文件,每个文件代表一个时间序列。我...
使用 Javascript 检测摇动事件,适用于所有主要浏览器/设备(iOS、Android)
我读过Javascript。监听 iPhone 震动事件?检测 html5 mobile 中的晃动,这为检测手机“晃动”事件提供了一个很好的解决方案: <p>我已经阅读了<a href="https://stackoverflow.com/questions/2202216/javascript-listen-for-iphone-shake-event">Javascript。监听 iPhone 震动事件?</a> 和 <a href="https://stackoverflow.com/questions/12334160/detecting-shaking-in-html5-mobile">Detecting shake in html5 mobile</a> 这为检测手机“震动”事件提供了一个很好的解决方案:</p> <pre><code><script src="shake.js"></script> <script> var myShakeEvent = new Shake({threshold: 15, timeout: 1000}); myShakeEvent.start(); window.addEventListener('shake', function() { alert('shake!'); }, false); </script> </code></pre> <p>不幸的是,这似乎不适用于最新的 iOS 设备,并且 <a href="https://github.com/alexgibson/shake.js/issues/53" rel="nofollow noreferrer">此问题</a> 表明应为最新的 iOS 版本授予特殊权限。请注意,<a href="https://dev.to/li/how-to-requestpermission-for-devicemotion-and-deviceorientation-events-in-ios-13-46g2" rel="nofollow noreferrer">此处的代码</a>在 shake.js 库中不容易使用。</p> <p><strong>问题:截至 2022 年,有哪种方法可以使用 Javascript 检测“摇动”事件,适用于主要浏览器(Firefox、Chrome、Safari)和移动设备(iOS、Android)?</strong></p> <p>如果首先出现一个请求许可的弹出窗口(例如请求地理定位请求许可的弹出窗口),那就可以了。</p> </question> <answer tick="true" vote="6"> <p>不存在 <pre><code>shake</code></pre> 事件:存在的最接近的事件是 <a href="https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent" rel="noreferrer"><pre><code>devicemotion</code></pre></a>。</p> <p>根据您问题的内容,我推断您只想订阅当设备加速度超过特定阈值时触发的事件,并在可能的触发器之间有一个去抖延迟(超时)。</p> <p>使用您链接到的“shake.js”库作为参考,我编写了一个 TypeScript 模块,您可以使用它来完成基本相同的事情。它包括在启动时获得用户权限批准,但请记住,您必须调用 <pre><code>ShakeInstance.start()</code></pre> 方法来响应用户启动的事件(例如单击按钮)。</p> <blockquote> <p>注意:您根据 MDN 相关文档页面上的兼容性数据列出的环境支持模块中使用的方法。 (值得注意的是,桌面版 Safari 根本不支持 DeviceMotionEvent。)但是,我无法访问您列出的所有环境组合以便自己执行测试,因此我将其留给您。</p> </blockquote> <p><a href="https://www.typescriptlang.org/play?noUncheckedIndexedAccess=true&target=99&useUnknownInCatchVariables=true&exactOptionalPropertyTypes=true#code/GYVwdgxgLglg9mABBATgUwIZTQUQG5phSIA8AKgJ4AOaiaAHtmACYDOirUKMYA5gDSIAImigYYAGwB8ACgCwAKESIo1NAC5ElGv0XLmo8RM0ixk3QoCUmgMIhOcALb5CUEqaNTEAMkQBvVRpNbTQAX389RHQoEBQkMDQAd0Q7B2cCIhlAtEE-AzMJUMtEDHZUqCcXIndDSS9fALVgtVCAbkVQxUVQSFgERF5RAFkMegBBCAg0CTQULHgkGTQMqBNlmCmhuD6wKqhrRDAQRwAjWYilRBniR1HEAF5EAAZ2y5hgRCWVgDoMSenZvMEMU-JFlMA4ChPhAEJxEABrNAURBwD4AbQA5PQMYIMRQcYgMQAvDEAXRK7BhYE4ILBymQsOIeAwEhAtEeIygAAtfidWF9XL9-jM5js0YiKOSAPxS56WV70+nvT7M1m0Ly3ejFTUPRCqtkK+mdS7G5TRWJITWvY2KBhUSHEbKIADKXIwiL2QiwGF1IjwGzQWx2e1edodKjULrdHpWuvKlRWJFd7twKy9Ynq-mymgxrGjaAxbVt9HtKEdkeTMdcABkYJxCOdHgKiJpK6nXMV7l48HAYMxXsXS+WaFGUwB5Kg7diPUGXAD0ACoF2CF4ghjwYI5jiVhYCdoc0GgDMwVHBEMw61QsBAuSUkMtXOoV4hHKJZuwaFDWGgqSfWABHEAMHQE8ZEcOdWAAJssb4V2fLkoCgKhWHUOc5wMAgJDgT9vkcOAiUkCQMG+SFeDnQgAFoAFVnXQuAIFYOcAHU0BOOcxgABQASTnP0AyDBY9jnP4phFIEwBXOdIm5dA8zgCRmE0I5TlmQ1F2XS5EFXMZgGwKEfTzFM6FjOtz0va8uSPQRWBAPk0EA1xjNcdhEkIw5tkQM4zNYK8oBvI9n3AWAJBKXTzh9ZhYnEgZ0Cwc5uQwJBIToQCWVPFQuVM-VaDAwi6x-BA2BgyTpM3NA4BAVZDmOM4UGtAcFDDMtkCI1h2DbOhGEINhED2MhgMGYhZ2UABiDAqCoFA4AIZgpU0E44HkzAwENEaZLQOSFNbfMJynTF1s25gyVW2BXwqqq212hZWH2srzuOyI1rK50xEcKglJq1SukuKlOBQEBoGSmRsKnObEA44DYBZJMdsna6pFpTSOBAT8ZHlOlfqGullAOrl5JPR4AEYAFYLEVHG7sq3VCaeWmyaNXUQeuxAZX8Iske5OtvjWrlZLxhTdVx-HDRxzLWG507yqpx5JfOkWMq5p7XxejA3sFyniFXCjCcNU1EEiNDEAAASgVgKJgXgwEhNBIgwZhmD2Wt6wSKF5A5ppCUMxEcTpCQ6yYWZtpTR3-YbKEAB9qokCR6eUJnYTBhalsSxBI7Ge2Q+d2YrthSIDh7PsLkVJ0xhQXhCd1CG5lfPTWBIPqBtETE7YdlYnYDlAySkNFCdJeWbJwlvM47rI1EEP2s-09hS-LwR4+pdGTW+-RzL8rk9k+B8W1HKsiAOJOZhT4b6XNOJkZwi8fIsvZm32XXl8QQ2TbNi2rfQSJ0Dwghh7Dz46WzT2+YfZIwgCyCQJw-jwiDrvKA7df6RyONHWOKI4YJ00D-F2OdqSp08otQ+ElLj517CeY+ONIwzwro8Kuqs3woDrg3MuTcMSf2mu2IgcCXZdx7n3OkA9ZjfBYd-NuocXajx0MgMBECIDwgpIgChc9UEL3vgoW2rAKCQBKBNKaBBPgHA4lNRw+USAH2Wl4UhiBlRiPKh8Tm4sxpaNYQTe4jwMTgAMMAHgR4MSI3JhYj4MgACEMgMR8U2NsQSKwMQWKQK5FgcBEiWGKKfJAtjubjUmo43UwAWTfnljjFAyJzHF0jBxWYhi2oLAAEr2TZJwAAYkgJsnYvD6KcEY0pKBymsAWCrbAUg8n0idEIIYOBBZqFRMIdYYTgyxgaFEGpG0oAdK6QsTQyy6zdIQNUhy9SkDs18coSx2QJkyFCYGcJCAN6lGECMmC6AdlLLKRshYDxnGEh6NABY3ii4HOUJjRAn4VkIF6eyEoiRxDEFOVM85MzHLXOGTgO5CzODrIqQgNGAzi5izSQ4maupAXPOBWIbAryXG8DmEQLxmLEB618dMb8Cs7HpO0UeQW-00ADNpfSUBa8fm+NSfYjJeLHjZIkLk7GNK6RcuSYynFQqjzKMem6FgMwzkCX6E2LeVU1UXN2CsIhhcux8oZNSYgF5gAfEeFq74ksVZqworKpWaA7VUHlpY81HwSCOtlpVJJogLTy3+SJaYupBojHGLuUUCxb6L0VJY4NIUvUCqFgpP1MQ4jy2Tc9V6VBdTWttTmzN2LL6+RvDfVAmBsA31zEAwQWrEm6wasoUo6iIAcDEM1NGayDFGJMYlMxGNGSaPlQTMFELZXMtYRiukliAmTpmmmi0iBRXiqRrE5g8TfgZ2EZPYJGEAx4R2ASAVyrmCquheqsAsaT7+rPlwA0kQbSXAcLmrtepiHGvXZuwRbDYEiNmHu6Fh6vmCBPYlM9aAdU7GvcaJ9314MqMQ4oNCKHUNofQxhzDWHsM4dwyh5Dc5EBUW-E+RD-yvagoSMkNsMgAi8w2vzRSiASagY1poGmtMigNQo1u1uNZ-0oGCRRgkywHgDp+rCJa3wsK8GCW2AJIm8DfHyEYG12bVZUDrUplTkghSiT3AsReXHvr-JOJVCojTzz0WOIKQaOAZiviIAAIQoFxZgQmO1QG8Q1SxZnELAh+X5izvGMEAYxBAP20iCQto0WjMTxqg24tZY8DA4KYDEB45wSG06QFDovHgXUG6IA2aIN8BazAKC-Amt1GwmUFIyCKyVqA3wK1xXs2gRzUA90wDwN469K8lPYEYDYBATBiCPAAAZjCS0xgAJH4F63A+AyHnUeSwoQJvyyCwgARHWp0wdyAgKYmh71hCM4oIAA" rel="noreferrer">TS游乐场</a></p> <pre><code>function createEvent <Type extends string, Detail>( type: Type, detail: Detail, ): CustomEvent<Detail> & {type: Type} { return new CustomEvent(type, {detail}) as CustomEvent<Detail> & {type: Type}; } function getMaxAcceleration (event: DeviceMotionEvent): number { let max = 0; if (event.acceleration) { for (const key of ['x', 'y', 'z'] as const) { const value = Math.abs(event.acceleration[key] ?? 0); if (value > max) max = value; } } return max; } export type ShakeEventData = DeviceMotionEvent; export type ShakeEvent = CustomEvent<ShakeEventData> & {type: 'shake'}; export type ShakeEventListener = (event: ShakeEvent) => void; export type ShakeOptions = { /** * Minimum acceleration needed to dispatch an event: * meters per second squared (m/s²). * * https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent/acceleration */ threshold: number; /** * After a shake event is dispatched, subsequent events will not be dispatched * until after a duration greater than or equal to this value (milliseconds). */ timeout: number; }; export class Shake extends EventTarget { #approved?: boolean; #threshold: ShakeOptions['threshold']; #timeout: ShakeOptions['timeout']; #timeStamp: number; constructor (options?: Partial<ShakeOptions>) { super(); const { threshold = 15, timeout = 1000, } = options ?? {}; this.#threshold = threshold; this.#timeout = timeout; this.#timeStamp = timeout * -1; } // @ts-ignore addEventListener ( type: 'shake', listener: ShakeEventListener | null, options?: boolean | AddEventListenerOptions ): void { type Arg1 = Parameters<EventTarget['addEventListener']>[1]; super.addEventListener(type, listener as Arg1, options); } dispatchEvent (event: ShakeEvent): boolean { return super.dispatchEvent(event); } // @ts-ignore removeEventListener ( type: 'shake', callback: ShakeEventListener | null, options?: EventListenerOptions | boolean ): void { type Arg1 = Parameters<EventTarget['removeEventListener']>[1]; super.removeEventListener(type, callback as Arg1, options); } async approve (): Promise<boolean> { if (typeof this.#approved === 'undefined') { if (!('DeviceMotionEvent' in window)) return this.#approved = false; try { type PermissionRequestFn = () => Promise<PermissionState>; type DME = typeof DeviceMotionEvent & { requestPermission: PermissionRequestFn }; if (typeof (DeviceMotionEvent as DME).requestPermission === 'function') { const permissionState = await (DeviceMotionEvent as DME).requestPermission(); this.#approved = permissionState === 'granted'; } else this.#approved = true; } catch { this.#approved = false; } } return this.#approved; } #handleDeviceMotion = (event: DeviceMotionEvent): void => { const diff = event.timeStamp - this.#timeStamp; if (diff < this.#timeout) return; const accel = getMaxAcceleration(event); if (accel < this.#threshold) return; this.#timeStamp = event.timeStamp; this.dispatchEvent(createEvent('shake', event)); }; async start (): Promise<boolean> { const approved = await this.approve(); if (!approved) return false; window.addEventListener('devicemotion', this.#handleDeviceMotion); return true; } stop (): void { window.removeEventListener('devicemotion', this.#handleDeviceMotion); } } </code></pre> <p>像这样使用:</p> <pre><code>const shake = new Shake({threshold: 15, timeout: 1000}); shake.addEventListener('shake', ev => { console.log('Shake!', ev.detail.timeStamp, ev.detail.acceleration); }); // Then, in response to a user-initiated event: const approved = await shake.start(); </code></pre> <blockquote> <p>我不确定 SO 片段环境是否会导致演示出现问题,但我已经包含了 TS Playground 链接中已编译的 JS,以防万一:</p> </blockquote> <p></p><div data-babel="false" data-lang="js" data-hide="true" data-console="true"> <div> <pre><code>"use strict"; function createEvent(type, detail) { return new CustomEvent(type, { detail }); } function getMaxAcceleration(event) { let max = 0; if (event.acceleration) { for (const key of ['x', 'y', 'z']) { const value = Math.abs(event.acceleration[key] ?? 0); if (value > max) max = value; } } return max; } class Shake extends EventTarget { constructor(options) { super(); this.#handleDeviceMotion = (event) => { const diff = event.timeStamp - this.#timeStamp; if (diff < this.#timeout) return; const accel = getMaxAcceleration(event); if (accel < this.#threshold) return; this.#timeStamp = event.timeStamp; this.dispatchEvent(createEvent('shake', event)); }; const { threshold = 15, timeout = 1000, } = options ?? {}; this.#threshold = threshold; this.#timeout = timeout; this.#timeStamp = timeout * -1; } #approved; #threshold; #timeout; #timeStamp; // @ts-ignore addEventListener(type, listener, options) { super.addEventListener(type, listener, options); } dispatchEvent(event) { return super.dispatchEvent(event); } // @ts-ignore removeEventListener(type, callback, options) { super.removeEventListener(type, callback, options); } async approve() { if (typeof this.#approved === 'undefined') { if (!('DeviceMotionEvent' in window)) return this.#approved = false; try { if (typeof DeviceMotionEvent.requestPermission === 'function') { const permissionState = await DeviceMotionEvent.requestPermission(); this.#approved = permissionState === 'granted'; } else this.#approved = true; } catch { this.#approved = false; } } return this.#approved; } #handleDeviceMotion; async start() { const approved = await this.approve(); if (!approved) return false; window.addEventListener('devicemotion', this.#handleDeviceMotion); return true; } stop() { window.removeEventListener('devicemotion', this.#handleDeviceMotion); } } //////////////////////////////////////////////////////////////////////////////// // Use: const shake = new Shake({ threshold: 15, timeout: 1000 }); shake.addEventListener('shake', ev => { console.log('Shake!', ev.detail.timeStamp, ev.detail.acceleration); }); const button = document.getElementById('start'); if (button) { button.addEventListener('click', async () => { const approved = await shake.start(); const div = document.body.appendChild(document.createElement('div')); div.textContent = `Approved: ${String(approved)}`; button.remove(); }, { once: true }); }</code></pre> <pre><code><button id="start">Approve</button></code></pre> </div> </div> <p></p> </answer> <answer tick="false" vote="1"> <h2>使用纯 JS 进行设备震动检测,无需库</h2> <p>通用震动检测的尝试。</p> <p>对于非 iOS:第一次摇动会向用户显示权限提示,要求允许使用传感器。</p> <p>对于 iOS(或任何对 <pre><code>requestPermission</code></pre> API 严格的设备):在用户体验中需要一个额外的步骤。用户必须自己调用传感器权限提示,而不是在第一次摇动时自行出现权限提示。这是通过您在体验中的某个位置(可能是在工具栏或模式中)提供一个按钮来完成的,其中该按钮调用 <pre><code>requestPermission</code></pre> API。</p> <p>除了上述之外,您还需要将其托管在 HTTPS 服务器上(我使用了 <pre><code>github-pages</code></pre>)。我也让它在 <pre><code>localhost</code></pre>/local-wifi 上工作,但那是另一个线程。对于这个问题,我会避免在在线 IDE(如 Codepen)中测试它,即使它们是 https,<pre><code>requestPermission</code></pre> 可能不起作用。</p> <p><strong>建议:</strong>无论您做什么,在您的应用程序(或网站)中,如果您独立存储用户的状态(即他们是否允许许可),那就太好了。如果他们点击“取消”,那么您可以可靠地知道这一点,并可能定期告诉他们“嘿,您错过了这个很棒的功能!”根据您的经验,并再次提供权限提示(通过显式 UI 控制)。</p> <p><strong>HTML</strong></p> <pre><code><button id="btn_reqPermission" style="display: none;padding: 2em"> Hey! This will be much better with sensors. Allow? </button> <div id="output_message"></div> </code></pre> <p><strong>Javascript:</strong></p> <pre><code>// PERMISSION BUTTON var btn_reqPermission = document.getElementById("btn_reqPermission") btn_reqPermission.addEventListener("click", () => { this.checkMotionPermission() }) // ON PAGE LOAD this.checkMotionPermission() // FUNCTIONS async function checkMotionPermission() { // Any browser using requestPermission API if (typeof DeviceOrientationEvent.requestPermission === 'function') { // If previously granted, user will see no prompts and listeners get setup right away. // If error, we show special UI to the user. // FYI, "requestPermission" acts more like "check permission" on the device. await DeviceOrientationEvent.requestPermission() .then(permissionState => { if (permissionState == 'granted') { // Hide special UI; no longer needed btn_reqPermission.style.display = "none" this.setMotionListeners() } }) .catch( (error) => { console.log("Error getting sensor permission: %O", error) // Show special UI to user, suggesting they should allow motion sensors. The tap-or-click on the button will invoke the permission dialog. btn_reqPermission.style.display = "block" }) // All other browsers } else { this.setMotionListeners() } } async function setMotionListeners() { // ORIENTATION LISTENER await window.addEventListener('orientation', event => { console.log('Device orientation event: %O', event) }) // MOTION LISTENER await window.addEventListener('devicemotion', event => { console.log('Device motion event: %O', event) // SHAKE EVENT // Using rotationRate, which essentially is velocity, // we check each axis (alpha, beta, gamma) whether they cross a threshold (e.g. 256). // Lower = more sensitive, higher = less sensitive. 256 works nice, imho. if ((event.rotationRate.alpha > 256 || event.rotationRate.beta > 256 || event.rotationRate.gamma > 256)) { this.output_message.innerHTML = "SHAKEN!" setTimeout(() => { this.message.innerHTML = null }, "2000") } }) } </code></pre> </answer> </body></html>
我正在 Unity iPhone 应用程序上读取陀螺仪,但无论我移动手机,它都会返回相同的值,它返回的值始终是常量值 (0.00000, 0.00000, 0.70711, -0.70711)。 我正在读它
将来自 Arduino 的加速度计和陀螺仪数据转换为 iOS SCNNode 位置和旋转
上下文: 我有一个 Arduino Nano RP2040 Connect 设备,它有一个内置的 IMU。 我还编写了一个 iOS 应用程序,它利用 SceneKit 并可以渲染/动画化 SCNNode。 目标 我想移动我的 Arduino
在 python 中使用 tflite 模型从 arduino nano 33 ble 读取加速度计和陀螺仪数据并预测所做的手势
我已经为 5 个手势训练了一个使用加速度计,在下载转换后的 tflite 模型供使用后,我遇到了无法调整输入数据大小的错误消息...
iPhone 加速度计/磁力计可以用来检测物体何时反转方向吗?
我正在尝试为一个应用程序编写代码,当 iPhone 连接到设备时,它可以检测设备何时反转方向。 到目前为止,我一直专注于尝试提取速度
我正在尝试通过融合来自加速度计、陀螺仪和磁力计的数据来确定 R3 中刚体的姿态。 我采用了“Op ...
我想检测 iPad 的小动作,比如当它被拿起时。 这可能与未运行但刚刚安装的应用程序有关吗?就像它在后台运行一样......