Diff of /URBasic/manipulation.py [000000] .. [c1b1c5]

Switch to unified view

a b/URBasic/manipulation.py
1
import math
2
from numpy import *
3
4
### HELPER FUNCTIONS ###
5
def randomVec(x):
6
    '''
7
    Generates a vector of length x, each component being a random float b/w -10 and 10
8
    '''
9
    return random.uniform(-10,10,(x,1))
10
11
12
def randomUnitAxisAngle():
13
    '''
14
    Generates a random unit axis and an angle
15
    '''
16
    # Random longitude
17
    u = random.uniform(0, 1)
18
    longitude = 2*math.pi*u
19
20
    # Random latitude
21
    v = random.uniform(0, 1)
22
    latitude = 2*math.pi*v
23
24
    # Random unit rotation axis
25
    axis = zeros((3,1))
26
    axis[0] = math.cos(latitude)*math.cos(longitude)
27
    axis[1] = math.cos(latitude)*math.sin(longitude)
28
    axis[2] = math.sin(latitude)
29
30
    # Random angle b/w 0 and 2pi
31
    theta = 2*math.pi*random.uniform(0, 1)
32
33
    return axis, theta
34
35
36
def normalize(v):
37
    '''
38
    Returns the normalized version of the vector v
39
    '''
40
    norm = linalg.norm(v)
41
    if norm == 0: 
42
       return v
43
    return v/norm
44
45
46
def is_identity_matrix(M):
47
    '''
48
    Returns True if input M is close to an identity matrix
49
    '''
50
    if len(M) != len(M[0]):
51
        return False
52
53
    c = list()
54
    for i, row in enumerate(M):
55
        for j, val in enumerate(row):
56
            if i==j:
57
                if val < 1.001 and val > 0.999:
58
                    c.append(True)
59
                else:
60
                    c.append(False)
61
            else:
62
                if abs(val) < 0.001:
63
                    c.append(True)
64
                else:
65
                    c.append(False)
66
67
    return all(c)
68
69
70
def is_rot_matrix(R):
71
    '''
72
    Returns True if input R is a valid rotation matrix.
73
    '''
74
    R = asarray(R)
75
    return is_identity_matrix(dot(R.T,R)) and (abs(linalg.det(R)-1) < 0.001)
76
77
78
### MAIN FUNCTIONS ###
79
def RotInv(R):
80
    '''
81
    Takes a rotation matrix belonging to SO(3) and returns its inverse.
82
    Example:
83
84
    R = [[.707,-.707,0],[.707,.707,0],[0,0,1]]
85
    RotInv(R)
86
    >> array([[ 0.707,  0.707,  0.   ],
87
              [-0.707,  0.707,  0.   ],
88
              [ 0.   ,  0.   ,  1.   ]])
89
    '''
90
    R = asarray(R)
91
    assert is_rot_matrix(R), 'Not a valid rotation matrix'
92
93
    return R.T
94
95
96
def VecToso3(w):
97
    '''
98
    Takes a 3-vector representing angular velocity and returns the 3x3 skew-symmetric matrix version, an element
99
    of so(3).
100
    Example:
101
102
    w = [2, 1, -4]
103
    VecToso3(w)
104
    >> array([[ 0,  4,  1],
105
              [-4,  0, -2],
106
              [-1,  2,  0]])
107
    '''
108
    w = asarray(w)
109
    assert len(w) == 3, 'Not a 3-vector'
110
111
    w = w.flatten()
112
    w_so3mat = array([[0, -w[2], w[1]], [w[2], 0, -w[0]], [-w[1], w[0], 0]])
113
    return w_so3mat
114
115
116
def so3ToVec(w_so3mat):
117
    '''
118
    Takes a 3x3 skew-symmetric matrix (an element of so(3)) and returns the corresponding 3-vector.
119
    Example:
120
121
    w_so3mat = [[ 0,  4,  1],[-4,  0, -2],[-1,  2,  0]]  
122
    so3ToVec(w_so3mat)
123
    >> array([[ 2],
124
              [ 1],
125
              [-4]]) 
126
    '''
127
    w_so3mat = asarray(w_so3mat)
128
    assert w_so3mat.shape == (3,3), 'Not a 3x3 matrix'
129
130
    w = array([[w_so3mat[2,1]], [w_so3mat[0,2]], [w_so3mat[1,0]]])
131
    return w
132
133
134
def AxisAng3(r):
135
    '''
136
    Takes a 3-vector of exp coords r = w_unit*theta and returns w_unit and theta.
137
    Example:
138
    
139
    r = [2, 1, -4]
140
    w_unit, theta = AxisAng3(r)
141
    w_unit
142
    >> array([ 0.43643578,  0.21821789, -0.87287156])
143
    theta
144
    >> 4.5825756949558398
145
    '''
146
    r = asarray(r)
147
    assert len(r) == 3, 'Not a 3-vector'
148
149
    theta = linalg.norm(r)
150
    w_unit = normalize(r)
151
152
    return w_unit, theta
153
154
155
def MatrixExp3(r):
156
    '''
157
    Takes a 3-vector of exp coords r = w_unit*theta and returns the corresponding
158
    rotation matrix R (an element of SO(3)).
159
    Example:
160
161
    r = [2, 1, -4]
162
    MatrixExp3(r)
163
    >> array([[ 0.08568414, -0.75796072, -0.64664811],
164
              [ 0.97309386, -0.07566572,  0.2176305 ],
165
              [-0.21388446, -0.64789679,  0.73108357]])
166
    '''
167
    r = asarray(r)
168
    assert len(r) == 3, 'Not a 3-vector'
169
170
    w_unit, theta = AxisAng3(r)
171
    w_so3mat = VecToso3(w_unit)
172
173
    R = identity(3) + math.sin(theta)*w_so3mat + (1-math.cos(theta))*dot(w_so3mat, w_so3mat)
174
    assert is_rot_matrix(R), 'Did not produce a valid rotation matrix'
175
    return R
176
177
178
def MatrixLog3(R):
179
    '''
180
    Takes a rotation matrix R and returns the corresponding 3-vector of exp coords r = w_unit*theta.
181
    Example:
182
183
    R = [[.707,-.707,0],[.707,.707,0],[0,0,1]]
184
    MatrixLog3(R)
185
    >> array([[ 0.        ],
186
              [ 0.        ],
187
              [ 0.78554916]])
188
    '''
189
    R = asarray(R)
190
    assert is_rot_matrix(R), 'Not a valid rotation matrix'
191
192
    if is_identity_matrix(R):
193
        return zeros((3,1))
194
195
    if trace(R) > -1.001 and trace(R) < -0.999:
196
        theta = math.pi
197
        c = max(diag(R))
198
        if c == R[2,2]:
199
            w_unit = array([[R[0,2]],[R[1,2]],[1+c]])*1/((2*(1+c))**0.5)
200
            return w_unit*theta
201
        elif c == R[1,1]:
202
            w_unit = array([[R[0,1]],[1+c],[R[2,1]]])*1/((2*(1+c))**0.5)
203
            return w_unit*theta
204
        elif c == R[0,0]:
205
            w_unit = array([[1+c],[R[1,0]],[R[2,0]]])*1/((2*(1+c))**0.5)
