Calculating the speed a variable increases (python) - python

I have a small problem that I really cant figure out how to solve after some time googling.
My project consists of a rasberry pi and a rotary encoder that I will use as a sensor to see how fast a shaft is spinning. This is then coded in Python. My problem then is that I have no clue how to calculate this. The rotary encoder is connected directly to the shaft and will spin at the same speed as the shaft, and if I use this code the variable "counter" will increment with 1 per "click". Assuming thats what I have to go on, I need to know how I can calculate how fast counter increases so I can get the speed of the shaft. This is because the shaft will be spinning at diffrent speeds at all times.
The reason I need to know how fast the shaft is spinning is because I have a UI that will display the speed.
I would also appreciate if you have any other approuches that I have missed.
Thank you in advance.

This is how I would calculate the speed :
first add this at the top
import time
then a start time variable
clk = 17
dt = 18
starttime = time.time() ## used to calculate a duration
if you subtract starttime from time.time() you will get how long it has been since you defined the start time variable
( time.time() - starttime )
therefore you then add this
if dtState != clkState:
counter += 1
timetakentospinshaft = time.time() - starttime ## this is how long the shaft took to spin 360 degrees
starttime = time.time() # resetting the duartion
now you have the time taken, so you can calculate the speed by dividing the distance by the time
( speed = distance / time )
the distance can be calculated by multiplying the length of the shaft by 2π (calculation for circumference)
( distance = length of shaft * 2π )

Related

Gravity strength and jump height somehow dependant on framerate - Pygame

I'm currently in the early stages of making a classic 2D platformer using pygame for a school project, and I was experimenting with the jump mechanic, when I ran into this rather strange problem. Even though I have factored in the timedelta between updates, the jump length and height both get shorter when the amount of time between frames increases.
Here I've let 3 instances of the Player object jump across the screen, moving right with a constant speed of 700 pixels/second, and an initial upwards speed of 700 pixels/second. They each had an artificially increased minimal delta_time of 0.001s, 0.017s and 0.1s respectively.
This is how the new speed and position vectors are calculated inside of the Player object's update function, which is called once every frame (the delta_time is passed in from the main update loop):
self.speed.y += 1000.0 * delta_time
self.position += self.speed * delta_time
And this is how delta_time is calculated at the end of every cycle of the main update loop (it is initialized with a value of zero for the first frame):
delta_time = time.time() - pre_time
pre_time = time.time()
if delta_time < min_delta_time:
time.sleep(min_delta_time - delta_time)
delta_time += time.time() - pre_time
pre_time = time.time()
The min_delta_time represents the minimal time between frame updates.
After many attempts at fixing this, I'm pretty certain that the flaw lies in the line that updates the speed, but even after double checking the math, I still can't figure out what the problem is. At first I thought that it could be the delta_time being imprecise, but if that was the case the horizontal speed would also be affected, and the trails would still line up.
So can i change anything to make the jump/gravity more consistent?
This isn't an error in coding so much as a logical error in the model: by modeling an acceleration as taking place instantaneously at update points rather than continuously across the full time span, inaccuracies are introduced which will get larger the sparser the updates.
To illustrate this, consider an object accelerating at 1m/s^2 from stop. If we model this as above with a 1-second interval, after six seconds our model will put the object at 21m. Repeating with a 2-second interval, we'll put it at 24m, and a 3-second interval will put it at 27m. However, the real position should be 18m.
The solution is to consider average velocity over the simulated time span rather than the instantaneous velocity at the sample points. In other words, rather than counting the full span's worth of acceleration, then using the result as the velocity for the whole span, add half of the span's acceleration, use that velocity to calculate distance traveled in that span, then add the remaining half of the acceleration.
So your update logic would become something like:
self.speed.y += 500.0 * delta_time
self.position += self.speed * delta_time
self.speed.y += 500.0 * delta_time

Calculating thd in python

