Accelerometer クラスについて
■Accelerometer クラスについて
Accelerometer クラスは、加速度センサーを利用するための機能がまとまっています。
■加速度センサーに対応しているか調べる
デバイスが加速度センサーを搭載していて利用可能か調べるには、
Accelerometer.isSupported プロパティを調べます。
true であれば、利用可能です。
加速度センサーが利用可能か調べる
var text_field = new TextField();
text_field.x = 10;
text_field.y = 10;
text_field.width = 500;
text_field.height = 20;
text_field .border = true;
stage.addChild(text_field);
text_field.text = "加速度センサーのサポート:" + Accelerometer.isSupported;
■ユーザーが加速度センサーをミュートしているか調べる
ユーザーの設定により、加速度センサーが利用停止状態か調べるには、
muted プロパティを調べます。
true であれば、利用できません。
加速度センサーがミュート設定か調べる
var text_field = new TextField();
text_field.x = 10;
text_field.y = 10;
text_field.width = 500;
text_field.height = 20;
text_field .border = true;
stage.addChild(text_field);
var acce:Accelerometer = new Accelerometer();
text_field.text = "加速度センサーのミュート設定:" + acce.muted;
■加速度センサーで加速度を検出する
加速度センサーを利用することにより、以下の加速度を検出することができます。
■重力加速度を検出する
地球上にデバイスが存在すると、常に重力の影響を受け続ける事になります。
実際に加速度センサーの値を調べてみると、静止している状態でも常に「真下方向に、長さが 1 のベクトル」を検出することができます。
デバイスの真下の方向を知ることができるので、デバイスがどれだけ傾いているかが計算できます。
「東西南北上下のどの方向を向いているか」は計算できません。「水平としたい状態からどれだけ傾いているか」は計算できます。
■遠心力を検出する
デバイスを手に持って振り回す円運動を行うと、外側に向かって遠心力が発生します。
遠心力は、加速度センサーで検出することができます。円運動を行っている間は、一定の遠心力が常に働き続けます。
■加速移動時の慣性力を検出する
デバイスを加速させる運動を行うと、移動した方向と反対の方向に、慣性力(止まり続けようとする力)が発生します。
車が急発進したときに、後ろに吹っ飛んで座席に押し付けられるイメージです。
慣性力は、加速度センサーで検出することができます。
デバイスが等速で移動中の場合は、慣性は発生しないので検出できません。
■減速移動時の慣性力を検出する
デバイスを減速させる運動を行うと、移動した方向に、慣性力(移動し続けようとする力)が発生します。
車が急停止したときに前に吹っ飛んでシートベルトに引っかかるイメージです。
慣性力は、加速度センサーで検出することができます。
デバイスが等速で移動中の場合は、慣性は発生しないので検出できません。
■取得できる加速度の座標系について
加速度は、3Dベクトルとして取得することができます。
この3D空間は、デバイスに表示されているFlash の画面の向きを基準とした座標系となります。
デバイスの向きを変えると画面も追従して回転するデバイスがありますが、この場合、Flashの表示されている向きが基準となります。
Flash の画面の左右方向が x 軸となります。
Flash の画面の上下方向が y 軸となります。
Flash の画面の前後方向が z 軸となります。
■加速度の方向について
加速度センサーは、重力加速度(9.8 m/s2)を約 1.0 として取得できます。
地球上にあるデバイスは重力の影響を受けるので、常にデバイスの下方向に対して 1.0 の長さのベクトルが検出できます。
また、加速度の座標系の正の方向は以下の通りです。Flash の座標系の正の方向とは違うので注意します。
x 軸方向について
端末の右端を下方向に向けると負の値が取得できます。
端末の左端を下方向に向けると正の値が取得できます。
端末の右端を外側に向けて円運動を行うと、負の値が取得できます。
端末の左端を外側に向けて円運動を行うと、正の値が取得できます。
端末を右方向に加速させると、正の値が取得できます。
端末の右方向に減速させると、負の値が取得できます。
端末を左方向に加速させると、負の値が取得できます。
端末の左方向に減速させると、正の値が取得できます。
y 軸方向について
端末の上端を下方向に向けると負の値が取得できます。
端末の下端を下方向に向けると正の値が取得できます。
端末の上端を外側に向けて円運動を行うと、負の値が取得できます。
端末の下端を外側に向けて円運動を行うと、正の値が取得できます。
端末を上方向に加速させると、正の値が取得できます。
端末の上方向に減速させると、負の値が取得できます。
端末を下方向に加速させると、負の値が取得できます。
端末の下方向に減速させると、正の値が取得できます。
z 軸方向について
端末の表側(液晶がある方)を下方向に向けると負の値が取得できます。
端末の裏側(液晶がない方)を下方向に向けると正の値が取得できます。
端末の表側を外側に向けて円運動を行うと、負の値が取得できます。
端末の裏側を外側に向けて円運動を行うと、正の値が取得できます。
端末を手前方向に加速させると、正の値が取得できます。
端末の手前方向に減速させると、負の値が取得できます。
端末を奥方向に加速させると、負の値が取得できます。
端末の奥方向に減速させると、正の値が取得できます。
加速度を取得する
サンプルをダウンロード
■加速度センサーの取得時間隔を変更する
加速度センサーの取得時間隔を変更するには、
setRequestedUpdateInterval() メソッドを使用します。
引数に、取得したい時間隔をミリ秒で指定します。
加速度センサーの取得時間隔を 10 ミリ秒に変更する
// 加速度センサー利用可能
if(Accelerometer.isSupported){
var acc:Accelerometer = new Accelerometer();
// 取得時間隔を変更
acc.setRequestedUpdateInterval(10);
}
■加速度を取得する
加速度を取得するには、AccelerometerEvent.UPDATE イベントを使用します。
一定の時間隔で登録した関数が呼び出されます。
加速度センサーの更新を取得する
// 加速度センサー利用可能
if(Accelerometer.isSupported){
var accelerometer:Accelerometer = new Accelerometer();
// 取得時間隔を変更
accelerometer.setRequestedUpdateInterval(10);
// 更新がある度に実行されるイベント
accelerometer.addEventListener(AccelerometerEvent.UPDATE, function(e:AccelerometerEvent):void{
});
}
■Accelerometer イベントから取得できる値
AccelerometerEvent には以下のプロパティがあります。
| プロパティ名 | 型 | 解説 |
| accelerationX | Number | x 軸方向の加速度 |
| accelerationY | Number | y 軸方向の加速度 |
| accelerationZ | Number | z 軸方向の加速度 |
| timestamp | Number | 初期化されてからイベント発生時までの時間(秒) |
取得例です。
加速度を取得する
var text_field = new TextField();
text_field.x = 10;
text_field.y = 10;
text_field.width = 500;
text_field.height = 100;
text_field .border = true;
stage.addChild(text_field);
// 加速度センサー利用可能
if(Accelerometer.isSupported){
var accelerometer:Accelerometer = new Accelerometer();
// 取得時間隔を変更
accelerometer.setRequestedUpdateInterval(10);
// 更新がある度に実行されるイベント
accelerometer.addEventListener(AccelerometerEvent.UPDATE, function(e:AccelerometerEvent):void{
text_field.text = "";
text_field.text += " x:" + e.accelerationX + "\n";
text_field.text += " y:" + e.accelerationY + "\n";
text_field.text += " z:" + e.accelerationZ + "\n";
});
}
■デバイスを振り回したかを調べる
加速度センサーで得られる値は、重力加速度や遠心力や慣性がすべて合成された結果となります。
デバイスをどのように振り回したかを調べたい場合は、重力加速度成分は不要です。
そこで、前回の加速度を残しておいて次回の加速度との差分を計算して加速度の変化を調べます。
重力加速度や、等角速度の回転運動といった、常に一定の加速度を発生させるような運動は検出できなくなりますが、
「突き」や「払い」や「左右に振る」「ひねる」といった動作は推測できるようになります。
取得例です。
加速度の変化を取得する
var text_field = new TextField();
text_field.x = 10;
text_field.y = 10;
text_field.width = 500;
text_field.height = 100;
text_field .border = true;
stage.addChild(text_field);
var vec:Vector3D = new Vector3D();
// 加速度センサー利用可能
if(Accelerometer.isSupported){
var accelerometer:Accelerometer = new Accelerometer();
// 取得時間隔を変更
accelerometer.setRequestedUpdateInterval(10);
// 更新がある度に実行されるイベント
accelerometer.addEventListener(AccelerometerEvent.UPDATE, function(e:AccelerometerEvent):void{
var x:Number = e.accelerationX - vec.x;
var y:Number = e.accelerationY - vec.y;
var z:Number = e.accelerationZ - vec.z;
vec.x = e.accelerationX;
vec.y = e.accelerationY;
vec.z = e.accelerationZ;
text_field.text = "";
text_field.text += " x:" + x + "\n";
text_field.text += " y:" + y + "\n";
text_field.text += " z:" + z + "\n";
});
}
デバイスの傾きを取得する
■傾けていないデフォルトの姿勢を確認する
まず、傾いていない状態の姿勢を確認します。
大抵の場合、「水平に置いている」か、「垂直に立てている」状態になるのではないでしょうか。
■デバイスを水平に置いている場合
■傾けていないデフォルトの姿勢を確認する
液晶のない裏面が真下を向いている状態です。このときの重力加速度は、
x 軸 が 0.0、y 軸が 0.0、z 軸が 1.0 となります。
■2次元情報として計算する
デバイスを水平においている場合、デバイスをデフォルトの状態から90度以上傾けると、液晶面が裏側を向くため物理的に見えなくなります。
これを利用して、3次元情報ではなく2次元情報として計算してみます。
z 軸情報を無視して、x 軸と y 軸情報だけを取得してみます。Flash の座標系に落とし込むには、x 軸を反転させる必要があります。
この2次元ベクトルの方向成分が、傾いている方向と考えることができます。また、2次元ベクトルの長さ成分が、傾きの強さと考えることができます。
水平に置いた状態からの傾きを Flash の2次元座標系で取得する
var text_field = new TextField();
text_field.x = 10;
text_field.y = 10;
text_field.width = 500;
text_field.height = 100;
text_field .border = true;
stage.addChild(text_field);
// 加速度センサー利用可能
if(Accelerometer.isSupported){
var accelerometer:Accelerometer = new Accelerometer();
// 取得時間隔を変更
accelerometer.setRequestedUpdateInterval(10);
// 更新がある度に実行されるイベント
accelerometer.addEventListener(AccelerometerEvent.UPDATE, function(e:AccelerometerEvent):void{
// x 軸と y 軸を取得する
var vec:Point = new Point();
vec.x = -e.accelerationX;
vec.y = e.accelerationY;
// ベクトルから傾いている方向(角度)を取得する
var r:Number = Math.atan2(vec.y,vec.x) * 180 / Math.PI;
// ベクトルから傾きの強さを取得する
var s:Number = vec.length;
text_field.text = "";
text_field.text += " r:" + r + "\n";
text_field.text += " s:" + s + "\n";
});
}
■3次元情報として計算する
デバイスが3次元的にどれだけ回転したか調べるには、2つの3次元ベクトルの角度差を計算します。
デフォルトの状態の3次元ベクトル (0,0,1)と、現在の姿勢の3次元ベクトルとの角度差を計算します。
デバイスをデフォルトの状態から傾けた角度を調べる
var text_field = new TextField();
text_field.x = 10;
text_field.y = 10;
text_field.width = 500;
text_field.height = 100;
text_field .border = true;
stage.addChild(text_field);
// 加速度センサー利用可能
if(Accelerometer.isSupported){
var accelerometer:Accelerometer = new Accelerometer();
// 取得時間隔を変更
accelerometer.setRequestedUpdateInterval(10);
// 更新がある度に実行されるイベント
accelerometer.addEventListener(AccelerometerEvent.UPDATE, function(e:AccelerometerEvent):void{
// 水平に置いた状態の加速度
var acc0:Vector3D = new Vector3D(0,0,1);
// 現在の加速度
var acc1:Vector3D = new Vector3D(e.accelerationX,e.accelerationY,e.accelerationZ);
// ベクトルを正規化
acc0.normalize();
acc1.normalize();
// 2つの3Dベクトルの角度差を計算する
var dot:Number = ((acc0.x * acc1.x) + (acc0.y * acc1.y) + (acc0.z * acc1.z));
var rot:Number = Math.acos(dot) * 180.0 / Math.PI;
text_field.text = "";
text_field.text += " r:" + rot + "\n";
});
}
得られる値は、0 ~ 180までの角度となります。
そこでデバイスが、どの3Dベクトルを軸に回転したかを調べます。回転軸を調べるには、2つの3Dベクトルの外積を調べます。
外積を計算すると、「2つの3Dベクトルから生まれる3D上の平面」に対して垂直となる3Dベクトルが得られます。
デバイスを傾けた回転軸を調べる
var text_field = new TextField();
text_field.x = 10;
text_field.y = 10;
text_field.width = 500;
text_field.height = 100;
text_field .border = true;
stage.addChild(text_field);
// 加速度センサー利用可能
if(Accelerometer.isSupported){
var accelerometer:Accelerometer = new Accelerometer();
// 取得時間隔を変更
accelerometer.setRequestedUpdateInterval(10);
// 更新がある度に実行されるイベント
accelerometer.addEventListener(AccelerometerEvent.UPDATE, function(e:AccelerometerEvent):void{
// 水平に置いた状態の加速度
var acc0:Vector3D = new Vector3D(0,0,1);
// 現在の加速度
var acc1:Vector3D = new Vector3D(e.accelerationX,e.accelerationY,e.accelerationZ);
// ベクトルを正規化
acc0.normalize();
acc1.normalize();
// 2つの3Dベクトルの角度差を計算する
var rot:Number = Vector3D.angleBetween(acc0,acc1) * 180 / Math.PI;
// 2つの3Dベクトルの外積を計算する
var cro:Vector3D = acc0.crossProduct(acc1);
text_field.text = "";
text_field.text += " r:" + rot + "\n";
text_field.text += " x:" + cro.x + "\n";
text_field.text += " y:" + cro.y + "\n";
text_field.text += " z:" + cro.z + "\n";
});
}
「回転軸の3Dベクトル」と「回転する角度」の2つのパラメータを使って、任意軸の回転行列や、任意軸の回転クォータニオンを作成します。
これで、デバイスのデフォルトの状態からの3次元としての傾きを計算することができます。
デバイスの傾きを行列として計算する
var text_field = new TextField();
text_field.x = 10;
text_field.y = 10;
text_field.width = 500;
text_field.height = 100;
text_field .border = true;
stage.addChild(text_field);
// 加速度センサー利用可能
if(Accelerometer.isSupported){
var accelerometer:Accelerometer = new Accelerometer();
// 取得時間隔を変更
accelerometer.setRequestedUpdateInterval(10);
// 更新がある度に実行されるイベント
accelerometer.addEventListener(AccelerometerEvent.UPDATE, function(e:AccelerometerEvent):void{
// 水平に置いた状態の加速度
var acc0:Vector3D = new Vector3D(0,0,1);
// 現在の加速度
var acc1:Vector3D = new Vector3D(e.accelerationX,e.accelerationY,e.accelerationZ);
// ベクトルを正規化
acc0.normalize();
acc1.normalize();
// 2つの3Dベクトルの角度差を計算する
var rot:Number = Vector3D.angleBetween(acc0,acc1) * 180 / Math.PI;
// 2つの3Dベクトルの外積を計算する
var cro:Vector3D = acc0.crossProduct(acc1);
// 回転軸と角度から行列を作成する
var mtx:Matrix3D = new Matrix3D();
mtx.prependRotation(rot, cro);
});
}
■デバイスを垂直に立てている場合
■傾けていないデフォルトの姿勢を確認する
液晶の下部が真下を向いている状態です。このときの重力加速度は、
x 軸 が 0.0、y 軸が 1.0、z 軸が 0.0 となります。
■2次元情報として計算する
デバイスを垂直に立てている場合、好きな方向に傾けるよりは、液晶を常に手前に表示しながら 360 度回転させるという Flash の画面を回転させる使い方なりそうです。
そこで、3次元情報ではなく2次元情報として計算してみます。
z 軸情報を無視して、x 軸と y 軸情報だけを取得してみます。
Flash の座標系に落とし込むには、x 軸を反転させる必要があります。
この2次元ベクトルの方向成分を利用すると、Flash 画面がどれだけ回転したかが計算できそうです。
ベクトルから得られた角度の符号を反転します。デフォルトの状態で、(0,1) が得られる為、さらに 90 度減算します。
垂直に立てた状態からどれだけ回転したかを調べる
var text_field = new TextField();
text_field.x = 10;
text_field.y = 10;
text_field.width = 500;
text_field.height = 100;
text_field .border = true;
stage.addChild(text_field);
// 加速度センサー利用可能
if(Accelerometer.isSupported){
var accelerometer:Accelerometer = new Accelerometer();
// 取得時間隔を変更
accelerometer.setRequestedUpdateInterval(10);
// 更新がある度に実行されるイベント
accelerometer.addEventListener(AccelerometerEvent.UPDATE, function(e:AccelerometerEvent):void{
// x 軸と y 軸を取得する
var vec:Point = new Point();
vec.x = -e.accelerationX;
vec.y = e.accelerationY;
// ベクトルから傾いている方向(角度)を取得する
var r:Number = Math.atan2(vec.y,vec.x) * 180 / Math.PI - 90;
text_field.text = "";
text_field.text += " r:" + r + "\n";
});
}
■3次元情報として計算する
デバイスが3次元的にどれだけ回転したか調べるには、2つの3次元ベクトルの角度差を計算します。
デフォルトの状態の3次元ベクトル (0,0,1)と、現在の姿勢の3次元ベクトルとの角度差を計算します。
デバイスをデフォルトの状態から傾けた角度を調べる
var text_field = new TextField();
text_field.x = 10;
text_field.y = 10;
text_field.width = 500;
text_field.height = 100;
text_field .border = true;
stage.addChild(text_field);
// 加速度センサー利用可能
if(Accelerometer.isSupported){
var accelerometer:Accelerometer = new Accelerometer();
// 取得時間隔を変更
accelerometer.setRequestedUpdateInterval(10);
// 更新がある度に実行されるイベント
accelerometer.addEventListener(AccelerometerEvent.UPDATE, function(e:AccelerometerEvent):void{
// 垂直に立てた状態の加速度
var acc0:Vector3D = new Vector3D(0,1,0);
// 現在の加速度
var acc1:Vector3D = new Vector3D(e.accelerationX,e.accelerationY,e.accelerationZ);
// ベクトルを正規化
acc0.normalize();
acc1.normalize();
// 2つの3Dベクトルの角度差を計算する
var dot:Number = ((acc0.x * acc1.x) + (acc0.y * acc1.y) + (acc0.z * acc1.z));
var rot:Number = Math.acos(dot) * 180.0 / Math.PI;
text_field.text = "";
text_field.text += " r:" + rot + "\n";
});
}
得られる値は、0 ~ 180までの角度となります。
そこでデバイスが、どの3Dベクトルを軸に回転したかを調べます。回転軸を調べるには、2つの3Dベクトルの外積を調べます。
外積を計算すると、「2つの3Dベクトルから生まれる3D上の平面」に対して垂直となる3Dベクトルが得られます。
デバイスを傾けた回転軸を調べる
var text_field = new TextField();
text_field.x = 10;
text_field.y = 10;
text_field.width = 500;
text_field.height = 100;
text_field .border = true;
stage.addChild(text_field);
// 加速度センサー利用可能
if(Accelerometer.isSupported){
var accelerometer:Accelerometer = new Accelerometer();
// 取得時間隔を変更
accelerometer.setRequestedUpdateInterval(10);
// 更新がある度に実行されるイベント
accelerometer.addEventListener(AccelerometerEvent.UPDATE, function(e:AccelerometerEvent):void{
// 垂直に立てた状態の加速度
var acc0:Vector3D = new Vector3D(0,1,0);
// 現在の加速度
var acc1:Vector3D = new Vector3D(e.accelerationX,e.accelerationY,e.accelerationZ);
// ベクトルを正規化
acc0.normalize();
acc1.normalize();
// 2つの3Dベクトルの角度差を計算する
var rot:Number = Vector3D.angleBetween(acc0,acc1) * 180 / Math.PI;
// 2つの3Dベクトルの外積を計算する
var cro:Vector3D = acc0.crossProduct(acc1);
text_field.text = "";
text_field.text += " r:" + rot + "\n";
text_field.text += " x:" + cro.x + "\n";
text_field.text += " y:" + cro.y + "\n";
text_field.text += " z:" + cro.z + "\n";
});
}
「回転軸の3Dベクトル」と「回転する角度」の2つのパラメータを使って、任意軸の回転行列や、任意軸の回転クォータニオンを作成します。
これで、デバイスのデフォルトの状態からの3次元としての傾きを計算することができます。
デバイスの傾きを行列として計算する
var text_field = new TextField();
text_field.x = 10;
text_field.y = 10;
text_field.width = 500;
text_field.height = 100;
text_field .border = true;
stage.addChild(text_field);
// 加速度センサー利用可能
if(Accelerometer.isSupported){
var accelerometer:Accelerometer = new Accelerometer();
// 取得時間隔を変更
accelerometer.setRequestedUpdateInterval(10);
// 更新がある度に実行されるイベント
accelerometer.addEventListener(AccelerometerEvent.UPDATE, function(e:AccelerometerEvent):void{
// 垂直に立てた状態の加速度
var acc0:Vector3D = new Vector3D(0,1,0);
// 現在の加速度
var acc1:Vector3D = new Vector3D(e.accelerationX,e.accelerationY,e.accelerationZ);
// ベクトルを正規化
acc0.normalize();
acc1.normalize();
// 2つの3Dベクトルの角度差を計算する
var rot:Number = Vector3D.angleBetween(acc0,acc1) * 180 / Math.PI;
// 2つの3Dベクトルの外積を計算する
var cro:Vector3D = acc0.crossProduct(acc1);
// 回転軸と角度から行列を作成する
var mtx:Matrix3D = new Matrix3D();
mtx.prependRotation(rot, cro);
});
}

