much cleaner Adjoint jacobian

release/4.3a0
Gerry Chen 2021-10-26 03:18:04 -04:00
parent 31e5cbb81a
commit f0fc0d4457
3 changed files with 147 additions and 189 deletions

View File

@ -5090,29 +5090,22 @@ Derivative of Adjoint
\begin_layout Standard \begin_layout Standard
Consider Consider
\begin_inset Formula $f:SE(3)\rightarrow\mathbb{R}^{6}$ \begin_inset Formula $f:SE(3)\times\mathbb{R}^{6}\rightarrow\mathbb{R}^{6}$
\end_inset \end_inset
is defined as is defined as
\begin_inset Formula $f(T)=Ad_{T}y$ \begin_inset Formula $f(T,\xi_{b})=Ad_{T}\hat{\xi}_{b}$
\end_inset
for some constant
\begin_inset Formula $y=\begin{bmatrix}\omega_{y}\\
v_{y}
\end{bmatrix}$
\end_inset \end_inset
. .
Defining The derivative is notated (see
\begin_inset Formula $\xi=\begin{bmatrix}\omega\\ \begin_inset CommandInset ref
v LatexCommand ref
\end{bmatrix}$ reference "sec:Derivatives-of-Actions"
\end_inset plural "false"
caps "false"
noprefix "false"
for the derivative notation (w.r.t.
pose
\begin_inset Formula $T$
\end_inset \end_inset
): ):
@ -5121,68 +5114,17 @@ v
\begin_layout Standard \begin_layout Standard
\begin_inset Formula \begin_inset Formula
\[ \[
f'(T)=\frac{\partial Ad_{T}y}{\partial\xi}=\begin{bmatrix}\frac{\partial f}{\omega} & \frac{\partial f}{v}\end{bmatrix} Df_{(T,y)}(\xi,\delta y)=D_{1}f_{(T,y)}(\xi)+D_{2}f_{(T,y)}(\delta y)
\] \]
\end_inset \end_inset
Then we can compute First, computing
\begin_inset Formula $f'(T)$ \begin_inset Formula $D_{2}f_{(T,\xi_{b})}(\xi_{b})$
\end_inset \end_inset
by considering the rotation and translation separately. is easy, as its matrix is simply
To reduce confusion with \begin_inset Formula $Ad_{T}$
\begin_inset Formula $\omega_{y},v_{y}$
\end_inset
, we will use
\begin_inset Formula $R,t$
\end_inset
to denote the rotation and translation of
\begin_inset Formula $T\exp\xi$
\end_inset
.
\end_layout
\begin_layout Standard
\begin_inset Formula
\[
\frac{\partial}{\partial\omega}\begin{bmatrix}R & 0\\{}
[t]_{\times}R & R
\end{bmatrix}\begin{bmatrix}\omega_{y}\\
v_{y}
\end{bmatrix}=\frac{\partial}{\partial\omega}\begin{bmatrix}R\omega_{y}\\{}
[t]_{\times}R\omega_{y}+Rv_{y}
\end{bmatrix}=\begin{bmatrix}-R[\omega_{y}]_{\times}\\
-[t]_{\times}R[w_{y}]_{\times}-R[v_{y}]_{\times}
\end{bmatrix}
\]
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Formula
\[
\frac{\partial}{\partial t}\begin{bmatrix}R & 0\\{}
[t]_{\times}R & R
\end{bmatrix}\begin{bmatrix}\omega\\
v
\end{bmatrix}=\frac{\partial}{\partial t}\begin{bmatrix}R\omega_{y}\\{}
[t]_{\times}R\omega_{y}+Rv_{y}
\end{bmatrix}=\begin{bmatrix}0\\
-[R\omega_{y}]
\end{bmatrix}
\]
\end_inset
Applying chain rule for the translation,
\begin_inset Formula $\frac{\partial}{\partial v}=\frac{\partial}{\partial t}\frac{\partial t}{\partial v}$
\end_inset \end_inset
: :
@ -5191,76 +5133,139 @@ Applying chain rule for the translation,
\begin_layout Standard \begin_layout Standard
\begin_inset Formula \begin_inset Formula
\[ \[
\frac{\partial}{\partial v}\begin{bmatrix}R & 0\\{} f(T,\xi_{b}+\delta\xi_{b})=Ad_{T}(\widehat{\xi_{b}+\delta\xi_{b}})=Ad_{T}(\hat{\xi}_{b})+Ad_{T}(\delta\hat{\xi}_{b})
[t]_{\times}R & R
\end{bmatrix}\begin{bmatrix}\omega_{y}\\
v_{y}
\end{bmatrix}=\begin{bmatrix}0\\
-[R\omega_{y}]_{\times}
\end{bmatrix}R=\begin{bmatrix}0\\
-[R\omega_{y}]_{\times}R
\end{bmatrix}=\begin{bmatrix}0\\
-R[\omega_{y}]_{\times}
\end{bmatrix}
\] \]
\end_inset \end_inset
The simplification
\family roman
\series medium
\shape up
\size normal
\emph off
\bar no
\strikeout off
\xout off
\uuline off
\uwave off
\noun off
\color none
\begin_inset Formula $[R\omega_{y}]_{\times}R=R[\omega_{y}]_{\times}$
\end_inset
can be derived by considering the result for when
\begin_inset Formula $\omega_{y}$
\end_inset
is each of the 3 standard basis vectors
\begin_inset Formula $\hat{e}_{i}$
\end_inset
:
\begin_inset Formula $-[R\hat{e}_{i}]_{\times}R$
\end_inset
.
\end_layout
\begin_layout Standard
Now putting together the rotation and translation:
\end_layout \end_layout
\begin_layout Standard \begin_layout Standard
\begin_inset Formula \begin_inset Formula
\[ \[
f'(T)=\frac{\partial Ad_{T}y}{\partial\xi}=\begin{bmatrix}\frac{\partial f}{\omega} & \frac{\partial f}{v}\end{bmatrix}=\begin{bmatrix}-R[\omega_{y}]_{\times} & 0\\ D_{2}f_{(T,\xi_{b})}(\xi_{b})=Ad_{T}
-[t]_{\times}R[w_{y}]_{\times}-R[v_{y}]_{\times} & -R[\omega_{y}]_{\times}
\end{bmatrix}
\] \]
\end_inset \end_inset
To compute
\begin_inset Formula $D_{1}f_{(T,\xi_{b})}(\xi_{b})$
\end_inset
\end_layout , we'll first define
\begin_inset Formula $g(T,\xi)\triangleq T\exp\hat{\xi}$
\begin_layout Standard
We can apply a similar procedure to compute the derivative of
\begin_inset Formula $Ad_{T}^{T}y$
\end_inset \end_inset
. .
From Section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Derivatives-of-Actions"
plural "false"
caps "false"
noprefix "false"
\end_inset
,
\end_layout
\begin_layout Standard
\begin_inset Formula
\begin{align*}
D_{2}g_{(T,\xi)}(\xi) & =T\hat{\xi}\\
D_{2}g_{(T,\xi)}^{-1}(\xi) & =-\hat{\xi}T^{-1}
\end{align*}
\end_inset
Now we can use the definition of the Adjoint representation
\begin_inset Formula $Ad_{g}\hat{\xi}=g\hat{\xi}g^{-1}$
\end_inset
(aka conjugation by
\begin_inset Formula $g$
\end_inset
) then apply product rule and simplify:
\end_layout
\begin_layout Standard
\begin_inset Formula
\begin{align*}
D_{1}f_{(T,\xi_{b})}(\xi)=D_{1}\left(Ad_{T\exp(\hat{\xi})}\hat{\xi}_{b}\right)(\xi) & =D_{1}\left(g\hat{\xi}g^{-1}\right)(\xi)\\
& =\left(D_{2}g_{(T,\xi)}(\xi)\right)\hat{\xi}g^{-1}(T,0)+g(T,0)\hat{\xi}\left(D_{2}g_{(T,\xi)}^{-1}(\xi)\right)\\
& =T\hat{\xi}\hat{\xi}_{b}T^{-1}-T\hat{\xi}_{b}\hat{\xi}T^{-1}\\
& =T\left(\hat{\xi}\hat{\xi}_{b}-\hat{\xi}_{b}\hat{\xi}\right)T^{-1}\\
& =-Ad_{T}(ad_{\xi_{b}}\hat{\xi})\\
D_{1}F_{(T,\xi_{b})} & =-(Ad_{T})(ad_{\hat{\xi}_{b}})
\end{align*}
\end_inset
An alternative, perhaps more intuitive way of deriving this would be to
use the fact that the derivative at the origin
\begin_inset Formula $D_{1}Ad_{I}\hat{\xi}_{b}=ad_{\hat{\xi}_{b}}$
\end_inset
by definition of the adjoint
\begin_inset Formula $ad_{\xi}$
\end_inset
.
Then applying the property
\begin_inset Formula $Ad_{AB}=Ad_{A}Ad_{B}$
\end_inset
,
\end_layout
\begin_layout Standard
\begin_inset Formula
\[
D_{1}Ad_{T}\hat{\xi}_{b}(\xi)=D_{1}Ad_{T*I}\hat{\xi}_{b}(\xi)=Ad_{T}\left(D_{1}Ad_{I}\hat{\xi}_{b}(\xi)\right)=Ad_{T}\left(ad_{\hat{\xi}_{b}}(\xi)\right)
\]
\end_inset
It's difficult to apply a similar procedure to compute the derivative of
\begin_inset Formula $Ad_{T}^{T}\hat{\xi}_{b}^{*}$
\end_inset
(note the
\begin_inset Formula $^{*}$
\end_inset
denoting that we are now in the dual space) because
\begin_inset Formula $Ad_{T}^{T}$
\end_inset
cannot be naturally defined as a conjugation so we resort to crunching
through the algebra.
The details are omitted but the result is a form vaguely resembling (but
not quite) the
\begin_inset Formula $ad(Ad_{T}^{T}\hat{\xi}_{b}^{*})$
\end_inset
:
\end_layout
\begin_layout Standard
\begin_inset Formula
\begin{align*}
\begin{bmatrix}\omega_{T}\\
v_{T}
\end{bmatrix}^{*} & \triangleq Ad_{T}^{T}\hat{\xi}_{b}^{*}\\
D_{1}Ad_{T}^{T}\hat{\xi}_{b}^{*}(\xi) & =\begin{bmatrix}\hat{\omega}_{T} & \hat{v}_{T}\\
\hat{v}_{T} & 0
\end{bmatrix}
\end{align*}
\end_inset
\end_layout \end_layout
\begin_layout Subsection \begin_layout Subsection

