From f0fc0d445718df993d904e4f1eaba5c8d567e91c Mon Sep 17 00:00:00 2001 From: Gerry Chen Date: Tue, 26 Oct 2021 03:18:04 -0400 Subject: [PATCH] much cleaner Adjoint jacobian --- doc/math.lyx | 253 ++++++++++++++++++++------------------- doc/math.pdf | Bin 264527 -> 272118 bytes gtsam/geometry/Pose3.cpp | 83 +++---------- 3 files changed, 147 insertions(+), 189 deletions(-) diff --git a/doc/math.lyx b/doc/math.lyx index f14ebc66f..6d7a5e318 100644 --- a/doc/math.lyx +++ b/doc/math.lyx @@ -5090,29 +5090,22 @@ Derivative of Adjoint \begin_layout Standard 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 is defined as -\begin_inset Formula $f(T)=Ad_{T}y$ -\end_inset - - for some constant -\begin_inset Formula $y=\begin{bmatrix}\omega_{y}\\ -v_{y} -\end{bmatrix}$ +\begin_inset Formula $f(T,\xi_{b})=Ad_{T}\hat{\xi}_{b}$ \end_inset . - Defining -\begin_inset Formula $\xi=\begin{bmatrix}\omega\\ -v -\end{bmatrix}$ -\end_inset + The derivative is notated (see +\begin_inset CommandInset ref +LatexCommand ref +reference "sec:Derivatives-of-Actions" +plural "false" +caps "false" +noprefix "false" - for the derivative notation (w.r.t. - pose -\begin_inset Formula $T$ \end_inset ): @@ -5121,68 +5114,17 @@ v \begin_layout Standard \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 -Then we can compute -\begin_inset Formula $f'(T)$ +First, computing +\begin_inset Formula $D_{2}f_{(T,\xi_{b})}(\xi_{b})$ \end_inset - by considering the rotation and translation separately. - To reduce confusion with -\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}$ + is easy, as its matrix is simply +\begin_inset Formula $Ad_{T}$ \end_inset : @@ -5191,76 +5133,139 @@ Applying chain rule for the translation, \begin_layout Standard \begin_inset Formula \[ -\frac{\partial}{\partial v}\begin{bmatrix}R & 0\\{} -[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} +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}) \] \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 \begin_layout Standard \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\\ --[t]_{\times}R[w_{y}]_{\times}-R[v_{y}]_{\times} & -R[\omega_{y}]_{\times} -\end{bmatrix} +D_{2}f_{(T,\xi_{b})}(\xi_{b})=Ad_{T} \] \end_inset +To compute +\begin_inset Formula $D_{1}f_{(T,\xi_{b})}(\xi_{b})$ +\end_inset -\end_layout - -\begin_layout Standard -We can apply a similar procedure to compute the derivative of -\begin_inset Formula $Ad_{T}^{T}y$ +, we'll first define +\begin_inset Formula $g(T,\xi)\triangleq T\exp\hat{\xi}$ \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 \begin_layout Subsection diff --git a/doc/math.pdf b/doc/math.pdf index 06dec078d5fb590fe6dfe74dcdc13aace1a22328..71f9dadc65bea48ee1dbd925f2cee058bb2bd832 100644 GIT binary patch delta 26953 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 A?*IS* delta 19439 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 H_pose, OptionalJacobian<6, 6> H_xib) const { - // Ad * xi = [ R 0 . [w - // [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; + const Matrix6 Ad = AdjointMap(); // Jacobians - if (H_pose) { - // pRw_H_posev = pRw_H_t * R = [Rw]x * R = R * [w]x = Rw_H_R - // where [ ]x denotes the skew-symmetric operator. - // See docs/math.pdf for more details. - const Matrix3 &pRw_H_posev = Rw_H_R; - *H_pose = (Matrix6() << Rw_H_R, /* */ Z_3x3, // - /* */ pRw_H_Rw * Rw_H_R + Rv_H_R, pRw_H_posev) - .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(); - } + // D1 Ad_T(xi_b) = D1 Ad_T Ad_I(xi_b) = Ad_T * D1 Ad_I(xi_b) = Ad_T * ad_xi_b + // D2 Ad_T(xi_b) = Ad_T + // See docs/math.pdf for more details. + // In D1 calculation, we could be more efficient by writing it out, but do not + // for readability + if (H_pose) *H_pose = -Ad * adjointMap(xi_b); + if (H_xib) *H_xib = Ad; - // Return - we computed result manually but it should be = AdjointMap() * xi - return result; + return Ad * xi_b; } /* ************************************************************************* */ /// The dual version of Adjoint Vector6 Pose3::AdjointTranspose(const Vector6& x, OptionalJacobian<6, 6> H_pose, OptionalJacobian<6, 6> H_x) const { - // Ad^T * xi = [ R^T R^T.[-t] . [w - // 0 R^T ] v] - // 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; + const Matrix6 &AdT = AdjointMap().transpose(); + const Vector6 &AdTx = AdT * x; // Jacobians + // See docs/math.pdf for more details. if (H_pose) { - // Rtv_H_posev = -Rtv_H_tv * tv_H_t * R = -R' * -[v]x * R = -[R'v]x = Rv_H_R - // where [ ]x denotes the skew-symmetric operator. - // See docs/math.pdf for more details. - const Matrix3 &Rtv_H_posev = Rv_H_R; - *H_pose = (Matrix6() << Rw_H_R - Rtv_H_R, Rtv_H_posev, - /* */ Rv_H_R, /* */ Z_3x3) + const auto &w_T_hat = skewSymmetric(AdTx.head<3>()), + &v_T_hat = skewSymmetric(AdTx.tail<3>()); + *H_pose = (Matrix6() << w_T_hat, v_T_hat, // + /* */ v_T_hat, Z_3x3) .finished(); } if (H_x) { - // This is just equal to AdjointMap().transpose() but we can reuse [t]x - *H_x = (Matrix6() << Rw_H_w, -Rtv_H_tv * tv_H_v, - /* */ Z_3x3, Rv_H_v) - .finished(); + *H_x = AdT; } - // Return - this should be equivalent to AdjointMap().transpose() * xi - return result; + return AdTx; } /* ************************************************************************* */