206
            return w_unit*theta
207
208
    theta = math.acos((trace(R)-1)/2)
209
    w_so3mat = (R - R.T)/(2*math.sin(theta))
210
    w_unit = normalize(so3ToVec(w_so3mat))
211
    return w_unit*theta
212
213
214
def RpToTrans(R,p):
215
    '''
216
    Takes a rotation matrix R and a point (3-vector) p, and returns the corresponding
217
    4x4 transformation matrix T, an element of SE(3).
218
    Example:
219
220
    R = [[.707,-.707,0],[.707,.707,0],[0,0,1]]
221
    p = [5,-4,9]
222
    RpToTrans(R,p)
223
    >> array([[ 0.707, -0.707,  0.   ,  5.   ],
224
              [ 0.707,  0.707,  0.   , -4.   ],
225
              [ 0.   ,  0.   ,  1.   ,  9.   ],
226
              [ 0.   ,  0.   ,  0.   ,  1.   ]])    
227
    '''
228
    p = asarray(p)
229
    R = asarray(R)
230
    assert len(p) == 3, "Point not a 3-vector"
231
    assert is_rot_matrix(R), "R not a valid rotation matrix"
232
233
    p.shape = (3,1)
234
    T = vstack((hstack((R,p)), array([0,0,0,1])))
235
    return T
236
237
238
def TransToRp(T):
239
    '''
240
    Takes a transformation matrix T and returns the corresponding R and p.
241
    Example:
242
243
    T = [[0.707,-0.707,0,5],[0.707,0.707,0,-4],[0,0,1,9],[0,0,0,1]]
244
    R, p = TransToRp(T)
245
    R
246
    >> array([[ 0.707, -0.707,  0.   ],
247
              [ 0.707,  0.707,  0.   ],
248
              [ 0.   ,  0.   ,  1.   ]])
249
    p
250
    >> array([[ 5.],
251
              [-4.],
252
              [ 9.]])
253
    '''
254
    T = asarray(T)
255
    assert T.shape == (4,4), "Input not a 4x4 matrix"
256
257
    R = T[:3,:3]
258
    assert is_rot_matrix(R), "Input not a valid transformation matrix"
259
260
    assert allclose([0,0,0,1],T[-1],atol=1e-03), "Last row of homogenous T matrix should be [0,0,0,1]"
261
262
    p = T[:3,-1]
263
    p.shape = (3,1)
264
265
    return R, p
266
267
268
def TransInv(T):
269
    '''
270
    Returns inverse of transformation matrix T.
271
    Example:
272
273
    T = [[0.707,-0.707,0,5],[0.707,0.707,0,-4],[0,0,1,9],[0,0,0,1]]
274
    TransInv(T)
275
    >> array([[ 0.707,  0.707,  0.   , -0.707],
276
              [-0.707,  0.707,  0.   ,  6.363],
277
              [ 0.   ,  0.   ,  1.   , -9.   ],
278
              [ 0.   ,  0.   ,  0.   ,  1.   ]])
279
    '''
280
    T = asarray(T)
281
    R, p = TransToRp(T)
282
283
    T_inv = RpToTrans(RotInv(R), dot(-RotInv(R),p))
284
    return T_inv
285
286
287
def VecTose3(V):
288
    '''
289
    Takes a 6-vector (representing spatial velocity) and returns the corresponding 4x4 matrix,
290
    an element of se(3).
291
    Example:
292
293
    V = [3,2,5,-3,7,0]
294
    VecTose3(V)
295
    >> array([[ 0., -5.,  2., -3.],
296
              [ 5.,  0., -3.,  7.],
297
              [-2.,  3.,  0.,  0.],
298
              [ 0.,  0.,  0.,  0.]])
299
    '''
300
    V = asarray(V)
301
    assert len(V) == 6, "Input not a 6-vector"
302
    
303
    V.shape = (6,1)
304
    w = V[:3]
305
    w_so3mat = VecToso3(w)
306
    v = V[3:]
307
    V_se3mat = vstack((hstack((w_so3mat,v)), zeros(4)))    
308
    return V_se3mat
309
310
311
def se3ToVec(V_se3mat):
312
    '''
313
    Takes an element of se(3) and returns the corresponding (6-vector) spatial velocity.
314
    Example:
315
316
    V_se3mat = [[ 0., -5.,  2., -3.],
317
                [ 5.,  0., -3.,  7.],
318
                [-2.,  3.,  0.,  0.],
319
                [ 0.,  0.,  0.,  0.]]
320
    se3ToVec(V_se3mat)
321
    >> array([[ 3.],
322
              [ 2.],
323
              [ 5.],
324
              [-3.],
325
              [ 7.],
326
              [ 0.]])
327
    '''
328
    V_se3mat = asarray(V_se3mat)
329
    assert V_se3mat.shape == (4,4), "Matrix is not 4x4"
330
331
    w_so3mat = V_se3mat[:3,:3]
332
    w = so3ToVec(w_so3mat)
333
334
    v = V_se3mat[:3,-1]
335
    v.shape = (3,1)
336
337
    V = vstack((w,v))
338
    return V
339
340
341
def Adjoint(T):
342
    '''
343
    Takes a transformation matrix T and returns the 6x6 adjoint representation [Ad_T]
344
    Example:
345
346
    T = [[0.707,-0.707,0,5],[0.707,0.707,0,-4],[0,0,1,9],[0,0,0,1]]
347
    Adjoint(T)
348
    >> array([[ 0.707, -0.707,  0.   ,  0.   ,  0.   ,  0.   ],
349
              [ 0.707,  0.707,  0.   ,  0.   ,  0.   ,  0.   ],
350
              [ 0.   ,  0.   ,  1.   ,  0.   ,  0.   ,  0.   ],
351
              [-6.363, -6.363, -4.   ,  0.707, -0.707,  0.   ],
352
              [ 6.363, -6.363, -5.   ,  0.707,  0.707,  0.   ],
353
              [ 6.363,  0.707,  0.   ,  0.   ,  0.   ,  1.   ]])
354
    '''
355
    T = asarray(T)
356
    assert T.shape == (4,4), "Input not a 4x4 matrix"
357
358
    R, p = TransToRp(T)
359
    p = p.flatten()
360
    p_skew = array([[0, -p[2], p[1]], [p[2], 0, -p[0]], [-p[1], p[0], 0]])
361
362
    ad1 = vstack((R, dot(p_skew,R)))
363
    ad2 = vstack((zeros((3,3)),R))
364
    adT = hstack((ad1,ad2))
365
    return adT
366
367
368
def ScrewToAxis(q,s_hat,h):
369
    '''
370
    Takes a point q (3-vector) on the screw, a unit axis s_hat (3-vector) in the direction of the screw,
371
    and a screw pitch h (scalar), and returns the corresponding 6-vector screw axis S (a normalized 
372
    spatial velocity).
373
    Example:
374
375
    q = [3,0,0]
376
    s_hat = [0,0,1]
377
    h = 2
378
    ScrewToAxis(q,s_hat,h)
379
    >> array([[ 0],
380
              [ 0],
381
              [ 1],
382
              [ 0],
383
              [-3],
384
              [ 2]])
385
    '''
386
    q = asarray(q)