I'm trying to calculate the total harmonic distortion values of ac voltage supplied. I am sampling voltage data using Arduino at over 8 KHz rate and storing those data into a text file. Then I'm trying to calculate thd using the following code snippet written in python:
import numpy as np
import scipy.fftpack
from scipy.fftpack import fft
from numpy import genfromtxt
sampled_data = genfromtxt('/../file.txt',delimiter=',')
abs_yf=np.abs(fft(sampled_data))
#As far as I know, THD=sqrt(sum of square magnitude of
#harmonics+noise)/Fundamental value (Is it correct?)So I'm
#just summing up square of all frequency data obtained from FFT,
#sqrt() them and dividing them with fundamental frequecy value.
def thd(abs_data):
sq_sum=0.0
for r in range(len(abs_data)):
sq_sum=sq_sum+(abs_data[r])**2
sq_harmonics=sq_sum-(max(abs_data))**2.0
thd=100*sq_harmonics**0.5/max(abs_data)
return thd
print "Total Harmonic Distortion(in percent):"
print thd(abs_yf)
Problem is, The obtained Thd values vary within 5% to 25% in my case. (In reality it's not more than 5% actually). What am I doing wrong? Is there any other way to find out thd?
Though this is long quiet, for anyone encountering this post like me: There are a couple of problems with the OP method.
1) The magnitudes returned by FFT include a magnitude of the 0 frequency bin, so the assumption that max(abs_data) is the magnitude corresponding to the fundamental frequency is not correct if there is any DC bias in the signal. This is a problem in the line
thd = 100*sq_harmonics**0.5 / max(abs_data)
The amplitude associated with the 0 frequency can just be ignored as a quick solution.
2) The second half of the abs_data should be thrown out, it is a "mirrored" reflection of the first. This is due to the nature of the Fourier transform.
Both these issues can be addressed by changing the input to the function, i.e by replacing
print thd(abs_yf)
with
print( thd(abs_yf[1:int(len(abs_yf)/2) ]) )
where we have changed the input to not include the first or the last N/2 elements.
The result is still not ideal because the window needs to be exactly an integer number of cycles as the previous answers noted above. Testing with a pure sine with offset and adjusting the window demonstrates that the method works fairly well but fails terribly if significant window errors.
t0=0
tf = 0.02 # integer number of cycles
dt = 1e-4
offset = 0.5
N = int((tf-t0)/dt)
time = np.linspace(0.0,tf,N ) #;
commandSigFreq = 100
Amplitude = 2
waveOfSin = Amplitude*np.sin(2.0*pi*commandSigFreq*time) + offset
abs_yf = np.abs(fft(waveOfSin))
#print("freq is" + str(scipy.fftpack.fftfreq(sampled_data, dt ) ))
#As far as I know, THD=sqrt(sum of square magnitude of
#harmonics+noise)/Fundamental value (Is it correct?)So I'm
#just summing up square of all frequency data obtained from FFT,
#sqrt() them and dividing them with fundamental frequency value.
def thd(abs_data):
sq_sum=0.0
for r in range( len(abs_data)):
sq_sum = sq_sum + (abs_data[r])**2
sq_harmonics = sq_sum -(max(abs_data))**2.0
thd = 100*sq_harmonics**0.5 / max(abs_data)
return thd
print("Total Harmonic Distortion(in percent):")
print(thd(abs_yf[1:int(len(abs_yf)/2) ]))
It is quite likely that you add additional distortion by the measurement process itself.
If you compare an Arduino ADC with a high class measurement device, the values of the Arduino will very likely much worse. At least you need a very stable and jitter-free clock.
Furthermore, the output of the data (I guess via UART) might interfere with the timing of the ADC measurement.

Time aligning signals of different sampling rate with missing values

I am working with signals from two different sensors having different sampling rate one with 10 Hz and one with 1 Hz. I want to time align these two signals as the timing is bit different (in seconds). Also, there were chunks of values missing at random intervals from sensor with 1 Hz sampling rate.
I am purely from CS background and have never worked before on DSP. I would highly appreciate if you point me in right direction.
You are trying to estimate an unknown function using samples taken at 1 Hz rate.
Simplest is just to use the previous sample as the estimated value.
First order linear draws a line through the two previous known values and uses the points on the line as the estimated values. Whenever you get a new sample you replace the 2nd value with the first, and the first with the new value. Keep track of the sample times also so that you can track properly across missing values.
If your samples are t1,v1,t2,v2 for times and values. Current time is t. Then estimated value will be
e = v1 + ((v2 - v1) * (t - t1) / ( t2 - t1))
Note that for t = t1 this evaluates to v1, and for t = t2 this evaluates to v2.

Code to resemble a rowing stroke

