I am trying to model the rotation of a coin. One full rotation is modeled as a change of one parameter from 1 to -1 back to 1, 1 being the straight coin and -1 being the coin upside down. The coin should decelerate progressively. The arguments of the function are the number of half-turns that the coin is meant to make before stopping, the number of frames the movement should take, and the initial speed the coin is rotating at (half rotations per frame).
First I calculate the value of the deceleration with the formula 2*(displacement - initial_v*time) / time*time
. Then I create a list with the distance values for each frame. Here something goes wrong since the values go really really high. (I am omitting the part of the code which restricts the position values between 1 and -1 since something goes wrong before getting to that point).
def animate_rotation(n_half_turns, n_frames, speed):
"""
First I calculate the appropriate deceleration given distance d, initial velocity t_0, and time t
Then I find the position value per frame by calculating the distance given the found acceleration
"""
displacement = n_half_turns # every half turn is a movement from 1 to -1, i.e. 2 units
v = speed # this is the initial speed, i.e. n of half turns per frame
time = n_frames
position = 1
deceleration = 2 * (displacement - v * time) / time*time
#distance traveled from initial position for each frame
frame_distance = []
for i in range(n_frames):
position += v
frame_distance.append(position)
v += deceleration
#the rest of the code transforms the values so that they are between 1 and -1. I eliminated this part because things go wrong before it.
animate_rotation(1, 10, 1)
I would like the new_dist list to get to the n_half_turns value in n_frames number of frames (the length of new_dist list) starting from a certain speed and decelerating appropriately. What I get when running the code however is more like a parable: first the position increases, then it goes beyond n_half_turns, and then goes back to it. The new_dist list is:
[1, 1.8200000000000003, 2.4600000000000004, 2.9200000000000004, 3.2, 3.3000000000000007, 3.2200000000000006, 2.960000000000001, 2.520000000000001, 1.9000000000000012]
Probably a partial answer (there may be other problems) but at least this formula is wrong:
2 * (displacement - v * time) / time*time
because division has precedence over multiplication, so it's equivalent to
2 * (displacement - v * time)
when you wanted it to be:
2 * (displacement - v * time) / (time*time)
Quick demo:
>>> 1/4*4
1.0
>>> 1/(4*4)
0.0625
Also, more a physics thing, in your loop:
for i in range(n_frames):
position += position * v
frame_distance.append(position)
v += v * deceleration
doesn't make sense. Each iteration is the elapsing time if I understand correctly. So you apply the speed to the position by just adding the speed, not the product of the speed with the position, which explains why your positions skyrocket.
Same goes for the speed variation. My proposal:
for i in range(n_frames):
position += v
frame_distance.append(position)
v += deceleration
with all those fixes I get a good looking set of values, not sure they're OK but the look better:
[1.0, 1.0984, 1.1952, 1.2904, 1.384, 1.476, 1.5664, 1.6552, 1.7424, 1.8279999999999998, 1.912, 1.9943999999999997, 2.0751999999999997, 2.1544, 2.2319999999999998, 2.308, 2.3823999999999996, 2.4551999999999996, 2.5263999999999993, 2.595999999999999, 2.6639999999999993, 2.730399999999999, 2.795199999999999, 2.8583999999999987, 2.9199999999999986, 2.9799999999999986, 3.0383999999999984, 3.0951999999999984, 3.1503999999999985, 3.2039999999999984, 3.2559999999999985, 3.3063999999999982, 3.355199999999998, 3.4023999999999983, 3.447999999999998, 3.491999999999998, 3.534399999999998, 3.575199999999998, 3.614399999999998, 3.651999999999998, 3.687999999999998, 3.7223999999999977, 3.7551999999999977, 3.7863999999999978, 3.8159999999999976, 3.8439999999999976, 3.8703999999999974, 3.8951999999999973, 3.918399999999997, 3.9399999999999973, 3.959999999999997, 3.9783999999999966, 3.9951999999999965, 4.010399999999997, 4.023999999999997, 4.035999999999996, 4.046399999999997, 4.055199999999996, 4.062399999999997, 4.067999999999996, 4.071999999999996, 4.074399999999995, 4.075199999999995, 4.074399999999995, 4.071999999999996, 4.067999999999996, 4.062399999999995, 4.055199999999996, 4.046399999999995, 4.035999999999996, 4.023999999999996, 4.010399999999995, 3.9951999999999948, 3.978399999999995, 3.959999999999995, 3.9399999999999946, 3.9183999999999943, 3.8951999999999942, 3.8703999999999943, 3.843999999999994, 3.815999999999994, 3.786399999999994, 3.755199999999994, 3.722399999999994, 3.687999999999994, 3.651999999999994, 3.614399999999994, 3.575199999999994, 3.534399999999994, 3.4919999999999938, 3.4479999999999937, 3.402399999999994, 3.3551999999999937, 3.306399999999994, 3.2559999999999936, 3.2039999999999935, 3.1503999999999936, 3.0951999999999935, 3.0383999999999936, 2.9799999999999933]