387
    s_hat = asarray(s_hat)
388
    assert len(q) == len(s_hat) == 3, "q or s_hat not a 3-vector"
389
    assert abs(linalg.norm(s_hat) - 1) < 0.001, "s_hat not a valid unit vector"
390
    assert isscalar(h), "h not a scalar"
391
392
    q = q.flatten()
393
    s_hat = s_hat.flatten()
394
395
    v_wnorm = -cross(s_hat, q) + h*s_hat
396
    v_wnorm.shape = (3,1)
397
    w_unit = s_hat
398
    w_unit.shape = (3,1)
399
    S = vstack((w_unit,v_wnorm))
400
    return S
401
402
403
def AxisAng6(STheta):
404
    '''
405
    Takes a 6-vector of exp coords STheta and returns the screw axis S and the distance traveled along/
406
    about the screw axis theta.
407
    Example:
408
409
    STheta = [0,0,1,0,-3,2]
410
    S, theta = AxisAng6(STheta)
411
    S
412
    >> array([[ 0.],
413
              [ 0.],
414
              [ 1.],
415
              [ 0.],
416
              [-3.],
417
              [ 2.]])
418
    theta
419
    >> 1.0
420
    '''
421
    STheta = asarray(STheta)
422
    assert len(STheta) == 6, 'Input not a 6-vector'
423
424
    w = STheta[:3]
425
    v = STheta[3:]
426
427
    if linalg.norm(w) == 0:
428
        theta = linalg.norm(v)
429
        v_unit = normalize(v)
430
        v_unit.shape = (3,1)
431
        S = vstack((zeros((3,1)), v_unit))
432
        return S, theta
433
434
    theta = linalg.norm(w)
435
    w_unit = normalize(w)
436
    w_unit.shape = (3,1)
437
    v_unit = v/theta
438
    v_unit.shape = (3,1)
439
    S = vstack((w_unit,v_unit))
440
    return S, theta
441
442
443
def MatrixExp6(STheta):
444
    '''
445
    Takes a 6-vector of exp coords STheta and returns the corresponding 4x4 transformation matrix T.
446
    Example:
447
448
    STheta = [0,0,1,0,-3,2]
449
    MatrixExp6(STheta)
450
    >> array([[ 0.54030231, -0.84147098,  0.        ,  1.37909308],
451
              [ 0.84147098,  0.54030231,  0.        , -2.52441295],
452
              [ 0.        ,  0.        ,  1.        ,  2.        ],
453
              [ 0.        ,  0.        ,  0.        ,  1.        ]])
454
    '''
455
    STheta = asarray(STheta)
456
    assert len(STheta) == 6, 'Input not a 6-vector'
457
458
    S, theta = AxisAng6(STheta)
459
460
    w_unit = S[:3]
461
    v_unit = S[3:]
462
463
    vTheta = STheta[3:]
464
    vTheta.shape = (3,1)
465
    
466
    if linalg.norm(w_unit) == 0:
467
        R = identity(3)
468
        p = vTheta
469
        T = RpToTrans(R,p)
470
        return T
471
472
    r = w_unit*theta
473
    R = MatrixExp3(r)
474
    w_so3mat = VecToso3(w_unit)
475
    p = dot((identity(3)*theta+(1-math.cos(theta))*w_so3mat+(theta-math.sin(theta))*dot(w_so3mat,w_so3mat)), v_unit) 
476
    T = RpToTrans(R,p)
477
    return T
478
479
480
def MatrixLog6(T):
481
    '''
482
    Takes a transformation matrix T and returns the corresponding 6-vector of exp coords STheta.
483
    Example:
484
485
    T = [[ 0.54030231, -0.84147098,  0.        ,  1.37909308],
486
         [ 0.84147098,  0.54030231,  0.        , -2.52441295],
487
         [ 0.        ,  0.        ,  1.        ,  2.        ],
488
         [ 0.        ,  0.        ,  0.        ,  1.        ]]
489
    MatrixLog6(T):
490
    >> array([[  0.00000000e+00],
491
              [  0.00000000e+00],
492
              [  9.99999995e-01],
493
              [  1.12156694e-08],
494
              [ -2.99999999e+00],
495
              [  2.00000000e+00]])
496
    '''
497
    T = asarray(T)
498
    assert T.shape == (4,4), "Input not a 4x4 matrix"
499
500
    R, p = TransToRp(T)
501
502
    if is_identity_matrix(R):
503
        w_unit = zeros((3,1))
504
        vTheta = p
505
        STheta = vstack((w_unit, p))
506
        return STheta
507
508
    if trace(R) > -1.001 and trace(R) < -0.999:
509
        theta = math.pi
510
        wTheta = MatrixLog3(R)
511
        w_unit = wTheta/theta
512
        w_so3mat = VecToso3(w_unit)
513
        Ginv = identity(3)/theta - w_so3mat/2 + (1/theta - 1/(math.tan(theta/2)*2))*dot(w_so3mat,w_so3mat)
514
        v_unit = dot(Ginv, p)
515
        vTheta = v_unit*theta
516
        STheta = vstack((wTheta, vTheta))
517
        return STheta
518
519
    theta = math.acos((trace(R)-1)/2)
520
    w_so3mat = (R - R.T)/(2*math.sin(theta))
521
    Ginv = identity(3)/theta - w_so3mat/2 + (1/theta - 1/(math.tan(theta/2)*2))*dot(w_so3mat,w_so3mat)
522
    wTheta = MatrixLog3(R)
523
    v_unit = dot(Ginv, p)
524
    vTheta = v_unit*theta
525
    STheta = vstack((wTheta, vTheta)) 
526
    return STheta
527
528
529
def FKinFixed(M,Slist,thetalist):
530
    '''
531
    Takes
532
    - an element of SE(3): M representing the configuration of the end-effector frame when
533
      the manipulator is at its home position (all joint thetas = 0),
534
    - a list of screw axes Slist for the joints w.r.t fixed world frame,
535
    - a list of joint coords thetalist,
536
    and returns the T of end-effector frame w.r.t. fixed world frame when the joints are at
537
    the thetas specified.
538
    Example:
539
540
    S1 = [0,0,1,4,0,0]
541
    S2 = [0,0,0,0,1,0]
542
    S3 = [0,0,-1,-6,0,-0.1]
543
    Slist = [S1, S2, S3]
544
    thetalist = [math.pi/2, 3, math.pi]
545
    M = [[-1,  0,  0,  0],
546
         [ 0,  1,  0,  6],
547
         [ 0,  0, -1,  2],
548
         [ 0,  0,  0,  1]]
549
    FKinFixed(M,Slist,thetalist)
550
    >> array([[ -1.14423775e-17,   1.00000000e+00,   0.00000000e+00, -5.00000000e+00],
551
              [  1.00000000e+00,   1.14423775e-17,   0.00000000e+00, 4.00000000e+00],
552
              [  0.00000000e+00,   0.00000000e+00,  -1.00000000e+00, 1.68584073e+00],
553
              [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00, 1.00000000e+00]])
554
    '''
555
    M = asarray(M)
556
    R_M = TransToRp(M)[0]
557
    assert M.shape == (4,4), "M not a 4x4 matrix"
