8000 new method to specify rotation in terms of directions of new frame wr… · kh11kim/spatialmath-python@53fedf9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 53fedf9

Browse files
committed
new method to specify rotation in terms of directions of new frame wrt old
1 parent d56878e commit 53fedf9

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

spatialmath/pose3d.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,69 @@ def OA(cls, o, a):
536536
"""
537537
return cls(base.oa2r(o, a), check=False)
538538

539+
@classmethod
540+
def TwoVectors(cls, x=None, y=None, z=None):
541+
"""
542+
Construct a new SO(3) from any two vectors
543+
544+
:param x: new x-axis, defaults to None
545+
:type x: str, array_like(3), optional
546+
:param y: new y-axis, defaults to None
547+
:type y: str, array_like(3), optional
548+
:param z: new z-axis, defaults to None
549+
:type z: str, array_like(3), optional
550+
551+
Create a rotation by defining the direction of two of the new
552+
axes in terms of the old axes. Axes are denoted by strings ``"x"``,
553+
``"y"``, ``"z"``, ``"-x"``, ``"-y"``, ``"-z"``.
554+
555+
The directions can also be specified by 3-element vectors, but these
556+
must be orthogonal.
557+
558+
To create a rotation where the new frame has its x-axis in -z-direction
559+
of the previous frame, and its z-axis in the x-direction of the previous
560+
frame is::
561+
562+
>>> SO3.TwoVectors(x='-z', z='x')
563+
"""
564+
def vval(v):
565+
if isinstance(v, str):
566+
sign = 1
567+
if v[0] == '-':
568+
sign = -1
569+
v = v[1:] # skip sign char
570+
elif v[0] == '+':
571+
v = v[1:] # skip sign char
572+
if v[0] == 'x':
573+
v = [sign, 0, 0]
574+
elif v[0] == 'y':
575+
v = [0, sign, 0]
576+
elif v[0] == 'z':
577+
v = [0, 0, sign]
578+
return np.r_[v]
579+
else:
580+
return base.unitvec(base.getvector(v, 3))
581+
582+
if x is not None and y is not None and z is None:
583+
# z = x x y
584+
x = vval(x)
585+
y = vval(y)
586+
z = np.cross(x, y)
587+
588+
elif x is None and y is not None and z is not None:
589+
# x = y x z
590+
y = vval(y)
591+
z = vval(z)
592+
x = np.cross(y, z)
593+
594+
elif x is not None and y is None and z is not None:
595+
# y = z x x
596+
z = vval(z)
597+
x = vval(x)
598+
y = np.cross(z, x)
599+
600+
return cls(np.c_[x, y, z], check=False)
601+
539602
@classmethod
540603
def AngleAxis(cls, theta, v, *, unit='rad'):
541604
r"""

0 commit comments

Comments
 (0)
0