重心測定
19回大会はLightのみ出場でしたが、今回は本戦にもグレートで出場したいですね。
さて、ROBO-ONEというと重心規定があるのですが、ちょっと昔にWiiFitで重心測定出来るソフトを公開しておきながらブログで紹介し忘れていたので、この機会に紹介します。
<WiiFit重心センサー>

WiiFitの重心位置をグラフ表示するソフトです。ついでに、体重も量ります。
データの記録とかそういうことはしません。
本当に作っただけというソフト。
公開できるほどのソースコードではないですが、続きの方に貼り付けておくので、中身を知りたい方は参考にどうぞ。
開発はコチラのHPを参考にしました。
それとライブラリはWiimotelibを使ってます。
ダウンロードの仕方と使い方
ダウンロード
リンク先のskydrive内の「wiifit重心センサー」のzipファイルをダウンロード。
中に「WiiFit」というアプリケーションとライブラリファイル「Wiimotelib.dll」があるので、WiiFitをPCと接続した状態でアプリケーション「WiiFit」をクリックするとソフトが起動します。
WiiFitとPCの接続は、WiiFit裏側のバッテリーカバーの下にある赤いボタンを押すとWiiFitがBluetooth接続待機状態になるので、後はマウスやキーボードなどの他のBluetooth機器と同様にペアリングをしてPCと接続して下さい。
機能
重心の位置をグラフ表示する他、体重の数値、グラフのX座標、Y座標を数値で表示します。
グラフの真ん中の座標は(0,0)です。
・体重ゼロ点調整
クリックすると、体重をゼロに校正します。
・座標ゼロ点調整(使用しないことを推奨)
重心がちょうど真ん中にある時にクリックすることで重心座標をゼロに校正します。
ただし、なにも乗せていない時でもケースの歪みなどで重心が真ん中にあるとは限らないようで、重心が真ん中にあることの判断が難しいため使用しないことを推奨します。
というわけで、とりあえず作って公開したという感じのソフト。
最後に注意点を。
軽いと反応しないです。
サイコロ一号(約700g)でも体重測定は出来ても、重心測定は出来ませんでした。
十分なテストもしてない状態で公開してるので、3kgではたして重心測定出来るのか実は未確認だったりしてます。
数10kgの人間の重さは反応することを確認しているのですが……
それと、座標はノイズ軽減のため0.02秒置きに取得するデータを100個平均化してます。
そのため、完全にデータが入れ替わるまでは2秒ほどかかるのでご了承ください。
ソースコード
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WiimoteLib;
namespace WiiFit
{
public partial class Form1 : Form
{
Wiimote wm = new Wiimote();
int i = 0;
float[] GravityX = new float[99];
float[] GravityY = new float[99];
float aveX;
float aveY;
float kg;
float a = 0;
float ax= 0;
float ay = 0;
float picx;
float picy;
WiimoteState ws;
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
this.wm.Connect();
timer1.Interval = 20;
timer1.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
ws = wm.WiimoteState;
aveX = aveX - GravityX[i];
aveY = aveY - GravityY[i];
float x = ws.BalanceBoardState.CenterOfGravity.X;
float y = ws.BalanceBoardState.CenterOfGravity.Y;
kg = ws.BalanceBoardState.WeightKg - a;
GravityX[i] = x;
GravityY[i] = y;
aveX = aveX + GravityX[i];
aveY = aveY + GravityY[i];
Graphics g = this.pictureBox1.CreateGraphics();
g.Clear(Color.Black);
picx = (((aveX - ax) / 100) + 20.0f) * 10;
picy = (((aveY - ay) / 100) + 12.0f) * 10;
g.FillEllipse(Brushes.Red, picx, picy, 10, 10);
g.Dispose();
this.label1.Text = "体重" + kg + "kg";
this.label9.Text = "X座標:" + (ax - aveX) / 100;
this.label10.Text = "Y座標:" + (ay - aveY) / 100;
i++;
if (i >= 100)
{
i = 0;
}
}
private void button1_Click(object sender, EventArgs e)
{
ax = aveX;
ay = aveY;
}
private void button2_Click(object sender, EventArgs e)
{
a = kg;
}
}
}
プログラム概要
①20ms間隔(timer1.Interval = 20)でWiiの重心情報習得(float x = ws.BalanceBoardState.CenterOfGravity.X)
②重心情報を配列に格納(GravityX[i] = x)
③配列内の数値を合計(aveX = aveX + GravityX[i])
④合計を100で割り平均化し、その他諸々し描写用のピクセルに調整(picx = (((aveX - ax) / 100) + 20.0f) * 10;)
⑤描写(g.FillEllipse(Brushes.Red, picx, picy, 10, 10);)