558
    assert len(Slist[0]) == 6, "Incorrect Screw Axis length"
559
    Slist = asarray(Slist).T
560
561
    c = MatrixExp6(Slist[:,0]*thetalist[0])
562
    for i in range(len(thetalist)-1):        
563
        nex = MatrixExp6(Slist[:,i+1]*thetalist[i+1])
564
        c = dot(c, nex)
565
566
    T_se = dot(c, M)
567
    return T_se
568
569
570
def FKinBody(M,Blist,thetalist):
571
    '''
572
    Same as FKinFixed, except here the screw axes are expressed in the end-effector frame.
573
    Example:
574
575
    B1 = [0,0,-1,2,0,0]
576
    B2 = [0,0,0,0,1,0]
577
    B3 = [0,0,1,0,0,0.1]
578
    Blist = [S1b, S2b, S3b]
579
    thetalist = [math.pi/2, 3, math.pi]
580
    M = [[-1,  0,  0,  0],
581
         [ 0,  1,  0,  6],
582
         [ 0,  0, -1,  2],
583
         [ 0,  0,  0,  1]]
584
    FKinBody(M,Blist,thetalist)
585
    >> array([[ -1.14423775e-17,   1.00000000e+00,   0.00000000e+00, -5.00000000e+00],
586
              [  1.00000000e+00,   1.14423775e-17,   0.00000000e+00, 4.00000000e+00],
587
              [  0.00000000e+00,   0.00000000e+00,  -1.00000000e+00, 1.68584073e+00],
588
              [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00, 1.00000000e+00]])
589
    '''
590
    M = asarray(M)
591
    R_M = TransToRp(M)[0]
592
    assert M.shape == (4,4), "M not a 4x4 matrix"
593
    assert len(Blist[0]) == 6, "Incorrect Screw Axis length"
594
    Blist = asarray(Blist).T
595
596
    c = dot(M, MatrixExp6(Blist[:,0]*thetalist[0]))
597
    for i in range(len(thetalist)-1):        
598
        nex = MatrixExp6(Blist[:,i+1]*thetalist[i+1])
599
        c = dot(c, nex)
600
601
    T_se = c
602
    return T_se
603
604
605
### end of HW2 functions #############################
606
607
### start of HW3 functions ###########################
608
609
610
def FixedJacobian(Slist,thetalist):
611
    '''
612
    Takes a list of joint angles (thetalist) and a list of screw axes (Slist) expressed in
613
    fixed space frame, and returns the space Jacobian (a 6xN matrix, where N is the # joints).
614
    Example:
615
616
    S1 = [0,0,1,4,0,0]
617
    S2 = [0,0,0,0,1,0]
618
    S3 = [0,0,-1,-6,0,-0.1]
619
    Slist = [S1, S2, S3]
620
    thetalist = [math.pi/2, 3, math.pi]
621
    FixedJacobian(Slist,thetalist)
622
    >> array([[  0.00000000e+00,   0.00000000e+00,   0.00000000e+00],
623
              [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00],
624
              [  1.00000000e+00,   0.00000000e+00,  -1.00000000e+00],
625
              [  4.00000000e+00,  -1.00000000e+00,  -4.00000000e+00],
626
              [  0.00000000e+00,   1.11022302e-16,  -5.00000000e+00],
627
              [  0.00000000e+00,   0.00000000e+00,  -1.00000000e-01]])
628
        '''
629
    N = len(thetalist)
630
    J = zeros((6,N))
631
    Slist = asarray(Slist).T
632
633
    J[:,0] = Slist[:,0]
634
    for k in range(1,N):
635
        c = MatrixExp6(Slist[:,0]*thetalist[0])
636
        for i in range(k-1):        
637
            nex = MatrixExp6(Slist[:,i+1]*thetalist[i+1])
638
            c = dot(c, nex)
639
        J[:,k] = dot(Adjoint(c), Slist[:,k])
640
641
    return J
642
643
644
def BodyJacobian(Blist,thetalist):
645
    '''
646
    Takes a list of joint angles (thetalist) and a list of screw axes (Blist) expressed in
647
    end-effector body frame, and returns the body Jacobian (a 6xN matrix, where N is the # joints).
648
    Example:
649
    
650
    B1 = [0,0,-1,2,0,0]
651
    B2 = [0,0,0,0,1,0]
652
    B3 = [0,0,1,0,0,0.1]
653
    Blist = [B1, B2, B3]
654
    thetalist = [math.pi/2, 3, math.pi]
655
    BodyJacobian(Blist,thetalist)
656
    >> array([[  0.00000000e+00,   0.00000000e+00,   0.00000000e+00],
657
              [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00],
658
              [ -1.00000000e+00,   0.00000000e+00,   1.00000000e+00],
659
              [ -5.00000000e+00,   1.22464680e-16,   0.00000000e+00],
660
              [ -6.12323400e-16,  -1.00000000e+00,   0.00000000e+00],
661
              [  0.00000000e+00,   0.00000000e+00,   1.00000000e-01]])
662
    '''
663
    N = len(thetalist)
664
    J = zeros((6,N))
665
    Blist = asarray(Blist).T
666
667
    J[:,N-1] = Blist[:,N-1]
668
    for k in range(N-1):
669
        c = MatrixExp6(-Blist[:,k+1]*thetalist[k+1])
670
        for i in range(k+2, len(thetalist)):        
671
            nex = MatrixExp6(-Blist[:,i]*thetalist[i])
672
            c = dot(nex, c)
673
        J[:,k] = dot(Adjoint(c), Blist[:,k])
674
675
    return J
676
677
678
def IKinBody(Blist, M, T_sd, thetalist_init, wthresh, vthresh):
679
    '''
680
    A numerical inverse kinematics routine based on Newton-Raphson method.
681
    Takes a list of screw axes (Blist) expressed in end-effector body frame, the end-effector zero
682
    configuration (M), the desired end-effector configuration (T_sd), an initial guess of joint angles
683
    (thetalist_init), and small positive scalar thresholds (wthresh, vthresh) controlling how close the
684
    final solution thetas must be to the desired thetas.
685
    Example:
686
687
    wthresh = 0.01
688
    vthresh = 0.001
689
    M = [[1,0,0,-.817],[0,0,-1,-.191],[0,1,0,-.006],[0,0,0,1]]
690
    T_sd = [[0,1,0,-.6],[0,0,-1,.1],[-1,0,0,.1],[0,0,0,1]]
691
    thetalist_init = [0]*6
692
    B1 = [0,1,0,.191,0,.817]
693
    B2 = [0,0,1,.095,-.817,0]
694
    B3 = [0,0,1,.095,-.392,0]
695
    B4 = [0,0,1,.095,0,0]
696
    B5 = [0,-1,0,-.082,0,0]
697
    B6 = [0,0,1,0,0,0]
698
    Blist = [B1,B2,B3,B4,B5,B6]
699
    round(IKinBody(Blist, M, T_sd, thetalist_init, wthresh, vthresh), 3)
700
    >>
701
    array([[ 0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.   ],
702
           [-0.356, -0.535,  0.468,  1.393, -0.356, -2.897],
703
           [-0.399, -1.005,  1.676, -0.434, -0.1  , -1.801],
704
           [-0.516, -1.062,  1.731, -1.63 , -0.502, -0.607],
705
           [-0.493, -0.923,  1.508, -0.73 , -0.289, -1.42 ],
706
           [-0.472, -0.818,  1.365, -0.455, -0.467, -1.662],
707
           [-0.469, -0.834,  1.395, -0.561, -0.467, -1.571]])
708
    '''
