1
2
3 """
4 Realizes the simulation of a pendulum.
5
6 Calculates the simulation in steps of about 10ms.
7 (So we don't need the correct differential equations.)
8
9 Beside the movement is also tries to model static and slipping friction.
10 Both values are set to the same value and simply modeled as force against
11 the movement direction. If the friction force is larger then the driving
12 force (external or own mass in movement) the movement stops.
13
14 Also contains some modifiable parameters.
15 """
16 import math
17 import random
18
19
21 """Simulation of a pendulum."""
22
23
24 NO_MOVEMENT = 0.00001
25
27 """Initialize the simulation."""
28 self.X = 0.0
29 self.dX_dT = 0.0
30 self.Phi = math.radians(270.0)
31 self.dPhi_dT = 0.0
32
33 self.a = 0.0
34
35 self.l = 1.0
36 self.m = 1.0
37 self.M_P = 0.1
38 self.a_W = 0.1
39
40 self.W = 1.0
41 self.Z = 0.01
42
43 self.pendulum_moves = 0
44 self.car_moves = 0
45
46
48 """Do one step of time dT.
49 If dT is too large it is subdivided in smaller steps."""
50 n = 1
51 dT_n = dT
52
53
54 if dT/0.01 >= 2.0:
55
56 n = round(dT/0.01)
57 dT_n = dT/float(n)
58
59 for _ in range(n):
60 self.doSmallStep(dT_n)
61
63 """Simulate a small step of not more than 0.02s."""
64
65 while dT > 0.0:
66 time_left = 0.0
67
68 a = self.a * self.W
69
70
71 if (self.car_moves==0) and (abs(a) > self.a_W):
72 self.car_moves = 1
73 if a > 0: self.dX_dT = +Pendulum.NO_MOVEMENT
74 else: self.dX_dT = -Pendulum.NO_MOVEMENT
75
76
77 if (abs(self.dX_dT) < Pendulum.NO_MOVEMENT) and (abs(a) <= self.a_W):
78 self.car_moves = 0
79 self.dX_dT = 0.0
80 a = 0.0
81
82
83 if self.car_moves == 1:
84 if self.dX_dT > 0: a = a - self.a_W
85 else: a = a + self.a_W
86
87 if self.dX_dT * (self.dX_dT + a * dT) < 0.0:
88
89 dT_ = - self.dX_dT/a
90 if abs(dT_) > 1.0E-5 and abs(dT-dT_) > 1.0E-5:
91 time_left = dT - dT_
92 dT = dT_
93
94 while dT > 0.0:
95 time_left2 = 0.0
96
97 M_D = self.l/2.0 * self.m * (
98 9.81 * -math.cos(self.Phi)
99 + a * math.sin(self.Phi)
100 + (self.Z * random.gauss(0.0,1.0)) * math.sin(self.Phi)
101 )
102
103 if (self.pendulum_moves == 0) and (abs(M_D) > self.M_P):
104
105 self.pendulum_moves = 1
106 if M_D > 0.0: self.dPhi_dT = +Pendulum.NO_MOVEMENT
107 else: self.dPhi_dT = -Pendulum.NO_MOVEMENT
108 if (abs(self.dPhi_dT) < Pendulum.NO_MOVEMENT) and (abs(M_D)<=self.M_P):
109
110 self.pendulum_moves = 0
111 self.dPhi_dT = 0.0
112 M_D = 0.0
113
114
115
116 if self.pendulum_moves:
117
118 if self.dPhi_dT > 0: M_D = M_D - self.M_P
119 else: M_D = M_D + self.M_P
120
121 d2Phi_dT2 = M_D/(4.0/3.0 * self.m * self.l*self.l/4.0)
122
123 if self.dPhi_dT * (self.dPhi_dT + d2Phi_dT2 * dT) < 0.0:
124
125 dT_ = - self.dPhi_dT/d2Phi_dT2
126 if abs(dT_) > 1.0E-5 and abs(dT-dT_) > 1.0E-5:
127 time_left2 = dT - dT_
128 dT = dT_
129
130
131 self.Phi += self.dPhi_dT * dT + d2Phi_dT2 * dT*dT
132 while self.Phi < 0.0: self.Phi = self.Phi + 2.0*math.pi
133 while self.Phi >= 2.0*math.pi: self.Phi = self.Phi - 2.0*math.pi
134
135
136 self.dPhi_dT += d2Phi_dT2 * dT
137
138
139 self.X += self.dX_dT * dT + a*dT*dT
140
141
142 self.dX_dT += a*dT
143
144 dT = time_left2
145 dT = time_left
146