/// <summary> /// this eventhandler should be fired by the derived classes to signal a shake detection /// </summary> /// <param name="gv"></param> public void OnIdleDetected(GMVector gv) { IdleDetectedEvent(this, new MovementEventArgs(gv)); }
/// <summary> /// implement this with the actual vector and use OnShakeEvent to signal a 'Shake' /// </summary> /// <param name="gv"></param> public abstract void addValues(GMVector gv);
public MovementEventArgs(GMVector gmvector) : base() { this._gmvector = gmvector; }
public override void addValues(GMVector gv) { GMVector gvOld; if (myQueue.Count>0)// !_firstCall) { //_samplesPerSecond= //calc samples per second if (!_samplesPerSecondsCalulated) { if (myQueue.Count > 10) { GMVector[] myQueueArray = myQueue.ToArray(); ulong iSamplesCount = 0; ulong iTickSum = 0; ulong tickDiff = 0; for (int c = myQueueArray.Length - 1; c > 1; c--) { iSamplesCount++; tickDiff = myQueueArray[c].Ticks - myQueueArray[c - 1].Ticks; iTickSum += tickDiff; } _samplesPerSecond = (uint)(1000 / (iTickSum / iSamplesCount)); // number of samples per second, ticks stored as milliseconds _samplesPerSecondsCalulated = true; } } //get and store delta gvOld = myQueue.Peek(); //calculate deltaG for current and last sample double deltaG = Math.Abs(gv.Length-gvOld.Length); //save for later use gRMSAverage currentRMS=new gRMSAverage(deltaG, gv.Ticks); myAverages.Enqueue(currentRMS); basicLogger(string.Format("{0}\t{1}\t{2}\t{3}\t{4}", gv.X, gv.Y, gv.Z, gv.Ticks, deltaG)); /* Theory: * RSD: Rapid Shake Detection * acceleration change is the sum of the delta G between consecutive samples divided * by the number of samples per second * Drastic Movement * average acceleration change exceeds about 0.9G per sample (50ms period) * calculated over the last .75 seconds * Sustained Movement * more fequently exceed an acceleration of about 0.5G (0.5G acceleration change per sample) * exceed 0.5G value within time frame for non-consecutive samples (cross counter) * time frame is set to reset after 60 non-consecutive (about 3 seconds at 50ms per sample) samples below 0.5G */ //test for condition1 bool bCondition1=false; if (myAverages.Count > 1) { bCondition1 = condition1(currentRMS); } //test for condition2 bool bCondition2=false; if (myAverages.Count > 1) { gRMSAverage lastRMS = myAverages.Peek(); bCondition2 = condition2(currentRMS, lastRMS); } //=============================================================================================== //start when queue is filled if (myQueue.Count >= 20) { //rapid shake detection (RSD) //Condition1: have at least an average of 0.9G for at least .75 second if(bCondition1 & bCondition2) OnMoveDetected(gv); }//start with filled queue } //else // _firstCall = false; myQueue.Enqueue(gv); gvOld = gv; }
public ulong TicksDiff(GMVector gvNew) { GMVector gvOld=this; ulong diff = gvNew.Ticks - gvOld.Ticks; //one tick is 100 nano seconds, scaled with 10000 to milliseconds return diff; }
/// <summary> /// calc the distance between the end of two vectors /// </summary> /// <param name="gvOld">the vector to compare to</param> /// <returns></returns> public double EuclideanDistance(GMVector gvOld) { return Math.Sqrt(Math.Pow(this.X - gvOld.X, 2) + Math.Pow(this.Y - gvOld.Y, 2) + Math.Pow(this.Z - gvOld.Z, 2)); }