709
    T_sd = asarray(T_sd)
710
    assert T_sd.shape == (4,4), "T_sd not a 4x4 matrix"
711
    
712
    maxiterates = 100
713
    N = len(thetalist_init)
714
715
    jointAngles = asarray(thetalist_init).reshape(1,N)
716
717
    T_sb = FKinBody(M, Blist, thetalist_init)
718
    Vb = MatrixLog6(dot(TransInv(T_sb), T_sd))
719
    wb = Vb[:3, 0]
720
    vb = Vb[3:, 0]
721
722
    thetalist_i = asarray(thetalist_init)
723
724
    i = 0
725
726
    while i<maxiterates and (linalg.norm(wb)>wthresh or linalg.norm(vb)>vthresh):
727
        thetalist_next = thetalist_i.reshape(N,1) + dot(linalg.pinv(BodyJacobian(Blist,thetalist_i)), Vb)
728
        # thetalist_next = (thetalist_next + pi)%(2*pi) - pi
729
        jointAngles = vstack((jointAngles, thetalist_next.reshape(1,N)))
730
        T_sb = FKinBody(M, Blist, thetalist_next.flatten())
731
        Vb = MatrixLog6(dot(TransInv(T_sb), T_sd))
732
        thetalist_i = thetalist_next.reshape(N,)
733
        wb = Vb[:3, 0]
734
        vb = Vb[3:, 0]
735
        i += 1
736
737
    return jointAngles
738
739
740
def IKinFixed(Slist, M, T_sd, thetalist_init, wthresh, vthresh):
741
    '''
742
    Similar to IKinBody, except the screw axes are in the fixed space frame.
743
    Example:
744
    
745
    M =  [[1,0,0,0],[0,1,0,0],[0,0,1,0.910],[0,0,0,1]]
746
    T_sd = [[1,0,0,.4],[0,1,0,0],[0,0,1,.4],[0,0,0,1]]
747
    thetalist_init = [0]*7
748
    S1 = [0,0,1,0,0,0]
749
    S2 = [0,1,0,0,0,0]
750
    S3 = [0,0,1,0,0,0]
751
    S4 = [0,1,0,-0.55,0,0.045]
752
    S5 = [0,0,1,0,0,0]
753
    S6 = [0,1,0,-0.85,0,0]
754
    S7 = [0,0,1,0,0,0]
755
    Slist = [S1,S2,S3,S4,S5,S6,S7]
756
    round(IKinFixed(Slist, M, T_sd, thetas, wthresh, vthresh), 3)
757
    >> 
758
    array([[  0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ],
759
           [  0.   ,   4.471,  -0.   , -11.333,  -0.   ,   6.863,  -0.   ],
760
           [ -0.   ,   3.153,  -0.   ,  -5.462,  -0.   ,   2.309,   0.   ],
761
           [ -0.   ,  -1.006,   0.   ,   5.679,  -0.   ,  -4.673,   0.   ],
762
           [ -0.   ,   1.757,   0.   ,  -0.953,   0.   ,  -0.804,  -0.   ],
763
           [ -0.   ,   1.754,   0.   ,  -2.27 ,  -0.   ,   0.516,  -0.   ],
764
           [  0.   ,   1.27 ,   0.   ,  -1.85 ,  -0.   ,   0.58 ,  -0.   ],
765
           [  0.   ,   1.367,   0.   ,  -1.719,  -0.   ,   0.351,  -0.   ],
766
           [  0.   ,   1.354,   0.   ,  -1.71 ,  -0.   ,   0.356,  -0.   ]])
767
    '''
768
    T_sd = asarray(T_sd)
769
    assert T_sd.shape == (4,4), "T_sd not a 4x4 matrix"
770
    
771
    maxiterates = 100
772
    
773
    N = len(thetalist_init)
774
775
    jointAngles = asarray(thetalist_init).reshape(1,N)
776
777
    T_sb = FKinFixed(M, Slist, thetalist_init)
778
    Vb = MatrixLog6(dot(TransInv(T_sb), T_sd))
779
    wb = Vb[:3, 0]
780
    vb = Vb[3:, 0]
781
782
    thetalist_i = asarray(thetalist_init)
783
784
    i = 0
785
786
    while i<maxiterates and (linalg.norm(wb)>wthresh or linalg.norm(vb)>vthresh):
787
        Jb = dot(Adjoint(TransInv(T_sb)), FixedJacobian(Slist,thetalist_i))
788
        thetalist_next = thetalist_i.reshape(N,1) + dot(linalg.pinv(Jb), Vb)
789
        jointAngles = vstack((jointAngles, thetalist_next.reshape(1,N)))
790
        
791
        T_sb = FKinFixed(M, Slist, thetalist_next.flatten())
792
        Vb = MatrixLog6(dot(TransInv(T_sb), T_sd))
793
        thetalist_i = thetalist_next.reshape(N,)
794
        wb = Vb[:3, 0]
795
        vb = Vb[3:, 0]
796
        i += 1
797
798
    return jointAngles
799
800
801
### end of HW3 functions #############################
802
803
### start of HW4 functions ###########################
804
805
806
def CubicTimeScaling(T,t):
807
    '''
808
    Takes a total travel time T and the current time t satisfying 0 <= t <= T and returns
809
    the path parameter s corresponding to a motion that begins and ends at zero velocity.
810
    Example:
811
812
    CubicTimeScaling(10, 7)
813
    >> 0.78399
814
    '''
815
    assert t >= 0 and t <= T, 'Invalid t'
816
817
    s = (3./(T**2))*(t**2) - (2./(T**3))*(t**3)
818
    return s 
819
820
821
def QuinticTimeScaling(T,t):
822
    '''
823
    Takes a total travel time T and the current time t satisfying 0 <= t <= T and returns
824
    the path parameter s corresponding to a motion that begins and ends at zero velocity
825
    and zero acceleration.
826
    Example:
827
828
    QuinticTimeScaling(10,7)
829
    >> 0.83692
830
    '''
831
    assert t >= 0 and t <= T, 'Invalid t'
832
833
    s = (10./(T**3))*(t**3) + (-15./(T**4))*(t**4) + (6./(T**5))*(t**5)
834
    return s
835
836
837
def JointTrajectory(thetas_start, thetas_end, T, N, method='cubic'):
838
    '''
839
    Takes initial joint positions (n-dim) thetas_start, final joint positions thetas_end, the time of
840
    the motion T in seconds, the number of points N >= 2 in the discrete representation of the trajectory,
841
    and the time-scaling method (cubic or quintic) and returns a trajectory as a matrix with N rows,
842
    where each row is an n-vector of joint positions at an instant in time. The trajectory is a straight-line
843
    motion in joint space.
844
    Example:
845
846
    thetas_start = [0.1]*6
847
    thetas_end = [pi/2]*6
848
    T = 2
849
    N = 5
850
    JointTrajectory(thetas_start, thetas_end, T, N, 'cubic')
851
    >>
852
    array([[ 0.1  ,  0.1  ,  0.1  ,  0.1  ,  0.1  ,  0.1  ],
853
           [ 0.33 ,  0.33 ,  0.33 ,  0.33 ,  0.33 ,  0.33 ],
854
           [ 0.835,  0.835,  0.835,  0.835,  0.835,  0.835],
855
           [ 1.341,  1.341,  1.341,  1.341,  1.341,  1.341],
856
           [ 1.571,  1.571,  1.571,  1.571,  1.571,  1.571]])
857
    '''
