13

I am trying to make an application that would detect what kind of shape you made with your iPhone using accelerometer. As an example, if you draw a circle with your hand holding the iPhone, the app would be able to redraw it on the screen. This could also work with squares, or even more complicated shapes. The only example of application I've seen doing such a thing is AirPaint (http://vimeo.com/2276713), but it doesn't seems to be able to do it in real time.

My first try is to apply a low-pass filter on the X and Y parameters from the accelerometer, and to make a pointer move toward these values, proportionally to the size of the screen. But this is clearly not enought, I have a very low accuracy, and if I shake the device it also makes the pointer move...

Any ideas about that ? Do you think accelerometer data is enought to do it ? Or should I consider using other data, such as the compass ?

Thanks in advance !

4

4 に答える 4

10

OK 動作するように見えるものを見つけましたが、まだいくつか問題があります。これが私が進める方法です(デバイスが垂直に保持されていることを認めます):

1 - デフォルトの x、y、および z 値があります。
2 - ローパス フィルターを使用して、このデータから重力ベクトルを抽出します。
3 - 各 x、y、z から正規化された重力ベクトルを引き、移動加速度を取得します。
4 - 次に、この加速度値を時間で積分すると、速度が得られます。
5 - この速度を時間に関して再度積分し、位置を見つけます。

以下のコードはすべて、コントローラーの accelerometer:didAccelerate: デリゲートに含まれています。見つけた位置に合わせてボールを動かそうとしています。これが私のコードです:

NSTimeInterval interval = 0;
NSDate *now = [NSDate date];
if (previousDate != nil)
{
    interval = [now timeIntervalSinceDate:previousDate];
}
previousDate = now;

//Isolating gravity vector
gravity.x = currentAcceleration.x * kFileringFactor + gravity.x * (1.0 - kFileringFactor);
gravity.y = currentAcceleration.y * kFileringFactor + gravity.y * (1.0 - kFileringFactor);
gravity.z = currentAcceleration.z * kFileringFactor + gravity.z * (1.0 - kFileringFactor);
float gravityNorm = sqrt(gravity.x * gravity.x + gravity.y * gravity.y + gravity.z * gravity.z);

//Removing gravity vector from initial acceleration
filteredAcceleration.x = acceleration.x - gravity.x / gravityNorm;
filteredAcceleration.y = acceleration.y - gravity.y / gravityNorm;
filteredAcceleration.z = acceleration.z - gravity.z / gravityNorm;

//Calculating velocity related to time interval
velocity.x = velocity.x + filteredAcceleration.x * interval;
velocity.y = velocity.y + filteredAcceleration.y * interval;
velocity.z = velocity.z + filteredAcceleration.z * interval;

//Finding position
position.x = position.x + velocity.x * interval * 160;
position.y = position.y + velocity.y * interval * 230;

これを実行すると、かなり良い値が得られます。つまり、動きに応じて加速度が正または負の値になることがわかります。しかし、その位置を自分のボール ビューに適用しようとすると、ボールが動いていることがわかりますが、一方の方向よりも他方の方向に進む傾向があります。これは、たとえば、デバイスで円を描くと、画面の左上隅に向かって曲線を描くボールが表示されることを意味します。そのような何か: http://img685.imageshack.us/i/capturedcran20100422133.png/

何が起こっているかについて何か考えはありますか?前もって感謝します !

于 2010-04-22T11:47:27.577 に答える
7

問題は、加速度を 2 回積分して位置を取得できないことです。初期位置と速度を知らずに。統合について学ぶときに学校で追加した +C 用語を覚えていますか? あなたが位置に着く頃には、それは ct+k タームです。そして、それは重要です。これは、取得している加速度データが量子化されて平均化されていることを考慮する前に、デバイスの実際の加速度を実際に統合していないためです。これらの誤差は、2 回積分すると大きくなってしまいます。

AirPaint のデモをよく見ると、まさにこれが起こっていることがわかります。レンダリングされた形状は、移動した形状とは大きく異なります。

位置と速度を感知するデバイス (Wii リモコンなど) でさえ、ジェスチャ認識に問題があります。人々が (たとえば、AILive のような企業に) 解決するために大金を支払うのは難しい問題です。

そうは言っても、大規模な特性が異なる場合、特定の種類のジェスチャを簡単に区別できます。デバイスが 6 つの角度範囲のそれぞれで加速度を受信した場合、円を検出できます (たとえば)。iPhoneを空中でスワイプするか、振るかを検出できます。

丸と四角の違いを見分けるのはもっと難しいでしょう。

于 2010-04-24T00:59:20.523 に答える
2

加速度が速度に、速度が位置にどのように関係しているかを調べる必要があります。現時点では、私の心は少しおならをしていますが、それは積分であると確信しています...時間に関して加速を統合したいと考えています。ウィキペディアは数学の助けになるはずです。私はあなたを助けることができる良いライブラリがどこかにあると確信しています.

ただし、加速度計は完璧ではなく、十分な速度でポーリングされるわけでもないことに注意してください。本当に急な動きは、うまく捉えられないことがあります。しかし、空中でやさしく描くには、問題なく動作するはずです。

于 2010-04-20T11:52:00.470 に答える
2

瞬間加速度で減算する前に、重力ベクトルを正規化しているようです。これにより、相対方向は保持されますが、相対スケールは削除されます。私がテストした最新のデバイス (確かに Idevice ではありません) は、およそ -9.8 で重力を返しましたが、これはおそらく m/s に調整されています。他の加速度がないと仮定すると、これを正規化してフィルター処理されたパスから差し引くと、現在の加速度は 0.0f ではなく -8.8 になります。

2 つのオプション: -フィルター パスの後で重力ベクトルを差し引くことができます。

また、デバイスの向きを考慮することも忘れないでください。

于 2010-07-06T21:05:22.263 に答える