Binary file not shown.

View File

@ -67,88 +67,41 @@ Matrix6 Pose3::AdjointMap() const {
// Calculate AdjointMap applied to xi_b, with Jacobians // Calculate AdjointMap applied to xi_b, with Jacobians
Vector6 Pose3::Adjoint(const Vector6& xi_b, OptionalJacobian<6, 6> H_pose, Vector6 Pose3::Adjoint(const Vector6& xi_b, OptionalJacobian<6, 6> H_pose,
OptionalJacobian<6, 6> H_xib) const { OptionalJacobian<6, 6> H_xib) const {
// Ad * xi = [ R 0 . [w const Matrix6 Ad = AdjointMap();
// [t]R R ] v]
// Declarations, aliases, and intermediate Jacobians easy to compute now
Vector6 result; // = AdjointMap() * xi
auto Rw = result.head<3>();
const auto &w = xi_b.head<3>(), &v = xi_b.tail<3>();
Matrix3 Rw_H_R, Rv_H_R, pRw_H_Rw;
const Matrix3 R = R_.matrix();
const Matrix3 &Rw_H_w = R;
const Matrix3 &Rv_H_v = R;
// Calculations
Rw = R_.rotate(w, H_pose ? &Rw_H_R : nullptr /*, Rw_H_w */);
const Vector3 Rv = R_.rotate(v, H_pose ? &Rv_H_R : nullptr /*, Rv_H_v */);
const Vector3 pRw = cross(t_, Rw, boost::none /* pRw_H_t */, pRw_H_Rw);
result.tail<3>() = pRw + Rv;
// Jacobians // Jacobians
if (H_pose) { // D1 Ad_T(xi_b) = D1 Ad_T Ad_I(xi_b) = Ad_T * D1 Ad_I(xi_b) = Ad_T * ad_xi_b
// pRw_H_posev = pRw_H_t * R = [Rw]x * R = R * [w]x = Rw_H_R // D2 Ad_T(xi_b) = Ad_T
// where [ ]x denotes the skew-symmetric operator. // See docs/math.pdf for more details.
// See docs/math.pdf for more details. // In D1 calculation, we could be more efficient by writing it out, but do not
const Matrix3 &pRw_H_posev = Rw_H_R; // for readability
*H_pose = (Matrix6() << Rw_H_R, /* */ Z_3x3, // if (H_pose) *H_pose = -Ad * adjointMap(xi_b);
/* */ pRw_H_Rw * Rw_H_R + Rv_H_R, pRw_H_posev) if (H_xib) *H_xib = Ad;
.finished();
}
if (H_xib) {
// This is just equal to AdjointMap() but we can reuse pRw_H_Rw = [t]x
*H_xib = (Matrix6() << Rw_H_w, /* */ Z_3x3,
/* */ pRw_H_Rw * Rw_H_w, Rv_H_v)
.finished();
}
// Return - we computed result manually but it should be = AdjointMap() * xi return Ad * xi_b;
return result;
} }
/* ************************************************************************* */ /* ************************************************************************* */
/// The dual version of Adjoint /// The dual version of Adjoint
Vector6 Pose3::AdjointTranspose(const Vector6& x, OptionalJacobian<6, 6> H_pose, Vector6 Pose3::AdjointTranspose(const Vector6& x, OptionalJacobian<6, 6> H_pose,
OptionalJacobian<6, 6> H_x) const { OptionalJacobian<6, 6> H_x) const {
// Ad^T * xi = [ R^T R^T.[-t] . [w const Matrix6 &AdT = AdjointMap().transpose();
// 0 R^T ] v] const Vector6 &AdTx = AdT * x;
// Declarations, aliases, and intermediate Jacobians easy to compute now
Vector6 result; // = AdjointMap().transpose() * x
const Vector3 &w = x.head<3>(), &v = x.tail<3>();
auto Rv = result.tail<3>();
Matrix3 Rw_H_R, Rv_H_R, Rtv_H_R;
const Matrix3 Rtranspose = R_.matrix().transpose();
const Matrix3 &Rw_H_w = Rtranspose;
const Matrix3 &Rv_H_v = Rtranspose;
const Matrix3 &Rtv_H_tv = Rtranspose;
const Matrix3 tv_H_v = skewSymmetric(t_);
// Calculations
const Vector3 Rw = R_.unrotate(w, H_pose ? &Rw_H_R : nullptr /*, Rw_H_w */);
Rv = R_.unrotate(v, H_pose ? &Rv_H_R : nullptr /*, Rv_H_v */);
const Vector3 tv = cross(t_, v, boost::none /* tv_H_t */, tv_H_v);
const Vector3 Rtv =
R_.unrotate(tv, H_pose ? &Rtv_H_R : nullptr /*, Rtv_H_tv */);
result.head<3>() = Rw - Rtv;
// Jacobians // Jacobians
// See docs/math.pdf for more details.
if (H_pose) { if (H_pose) {
// Rtv_H_posev = -Rtv_H_tv * tv_H_t * R = -R' * -[v]x * R = -[R'v]x = Rv_H_R const auto &w_T_hat = skewSymmetric(AdTx.head<3>()),
// where [ ]x denotes the skew-symmetric operator. &v_T_hat = skewSymmetric(AdTx.tail<3>());
// See docs/math.pdf for more details. *H_pose = (Matrix6() << w_T_hat, v_T_hat, //
const Matrix3 &Rtv_H_posev = Rv_H_R; /* */ v_T_hat, Z_3x3)
*H_pose = (Matrix6() << Rw_H_R - Rtv_H_R, Rtv_H_posev,
/* */ Rv_H_R, /* */ Z_3x3)
.finished(); .finished();
} }
if (H_x) { if (H_x) {
// This is just equal to AdjointMap().transpose() but we can reuse [t]x *H_x = AdT;
*H_x = (Matrix6() << Rw_H_w, -Rtv_H_tv * tv_H_v,
/* */ Z_3x3, Rv_H_v)
.finished();
} }
// Return - this should be equivalent to AdjointMap().transpose() * xi return AdTx;
return result;
} }
/* ************************************************************************* */ /* ************************************************************************* */