12
12
13
13
_numtypes = (int , np .int64 , float , np .float64 )
14
14
15
+
15
16
class BasePoseList (UserList , ABC ):
16
17
"""
17
18
List properties for spatial math classes
18
19
19
20
Each of the spatial math classes behaves like a regular Python object and
20
- an instance contains a value of a particular type, for example an SE(3)
21
+ an instance contains a value of a particular type, for example an SE(3)
21
22
matrix, a unit quaternion, a twist etc.
22
23
23
24
This class adds list-like capabilities to each of spatial math classes. This
24
- means that an instance is not limited to holding just a single value (a
25
- singleton instance), it can hold a list of values. That list can contain
25
+ means that an instance is not limited to holding just a single value (a
26
+ singleton instance), it can hold a list of values. That list can contain
26
27
zero or more items. This is helpful for:
27
-
28
+
28
29
- storing sequences (trajectories) where it is important to know that all
29
30
elements in the sequence are of the same time and have valid values
30
31
- arrays of the same type to enable C++ like programming patterns
@@ -86,7 +87,7 @@ def _import(self, x, check=True):
86
87
def Empty (cls ):
87
88
"""
88
89
Construct an empty instance (BasePoseList superclass method)
89
-
90
+
90
91
:return: pose instance with zero values
91
92
92
93
Example::
@@ -117,7 +118,7 @@ def Alloc(cls, n=1):
117
118
can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
118
119
119
120
.. note:: The default value depends on the pose class and is the result
120
- of the empty constructor. For ``SO2``,
121
+ of the empty constructor. For ``SO2``,
121
122
``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
122
123
twist class ``Twist2`` or ``Twist3`` it is a zero vector,
123
124
for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
@@ -195,10 +196,16 @@ def arghandler(self, arg, convertfrom=(), check=True):
195
196
196
197
elif type (arg [0 ]) == type (self ):
197
198
# possibly a list of objects of same type
198
- assert all (map (lambda x : type (x ) == type (self ), arg )), 'elements of list are incorrect type'
199
+ assert all (
200
+ map (lambda x : type (x ) == type (self ), arg )
201
+ ), "elements of list are incorrect type"
199
202
self .data = [x .A for x in arg ]
200
203
201
- elif argcheck .isnumberlist (arg ) and len (self .shape ) == 1 and len (arg ) == self .shape [0 ]:
204
+ elif (
205
+ argcheck .isnumberlist (arg )
206
+ and len (self .shape ) == 1
207
+ and len (arg ) == self .shape [0 ]
208
+ ):
202
209
self .data = [np .array (arg )]
203
210
204
211
else :
@@ -215,7 +222,9 @@ def arghandler(self, arg, convertfrom=(), check=True):
215
222
# get method to convert from arg to self types
216
223
converter = getattr (arg .__class__ , type (self ).__name__ )
217
224
except AttributeError :
218
- raise ValueError ('argument has no conversion method to this type' ) from None
225
+ raise ValueError (
226
+ "argument has no conversion method to this type"
227
+ ) from None
219
228
self .data = [converter (arg ).A ]
220
229
221
230
else :
@@ -245,11 +254,11 @@ def A(self):
245
254
:return: NumPy array value of this instance
246
255
:rtype: ndarray
247
256
248
- - ``X.A`` is a NumPy array that represents the value of this instance,
257
+ - ``X.A`` is a NumPy array that represents the value of this instance,
249
258
and has a shape given by ``X.shape``.
250
259
251
260
.. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
252
- instance.
261
+ instance.
253
262
"""
254
263
255
264
if len (self .data ) == 1 :
@@ -270,9 +279,9 @@ def __getitem__(self, i):
270
279
:raises IndexError: if the element is out of bounds
271
280
272
281
Note that only a single index is supported, slices are not.
273
-
282
+
274
283
Example::
275
-
284
+
276
285
>>> x = X.Alloc(10)
277
286
>>> len(x)
278
287
10
@@ -296,14 +305,19 @@ def __getitem__(self, i):
296
305
else :
297
306
# stop is positive, use it directly
298
307
end = i .stop
299
- return self .__class__ ([self .data [k ] for k in range (i .start or 0 , end , i .step or 1 )])
308
+ return self .__class__ (
309
+ [self .data [k ] for k in range (i .start or 0 , end , i .step or 1 )]
310
+ )
300
311
else :
301
- return self .__class__ (self .data [i ], check = False )
302
-
312
+ ret = self .__class__ (self .data [i ], check = False )
313
+ # ret.__array_interface__ = self.data[i].__array_interface__
314
+ return ret
315
+ # return self.__class__(self.data[i], check=False)
316
+
303
317
def __setitem__ (self , i , value ):
304
318
"""
305
319
Assign a value to an instance (BasePoseList superclass method)
306
-
320
+
307
321
:param i: index of element to assign to
308
322
:type i: int
309
323
:param value: the value to insert
@@ -312,7 +326,7 @@ def __setitem__(self, i, value):
312
326
313
327
Assign the argument to an element of the object's internal list of values.
314
328
This supports the assignement operator, for example::
315
-
329
+
316
330
>>> x = X.Alloc(10)
317
331
>>> len(x)
318
332
10
@@ -324,7 +338,9 @@ def __setitem__(self, i, value):
324
338
if not type (self ) == type (value ):
325
339
raise ValueError ("can't insert different type of object" )
326
340
if len (value ) > 1 :
327
- raise ValueError ("can't insert a multivalued element - must have len() == 1" )
341
+ raise ValueError (
342
+ "can't insert a multivalued element - must have len() == 1"
343
+ )
328
344
self .data [i ] = value .A
329
345
330
346
# flag these binary operators as being not supported
@@ -343,7 +359,7 @@ def __ge__(self, other):
343
359
def append (self , item ):
344
360
"""
345
361
Append a value to an instance (BasePoseList superclass method)
346
-
362
+
347
363
:param x: the value to append
348
364
:type x: Quaternion or UnitQuaternion instance
349
365
:raises ValueError: incorrect type of appended object
@@ -361,18 +377,17 @@ def append(self, item):
361
377
362
378
where ``X`` is any of the SMTB classes.
363
379
"""
364
- #print('in append method')
380
+ # print('in append method')
365
381
if not type (self ) == type (item ):
366
382
raise ValueError ("can't append different type of object" )
367
383
if len (item ) > 1 :
368
384
raise ValueError ("can't append a multivalued instance - use extend" )
369
385
super ().append (item .A )
370
-
371
386
372
387
def extend (self , iterable ):
373
388
"""
374
389
Extend sequence of values in an instance (BasePoseList superclass method)
375
-
390
+
376
391
:param x: the value to extend
377
392
:type x: instance of same type
378
393
:raises ValueError: incorrect type of appended object
@@ -390,7 +405,7 @@ def extend(self, iterable):
390
405
391
406
where ``X`` is any of the SMTB classes.
392
407
"""
393
- #print('in extend method')
408
+ # print('in extend method')
394
409
if not type (self ) == type (iterable ):
395
410
raise ValueError ("can't append different type of object" )
396
411
super ().extend (iterable ._A )
@@ -427,9 +442,11 @@ def insert(self, i, item):
427
442
if not type (self ) == type (item ):
428
443
raise ValueError ("can't insert different type of object" )
429
444
if len (item ) > 1 :
430
- raise ValueError ("can't insert a multivalued instance - must have len() == 1" )
445
+ raise ValueError (
446
+ "can't insert a multivalued instance - must have len() == 1"
447
+ )
431
448
super ().insert (i , item ._A )
432
-
449
+
433
450
def pop (self , i = - 1 ):
434
451
"""
435
452
Pop value from an instance (BasePoseList superclass method)
@@ -442,7 +459,7 @@ def pop(self, i=-1):
442
459
443
460
Removes a value from the value list and returns it. The original
444
461
instance is modified.
445
-
462
+
446
463
Example::
447
464
448
465
>>> x = X.Alloc(10)
@@ -462,7 +479,7 @@ def pop(self, i=-1):
462
479
def binop (self , right , op , op2 = None , list1 = True ):
463
480
"""
464
481
Perform binary operation
465
-
482
+
466
483
:param left: left operand
467
484
:type left: BasePoseList subclass
468
485
:param right: right operand
@@ -523,7 +540,7 @@ def binop(self, right, op, op2=None, list1=True):
523
540
524
541
# class * class
525
542
if len (left ) == 1 :
526
- # singleton *
543
+ # singleton *
527
544
if argcheck .isscalar (right ):
528
545
if list1 :
529
546
return [op (left ._A , right )]
@@ -539,7 +556,7 @@ def binop(self, right, op, op2=None, list1=True):
539
556
# singleton * non-singleton
540
557
return [op (left .A , x ) for x in right .A ]
541
558
else :
542
- # non-singleton *
559
+ # non-singleton *
543
560
if argcheck .isscalar (right ):
544
561
return [op (x , right ) for x in left .A ]
545
562
elif len (right ) == 1 :
@@ -549,12 +566,12 @@ def binop(self, right, op, op2=None, list1=True):
549
566
# non-singleton * non-singleton
550
567
return [op (x , y ) for (x , y ) in zip (left .A , right .A )]
551
568
else :
552
- raise ValueError (' length of lists to == must be same length' )
569
+ raise ValueError (" length of lists to == must be same length" )
553
570
554
571
# if isinstance(right, left.__class__):
555
572
# # class * class
556
573
# if len(left) == 1:
557
- # # singleton *
574
+ # # singleton *
558
575
# if len(right) == 1:
559
576
# # singleton * singleton
560
577
# if list1:
@@ -565,7 +582,7 @@ def binop(self, right, op, op2=None, list1=True):
565
582
# # singleton * non-singleton
566
583
# return [op(left.A, x) for x in right.A]
567
584
# else:
568
- # # non-singleton *
585
+ # # non-singleton *
569
586
# if len(right) == 1:
570
587
# # non-singleton * singleton
571
588
# return [op(x, right.A) for x in left.A]
@@ -587,7 +604,7 @@ def binop(self, right, op, op2=None, list1=True):
587
604
def unop (self , op , matrix = False ):
588
605
"""
589
606
Perform unary operation
590
-
607
+
591
608
:param self: operand
592
609
:type self: BasePoseList subclass
593
610
:param op: unnary operation
@@ -598,7 +615,7 @@ def unop(self, op, matrix=False):
598
615
:rtype: list or NumPy array
599
616
600
617
The is a helper method for implementing unary operations where the
601
- operand has multiple value. This method computes the value of
618
+ operand has multiple value. This method computes the value of
602
619
the operation for all input values and returns the result as either
603
620
a list or as a matrix which vertically stacks the results.
604
621
@@ -613,7 +630,7 @@ def unop(self, op, matrix=False):
613
630
========= ==== ===================================
614
631
615
632
The result is:
616
-
633
+
617
634
- a list of values if ``matrix==False``, or
618
635
- a 2D NumPy stack of values if ``matrix==True``, it is assumed
619
636
that the value is a 1D array.
@@ -623,4 +640,3 @@ def unop(self, op, matrix=False):
623
640
return np .vstack ([op (x ) for x in self .data ])
624
641
else :
625
642
return [op (x ) for x in self .data ]
626
-
0 commit comments