A gtsam.Rot2
represents rotation in 2D space. It models a 2D rotation in the Special Orthogonal Group .
%pip install --quiet gtsam-develop
from gtsam import Rot2, Point2
import numpy as np
Initialization and properties¶
A Rot2
can be initialized with no arguments, which yields the identity rotation, or it can be constructed from an angle in radians, degrees, cos-sin form, or the bearing or arctangent of a 2D point. Rot2
uses radians to communicate angle by default.
# The identity rotation has theta = 0.
identity = Rot2()
print("Identities:")
print(identity.theta())
print(Rot2.Identity().theta())
# The constructor uses radians, so it is identical to Rot2.fromAngle(r).
rads = Rot2(np.pi / 2)
also_rads = Rot2.fromAngle(np.pi / 2)
print("Radians:")
print(rads.theta())
print(also_rads.theta())
# Rot2.fromDegrees(d) constructs from degrees.
degs = Rot2.fromDegrees(90)
print("Degrees:")
print(degs.theta())
# Rot2 can also be constructed using cosine and sine values, if you have them lying around.
c = np.cos(np.pi / 6)
s = np.sin(np.pi / 6)
cs = Rot2.fromCosSin(c, s)
print("Cos-Sin:")
print(cs.theta())
# Construct with bearing to point from theta = 0.
p = Point2(2, 2)
bear = Rot2.relativeBearing(p)
print("Bearing:")
print(bear.theta())
# Or with atan2(y, x), which accomplishes the same thing.
atan = Rot2.atan2(p[1], p[0])
print(atan.theta())
Identities:
0.0
0.0
Radians:
1.5707963267948966
1.5707963267948966
Degrees:
1.5707963267948966
Cos-Sin:
0.5235987755982988
Bearing:
0.7853981633974483
0.7853981633974483
The following properties are available from the standard interface:
theta()
(in radians)degrees()
c()
(the cosine value, precalculated)s()
(the sine value, precalculated)matrix()
(the 2x2 rotation matrix: )
example_rot = Rot2(3 * np.pi / 4)
# The default print statement includes 'theta: ' and a newline at the end.
print(example_rot)
print(f"Radians: {example_rot.theta()}")
print(f"Degrees: {example_rot.degrees()}")
print(f"Cosine: {example_rot.c()}")
print(f"Sine: {example_rot.s()}")
print(f"Matrix:\n{example_rot.matrix()}")
theta: 2.35619
Radians: 2.356194490192345
Degrees: 135.0
Cosine: -0.7071067811865475
Sine: 0.7071067811865476
Matrix:
[[-0.70710678 -0.70710678]
[ 0.70710678 -0.70710678]]
Basic operations¶
For basic use, a Rot2
can rotate and unrotate a point.
rot = Rot2.fromDegrees(45)
p = Point2(-2, 2)
# Rotate the point at (-2, 2) 45 degrees to the -x axis.
rotated = rot.rotate(p)
print(f"Rotated: {rotated}")
# Perform the inverse rotation with unrotate()
print(f"Unrotated: {rot.unrotate(rotated)}")
# Of course, unrotating a point you didn't rotate just rotates it backwards.
print(f"Unrotated again: {rot.unrotate(p)}")
Rotated: [-2.82842712e+00 2.22044605e-16]
Unrotated: [-2. 2.]
Unrotated again: [-2.22044605e-16 2.82842712e+00]
Also, the equals()
function allows for comparison of two Rot2
objects with a tolerance.
eq_rads = Rot2(np.pi / 4)
eq_degs = Rot2.fromDegrees(45)
print(eq_rads.equals(eq_degs, 1e-8))
# Direct comparison does not work for Rot2.
print(eq_rads == eq_degs)
True
False
Lie group ¶
Group operations¶
Rot2
implements the group operations inverse
, compose
, between
and identity
. For more information on groups and their use here, see GTSAM concepts.
a = Rot2(np.pi / 6)
b = Rot2(np.pi / 3)
# The inverse of a Rot2 is just the negative of its angle.
print("Inverse:")
print(a.inverse())
# The composition of two Rot2 objects is their angles added together.
# The operator for compose is *, but make no mistake, this does not multiply the angles.
print("Compose:")
print(a * b)
print(a.compose(b))
# Between gives the difference between the two angles.
print("Between:")
print(a.between(b))
# The identity is theta = 0, as above.
print("Identity:")
print(Rot2.Identity())
Inverse:
theta: -0.523599
Compose:
theta: 1.5708
theta: 1.5708
Between:
theta: 0.523599
Identity:
theta: 0
Lie group operations¶
Rot2
implements the Lie group operations for exponential mapping and log mapping. For more information on Lie groups and their use here, see GTSAM concepts.
r = Rot2(np.pi / 2)
w = Rot2(np.pi / 4)
v = [np.pi / 2]
# The exponential map transforms a 1-dimensional vector representing an angle
# into its Rot2 equivalent.
print(Rot2.Expmap(v))
# The retract function takes the exponential map of the supplied 1D vector and
# composes it with the calling Rot2.
print(r.retract(v))
# The static log map transforms a Rot2 into its 1D vector equivalent.
print(Rot2.Logmap(r))
# The member log map transforms a Rot2 into its 1D vector equivalent relative to
# the Rot2 calling the function.
print(r.logmap(w))
# logmap is the same as calculating the coordinate of the second Rot2 in the
# local frame of the first, which localCoordinates (inherited from LieGroup) does.
print(r.localCoordinates(w))
theta: 1.5708
theta: 3.14159
[1.57079633]
[-0.78539816]
[-0.78539816]