import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import fsolve
plt.style.use('fivethirtyeight')

Creating a pin constraint

In this notebook, you create a general method to constrain two bodies via one pin. Your goal is to create a method that can be reused in different dynamic analyses.

Defining constraints \(\mathbf{C}(\mathbf{q},~t)\)

A kinematic constraint is a function that defines how the geometry of motion is defined in dynamics. You are limiting your analysis to planar motion, so we have already set some kinematic constraints on rigid bodies,

Planar motion constraints

A rigid body has six degrees of freedom. One choice of generalized coordinates is the position of the center of mass, \(\mathbf{r}_G = R_x\hat{i}+R_y\hat{j}+R_z\hat{k}\), and the roll, yaw, and pitch of the object, \(\psi,~\phi,~and~\theta\), respectively. The generalized coordinates are as such

\(\mathbf{q} =\left[R_x,~R_y,~R_z,~\psi,~\phi,~\theta\right]\).

In planar motion, you create 3 constraints:

  1. \(R_z=cst\)

  2. \(\psi=cst\)

  3. \(\phi=cst\)

If you wanted to write these as a set of constraint equations, you have \(\mathbf{C}(\mathbf{q},~t)= \mathbf{0} = \left[\begin{array} ~R_z-cst\\ \psi-cst\\ \phi-cst\end{array}\right]\)

Since these constraints do not affect the motion of a planar system, it is common practice to reduce the degrees of freedom to just

\(\mathbf{q} =\left[R_x,~R_y,\theta\right]\).

General pin constraint

Two bodies constrained by a pin

Now, you have identified 3 degrees of freedom. Your constraints will take the form \(\mathbf{C}(\mathbf{q},~t)= \mathbf{0}\). Consider 2 bodies that have center of mass positions, \(\mathbf{R}^1\) and \(\mathbf{R}^2\). Each body has a coordinate system with origin at \(\mathbf{R}^i\). The transformation from the body coordinate system, \(X^i-Y^i\), to the global, \(X-Y\), is accomplished by rotating about the z axis as such,

\(\mathbf{u}_P = \mathbf{A}^i\mathbf{u}_P^i\)

where

\(\mathbf{A}^i = \left[ \begin{array}{cc} \cos \theta^i & -\sin \theta^i \\ \sin \theta^i & \cos \theta^i \\ \end{array} \right]\) and \(\mathbf{u}_P^i=\left[\begin{array}{c} \bar{x}^{i}_{P} \\ \bar{y}^{i}_{P}\end{array}\right]\)

\(\mathbf{u}_{P}\) is the location of a point \(P\) within body \(i\).

A pin constrains point \(P\), location of a pin, to be equal in both body 1 and 2. The relative position of the pin with respect to each origin is constant as such,

\(\mathbf{R}_P = \mathbf{R}^1+\mathbf{R}_{P/O^1} = \mathbf{R}^2+\mathbf{R}_{P/O^2}\).

Rewriting this equation in terms of \(\mathbf{A}\) and local body coordinate systems, you have

\(\mathbf{C}_{pin}(\mathbf{q},~t)=\mathbf{0} = \mathbf{R}^1 + \mathbf{A}^1\left[\begin{array}{c} \bar{x}^{1}_{P} \\ \bar{y}^{1}_{P}\end{array}\right] - \mathbf{R}^2 - \mathbf{A}^2\left[\begin{array}{c} \bar{x}^{2}_{P} \\ \bar{y}^{2}_{P}\end{array}\right]\)

This equation describes the constraints in a general planar system that has two bodies pinned together.

Post processing results

You now have a \(3\times50\) array with position and orientation of the link in the global coordinate system. You can verify your results by plotting and consider the motion of a compound pendulum.

Plot the generalized coodinates

In the next cell block, you plot the three generalized coordinates as a function of time. Each generalized coordinate is given a subplot and shares a common x-axis. You should notice that the \(R_x^1\propto\theta^1\) because \(\theta^1<<1\).

fig, (ax1, ax2, ax3) = plt.subplots(3)
fig.suptitle(r'Generalized coordinates $\mathbf{q}(t)$')
ax1.plot(t, q[0, :])
ax1.set_ylabel(r'$R^1_x$ (m)');
ax2.plot(t, q[1, :])
ax2.set_ylabel(r'$R^1_y$ (m)');
ax3.plot(t, q[2,:]*180/np.pi)
plt.xlabel('time (s)')
ax3.set_ylabel(r'$\theta$ (deg)')
for ax in fig.get_axes():
    ax.label_outer()
../_images/pin-constraint_14_0.png

Animate the result

In the next few blocks you will

  1. set up a function to plot a ‘link’ shape based upon its generalized coordinate

  2. initialize the lines and coordinate system

  3. create your init and animation functions to update the lines on the plot

  4. display the result in an HTML video

2. initialize the lines and coordinate system

fig, ax = plt.subplots()
link, = ax.plot([], [], linewidth = 10)
marker, = ax.plot([], [], 'o', markersize = 20)
path, = ax.plot([], [])
ax.set_xlim((0, 2))
ax.set_ylim((-1.1, 0.1))
ax.set_xlabel('X-axis (m)')
ax.set_ylabel('Y-axis (m)')
ax.set_title('Pendulum Motion and Path')
Text(0.5, 1.0, 'Pendulum Motion and Path')
../_images/pin-constraint_18_1.png

3. create your init and animation functions to update the lines on the plot

Create an initializing (init) function that clears the previous lines and markers

Create an animating (animate) function that updates the link, base, and path

def init():
    link.set_data([], [])
    marker.set_data([], [])
    path.set_data([], [])
    return (link, path,)
def animate(i):
    '''function that updates the line and marker data
    arguments:
    ----------
    i: index of timestep
    outputs:
    --------
    link: the line object plotted in the above ax.plot(...)
    path: the marker for the end of the 2-bar linkage plotted above with ax.plot('...','o')'''
    
    datax, datay = plot_shape('link', np.array([1]), q[:, i])
    link.set_data(datax, datay)
    pinx, piny = plot_shape('base', [], np.array([xa(t[i]), 0]))
    marker.set_data(pinx, piny)
    path.set_data(q[0, :i+1], q[1, :i+1])
    return (link, path, )

4. display the result in an HTML video

Import the animation and HTML functions. Then, create an animation (anim) variable using the animation.FuncAnimation

from matplotlib import animation
from IPython.display import HTML
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=range(0,len(t)), interval=30, 
                               blit=True)
HTML(anim.to_html5_video())

Wrapping up

In this notebook, you set up and solved a set of constraint equations, \(\mathbf{C}(\mathbf{q},~t)\). The result is an array of generalized coordinates that change over time, but always satisfy a given set of constraints.

Then, you post-processed this data by creating plots and an animation of the results.