Skip to content

Commit 48e97d3

Browse files
committed
Make Ts None if no static transform
1 parent 68ffcdb commit 48e97d3

File tree

4 files changed

+28
-33
lines changed

4 files changed

+28
-33
lines changed

roboticstoolbox/robot/ET.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ def A(self, q: Union[float, Sym] = 0.0) -> ndarray:
561561
# We can't use the fast version, lets use Python instead
562562
if self.isjoint:
563563
if self.isflip:
564-
q = -q
564+
q = -q # type: ignore
565565

566566
if self.axis_func is not None:
567567
return self.axis_func(q)

roboticstoolbox/robot/Link.py

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -226,25 +226,25 @@ def dynpar(self, name, value, default):
226226
def _init_Ts(self):
227227
# Compute the leading, constant, part of the ETS
228228

229-
# Ts can not be equal to None otherwise things seem
230-
# to break everywhere, so initialise Ts np be identity
231-
232229
if isinstance(self, Link2):
233-
T = np.eye(3)
230+
T = None
234231
else:
235-
T = np.eye(4)
232+
T = None
236233

237234
for et in self._ets:
238235
# constant transforms only
239236
if et.isjoint:
240237
break
241238
else:
242-
T = T @ et.A()
239+
if T is None:
240+
T = et.A()
241+
else:
242+
T = T @ et.A()
243243

244244
self._Ts = T
245245

246246
@property
247-
def Ts(self) -> NDArray:
247+
def Ts(self) -> Union[NDArray, None]:
248248
"""
249249
Constant part of link ETS
250250
@@ -733,7 +733,6 @@ def I(self) -> NDArray: # noqa
733733
@I.setter
734734
@_listen_dyn
735735
def I(self, I_new: ArrayLike): # noqa
736-
737736
if ismatrix(I_new, (3, 3)):
738737
# 3x3 matrix passed
739738
if np.any(np.abs(I_new - I_new.T) > 1e-8): # type: ignore
@@ -947,7 +946,6 @@ def collision(self) -> SceneGroup:
947946

948947
@collision.setter
949948
def collision(self, coll: Union[SceneGroup, List[Shape], Shape]):
950-
951949
if isinstance(coll, list):
952950
self.collision.scene_children = coll # type: ignore
953951
elif isinstance(coll, Shape):
@@ -957,7 +955,6 @@ def collision(self, coll: Union[SceneGroup, List[Shape], Shape]):
957955

958956
@geometry.setter
959957
def geometry(self, geom: Union[SceneGroup, List[Shape], Shape]):
960-
961958
if isinstance(geom, list):
962959
self.geometry.scene_children = geom # type: ignore
963960
elif isinstance(geom, Shape):
@@ -1616,7 +1613,6 @@ class Link(BaseLink):
16161613
def __init__(
16171614
self, ets: Union[ETS, ET] = ETS(), jindex: Union[None, int] = None, **kwargs
16181615
):
1619-
16201616
# process common options
16211617
super().__init__(ets=ets, **kwargs)
16221618

@@ -1651,14 +1647,19 @@ def A(self, q: float = 0.0) -> SE3:
16511647
16521648
"""
16531649
if self.isjoint:
1654-
return SE3(self._Ts @ self._ets[-1].A(q), check=False)
1655-
else:
1650+
if self._Ts is not None:
1651+
return SE3(self._Ts @ self._ets[-1].A(q), check=False)
1652+
else:
1653+
return SE3(self._ets[-1].A(q), check=False)
1654+
1655+
elif self._Ts is not None:
16561656
return SE3(self._Ts, check=False)
1657+
else:
1658+
return SE3()
16571659

16581660

16591661
class Link2(BaseLink):
16601662
def __init__(self, ets: ETS2 = ETS2(), jindex: Union[int, None] = None, **kwargs):
1661-
16621663
# process common options
16631664
super().__init__(ets=ets, **kwargs)
16641665

