Robot Dynamics encompasses the analysis of forces like Coriolis effects, mass distribution, and gravity on a robot, crucial for designing control strategies. This understanding ensures precise and stable movements in various operational scenarios
Robot Dynamics
Here we will simulate the dynamics of the planar robot shown above. We have the dynamics of this robot mentioned in the code.
Now we combine our simulation with the dynamics we have for the specified robot. We will need to get the (𝑥, 𝑦) position of each link to plot the robot. We are using the given simulation parameters and frame rates.
Make a simulation where \(\normalsize \tau = [0, 0]^{𝑇}\) and the robot has no friction.
Make a simulation where \(\normalsize \tau = [0, 0]^{𝑇}\) and the robot has viscous friction 𝐵 = 𝐼.
Make a simulation where \(\normalsize \tau = [20, 5]^{𝑇}\) and the robot has viscous friction 𝐵 = 𝐼.
We can play with the parameters (such as mass, inertia, friction, and 𝜏), and see how these parameters affect the simulation. We can see the implementations below for the simulation codes I am responsible for.
Environment 1: Make a simulation where \(\normalsize \tau = [0, 0]^{𝑇}\) and the robot has no friction.
closeallclearclc% create figurefigureaxis([-2,2,-2,2])gridonholdon% save as a video filev=VideoWriter('Pendulum_Case_1.mp4','MPEG-4');v.FrameRate=100;open(v);% pick your system parametersL1=1;L2=1;m1=1;m2=1;I1=0.1;I2=0.1;g=9.81;tau= [0;0];% Case 1% Initial conditionstheta= [0;0];% joint positionthetadot= [0;0];% joint velocitythetadotdot= [0;0];% joint accelerationmasses= [m1,m2];omega= [0;0;1];Inertia_1= [000;000;00I1];Inertia_2= [000;000;00I2];q1= [0;0;0];% Position of Joint 1q2= [L1;0;0];% Position of Joint 2q3= [L1+L2;0;0];% end effector positionS1= [omega;-cross(omega,q1)];S2= [omega;-cross(omega,q2)];S_eq1= [S1,[0;0;0;0;0;0]];S_eq2= [S1,S2];M1= [eye(3),q2;0001];M2= [eye(3), [L1+L2;0;0];0001];gravity_vector= (zeros(length(theta),1));Coriolis_Matrix= (zeros(2,2));Mass_Matrix= [I1+I2+L1^2*m1+L1^2*m2+L2^2*m2+2*L1*L2*m2*cos(theta(2)),m2*L2^2+L1*m2*cos(theta(2))*L2+I2;m2*L2^2+L1*m2*cos(theta(2))*L2+I2,m2*L2^2+I2];foridx=1:1000% plot the robot% 1. get the position of each linkp0= [0;0];T1=fk(M1,S_eq2(:,1:1),theta(1:1,:));p1=T1(1:2,4);% position of link 1 (location of joint 2)T2=fk(M2,S_eq2,theta);p2=T2(1:2,4);% position of link 2 (the end-effector)P= [p0,p1,p2];% 2. draw the robot and save the framecla;plot(P(1,:),P(2,:),'o-','color',[1,0.5,0],'linewidth',4);drawnow;frame=getframe(gcf);writeVideo(v,frame);% integrate to update velocity and position% your code heredeltaT=0.01;thetadot=thetadot+deltaT*thetadotdot;theta=theta+deltaT*thetadot;Mass_Matrix=[I1+I2+L1^2*m1+L1^2*m2+L2^2*m2+2*L1*L2*m2*cos(theta(2)),m2*L2^2+L1*m2*cos(theta(2))*L2+I2;m2*L2^2+L1*m2*cos(theta(2))*L2+I2,m2*L2^2+I2];Coriolis_Matrix= [-L1*L2*m2*thetadot(2)*sin(theta(2)),-L1*L2*m2*sin(theta(2))*(thetadot(1) +thetadot(2));L1*L2*m2*thetadot(1)*sin(theta(2)),0] ;gravity_vector= [(g*(m1+m2)*L1*cos(theta(1))) +g*m2*L2*cos(theta(1) +theta(2));g*m2*L2*cos(theta(1) +theta(2))];B= [[00] [00]];% Case 1thetadotdot= (inv(Mass_Matrix)) * (tau-Coriolis_Matrix*thetadot-B*thetadot-gravity_vector);endclose(v);closeall
Result:
Environment 2: Make a simulation where \(\normalsize \tau = [0, 0]^𝑇\) and the robot has viscous friction \(\normalsize 𝐵 = 𝐼\).
closeallclearclc% create figurefigureaxis([-2,2,-2,2])gridonholdon% save as a video filev=VideoWriter('Pendulum_Case_2.mp4','MPEG-4');v.FrameRate=100;open(v);% pick your system parametersL1=1;L2=1;m1=1;m2=1;I1=0.1;I2=0.1;g=9.81;tau= [0;0];% Case 2% Initial conditionstheta= [0;0];% joint positionthetadot= [0;0];% joint velocitythetadotdot= [0;0];% joint accelerationmasses= [m1,m2];omega= [0;0;1];Inertia_1= [000;000;00I1];Inertia_2= [000;000;00I2];q1= [0;0;0];% Position of Joint 1q2= [L1;0;0];% Position of Joint 2q3= [L1+L2;0;0];% end effector positionS1= [omega;-cross(omega,q1)];S2= [omega;-cross(omega,q2)];S_eq1= [S1,[0;0;0;0;0;0]];S_eq2= [S1,S2];M1= [eye(3),q2;0001];M2= [eye(3), [L1+L2;0;0];0001];gravity_vector= (zeros(length(theta),1));Coriolis_Matrix= (zeros(2,2));Mass_Matrix= [I1+I2+L1^2*m1+L1^2*m2+L2^2*m2+2*L1*L2*m2*cos(theta(2)),m2*L2^2+L1*m2*cos(theta(2))*L2+I2;m2*L2^2+L1*m2*cos(theta(2))*L2+I2,m2*L2^2+I2];foridx=1:1000% plot the robot% 1. get the position of each linkp0= [0;0];T1=fk(M1,S_eq2(:,1:1),theta(1:1,:));p1=T1(1:2,4);% position of link 1 (location of joint 2)T2=fk(M2,S_eq2,theta);p2=T2(1:2,4);% position of link 2 (the end-effector)P= [p0,p1,p2];% 2. draw the robot and save the framecla;plot(P(1,:),P(2,:),'o-','color',[1,0.5,0],'linewidth',4);drawnow;frame=getframe(gcf);writeVideo(v,frame);% integrate to update velocity and position% your code heredeltaT=0.01;thetadot=thetadot+deltaT*thetadotdot;theta=theta+deltaT*thetadot;Mass_Matrix=[I1+I2+L1^2*m1+L1^2*m2+L2^2*m2+2*L1*L2*m2*cos(theta(2)),m2*L2^2+L1*m2*cos(theta(2))*L2+I2;m2*L2^2+L1*m2*cos(theta(2))*L2+I2,m2*L2^2+I2];Coriolis_Matrix= [-L1*L2*m2*thetadot(2)*sin(theta(2)),-L1*L2*m2*sin(theta(2))*(thetadot(1) +thetadot(2));L1*L2*m2*thetadot(1)*sin(theta(2)),0] ;gravity_vector= [(g*(m1+m2)*L1*cos(theta(1))) +g*m2*L2*cos(theta(1) +theta(2));g*m2*L2*cos(theta(1) +theta(2))];B=eye(2);% Case 2thetadotdot= (inv(Mass_Matrix)) * (tau-Coriolis_Matrix*thetadot-B*thetadot-gravity_vector);endclose(v);closeall
Result:
Environment 3: Make a simulation where \(\normalsize \tau = [20, 5]^𝑇\) and the robot has viscous friction \(\normalsize 𝐵 = 𝐼\).
closeallclearclc% create figurefigureaxis([-2,2,-2,2])gridonholdon% save as a video filev=VideoWriter('Pendulum_Python_3.mp4','MPEG-4');v.FrameRate=100;open(v);% pick your system parametersL1=1;L2=1;m1=1;m2=1;I1=0.1;I2=0.1;g=9.81;tau= [20;5];% Case 3% Initial conditionstheta= [0;0];% joint positionthetadot= [0;0];% joint velocitythetadotdot= [0;0];% joint accelerationmasses= [m1,m2];omega= [0;0;1];Inertia_1= [000;000;00I1];Inertia_2= [000;000;00I2];q1= [0;0;0];% Position of Joint 1q2= [L1;0;0];% Position of Joint 2q3= [L1+L2;0;0];% end effector positionS1= [omega;-cross(omega,q1)];S2= [omega;-cross(omega,q2)];S_eq1= [S1,[0;0;0;0;0;0]];S_eq2= [S1,S2];M1= [eye(3),q2;0001];M2= [eye(3), [L1+L2;0;0];0001];gravity_vector= (zeros(length(theta),1));Coriolis_Matrix= (zeros(2,2));Mass_Matrix= [I1+I2+L1^2*m1+L1^2*m2+L2^2*m2+2*L1*L2*m2*cos(theta(2)),m2*L2^2+L1*m2*cos(theta(2))*L2+I2;m2*L2^2+L1*m2*cos(theta(2))*L2+I2,m2*L2^2+I2];foridx=1:1000% plot the robot% 1. get the position of each linkp0= [0;0];T1=fk(M1,S_eq2(:,1:1),theta(1:1,:));p1=T1(1:2,4);% position of link 1 (location of joint 2)T2=fk(M2,S_eq2,theta);p2=T2(1:2,4);% position of link 2 (the end-effector)P= [p0,p1,p2];% 2. draw the robot and save the framecla;plot(P(1,:),P(2,:),'o-','color',[1,0.5,0],'linewidth',4);drawnow;frame=getframe(gcf);writeVideo(v,frame);% integrate to update velocity and position% your code heredeltaT=0.01;thetadot=thetadot+deltaT*thetadotdot;theta=theta+deltaT*thetadot;Mass_Matrix=[I1+I2+L1^2*m1+L1^2*m2+L2^2*m2+2*L1*L2*m2*cos(theta(2)),m2*L2^2+L1*m2*cos(theta(2))*L2+I2;m2*L2^2+L1*m2*cos(theta(2))*L2+I2,m2*L2^2+I2];Coriolis_Matrix= [-L1*L2*m2*thetadot(2)*sin(theta(2)),-L1*L2*m2*sin(theta(2))*(thetadot(1) +thetadot(2));L1*L2*m2*thetadot(1)*sin(theta(2)),0] ;gravity_vector= [(g*(m1+m2)*L1*cos(theta(1))) +g*m2*L2*cos(theta(1) +theta(2));g*m2*L2*cos(theta(1) +theta(2))];B=eye(2);% Case 3thetadotdot= (inv(Mass_Matrix)) * (tau-Coriolis_Matrix*thetadot-B*thetadot-gravity_vector);endclose(v);closeall
---title: "Robot Dynamics"description: "Robot Dynamics encompasses the analysis of forces like Coriolis effects, mass distribution, and gravity on a robot, crucial for designing control strategies. This understanding ensures precise and stable movements in various operational scenarios"categories: [Robotics]image: Dynamics_Pendulum_Cover_GIF.gifformat: html: code-fold: show code-overflow: wrap code-tools: true---## Robot Dynamics{fig-align="center" width="50%"}Here we will simulate the dynamics of the planar robot shown above. We have the dynamics of this robot mentioned in the code.Now we combine our simulation with the dynamics we have for the specified robot. We will need to get the (𝑥, 𝑦) position of each link to plot the robot. We are using the given simulation parameters and frame rates.- Make a simulation where $\normalsize \tau = [0, 0]^{𝑇}$ and the robot has no friction.- Make a simulation where $\normalsize \tau = [0, 0]^{𝑇}$ and the robot has viscous friction 𝐵 = 𝐼.- Make a simulation where $\normalsize \tau = [20, 5]^{𝑇}$ and the robot has viscous friction 𝐵 = 𝐼.We can play with the parameters (such as mass, inertia, friction, and 𝜏), and see how these parameters affect the simulation. We can see the implementations below for the simulation codes I am responsible for.- **Environment 1:** Make a simulation where $\normalsize \tau = [0, 0]^{𝑇}$ and the robot has no friction.### Implementations#### Python```{python}import numpy as npimport matplotlibmatplotlib.use('Agg') # Set the backend to a non-interactive backendimport matplotlib.pyplot as pltimport matplotlib.animation as animationfrom matplotlib.animation import PillowWriterfrom scipy.spatial.transform import Rotation as Rdef expm(A):return np.linalg.matrix_power(np.eye(A.shape[0]) + A /16, 16)def bracket_s(s):return np.array([[0, -s[2], s[1], s[3]], [s[2], 0, -s[0], s[4]], [-s[1], s[0], 0, s[5]], [0, 0, 0, 0]])def fk(M, S, theta): T = np.eye(4)for i inrange(len(theta)): T = np.dot(T, expm(bracket_s(S[:, i]) * theta[i]))return np.dot(T, M)# System parametersL1 =1L2 =1m1 =1m2 =1I1 =0.1I2 =0.1g =9.81tau = np.array([0, 0]) # Case 1# Initial conditionstheta = np.array([0.0, 0.0])thetadot = np.array([0.0, 0.0])thetadotdot = np.array([0.0, 0.0])omega = np.array([0, 0, 1])q1 = np.array([0, 0, 0])q2 = np.array([L1, 0, 0])q3 = np.array([L1 + L2, 0, 0])S1 = np.hstack((omega, -np.cross(omega, q1)))S2 = np.hstack((omega, -np.cross(omega, q2)))S_eq1 = np.column_stack((S1, np.zeros(6)))S_eq2 = np.column_stack((S1, S2))M1 = np.vstack((np.hstack((np.eye(3), q2[:, None])), [0, 0, 0, 1]))M2 = np.vstack((np.hstack((np.eye(3), np.array([[L1 + L2, 0, 0]]).T)), [0, 0, 0, 1]))# Plot setupmax_reach = L1 + L2fig, ax = plt.subplots()ax.set_xlim(-3, 3)ax.set_ylim(-3, 3)ax.grid()# Animation setupframes =1000deltaT =0.01lines, = ax.plot([], [], 'o-', color=[1, 0.5, 0], linewidth=4)def animate(idx):global theta, thetadot, thetadotdot p0 = np.array([0,0]) T1 = fk(M1, S_eq2[:, 0:1], theta[0:1]) p1 = T1[0:2, 3] T2 = fk(M2, S_eq2, theta) p2 = T2[0:2, 3] P = np.column_stack((p0, p1, p2)) lines.set_data(P[0, :], P[1, :]) thetadot += deltaT * thetadotdot theta += deltaT * thetadot# Dynamics and integration Mass_Matrix = np.array([ [I1 + I2 + L1**2*m1 + L1**2*m2 + L2**2*m2 +2*L1*L2*m2*np.cos(theta[1]), m2*L2**2+ L1*m2*np.cos(theta[1])*L2 + I2], [m2*L2**2+ L1*m2*np.cos(theta[1])*L2 + I2, m2*L2**2+ I2] ]) Coriolis_Matrix = np.array([ [-L1*L2*m2*thetadot[1]*np.sin(theta[1]), -L1*L2*m2*np.sin(theta[1])*(thetadot[0] + thetadot[1])], [L1*L2*m2*thetadot[0]*np.sin(theta[1]), 0] ]) gravity_vector = np.array([ g*(m1 + m2)*L1*np.cos(theta[0]) + g*m2*L2*np.cos(np.sum(theta)), g*m2*L2*np.cos(np.sum(theta)) ]) B = np.array([[0, 0], [0, 0]]) # Case 1 thetadotdot = np.linalg.inv(Mass_Matrix) @ (tau - Coriolis_Matrix @ thetadot - B @ thetadot - gravity_vector)return lines,ani = animation.FuncAnimation(fig, animate, frames=frames, interval=deltaT*1000, blit=False)# Save as GIFani.save('Pendulum_Python_1.gif', writer=PillowWriter(fps=33))```#### MATLAB<details><summary>Code</summary>``` matlabcloseallclearclc% create figurefigureaxis([-2,2,-2,2])gridonholdon% save as a video filev=VideoWriter('Pendulum_Case_1.mp4','MPEG-4');v.FrameRate=100;open(v);% pick your system parametersL1=1;L2=1;m1=1;m2=1;I1=0.1;I2=0.1;g=9.81;tau= [0;0];% Case 1% Initial conditionstheta= [0;0];% joint positionthetadot= [0;0];% joint velocitythetadotdot= [0;0];% joint accelerationmasses= [m1,m2];omega= [0;0;1];Inertia_1= [000;000;00I1];Inertia_2= [000;000;00I2];q1= [0;0;0];% Position of Joint 1q2= [L1;0;0];% Position of Joint 2q3= [L1+L2;0;0];% end effector positionS1= [omega;-cross(omega,q1)];S2= [omega;-cross(omega,q2)];S_eq1= [S1,[0;0;0;0;0;0]];S_eq2= [S1,S2];M1= [eye(3),q2;0001];M2= [eye(3), [L1+L2;0;0];0001];gravity_vector= (zeros(length(theta),1));Coriolis_Matrix= (zeros(2,2));Mass_Matrix= [I1+I2+L1^2*m1+L1^2*m2+L2^2*m2+2*L1*L2*m2*cos(theta(2)),m2*L2^2+L1*m2*cos(theta(2))*L2+I2;m2*L2^2+L1*m2*cos(theta(2))*L2+I2,m2*L2^2+I2];foridx=1:1000% plot the robot% 1. get the position of each linkp0= [0;0];T1=fk(M1,S_eq2(:,1:1),theta(1:1,:));p1=T1(1:2,4);% position of link 1 (location of joint 2)T2=fk(M2,S_eq2,theta);p2=T2(1:2,4);% position of link 2 (the end-effector)P= [p0,p1,p2];% 2. draw the robot and save the framecla;plot(P(1,:),P(2,:),'o-','color',[1,0.5,0],'linewidth',4);drawnow;frame=getframe(gcf);writeVideo(v,frame);% integrate to update velocity and position% your code heredeltaT=0.01;thetadot=thetadot+deltaT*thetadotdot;theta=theta+deltaT*thetadot;Mass_Matrix=[I1+I2+L1^2*m1+L1^2*m2+L2^2*m2+2*L1*L2*m2*cos(theta(2)),m2*L2^2+L1*m2*cos(theta(2))*L2+I2;m2*L2^2+L1*m2*cos(theta(2))*L2+I2,m2*L2^2+I2];Coriolis_Matrix= [-L1*L2*m2*thetadot(2)*sin(theta(2)),-L1*L2*m2*sin(theta(2))*(thetadot(1) +thetadot(2));L1*L2*m2*thetadot(1)*sin(theta(2)),0] ;gravity_vector= [(g*(m1+m2)*L1*cos(theta(1))) +g*m2*L2*cos(theta(1) +theta(2));g*m2*L2*cos(theta(1) +theta(2))];B= [[00] [00]];% Case 1thetadotdot= (inv(Mass_Matrix)) * (tau-Coriolis_Matrix*thetadot-B*thetadot-gravity_vector);endclose(v);closeall```</details>#### Result:<imgsrc="Pendulum_Case_1.gif"alt="Animated GIF"width="50%"height="100%"/>-**Environment2:**Makeasimulationwhere $\normalsize\tau= [0,0]^𝑇$ andtherobothasviscousfriction $\normalsize 𝐵 = 𝐼$.### Implementations#### Python```{python}importnumpyasnpimportmatplotlibmatplotlib.use('Agg') # Setthebackendtoanon-interactivebackendimportmatplotlib.pyplotaspltimportmatplotlib.animationasanimationfrommatplotlib.animationimportPillowWriterfromscipy.spatial.transformimportRotationasRdefexpm(A):returnnp.linalg.matrix_power(np.eye(A.shape[0]) +A/16,16)defbracket_s(s):returnnp.array([[0,-s[2],s[1],s[3]], [s[2],0,-s[0],s[4]], [-s[1],s[0],0,s[5]], [0,0,0,0]])deffk(M,S,theta):T=np.eye(4)foriinrange(len(theta)):T=np.dot(T,expm(bracket_s(S[:,i]) *theta[i]))returnnp.dot(T,M)# SystemparametersL1=1L2=1m1=1m2=1I1=0.1I2=0.1g=9.81tau=np.array([0,0]) # Case2# Initialconditionstheta=np.array([0.0,0.0])thetadot=np.array([0.0,0.0])thetadotdot=np.array([0.0,0.0])omega=np.array([0,0,1])q1=np.array([0,0,0])q2=np.array([L1,0,0])q3=np.array([L1+L2,0,0])S1=np.hstack((omega,-np.cross(omega,q1)))S2=np.hstack((omega,-np.cross(omega,q2)))S_eq1=np.column_stack((S1,np.zeros(6)))S_eq2=np.column_stack((S1,S2))M1=np.vstack((np.hstack((np.eye(3),q2[:,None])), [0,0,0,1]))M2=np.vstack((np.hstack((np.eye(3),np.array([[L1+L2,0,0]]).T)), [0,0,0,1]))# Plotsetupmax_reach=L1+L2fig,ax=plt.subplots()ax.set_xlim(-3,3)ax.set_ylim(-3,3)ax.grid()# Animationsetupframes=1000deltaT=0.01lines,=ax.plot([], [],'o-',color=[1,0.5,0],linewidth=4)defanimate(idx):globaltheta,thetadot,thetadotdotp0=np.array([0,0])T1=fk(M1,S_eq2[:,0:1],theta[0:1])p1=T1[0:2,3]T2=fk(M2,S_eq2,theta)p2=T2[0:2,3]P=np.column_stack((p0,p1,p2))lines.set_data(P[0,:],P[1,:])thetadot+=deltaT*thetadotdottheta+=deltaT*thetadot # DynamicsandintegrationMass_Matrix=np.array([ [I1+I2+L1**2*m1+L1**2*m2+L2**2*m2+2*L1*L2*m2*np.cos(theta[1]),m2*L2**2+L1*m2*np.cos(theta[1])*L2+I2], [m2*L2**2+L1*m2*np.cos(theta[1])*L2+I2,m2*L2**2+I2] ])Coriolis_Matrix=np.array([ [-L1*L2*m2*thetadot[1]*np.sin(theta[1]),-L1*L2*m2*np.sin(theta[1])*(thetadot[0] +thetadot[1])], [L1*L2*m2*thetadot[0]*np.sin(theta[1]),0] ])gravity_vector=np.array([g*(m1+m2)*L1*np.cos(theta[0]) +g*m2*L2*np.cos(np.sum(theta)),g*m2*L2*np.cos(np.sum(theta)) ])B=np.array([[1,0], [0,1]]) # Case2thetadotdot=np.linalg.inv(Mass_Matrix) @ (tau-Coriolis_Matrix@thetadot-B@thetadot-gravity_vector)returnlines,ani=animation.FuncAnimation(fig,animate,frames=frames,interval=deltaT*1000,blit=False)# SaveasGIFani.save('Pendulum_Python_2.gif',writer=PillowWriter(fps=33))```#### MATLAB<details><summary>Code</summary>``` matlabcloseallclearclc% create figurefigureaxis([-2,2,-2,2])gridonholdon% save as a video filev=VideoWriter('Pendulum_Case_2.mp4','MPEG-4');v.FrameRate=100;open(v);% pick your system parametersL1=1;L2=1;m1=1;m2=1;I1=0.1;I2=0.1;g=9.81;tau= [0;0];% Case 2% Initial conditionstheta= [0;0];% joint positionthetadot= [0;0];% joint velocitythetadotdot= [0;0];% joint accelerationmasses= [m1,m2];omega= [0;0;1];Inertia_1= [000;000;00I1];Inertia_2= [000;000;00I2];q1= [0;0;0];% Position of Joint 1q2= [L1;0;0];% Position of Joint 2q3= [L1+L2;0;0];% end effector positionS1= [omega;-cross(omega,q1)];S2= [omega;-cross(omega,q2)];S_eq1= [S1,[0;0;0;0;0;0]];S_eq2= [S1,S2];M1= [eye(3),q2;0001];M2= [eye(3), [L1+L2;0;0];0001];gravity_vector= (zeros(length(theta),1));Coriolis_Matrix= (zeros(2,2));Mass_Matrix= [I1+I2+L1^2*m1+L1^2*m2+L2^2*m2+2*L1*L2*m2*cos(theta(2)),m2*L2^2+L1*m2*cos(theta(2))*L2+I2;m2*L2^2+L1*m2*cos(theta(2))*L2+I2,m2*L2^2+I2];foridx=1:1000% plot the robot% 1. get the position of each linkp0= [0;0];T1=fk(M1,S_eq2(:,1:1),theta(1:1,:));p1=T1(1:2,4);% position of link 1 (location of joint 2)T2=fk(M2,S_eq2,theta);p2=T2(1:2,4);% position of link 2 (the end-effector)P= [p0,p1,p2];% 2. draw the robot and save the framecla;plot(P(1,:),P(2,:),'o-','color',[1,0.5,0],'linewidth',4);drawnow;frame=getframe(gcf);writeVideo(v,frame);% integrate to update velocity and position% your code heredeltaT=0.01;thetadot=thetadot+deltaT*thetadotdot;theta=theta+deltaT*thetadot;Mass_Matrix=[I1+I2+L1^2*m1+L1^2*m2+L2^2*m2+2*L1*L2*m2*cos(theta(2)),m2*L2^2+L1*m2*cos(theta(2))*L2+I2;m2*L2^2+L1*m2*cos(theta(2))*L2+I2,m2*L2^2+I2];Coriolis_Matrix= [-L1*L2*m2*thetadot(2)*sin(theta(2)),-L1*L2*m2*sin(theta(2))*(thetadot(1) +thetadot(2));L1*L2*m2*thetadot(1)*sin(theta(2)),0] ;gravity_vector= [(g*(m1+m2)*L1*cos(theta(1))) +g*m2*L2*cos(theta(1) +theta(2));g*m2*L2*cos(theta(1) +theta(2))];B=eye(2);% Case 2thetadotdot= (inv(Mass_Matrix)) * (tau-Coriolis_Matrix*thetadot-B*thetadot-gravity_vector);endclose(v);closeall```</details>#### Result:<imgsrc="Pendulum_Case_2.gif"alt="Animated GIF"width="50%"height="100%"/>-**Environment3:**Makeasimulationwhere $\normalsize\tau= [20,5]^𝑇$ andtherobothasviscousfriction $\normalsize 𝐵 = 𝐼$.### Implementations#### Python```{python}importnumpyasnpimportmatplotlibmatplotlib.use('Agg') # Setthebackendtoanon-interactivebackendimportmatplotlib.pyplotaspltimportmatplotlib.animationasanimationfrommatplotlib.animationimportPillowWriterfromscipy.spatial.transformimportRotationasRdefexpm(A):returnnp.linalg.matrix_power(np.eye(A.shape[0]) +A/16,16)defbracket_s(s):returnnp.array([[0,-s[2],s[1],s[3]], [s[2],0,-s[0],s[4]], [-s[1],s[0],0,s[5]], [0,0,0,0]])deffk(M,S,theta):T=np.eye(4)foriinrange(len(theta)):T=np.dot(T,expm(bracket_s(S[:,i]) *theta[i]))returnnp.dot(T,M)# SystemparametersL1=1L2=1m1=1m2=1I1=0.1I2=0.1g=9.81tau=np.array([20,5]) # Case3# Initialconditionstheta=np.array([0.0,0.0])thetadot=np.array([0.0,0.0])thetadotdot=np.array([0.0,0.0])omega=np.array([0,0,1])q1=np.array([0,0,0])q2=np.array([L1,0,0])q3=np.array([L1+L2,0,0])S1=np.hstack((omega,-np.cross(omega,q1)))S2=np.hstack((omega,-np.cross(omega,q2)))S_eq1=np.column_stack((S1,np.zeros(6)))S_eq2=np.column_stack((S1,S2))M1=np.vstack((np.hstack((np.eye(3),q2[:,None])), [0,0,0,1]))M2=np.vstack((np.hstack((np.eye(3),np.array([[L1+L2,0,0]]).T)), [0,0,0,1]))# Plotsetupmax_reach=L1+L2fig,ax=plt.subplots()ax.set_xlim(-3,3)ax.set_ylim(-3,3)ax.grid()# Animationsetupframes=1000deltaT=0.01lines,=ax.plot([], [],'o-',color=[1,0.5,0],linewidth=4)defanimate(idx):globaltheta,thetadot,thetadotdotp0=np.array([0,0])T1=fk(M1,S_eq2[:,0:1],theta[0:1])p1=T1[0:2,3]T2=fk(M2,S_eq2,theta)p2=T2[0:2,3]P=np.column_stack((p0,p1,p2))lines.set_data(P[0,:],P[1,:])thetadot+=deltaT*thetadotdottheta+=deltaT*thetadot # DynamicsandintegrationMass_Matrix=np.array([ [I1+I2+L1**2*m1+L1**2*m2+L2**2*m2+2*L1*L2*m2*np.cos(theta[1]),m2*L2**2+L1*m2*np.cos(theta[1])*L2+I2], [m2*L2**2+L1*m2*np.cos(theta[1])*L2+I2,m2*L2**2+I2] ])Coriolis_Matrix=np.array([ [-L1*L2*m2*thetadot[1]*np.sin(theta[1]),-L1*L2*m2*np.sin(theta[1])*(thetadot[0] +thetadot[1])], [L1*L2*m2*thetadot[0]*np.sin(theta[1]),0] ])gravity_vector=np.array([g*(m1+m2)*L1*np.cos(theta[0]) +g*m2*L2*np.cos(np.sum(theta)),g*m2*L2*np.cos(np.sum(theta)) ])B=np.array([[1,0], [0,1]]) # Case3thetadotdot=np.linalg.inv(Mass_Matrix) @ (tau-Coriolis_Matrix@thetadot-B@thetadot-gravity_vector)returnlines,ani=animation.FuncAnimation(fig,animate,frames=frames,interval=deltaT*1000,blit=False)# SaveasGIFani.save('Pendulum_Python_3.gif',writer=PillowWriter(fps=33))```#### MATLAB<details><summary>Code</summary>``` matlabcloseallclearclc% create figurefigureaxis([-2,2,-2,2])gridonholdon% save as a video filev=VideoWriter('Pendulum_Python_3.mp4','MPEG-4');v.FrameRate=100;open(v);% pick your system parametersL1=1;L2=1;m1=1;m2=1;I1=0.1;I2=0.1;g=9.81;tau= [20;5];% Case 3% Initial conditionstheta= [0;0];% joint positionthetadot= [0;0];% joint velocitythetadotdot= [0;0];% joint accelerationmasses= [m1,m2];omega= [0;0;1];Inertia_1= [000;000;00I1];Inertia_2= [000;000;00I2];q1= [0;0;0];% Position of Joint 1q2= [L1;0;0];% Position of Joint 2q3= [L1+L2;0;0];% end effector positionS1= [omega;-cross(omega,q1)];S2= [omega;-cross(omega,q2)];S_eq1= [S1,[0;0;0;0;0;0]];S_eq2= [S1,S2];M1= [eye(3),q2;0001];M2= [eye(3), [L1+L2;0;0];0001];gravity_vector= (zeros(length(theta),1));Coriolis_Matrix= (zeros(2,2));Mass_Matrix= [I1+I2+L1^2*m1+L1^2*m2+L2^2*m2+2*L1*L2*m2*cos(theta(2)),m2*L2^2+L1*m2*cos(theta(2))*L2+I2;m2*L2^2+L1*m2*cos(theta(2))*L2+I2,m2*L2^2+I2];foridx=1:1000% plot the robot% 1. get the position of each linkp0= [0;0];T1=fk(M1,S_eq2(:,1:1),theta(1:1,:));p1=T1(1:2,4);% position of link 1 (location of joint 2)T2=fk(M2,S_eq2,theta);p2=T2(1:2,4);% position of link 2 (the end-effector)P= [p0,p1,p2];% 2. draw the robot and save the framecla;plot(P(1,:),P(2,:),'o-','color',[1,0.5,0],'linewidth',4);drawnow;frame=getframe(gcf);writeVideo(v,frame);% integrate to update velocity and position% your code heredeltaT=0.01;thetadot=thetadot+deltaT*thetadotdot;theta=theta+deltaT*thetadot;Mass_Matrix=[I1+I2+L1^2*m1+L1^2*m2+L2^2*m2+2*L1*L2*m2*cos(theta(2)),m2*L2^2+L1*m2*cos(theta(2))*L2+I2;m2*L2^2+L1*m2*cos(theta(2))*L2+I2,m2*L2^2+I2];Coriolis_Matrix= [-L1*L2*m2*thetadot(2)*sin(theta(2)),-L1*L2*m2*sin(theta(2))*(thetadot(1) +thetadot(2));L1*L2*m2*thetadot(1)*sin(theta(2)),0] ;gravity_vector= [(g*(m1+m2)*L1*cos(theta(1))) +g*m2*L2*cos(theta(1) +theta(2));g*m2*L2*cos(theta(1) +theta(2))];B=eye(2);% Case 3thetadotdot= (inv(Mass_Matrix)) * (tau-Coriolis_Matrix*thetadot-B*thetadot-gravity_vector);endclose(v);closeall```</details>#### Result:<imgsrc="Pendulum_Case_3.gif"alt="Animated GIF"width="50%"height="100%"/>```{=html}<script>consttooltipTriggerList=document.querySelectorAll('[data-bs-toggle="tooltip"]')consttooltipList= [...tooltipTriggerList].map(tooltipTriggerEl=>newbootstrap.Tooltip(tooltipTriggerEl))</script><style>div#quarto-sidebar-glass { display:none!important; }ul.navbar-nav.navbar-nav-scroll { -webkit-flex-direction:row!important; }/* #quarto-sidebar { padding:5px; }#quarto-sidebar>* { padding:5px; }div.sidebar-menu-container>* { padding:5px5px5px5px; }#quarto-margin-sidebar { padding:40px; } */</style>```