I'm currently occupied in a practicum and my boss wants me to have a FFT ready by the end of the week programmed in java.
Now I already got a code for the FFT from Princeton University: http://introcs.cs.princeton.edu/java/97data/FFT.java
I implemented and extended this code in my project with which I'm now being able to first read the binary input of a signal, then process the FFT on this sample values and then provide the magnitude.
Now I come to my problem.
I inputted the following values which I generated with final double d = Math.sin(i); and looped 8 times (this is just for testing purpose, next week I'll have to input real values).
0.0
0.8414709848078965
0.9092974268256817
0.1411200080598672
-0.7568024953079282
-0.9589242746631385
-0.27941549819892586
0.6569865987187891
so those values come from a pure sine (I don't know the right English word but with pure sine I mean a sine with exactly one frequency for example 50 Hz).
The output is now
0.553732750242242
2.3946469565385193 - 2.0970118573701813i
-1.386684423934684 + 0.9155598966338983i
-0.8810419659226628 + 0.28041399267903344i
-0.8075738836045867
-0.8810419659226628 - 0.28041399267903366i
-1.386684423934684 - 0.9155598966338983i
2.394646956538519 + 2.0970118573701817i
And the magnitudes of the output
0.553732750242242
3.183047718211326
1.6616689248786416
0.9245901540720989
0.8075738836045867
0.924590154072099
1.6616689248786416
3.183047718211326
Now I actually expected the output values to be 0 at each frequency sample point up until I reach the frequency the pure sine is dominated by, where the output should be >0 (for example at 50 Hz). At least that's what my boss expected when he gave me this task.
Summary:
So this is what I'm struggling with. I've read another thread asking about a similar issue, but there are still unanswered questions for me. What am I supposed to do with the given output data? How do I find the most occurring frequency?
I really could need some help or explanation of where my thinking is wrong.
Thanks for listening...
Computing a 512-point fourier transform after applying a simple window function:
w(i)= ((float)i-(float)(n-1f)/2f)
it gives peak at i=25 (max magnitude on result array).
Input was also added with more info such as frequency of sine wave generator (50 Hz) and sampling rate (1kHz or 0.001 seconds per sample) and adding 2PI constant:
initialization now looks like this(as a sin(2xPIxFxi) notation):
for (int i = 0; i < n; i++)
{
v1[i] = ((float)i-(float)(n-1f)/2f)*
(float)Math.Sin(0.001f* 50f*2f*Math.PI*(float)i);
^ ^ ^ ^
| | | |
| F | |
sampling 2xPi constant sample bin
rate(simulation)
}
and result peak looks like:
v2[22] 2145,21852033773
v2[23] 3283,36245333956
v2[24] 6368,06249969329
v2[25] 28160,6579468591 <-- peak
v2[26] 23231,0481898687
v2[27] 1503,8455705291
v2[28] 1708,68502071037
so we have
25
now these steps are in frequency space and input was at 1kHz rate so you can perceive a maximum of 500 Hz harmonic signal(half of sampling rate).
25*500 = 12500
also result range is 0 to N/2 with other half mirrored, and dividing perceivable frequency range(500) to results range(256 for N=512) gives
48.83 Hz
big portion of the error must have been the window function used at the beginning but v2[26] has higher value than v2[24] so actual pick is somewhere closer to v2[26] and smoothed graph of these points should show 50 Hz.
Ignore first element of result array as it is about constant signal level or infinity wavelength or zero frequency.
Here are dft computing codes just to be sure if fft is returning right results:
//a---->b Fourier Transformation brute-force
__kernel void dft(__global float *aRe,
__global float *aIm,
__global float *bRe,
__global float *bIm)
{
int id=get_global_id(0); // thread id
int s=get_global_size(0); // total threads = 512
double cRe=0.0f;
double cIm=0.0f;
double fid=(double)id;
double fmpi2n=(-2.0*M_PI)*fid/(double)s;
for(int i=0;i<s;i++)
{
double fi=(float)i;
double re=cos(fmpi2n*fi);
double im=sin(fmpi2n*fi);
cRe+=aRe[i]*re-aIm[i]*im;
cIm+=aRe[i]*im+aIm[i]*re;
}
bRe[id]=cRe;
bIm[id]=cIm;
}
and to be sure, testing result against inverse-transformation to check if original input signal is achieved again:
// a--->b inverse Fourier Transformation brute force
__kernel void idft(__global float *aRe,
__global float *aIm,
__global float *bRe,
__global float *bIm)
{
int id=get_global_id(0); // thread id
int s=get_global_size(0); // total threads = 512
double cRe=0.0f;
double cIm=0.0f;
for(int i=0;i<s;i++)
{
double re=cos(2.0*M_PI*((double)id)*((double)i)/(double)s);
double im=sin(2.0*M_PI*((double)id)*((double)i)/(double)s);
cRe+=aRe[i]*re-aIm[i]*im;
cIm+=aRe[i]*im+aIm[i]*re;
}
cRe/=(double)s;
cIm/=(double)s;
bRe[id]=cRe;
bIm[id]=cIm;
}
I know it's bad to run slow code on fast machines but this looks so much simpler to try and is scalable to many cores (2.4ms for a 320core-gpu including array copies).
Related
I'd like to use my accelerometer in my car and with the accelerometer values, draw a trajectory in excel or any other platform with the origin in the first position value, that is the beginning of the path.
How can I achieve this? Please give me details I don't have any physics notion.
Please help, thanks in advance.
PS: I already programmed the SensorListener...
I have this for instance:
#Override
public void onSensorChanged(SensorEvent event){
if(last_values != null){
float dt = (event.timestamp - last_timestamp) * NS2S;
for(int index = 0 ; index < 3 ; ++index){
acceleration[index] = event.values[index];
velocity[index] += (acceleration[index] + last_values[index])/2 * dt;
position[index] += velocity[index] * dt;
}
vxarr.add(velocity[0]);
vyarr.add(velocity[1]);
vzarr.add(velocity[2]);
axarr.add(acceleration[0]);
ayarr.add(acceleration[1]);
azarr.add(acceleration[2]);
}
else{
last_values = new float[3];
acceleration = new float[3];
velocity = new float[3];
position = new float[3];
velocity[0] = velocity[1] = velocity[2] = 0f;
position[0] = position[1] = position[2] = 0f;
}
xarr.add(position[0]);
yarr.add(position[1]);
zarr.add(position[2]);
tvX.setText(String.valueOf(acceleration[0]));
tvY.setText(String.valueOf(acceleration[1]));
tvZ.setText(String.valueOf(acceleration[2]));
last_timestamp = event.timestamp;
}
but when I draw a circle with my phone I got this:
Sometimes I have just only negative values and sometimes I have just positive values, I never have negative AND positive values in order to have circle.
Acceleration is the derivative of speed by time (in other words, rate of change of speed); speed is the derivative of position by time. Therefore, acceleration is the second derivative of position. Conversely, position is the second antiderivative of acceleration. You could take the accelerometer measurements and do the double intergration over time to obtain the positions for your trajectory, except for two problems:
1) It's an indefinite integral, i.e. there are infinitely many solutions (see e.g. https://en.wikipedia.org/wiki/Antiderivative). In this context, it means that your measurements tell you nothing about the initial speed. But you can get it from GPS (with limited accuracy) or from user input in some form (e.g. assume the speed is zero when the user hits some button to start calculating the trajectory).
2) Error accumulation. Suppose the accelerometer error in any given direction a = 0.01 m/s^2 (a rough guess based on my phone). Over t = 5 minutes, this gives you an error of a*t^2/2 = 450 meters.
So you can't get a very accurate trajectory, especially over a long period of time. If that doesn't matter to you, you may be able to use code from the other answer, or write your own etc. but first you need to realize the very serious limitations of this approach.
How to calculate the position of the device using the accelerometer values?
Physicists like to think of the position in space of an object at a given time as a mathematical function p(t) with values ( x(t), y(t), z(t) ). The velocity v(t) of that object turns out to be the first derivative of p(t), and the acceleration a(t) nicely fits in as the first derivative of v(t).
From now on, we will just look at one dimension, the other two can be treated in the same way.
In order to get the velocity from the acceleration, we have to "reverse" the operation using our known initial values (without them we would not obtain a unique solution).
Another problem we are facing is that we don't have the acceleration as a function. We just have sample values handed to us more or less frequently by the accelerometer sensor.
So, with a prayer to Einstein, Newton and Riemann, we take these values and think of the acceleration function as a lot of small lines glued together. If the sensor fires often, this will be a very good approximation.
Our problem now has become much simpler: the (indefinite) integral (= antiderivative) to a linear function
f(t) = m*t + b is F(t) = m/2 * t^2 + b*t + c, where c can be chosen to satisfy the initial condition (zero velocity in our case) .
Let's use the point-slope form to model our approximation (with time values t0 and t1 and corresponding acceleration values a0 and a1):
a(t) = a0 + (a1 – a0)/(t1 – t0) * (t – t0)
Then we get (first calculate v(t0) + "integral-between-t0-and-t-of-a", then use t1 in place of t)
v(t1) = v(t0) + (a1 + a0) * (t1 – t0) / 2
Using the same logic, we also get a formula for the position:
p(t1) = p(t0) + (v(t1) + v(t0)) * (t1 – t0) / 2
Translated into code, where last_values is used to store the old acceleration values:
float dt = (event.timestamp - last_timestamp) * NS2S;
for(int index = 0 ; index < 3 ; ++index){
acceleration[index] = event.values[index];
float last_velocity = velocity[index];
velocity[index] += (acceleration[index] + last_values[index])/2 * dt;
position[index] += (velocity[index] + last_velocity )/2 * dt;
last_values[index] = acceleration[index];
}
**EDIT: **
All of this is only useful for us as long as our device is aligned with the world's coordinate system. Which will almost never be the case. So before calculating our values like above, we first have to transform them to world coordinates by using something like the rotation matrix from SensorManager.getRotationMatrix().
There is a code snippet in this answer by Csaba Szugyiczki which shows how to get the rotation matrix.
But as the documentation on getRotationMatrix() states
If the device is accelerating, or placed into a strong magnetic field, the returned matrices may be inaccurate.
...so I'm a bit pessimistic about using it while driving a car.
My particular case of summing digits deals with colors represented as integer. Java function BufferedImage.getRGB returns image in 0x00RRGGBB format. I'm making a function that gives you grayscale (color independent) sum of colors on the image. Currently, my operation looks very naive:
//Just a pseudocode
int sum = 0;
for(x->width) {
for(y->height) {
int pixel = image.getRGB(x,y);
sum+=(pixel&0x00FF0000)+(pixel&0x0000FF00)+(pixel&0x000000FF);
}
}
//The average value for any color then equals:
float avg = sum/(width*height*3);
I was wondering if I could do it even faster with some bit-shifting logic. And I am mostly asking this question to learn more about bit-shifting as I doubt any answer will speed up the program really significantly.
R, G and B do not attribute equally to the perceived intensity. A better way to sum things up than this:
sum+=(pixel&0x00FF0000)+(pixel&0x0000FF00)+(pixel&0x000000FF);
Would be, with the necessary bitshifting and weighing (assuming 00RRGGBB):
sum+= ((pixel&0x00FF0000)>>16) * .30 / 255
+ ((pixel&0x0000FF00)>> 8) * .59 / 255
+ (pixel&0x000000FF) * .11 / 255;
You might want to leave the /255 part out here and replace the floating point numbers with scaled-up integer numbers (like 30, 59 and 11), bearing in mind that you'll need a long sum to prevent overflow to a reasonable degree.
I'm trying to write a GPS tracking (akin to a jogging app) on android and the issue of GPS location jitter has reared it's ugly head. When accuracy is FINE and accuracy is within 5 meters, the position is jittering 1-n meters per second. How do you determine or filter out this jitter from legitimate movement?
Sporypal etc apps clearly have some way they are filtering out this noise.
Any thoughts?
Could you just run the positions through a low pass filter?
Something of the order
x(n) = (1-K)*x(n-1) + K*S(n)
where
S is your noisy samples and x, the low pass filtered samples. K is a constant between 0 and 1 which you would probably have to experiment with for best performance.
Per TK's suggestion:
My pseudocode will look awfully C like:
float noisy_lat[128], noisy_long[128];
float smoothed_lat[128], smoothed_lon[128];
float lat_delay=0., lon_delay=0.;
float smooth(float in[], float out[], int n, float K, float delay)
{
int i;
for (i=0; i<n; i++) {
*out = *in++ * K + delay * (1-K);
delay = *out++;
}
return delay;
}
loop:
Get new samples of position in noisy_lat and noise_lon
// LPF the noise samples to produce smoother position data
lat_delay = smooth(noisy_lat, smoothed_lat, 128, K, lat_delay);
lon_delay = smooth(noisy_lon, smoothed_lon, 128, K, lon_delay);
// Rinse. Repeat.
go to loop:
In a nutshell, this is a simply a feedback integrator with a one-sample delay. If your input has low frequency white-ish noise on top of the desired signal, this integrator will average the input signal over time, thus causing the noise components to average out to near zero, leaving you with the desired signal.
How well it works will depend on how much noise your signal has and the filter feedback factor K. As I said before, you'll have to play around a bit with the value to see which value produces the cleanest, most desirable result.
How, in Java, would you generate a random number but make that random number skewed toward a specific number. For example, I want to generate a number between 1 and 100 inclusive, but I want that number skewed toward say, 75. But I still want the possibility of getting other numbers in the range, but I want more of a change of getting numbers close to say 75 as opposed to just getting random numbers all across the range. Thanks
Question is a bit old, but if anyone wants to do this without the special case handling, you can use a function like this:
final static public Random RANDOM = new Random(System.currentTimeMillis());
static public double nextSkewedBoundedDouble(double min, double max, double skew, double bias) {
double range = max - min;
double mid = min + range / 2.0;
double unitGaussian = RANDOM.nextGaussian();
double biasFactor = Math.exp(bias);
double retval = mid+(range*(biasFactor/(biasFactor+Math.exp(-unitGaussian/skew))-0.5));
return retval;
}
The parameters do the following:
min - the minimum skewed value possible
max - the maximum skewed value possible
skew - the degree to which the values cluster around the mode of the distribution; higher values mean tighter clustering
bias - the tendency of the mode to approach the min, max or midpoint value; positive values bias toward max, negative values toward min
Try http://download.oracle.com/javase/6/docs/api/java/util/Random.html#nextGaussian()
Math.max(1, Math.min(100, (int) 75 + Random.nextGaussian() * stddev)))
Pick a stddev like 10 and play around until you get the distribution you want. There are going to be slightly more at 1 and 100 though than at 2 or 99. If you want to change the rate at which it drops off, you can raise the gaussian to a power.
How can I randomly generate letters according to their frequency of use in common speech?
Any pseudo-code appreciated, but an implementation in Java would be fantastic. Otherwise just a poke in the right direction would be helpful.
Note: I don't need to generate the frequencies of usage - I'm sure I can look that up easily enough.
I am assuming that you store the frequencies as floating point numbers between 0 and 1 that total to make 1.
First you should prepare a table of cumulative frequencies, i.e. the sum of the frequency of that letter and all letters before it.
To simplify, if you start with this frequency distribution:
A 0.1
B 0.3
C 0.4
D 0.2
Your cumulative frequency table would be:
A 0.1
B 0.4 (= 0.1 + 0.3)
C 0.8 (= 0.1 + 0.3 + 0.4)
D 1.0 (= 0.1 + 0.3 + 0.4 + 0.2)
Now generate a random number between 0 and 1 and see where in this list that number lies. Choose the letter that has the smallest cumulative frequency larger than your random number. Some examples:
Say you randomly pick 0.612. This lies between 0.4 and 0.8, i.e. between B and C, so you'd choose C.
If your random number was 0.039, that comes before 0.1, i.e. before A, so choose A.
I hope that makes sense, otherwise feel free to ask for clarifications!
One quick way to do it would be to generate a list of letters, where each letter appeared in the list in accordance with its frequency. Say, if "e" was used 25.6% of the time, and your list had length 1000, it would have 256 "e"s.
Then you could just randomly pick spots from the list by using (int) (Math.random() * 1000) to generate random numbers between 0 and 999.
What I would do is scale the relative frequencies as floating point numbers such that their sum is 1.0. Then I would create an array of the cumulative totals per letter, i.e. the number that must be topped to get that letter and all those "below" it. Say the frequency of A is 10%, b is 2% and z is 1%; then your table would look something like this:
0.000 A ; from 0% to 10% gets you an A
0.100 B ; above 10% is at least a B
0.120 C ; 12% for C...
...
0.990 Z ; if your number is >= 99% then you get a Z
Then you generate yourself a random number between 0.0 and 1.0 and do a binary search in the array for the first number smaller than your random number. Then pick the letter at that position. Done.
Not even a pseudo-code, but a possible approach is as follows:
Let p1, p2, ..., pk be the frequencies that you want to match.
Calculate the cumulative frequencies: p1, p1+p2, p1+p2+p3, ... , 1
Generate a random uniform (0,1) number x
Check which interval of the cumulative frequencies x belongs to: if it is between, say, p1+..+pi and p1+...+pi+p(i+1), then output the (i+1)st letter
Depending on how you implement the interval-finding, the procedure is usually more efficient if the p1,p2,... are sorted in decreasing order, because you will usually find the interval containing x sooner.
Using a binary tree gives you a nice, clean way to find the right entry. Here, you start with a frequency map, where the keys are the symbols (English letters), and the values are the frequency of their occurrence. This gets inverted, and a NavigableMap is created where the keys are cumulative probability, and the values are symbols. That makes the lookup easy.
private final Random generator = new Random();
private final NavigableMap<Float, Integer> table =
new TreeMap<Float, Integer>();
private final float max;
public Frequency(Map<Integer, Float> frequency)
{
float total = 0;
for (Map.Entry<Integer, Float> e : frequency.entrySet()) {
total += e.getValue();
table.put(total, e.getKey());
}
max = total;
}
/**
* Choose a random symbol. The choices are weighted by frequency.
*/
public int roll()
{
Float key = generator.nextFloat() * max;
return table.higherEntry(key).getValue();
}