|
| 1 | +#!/usr/bin/env python |
| 2 | + |
| 3 | +from sympy import symbols |
| 4 | +import sympy.physics.mechanics as me |
| 5 | + |
| 6 | +print("Defining the problem.") |
| 7 | + |
| 8 | +# The conical pendulum will have three links and three bobs. |
| 9 | +n = 3 |
| 10 | + |
| 11 | +# Each link's orientation is described by two spaced fixed angles: alpha and |
| 12 | +# beta. |
| 13 | + |
| 14 | +# Generalized coordinates |
| 15 | +alpha = me.dynamicsymbols('alpha:{}'.format(n)) |
| 16 | +beta = me.dynamicsymbols('beta:{}'.format(n)) |
| 17 | + |
| 18 | +# Generalized speeds |
| 19 | +omega = me.dynamicsymbols('omega:{}'.format(n)) |
| 20 | +delta = me.dynamicsymbols('delta:{}'.format(n)) |
| 21 | + |
| 22 | +# At each joint there are point masses (i.e. the bobs). |
| 23 | +m_bob = symbols('m:{}'.format(n)) |
| 24 | + |
| 25 | +# Each link is modeled as a cylinder so it will have a lenght, mass, and a |
| 26 | +# symmetric inertia tensor. |
| 27 | +l = symbols('l:{}'.format(n)) |
| 28 | +m_link = symbols('M:{}'.format(n)) |
| 29 | +Ixx = symbols('Ixx:{}'.format(n)) |
| 30 | +Iyy = symbols('Iyy:{}'.format(n)) |
| 31 | +Izz = symbols('Izz:{}'.format(n)) |
| 32 | + |
| 33 | +# Acceleration due to gravity will be used when prescribing the forces |
| 34 | +# acting on the links and bobs. |
| 35 | +g = symbols('g') |
| 36 | + |
| 37 | +# Now defining an inertial reference frame for the system to live in. The Y |
| 38 | +# axis of the frame will be aligned with, but opposite to, the gravity |
| 39 | +# vector. |
| 40 | + |
| 41 | +I = me.ReferenceFrame('I') |
| 42 | + |
| 43 | +# Three reference frames will track the orientation of the three links. |
| 44 | + |
| 45 | +A = me.ReferenceFrame('A') |
| 46 | +A.orient(I, 'Space', [alpha[0], beta[0], 0], 'ZXY') |
| 47 | + |
| 48 | +B = me.ReferenceFrame('B') |
| 49 | +B.orient(A, 'Space', [alpha[1], beta[1], 0], 'ZXY') |
| 50 | + |
| 51 | +C = me.ReferenceFrame('C') |
| 52 | +C.orient(B, 'Space', [alpha[2], beta[2], 0], 'ZXY') |
| 53 | + |
| 54 | +# Define the kinematical differential equations such that the generalized |
| 55 | +# speeds equal the time derivative of the generalized coordinates. |
| 56 | +kinematic_differentials = [] |
| 57 | +for i in range(n): |
| 58 | + kinematic_differentials.append(omega[i] - alpha[i].diff()) |
| 59 | + kinematic_differentials.append(delta[i] - beta[i].diff()) |
| 60 | + |
| 61 | +# The angular velocities of the three frames can then be set. |
| 62 | +A.set_ang_vel(I, omega[0] * I.z + delta[0] * I.x) |
| 63 | +B.set_ang_vel(I, omega[1] * I.z + delta[1] * I.x) |
| 64 | +C.set_ang_vel(I, omega[2] * I.z + delta[2] * I.x) |
| 65 | + |
| 66 | +# The base of the pendulum will be located at a point O which is stationary |
| 67 | +# in the inertial reference frame. |
| 68 | +O = me.Point('O') |
| 69 | +O.set_vel(I, 0) |
| 70 | + |
| 71 | +# The location of the bobs (at the joints between the links) are created by |
| 72 | +# specifiying the vectors between the points. |
| 73 | +P1 = O.locatenew('P1', -l[0] * A.y) |
| 74 | +P2 = P1.locatenew('P2', -l[1] * B.y) |
| 75 | +P3 = P2.locatenew('P3', -l[2] * C.y) |
| 76 | + |
| 77 | +# The velocities of the points can be computed by taking advantage that |
| 78 | +# pairs of points are fixed on the referene frames. |
| 79 | +P1.v2pt_theory(O, I, A) |
| 80 | +P2.v2pt_theory(P1, I, B) |
| 81 | +P3.v2pt_theory(P2, I, C) |
| 82 | +points = [P1, P2, P3] |
| 83 | + |
| 84 | +# Now create a particle to represent each bob. |
| 85 | +Pa1 = me.Particle('Pa1', points[0], m_bob[0]) |
| 86 | +Pa2 = me.Particle('Pa2', points[1], m_bob[1]) |
| 87 | +Pa3 = me.Particle('Pa3', points[2], m_bob[2]) |
| 88 | +particles = [Pa1, Pa2, Pa3] |
| 89 | + |
| 90 | +# The mass centers of each link need to be specified and, assuming a |
| 91 | +# constant density cylinder, it is equidistance from each joint. |
| 92 | +P_link1 = O.locatenew('P_link1', -l[0] / 2 * A.y) |
| 93 | +P_link2 = P1.locatenew('P_link2', -l[1] / 2 * B.y) |
| 94 | +P_link3 = P2.locatenew('P_link3', -l[2] / 2 * C.y) |
| 95 | + |
| 96 | +# The linear velocities can be specified the same way as the bob points. |
| 97 | +P_link1.v2pt_theory(O, I, A) |
| 98 | +P_link2.v2pt_theory(P1, I, B) |
| 99 | +P_link3.v2pt_theory(P2, I, C) |
| 100 | + |
| 101 | +points_rigid_body = [P_link1, P_link2, P_link3] |
| 102 | + |
| 103 | +# The inertia tensors for the links are defined with respect to the mass |
| 104 | +# center of the link and the link's reference frame. |
| 105 | +inertia_link1 = (me.inertia(A, Ixx[0], Iyy[0], Izz[0]), P_link1) |
| 106 | +inertia_link2 = (me.inertia(B, Ixx[1], Iyy[1], Izz[1]), P_link2) |
| 107 | +inertia_link3 = (me.inertia(C, Ixx[2], Iyy[2], Izz[2]), P_link3) |
| 108 | + |
| 109 | +# Now rigid bodies can be created for each link. |
| 110 | +link1 = me.RigidBody('link1', P_link1, A, m_link[0], inertia_link1) |
| 111 | +link2 = me.RigidBody('link2', P_link2, B, m_link[1], inertia_link2) |
| 112 | +link3 = me.RigidBody('link3', P_link3, C, m_link[2], inertia_link3) |
| 113 | +links = [link1, link2, link3] |
| 114 | + |
| 115 | +# The only contributing forces to the system is the force due to gravity |
| 116 | +# acting on each particle and body. |
| 117 | +forces = [] |
| 118 | + |
| 119 | +for particle in particles: |
| 120 | + mass = particle.get_mass() |
| 121 | + point = particle.get_point() |
| 122 | + forces.append((point, -mass * g * I.y)) |
| 123 | + |
| 124 | +for link in links: |
| 125 | + mass = link.get_mass() |
| 126 | + point = link.get_masscenter() |
| 127 | + forces.append((point, -mass * g * I.y)) |
| 128 | + |
| 129 | +# Make a list of all the particles and bodies in the system. |
| 130 | +total_system = links + particles |
| 131 | + |
| 132 | +# Lists of all generalized coordinates and speeds. |
| 133 | +q = alpha + beta |
| 134 | +u = omega + delta |
| 135 | + |
| 136 | +# Now the equations of motion of the system can be formed. |
| 137 | +print("Generating equations of motion.") |
| 138 | +kane = me.KanesMethod(I, q_ind=q, u_ind=u, kd_eqs=kinematic_differentials) |
| 139 | +fr, frstar = kane.kanes_equations(forces, total_system) |
| 140 | +print("Derivation complete.") |
0 commit comments