Skip to content

Commit adfa2f0

Browse files
authored
Add files via upload
1 parent a891055 commit adfa2f0

File tree

2 files changed

+465
-0
lines changed

2 files changed

+465
-0
lines changed

FwdKin.py

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
from mpl_toolkits.mplot3d import Axes3D
4+
from random import randint
5+
6+
#make numpy raise errors instead of warn so can be caught by try except blocks
7+
np.seterr(all='raise')
8+
9+
#plot axis origins onto point with rotation
10+
def plotOrigin(tx, ty, tz, rx, ry, rz, length):
11+
#transform origin
12+
rotall = np.matmul(np.matmul(Rz(rz), Ry(ry)), Rx(rx))
13+
xplots = np.matmul(rotall, ((0,length), (0,0), (0,0)))
14+
yplots = np.matmul(rotall, ((0,0), (0,length), (0,0)))
15+
zplots = np.matmul(rotall, ((0,0), (0,0), (0,length)))
16+
xplots[0] += tx
17+
xplots[1] += ty
18+
xplots[2] += tz
19+
yplots[0] += tx
20+
yplots[1] += ty
21+
yplots[2] += tz
22+
zplots[0] += tx
23+
zplots[1] += ty
24+
zplots[2] += tz
25+
26+
#plot origin
27+
ax.plot(*xplots, c='#ff0000')
28+
ax.plot(*yplots, c='#00ff00')
29+
ax.plot(*zplots, c='#0000ff')
30+
31+
#find the position of point given a vector
32+
def findPoint(start, length, theta1, theta2):
33+
end = [0, 0, 0]
34+
end[0] = start[0] + length * np.cos(theta1) * np.cos(theta2)
35+
end[1] = start[1] + length * np.cos(theta1) * np.sin(theta2)
36+
end[2] = start[2] + length * np.sin(theta1)
37+
return end
38+
39+
#define rotation matrices
40+
def Rx(a):
41+
return ((1, 0, 0),
42+
(0, np.cos(a), -np.sin(a)),
43+
(0, np.sin(a), np.cos(a)))
44+
45+
def Ry(a):
46+
return ((np.cos(a), 0, np.sin(a)),
47+
(0, 1, 0),
48+
(-np.sin(a), 0, np.cos(a)))
49+
50+
def Rz(a):
51+
return ((np.cos(a), -np.sin(a), 0),
52+
(np.sin(a), np.cos(a), 0),
53+
(0, 0, 1))
54+
55+
#function to find angle between two vectors
56+
def getAngle(vect1, vect2):
57+
try:
58+
temp1 = np.linalg.norm(vect1)
59+
temp2 = np.linalg.norm(vect2)
60+
unitvect1 = vect1 / temp1
61+
unitvect2 = vect2 / temp2
62+
theta = np.arccos(np.clip(np.dot(unitvect1, unitvect2), -1.0, 1.0))
63+
return theta
64+
except Exception:
65+
return np.pi/2 if temp2 > 0 else -np.pi/2
66+
67+
#linear interpolation
68+
def lerp(a, b, t):
69+
return (a * (1 - t)) + (b * t)
70+
71+
def fwdKin(lengths, angles):
72+
#trace the path to find plot points
73+
xplots = [0, 0]
74+
yplots = [0, 0]
75+
zplots = [0, lengths[0]]
76+
mainlength1 = lengths[1]
77+
mainlength2 = lengths[2] + lengths[3]
78+
mainlength3 = lengths[4] + lengths[5]
79+
theta1 = (np.pi/2)-angles[1]
80+
theta2 = angles[0]
81+
point = findPoint([xplots[1], yplots[1], zplots[1]], mainlength1, theta1, theta2)
82+
xplots.append(point[0])
83+
yplots.append(point[1])
84+
zplots.append(point[2])
85+
theta1 = (np.pi/2)-angles[1]-angles[2]
86+
theat2 = angles[0]
87+
point = findPoint([xplots[2], yplots[2], zplots[2]], mainlength2, theta1, theta2)
88+
savedpoint = point #save the point for later derivation
89+
xplots.append(lerp(xplots[2], point[0], lengths[2]/mainlength2))
90+
yplots.append(lerp(yplots[2], point[1], lengths[2]/mainlength2))
91+
zplots.append(lerp(zplots[2], point[2], lengths[2]/mainlength2))
92+
xplots.append(point[0])
93+
yplots.append(point[1])
94+
zplots.append(point[2])
95+
transformed = np.array([mainlength3, 0, 0])
96+
transformed = np.matmul(Ry(angles[4]), transformed)
97+
transformed = np.matmul(Rx(angles[3]), transformed)
98+
transformed = np.matmul(Ry(np.pi + theta1), transformed)
99+
transformed = np.matmul(Rz(np.pi + theta2), transformed)
100+
point = transformed + point
101+
xplots.append(lerp(xplots[4], point[0], lengths[4]/mainlength3))
102+
yplots.append(lerp(yplots[4], point[1], lengths[4]/mainlength3))
103+
zplots.append(lerp(zplots[4], point[2], lengths[4]/mainlength3))
104+
xplots.append(point[0])
105+
yplots.append(point[1])
106+
zplots.append(point[2])
107+
108+
#convert the data type
109+
xplots = np.array(xplots)
110+
yplots = np.array(yplots)
111+
zplots = np.array(zplots)
112+
113+
#we now know the end position
114+
tx = xplots[-1]
115+
ty = yplots[-1]
116+
tz = zplots[-1]
117+
118+
#derive theta1 and theta2 of wrist vector
119+
#define root vectors
120+
wrstvect = point - savedpoint
121+
122+
txdelta = wrstvect[0]
123+
tydelta = wrstvect[1]
124+
tzdelta = wrstvect[2]
125+
126+
elevvect = np.array([txdelta, tydelta, 0])
127+
azimvect = np.array([txdelta, 0, tzdelta])
128+
129+
elevangle = getAngle(elevvect, wrstvect)
130+
azimangle = getAngle(azimvect, wrstvect)
131+
132+
if tzdelta < 0:
133+
elevangle *= -1
134+
135+
if tydelta < 0:
136+
azimangle *= -1
137+
138+
rx = angles[5]
139+
ry = -elevangle
140+
rz = azimangle
141+
142+
return ((tx,ty,tz,rx,ry,rz), xplots, yplots, zplots)
143+
144+
def main():
145+
global ax
146+
147+
#create and configure plot object
148+
fig = plt.figure(figsize=(8,8))
149+
fig.subplots_adjust(left=0.01, bottom=0.01, right=0.96, top=0.96)
150+
ax = fig.add_subplot(111, projection='3d')
151+
#ax.set(xlim=(-260,260), ylim=(-260,260), zlim=(0,400))
152+
ax.set(xlim=(0,260), ylim=(0,260), zlim=(0,200))
153+
ax.w_xaxis.line.set_color('#ff0000')
154+
ax.w_yaxis.line.set_color('#00ff00')
155+
ax.w_zaxis.line.set_color('#0000ff')
156+
ax.set_xlabel('x-axis')
157+
ax.set_ylabel('y-axis')
158+
ax.set_zlabel('z-axis')
159+
#ax.view_init(elev=30, azim=-135)
160+
ax.view_init(elev=30, azim=135)
161+
162+
lengths = np.array([50.0, 200.0, 100.0, 100.0, 25.0, 25.0])
163+
164+
angles = np.array([60, 30, 90, 0, 0, 0])
165+
166+
raw = fwdKin(lengths, np.radians(angles))
167+
tx = raw[0][0]
168+
ty = raw[0][1]
169+
tz = raw[0][2]
170+
rx = raw[0][3]
171+
ry = raw[0][4]
172+
rz = raw[0][5]
173+
xplots = raw[1]
174+
yplots = raw[2]
175+
zplots = raw[3]
176+
177+
#plot data
178+
ax.plot(xplots, yplots, zplots, c='#000000')
179+
ax.scatter(xplots, yplots, zplots, c='#00ffff')
180+
plotOrigin(xplots[0], yplots[0], zplots[0], 0, 0, 0, 50)
181+
plotOrigin(xplots[6], yplots[6], zplots[6], rx, ry, rz, 50)
182+
183+
#output calculated position
184+
print(f'Tx = {round(tx,2)} mm')
185+
print(f'Ty = {round(ty,2)} mm')
186+
print(f'Tz = {round(tz,2)} mm')
187+
print(f'Rx = {round(np.degrees(rx),2)} deg')
188+
print(f'Ry = {round(np.degrees(ry),2)} deg')
189+
print(f'Rz = {round(np.degrees(rz),2)} deg')
190+
191+
#show plotted data
192+
plt.show()
193+
194+
if __name__ == '__main__':
195+
main()

0 commit comments

Comments
 (0)