@@ -805,11 +805,11 @@ def oa2r(o, a=None):
805
805
806
806
.. note::
807
807
808
- - The A vector is the only guaranteed to have the same direction in the
808
+ - The A vector is the only guaranteed to have the same direction in the
809
809
resulting rotation matrix
810
810
- O and A do not have to be unit-length, they are normalized
811
811
- O and A do not have to be orthogonal, so long as they are not parallel
812
- - The vectors O and A are parallel to the Y- and Z-axes of the
812
+ - The vectors O and A are parallel to the Y- and Z-axes of the
813
813
equivalent coordinate frame.
814
814
815
815
:seealso: :func:`~oa2tr`
@@ -861,7 +861,7 @@ def oa2tr(o, a=None):
861
861
- O and A do not have to be unit-length, they are normalized
862
862
- O and A do not have to be orthogonal, so long as they are not parallel
863
863
- The translational part is zero.
864
- - The vectors O and A are parallel to the Y- and Z-axes of the
864
+ - The vectors O and A are parallel to the Y- and Z-axes of the
865
865
equivalent coordinate frame.
866
866
867
867
:seealso: :func:`~oa2r`
@@ -1856,11 +1856,12 @@ def exp2jac(v):
1856
1856
# (2.106)
1857
1857
E = (
1858
1858
np .eye (3 )
1859
- + sk * (1 - np .cos (theta )) / theta ** 2
1860
- + sk @ sk * (theta - np .sin (theta )) / theta ** 3
1859
+ + sk * (1 - np .cos (theta )) / theta ** 2
1860
+ + sk @ sk * (theta - np .sin (theta )) / theta ** 3
1861
1861
)
1862
1862
return E
1863
1863
1864
+
1864
1865
def r2x (R , representation = "rpy/xyz" ):
1865
1866
r"""
1866
1867
Convert SO(3) matrix to angular representation
@@ -1893,14 +1894,15 @@ def r2x(R, representation="rpy/xyz"):
1893
1894
r = tr2eul (R )
1894
1895
elif representation .startswith ("rpy/" ):
1895
1896
r = tr2rpy (R , order = representation [4 :])
1896
- elif representation in (' arm' , ' vehicle' , ' camera' ):
1897
+ elif representation in (" arm" , " vehicle" , " camera" ):
1897
1898
r = tr2rpy (R , order = representation )
1898
1899
elif representation == "exp" :
1899
1900
r = trlog (R , twist = True )
1900
1901
else :
1901
1902
raise ValueError (f"unknown representation: { representation } " )
1902
1903
return r
1903
1904
1905
+
1904
1906
def x2r (r , representation = "rpy/xyz" ):
1905
1907
r"""
1906
1908
Convert angular representation to SO(3) matrix
@@ -1933,14 +1935,15 @@ def x2r(r, representation="rpy/xyz"):
1933
1935
R = eul2r (r )
1934
1936
elif representation .startswith ("rpy/" ):
1935
1937
R = rpy2r (r , order = representation [4 :])
1936
- elif representation in (' arm' , ' vehicle' , ' camera' ):
1938
+ elif representation in (" arm" , " vehicle" , " camera" ):
1937
1939
R = rpy2r (r , order = representation )
1938
1940
elif representation == "exp" :
1939
1941
R = trexp (r )
1940
1942
else :
1941
1943
raise ValueError (f"unknown representation: { representation } " )
1942
1944
return R
1943
1945
1946
+
1944
1947
def tr2x (T , representation = "rpy/xyz" ):
1945
1948
r"""
1946
1949
Convert SE(3) to an analytic representation
@@ -1975,9 +1978,10 @@ def tr2x(T, representation="rpy/xyz"):
1975
1978
r = r2x (R , representation = representation )
1976
1979
return np .r_ [t , r ]
1977
1980
1981
+
1978
1982
def x2tr (x , representation = "rpy/xyz" ):
1979
1983
r"""
1980
- Convert analytic representation to SE(3)
1984
+ Convert analytic representation to SE(3)
1981
1985
1982
1986
:param x: analytic vector representation
1983
1987
:type x: array_like(6)
@@ -2014,19 +2018,22 @@ def rot2jac(R, representation="rpy/xyz"):
2014
2018
"""
2015
2019
DEPRECATED, use :func:`rotvelxform` instead
2016
2020
"""
2017
- raise DeprecationWarning ('use rotvelxform instead' )
2021
+ raise DeprecationWarning ("use rotvelxform instead" )
2022
+
2018
2023
2019
2024
def angvelxform (𝚪 , inverse = False , full = True , representation = "rpy/xyz" ):
2020
2025
"""
2021
2026
DEPRECATED, use :func:`rotvelxform` instead
2022
2027
"""
2023
- raise DeprecationWarning ('use rotvelxform instead' )
2028
+ raise DeprecationWarning ("use rotvelxform instead" )
2029
+
2024
2030
2025
2031
def angvelxform_dot (𝚪 , 𝚪d , full = True , representation = "rpy/xyz" ):
2026
2032
"""
2027
2033
DEPRECATED, use :func:`rotvelxform` instead
2028
2034
"""
2029
- raise DeprecationWarning ('use rotvelxform_inv_dot instead' )
2035
+ raise DeprecationWarning ("use rotvelxform_inv_dot instead" )
2036
+
2030
2037
2031
2038
def rotvelxform (𝚪 , inverse = False , full = False , representation = "rpy/xyz" ):
2032
2039
r"""
@@ -2069,7 +2076,7 @@ def rotvelxform(𝚪, inverse=False, full=False, representation="rpy/xyz"):
2069
2076
============================ ========================================
2070
2077
2071
2078
If ``inverse==True`` return :math:`\mat{A}^{-1}` computed using
2072
- a closed-form solution rather than matrix inverse.
2079
+ a closed-form solution rather than matrix inverse.
2073
2080
2074
2081
If ``full=True`` a block diagonal 6x6 matrix is returned which transforms analytic
2075
2082
velocity to spatial velocity.
@@ -2078,9 +2085,9 @@ def rotvelxform(𝚪, inverse=False, full=False, representation="rpy/xyz"):
2078
2085
with ``full=False``.
2079
2086
2080
2087
The analytical Jacobian is
2081
-
2088
+
2082
2089
.. math::
2083
-
2090
+
2084
2091
\mat{J}_a(q) = \mat{A}^{-1}(\Gamma)\, \mat{J}(q)
2085
2092
2086
2093
where :math:`\mat{A}` is computed with ``inverse==True`` and ``full=True``.
@@ -2099,7 +2106,7 @@ def rotvelxform(𝚪, inverse=False, full=False, representation="rpy/xyz"):
2099
2106
if smb .isrot (𝚪 ):
2100
2107
# passed a rotation matrix
2101
2108
# convert to the representation
2102
- gamma = r2x (𝚪 , representation = representation )
2109
+ 𝚪 = r2x (𝚪 , representation = representation )
2103
2110
2104
2111
if sym .issymbol (𝚪 ):
2105
2112
C = sym .cos
@@ -2207,19 +2214,16 @@ def rotvelxform(𝚪, inverse=False, full=False, representation="rpy/xyz"):
2207
2214
# (2.106)
2208
2215
A = (
2209
2216
np .eye (3 )
2210
- + sk * (1 - C (theta )) / theta ** 2
2211
- + sk @ sk * (theta - S (theta )) / theta ** 3
2217
+ + sk * (1 - C (theta )) / theta ** 2
2218
+ + sk @ sk * (theta - S (theta )) / theta ** 3
2212
2219
)
2213
2220
else :
2214
2221
# angular velocity -> analytical rates
2215
2222
# (2.107)
2216
2223
A = (
2217
2224
np .eye (3 )
2218
2225
- sk / 2
2219
- + sk
2220
- @ sk
2221
- / theta ** 2
2222
- * (1 - (theta / 2 ) * (S (theta ) / (1 - C (theta ))))
2226
+ + sk @ sk / theta ** 2 * (1 - (theta / 2 ) * (S (theta ) / (1 - C (theta ))))
2223
2227
)
2224
2228
2225
2229
if full :
@@ -2249,9 +2253,9 @@ def rotvelxform_inv_dot(𝚪, 𝚪d, full=False, representation="rpy/xyz"):
2249
2253
2250
2254
\dvec{x} = \mat{A}^{-1}(\Gamma) \vec{\nu}
2251
2255
2252
- where :math:`\dvec{x} \in \mathbb{R}^6` is analytic velocity :math:`(\vec{v}, \dvec{\Gamma})`,
2256
+ where :math:`\dvec{x} \in \mathbb{R}^6` is analytic velocity :math:`(\vec{v}, \dvec{\Gamma})`,
2253
2257
:math:`\vec{\nu} \in \mathbb{R}^6` is spatial velocity :math:`(\vec{v}, \vec{\omega})`, and
2254
- :math:`\vec{\Gamma} \in \mathbb{R}^3` is a minimal rotational
2258
+ :math:`\vec{\Gamma} \in \mathbb{R}^3` is a minimal rotational
2255
2259
representation.
2256
2260
2257
2261
The relationship between spatial and analytic acceleration is
@@ -2261,8 +2265,8 @@ def rotvelxform_inv_dot(𝚪, 𝚪d, full=False, representation="rpy/xyz"):
2261
2265
\ddvec{x} = \dmat{A}^{-1}(\Gamma, \dot{\Gamma) \vec{\nu} + \mat{A}^{-1}(\Gamma) \dvec{\nu}
2262
2266
2263
2267
and :math:`\dmat{A}^{-1}(\Gamma, \dot{\Gamma)` is computed by this function.
2264
-
2265
-
2268
+
2269
+
2266
2270
============================ ========================================
2267
2271
``representation`` Rotational representation
2268
2272
============================ ========================================
@@ -2303,11 +2307,10 @@ def rotvelxform_inv_dot(𝚪, 𝚪d, full=False, representation="rpy/xyz"):
2303
2307
- (
2304
2308
beta_dot * math .sin (beta ) * S (gamma ) / C (beta )
2305
2309
+ gamma_dot * C (gamma )
2306
- ) / C (beta ),
2307
- (
2308
- beta_dot * S (beta ) * C (gamma ) / C (beta )
2309
- - gamma_dot * S (gamma )
2310
- ) / C (beta ),
2310
+ )
2311
+ / C (beta ),
2312
+ (beta_dot * S (beta ) * C (gamma ) / C (beta ) - gamma_dot * S (gamma ))
2313
+ / C (beta ),
2311
2314
],
2312
2315
[0 , - gamma_dot * S (gamma ), gamma_dot * C (gamma )],
2313
2316
[
@@ -2328,14 +2331,10 @@ def rotvelxform_inv_dot(𝚪, 𝚪d, full=False, representation="rpy/xyz"):
2328
2331
Ainv_dot = np .array (
2329
2332
[
2330
2333
[
2331
- (
2332
- beta_dot * S (beta ) * C (gamma ) / C (beta )
2333
- - gamma_dot * S (gamma )
2334
- ) / C (beta ),
2335
- (
2336
- beta_dot * S (beta ) * S (gamma ) / C (beta )
2337
- + gamma_dot * C (gamma )
2338
- ) / C (beta ),
2334
+ (beta_dot * S (beta ) * C (gamma ) / C (beta ) - gamma_dot * S (gamma ))
2335
+ / C (beta ),
2336
+ (beta_dot * S (beta ) * S (gamma ) / C (beta ) + gamma_dot * C (gamma ))
2337
+ / C (beta ),
2339
2338
0 ,
2340
2339
],
2341
2340
[- gamma_dot * C (gamma ), - gamma_dot * S (gamma ), 0 ],
@@ -2357,26 +2356,20 @@ def rotvelxform_inv_dot(𝚪, 𝚪d, full=False, representation="rpy/xyz"):
2357
2356
Ainv_dot = np .array (
2358
2357
[
2359
2358
[
2360
- (beta_dot * S (beta ) * S (gamma ) / C (beta )
2361
- + gamma_dot * C ( gamma )) / C (beta ),
2359
+ (beta_dot * S (beta ) * S (gamma ) / C (beta ) + gamma_dot * C ( gamma ))
2360
+ / C (beta ),
2362
2361
0 ,
2363
- (beta_dot * S (beta ) * C (gamma ) / C (beta )
2364
- - gamma_dot * S ( gamma )) / C (beta )
2362
+ (beta_dot * S (beta ) * C (gamma ) / C (beta ) - gamma_dot * S ( gamma ))
2363
+ / C (beta ),
2365
2364
],
2365
+ [- gamma_dot * S (gamma ), 0 , - gamma_dot * C (gamma )],
2366
2366
[
2367
- - gamma_dot * S (gamma ),
2367
+ beta_dot * S (gamma ) / C ( beta ) ** 2 + gamma_dot * C ( gamma ) * T ( beta ),
2368
2368
0 ,
2369
- - gamma_dot * C (gamma )
2369
+ beta_dot * C ( gamma ) / C ( beta ) ** 2 - gamma_dot * S (gamma ) * T ( beta ),
2370
2370
],
2371
- [
2372
- beta_dot * S (gamma ) / C (beta )** 2
2373
- + gamma_dot * C (gamma ) * T (beta ),
2374
- 0 ,
2375
- beta_dot * C (gamma ) / C (beta )** 2
2376
- - gamma_dot * S (gamma ) * T (beta )
2377
- ]
2378
2371
]
2379
- )
2372
+ )
2380
2373
2381
2374
elif representation == "eul" :
2382
2375
# autogenerated by symbolic/angvelxform.ipynb
@@ -2394,15 +2387,9 @@ def rotvelxform_inv_dot(𝚪, 𝚪d, full=False, representation="rpy/xyz"):
2394
2387
],
2395
2388
[- phi_dot * C (phi ), - phi_dot * S (phi ), 0 ],
2396
2389
[
2397
- - (
2398
- phi_dot * S (phi )
2399
- + theta_dot * C (phi ) * C (theta ) / S (theta )
2400
- )
2390
+ - (phi_dot * S (phi ) + theta_dot * C (phi ) * C (theta ) / S (theta ))
2401
2391
/ S (theta ),
2402
- (
2403
- phi_dot * C (phi )
2404
- - theta_dot * S (phi ) * C (theta ) / S (theta )
2405
- )
2392
+ (phi_dot * C (phi ) - theta_dot * S (phi ) * C (theta ) / S (theta ))
2406
2393
/ S (theta ),
2407
2394
0 ,
2408
2395
],
@@ -2424,15 +2411,10 @@ def rotvelxform_inv_dot(𝚪, 𝚪d, full=False, representation="rpy/xyz"):
2424
2411
# results are close but different to numerical cross check
2425
2412
# something wrong in the derivation
2426
2413
Theta_dot = (
2427
- (
2428
- - theta * C (theta )
2429
- - S (theta ) +
2430
- theta * S (theta )** 2 / (1 - C (theta ))
2431
- ) * theta_dot / 2 / (1 - C (theta )) / theta ** 2
2432
- - (
2433
- 2 - theta * S (theta ) / (1 - C (theta ))
2434
- ) * theta_dot / theta ** 3
2435
- )
2414
+ - theta * C (theta ) - S (theta ) + theta * S (theta ) ** 2 / (1 - C (theta ))
2415
+ ) * theta_dot / 2 / (1 - C (theta )) / theta ** 2 - (
2416
+ 2 - theta * S (theta ) / (1 - C (theta ))
2417
+ ) * theta_dot / theta ** 3
2436
2418
2437
2419
Ainv_dot = - 0.5 * skd + 2.0 * sk @ skd * Theta + sk @ sk * Theta_dot
2438
2420
else :
@@ -2583,11 +2565,7 @@ def trprint(
2583
2565
# print the angular part in various representations
2584
2566
2585
2567
# define some aliases for rpy conventions for arms, vehicles and cameras
2586
- aliases = {
2587
- 'arm' : 'rpy/xyz' ,
2588
- 'vehicle' : 'rpy/zyx' ,
2589
- 'camera' : 'rpy/yxz'
2590
- }
2568
+ aliases = {"arm" : "rpy/xyz" , "vehicle" : "rpy/zyx" , "camera" : "rpy/yxz" }
2591
2569
if orient in aliases :
2592
2570
orient = aliases [orient ]
2593
2571
@@ -2632,12 +2610,8 @@ def _vec2s(fmt, v):
2632
2610
return ", " .join ([fmt .format (x ) for x in v ])
2633
2611
2634
2612
2635
-
2636
-
2637
-
2638
2613
def trplot (
2639
2614
T ,
2640
-
2641
2615
color = "blue" ,
2642
2616
frame = None ,
2643
2617
axislabel = True ,
@@ -2657,7 +2631,7 @@ def trplot(
2657
2631
dims = None ,
2658
2632
d2 = 1.15 ,
2659
2633
flo = (- 0.05 , - 0.05 , - 0.05 ),
2660
- ** kwargs
2634
+ ** kwargs ,
2661
2635
):
2662
2636
"""
2663
2637
Plot a 3D coordinate frame
@@ -2806,7 +2780,7 @@ def trplot(
2806
2780
2807
2781
# unpack the anaglyph parameters
2808
2782
if anaglyph is True :
2809
- colors = 'rc'
2783
+ colors = "rc"
2810
2784
shift = 0.1
2811
2785
elif isinstance (anaglyph , tuple ):
2812
2786
colors = anaglyph [0 ]
@@ -2867,7 +2841,7 @@ def trplot(
2867
2841
flo = flo ,
2868
2842
anaglyph = anaglyph ,
2869
2843
axislabel = axislabel ,
2870
- ** kwargs
2844
+ ** kwargs ,
2871
2845
)
2872
2846
return
2873
2847
@@ -3023,6 +2997,7 @@ def trplot(
3023
2997
if block :
3024
2998
# calling this at all, causes FuncAnimation to fail so when invoked from tranimate skip this bit
3025
2999
import matplotlib .pyplot as plt
3000
+
3026
3001
# TODO move blocking into graphics
3027
3002
plt .show (block = block )
3028
3003
return ax
@@ -3079,14 +3054,14 @@ def tranimate(T, **kwargs):
3079
3054
3080
3055
anim = smb .animate .Animate (** kwargs )
3081
3056
try :
3082
- del kwargs [' dims' ]
3057
+ del kwargs [" dims" ]
3083
3058
except KeyError :
3084
3059
pass
3085
-
3060
+
3086
3061
anim .trplot (T , ** kwargs )
3087
3062
anim .run (** kwargs )
3088
3063
3089
- #plt.show(block=block)
3064
+ # plt.show(block=block)
3090
3065
3091
3066
3092
3067
if __name__ == "__main__" : # pragma: no cover
0 commit comments