Skip to content

Commit e21ccb1

Browse files
committed
fast hessian and 3+ partial dierivative progress
1 parent bcd2b04 commit e21ccb1

File tree

2 files changed

+220
-8
lines changed

2 files changed

+220
-8
lines changed

examples/swifty.py

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import roboticstoolbox as rtb
77
import spatialmath as sm
8+
import numpy as np
89

910
# Launch the simulator Swift
1011
# env = rtb.backends.Swift()
@@ -67,9 +68,70 @@
6768
# print(panda.fkine(panda.q))
6869
# print(T)
6970

70-
r = rtb.models.Puma560()
71-
# r.q = [-0.5, -0.5, 0.5, 0.5, 0.5, 0.5]
72-
env = rtb.backends.Swift()
73-
env.launch()
74-
env.add(r)
75-
env.hold()
71+
# r = rtb.models.Puma560()
72+
# # r.q = [-0.5, -0.5, 0.5, 0.5, 0.5, 0.5]
73+
# env = rtb.backends.Swift()
74+
# env.launch()
75+
# env.add(r)
76+
# env.hold()
77+
78+
r = rtb.models.ETS.Panda()
79+
r.q = r.qr
80+
81+
q1 = r.qr
82+
q2 = q1 + 0.1
83+
84+
85+
def derivative(f, a, method='central', h=0.01):
86+
'''Compute the difference formula for f'(a) with step size h.
87+
88+
Parameters
89+
----------
90+
f : function
91+
Vectorized function of one variable
92+
a : number
93+
Compute derivative at x = a
94+
method : string
95+
Difference formula: 'forward', 'backward' or 'central'
96+
h : number
97+
Step size in difference formula
98+
99+
Returns
100+
-------
101+
float
102+
Difference formula:
103+
central: f(a+h) - f(a-h))/2h
104+
forward: f(a+h) - f(a))/h
105+
backward: f(a) - f(a-h))/h
106+
'''
107+
if method == 'central':
108+
return (f(a + h) - f(a - h))/(2*h)
109+
elif method == 'forward':
110+
return (f(a + h) - f(a))/h
111+
elif method == 'backward':
112+
return (f(a) - f(a - h))/h
113+
else:
114+
raise ValueError("Method must be 'central', 'forward' or 'backward'.")
115+
116+
117+
# Numerical hessian wrt q[0]
118+
# d = derivative(lambda x: r.jacob0(np.r_[x, q1[1:]]), q1[0], h=0.1)
119+
# print(np.round(h1[:, :, 0], 3))
120+
# print(np.round(d, 3))
121+
122+
# Numerical third wrt q[0]
123+
d = derivative(lambda x: r.hessian0(np.r_[x, q1[1:]]), q1[0], h=0.01)
124+
print(np.round(d[3:, :, 0], 3))
125+
print(np.round(r.third(q1)[3:, :, 0, 0], 3))
126+
127+
l = r.deriv(q1, 3)
128+
print(np.round(l[3:, :, 0, 0], 3))
129+
130+
# def runner():
131+
# for i in range(10000):
132+
# r.jacob0(r.q)
133+
# # r.hessian0(r.q)
134+
135+
136+
# import cProfile
137+
# cProfile.run('runner()')

roboticstoolbox/robot/ERobot.py

Lines changed: 152 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,6 +1364,150 @@ def jacobe(self, q, endlink=None, startlink=None, offset=None, T=None):
13641364
Je = self.jacobev(q, endlink, startlink, offset, T) @ J0
13651365
return Je
13661366

