728x90
IOS에서 선수파일 저장 위치
바이너리 파일 Read
TextAsset bindata = Resources.Load("kimsangkyung") as TextAsset;
Stream s = new MemoryStream(bindata.bytes);
BinaryReader br = new BinaryReader(s);
Debug.Log("br: " + bindata.bytes.Length + "," + br.ToString());
텍스트 파일 Read
TextAsset txtData;
txtData = Resources.Load("kimyoungseong_left") as TextAsset;
string fs = txtData.ToString();
string[] fLines = Regex.Split(fs, "\n");
아이폰 로그파일
선수파일(바이너리파일)
BLE 스윙 데이터 수신
1. BLE subscribe FILE:GetBluetoothData.cs
2. 스윙 데이터 분석 FILE:GetBluetoothData.cs
private void readDataFromRacket(byte[] bytes)
{
//if (bytes[0] == 0x00)
// ButtonPositionText.text = "Not Pushed";
//else
// ButtonPositionText.text = "Pushed";
StatusText.text = ConvertByteToHexString(bytes) + "," + bytes.Length.ToString();
int aX = 0;
int aY = 0;
int aZ = 0;
int gX = 0;
int gY = 0;
int gZ = 0;
int p = 0;
float [] q = new float[4];
aX = (((bytes[1] & 0xff) << 8 | (bytes[0] & 0xff))) - 32768;
aY = (((bytes[1 + 2] & 0xff) << 8 | (bytes[2] & 0xff))) - 32768;
aZ = (((bytes[1 + 4] & 0xff) << 8 | (bytes[4] & 0xff))) - 32768;
gX = (((bytes[6 + 1] & 0xff) << 8 | (bytes[6] & 0xff))) - 32768;
gY = 0; // gY = (((txValue[6 + 1 + 2] & 0xff) << 8 | (txValue[6 + 2] & 0xff))) - 32768;
p = (((bytes[6 + 1 + 2] & 0xff) << 8 | (bytes[6 + 2] & 0xff))) - 32768;
gZ = (((bytes[6 + 1 + 4] & 0xff) << 8 | (bytes[6 + 4] & 0xff))) - 32768;
q[0] = (float)(((bytes[12 + 1] & 0xff) << 8 | (bytes[12] & 0xff)));
q[1] = (float)(((bytes[12 + 1 + 2] & 0xff) << 8 | (bytes[12 + 2] & 0xff)));
q[2] = (float)(((bytes[12 + 1 + 4] & 0xff) << 8 | (bytes[12 + 4] & 0xff)));
q[3] = (float)(((bytes[19] & 0xff) << 8 | (bytes[18] & 0xff)));
if (32767 < q[0]) q[0] -= 65535;
if (32767 < q[1]) q[1] -= 65535;
if (32767 < q[2]) q[2] -= 65535;
if (32767 < q[3]) q[3] -= 65535;
q[0] /= 100;
q[1] /= 100;
q[2] /= 100;
q[3] /= 100;
GameManager.g_Analysis.addData(aX,
aY,
aZ,
gX,
gY,
gZ,
q[0],
q[1],
q[2],
q[3],
p); // piezo
}
3. 스윙 패킷을 버퍼에 저장합니다. FILE:DataAnalysis.cs
public void addData(int ax, int ay, int az, int gx, int gy, int gz, float q1, float q2, float q3, float q4, int p)
{
ac_x = ax;
ac_y = ay;
ac_z = az;
gy_x = gx;
gy_y = gy;
gy_z = gz;
Quat_W = q1;
Quat_X = q2;
Quat_Y = q3;
Quat_Z = q4;
//piezo = 1400 - p;
piezo = p;
Buffer.BlockCopy(mRecognitionHistory[0], 0 * INT_SIZE, mRecognitionHistory[0], 1 * INT_SIZE, (DATA_NUM - 1) * INT_SIZE);
Buffer.BlockCopy(mRecognitionHistory[1], 0 * INT_SIZE, mRecognitionHistory[1], 1 * INT_SIZE, (DATA_NUM - 1) * INT_SIZE);
Buffer.BlockCopy(mRecognitionHistory[2], 0 * INT_SIZE, mRecognitionHistory[2], 1 * INT_SIZE, (DATA_NUM - 1) * INT_SIZE);
Buffer.BlockCopy(mRecognitionHistory[3], 0 * INT_SIZE, mRecognitionHistory[3], 1 * INT_SIZE, (DATA_NUM - 1) * INT_SIZE);
Buffer.BlockCopy(mRecognitionHistory[4], 0 * INT_SIZE, mRecognitionHistory[4], 1 * INT_SIZE, (DATA_NUM - 1) * INT_SIZE);
Buffer.BlockCopy(mRecognitionHistory[5], 0 * INT_SIZE, mRecognitionHistory[5], 1 * INT_SIZE, (DATA_NUM - 1) * INT_SIZE);
mRecognitionHistory[0][0] = ac_x;
mRecognitionHistory[1][0] = ac_y;
mRecognitionHistory[2][0] = ac_z;
mRecognitionHistory[3][0] = gy_x;
mRecognitionHistory[4][0] = gy_y;
mRecognitionHistory[5][0] = gy_z;
Buffer.BlockCopy(quarternionHistory[0], 0 * sizeof(float), quarternionHistory[0], 1 * sizeof(float), (DATA_NUM - 1) * sizeof(float));
Buffer.BlockCopy(quarternionHistory[1], 0 * sizeof(float), quarternionHistory[1], 1 * sizeof(float), (DATA_NUM - 1) * sizeof(float));
Buffer.BlockCopy(quarternionHistory[2], 0 * sizeof(float), quarternionHistory[2], 1 * sizeof(float), (DATA_NUM - 1) * sizeof(float));
Buffer.BlockCopy(quarternionHistory[3], 0 * sizeof(float), quarternionHistory[3], 1 * sizeof(float), (DATA_NUM - 1) * sizeof(float));
quarternionHistory[0][0] = q1;
quarternionHistory[1][0] = q2;
quarternionHistory[2][0] = q3;
quarternionHistory[3][0] = q4;
Buffer.BlockCopy(racketAngle, 0 * sizeof(int), racketAngle, 1 * sizeof(int), (DATA_NUM - 1) * sizeof(int));
racketAngle[0] = swing_degree;
Buffer.BlockCopy(racketAnglez, 0 * sizeof(int), racketAnglez, 1 * sizeof(int), (DATA_NUM - 1) * sizeof(int));
racketAnglez[0] = swing_degree_z;
Buffer.BlockCopy(eulerAngleY, 0 * sizeof(float), eulerAngleY, 1 * sizeof(float), (DATA_NUM - 1) * sizeof(float));
eulerAngleY[0] = euler_angle_y;
Buffer.BlockCopy(racketSpeed, 0 * sizeof(int), racketSpeed, 1 * sizeof(int), (DATA_NUM - 1) * sizeof(int));
racketSpeed[0] = acSpeed;
Buffer.BlockCopy(racketPiezo, 0 * sizeof(int), racketPiezo, 1 * sizeof(int), (DATA_NUM - 1) * sizeof(int)); // piezo
racketPiezo[0] = piezo;
if (SwingInvaildCheck == true)
{
#if UNITY_EDITOR
if (checkSwing(gy_z) == true)
#else
if (checkSwing(acSpeed) == true)
#endif
{
if (iDataTimeout < (validDuration - 10))
{
iDataTrainValid += 1;
if (1 <= iDataTrainValid) // 스윙이라고 인식
{
iDataTimeout = validDuration;
bSwingData = true;
iDataTrainValid = 0;
}
else
if (bSwingData == true)
{
#if UNITY_EDITOR // test zwin
#else
SwingSaveDB();
#endif
Debug.Log("DATA VALID! iDataTimeout#1=" + iDataTimeout);
SwingDataSave();
bSwingData = false;
iDataTimeout = 0;
}
}
}
else
{
iDataTrainValid = 0;
}
if (0 < iDataTimeout)
{
iDataTimeout -= 1;
if (iDataTimeout == 0)
{
if (bSwingData == true)
{
#if UNITY_EDITOR // test zwin
#else
// SwingSaveDB();
#endif
Debug.Log("DATA VALID! iDataTimeout#2=" + iDataTimeout);
SwingSaveDB();
SwingDataSave();
bSwingData = false;
}
}
}
}
}
4. 스윙을 분석합니다. FILE:DataAnalysis.cs
int dataParsing()
{
// Debug.Log("AX\tAY\tAZ\tGX\tGY\tGZ");
// for (int i = 0; i < DATA_NUM; i++)
// {
// Debug.Log(mRecognitionHistory[0][i] + "\t" + mRecognitionHistory[1][i] + "\t" + mRecognitionHistory[2][i] + "\t"
// + mRecognitionHistory[3][i] + "\t" + mRecognitionHistory[4][i] + "\t" + mRecognitionHistory[5][i]);
// }
// You can add up the values in as many cells as you want.
// 라켓 스윙 기울기
// Debug.Log("스윙유효2");
float min = 0, max = 0;
for (int i = 0; i < DATA_NUM; i++)
{
if(mRecognitionHistory[5][i] < min) min = mRecognitionHistory[5][i]; // gz
if (max < mRecognitionHistory[5][i]) max = mRecognitionHistory[5][i]; // gz
}
//Debug.Log("라켓기울기 max: " + max + " min: " + min + " = " + (max - min) );
int PizeoPos = 0;
int PiezoMax = 0;
for (int i = 0; i < DATA_NUM; i++)
{
if (racketPiezo[i] < min) max = mRecognitionHistory[5][i];
if (PiezoMax < racketPiezo[i])
{
PiezoMax = racketPiezo[i];
PizeoPos = i;
}
}
// Debug.Log("PiezoMax: " + PiezoMax + " PizeoPos: " + PizeoPos);
// GameManager.g_Analysis.swing_accuracy = PizeoPos * 100 / 60;
// GameManager.g_Analysis.swing_power = PiezoMax / 10;
#if UNITY_ANDROID
GetJavaObject().Call("Debug_Log", "라켓기울기 max: " + max + " min: " + min + " = " + (max - min));
for (int i = 0; i < DATA_NUM; i++)
{
//Debug.Log("Y값 : " + target.transform.GetChild(0).transform.localEulerAngles.y);
GetJavaObject().Call("Debug_Log", "" +
(quarternionHistory[0][i]*100) + "\t" +
(quarternionHistory[1][i]*100) + "\t" +
(quarternionHistory[2][i]*100) + "\t" +
(quarternionHistory[2][i]*100) + "\t" +
racketAngle[i] + "\t" +
racketSpeed[i]);
}
#endif
double[] sum = new double[SWING_KINDS];
double swing_low_value = 600000;
int swing_match_first = 0;
// dtw
for (int i = 0; i < SWING_KINDS; i++)
{
for (int j = 0; j < SENSOR_NUM; j++)
{
double[] r = Array.ConvertAll(mRecognitionHistory[j], x => (double)x);
double[] t = new double [DATA_NUM];
switch(i)
{
case TRAIN_FOREHAND_SMASH: t = Array.ConvertAll(forehand_smash[j], x => (double)x); break;
case TRAIN_FOREHAND_DRIVE: t = Array.ConvertAll(forehand_drive[j], x => (double)x); break;
case TRAIN_FOREHAND_SHORT: t = Array.ConvertAll(forehand_short[j], x => (double)x); break;
case TRAIN_FOREHAND_CUT: t = Array.ConvertAll(forehand_cut[j], x => (double)x); break;
case TRAIN_BACKHAND_SMASH: t = Array.ConvertAll(backhand_smash[j], x => (double)x); break;
case TRAIN_BACKHAND_DRIVE: t = Array.ConvertAll(backhand_drive[j], x => (double)x); break;
case TRAIN_BACKHAND_SHORT: t = Array.ConvertAll(backhand_short[j], x => (double)x); break;
case TRAIN_BACKHAND_CUT: t = Array.ConvertAll(backhand_cut[j], x => (double)x); break;
case TRAIN_FOREHAND_SMASH_2: t = Array.ConvertAll(forehand_smash_2[j], x => (double)x); break;
case TRAIN_FOREHAND_DRIVE_2: t = Array.ConvertAll(forehand_drive_2[j], x => (double)x); break;
case TRAIN_FOREHAND_SHORT_2: t = Array.ConvertAll(forehand_short_2[j], x => (double)x); break;
case TRAIN_FOREHAND_CUT_2: t = Array.ConvertAll(forehand_cut_2[j], x => (double)x); break;
case TRAIN_BACKHAND_SMASH_2: t = Array.ConvertAll(backhand_smash_2[j], x => (double)x); break;
case TRAIN_BACKHAND_DRIVE_2: t = Array.ConvertAll(backhand_drive_2[j], x => (double)x); break;
case TRAIN_BACKHAND_SHORT_2: t = Array.ConvertAll(backhand_short_2[j], x => (double)x); break;
case TRAIN_BACKHAND_CUT_2: t = Array.ConvertAll(backhand_cut_2[j], x => (double)x); break;
}
SimpleDTW dtw = new SimpleDTW(r, t);
dtw.computeDTW();
// Debug.Log("dtw " + i + "/" + j + " sum=" + dtw.getSum());
sum[i] += dtw.getSum();
}
// Debug.Log("dtw " + i + " sum=" + sum);
if(sum[i] < swing_low_value)
{
swing_match_first = i;
swing_low_value = sum[i];
}
}
GameManager.g_Analysis.swing = swing_match_first % 8;
Debug.Log("swing_match_first=" + swing_match_first);
Debug.Log("" + sum[0] + " " + sum[1] + " " + sum[2] + " " + sum[3] + " " + sum[4] + " " + sum[5] + " " + sum[6] + " " + sum[7]);
Debug.Log("" + sum[8+0] + " " + sum[8 + 1] + " " + sum[8 + 2] + " " + sum[8 + 3] + " " + sum[8 + 4] + " " + sum[8 + 5] + " " + sum[8 + 6] + " " + sum[8 + 7]);
// #if UNITY_EDITOR // test zwin
#if (UNITY_IOS || UNITY_STANDALONE_OSX || UNITY_IPHONE)
double matching = 400000-swing_low_value;
matching /= 10000;
if (matching < 0) matching = 0;
switch (GameManager.SWING_EXER_menu)
{
case GameManager.SWING_EXER_MENU.SWING_EXER_F_SMASH:
{
switch (GameManager.g_Analysis.swing)
{
case 0: case 8 + 0: matching += 60; break; // Fsmash
case 1: case 8 + 1: matching += 40; break; // Fdrive
case 2: case 8 + 2: matching += 40; break; // Fshort
case 3: case 8 + 3: matching += 20; break; // Fcut
case 4: case 8 + 4: break; // Bsmash
case 5: case 8 + 5: break; // Bdrive
case 6: case 8 + 6: break; // Bshort
case 7: case 8 + 7: break; // Bcut
}
break;
}
case GameManager.SWING_EXER_MENU.SWING_EXER_F_DRIVE:
{
switch (GameManager.g_Analysis.swing)
{
case 0: case 8 + 0: matching += 40; break; // Fsmash
case 1: case 8 + 1: matching += 60; break; // Fdrive
case 2: case 8 + 2: matching += 40; break; // Fshort
case 3: case 8 + 3: matching += 20; break; // Fcut
case 4: case 8 + 4: break; // Bsmash
case 5: case 8 + 5: break; // Bdrive
case 6: case 8 + 6: break; // Bshort
case 7: case 8 + 7: break; // Bcut
}
break;
}
case GameManager.SWING_EXER_MENU.SWING_EXER_F_SHORT:
{
switch (GameManager.g_Analysis.swing)
{
case 0: case 8 + 0: matching += 40; break; // Fsmash
case 1: case 8 + 1: matching += 40; break; // Fdrive
case 2: case 8 + 2: matching += 60; break; // Fshort
case 3: case 8 + 3: matching += 20; break; // Fcut
case 4: case 8 + 4: break; // Bsmash
case 5: case 8 + 5: break; // Bdrive
case 6: case 8 + 6: break; // Bshort
case 7: case 8 + 7: break; // Bcut
}
break;
}
case GameManager.SWING_EXER_MENU.SWING_EXER_F_CUT:
{
switch (GameManager.g_Analysis.swing)
{
case 0: case 8 + 0: matching += 20; break; // Fsmash
case 1: case 8 + 1: matching += 20; break; // Fdrive
case 2: case 8 + 2: matching += 20; break; // Fshort
case 3: case 8 + 3: matching += 60; break; // Fcut
case 4: case 8 + 4: break; // Bsmash
case 5: case 8 + 5: break; // Bdrive
case 6: case 8 + 6: break; // Bshort
case 7: case 8 + 7: break; // Bcut
}
break;
}
case GameManager.SWING_EXER_MENU.SWING_EXER_B_SMASH:
switch (GameManager.g_Analysis.swing)
{
case 0: case 8 + 0: break; // Fsmash
case 1: case 8 + 1: break; // Fdrive
case 2: case 8 + 2: break; // Fshort
case 3: case 8 + 3: break; // Fcut
case 4: case 8 + 4: matching += 60; break; // Bsmash
case 5: case 8 + 5: matching += 40; break; // Bdrive
case 6: case 8 + 6: matching += 40; break; // Bshort
case 7: case 8 + 7: matching += 20; break; // Bcut
}
break;
case GameManager.SWING_EXER_MENU.SWING_EXER_B_DRIVE:
switch (GameManager.g_Analysis.swing)
{
case 0: case 8 + 0: break; // Fsmash
case 1: case 8 + 1: break; // Fdrive
case 2: case 8 + 2: break; // Fshort
case 3: case 8 + 3: break; // Fcut
case 4: case 8 + 4: matching += 40; break; // Bsmash
case 5: case 8 + 5: matching += 40; break; // Bdrive
case 6: case 8 + 6: matching += 60; break; // Bshort
case 7: case 8 + 7: matching += 20; break; // Bcut
}
break;
case GameManager.SWING_EXER_MENU.SWING_EXER_B_SHORT:
switch (GameManager.g_Analysis.swing)
{
case 0: case 8 + 0: break; // Fsmash
case 1: case 8 + 1: break; // Fdrive
case 2: case 8 + 2: break; // Fshort
case 3: case 8 + 3: break; // Fcut
case 4: case 8 + 4: matching += 40; break; // Bsmash
case 5: case 8 + 5: matching += 40; break; // Bdrive
case 6: case 8 + 6: matching += 60; break; // Bshort
case 7: case 8 + 7: matching += 20; break; // Bcut
}
break;
case GameManager.SWING_EXER_MENU.SWING_EXER_B_CUT:
switch (GameManager.g_Analysis.swing)
{
case 0: case 8 + 0: break; // Fsmash
case 1: case 8 + 1: break; // Fdrive
case 2: case 8 + 2: break; // Fshort
case 3: case 8 + 3: break; // Fcut
case 4: case 8 + 4: matching += 20; break; // Bsmash
case 5: case 8 + 5: matching += 20; break; // Bdrive
case 6: case 8 + 6: matching += 20; break; // Bshort
case 7: case 8 + 7: matching += 60; break; // Bcut
}
break;
case GameManager.SWING_EXER_MENU.SWING_EXER_SERVE: break;
}
GameManager.g_Analysis.swing_matching = (int)matching;
// int tempMathing = UnityEngine.Random.Range(0, 100);
// random_i += 77;
// GameManager.g_Analysis.swing_matching = random_i % 100;
//swing = (random_i % 8);
// GameManager.g_Analysis.swing_speed = (int)acSpeed / 100;
//int tempSwing = UnityEngine.Random.Range(0, 7);
doSwing("" + GameManager.g_Analysis.swing); // swing); // "" + tempSwing); // for test
#endif
if (GameManager.SWING_EXER_MENU.SWING_RECORD_TIMER == GameManager.SWING_EXER_menu)
{
if (swing < 4)
GameManager.g_Analysis.RECORD_hand[HAND_RIGHT] += 1;
else
GameManager.g_Analysis.RECORD_hand[HAND_LEFT] += 1;
GameManager.g_Analysis.RECORD_swing[swing] += 1;
Debug.Log("RECORD=" + " {" + GameManager.g_Analysis.RECORD_hand[HAND_RIGHT] + "," + GameManager.g_Analysis.RECORD_hand[HAND_LEFT] + " } {" +
GameManager.g_Analysis.RECORD_swing[0] + "," +
GameManager.g_Analysis.RECORD_swing[1] + "," +
GameManager.g_Analysis.RECORD_swing[2] + "," +
GameManager.g_Analysis.RECORD_swing[3] + "," +
GameManager.g_Analysis.RECORD_swing[4] + "," +
GameManager.g_Analysis.RECORD_swing[5] + "," +
GameManager.g_Analysis.RECORD_swing[6] + "," +
GameManager.g_Analysis.RECORD_swing[7] + "} ");
}
ArraySave();
//Save(); // file to csv
return 0;
}
스윙인식
1. 포핸드 드라이브 인식
2. 스윙 종류
백핸드 드라이브 인식
포핸드 쇼트 인식
'유니티 > IOS BLE' 카테고리의 다른 글
Ble Racket Data (0) | 2020.12.22 |
---|---|
Unity IOS BLE 컴파일 환경 구성 (0) | 2020.12.08 |