public
Description: A Python tool for studying Dynamics
Homepage: http://www.pydy.org
Clone URL: git://github.com/hazelnusse/pydy.git
pydy / examples / gyrostat / gyrostat.py
100755 131 lines (110 sloc) 4.666 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env python
from pydy import *
from sympy import factor
 
# Create a Newtonian reference frame
N = NewtonianReferenceFrame('N')
 
# Declare parameters, coordinates, speeds
params = N.declare_parameters('l1 l2 l3 ma mb g I11 I22 I33 I12 I23 I13 I J K T')
q, qd = N.declare_coords('q', 7)
u, ud = N.declare_speeds('u', 7)
# Unpack the lists
l1, l2, l3, ma, mb, g, I11, I22, I33, I12, I23, I13, I, J, K, T = params
q1, q2, q3, q4, q5, q6, q7 = q
q1d, q2d, q3d, q4d, q5d, q6d, q7d = qd
u1, u2, u3, u4, u5, u6, u7 = u
u1d, u2d, u3d, u4d, u5d, u6d, u7d = ud
 
# Some extra symbols for convenience
l1a, l3a, l1b, l3b = symbols('l1a l3a l1b l3b')
M, Md = symbols('M Md')
 
# Frame fixed to the rigid body
A = N.rotate("A", 'BODY312', (q1, q2, q3), I=(I11, I22, I33, 0, 0, I13))
B = A.rotate("B", 2, q4, I=(I, J, I, 0, 0, 0), I_frame=A)
 
# Create the point AO
AO = Point('AO')
# Locate AO relative to BO
BO = AO.locate('BO', l1*A[1] + l3*A[3])
# Position from ABO to AO
P_ABO_AO = -mass_center(AO, [(AO, ma), (BO, mb)])
# Position from ABO to BO
P_ABO_BO = -mass_center(BO, [(AO, ma), (BO, mb)])
 
l_dict_r = {l1a: dot(P_ABO_AO, A[1]),
            l3a: dot(P_ABO_AO, A[3]),
            l1b: dot(P_ABO_BO, A[1]),
            l3b: dot(P_ABO_BO, A[3])}
l_dict = dict([(v, k) for k, v in l_dict_r.items()])
 
# Locate the mass center of the system
ABO = N.O.locate('ABO', q5*N[1] + q6*N[2] + q7*N[3])
# Overwrite previous definitions of AO and BO
#AO = ABO.locate('AO', P_ABO_AO.subs(l_dict), mass=ma)
#BO = ABO.locate('AO', P_ABO_BO.subs(l_dict), mass=mb)
# Overwrite previous definitions of AO and BO
AO = ABO.locate('AO', P_ABO_AO, mass=ma)
BO = ABO.locate('AO', P_ABO_BO, mass=mb)
 
# Define the generalized speeds
u_rhs = [dot(A.ang_vel(), A[i]) for i in (1, 2, 3)] + \
        [dot(B.ang_vel(), A[2])] + \
        [dot(ABO.vel(), N[i]) for i in (1, 2, 3)]
 
# Form the list of equations mapping qdots to generalized speeds
qd_to_u_eqs = [Eq(ui, ui_rhs) for ui, ui_rhs in zip(u, u_rhs)]
# Form the matrix that maps qdot's to u's
qd_to_u = coefficient_matrix(u_rhs, qd)
adj = qd_to_u.adjugate().expand().subs(N.csqrd_dict).expand()
det = qd_to_u.det(method="berkowitz").expand().subs(N.csqrd_dict).expand()
u_to_qd = (adj / det).expand()#.subs({sin(q2)**2:1-cos(q2)**2}).expand()
 
qd_rhs = u_to_qd * Matrix(u)
# Create a list of kinematic differential equations
u_to_qd_eqs = []
print 'Kinematic differential equations'
for qdot, eqn in zip(qd, qd_rhs):
    u_to_qd_eqs.append(Eq(qdot, eqn.subs({sin(q2)/cos(q2): tan(q2)})))
    print u_to_qd_eqs[-1]
 
# Set velocities and angular velocities using only generalized speeds
A.abs_ang_vel = Vector(u1*A[1] + u2*A[2] + u3*A[3])
B.abs_ang_vel = Vector(u1*A[1] + u4*A[2] + u3*A[3])
ABO.abs_vel = Vector(u5*N[1] + u6*N[2] + u7*N[3])
#AO.abs_vel = ABO.abs_vel + cross(A.ang_vel(N), AO.rel(ABO)).subs(l_dict)
#BO.abs_vel = ABO.abs_vel + cross(A.ang_vel(N), BO.rel(ABO)).subs(l_dict)
AO.abs_vel = ABO.abs_vel + cross(A.ang_vel(N), AO.rel(ABO))#.subs(l_dict)
BO.abs_vel = ABO.abs_vel + cross(A.ang_vel(N), BO.rel(ABO))#.subs(l_dict)
# Set accelerations and angular accelerations
A.abs_ang_acc = dt(A.abs_ang_vel, N)
B.abs_ang_acc = dt(B.abs_ang_vel, N)
ABO.abs_acc = Vector(u5d*N[1] + u6d*N[2] + u7d*N[3])
AO.abs_acc = dt(AO.abs_vel, N)
BO.abs_acc = dt(BO.abs_vel, N)
 
# Apply gravity
N.gravity(g*N[3])
# Apply a torque between the two bodies
B.apply_torque(T*A[2], A)
 
# Form Kane's equations and solve them for the udots
kanes_eqns = N.form_kanes_equations()
 
print 'Dynamic differential equations'
for i in range(7):
    print kanes_eqns[i]
 
# Alternative formulation
AO.mass = S(0)
AO.force = Vector(0)
BO.mass = S(0)
BO.force = Vector(0)
ABO.mass = M
ABO.force = Vector(M*g*N[3])
IAB11, IAB22, IAB33, IAB13 = symbols('IAB11 IAB22 IAB33 IAB13')
A.inertia = Inertia(A, (IAB11, IAB22, IAB33, 0, 0, IAB13))
B.inertia = Inertia(A, (0, J, 0, 0, 0, 0))
 
# Form Kane's equations and solve them for the udots
kanes_eqns2 = N.form_kanes_equations()
 
print 'Dynamic differential equations combined'
for i in range(7):
    print kanes_eqns2[i]
 
I_AO_ABO = inertia_of_point_mass(ma, P_ABO_AO, A)
I_BO_ABO = inertia_of_point_mass(mb, P_ABO_BO, A)
I_A_AO = Dyad({A[1]*A[1]: I11, A[2]*A[2]: I22, A[3]*A[3]:I33, A[1]*A[3]:I13,
    A[3]*A[1]:I13})
 
# Planar components of B's inertia
I_B_BO_p = Dyad({A[1]*A[1]: I, A[3]*A[3]: I})
# Combined system inertia except for B's out of plane moment of inertia
I_SYS_ABO = I_A_AO + I_AO_ABO + I_B_BO_p + I_BO_ABO
 
print 'I_AB11', dot(A[1], dot(I_SYS_ABO, A[1]))
print 'I_AB22', dot(A[2], dot(I_SYS_ABO, A[2]))
print 'I_AB33', dot(A[3], dot(I_SYS_ABO, A[3]))
print 'I_AB13', dot(A[1], dot(I_SYS_ABO, A[3]))