858
    assert len(thetas_start) == len(thetas_end), 'Incompatible thetas'
859
    assert N >= 2, 'N must be >= 2'
860
    assert isinstance(N, int), 'N must be an integer'
861
    assert method == 'cubic' or method == 'quintic', 'Incorrect time-scaling method argument'
862
863
    trajectory = asarray(thetas_start)
864
865
    if method == 'cubic':
866
        for i in range(1,N):
867
            t = i*float(T)/(N-1)
868
            s = CubicTimeScaling(T,t)
869
            thetas_s = asarray(thetas_start)*(1-s) + asarray(thetas_end)*s
870
            trajectory = vstack((trajectory, thetas_s))
871
        return trajectory
872
873
    elif method == 'quintic':
874
        for i in range(1,N):
875
            t = i*float(T)/(N-1)
876
            s = QuinticTimeScaling(T,t)
877
            thetas_s = asarray(thetas_start)*(1-s) + asarray(thetas_end)*s
878
            trajectory = vstack((trajectory, thetas_s))
879
        return trajectory
880
881
882
def ScrewTrajectory(X_start, X_end, T, N, method='cubic'):
883
    '''
884
    Similar to JointTrajectory, except that it takes the initial end-effector configuration X_start in SE(3),
885
    the final configuration X_end, and returns the trajectory as a 4N x 4 matrix in which every 4 rows is an
886
    element of SE(3) separated in time by T/(N-1). This represents a discretized trajectory of the screw motion
887
    from X_start to X_end.
888
    Example:
889
890
    thetas_start = [0.1]*6
891
    thetas_end = [pi/2]*6
892
    M_ur5 = [[1,0,0,-.817],[0,0,-1,-.191],[0,1,0,-.006],[0,0,0,1]]
893
    S1_ur5 = [0,0,1,0,0,0]
894
    S2_ur5 = [0,-1,0,.089,0,0]
895
    S3_ur5 = [0,-1,0,.089,0,.425]
896
    S4_ur5 = [0,-1,0,.089,0,.817]
897
    S5_ur5 = [0,0,-1,.109,-.817,0]
898
    S6_ur5 = [0,-1,0,-.006,0,.817]
899
    Slist_ur5 = [S1_ur5,S2_ur5,S3_ur5,S4_ur5,S5_ur5,S6_ur5]
900
    X_start = FKinFixed(M_ur5, Slist_ur5, thetas_start)
901
    X_end = FKinFixed(M_ur5, Slist_ur5, thetas_end)
902
    T = 2
903
    N = 3
904
    ScrewTrajectory(X_start, X_end, T, N, 'quintic')
905
    >>
906
    array([[ 0.922, -0.388,  0.004, -0.764],
907
           [-0.007, -0.029, -1.   , -0.268],
908
           [ 0.388,  0.921, -0.03 , -0.124],
909
           [ 0.   ,  0.   ,  0.   ,  1.   ],
910
           [ 0.534, -0.806,  0.253, -0.275],
911
           [ 0.681,  0.234, -0.694, -0.067],
912
           [ 0.5  ,  0.543,  0.674, -0.192],
913
           [ 0.   ,  0.   ,  0.   ,  1.   ],
914
           [ 0.   , -1.   , -0.   ,  0.109],
915
           [ 1.   ,  0.   ,  0.   ,  0.297],
916
           [-0.   , -0.   ,  1.   , -0.254],
917
           [ 0.   ,  0.   ,  0.   ,  1.   ]])
918
    '''
919
    R_start, p_start = TransToRp(X_start) #Just to ensure X_start is valid
920
    R_end ,p_end = TransToRp(X_end)       #Just to ensure X_end is valid
921
    assert N >= 2, 'N must be >= 2'
922
    assert isinstance(N, int), 'N must be an integer'
923
    assert method == 'cubic' or method == 'quintic', 'Incorrect time-scaling method argument'
924
925
    trajectory = X_start
926
927
    if method == 'cubic':
928
        for i in range(1,N):
929
            t = i*float(T)/(N-1)
930
            s = CubicTimeScaling(T,t)
931
            X_s = X_start.dot(MatrixExp6(MatrixLog6(TransInv(X_start).dot(X_end))*s))
932
            trajectory = vstack((trajectory, X_s))
933
        return trajectory
934
935
    elif method == 'quintic':
936
        for i in range(1,N):
937
            t = i*float(T)/(N-1)
938
            s = QuinticTimeScaling(T,t)
939
            X_s = X_start.dot(MatrixExp6(MatrixLog6(TransInv(X_start).dot(X_end))*s))
940
            trajectory = vstack((trajectory, X_s))
941
        return trajectory
942
943
944
def CartesianTrajectory(X_start, X_end, T, N, method='cubic'):
945
    '''
946
    Similar to ScrewTrajectory, except the origin of the end-effector frame follows a straight line,
947
    decoupled from the rotational motion.
948
    Example:
949
950
    thetas_start = [0.1]*6
951
    thetas_end = [pi/2]*6
952
    M_ur5 = [[1,0,0,-.817],[0,0,-1,-.191],[0,1,0,-.006],[0,0,0,1]]
953
    S1_ur5 = [0,0,1,0,0,0]
954
    S2_ur5 = [0,-1,0,.089,0,0]
955
    S3_ur5 = [0,-1,0,.089,0,.425]
956
    S4_ur5 = [0,-1,0,.089,0,.817]
957
    S5_ur5 = [0,0,-1,.109,-.817,0]
958
    S6_ur5 = [0,-1,0,-.006,0,.817]
959
    Slist_ur5 = [S1_ur5,S2_ur5,S3_ur5,S4_ur5,S5_ur5,S6_ur5]
960
    X_start = FKinFixed(M_ur5, Slist_ur5, thetas_start)
961
    X_end = FKinFixed(M_ur5, Slist_ur5, thetas_end)
962
    T = 2
963
    N = 3
964
    CartesianTrajectory(X_start, X_end, T, N, 'quintic')
965
    >>
966
    array([[ 0.922, -0.388,  0.004, -0.764],
967
           [-0.007, -0.029, -1.   , -0.268],
968
           [ 0.388,  0.921, -0.03 , -0.124],
969
           [ 0.   ,  0.   ,  0.   ,  1.   ],
970
           [ 0.534, -0.806,  0.253, -0.327],
971
           [ 0.681,  0.234, -0.694,  0.014],
972
           [ 0.5  ,  0.543,  0.674, -0.189],
973
           [ 0.   ,  0.   ,  0.   ,  1.   ],
974
           [ 0.   , -1.   , -0.   ,  0.109],
975
           [ 1.   ,  0.   ,  0.   ,  0.297],
976
           [-0.   , -0.   ,  1.   , -0.254],
977
           [ 0.   ,  0.   ,  0.   ,  1.   ]])
978
979
    Notice the R of every T is same for ScrewTrajectory and CartesianTrajectory, but the translations
980
    are different. 
981
    '''
