4
4
from spatialmath import base
5
5
import spatialmath .pose3d as pose3d
6
6
from spatialmath .base .types import ArrayLike3 , R8x8 , R8
7
- from typing import Self , overload
7
+ from typing import overload
8
8
9
9
# TODO scalar multiplication
10
10
@@ -77,7 +77,7 @@ def __init__(
77
77
raise ValueError ("expecting zero or two parameters" )
78
78
79
79
@classmethod
80
- def Pure (cls , x : ArrayLike3 ) -> Self :
80
+ def Pure (cls , x : ArrayLike3 ) -> DualQuaternion :
81
81
x = base .getvector (x , 3 )
82
82
return cls (UnitQuaternion (), Quaternion .Pure (x ))
83
83
@@ -123,7 +123,7 @@ def norm(self) -> tuple[float, float]:
123
123
b = self .real * self .dual .conj () + self .dual * self .real .conj ()
124
124
return (base .sqrt (a .s ), base .sqrt (b .s ))
125
125
126
- def conj (self ) -> Self :
126
+ def conj (self ) -> DualQuaternion :
127
127
r"""
128
128
Conjugate of dual quaternion
129
129
@@ -144,7 +144,7 @@ def conj(self) -> Self:
144
144
"""
145
145
return DualQuaternion (self .real .conj (), self .dual .conj ())
146
146
147
- def __add__ (left , right : DualQuaternion ) -> Self : # pylint: disable=no-self-argument
147
+ def __add__ (self : DualQuaternion , right : DualQuaternion ) -> DualQuaternion :
148
148
"""
149
149
Sum of two dual quaternions
150
150
@@ -159,9 +159,12 @@ def __add__(left, right: DualQuaternion) -> Self: # pylint: disable=no-self-arg
159
159
>>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
160
160
>>> d + d
161
161
"""
162
- return DualQuaternion (left .real + right .real , left .dual + right .dual )
162
+ assert self .real is not None and self .dual is not None
163
+ assert right .real is not None and right .dual is not None
163
164
164
- def __sub__ (left , right : DualQuaternion ) -> Self : # pylint: disable=no-self-argument
165
+ return DualQuaternion (self .real + right .real , self .dual + right .dual )
166
+
167
+ def __sub__ (self , right : DualQuaternion ) -> DualQuaternion :
165
168
"""
166
169
Difference of two dual quaternions
167
170
@@ -176,9 +179,12 @@ def __sub__(left, right: DualQuaternion) -> Self: # pylint: disable=no-self-arg
176
179
>>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
177
180
>>> d - d
178
181
"""
179
- return DualQuaternion (left .real - right .real , left .dual - right .dual )
182
+ assert self .real is not None and self .dual is not None
183
+ assert right .real is not None and right .dual is not None
184
+
185
+ return DualQuaternion (self .real - right .real , self .dual - right .dual )
180
186
181
- def __mul__ (left , right : Self ) -> Self : # pylint: disable=no-self-argument
187
+ def __mul__ (self : DualQuaternion , right : DualQuaternion ) -> DualQuaternion :
182
188
"""
183
189
Product of dual quaternion
184
190
@@ -196,19 +202,23 @@ def __mul__(left, right: Self) -> Self: # pylint: disable=no-self-argument
196
202
>>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
197
203
>>> d * d
198
204
"""
205
+ assert self .real is not None and self .dual is not None
206
+ assert right .real is not None and right .dual is not None
207
+
199
208
if isinstance (right , DualQuaternion ):
200
- real = left .real * right .real
201
- dual = left .real * right .dual + left .dual * right .real
209
+ real = self .real * right .real
210
+ dual = self .real * right .dual + self .dual * right .real
202
211
203
- if isinstance (left , UnitDualQuaternion ) and isinstance (
204
- left , UnitDualQuaternion
212
+ if isinstance (self , UnitDualQuaternion ) and isinstance (
213
+ self , UnitDualQuaternion
205
214
):
206
215
return UnitDualQuaternion (real , dual )
207
216
else :
208
217
return DualQuaternion (real , dual )
209
- elif isinstance (left , UnitDualQuaternion ) and base .isvector (right , 3 ):
218
+
219
+ elif isinstance (self , UnitDualQuaternion ) and base .isvector (right , 3 ):
210
220
v = base .getvector (right , 3 )
211
- vp = left * DualQuaternion .Pure (v ) * left .conj ()
221
+ vp = self * DualQuaternion .Pure (v ) * self .conj ()
212
222
return vp .dual .v
213
223
214
224
def matrix (self ) -> R8x8 :
@@ -231,6 +241,8 @@ def matrix(self) -> R8x8:
231
241
>>> d.matrix() @ d.vec
232
242
>>> d * d
233
243
"""
244
+ assert self .real is not None and self .dual is not None
245
+
234
246
return np .block (
235
247
[[self .real .matrix , np .zeros ((4 , 4 ))], [self .dual .matrix , self .real .matrix ]]
236
248
)
@@ -251,10 +263,9 @@ def vec(self) -> R8:
251
263
>>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
252
264
>>> d.vec
253
265
"""
254
- return np . r_ [ self .real . vec , self .dual . vec ]
266
+ assert self .real is not None and self .dual is not None
255
267
256
- # def log(self):
257
- # pass
268
+ return np .r_ [self .real .vec , self .dual .vec ]
258
269
259
270
260
271
class UnitDualQuaternion (DualQuaternion ):
@@ -270,13 +281,7 @@ class UnitDualQuaternion(DualQuaternion):
270
281
:seealso: :func:`UnitDualQuaternion`
271
282
"""
272
283
273
- @overload
274
- def __init__ (self , T : pose3d .SE3 ): ...
275
-
276
- @overload
277
- def __init__ (self , real : Quaternion , dual : Quaternion ): ...
278
-
279
- def __init__ (self , real = None , dual = None ):
284
+ def __init__ (self , real : Quaternion | None = None , dual : Quaternion | None = None ) -> None :
280
285
r"""
281
286
Create new unit dual quaternion
282
287
0 commit comments