1367+
# def deriv(self, q, n, J0=None, endlink=None, startlink=None):
1368+
# endlink, startlink = self._get_limit_links(endlink, startlink)
1369+
1370+
# def cross(a, b):
1371+
# x = a[1] * b[2] - a[2] * b[1]
1372+
# y = a[2] * b[0] - a[0] * b[2]
1373+
# z = a[0] * b[1] - a[1] * b[0]
1374+
# return np.array([x, y, z])
1375+
1376+
# _, nl = self.get_path(endlink, startlink)
1377+
1378+
# J = self.jacob0(q, endlink=endlink, startlink=startlink)
1379+
# H = self.hessian0(q, J, endlink, startlink)
1380+
1381+
# d = [J, H]
1382+
# size = [6, nl, nl]
1383+
# count = np.array([0, 0])
1384+
# c = 2
1385+
1386+
# def add_indices(indices, c):
1387+
# total = len(indices * 2)
1388+
# new_indices = []
1389+
1390+
# for i in range(total):
1391+
# j = i // 2
1392+
# new_indices.append([])
1393+
# new_indices[i].append(indices[j][0].copy())
1394+
# new_indices[i].append(indices[j][1].copy())
1395+
1396+
# # if even number
1397+
# if i % 2 == 0:
1398+
# new_indices[i][0].append(c)
1399+
# # if odd number
1400+
# else:
1401+
# new_indices[i][1].append(c)
1402+
1403+
# return new_indices
1404+
1405+
# def add_pdi(pdi):
1406+
# total = len(pdi * 2)
1407+
# new_pdi = []
1408+
1409+
# for i in range(total):
1410+
# j = i // 2
1411+
# new_pdi.append([])
1412+
# new_pdi[i].append(pdi[j][0])
1413+
# new_pdi[i].append(pdi[j][1])
1414+
1415+
# # if even number
1416+
# if i % 2 == 0:
1417+
# new_pdi[i][0] += 1
1418+
# # if odd number
1419+
# else:
1420+
# new_pdi[i][1] += 1
1421+
1422+
# return new_pdi
1423+
1424+
# # these are the indices used for the hessian
1425+
# # indices = [[[2, 3], [1]], [[2], [1, 3]]]
1426+
# indices = [[[1], [0]]]
1427+
1428+
# # the are the pd indices used in the corss prods
1429+
# # pdi = [[2, 1], [1, 2]]
1430+
# pdi = [[0, 0]]
1431+
1432+
# while len(d) != n:
1433+
# size.append(nl)
1434+
# count = np.r_[count, 0]
1435+
# c += 1
1436+
# indices = add_indices(indices, 2)
1437+
# pdi = add_pdi(pdi)
1438+
# # print(indices)
1439+
# # print(pdi)
1440+
1441+
# # print("Statring:")
1442+
# # print(count)
1443+
# # print(size)
1444+
# # print(len(d))
1445+
1446+
# pd = np.zeros(size)
1447+
1448+
# for i in range(nl ** c):
1449+
# # print('Count: {0}'.format(count))
1450+
1451+
# res = np.zeros(3)
1452+
1453+
# for j in range(len(indices)):
1454+
# # print(pdi[j][0])
1455+
# pdr0 = d[pdi[j][0]]
1456+
# pdr1 = d[pdi[j][1]]
1457+
1458+
# idx0 = count[indices[j][0]]
1459+
# idx1 = count[indices[j][1]]
1460+
1461+
# res += cross(
1462+
# pdr0[(slice(3, 6), *idx0)],
1463+
# pdr1[(slice(3, 6), *idx1)])
1464+
# # print(pdr1[:3, idx1].shape)
1465+
# # res += pdr[:3, :, indices[j][0]]
1466+
1467+
# pd[(slice(3, 6), *count)] = res
1468+
1469+
# count[0] += 1
1470+
# for j in range(len(count)):
1471+
# if count[j] == nl:
1472+
# count[j] = 0
1473+
# if (j != len(count) - 1):
1474+
# count[j + 1] += 1
1475+
1476+
# d.append(pd)
1477+
# return d[-1]
1478+
1479+
# def third(self, q=None, J0=None, endlink=None, startlink=None):
1480+
# endlink, startlink = self._get_limit_links(endlink, startlink)
1481+
# path, n = self.get_path(endlink, startlink)
1482+
1483+
# def cross(a, b):
1484+
# x = a[1] * b[2] - a[2] * b[1]
1485+
# y = a[2] * b[0] - a[0] * b[2]
1486+
# z = a[0] * b[1] - a[1] * b[0]
1487+
# return np.array([x, y, z])
1488+
1489+
# if J0 is None:
1490+
# q = getvector(q, n)
1491+
# J0 = self.jacob0(q, endlink=endlink)
1492+
# else:
1493+
# verifymatrix(J0, (6, n))
1494+
1495+
# H0 = self.hessian0(q, J0, endlink, startlink)
1496+
1497+
# L = np.zeros((6, n, n, n))
1498+
1499+
# for l in range(n):
1500+
# for k in range(n):
1501+
# for j in range(n):
1502+
1503+
# # H[:3, i, j] = cross(J0[3:, j], J0[:3, i])
1504+
# L[3:, j, k, l] = cross(H0[3:, k, l], J0[3:, j]) + \
1505+
# cross(J0[3:, k], H0[3:, j, l])
1506+
# # if i != j:
1507+
# # H[:3, j, i] = H[:3, i, j]
1508+
1509+
# return L
1510+
13671511
def hessian0(self, q=None, J0=None, endlink=None, startlink=None):
13681512
"""
13691513
The manipulator Hessian tensor maps joint acceleration to end-effector
@@ -1406,6 +1550,12 @@ def hessian0(self, q=None, J0=None, endlink=None, startlink=None):
14061550
endlink, startlink = self._get_limit_links(endlink, startlink)
14071551
path, n = self.get_path(endlink, startlink)
14081552

1553+
def cross(a, b):
1554+
x = a[1] * b[2] - a[2] * b[1]
1555+
y = a[2] * b[0] - a[0] * b[2]
1556+
z = a[0] * b[1] - a[1] * b[0]
1557+
return np.array([x, y, z])
1558+
14091559
if J0 is None:
14101560
q = getvector(q, n)
14111561
J0 = self.jacob0(q, endlink=endlink)
@@ -1417,8 +1567,8 @@ def hessian0(self, q=None, J0=None, endlink=None, startlink=None):
14171567
for j in range(n):
14181568
for i in range(j, n):
14191569

1420-
H[:3, i, j] = np.cross(J0[3:, j], J0[:3, i])
1421-
H[3:, i, j] = np.cross(J0[3:, j], J0[3:, i])
1570+
H[:3, i, j] = cross(J0[3:, j], J0[:3, i])
1571+
H[3:, i, j] = cross(J0[3:, j], J0[3:, i])
14221572

14231573
if i != j:
14241574
H[:3, j, i] = H[:3, i, j]

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy