4
4
"""
5
5
6
6
# import numpy as np
7
- from spatialmath import SE3
7
+ from spatialmath import SE3 , SE2 , SMPose
8
8
# from spatialmath.base.argcheck import getvector, verifymatrix, isscalar
9
9
import roboticstoolbox as rp
10
- from roboticstoolbox .robot .ETS import ETS
10
+ from roboticstoolbox .robot .ETS import ETS , SuperETS
11
11
from roboticstoolbox .robot .Link import Link
12
12
13
13
@@ -41,7 +41,15 @@ class ELink(Link):
41
41
42
42
It inherits from the Link class which provides common functionality such
43
43
as joint and link such as kinematics parameters,
44
- .
44
+
45
+
46
+ The transform to the next link is given as an ETS with the joint
47
+ variable, if present, as the last term. This is preprocessed and
48
+ the object stores:
49
+
50
+ * ``Ts`` the constant part as a NumPy array, or None
51
+ * ``v`` a pointer to an ETS object representing the joint variable.
52
+ or None
45
53
46
54
:references:
47
55
- Kinematic Derivatives using the Elementary Transform Sequence,
@@ -62,11 +70,12 @@ def __init__(
62
70
super (ELink , self ).__init__ (** kwargs )
63
71
64
72
# check we have an ETS
65
- if isinstance (ets , ETS ):
66
- self ._ets = ets
67
- else :
73
+ if not isinstance (ets , SuperETS ):
68
74
raise TypeError (
69
75
'The ets argument must be of type ETS' )
76
+ self ._ndims = ets ._ndims
77
+
78
+ self ._ets = ets
70
79
71
80
if v is None and len (ets ) > 0 and ets [- 1 ].isjoint :
72
81
v = ets .pop ()
@@ -76,10 +85,10 @@ def __init__(
76
85
jindex = v .jindex
77
86
78
87
# TODO simplify this logic, can be ELink class or None
79
- if isinstance (parent , list ):
80
- raise TypeError (
81
- 'Only one parent link can be present' )
82
- elif not isinstance (parent , ELink ) and parent is not None :
88
+ # if isinstance(parent, list):
89
+ # raise TypeError(
90
+ # 'Only one parent link can be present')
91
+ if not isinstance (parent , ELink ) and parent is not None :
83
92
raise TypeError (
84
93
'Parent must be of type ELink' )
85
94
@@ -95,7 +104,7 @@ def __init__(
95
104
# Check the variable joint
96
105
if v is None :
97
106
self ._joint = False
98
- elif not isinstance (v , ETS ):
107
+ elif not isinstance (v , SuperETS ):
99
108
raise TypeError ('v must be of type ETS' )
100
109
elif not v [0 ].isjoint :
101
110
raise ValueError ('v must be a variable ETS' )
@@ -111,20 +120,28 @@ def _init_Ts(self):
111
120
# Number of transforms in the ETS excluding the joint variable
112
121
self ._M = len (self ._ets )
113
122
114
- # Initialise joints
115
- if isinstance (self ._ets , ETS ):
116
- self ._Ts = SE3 ()
117
- for i in range (self .M ):
118
- if self ._ets [i ].isjoint :
123
+ # Compute the leading, constant, part of the ETS
124
+ # TODO probably should use ETS.compile()
125
+
126
+ if isinstance (self ._ets , SuperETS ):
127
+ first = True
128
+ T = None
129
+
130
+ for et in self ._ets :
131
+ # constant transforms only
132
+ if et .isjoint :
119
133
raise ValueError ('The transforms in ets must be constant' )
120
134
121
- if not isinstance (self ._ets [i ].T (), SE3 ):
122
- self ._Ts *= SE3 (self ._ets [i ].T ())
135
+ if first :
136
+ T = et .T ()
137
+ first = False
123
138
else :
124
- self ._Ts *= self ._ets [i ].T ()
139
+ T = T @ et .T ()
140
+ self ._Ts = T
125
141
126
142
elif isinstance (self ._ets , SE3 ):
127
143
self ._Ts = self ._ets
144
+ raise RuntimeError ('this shouldnt happen' )
128
145
129
146
def __repr__ (self ):
130
147
name = self .__class__ .__name__
@@ -365,21 +382,43 @@ def A(self, q=None, fast=False):
365
382
transformation from the previous to the current link frame to
366
383
the next, which depends on the joint coordinate ``q``.
367
384
385
+ If ``fast`` is True return a NumPy array, either SE(2) or SE(3).
386
+ A value of None means that it is the identity matrix.
387
+
388
+ If ``fast`` is False return an ``SE2`` or ``SE3`` instance.
389
+
368
390
"""
369
391
392
+ # we work with NumPy arrays for speed
370
393
if self .isjoint :
371
394
# a variable joint
372
395
if q is None :
373
396
raise ValueError ("q is required for variable joints" )
374
- T = self .Ts .A @ self .v .T (q )
397
+
398
+ # premultiply variable part by constant part if present
399
+ Ts = self .Ts
400
+ if Ts is None :
401
+ T = self .v .T (q )
402
+ else :
403
+ T = Ts @ self .v .T (q )
375
404
else :
376
405
# a fixed joint
377
- T = self .Ts . A
406
+ T = self .Ts
378
407
379
408
if fast :
380
409
return T
410
+
411
+ if T is None :
412
+ if self ._ndims == 3 :
413
+ return SE3 ()
414
+ elif self ._ndims == 2 :
415
+ return SE2 ()
381
416
else :
382
- return SE3 (T , check = False )
417
+ if self ._ndims == 3 :
418
+ return SE3 (T , check = False )
419
+ elif self ._ndims == 2 :
420
+ return SE2 (T , check = False )
421
+
383
422
384
423
def ets (self ):
385
424
if self .v is None :
0 commit comments