def test_w_diff_dcm1(): # Ref: # Dynamics Theory and Applications, Kane 1985 # Sec. 2.1 ANGULAR VELOCITY A = ReferenceFrame('A') B = ReferenceFrame('B') c11, c12, c13 = dynamicsymbols('C11 C12 C13') c21, c22, c23 = dynamicsymbols('C21 C22 C23') c31, c32, c33 = dynamicsymbols('C31 C32 C33') c11d, c12d, c13d = dynamicsymbols('C11 C12 C13', level=1) c21d, c22d, c23d = dynamicsymbols('C21 C22 C23', level=1) c31d, c32d, c33d = dynamicsymbols('C31 C32 C33', level=1) DCM = Matrix([[c11, c12, c13], [c21, c22, c23], [c31, c32, c33]]) B.orient(A, 'DCM', DCM) b1a = (B.x).express(A) b2a = (B.y).express(A) b3a = (B.z).express(A) # Equation (2.1.1) B.set_ang_vel( A, B.x * (dot((b3a).dt(A), B.y)) + B.y * (dot( (b1a).dt(A), B.z)) + B.z * (dot((b2a).dt(A), B.x))) # Equation (2.1.21) expr = ((c12 * c13d + c22 * c23d + c32 * c33d) * B.x + (c13 * c11d + c23 * c21d + c33 * c31d) * B.y + (c11 * c12d + c21 * c22d + c31 * c32d) * B.z) assert B.ang_vel_in(A) - expr == 0
def test_w_diff_dcm(): a = ReferenceFrame('a') b = ReferenceFrame('b') c11, c12, c13, c21, c22, c23, c31, c32, c33 = dynamicsymbols('c11 c12 c13 c21 c22 c23 c31 c32 c33') c11d, c12d, c13d, c21d, c22d, c23d, c31d, c32d, c33d = dynamicsymbols('c11 c12 c13 c21 c22 c23 c31 c32 c33', 1) b.orient(a, 'DCM', Matrix([c11,c12,c13,c21,c22,c23,c31,c32,c33]).reshape(3, 3)) b1a=(b.x).express(a) b2a=(b.y).express(a) b3a=(b.z).express(a) b.set_ang_vel(a, b.x*(dot((b3a).dt(a), b.y)) + b.y*(dot((b1a).dt(a), b.z)) + b.z*(dot((b2a).dt(a), b.x))) expr = ((c12*c13d + c22*c23d + c32*c33d)*b.x + (c13*c11d + c23*c21d + c33*c31d)*b.y + (c11*c12d + c21*c22d + c31*c32d)*b.z) assert b.ang_vel_in(a) - expr == 0
def test_dot(): assert dot(A.x, A.x) == 1 assert dot(A.x, A.y) == 0 assert dot(A.x, A.z) == 0 assert dot(A.y, A.x) == 0 assert dot(A.y, A.y) == 1 assert dot(A.y, A.z) == 0 assert dot(A.z, A.x) == 0 assert dot(A.z, A.y) == 0 assert dot(A.z, A.z) == 1
def test_Vector(): assert A.x != A.y assert A.y != A.z assert A.z != A.x assert A.x + 0 == A.x v1 = x * A.x + y * A.y + z * A.z v2 = x**2 * A.x + y**2 * A.y + z**2 * A.z v3 = v1 + v2 v4 = v1 - v2 assert isinstance(v1, Vector) assert dot(v1, A.x) == x assert dot(v1, A.y) == y assert dot(v1, A.z) == z assert isinstance(v2, Vector) assert dot(v2, A.x) == x**2 assert dot(v2, A.y) == y**2 assert dot(v2, A.z) == z**2 assert isinstance(v3, Vector) # We probably shouldn't be using simplify in dot... assert dot(v3, A.x) == x**2 + x assert dot(v3, A.y) == y**2 + y assert dot(v3, A.z) == z**2 + z assert isinstance(v4, Vector) # We probably shouldn't be using simplify in dot... assert dot(v4, A.x) == x - x**2 assert dot(v4, A.y) == y - y**2 assert dot(v4, A.z) == z - z**2 assert v1.to_matrix(A) == Matrix([[x], [y], [z]]) q = symbols('q') B = A.orientnew('B', 'Axis', (q, A.x)) assert v1.to_matrix(B) == Matrix([[x], [y * cos(q) + z * sin(q)], [-y * sin(q) + z * cos(q)]]) #Test the separate method B = ReferenceFrame('B') v5 = x * A.x + y * A.y + z * B.z assert Vector(0).separate() == {} assert v1.separate() == {A: v1} assert v5.separate() == {A: x * A.x + y * A.y, B: z * B.z} #Test the free_symbols property v6 = x * A.x + y * A.y + z * A.z assert v6.free_symbols(A) == {x, y, z} raises(TypeError, lambda: v3.applyfunc(v1))
A = ReferenceFrame('A') A_1 = A.orientnew('A_1', 'axis', [ea[0], A.x]) A_2 = A_1.orientnew('A_2', 'axis', [ea[1], A_1.y]) B = A_2.orientnew('B', 'axis', [ea[2], A_2.z]) # display the rotation matrix C from frame A to frame B print('Rotation matrix C:') mprint(B.dcm(A)) # define angular velocity vector w = dynamicsymbols('ω_x ω_y ω_z') omega_A = sum((a * uv for a, uv in zip(w, A)), Vector(0)) omega_B = sum((a * uv for a, uv in zip(w, B)), Vector(0)) # display angular velocity vector omega print('\nangular velocity:') omega = B.ang_vel_in(A) print('ω = {}'.format(msprint(omega))) print('ω_A = {}'.format(msprint(omega.express(A)))) print('ω_B = {}'.format(msprint(omega.express(B)))) # solve for alpha, beta, gamma in terms of angular velocity components dea = [a.diff() for a in ea] for omega_fr, frame in [(omega_A, A), (omega_B, B)]: eqs = [dot(omega - omega_fr, uv) for uv in frame] soln = solve(eqs, dea) print('\nif angular velocity components are taken to be in frame ' '{}'.format(frame)) for a in dea: print('{} = {}'.format(msprint(a), msprint(soln[a])))
A = ReferenceFrame('A') A_1 = A.orientnew('A_1', 'axis', [ea[0], A.x]) A_2 = A_1.orientnew('A_2', 'axis', [ea[1], A_1.y]) B = A_2.orientnew('B', 'axis', [ea[2], A_2.z]) # display the rotation matrix C from frame A to frame B print('Rotation matrix C:') mprint(B.dcm(A)) # define angular velocity vector w = dynamicsymbols('ω_x ω_y ω_z') omega_A = sum((a*uv for a, uv in zip(w, A)), Vector(0)) omega_B = sum((a*uv for a, uv in zip(w, B)), Vector(0)) # display angular velocity vector omega print('\nangular velocity:') omega = B.ang_vel_in(A) print('ω = {}'.format(msprint(omega))) print('ω_A = {}'.format(msprint(omega.express(A)))) print('ω_B = {}'.format(msprint(omega.express(B)))) # solve for alpha, beta, gamma in terms of angular velocity components dea = [a.diff() for a in ea] for omega_fr, frame in [(omega_A, A), (omega_B, B)]: eqs = [dot(omega - omega_fr, uv) for uv in frame] soln = solve(eqs, dea) print('\nif angular velocity components are taken to be in frame ' '{}'.format(frame)) for a in dea: print('{} = {}'.format(msprint(a), msprint(soln[a])))
A, B, mul #%% from sympy import * # import matplotlib.pyplot as plt # import matplotlib as mpl x, y, z = symbols('x y z ') init_printing(use_latex=True) #init_session(quiet=True, use_latex=True) expr = exp(x) * (4 * y - x * y - y**2) deriv_x = diff(expr, x) deriv_y = diff(expr, y) deriv_x, deriv_y # from sympy import * # x,y,z = symbols('x y z ') # init_printing(pretty_print = True) # Integral(sqrt(1/x), x) #%% from sympy import * from sympy.physics.vector import ReferenceFrame, dot init_printing(use_latex=True) # Система отсчета N = ReferenceFrame('N') from sympy import vector x1, x2, y1, y2, z1, z2 = symbols('x1 x2 y1 y2 z1 z2') v1 = x1 * N.x + y1 * N.y + z1 * N.z v2 = x2 * N.x + y2 * N.y + z2 * N.z dot(v1, v2)
print(pC.vel(N).express(N)) print('\ndisc is rolling without slip so v_C_N = 0') print('solving for {} with {} = {}'.format(msprint(q2d), theta, theta_val)) soln = solve(pC.vel(N).magnitude(), q2d) omega2_val = simplify(soln[0].subs(theta, theta_val)) print('{} = {}'.format(msprint(q2d), msprint(soln[0]))) print('{} = {}'.format(msprint(q2d), msprint(omega2_val))) print('\nthe instantaneous axis of rotation of the disk is simply the') print('angular velocity vector with respect to frame N') omega = B.ang_vel_in(N).subs({theta: theta_val, q2d: omega2_val}).express(N) print('ω = {}'.format(omega)) print('\nto be horizontal, dot(N.z, ω) = 0') R_val = solve(dot(N.z, omega), R)[0] print('{} = {} = {}'.format(R, R_val, R_val.subs(theta, theta_val))) print('\nto find the principal axis of rotation \'a\' and principal ' 'angle of rotation \'φ\'') print('we can use the equations') print(' tr(C) = 1 + 2*cos(φ)') print(' a_x = (c_yz - c_zy)/(2*sin(φ))') print(' a_y = (c_zx - c_xz)/(2*sin(φ))') print(' a_z = (c_xy - c_yx)/(2*sin(φ))') C = C.subs({q1: pi/2, q2:0}) phi = acos((C.trace() - 1)/2) a_x = (C[1, 2] - C[2, 1])/(2*sin(phi)) a_y = (C[2, 0] - C[0, 2])/(2*sin(phi)) a_z = (C[0, 1] - C[1, 0])/(2*sin(phi)) a = (a_x*N.x + a_y*N.y + a_z*N.z).simplify()
def test_Vector(): assert A.x != A.y assert A.y != A.z assert A.z != A.x v1 = x * A.x + y * A.y + z * A.z v2 = x ** 2 * A.x + y ** 2 * A.y + z ** 2 * A.z v3 = v1 + v2 v4 = v1 - v2 assert isinstance(v1, Vector) assert dot(v1, A.x) == x assert dot(v1, A.y) == y assert dot(v1, A.z) == z assert isinstance(v2, Vector) assert dot(v2, A.x) == x ** 2 assert dot(v2, A.y) == y ** 2 assert dot(v2, A.z) == z ** 2 assert isinstance(v3, Vector) # We probably shouldn't be using simplify in dot... assert dot(v3, A.x) == x ** 2 + x assert dot(v3, A.y) == y ** 2 + y assert dot(v3, A.z) == z ** 2 + z assert isinstance(v4, Vector) # We probably shouldn't be using simplify in dot... assert dot(v4, A.x) == x - x ** 2 assert dot(v4, A.y) == y - y ** 2 assert dot(v4, A.z) == z - z ** 2 assert v1.to_matrix(A) == Matrix([[x], [y], [z]]) q = symbols("q") B = A.orientnew("B", "Axis", (q, A.x)) assert v1.to_matrix(B) == Matrix([[x], [y * cos(q) + z * sin(q)], [-y * sin(q) + z * cos(q)]])
x = sp.Function('x')(t) y = sp.Function('y')(t) r1, r2, L1, L2, R = sp.symbols('r1, r2, L1, L2, R', real=True) ##### Kinematics ##### X = x * E.x + y * E.y eR = cos(p) * E.x + sin(p) * E.y # Link 1 er1 = cos(t1 + p) * E.x + sin(t1 + p) * E.y Xp = X + R * eR + r1 * er1 Vp = Xp.diff(t, E) n1 = sin(t1 + p) * E.x - cos(t1 + p) * E.y Vn1 = v.dot(Vp, n1) * n1 # Link2 er2 = cos(t2 + t1 + p) * E.x + sin(t2 + t1 + p) * E.y Xq = X + R * eR + L1 * er1 + r2 * er2 Vq = Xq.diff(t, E) n2 = sin(t2 + t1 + p) * E.x - cos(t2 + t1 + p) * E.y Vn2 = v.dot(Vq, n2) * n2 ##### Dynamics ##### Ma, Mv, Iv = sp.symbols('Ma,Mv,Iv', real=True) s1, s2, s3 = sp.symbols('s1,s2,s3', real=True) # Z1 = sp.Rational(1,2)*rho*Cd*H # Z2 = sp.Rational(1,2)*rho*Cdv*Sv
def test_Vector(): assert A.x != A.y assert A.y != A.z assert A.z != A.x v1 = x * A.x + y * A.y + z * A.z v2 = x**2 * A.x + y**2 * A.y + z**2 * A.z v3 = v1 + v2 v4 = v1 - v2 assert isinstance(v1, Vector) assert dot(v1, A.x) == x assert dot(v1, A.y) == y assert dot(v1, A.z) == z assert isinstance(v2, Vector) assert dot(v2, A.x) == x**2 assert dot(v2, A.y) == y**2 assert dot(v2, A.z) == z**2 assert isinstance(v3, Vector) # We probably shouldn't be using simplify in dot... assert dot(v3, A.x) == x**2 + x assert dot(v3, A.y) == y**2 + y assert dot(v3, A.z) == z**2 + z assert isinstance(v4, Vector) # We probably shouldn't be using simplify in dot... assert dot(v4, A.x) == x - x**2 assert dot(v4, A.y) == y - y**2 assert dot(v4, A.z) == z - z**2 assert v1.to_matrix(A) == Matrix([[x], [y], [z]]) q = symbols('q') B = A.orientnew('B', 'Axis', (q, A.x)) assert v1.to_matrix(B) == Matrix([[x], [y * cos(q) + z * sin(q)], [-y * sin(q) + z * cos(q)]])
#MASS : spine link, foot m_spine, m_contact = symbols('m_spine, m_contact') particles = [] g_p = me.Particle('g_p', G, m_spine) particles.append(g_p) rc_p = me.Particle('rc_p', RC, m_contact) particles.append(rc_p) sg_p = me.Particle('sg_p', SG, m_spine) particles.append(sg_p) s1_p = me.Particle('s1_p', S1, m_spine) particles.append(s1_p) for part in particles: part.potential_energy = part.mass * dot(part.point.pos_from(O), inertial_rf.z) #### FORCES # force = (point, vector) # torque = (reference frame, vector) #GRAVITY def apply_gravity_force (particle, inertial_reference_frame): #this function assumes that a variable called 'g' exists and corresponds to a symbol representing gravity constant force = (particle.point, -particle.mass*g*inertial_reference_frame.z) return force gravity_forces = [] for part in particles: gravity_forces.append(apply_gravity_force(part, inertial_rf)) #print(gravity_forces)
pB_hat.v2pt_theory(pB_star, N, B) # pB* and pB^ are both fixed in frame B I_rod = inertia(C, 0, m0*L**2/12, m0*L**2/12, 0, 0, 0) rbC = RigidBody('rod_C', pC_star, C, m0, (I_rod, pC_star)) I_discA = inertia(A, m*r**2/2, m*r**2/4, m*r**2/4, 0, 0, 0) rbA = RigidBody('disc_A', pA_star, A, m, (I_discA, pA_star)) I_discB = inertia(B, m*r**2/2, m*r**2/4, m*r**2/4, 0, 0, 0) rbB = RigidBody('disc_B', pB_star, B, m, (I_discB, pB_star)) print('omega_A_N = {}'.format(msprint(A.ang_vel_in(N).express(C)))) print('v_pA*_N = {}'.format(msprint(pA_hat.vel(N)))) qd_val = solve([dot(pA_hat.vel(N), C.y), dot(pB_hat.vel(N), C.y)], [q2d, q3d]) print(msprint(qd_val)) print('T_A = {}'.format(msprint(simplify(rbA.kinetic_energy(N).subs(qd_val))))) print('T_B = {}'.format(msprint(simplify(rbB.kinetic_energy(N).subs(qd_val))))) T = expand(simplify( rbA.kinetic_energy(N).subs(qd_val) + rbB.kinetic_energy(N).subs(qd_val) + rbC.kinetic_energy(N))) print('T = {}'.format(msprint(T))) #T = rb_disc.kinetic_energy(N).subs({theta: theta_val, q2d: q2d_val}) #print('T = {}'.format(msprint(simplify(T)))) #
def test_operator_match(): """Test that the output of dot, cross, outer functions match operator behavior. """ A = ReferenceFrame('A') v = A.x + A.y d = v | v zerov = Vector(0) zerod = Dyadic(0) # dot products assert d & d == dot(d, d) assert d & zerod == dot(d, zerod) assert zerod & d == dot(zerod, d) assert d & v == dot(d, v) assert v & d == dot(v, d) assert d & zerov == dot(d, zerov) assert zerov & d == dot(zerov, d) raises(TypeError, lambda: dot(d, S(0))) raises(TypeError, lambda: dot(S(0), d)) raises(TypeError, lambda: dot(d, 0)) raises(TypeError, lambda: dot(0, d)) assert v & v == dot(v, v) assert v & zerov == dot(v, zerov) assert zerov & v == dot(zerov, v) raises(TypeError, lambda: dot(v, S(0))) raises(TypeError, lambda: dot(S(0), v)) raises(TypeError, lambda: dot(v, 0)) raises(TypeError, lambda: dot(0, v)) # cross products raises(TypeError, lambda: cross(d, d)) raises(TypeError, lambda: cross(d, zerod)) raises(TypeError, lambda: cross(zerod, d)) assert d ^ v == cross(d, v) assert v ^ d == cross(v, d) assert d ^ zerov == cross(d, zerov) assert zerov ^ d == cross(zerov, d) assert zerov ^ d == cross(zerov, d) raises(TypeError, lambda: cross(d, S(0))) raises(TypeError, lambda: cross(S(0), d)) raises(TypeError, lambda: cross(d, 0)) raises(TypeError, lambda: cross(0, d)) assert v ^ v == cross(v, v) assert v ^ zerov == cross(v, zerov) assert zerov ^ v == cross(zerov, v) raises(TypeError, lambda: cross(v, S(0))) raises(TypeError, lambda: cross(S(0), v)) raises(TypeError, lambda: cross(v, 0)) raises(TypeError, lambda: cross(0, v)) # outer products raises(TypeError, lambda: outer(d, d)) raises(TypeError, lambda: outer(d, zerod)) raises(TypeError, lambda: outer(zerod, d)) raises(TypeError, lambda: outer(d, v)) raises(TypeError, lambda: outer(v, d)) raises(TypeError, lambda: outer(d, zerov)) raises(TypeError, lambda: outer(zerov, d)) raises(TypeError, lambda: outer(zerov, d)) raises(TypeError, lambda: outer(d, S(0))) raises(TypeError, lambda: outer(S(0), d)) raises(TypeError, lambda: outer(d, 0)) raises(TypeError, lambda: outer(0, d)) assert v | v == outer(v, v) assert v | zerov == outer(v, zerov) assert zerov | v == outer(zerov, v) raises(TypeError, lambda: outer(v, S(0))) raises(TypeError, lambda: outer(S(0), v)) raises(TypeError, lambda: outer(v, 0)) raises(TypeError, lambda: outer(0, v))
def test_dot_different_frames(): assert dot(N.x, A.x) == cos(q1) assert dot(N.x, A.y) == -sin(q1) assert dot(N.x, A.z) == 0 assert dot(N.y, A.x) == sin(q1) assert dot(N.y, A.y) == cos(q1) assert dot(N.y, A.z) == 0 assert dot(N.z, A.x) == 0 assert dot(N.z, A.y) == 0 assert dot(N.z, A.z) == 1 assert dot(N.x, A.x + A.y) == sqrt(2)*cos(q1 + pi/4) == dot(A.x + A.y, N.x) assert dot(A.x, C.x) == cos(q3) assert dot(A.x, C.y) == 0 assert dot(A.x, C.z) == sin(q3) assert dot(A.y, C.x) == sin(q2)*sin(q3) assert dot(A.y, C.y) == cos(q2) assert dot(A.y, C.z) == -sin(q2)*cos(q3) assert dot(A.z, C.x) == -cos(q2)*sin(q3) assert dot(A.z, C.y) == sin(q2) assert dot(A.z, C.z) == cos(q2)*cos(q3)
pA_hat.v2pt_theory(pA_star, N, A) # pA* and pA^ are both fixed in frame A pB_hat.v2pt_theory(pB_star, N, B) # pB* and pB^ are both fixed in frame B I_rod = inertia(C, 0, m0 * L**2 / 12, m0 * L**2 / 12, 0, 0, 0) rbC = RigidBody('rod_C', pC_star, C, m0, (I_rod, pC_star)) I_discA = inertia(A, m * r**2 / 2, m * r**2 / 4, m * r**2 / 4, 0, 0, 0) rbA = RigidBody('disc_A', pA_star, A, m, (I_discA, pA_star)) I_discB = inertia(B, m * r**2 / 2, m * r**2 / 4, m * r**2 / 4, 0, 0, 0) rbB = RigidBody('disc_B', pB_star, B, m, (I_discB, pB_star)) print('omega_A_N = {}'.format(msprint(A.ang_vel_in(N).express(C)))) print('v_pA*_N = {}'.format(msprint(pA_hat.vel(N)))) qd_val = solve([dot(pA_hat.vel(N), C.y), dot(pB_hat.vel(N), C.y)], [q2d, q3d]) print(msprint(qd_val)) print('T_A = {}'.format(msprint(simplify(rbA.kinetic_energy(N).subs(qd_val))))) print('T_B = {}'.format(msprint(simplify(rbB.kinetic_energy(N).subs(qd_val))))) T = expand( simplify( rbA.kinetic_energy(N).subs(qd_val) + rbB.kinetic_energy(N).subs(qd_val) + rbC.kinetic_energy(N))) print('T = {}'.format(msprint(T))) #T = rb_disc.kinetic_energy(N).subs({theta: theta_val, q2d: q2d_val}) #print('T = {}'.format(msprint(simplify(T)))) # #t = symbols('t')
def test_dot_different_frames(): assert dot(N.x, A.x) == cos(q1) assert dot(N.x, A.y) == -sin(q1) assert dot(N.x, A.z) == 0 assert dot(N.y, A.x) == sin(q1) assert dot(N.y, A.y) == cos(q1) assert dot(N.y, A.z) == 0 assert dot(N.z, A.x) == 0 assert dot(N.z, A.y) == 0 assert dot(N.z, A.z) == 1 assert dot(N.x, A.x + A.y) == sqrt(2) * cos(q1 + pi / 4) == dot( A.x + A.y, N.x) assert dot(A.x, C.x) == cos(q3) assert dot(A.x, C.y) == 0 assert dot(A.x, C.z) == sin(q3) assert dot(A.y, C.x) == sin(q2) * sin(q3) assert dot(A.y, C.y) == cos(q2) assert dot(A.y, C.z) == -sin(q2) * cos(q3) assert dot(A.z, C.x) == -cos(q2) * sin(q3) assert dot(A.z, C.y) == sin(q2) assert dot(A.z, C.z) == cos(q2) * cos(q3)
def test_Vector(): assert A.x != A.y assert A.y != A.z assert A.z != A.x v1 = x*A.x + y*A.y + z*A.z v2 = x**2*A.x + y**2*A.y + z**2*A.z v3 = v1 + v2 v4 = v1 - v2 assert isinstance(v1, Vector) assert dot(v1, A.x) == x assert dot(v1, A.y) == y assert dot(v1, A.z) == z assert isinstance(v2, Vector) assert dot(v2, A.x) == x**2 assert dot(v2, A.y) == y**2 assert dot(v2, A.z) == z**2 assert isinstance(v3, Vector) # We probably shouldn't be using simplify in dot... assert dot(v3, A.x) == x**2 + x assert dot(v3, A.y) == y**2 + y assert dot(v3, A.z) == z**2 + z assert isinstance(v4, Vector) # We probably shouldn't be using simplify in dot... assert dot(v4, A.x) == x - x**2 assert dot(v4, A.y) == y - y**2 assert dot(v4, A.z) == z - z**2 assert v1.to_matrix(A) == Matrix([[x], [y], [z]]) q = symbols('q') B = A.orientnew('B', 'Axis', (q, A.x)) assert v1.to_matrix(B) == Matrix([[x], [ y * cos(q) + z * sin(q)], [-y * sin(q) + z * cos(q)]]) #Test the separate method B = ReferenceFrame('B') v5 = x*A.x + y*A.y + z*B.z assert Vector(0).separate() == {} assert v1.separate() == {A: v1} assert v5.separate() == {A: x*A.x + y*A.y, B: z*B.z} #Test the free_symbols property v6 = x*A.x + y*A.y + z*A.z assert v6.free_symbols(A) == {x,y,z}
print(pC.vel(N).express(N)) print('\ndisc is rolling without slip so v_C_N = 0') print('solving for {} with {} = {}'.format(msprint(q2d), theta, theta_val)) soln = solve(pC.vel(N).magnitude(), q2d) omega2_val = simplify(soln[0].subs(theta, theta_val)) print('{} = {}'.format(msprint(q2d), msprint(soln[0]))) print('{} = {}'.format(msprint(q2d), msprint(omega2_val))) print('\nthe instantaneous axis of rotation of the disk is simply the') print('angular velocity vector with respect to frame N') omega = B.ang_vel_in(N).subs({theta: theta_val, q2d: omega2_val}).express(N) print('ω = {}'.format(omega)) print('\nto be horizontal, dot(N.z, ω) = 0') R_val = solve(dot(N.z, omega), R)[0] print('{} = {} = {}'.format(R, R_val, R_val.subs(theta, theta_val))) print('\nto find the principal axis of rotation \'a\' and principal ' 'angle of rotation \'φ\'') print('we can use the equations') print(' tr(C) = 1 + 2*cos(φ)') print(' a_x = (c_yz - c_zy)/(2*sin(φ))') print(' a_y = (c_zx - c_xz)/(2*sin(φ))') print(' a_z = (c_xy - c_yx)/(2*sin(φ))') C = C.subs({q1: pi / 2, q2: 0}) phi = acos((C.trace() - 1) / 2) a_x = (C[1, 2] - C[2, 1]) / (2 * sin(phi)) a_y = (C[2, 0] - C[0, 2]) / (2 * sin(phi)) a_z = (C[0, 1] - C[1, 0]) / (2 * sin(phi)) a = (a_x * N.x + a_y * N.y + a_z * N.z).simplify()