-
Notifications
You must be signed in to change notification settings - Fork 0
/
CoordSys.py
157 lines (134 loc) · 4.12 KB
/
CoordSys.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import numpy as np
from glm import mat4
class Robot:
def __init__(self):
self.joints = None
def initialise(self):
"""
Initialise joints
self.joints is structured such that object at index i-1 is the parent of the object at i
:return:
"""
self.joints = [None, Joint(None), Joint(None)]
def return_joint(self, i):
"""
Return specified joint
:param i: Number of the joint to be returned
:return: Specified joint
"""
return self.joints[i + 2]
def append_joint(self):
"""
Add an extra joint at the end up to 10
:return: Success value
"""
if self.len > 10:
return 0
self.joints.append(Joint(self.joints[-1]))
return 1
def insert_joint(self, i):
"""
Inserts a new joint before the one specified up to 10
:param i: Number the new joint will have
:return: Success value
"""
if self.len > 10:
return 0
self.joints.insert(i + 1, Joint(self.joints[i]))
return 1
def pop_joint(self):
"""
Remove a joint from the and down to 2
:return: Success value
"""
if self.len == 2:
return 0
self.joints.pop(-1)
return 1
def remove_joint(self, i):
"""
Remove a specified joint
:param i: Number of the joint to be removed
:return: Success value
"""
if self.len == 2:
return 0
self.joints.pop(i + 1)
return 1
@property
def len(self):
return len(self.joints) - 1
def update_joint(self, joint_num):
"""
Update position of a joint, and all his children
:param joint_num: Number of the joint to be updated
:return:
"""
for i in range(joint_num+2, len(self.joints)):
self.joints[i].update(self.joints[i-1])
def draw(self, proj, view):
"""
Draw all the joints
:param proj: projection matrix
:param view: view matrix
:return:
"""
for joint in reversed(self.joints[1:]):
joint.draw(proj, view)
class Joint:
def __init__(self, parent):
from Objects3D import coord_3d
self.coord_3d = coord_3d.copy()
self.alpha, self.a, self.d, self.theta = 0.0, 0.0, 0.0, 0.0
self.d_var, self.theta_var = False, False # Not used yet
self.mat = np.eye(4)
# place it in the world on initialisation
self.update(parent)
def update(self, parent):
"""
Update joints positions relative to it's parent
:param parent: Joint parent
:return:
"""
# if this is the parent joint then this joint is in the origin so no translation nor rotation
if parent is None:
self.mat = np.eye(4)
else:
# if it has a parent then calculate this joints global position matrix
self.mat = parent.mat @ self.generate_matrix
# apply the matrix
self.coord_3d.apply_mat(mat4(self.mat.T.tolist()))
@property
def generate_matrix(self) -> np.ndarray:
"""
Create and return homogeneous matrix
"""
s_t = self.sin(self.theta)
c_t = self.cos(self.theta)
s_a = self.sin(self.alpha)
c_a = self.cos(self.alpha)
return np.array([[c_t, -s_t * c_a, s_t * s_a, self.a * c_t],
[s_t, c_t * c_a, -c_t * s_a, self.a * s_t],
[0, s_a, c_a, self.d],
[0, 0, 0, 1]])
# Sin i cos that return whole numbers for popular angles
@staticmethod
def sin(x):
if x in [0, 180]:
return 0
if x == 90:
return 1
if x == 270:
return -1
return np.sin(np.deg2rad(x))
@staticmethod
def cos(x):
if x == 0:
return 1
if x in [90, 270]:
return 0
if x == 180:
return -1
return np.cos(np.deg2rad(x))
def draw(self, proj, view):
self.coord_3d.draw(proj, view)