Skip to content

Commit e37919b

Browse files
authored
Two link PID
1 parent ce64033 commit e37919b

File tree

1 file changed

+210
-0
lines changed

1 file changed

+210
-0
lines changed

two_link2.py

+210
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Created on Tue Oct 2 13:09:34 2018
4+
5+
@author: Natarajan Vaidyanathan
6+
"""
7+
8+
# two joint arm in a vertical plane, with gravity
9+
import numpy as np
10+
import matplotlib.pyplot as plt
11+
import matplotlib.animation as animation
12+
from scipy.integrate import odeint
13+
14+
def get_Jee(state,aparams):
15+
l1 = aparams['l1'];l2 = aparams['l2']
16+
a1,a2,a1d,a2d = state
17+
Jee = np.array([[-l1*np.sin(a1)-l2*np.sin(a1+a2),-l2*np.sin(a1+a2)],[l1*np.cos(a1)+l2*np.cos(a1+a2),l2*np.cos(a1+a2)]])
18+
return Jee
19+
20+
def get_Mxee(state,aparams):
21+
a1,a2,a1d,a2d = state;
22+
l1,l2 = aparams['l1'], aparams['l2']
23+
m1,m2 = aparams['m1'], aparams['m2']
24+
M11 = (m1+m2)*l1**2 + m2*l2**2 + 2*m2*l1*l2*np.cos(a2)
25+
M12 = m2*l2**2 + m2*l1*l2*np.cos(a2);M21 = M12
26+
M22 = m2*l2**2
27+
M = np.matrix([[M11,M12],[M21,M22]])
28+
Jee=get_Jee(state,aparams)
29+
return(np.linalg.pinv(Jee @ np.linalg.pinv(M) @Jee.T))
30+
31+
def get_G(state,aparams):
32+
a1,a2,a1d,a2d = state;
33+
l1,l2 = aparams['l1'], aparams['l2']
34+
m1,m2 = aparams['m1'], aparams['m2']; g = aparams['g']
35+
G1 = (m1+m2)*g*l1*np.cos(a1) + m2*g*l2*np.cos(a1+a2)
36+
G2 = m2*g*l2*np.cos(a1+a2)
37+
G = np.matrix([[G1],[G2]]);
38+
return(G)
39+
40+
#Mxee=get_Mxee(statw, aparams)
41+
#Jee=get_Jee(statw, aparams)
42+
#u = Jee.T @ Mxee @(kp*np.array([[xf[0]-xo[0]],[xf[1]-xo[1]]]) )
43+
#%%
44+
45+
# forward dynamics equations of our passive two-joint arm
46+
def get_ctrl(state,aparams,kp,kd):
47+
a1,a2,a1d,a2d = state
48+
l1,l2 = aparams['l1'], aparams['l2']
49+
m1,m2 = aparams['m1'], aparams['m2'];g = aparams['g']
50+
G1 = (m1+m2)*g*l1*np.cos(a1) + m2*g*l2*np.cos(a1+a2)
51+
G2 = m2*g*l2*np.cos(a1+a2)
52+
G = np.matrix([[G1],[G2]]);U =np.matrix([[kp*(xd[0,0]-a1)-kd*a1d],[.5*kp*(xd[1,0]-a2)-kd*a2d]])+G;return U
53+
54+
def get_ctrl2(state,aparams,kp,kd):
55+
"""This is in task space"""
56+
a1,a2,a1d,a2d = state
57+
l1,l2 = aparams['l1'], aparams['l2']
58+
m1,m2 = aparams['m1'], aparams['m2'];g = aparams['g']
59+
G1 = (m1+m2)*g*l1*np.cos(a1) + m2*g*l2*np.cos(a1+a2)
60+
G2 = m2*g*l2*np.cos(a1+a2)
61+
G = np.matrix([[G1],[G2]]);
62+
Mxee=get_Mxee(state, aparams)
63+
Jee=get_Jee(state, aparams)
64+
pa=np.matrix([a1,a2])
65+
pw=np.matrix([a1d,a2d])
66+
px,_ = joints_to_hand(pa,aparams)
67+
pv = Jee@pw.T
68+
U = Jee.T @ Mxee @(kp*np.array([[xf[0]-px[0,0]],[xf[1]-px[0,1]]]) -kd*pv)+G
69+
return U
70+
71+
def twojointarm(state,t,aparams):
72+
a1,a2,a1d,a2d = state
73+
l1,l2 = aparams['l1'], aparams['l2']
74+
m1,m2 = aparams['m1'], aparams['m2']
75+
# i1,i2 = aparams['i1'], aparams['i2']
76+
# r1,r2 = aparams['r1'], aparams['r2']
77+
M11 = (m1+m2)*l1**2 + m2*l2**2 + 2*m2*l1*l2*np.cos(a2)
78+
M12 = m2*l2**2 + m2*l1*l2*np.cos(a2)
79+
M21 = M12
80+
M22 = m2*l2**2
81+
M = np.matrix([[M11,M12],[M21,M22]])
82+
C1 = -m2*l1*l2*(2*a1d*a2d+a2d**2)*np.sin(a2)
83+
C2 = m2*l1*l2*a1d**2*np.sin(a2)
84+
C = np.matrix([[C1],[C2]]);g = aparams['g']
85+
G1 = (m1+m2)*g*l1*np.cos(a1) + m2*g*l2*np.cos(a1+a2)
86+
G2 = m2*g*l2*np.cos(a1+a2)
87+
G = np.matrix([[G1],[G2]]);U = get_ctrl2(state,aparams,kp,kd) ##############################
88+
ACC = np.linalg.inv(M) * (U-C-G)
89+
a1dd,a2dd = ACC[0,0],ACC[1,0]
90+
return [a1d, a2d, a1dd, a2dd]
91+
92+
# parameters of the arm
93+
aparams = {
94+
'l1' : 1.0, # metres
95+
'l2' : 1.0,
96+
'r1' : 0.5,
97+
'r2' : 0.5,
98+
'm1' : 1.0, # kg
99+
'm2' : 1.0,
100+
'i1' : 0.025, # kg*m*m
101+
'i2' : 0.025,
102+
'g' : 10
103+
}
104+
105+
# forward kinematics
106+
def joints_to_hand(A,aparams):
107+
108+
l1 = aparams['l1']
109+
l2 = aparams['l2']
110+
n = np.shape(A)[0]
111+
E = np.zeros((n,2))
112+
H = np.zeros((n,2))
113+
for i in range(n):
114+
E[i,0] = l1 * np.cos(A[i,0])
115+
E[i,1] = l1 * np.sin(A[i,0])
116+
H[i,0] = E[i,0] + (l2 * np.cos(A[i,0]+A[i,1]))
117+
H[i,1] = E[i,1] + (l2 * np.sin(A[i,0]+A[i,1]))
118+
return H,E
119+
120+
def hand2joint(xo,aparams):
121+
l1 = aparams['l1']; l2 = aparams['l2']
122+
r2 = xo[0]**2 + xo[1]**2
123+
C = (r2 - (l1**2 +l2**2))/2*l1*l2
124+
D = np.sqrt(1-C**2)
125+
q2=np.arctan2(D,C)
126+
q1=np.arctan2(xo[1],xo[0])-np.arctan2(l2*np.sin(q2),l1+l2*np.cos(q2))
127+
128+
return (q1,q2)
129+
130+
131+
#%%---------------------------------------------------------------------------------------
132+
133+
134+
def init():
135+
"""initialize animation"""
136+
line.set_data([], [])
137+
plt.xlim([-l1-l2, l1+l2])
138+
plt.ylim([-l1-l2, l1+l2])
139+
time_text.set_text('')
140+
141+
return line, time_text
142+
143+
def animatearm(i):
144+
dt=0.05
145+
thisx = [0, E[i,0], H[i,0]]
146+
thisy = [0, E[i,1], H[i,1]]
147+
148+
line.set_data(thisx, thisy)
149+
time_text.set_text(time_template % (i*dt))
150+
return line, time_text
151+
152+
153+
kp=50; kd=20
154+
#%%
155+
# xo=np.array([1.0,1.0]);xf=np.array([2.0,0])
156+
xo=np.array([0.7,1.5]);xf=np.array([0.04,1.6])
157+
q1,q2=hand2joint(xo,aparams);q3,q4=hand2joint(xf,aparams)
158+
to_animate=True
159+
to_plot=True
160+
#%%
161+
"""
162+
#%%
163+
plt.plot(0,0,'kx')
164+
print(np.rad2deg(q1));print(np.rad2deg(q2))
165+
plt.plot(l1*np.cos(q1),l1*np.sin(q1),'b.');plt.plot(l1*np.cos(q3),l1*np.sin(q3),'g.');
166+
plt.axis('equal');np.rad2deg([q3,q4])
167+
plt.plot(xo[0],xo[1],'bx');plt.plot(xf[0],xf[1],'gx')
168+
ang=np.arange(-np.pi,np.pi,0.01)
169+
plt.plot((l1+l2)*np.cos(ang),(l1+l2)*np.sin(ang),'b');np.rad2deg([q3,q4])
170+
#%%
171+
"""
172+
state0 = [q1, q2, 0, 0] # initial joint angles and vels
173+
xd=np.matrix([[q3],[q4]])
174+
t = np.arange(4001.)/1000 # 10 seconds at 200 Hz
175+
state = odeint(twojointarm, state0, t, args=(aparams,))
176+
#plt.plot(t,state)
177+
A = state[:,[0,1]]
178+
#A[:,0] = A[:,0] - (np.pi/2)
179+
H,E = joints_to_hand(A,aparams)
180+
temp=H.shape[0]
181+
#%%
182+
fig = plt.figure(figsize=(5,5))
183+
l1,l2 = aparams['l1'], aparams['l2'];
184+
ang=np.arange(-np.pi,np.pi,0.01)
185+
ax = fig.add_subplot(111, autoscale_on=False, xlim=([-l1-l2, l1+l2]), ylim=([-l1-l2, l1+l2]))
186+
ax.grid()
187+
ax.plot(xo[0],xo[1],'bx'); ax.plot(xf[0],xf[1],'gx')
188+
ax.plot((l1+l2)*np.cos(ang),(l1+l2)*np.sin(ang),'b');
189+
line, = ax.plot([], [], 'o-', lw=2)
190+
time_template = 'time = %.1fs'
191+
time_text = ax.text(0.05, 0.9, '', transform=ax.transAxes)
192+
193+
#%%
194+
if to_animate:ani=animation.FuncAnimation(fig, animatearm,np.arange(1,temp,5),interval=25, blit=True, init_func=init)
195+
if to_plot:
196+
thisx = [0, E[0,0], H[0,0]]
197+
thisy = [0, E[0,1], H[0,1]]
198+
endx = [0, E[-1,0], H[-1,0]]
199+
endy = [0, E[-1,1], H[-1,1]]
200+
plt.plot(thisx, thisy,'b-o');plt.plot(endx, endy,'g-o');plt.plot(H[:,0],H[:,1],'k--')
201+
plt.plot(0,0,'ko')
202+
plt.axis('equal');
203+
ang=np.arange(-np.pi,np.pi,0.01)
204+
plt.plot((l1+l2)*np.cos(ang),(l1+l2)*np.sin(ang),'b');np.rad2deg([q3,q4])
205+
206+
207+
#%%
208+
#plt.plot(t,state)
209+
210+

0 commit comments

Comments
 (0)