@@ -1693,6 +1694,12 @@ def A(self, q: float = 0.0) -> SE2:
16931694
"""
16941695

16951696
if self.isjoint:
1696-
return SE2(self._Ts @ self._ets[-1].A(q), check=False)
1697-
else:
1697+
if self._Ts is not None:
1698+
return SE2(self._Ts @ self._ets[-1].A(q), check=False)
1699+
else:
1700+
return SE2(self._ets[-1].A(q), check=False)
1701+
1702+
elif self._Ts is not None:
16981703
return SE2(self._Ts, check=False)
1704+
else:
1705+
return SE2()

roboticstoolbox/robot/Robot.py

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@
6363

6464

6565
class Robot(BaseRobot[Link], RobotKinematicsMixin):
66-
6766
_color = True
6867

6968
def __init__(
@@ -83,7 +82,6 @@ def __init__(
8382
urdf_string: Union[str, None] = None,
8483
urdf_filepath: Union[Path, PurePosixPath, None] = None,
8584
):
86-
8785
# Process links
8886
if isinstance(arg, Robot):
8987
# We're passed a Robot, clone it
@@ -117,7 +115,6 @@ def __init__(
117115
self._urdf_string = arg.urdf_string
118116
self._urdf_filepath = arg.urdf_filepath
119117
else:
120-
121118
if isinstance(arg, ETS):
122119
# We're passed an ETS string
123120
links = []
@@ -161,11 +158,9 @@ def __init__(
161158
# --------------------------------------------------------------------- #
162159

163160
def _to_dict(self, robot_alpha=1.0, collision_alpha=0.0):
164-
165161
ob = []
166162

167163
for link in self.links:
168-
169164
if robot_alpha > 0:
170165
for gi in link.geometry:
171166
gi.set_alpha(robot_alpha)
@@ -178,7 +173,6 @@ def _to_dict(self, robot_alpha=1.0, collision_alpha=0.0):
178173
# Do the grippers now
179174
for gripper in self.grippers:
180175
for link in gripper.links:
181-
182176
if robot_alpha > 0:
183177
for gi in link.geometry:
184178
gi.set_alpha(robot_alpha)
@@ -198,7 +192,6 @@ def _fk_dict(self, robot_alpha=1.0, collision_alpha=0.0):
198192

199193
# Do the robot
200194
for link in self.links:
201-
202195
if robot_alpha > 0:
203196
for gi in link.geometry:
204197
ob.append(gi.fk_dict())
@@ -1049,7 +1042,6 @@ def jacob0_dot(
10491042
qd = np.array(qd)
10501043

10511044
if representation is None:
1052-
10531045
if J0 is None:
10541046
J0 = self.jacob0(q)
10551047
H = self.hessian0(q, J0=J0)
@@ -1767,7 +1759,7 @@ def rne(
17671759
I[j] = SpatialInertia(m=link.m, r=link.r)
17681760
if symbolic and link.Ts is None: # pragma: nocover
17691761
Xtree[j] = SE3(np.eye(4, dtype="O"), check=False)
1770-
else:
1762+
elif link.Ts is not None:
17711763
Xtree[j] = Ts * SE3(link.Ts, check=False)
17721764

17731765
if link.v is not None:
@@ -1780,7 +1772,8 @@ def rne(
17801772
Ts = SE3()
17811773
else: # pragma nocover
17821774
# TODO Keep track of inertia and transform???
1783-
Ts *= SE3(link.Ts, check=False)
1775+
if link.Ts is not None:
1776+
Ts *= SE3(link.Ts, check=False)
17841777

17851778
if gravity is None:
17861779
a_grav = -SpatialAcceleration(self.gravity)
@@ -1808,7 +1801,6 @@ def rne(
18081801

18091802
# backward recursion
18101803
for j in reversed(range(0, n)):
1811-
18121804
# next line could be dot(), but fails for symbolic arguments
18131805
Q[k, j] = sum(f[j].A * s[j])
18141806

@@ -1829,7 +1821,6 @@ def rne(
18291821

18301822
class Robot2(BaseRobot[Link2]):
18311823
def __init__(self, arg, **kwargs):
1832-
18331824
if isinstance(arg, ETS2):
18341825
# we're passed an ETS string
18351826
links = []

tests/test_ELink.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@ def test_properties(self):
166166
self.assertEqual(l0.Jm, 0.0)
167167

168168
def test_fail_parent(self):
169-
170169
with self.assertRaises(TypeError):
171170
rtb.Link(parent=1)
172171

@@ -243,7 +242,7 @@ def test_init_ets2(self):
243242
e1 = rtb.ET2.R()
244243
link = BaseLink(e1)
245244

246-
nt.assert_almost_equal(link.Ts, np.eye(4))
245+
self.assertEqual(link.Ts, None)
247246

248247
def test_get_ets(self):
249248
e1 = rtb.ETS(rtb.ET.Ry())
@@ -334,7 +333,6 @@ def test_dyn2list(self):
334333
self.assertEqual(s, ans)
335334

336335
def test_init_fail4(self):
337-
338336
with self.assertRaises(TypeError):
339337
rtb.Link(2.0) # type: ignore
340338

@@ -352,5 +350,4 @@ def test_ets2_A2(self):
352350

353351

354352
if __name__ == "__main__":
355-
356353
unittest.main()

0 commit comments

Comments
 (0)