I'm working on a small program displaying moving rowing boats. The following shows a simple sample code (Python 2.x):
import time
class Boat:
def __init__(self, pace, spm):
self.pace = pace #velocity of the boat in m/s
self.spm = spm #strokes per minute
self.distance = 0 #distance travelled
def move(self, deltaT):
self.distance = self.distance + (self.pace * deltaT)
boat1 = Boat(3.33, 20)
while True:
boat1.move(0.1)
print boat1.distance
time.sleep(0.1)
As you can see a boat has a pace and rows with a number of strokes per minute. Everytime the method move(deltaT) is called it moves a certain distance according to the pace.
The above boat just travels at a constant pace which is not realistic. A real rowing boat accelerates at the beginning of a stroke and then decelerates after the rowing blades left the water. There are many graphs online which show a typical rowing curve (force shown here, velocity looks similar):
Source: highperformancerowing.net
The pace should be constant over time, but it should change during the stroke.
What is the best way to change the constant velocity into a curve which (at least basically) resembles a more realistic rowing stroke?
Note: Any ideas on how to tag this question better? Is it an algorithm-problem?
If your goal is to simply come up with something visually plausible and not to do a full physical simulation, you can simply add a sine wave to the position.
class Boat:
def __init__(self, pace, spm, var=0.5):
self.pace = pace #average velocity of the boat in m/s
self.sps = spm/60.0 #strokes per second
self.var = var #variation in speed from 0-1
self.totalT = 0 #total time
self.distance = 0 #distance traveled
def move(self, deltaT):
self.totalT += deltaT
self.distance = self.pace * (self.totalT + self.var * math.sin(self.totalT * self.sps * 2*math.pi)
You need to be careful with the variation var, if it gets too high the boat might go backwards and destroy the illusion.
You can convert a curve like this into a polynomial equation for velocity.
A description/example of how to do this can be found at:
python numpy/scipy curve fitting
This shows you how to take a set of x,y coordinates (which you can get by inspection of your existing plot or from actual data) and create a polynomial function.
If you are using the same curve for each Boat object, you could just hard code it into your program. But you could also have a separate polynomial equation for each Boat object as well, assuming each rower or boat has a different profile.
You can perform simple integration of the differential equation of motion. (This is what you are already doing to get space as a function of time, with constant speed, x' = x + V.dt.)
Assume a simple model with a constant force during the stroke and no force during the glide, and drag proportional to the speed.
So the acceleration is a = P - D.v during stroke, and - D.v during glide (deceleration).
The speed is approximated with v' = v + a.dt.
The space is approximated with x' = x + v.dt.
If dt is sufficiently small, this motion should look realistic. You can refine the model with a more accurate force law and better integration techniques like Runge-Kutta, but I am not sure it is worth it.
Below an example plot of speed and space vs time using this technique. It shows speed oscillations quickly establishing a periodic regime, and quasi-linear displacement with undulations.

Calculate histogram of distances between points in big data set

I have big data set, representing 1.2M points in 220 dimensional periodic space (x changes fom (-pi,pi))... (matrix: 1.2M x 220).
I would like to calculate histogram of distances between these points taking into account periodicity. I have written some code in python but still it works quite slow for my test case (I am not even trying to run it on the whole set...).
Can you maybe take a look and help me with some tweaking?
Any suggestions and comments much appreciated.
import numpy as np
# 1000x220 test set (-pi,pi)
d=np.random.random((1000, 220))*2*np.pi-np.pi
# calculating theoretical limit on the histogram range, max distance between
# two points can be pi in each dimension
m=np.zeros(np.shape(d)[1])+np.pi
m_=np.sqrt(np.sum(m**2))
# hist range is from 0 to mm
mm=np.floor(m_)
bins=mm/0.01
m=np.zeros(bins)
# proper calculations
import time
start_time = time.time()
for i in range(np.shape(d)[0]):
diff=d[:-(i+1),:]-d[i+1:,:]
diff=np.absolute(diff)
adiff=diff-np.pi
diff=np.pi-np.absolute(adiff)
s=np.sqrt(np.einsum('ij,ij->i', diff,diff))
m+=np.histogram(s,range=(0,mm),bins=bins)[0]
print time.time() - start_time
I think you will see the most improvement from breaking the main loop to smaller parts by dividing range(...) to a couple of smaller ranges and use the threading module to have a couple of threads run the loop concurrently

Categories