1 from . import np, DifferentiableManifold, Group, contract
2 from .. import logm, expm
3 from contracts import new_contract
7 '''
8 This is the base class for matrix Lie groups.
9
10 Subclasses should provide a MatrixLieAlgebra
11 object. Given the Lie algebra, we can compute everything.
12 However, subclasses can choose to overload
13 some functions if they know a more numerically stable implementation.
14
15 '''
16
17 - def __init__(self, n, dimension, algebra):
18 '''
19 Initializes the Lie group.
20
21 :param n: dimension of the matrix group.
22 :param algebra: instance of :py:class:MatrixLieAlgebra
23 '''
24 DifferentiableManifold.__init__(self, dimension=dimension)
25 self.n = n
26 self.algebra = algebra
27 assert self.algebra.n == self.n
28
29 from . import MatrixLieGroupTangent
30 self._tangent_bundle_algebra_rep = MatrixLieGroupTangent(self)
31
33 return self._tangent_bundle_algebra_rep
34
36 ''' Returns the interface to the corresponding Lie algebra. '''
37 return self.algebra
38
41
42 @contract(g='belongs', h='belongs')
45
46 @contract(g='belongs', returns='belongs')
48 return np.linalg.inv(g)
49
50 @new_contract
53
54 @contract(bv='tuple(belongs, *)')
56 '''
57 Projects the vector *x* to the tangent space at point *base*.
58
59 In the case of Lie Groups, we do this by translating the
60 vector to the origin, projecting it to the Lie Algebra,
61 and then translating it back.
62 '''
63
64 base, vel = bv
65 y = np.dot(self.inverse(base), vel)
66
67 ty = self.algebra.project(y)
68
69 tty = np.dot(base, ty)
70 return base, tty
71
72 @contract(a='belongs', b='belongs')
74 '''
75 Computes the distance between two points.
76
77 In the case of Lie groups, this is done by
78 translating everything to the origin, computing the
79 logmap, and using the norm defined in the Lie Algebra object.
80
81 '''
82 x = self.multiply(a, self.inverse(b))
83 xt = self.algebra_from_group(x)
84 return self.algebra.norm(xt)
85
86 @contract(base='belongs', target='belongs', returns='belongs_ts',)
87 - def logmap(self, base, target):
88 '''
89 Returns the direction from base to target.
90
91 In the case of Lie groups, this is implemented
92 by using the usual matrix logarithm at the origin.
93
94 Here the :py:func:`MatrixLieAlgebra.project` function
95 is used to mitigate numerical errors.
96 '''
97 diff = self.multiply(self.inverse(base), target)
98 X = self.algebra_from_group(diff)
99 bX = np.dot(base, X)
100 return (base, bX)
101
102 @contract(bv='belongs_ts', returns='belongs')
104 '''
105 This is the inverse of :py:func:`logmap_`.
106
107 In the case of Lie groups, this is implemented using
108 the usual matrix exponential.
109
110 Here the :py:func:`MatrixLieAlgebra.project` function
111 is used to mitigate numerical errors.
112 '''
113 base, vel = bv
114 tv = np.dot(self.inverse(base), vel)
115 tv = self.algebra.project(tv)
116 x = self.group_from_algebra(tv)
117 return np.dot(base, x)
118
119 @contract(g='belongs', returns='belongs_algebra')
121 '''
122 Converts an element of the group to the algebra.
123 Uses generic matrix logarithm plus projection.
124 '''
125 X = np.array(logm(g).real)
126
127 X = self.algebra.project(X)
128 return X
129
130 @contract(a='belongs_algebra', returns='belongs')
132 '''
133 Converts an element of the algebra to the group.
134
135 Uses generic matrix exponential.
136 '''
137 return expm(a)
138
139
140 @contract(a='belongs', b='belongs', returns='belongs_ts')
142 '''
143 Find the velocity in local frame to go from *a* to *b* in
144 *delta* time.
145 '''
146 x = self.multiply(self.inverse(a), b)
147 xt = self.algebra_from_group(x)
148
149
150 return self.identity(), xt / delta
151