如何使用 SensorManager.getOrientation 进行倾斜控制,例如“我的纸飞机”?

发布于 2024-10-10 07:08:35 字数 2120 浏览 3 评论 0原文

Android 游戏我的纸飞机 是如何实现倾斜控制的一个很好的例子,但我一直在努力理解如何做类似的事情。

我有以下示例,该示例使用 SensorManager 中的 getOrientation() 。整个内容都在pastebin 这里。它只是将方向值打印到文本字段。这是最相关的片段:

private void computeOrientation() {
    if (SensorManager.getRotationMatrix(m_rotationMatrix, null,
                                        m_lastMagFields, m_lastAccels)) {
        SensorManager.getOrientation(m_rotationMatrix, m_orientation);

        /* 1 radian = 57.2957795 degrees */
        /* [0] : yaw, rotation around z axis
         * [1] : pitch, rotation around x axis
         * [2] : roll, rotation around y axis */
        float yaw = m_orientation[0] * 57.2957795f;
        float pitch = m_orientation[1] * 57.2957795f;
        float roll = m_orientation[2] * 57.2957795f;

        /* append returns an average of the last 10 values */
        m_lastYaw = m_filters[0].append(yaw);
        m_lastPitch = m_filters[1].append(pitch);
        m_lastRoll = m_filters[2].append(roll);
        TextView rt = (TextView) findViewById(R.id.roll);
        TextView pt = (TextView) findViewById(R.id.pitch);
        TextView yt = (TextView) findViewById(R.id.yaw);
        yt.setText("azi z: " + m_lastYaw);
        pt.setText("pitch x: " + m_lastPitch);
        rt.setText("roll y: " + m_lastRoll);
    }
}

问题是这个吐出的值看起来像是无意义的,或者至少没有办法隔离用户执行的运动类型。我画了一个图表来指示我想要检测的两种运动类型 - 1.“倾斜”表示俯仰,2.“旋转”表示滚动/转向

: sstatic.net/ylWJb.png" alt="图 1. 俯仰和滚动">

(当然,这是手机在横向模式下的等距视图)

当我沿着手机的长轴向前和向后倾斜手机时 - 如图所示1. - 我预计只有 1 个值会发生很大变化,但所有这些值似乎都发生了巨大变化。同样,如果我围绕从屏幕中出来的一条假想线旋转手机(如图 2 所示),我希望只有滚动值会发生变化,但所有值都会发生很大变化。

问题是当我校准我的游戏时 - 这意味着记录角度 x、y 和 z 的当前值 - 我后来不知道如何解释传入的更新角度说“好吧,看起来你已经倾斜了手机,并且你想向左滚动 3 度”。它更像是“好吧,你移动了手机,你同时倾斜和滚动”,即使意图只是滚动。有道理吗?

有什么想法吗?我尝试使用 remapCooperativeSystem 来查看更改轴是否有任何效果。没有喜悦。我想我错过了一些基本的东西:-(

The Android game My Paper Plane is a great example of how to implement tilt controls, but I've been struggling to understand how I can do something similar.

I have the following example that uses getOrientation() from the SensorManager. The whole thing is on pastebin here. It just prints the orientation values to text fields. Here is the most relevant snippet:

private void computeOrientation() {
    if (SensorManager.getRotationMatrix(m_rotationMatrix, null,
                                        m_lastMagFields, m_lastAccels)) {
        SensorManager.getOrientation(m_rotationMatrix, m_orientation);

        /* 1 radian = 57.2957795 degrees */
        /* [0] : yaw, rotation around z axis
         * [1] : pitch, rotation around x axis
         * [2] : roll, rotation around y axis */
        float yaw = m_orientation[0] * 57.2957795f;
        float pitch = m_orientation[1] * 57.2957795f;
        float roll = m_orientation[2] * 57.2957795f;

        /* append returns an average of the last 10 values */
        m_lastYaw = m_filters[0].append(yaw);
        m_lastPitch = m_filters[1].append(pitch);
        m_lastRoll = m_filters[2].append(roll);
        TextView rt = (TextView) findViewById(R.id.roll);
        TextView pt = (TextView) findViewById(R.id.pitch);
        TextView yt = (TextView) findViewById(R.id.yaw);
        yt.setText("azi z: " + m_lastYaw);
        pt.setText("pitch x: " + m_lastPitch);
        rt.setText("roll y: " + m_lastRoll);
    }
}

The problem is that the values this spits out look like nonsense, or at least there's no way to isolate which type of motion the user performed. I've drawn a diagram to indicate the 2 types of motion that I'd like to detect - 1. "tilt" for pitch and 2. "rotate" for roll/steering:

Figure 1. Pitch and roll

(That's an isometric-ish view of a phone in landscape mode, of course)

When I tilt the phone forwards and backwards along its long axis - shown by 1. - I expected only 1 of the values to change much, but all of them seem to change drastically. Similarly, if I rotate the phone about an imaginary line that comes out of the screen - shown in 2. - I'd hope that only the roll value changes, but all the values change a lot.

The problem is when I calibrate my game - which means recording the current values of the angles x, y and z - I later don't know how to interpret incoming updated angles to say "ok, looks like you have tilted the phone and you want to roll 3 degrees left". It's more like "ok, you've moved the phone and you're a-tiltin' and a-rollin' at the same time", even if the intent was only a roll. Make sense?

Any ideas? I've tried using remapCoordinateSystem to see if changing the axis has any effect. No joy. I think I'm missing something fundamental with this :-(

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绮筵 2024-10-17 07:08:35

您混合了加速器和磁传感器阵列。代码应该是:

if (SensorManager.getRotationMatrix(m_rotationMatrix, null,
                                    m_lastAccels, m_lastMagFields)) {

查看 getRotationMatrix(..)

You mixed the accelerator and megnetic sensor arrays. The code should be:

if (SensorManager.getRotationMatrix(m_rotationMatrix, null,
                                    m_lastAccels, m_lastMagFields)) {

Check out getRotationMatrix(..)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文