982
    R_start, p_start = TransToRp(X_start)
983
    R_end ,p_end = TransToRp(X_end)
984
    assert N >= 2, 'N must be >= 2'
985
    assert isinstance(N, int), 'N must be an integer'
986
    assert method == 'cubic' or method == 'quintic', 'Incorrect time-scaling method argument'
987
988
    trajectory = X_start
989
990
    if method == 'cubic':
991
        for i in range(1,N):
992
            t = i*float(T)/(N-1)
993
            s = CubicTimeScaling(T,t)
994
            p_s = (1-s)*p_start + s*p_end
995
            R_s = R_start.dot(MatrixExp3(MatrixLog3(RotInv(R_start).dot(R_end))*s))
996
            X_s = RpToTrans(R_s, p_s)
997
            trajectory = vstack((trajectory, X_s))
998
        return trajectory
999
1000
    elif method == 'quintic':
1001
        for i in range(1,N):
1002
            t = i*float(T)/(N-1)
1003
            s = QuinticTimeScaling(T,t)
1004
            p_s = (1-s)*p_start + s*p_end
1005
            R_s = R_start.dot(MatrixExp3(MatrixLog3(RotInv(R_start).dot(R_end))*s))
1006
            X_s = RpToTrans(R_s, p_s)
1007
            trajectory = vstack((trajectory, X_s))
1008
        return trajectory
1009
1010
1011
### end of HW4 functions #############################
1012
1013
### start of HW5 functions ###########################
1014
1015
1016
def LieBracket(V1, V2):
1017
    assert len(V1)==len(V2)==6, 'Needs two 6 vectors'
1018
    V1.shape = (6,1)
1019
    w1 = V1[:3,:]
1020
    v1 = V1[3:,:]
1021
1022
    w1_mat = VecToso3(w1)
1023
    v1_mat = VecToso3(v1)
1024
    col1 = vstack((w1_mat, v1_mat))
1025
    col2 = vstack((zeros((3,3)), w1_mat))
1026
    mat1 = hstack((col1, col2))
1027
1028
    return mat1.dot(V2)
1029
1030
1031
def TruthBracket(V1, V2):       # Transposed version of Lie Bracket
1032
    assert len(V1)==len(V2)==6, 'Needs two 6 vectors'
1033
    V1.shape = (6,1)
1034
    w1 = V1[:3,:]
1035
    v1 = V1[3:,:]
1036
1037
    w1_mat = VecToso3(w1)
1038
    v1_mat = VecToso3(v1)
1039
    col1 = vstack((w1_mat, v1_mat))
1040
    col2 = vstack((zeros((3,3)), w1_mat))
1041
    mat1 = hstack((col1, col2))
1042
1043
    return (mat1.T).dot(V2)
1044
1045
1046
def InverseDynamics(thetas, thetadots, thetadotdots, g, Ftip, M_rels, Glist, Slist):
1047
    '''
1048
    M1 = array(([1.,0.,0.,0.],[0.,1.,0.,0.],[0.,0.,1.,0.],[0.,0.,.089159,1.])).T
1049
    M2 = array(([0.,0.,-1.,0.],[0.,1.,0.,0.],[1.,0.,0.,0.],[.28,.13585,.089159,1.])).T
1050
    M3 = array(([0.,0.,-1.,0.],[0.,1.,0.,0.],[1.,0.,0.,0.],[.675,.01615,.089159,1.])).T
1051
    M4 = array(([-1.,0.,0.,0.],[0.,1.,0.,0.],[0.,0.,-1.,0.],[.81725,.01615,.089159,1.])).T
1052
    M5 = array(([-1.,0.,0.,0.],[0.,1.,0.,0.],[0.,0.,-1.,0.],[.81725,.10915,.089159,1.])).T
1053
    M6 = array(([-1.,0.,0.,0.],[0.,1.,0.,0.],[0.,0.,-1.,0.],[.81725,.10915,-.005491,1.])).T
1054
    M01 = array(([1.,0.,0.,0.],[0.,1.,0.,0.],[0.,0.,1.,0.],[0.,0.,.089159,1.])).T
1055
    M12 = array(([0.,0.,-1.,0.],[0.,1.,0.,0.],[1.,0.,0.,0.],[.28,.13585,0.,1.])).T
1056
    M23 = array(([1.,0.,0.,0.],[0.,1.,0.,0.],[0.,0.,1.,0.],[0.,-.1197,.395,1])).T
1057
    M34 = array(([0.,0.,-1.,0.],[0.,1.,0.,0.],[1.,0.,0.,0.],[0.,0.,.14225,1.])).T
1058
    M45 = array(([1.,0.,0.,0.],[0.,1.,0.,0.],[0.,0.,1.,0.],[0.,.093,0.,1.])).T
1059
    M56 = array(([1.,0.,0.,0.],[0.,1.,0.,0.],[0.,0.,1.,0.],[0.,0.,.09465,1.])).T
1060
1061
    G1 = array(([.010267,0.,0.,0.,0.,0.],[0.,.010267,0.,0.,0.,0.],[0.,0.,.00666,0.,0.,0.],[0.,0.,0.,3.7,0.,0.],[0.,0.,0.,0.,3.7,0.],[0.,0.,0.,0.,0.,3.7]))
1062
    G2 = array(([.22689,0.,0.,0.,0.,0.],[0.,.22689,0.,0.,0.,0.],[0.,0.,.0151074,0.,0.,0.],[0.,0.,0.,8.393,0.,0.],[0.,0.,0.,0.,8.393,0.],[0.,0.,0.,0.,0.,8.393]))
1063
    G3 = array(([.0494433,0.,0.,0.,0.,0.],[0.,.0494433,0.,0.,0.,0.],[0.,0.,.004095,0.,0.,0.],[0.,0.,0.,2.275,0.,0.],[0.,0.,0.,0.,2.275,0.],[0.,0.,0.,0.,0.,2.275]))
1064
    G4 = array(([.111172,0.,0.,0.,0.,0.],[0.,.111172,0.,0.,0.,0.],[0.,0.,.21942,0.,0.,0.],[0.,0.,0.,1.219,0.,0.],[0.,0.,0.,0.,1.219,0.],[0.,0.,0.,0.,0.,1.219]))
1065
    G5 = array(([.111172,0.,0.,0.,0.,0.],[0.,.111172,0.,0.,0.,0.],[0.,0.,.21942,0.,0.,0.],[0.,0.,0.,1.219,0.,0.],[0.,0.,0.,0.,1.219,0.],[0.,0.,0.,0.,0.,1.219]))
1066
    G6 = array(([.0171364,0.,0.,0.,0.,0.],[0.,.0171364,0.,0.,0.,0.],[0.,0.,.033822,.0,0.,0.],[0.,0.,0.,.1879,0.,0.],[0.,0.,0.,0.,.1879,0.],[0.,0.,0.,0.,0.,.1879]))
1067
1068
    Slist = [[0.,0.,1.,0.,0.,0.],[0.,1.,0.,-.089,0.,0.],[0.,1.,0.,-.089,0.,.425],[0.,1.,0.,-.089,0.,.817],[0.,0.,-1.,-.109,.817,.0],[0.,1.,0.,.006,0.,.817]]
1069
1070
    Glist = [G1,G2,G3,G4,G5,G6]
1071
    M_rels = [M01,M12,M23,M34,M45,M56]
1072
    Ftip = [0.,0.,0.,0.,0.,0.]
1073
    '''
