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