Spectral analysis of accelerometer data

Hi,

I wonder if any of you did already tried to implement spectral analysis... What I'm looking into is finding peaks around low frequencies - between 0.5 up to 2 Hz, meaning, sampling around 4Hz should be good enough...

Yet - it means - I'd need to implement FFT what could possibly kill the processor (or to be precise - consume a lot of power).

Why so - after a little of research my idea was to detect horse ride type basing on frequency (there are good research available over the net).

On the other hand - as these are quite low frequencies, I'm thinking that maybe simpler would do quick correlation check for specific frequencies...

Just wonder if any of you tried anything like that :)

  • From the feedback I start to believe - this is not a common topic... If somebody will be interested in my observation - can share later on.

    At the moment did implement FFT on 16Hz sampling (unfortunately it has to be n^2 - and 32Hz sampling is not available) - yet I'm aiming at detecting frequencies around 2-7Hz - so should be good enough.

    It is NOT killing processor so far and I'm doing currently tests to see if detection is good for my use (can be maybe used to detect other activities). Don't know yet if results will be reliable, but at least have some fun :)

  • Very interresting, I've done some attempt at using accelerometer data but have not got so far for now!

  • I tried some of this a couple of years ago to detect a wrist flick, but found the sampling rate was too slow.

  • I'm still collecting data for further analysis. Sampling is pretty low indeed, yet I think that it might be useful at least for my purpose.

    Interesting however is how to combine all three axis - here I still need to think.

    If you want - can share the code (it's not mine anyway - just adjustment to MonkeyC).

  • I'm a bit late to the party, but in case you start having issues with the FFT performance, use a lomb-scargle periodogram instead. Gives the same info but it's a lot faster to compute on limited devices.

  • In case anybody interested.

    Not killing CPU, sampling at 16Hz therefore both - number of samples and sample_rate to be set to 16, sign not used here.

    Hopefully didn't make any mistake :)

    	function FFT(data,number_of_samples,sample_rate,sign) {
    		//variables for the fft
    		var n;
    		var mmax;
    		var m;
    		var j;
    		var istep;
    		var i;//unsigned long
    		
    		//double 
    		var wtemp;
    		var wr;
    		var wpr;
    		var wpi;
    		var wi;
    		var theta;
    		var tempr;
    		var tempi;
    
    		var vector = null;
    		var swap;
    		
    	//the complex array is real+complex so the array 
        //as a size n = 2* number of complex samples
        //real part is the data[index] and 
        //the complex part is the data[index+1]
    
    	//new complex array of size n=2*sample_rate
    	//if(vector!=NULL)
        //    delete [] vector;
    
    		vector = new [2*sample_rate];
    
    	//put the real array in a complex array
    	//the complex part is filled with 0's
    	//the remaining vector with no data is filled with 0's
    		for(n=0; n<sample_rate;n++)
    		{
    			if(n<number_of_samples) {
    				vector[2*n]=data[n];
    			} else {
    				vector[2*n]=0;
    			}
    			vector[2*n+1]=0;
    		}
    
    	//binary inversion (note that the indexes 
        //start from 0 witch means that the
        //real part of the complex is on the even-indexes 
        //and the complex part is on the odd-indexes)
    		n=sample_rate << 1;
    		j=0;
    		for (i=0;i<n/2;i+=2) {
    			if (j > i) {
    				//SWAP(vector[j],vector[i]);
    				swap=vector[j];
    				vector[j] = vector[i];
    				vector[i] = swap;
    				
    				//SWAP(vector[j+1],vector[i+1]);
    				swap=vector[j+1];
    				vector[j+1] = vector[i+1];
    				vector[i+1] = swap;
    				
    				
    				if((j/2)<(n/4)){
    					//SWAP(vector[(n-(i+2))],vector[(n-(j+2))]);
    					swap=vector[(n-(i+2))];
    					vector[(n-(i+2))] = vector[(n-(j+2))];
    					vector[(n-(j+2))] = swap;
    					
    					
    					//SWAP(vector[(n-(i+2))+1],vector[(n-(j+2))+1]);
    					swap=vector[(n-(i+2))+1];
    					vector[(n-(i+2))+1] = vector[(n-(j+2))+1];
    					vector[(n-(j+2))+1] = swap;
    				}
    			}
    			m=n >> 1;
    			while (m >= 2 && j >= m) {
    				j -= m;
    				m >>= 1;
    			}
    			j += m;
    		}
    	//end of the bit-reversed order algorithm
    
    	//f routine
    		mmax=2;
    		while (n > mmax) {
    			istep=mmax << 1;
    			theta=sign*(2.0f*Math.PI/((mmax)*1.0f));
    			wtemp=Math.sin(0.5f*theta);
    			wpr = -2.0f*wtemp*wtemp;
    			wpi=Math.sin(theta);
    			wr=1.0;
    			wi=0.0;
    			for (m=1;m<mmax;m+=2) {
    				for (i=m;i<=n;i+=istep) {
    					j=i+mmax;
    					tempr=wr*vector[j-1]-wi*vector[j];
    					tempi=wr*vector[j]+wi*vector[j-1];
    					vector[j-1]=vector[i-1]-tempr;
    					vector[j]=vector[i]-tempi;
    					vector[i-1] += tempr;
    					vector[i] += tempi;
    				}
    				//wr=(wtemp=wr)*wpr-wi*wpi+wr;
    				wtemp=wr;
    				wr=wtemp*wpr-wi*wpi+wr;
    				wi=wi*wpr+wtemp*wpi+wi;
    			}
    			mmax=istep;
    		}
    	//end of the algorithm
    	
    	//determine the fundamental frequency
    	//look for the maximum absolute value in the complex array
        
        //System.println("Out:" + vector);
    		var fundamental_frequency=0;
    		for(i=2; i<=sample_rate; i+=2)
    		{
    			if((Math.pow(vector[i],2)+Math.pow(vector[i+1],2))>(Math.pow(vector[fundamental_frequency],2)+Math.pow(vector[fundamental_frequency+1],2))){
    			
    				fundamental_frequency=i;
    			
    			}
    		}
    	//since the array of complex has the format [real][complex]=>[absolute value]
    	//the maximum absolute value must be ajusted to half
    		fundamental_frequency= (fundamental_frequency)/2;
    		return fundamental_frequency;
    	}
    
    //end FFT

  • In my case, the use of accelerometer had 2 chalenges :

    * implement a correct/working FIR filter : the lack of garmin doc for that is a great deal of difficulties

    * implement the "gesture/movemetn" recognation : in my case i was not thniking in term of FFT but more in state machine. How would you to that with FFT ?

  • I implemented the same code (the code is from the first website after googeling but apears to be good).
    The implementation is unable to go beyon 512 data points which leaves you at a resolution of 3 something / per min. Kind of sad that the watch dog is killing the process

  • Well, I'm after tests and... it seems, it is useless. Number of samples is far too small to make it usable. I'm abandoning this approach.

    I'll unfortunately analyze only speed.

    It's pity Expressionless 

  • hi, i know that the post is very old and maybe you left the idea to use the FFT but... i tried before to read your post. I was very near to your solution and at the end i used your code but anyway in both cases i had a strange behaviour. 

    The watch can collect some BBI or HRI (heart beat interval) into a vector tipically composed by 9/10 items. I do the FFT on this vector and everything work fine at least on the garmin simulator. I plot the FFT on the screen and its face is very similar to what i was expecting but... when i run on the real device unfortunately i see only zeroes or at least the first bin different from zero! Do you think it is the watchdog killing the process because it is too much time-expensive??

    thank you very much for any answer about