1074
    assert len(thetas) == len(thetadots) == len(thetadotdots), 'Joint inputs mismatch'
1075
    Slist = asarray(Slist)
1076
    N = len(thetas) # no. of links
1077
    Ftip = asarray(Ftip)
1078
1079
    # initialize iterables
1080
    Mlist = [0]*N
1081
    T_rels = [0]*N
1082
    Vlist = [0]*N
1083
    Vdotlist = [0]*N
1084
    Alist = [0]*N
1085
    Flist = [0]*N
1086
    Taulist = [0]*N
1087
1088
    
1089
    Mlist[0] = M_rels[0]
1090
    for i in range(1, N):
1091
        Mlist[i] = Mlist[i-1].dot(M_rels[i])
1092
1093
1094
    for i in range(N):
1095
        Alist[i] = Adjoint(TransInv(Mlist[i])).dot(Slist[i])
1096
1097
1098
    for i in range(N):
1099
        T_rels[i] = M_rels[i].dot(MatrixExp6(Alist[i]*thetas[i]))
1100
1101
1102
    V0 = zeros((6,1))
1103
    Vlist[0] = V0
1104
1105
    Vdot0 = -asarray([0,0,0]+g)
1106
    Vdotlist[0] = Vdot0
1107
1108
    F_ip1 = asarray(Ftip).reshape(6,1)
1109
1110
    # forward iterations
1111
    for i in range(1, N):
1112
        # print i
1113
        T_i_im1 = TransInv(T_rels[i]) #### should it be i-1???
1114
1115
        Vlist[i] = Adjoint(T_i_im1).dot(Vlist[i-1]) + (Alist[i]*thetadots[i]).reshape(6,1)
1116
1117
        Vdotlist[i] = Adjoint(T_i_im1).dot(Vdotlist[i-1]) + LieBracket(Vlist[i], Alist[i])*thetadots[i] + Alist[i]*thetadotdots[i]
1118
1119
1120
    # print T_rels
1121
    # print Vlist
1122
    # print Vdotlist
1123
    # print Alist
1124
1125
    # backward iterations
1126
    for i in range(N-1,-1,-1):
1127
        T_ip1_i = TransInv(T_rels[i])
1128
        Flist[i] = (Adjoint(T_ip1_i).T).dot(F_ip1) + (Glist[i].dot(Vdotlist[i])).reshape(6,1) - TruthBracket(Vlist[i], Glist[i].dot(Vlist[i]))
1129
        Taulist[i] = (Flist[i].T).dot(Alist[i])
1130
1131
    return asarray(Taulist).flatten()
1132
1133
1134
def InertiaMatrix(thetas, M_rels, Glist, Slist):
1135
    Slist = asarray(Slist)
1136
    N = len(thetas) # no. of links
1137
1138
    M = zeros((N,N))
1139
1140
    for i in range(N):
1141
        thetadotdots = [0]*N
1142
        thetadotdots[i] = 1
1143
        M[:, i] = InverseDynamics(thetas, [0]*6, thetadotdots, [0]*3, [0]*6, M_rels, Glist, Slist)
1144
1145
    return M
1146
1147
1148
def CoriolisForces(thetas, thetadots, M_rels, Glist, Slist):
1149
    C = InverseDynamics(thetas, thetadots, [0]*6, [0]*3, [0]*6, M_rels, Glist, Slist)
1150
    return C
1151
1152
1153
def GravityForces(thetas, g, M_rels, Glist, Slist):
1154
    Gvec = InverseDynamics(thetas, [0]*6, [0]*6, g, [0]*6, M_rels, Glist, Slist)
1155
    return Gvec
1156
1157
1158
def EndEffectorForces(Ftip, thetas, M_rels, Glist, Slist):
1159
    return InverseDynamics(thetas, [0]*6, [0]*6, [0]*3, Ftip, M_rels, Glist, Slist)
1160
1161
1162
def ForwardDynamics(thetas, thetadots, taus, g, Ftip, M_rels, Glist, Slist):
1163
    M = InertiaMatrix(thetas, M_rels, Glist, Slist)
1164
    C = CoriolisForces(thetas, thetadots, M_rels, Glist, Slist)
1165
    Gvec = GravityForces(thetas, g, M_rels, Glist, Slist)
1166
    eeF = EndEffectorForces(Ftip, thetas, M_rels, Glist, Slist)
1167
1168
    thetadotdots = (linalg.pinv(M)).dot(taus - C - Gvec - eeF)
1169
    return thetadotdots
1170
1171
1172
def EulerStep(thetas_t, thetadots_t, thetadotdots_t, delt):
1173
    thetas_t = asarray(thetas_t)
1174
    thetadots_t = asarray(thetadots_t)
1175
    thetadotdots_t = asarray(thetadotdots_t)
1176
1177
    thetas_next = thetas_t + delt*thetadots_t
1178
    thetadots_next = thetadots_t + delt*thetadotdots_t
1179
1180
    return thetas_next, thetadots_next
1181
1182
1183
def InverseDynamicsTrajectory(thetas_traj, thetadots_traj, thetadotdots_traj, Ftip_traj, g, M_rels, Glist, Slist):
1184
    Np1 = len(thetas_traj)
1185
    # N = Np1-1
1186
    idtraj = []
1187
    for i in range(Np1):
1188
        taus = InverseDynamics(thetas_traj[i], thetadots_traj[i], thetadotdots_traj[i], g, Ftip_traj[i], M_rels, Glist, Slist)
1189
        idtraj.append(taus)
1190
1191
    return asarray(idtraj)
1192
1193
1194
def ForwardDynamicsTrajectory(thetas_init, thetadots_init, tau_hist, delt, g, Ftip_traj, M_rels, Glist, Slist):   
1195
    Np1 = len(tau_hist)
1196
    thetas_traj = asarray(thetas_init)
1197
    thetadots_traj = asarray(thetadots_init)
1198
1199
    for i in range(Np1):
1200
        thetadotdots_init = ForwardDynamics(thetas_init, thetadots_init, tau_hist[i], g, Ftip_traj[i], M_rels, Glist, Slist)
1201
        thetas_next, thetadots_next = EulerStep(thetas_init, thetadots_init, thetadotdots_init, delt)
1202
        # append new state
1203
        thetas_traj = hstack((thetas_traj, thetas_next))
1204
        thetadots_traj = hstack((thetadots_traj, thetadots_next))
1205
        # update initial conditions
1206
        thetas_init = thetas_next
1207
        thetadots_init = thetadots_next
1208
1209
    return thetas_traj.reshape(Np1+1, len(thetas_init)), thetadots_traj.reshape(Np1+1, len(thetas_init))
1210
1211
1212
### end of HW5 functions #############################