void OnMeasureDataEvent(Hot2gEnumerations.EnumHot2gMeasResult e, object meas_data, string device_address) { //- 注意:3種類のBLEパケットが来るのでここは21Hzくらい。10Hz(Ac1) ,10Hz(Gyro), 1Hz(HR)... Debug.Log("1===:" + e + "::" + this.m_Mode); if (this.m_Mode == eMode.GainSetting) { /* 手動ゲイン調整 */ adjustGain(m_nfb, m_gc, e, meas_data, m_Logger);//- -> State will change to RecieveData after this. } else if (this.m_Mode == eMode.RecieveData) { /* データ受信 */ receiveData(m_nfb, e, meas_data, m_Logger); } else if (this.m_Mode == eMode.ResetGain) { /* ゲインリセット */ resetGain(m_nfb, m_gc); //- -> State will change to Waiting after this. } else if (this.m_Mode == eMode.Waiting) { /* データ受信 */ receiveData(m_nfb, e, meas_data, m_Logger); } //- Check status GyroScope.Stability st_stability = this.dataStore.stability[this.dataStore.stability.Count - 1]; Debug.Log("Check2 " + "stability: " + st_stability.ToString() + " / state2:" + state2.ToString() + " / mode: " + Hot2gApplication.Instance.mode.ToString()); //- RecieveData to Waiting if (Hot2gApplication.Instance.mode == eMode.RecieveData) { if (st_stability != GyroScope.Stability.Stabled || state2 != eState.OnHead) { resetGain(m_nfb, m_gc); //GainSetDeray(); Hot2gApplication.instance.setStateToWating();//- to Waiting Debug.Log("Check2 " + "GainReset!!!***************************"); } } else if (Hot2gApplication.Instance.mode == eMode.Waiting) { if (st_stability == GyroScope.Stability.Stabled && state2 == eState.OnHead) { Hot2gApplication.instance.setStateToMGC();//- --> MGC --> RecieveData Debug.Log("Check2 " + "MGC Start >>>>>>>>>>>>>>>>>>>>>>>>>>"); } } }
/** * isupdateActivenessesを管理するメソッド * ・心拍数が40~180の範囲を超えている状態が5秒続いたら、画面の色更新を止めます * ・心拍数が40~180の範囲に入っている状態が3秒続いたら、画面の色更新をします * * * Revised conditions * sample num: 20 * * 1. HbT 3cm: abs(median - mean)<3 * 2. HbT 3cm: non zero * 3. Hb 1cm: median(v-v(1))<0.3 * 4. Gyro-Z: median(v-v(1))<7 * */ static void updateActivenesses() { if (Hot2gApplication.Instance.datastore.stability.Count <= 0) { return; } List <double> brain1 = Hot2gApplication.Instance.datastore.l1Ac; List <double> brain3 = Hot2gApplication.Instance.datastore.l3Ac; List <double> gyroZ = Hot2gApplication.Instance.datastore.gyroZ; GyroScope.Stability stability = Hot2gApplication.Instance.datastore.stability[Hot2gApplication.Instance.datastore.stability.Count - 1]; //Debug.Log("HRTEST State:" + sF(NpodApplication.app.state.toString()) + " / State2:" + sF(NpodApplication.app.state2.toString())) int sz = 20; if (brain1.Count > sz) { bool lastStatus = isupdateActivenesses; bool cndStability = (stability == GyroScope.Stability.Stabled); //true;//stability.isStable; // 1. HbT 3cm: abs(median - mean)<3 // val cnd1 = (median(brain3.takeLast(sz)) - brain3.takeLast(sz).average()).absoluteValue < 3.0 double B3_median = median(takeLast(brain3, sz)); double B3_ave = AnalyseHelper.Average(brain3, brain3.Count - sz, brain3.Count); bool cnd1 = (Math.Abs(B3_median - B3_ave) < 3); // 2. HbT 3cm: non zero //val cnd2 = (median(brain3.takeLast(sz)) - brain3.takeLast(sz).average()).absoluteValue != 0.0 bool cnd2 = (Math.Abs(B3_median - B3_ave) != 0.0); // 3. Hb 1cm: median(v-v(1))<0.3 bool cnd3 = median(subtract(takeLast(brain1, sz), brain1[brain1.Count - sz])) < 0.3; // 4. Gyro-Z: median(v-v(1))<7 bool cnd4 = median(subtract(takeLast(gyroZ, sz), gyroZ[gyroZ.Count - sz])) < 7; // 5. 置いたままの状態を加速度から検出 bool cnd5 = sd(takeLast(gyroZ, sz)) > 0.02; isupdateActivenessesBuffer.Add(cndStability && cnd1 && cnd2 && cnd3 && cnd4 && cnd5); if (isupdateActivenessesBuffer.Count > 50) { isupdateActivenessesBuffer.RemoveAt(0); } //isupdateActivenesses = !isupdateActivenessesBuffer.takeLast(2).all { !it } if (isupdateActivenessesBuffer.Count == 1) { isupdateActivenesses = isupdateActivenessesBuffer[0]; } else { int c = isupdateActivenessesBuffer.Count - 1; isupdateActivenesses = (isupdateActivenessesBuffer[c] || isupdateActivenessesBuffer[c - 1]); } Debug.Log("HRTEST 1:" + cnd1 + " 2:" + cnd2 + " 3:" + cnd3 + " 4:" + cnd4 + " 5:" + cnd5); if (!isupdateActivenesses) /** 非装着検出! */ { /** 計測中(装着) → 非装着 */ if (Hot2gApplication.Instance.mode == Hot2gApplication.eMode.RecieveData) { Hot2gApplication.Instance.setStateToResetGain(); //- リセット後はルーチン内でWaitingに設定される Hot2gApplication.Instance.setState2ToNotOnHead(); } else if (Hot2gApplication.Instance.mode == Hot2gApplication.eMode.Waiting) { /** 非装着中 */ //Hot2gApplication.Instance.setStateToWating(); //Hot2gApplication.Instance.setState2ToNotOnHead(); } } else { if (Hot2gApplication.Instance.mode == Hot2gApplication.eMode.Waiting) /** 装着中検出 */ { /** 非装着 → 装着 */ Hot2gApplication.Instance.setStateToMGC(); Hot2gApplication.Instance.setState2ToOnHead(); } else { /** 装着中 */ Hot2gApplication.Instance.setState2ToOnHead(); } } #if false if (!isupdateActivenesses) { /** 装着 → 非装着 */ if (lastStatus) { Hot2gApplication.Instance.setStateToResetGain(); Hot2gApplication.Instance.setState2ToNotOnHead(); } else { /** 非装着中 */ Hot2gApplication.Instance.setStateToWating(); Hot2gApplication.Instance.setState2ToNotOnHead(); } } else if (!lastStatus) { /** 非装着 → 装着 */ Hot2gApplication.Instance.setStateToMGC(); Hot2gApplication.Instance.setState2ToOnHead(); } else { /** 装着中 */ Hot2gApplication.Instance.setState2ToOnHead(); } #endif } #if false /* * var heartRate = NpodApplication.app.dataStore.heartRate * * if (heartRate.takeLast(30).all { 40 <= it && it <= 180 }) { * isupdateActivenesses = true * } * if (heartRate.takeLast(50).all { it < 40 || 180 < it }) { * isupdateActivenesses = false * } */ List <double> pulseCoef = Hot2gApplication.Instance.datastore.pulseAmplitudeCoeff; List <double> brain1 = Hot2gApplication.Instance.datastore.l1Ac; List <double> brain3 = Hot2gApplication.Instance.datastore.l3Ac; Debug.Log("HRTEST\n" + pulseCoef.Count + "," + Hot2gApplication.Instance.mode.ToString()); int sz = 20; if (pulseCoef.Count > sz) { List <double> takeLast_sz = new List <double>(); List <double> takeLast_sz_brain1 = new List <double>(); List <double> takeLast_sz_brain3 = new List <double>(); for (int i = pulseCoef.Count - 20; i < pulseCoef.Count; i++) { takeLast_sz.Add(pulseCoef[i]); takeLast_sz_brain1.Add(brain1[i]); takeLast_sz_brain3.Add(brain3[i]); } bool lastStatus = isupdateActivenesses; bool cond3 = false; double c3buf = sd(takeLast_sz.ToArray()); if (2 <= c3buf && c3buf <= 1000) { cond3 = true; } Debug.Log("c3buf " + c3buf); bool cond4 = (brain1[brain1.Count - 1] != double.NaN && brain3[brain3.Count - 1] != double.NaN); bool cond5 = max(takeLast_sz_brain1) < 30.0 && max(takeLast_sz_brain3) < 30.0; //bool cond6 = (brain1[brain1.Count - 1] != 0.0 && brain3[brain3.Count - 1] != 0.0); bool cond6 = true; Debug.Log("HRTEST 3:" + cond3 + " 4:" + cond4 + " 5:" + cond5 + " 6:" + cond6); isupdateActivenesses = cond3 && cond4 && cond5 && cond6; /** 非装着時はStateをWatingにキープ */ if (!isupdateActivenesses) { Debug.Log("NotOnHead"); Hot2gApplication.Instance.setStateToWating(); Hot2gApplication.Instance.setState2ToNotOnHead(); } /** 非装着 → 装着 */ if (isupdateActivenesses && !lastStatus) { Debug.Log("Not To OnHead"); Hot2gApplication.Instance.setStateToMGC(); Hot2gApplication.Instance.setState2ToOnHead(); } /** 装着 → 非装着 */ if (!isupdateActivenesses && lastStatus) { Debug.Log("OnHead To Not"); Hot2gApplication.Instance.setStateToResetGain(); Hot2gApplication.Instance.setState2ToNotOnHead(); } } #endif }
/** * ゲイン調整済みデータ受信時の動作 */ private void receiveData(BrainDataFeedbacker nfb, Hot2gEnumerations.EnumHot2gMeasResult e, object data, DataLogger logger) { switch (e) { /*XB-01*/ case Hot2gEnumerations.EnumHot2gMeasResult.Ac1ch: //Debug.Log("Ac1ch:" + LitJson.JsonMapper.ToJson(data)); //- check afterGainCounter checkAfterGainCounter(); if (Hot2gApplication.Instance.datastore.stability.Count > 1) { Debug.Log("Ac1chRec: [ " + Hot2gApplication.Instance.mode.ToString() + " ]/[ " + Hot2gApplication.Instance.datastore.stability[Hot2gApplication.Instance.datastore.stability.Count - 1] + " ]/[: " + Hot2gApplication.Instance.state2.ToString() + " ]/[G1: " + Hot2gApplication.Instance.m_gc.getL1Gain() + "][G3: " + Hot2gApplication.Instance.m_gc.getL3Gain() + " ]/[Raw 1: " + Hot2gApplication.Instance.datastore.l1Ac[Hot2gApplication.Instance.datastore.l1Ac.Count - 1] + " ]/[Raw 3: " + Hot2gApplication.Instance.datastore.l3Ac[Hot2gApplication.Instance.datastore.l3Ac.Count - 1] + " ]/ after MGC: " + Hot2gApplication.Instance.afterMGC_counter.ToString() ); } Xb01data xbData = this.dataStore.add(data as Hot2gMeasData1chAc, nfb.calcActivenessFromBuffered()); state2 = updateStatusOnHead(); //- check XB-01 On head status nfb.bufferActiveness(); //- calc Brain activation level if (logger != null) { logger.write(xbData.ConvCSV()); } break; #if false case Hot2gEnumerations.EnumHot2gMeasResult.Ac2ch: { when(Hot2gDevInfo().valDevType) { /* HOT-2000 */ Hot2gEnumerations.EnumHot2gDevType.HOT2000->{ val hot2Data = this.dataStore.add(data as Hot2gMeasData2chAc) logger?.write(hot2Data) } /* HOT-1000 */ Hot2gEnumerations.EnumHot2gDevType.HOT1000->{ val hot1data = this.dataStore.add(data as Hot2gMeasData2chAc) logger?.write(hot1data) } } #endif /* 心拍数 */ case Hot2gEnumerations.EnumHot2gMeasResult.HeartRate: this.dataStore.add(data as Hot2gMeasDataHR); break; /* 脈波振幅関連係数 */ case Hot2gEnumerations.EnumHot2gMeasResult.HRElement1: this.dataStore.add(data as Hot2gMeasDataHRElement); break; /* 姿勢変化のチェック */ case Hot2gEnumerations.EnumHot2gMeasResult.MotionBatt: GyroScope.Stability s_pre = this.dataStore.stability[this.dataStore.stability.Count - 1]; GyroScope.Stability s = this.dataStore.add(data as Hot2gMeasDataMotBatt); break; } }