检测360度旋转算法

5

我已成功检测手机绕一个轴的0-360度旋转(横滚),但现在我很难设计一种有效的算法来检测一次完整的旋转。我的工作算法可行,但我认为不够优雅和有效:

private boolean detectRoll;
private boolean[] checkpointsR = new boolean[4];
private boolean fullRollTurn;

public void detectingRoll() {
    setDetectRoll(true);
    checkpointsR[0] = true;
    for (int i = 1; i < 4; i++) {
        if (roll > 90 * i && roll < 90 * (i + 1)
            && checkpointsR[i - 1] == true) {
            checkpointsR[i] = true;
        }
    }

    if (areAllTrue(checkpointsR) && roll > 0 && roll < 45) {
        fullRollTurn = true;
        // reset rollCheckpoints
        for (int i = 1; i < 4; i++) {
            checkpointsR[i] = false;
        }
    }
}

public static boolean areAllTrue(boolean[] array) {
    for (boolean b : array)
        if (!b)
            return false;
    return true;
}

public void setDetectRoll(boolean detectRoll) {
    this.detectRoll = detectRoll;
}

任何帮助都将不胜感激。

3
这段代码的时间复杂度为常数级别(O(1)),因为无论发生什么情况,你只需要迭代遍历4个检查点。所以除非你已经进行了一些性能分析,告诉你这是一个瓶颈,否则我认为优化它所获得的收益是微不足道的。 - Simon
谢谢您的回复。我正在寻找任何新的建议,而不是优化我的算法,因为我知道它并不像应该的那样。 - Uroš Trstenjak
如果它工作正常,但你不想进行优化,那么你想要什么呢?“建议”太宽泛了,很可能会导致关闭。 - Geobits
问题说在完整的360度旋转时还没有效果。但期望的是,为什么不能将较小的旋转相加呢? - clwhisk
1个回答

1

嗯,你的代码只能检测到由增加的roll引起的转弯。在另一个方向上,也就是由roll下降引起的转弯,它无法检测到。

    if (checkpointsR[i - 1] == true) 
    {
        checkpointsR[i] = true; 
    }

永远不会触发。

虽然这很容易修复,但如果你唯一的传感器输入是roll,那么固定检查点的方法总是会有问题。最好的方式是将你的检查点想象成圆上的小红点,而手机的旋转对应着蚂蚁在圆边上爬行。假设当蚂蚁经过一个点时,它变成绿色,这代表检查点被设置为true。如果蚂蚁从两个检查点AB之间开始,它可以通过爬过B,一直绕到A,然后掉头向另一个方向走。所有的检查点都将变成绿色,但蚂蚁并没有完成一整圈。

解决这个问题的方法是改变两件事情:首先,给检查点三种状态:unvisitedclockwiseanticlockwise。其次,将蚂蚁放在检查点上方开始运动

以下是新规则:

  • 每一个点都是未访问状态(一个红点)。
  • 如果蚂蚁沿顺时针方向通过一个检查点,将其状态设置为顺时针(一个小绿箭头从该点顺时针指向)。
  • 如果蚂蚁沿逆时针方向通过一个检查点,将其状态设置为逆时针(一个小绿箭头从该点逆时针指向)。
  • 如果所有的检查点都是顺时针或者都是逆时针,则认为完成了一次转弯。

只需要三个检查点,可以放在圆上任何位置,但第一个检查点必须位于蚂蚁的初始位置下方。出于对称性的考虑,我建议使用{initial, inital + 120, initial + 240}

(思想实验中使用两个检查点也是可行的,但问题在于有一对区域之间存在一个非唯一的检查点,在蚂蚁从一个区域到另一个区域时会混淆它究竟经过了哪个检查点)


你能帮我解决这个问题吗? - Skizo-ozᴉʞS ツ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接