【C++】sophus : rxso2.hpp 描述二维旋转和缩放的数学工具类 (二十)

206e7d856fe81012d56ad129e8ce762a.png

rxso2.hpp 文件主要实现了一个描述二维空间中旋转和缩放组合的数学对象RxSO2。这个对象结合了旋转群 SO(2) 和正实数缩放群 R+,可以用于表示和操作二维变换。以下是该文件的主要内容总结:

  1. 类模板定义

  • template <class Scalar_, int Options = 0> class RxSO2:定义了RxSO2 模板类,用于描述带缩放的旋转矩阵。

  • using RxSO2d = RxSO2<double> 和using RxSO2f = RxSO2<float>:分别定义了double 和float 类型的RxSO2

类和方法实现

  • RxSO2Base:一个模板基类,实现了大部分RxSO2 的功能,包括旋转矩阵和缩放因子的计算、读取和设置。

  • RxSO2:派生类,继承自RxSO2Base,提供了具体的数据存储和操作。

辅助函数和操作

  • 复数访问器:提供了对内部复数表示的读写访问,如complex()data()

  • 矩阵变换和旋转:实现了旋转矩阵和缩放因子的计算,如rotationMatrix()scale()

  • 指数和对数映射:实现了李群和李代数之间的转换,如exp() 和log()

  • 群操作:实现了对点、直线和超平面的群操作,如operator*()

特化和映射

  • Eigen::Map 特化:实现了对RxSO2 和RxSO2 const 的特化,使其可以与Eigen 库的其他部分配合使用。

保护机制

  • 确保缩放因子在合理范围内,以避免数值不稳定。

总体来说,rxso2.hpp 文件实现了一个用于描述二维旋转和缩放的数学工具类,可以广泛用于计算机图形学、机器人学等领域。文件通过模板和特化的方式实现了灵活且高效的数值计算功能。

/// R X SO(2) 直积 - 在二维空间中的旋转和缩放。
#pragma once
#include "so2.hpp"  // 包含定义 SO2 类的头文件
namespace Sophus {    template <class Scalar_, int Options = 0>    class RxSO2;  // 定义模板类 RxSO2    using RxSO2d = RxSO2<double>;  // RxSO2 类的 double 类型特化    using RxSO2f = RxSO2<float>;  // RxSO2 类的 float 类型特化} // namespace Sophus
namespace Eigen {    namespace internal {        template <class Scalar_, int Options_>        struct traits<Sophus::RxSO2<Scalar_, Options_>> {            static constexpr int Options = Options_;  // 定义 Options 常量            using Scalar = Scalar_;  // 定义标量类型            using ComplexType = Sophus::Vector2<Scalar, Options>;  // 定义复数类型        };
        template <class Scalar_, int Options_>        struct traits<Map<Sophus::RxSO2<Scalar_>, Options_>> : traits<Sophus::RxSO2<Scalar_, Options_>> {            static constexpr int Options = Options_;  // 定义 Options 常量            using Scalar = Scalar_;  // 定义标量类型            using ComplexType = Map<Sophus::Vector2<Scalar>, Options>;  // 定义复数类型        };
        template <class Scalar_, int Options_>        struct traits<Map<Sophus::RxSO2<Scalar_> const, Options_>> : traits<Sophus::RxSO2<Scalar_, Options_> const> {            static constexpr int Options = Options_;  // 定义 Options 常量            using Scalar = Scalar_;  // 定义标量类型            using ComplexType = Map<Sophus::Vector2<Scalar> const, Options>;  // 定义复数类型        };    } // namespace internal} // namespace Eigen
namespace Sophus {    /// RxSO2 基类型 - 实现了 RxSO2 类但不包含存储特定信息    ///    /// 这个类实现了群 ``R+ x SO(2)``, 即正实数群与二维特殊正交群 SO(2) 的直积。    /// 从几何上看,它是二维空间中的旋转和缩放的群。    /// 作为矩阵群,R+ x SO(2) 由形如 ``s * R`` 的矩阵组成,其中 ``R`` 是行列式为 1 的正交矩阵,``s > 0`` 是正实数。    /// 特别是,它具有如下形式:    ///    /// | s * cos(theta) s * -sin(theta) |    /// | s * sin(theta) s * cos(theta) |    ///    /// 其中 ``theta`` 是旋转角度。在内部,它由旋转矩阵的第一列表示,或者说由一个非零的复数表示。    ///    /// R+ x SO(2) 不是紧群,但它是交换群。首先,它不是紧群,因为缩放因子不受限。其次,它是交换群,因为    /// ``sR(alpha, s1) * sR(beta, s2) = sR(beta, s2) * sR(alpha, s1)``, 只是因为 ``alpha + beta = beta + alpha`` 和 ``s1 * s2 = s2 * s1``    /// 其中 ``alpha`` 和 ``beta`` 是旋转角度,``s1`` 和 ``s2`` 是缩放因子。    ///    /// 这个类有一个显式的类不变性,即缩放 ``s`` 不会过于接近零或无穷大。严格来说,必须满足以下条件:    ///    /// ``complex().norm() >= Constants::epsilon()`` 并且    /// ``1. / complex().norm() >= Constants::epsilon()``。    ///    /// 为了遵守这个条件,群乘法通过饱和实现,使得乘积始终具有不小于这个阈值的缩放比例。
    template <class Derived>    class RxSO2Base {    public:        static constexpr int Options = Eigen::internal::traits<Derived>::Options;  // 定义 Options 常量        using Scalar = typename Eigen::internal::traits<Derived>::Scalar;  // 定义标量类型        using ComplexType = typename Eigen::internal::traits<Derived>::ComplexType;  // 定义复数类型        using ComplexTemporaryType = Sophus::Vector2<Scalar, Options>;  // 定义临时复数类型
        /// 流形的自由度,即切空间的维数 (一个用于旋转,一个用于缩放)。        static int constexpr DoF = 2;  
        /// 使用的内部参数数量 (复数是一个元组)。        static int constexpr num_parameters = 2;  
        /// 群变换是 2x2 矩阵。        static int constexpr N = 2;  
        /// 点是二维的。        static int constexpr Dim = 2;  
        using Transformation = Matrix<Scalar, N, N>;  // 定义变换矩阵类型        using Point = Vector2<Scalar>;  // 定义点的类型        using HomogeneousPoint = Vector3<Scalar>;  // 定义齐次点的类型        using Line = ParametrizedLine2<Scalar>;  // 定义参数化线的类型        using Hyperplane = Hyperplane2<Scalar>;  // 定义超平面的类型        using Tangent = Vector<Scalar, DoF>;  // 定义切向量的类型        using Adjoint = Matrix<Scalar, DoF, DoF>;  // 定义伴随矩阵的类型
        /// 对于二元运算,返回类型由 Eigen 的 ScalarBinaryOpTraits 特性决定。        /// 这允许混合具体类型和 Map 类型,以及其他兼容的标量类型,例如 Ceres::Jet 和 double 标量与 RxSO2 运算。        template <typename OtherDerived>        using ReturnScalar = typename Eigen::ScalarBinaryOpTraits<Scalar, typename OtherDerived::Scalar>::ReturnType;
        template <typename OtherDerived>        using RxSO2Product = RxSO2<ReturnScalar<OtherDerived>>;  // 定义 RxSO2 乘积的类型
        template <typename PointDerived>        using PointProduct = Vector2<ReturnScalar<PointDerived>>;  // 定义点乘积的类型
        template <typename HPointDerived>        using HomogeneousPointProduct = Vector3<ReturnScalar<HPointDerived>>;  // 定义齐次点乘积的类型
/// 伴随变换////// 这个函数返回群元素 ``A`` 的伴随变换 ``Ad``,使得对于所有 ``x`` 均满足/// ``hat(Ad_A * x) = A * hat(x) A^{-1}``。参见下面的帽操作符。////// 对于 RxSO(2),它仅返回单位矩阵。///SOPHUS_FUNC Adjoint Adj() const { return Adjoint::Identity(); }
/// 返回旋转角度。///SOPHUS_FUNC Scalar angle() const { return SO2<Scalar>(complex()).log(); }
/// 返回转换为 NewScalarType 类型的实例的副本。///template <class NewScalarType>SOPHUS_FUNC RxSO2<NewScalarType> cast() const {    typename RxSO2<NewScalarType>::ComplexType c =        complex().template cast<NewScalarType>();    return RxSO2<NewScalarType>(c);}
/// 提供对内部数据的不安全读写访问。RxSO(2) 由一个复数(两个参数)表示。/// 使用直接写访问时,用户需要注意复数不能设置得太接近零。////// 注意:第一个参数表示实部,而第二个参数表示虚部。///SOPHUS_FUNC Scalar* data() { return complex_nonconst().data(); }
/// 上面 data() 的常量版本。///SOPHUS_FUNC Scalar const* data() const { return complex().data(); }
/// 返回群逆。///SOPHUS_FUNC RxSO2<Scalar> inverse() const {    Scalar squared_scale = complex().squaredNorm();    Vector2<Scalar> xy = complex() / squared_scale;    return RxSO2<Scalar>(xy.x(), -xy.y());}
/// 对数映射////// 计算对数,即群指数的逆运算,将群元素(缩放的旋转矩阵)映射到切空间的元素(旋转向量加上缩放因子的对数)。////// 具体来说,这个函数计算 ``vee(logmat(.))``,其中 ``logmat(.)`` 是矩阵对数,``vee(.)`` 是 RxSO2 的对偶操作符。///SOPHUS_FUNC Tangent log() const {    using std::log;    Tangent theta_sigma;    theta_sigma[1] = log(scale());    theta_sigma[0] = SO2<Scalar>(complex()).log();    return theta_sigma;}
/// 返回实例的 2x2 矩阵表示。////// 对于 RxSO2,矩阵表示是一个缩放的正交矩阵 ``sR``,其中 ``det(R)=s^2``,因此是一个具有缩放 ``s`` 的旋转矩阵 ``R``。///SOPHUS_FUNC Transformation matrix() const {    Transformation sR;    // clang-format off    sR << complex()[0], -complex()[1],          complex()[1],  complex()[0];    // clang-format on    return sR;}
/// 赋值操作符。///template <class OtherDerived>SOPHUS_FUNC RxSO2Base<Derived>& operator=(    RxSO2Base<OtherDerived> const& other) {    complex_nonconst() = other.complex();    return *this;}
/// 群乘法,即旋转合并和缩放相乘。////// 注意:此函数对接近零的乘积进行饱和处理,以确保类不变性。///template <typename OtherDerived>SOPHUS_FUNC RxSO2Product<OtherDerived> operator*(    RxSO2Base<OtherDerived> const& other) const {    using ResultT = ReturnScalar<OtherDerived>;
    Scalar lhs_real = complex().x();    Scalar lhs_imag = complex().y();    typename OtherDerived::Scalar const& rhs_real = other.complex().x();    typename OtherDerived::Scalar const& rhs_imag = other.complex().y();    /// 复数乘法    typename RxSO2Product<OtherDerived>::ComplexType result_complex(        lhs_real * rhs_real - lhs_imag * rhs_imag,        lhs_real * rhs_imag + lhs_imag * rhs_real);
    const ResultT squared_scale = result_complex.squaredNorm();
    if (squared_scale <        Constants<ResultT>::epsilon() * Constants<ResultT>::epsilon()) {        /// 饱和处理以确保类不变性。        result_complex.normalize();        result_complex *= Constants<ResultT>::epsilonPlus();    }    if (squared_scale > Scalar(1.) / (Constants<ResultT>::epsilon() *                                      Constants<ResultT>::epsilon())) {        /// 饱和处理以确保类不变性。        result_complex.normalize();        result_complex /= Constants<ResultT>::epsilonPlus();    }    return RxSO2Product<OtherDerived>(result_complex);}
/// 对二维点进行群操作。////// 这个函数通过 SO2 元素 ``bar_R_foo``(即旋转矩阵)旋转一个二维点 ``p``,并按缩放因子 ``s`` 缩放://////   ``p_bar = s * (bar_R_foo * p_foo)``。///template <typename PointDerived,          typename = typename std::enable_if_t<              IsFixedSizeVector<PointDerived, 2>::value>>SOPHUS_FUNC PointProduct<PointDerived> operator*(    Eigen::MatrixBase<PointDerived> const& p) const {  return matrix() * p;}
/// 对齐次二维点进行群操作。详情请参见上文。///template <typename HPointDerived,          typename = typename std::enable_if_t<              IsFixedSizeVector<HPointDerived, 3>::value>>SOPHUS_FUNC HomogeneousPointProduct<HPointDerived> operator*(    Eigen::MatrixBase<HPointDerived> const& p) const {  const auto rsp = *this * p.template head<2>();  return HomogeneousPointProduct<HPointDerived>(rsp(0), rsp(1), p(2));}
/// 对直线进行群操作。////// 这个函数通过 SO2 元素旋转参数化直线 ``l(t) = o + t * d``,并按缩放因子缩放。////// 原点 ``o`` 被旋转和缩放/// 方向 ``d`` 被旋转(保持其范数)SOPHUS_FUNC Line operator*(Line const& l) const {  return Line((*this) * l.origin(), (*this) * l.direction() / scale());}
/// 对超平面进行群操作。////// 这个函数通过 SO2 元素旋转超平面 ``n.x + d = 0``,并按缩放因子缩放偏移量。////// 法向量 ``n`` 被旋转/// 偏移量 ``d`` 被缩放////// 注意,在二维情况下,超平面只是直线的另一种参数化表示///SOPHUS_FUNC Hyperplane operator*(Hyperplane const& p) const {  const auto this_scale = scale();  return Hyperplane((*this) * p.normal() / this_scale,                    this_scale * p.offset());}
/// 就地进行群乘法。如果乘法的返回类型与此 SO2 的标量类型兼容,则此方法有效。////// 注意:这个函数对接近零的乘积进行饱和处理,以确保类不变性。///template <typename OtherDerived,          typename = typename std::enable_if_t<              std::is_same<Scalar, ReturnScalar<OtherDerived>>::value>>SOPHUS_FUNC RxSO2Base<Derived>& operator*=(    RxSO2Base<OtherDerived> const& other) {  *static_cast<Derived*>(this) = *this * other;  return *this;}
/// 返回 this * RxSO2::exp(x) 对 x 在 x=0 处的导数。///SOPHUS_FUNC Matrix<Scalar, num_parameters, DoF> Dx_this_mul_exp_x_at_0()    const {  Matrix<Scalar, num_parameters, DoF> J;  J << -complex().y(), complex().x(), complex().x(), complex().y();  return J;}
/// 返回 log(this^{-1} * x) 对 x 在 x=this 处的导数。///SOPHUS_FUNC Matrix<Scalar, DoF, num_parameters> Dx_log_this_inv_by_x_at_this()    const {  Matrix<Scalar, DoF, num_parameters> J;  const Scalar norm_sq_inv = Scalar(1.) / complex().squaredNorm();  J << -complex().y(), complex().x(), complex().x(), complex().y();  return J * norm_sq_inv;}
/// 返回 RxSO(2) 的内部参数。////// 它返回 (c[0], c[1]),其中 c 是复数。///SOPHUS_FUNC Sophus::Vector<Scalar, num_parameters> params() const {  return complex();}
/// 设置非零复数。////// 前提条件:``z`` 不能太接近零或无穷大。SOPHUS_FUNC void setComplex(Vector2<Scalar> const& z) {  SOPHUS_ENSURE(z.squaredNorm() > Constants<Scalar>::epsilon() *                                    Constants<Scalar>::epsilon(),                "Scale factor must be greater-equal epsilon.");  SOPHUS_ENSURE(z.squaredNorm() < Scalar(1.) / (Constants<Scalar>::epsilon() *                                                Constants<Scalar>::epsilon()),                "Inverse scale factor must be greater-equal epsilon.");  static_cast<Derived*>(this)->complex_nonconst() = z;}
/// 访问复数。///SOPHUS_FUNC ComplexType const& complex() const {  return static_cast<Derived const*>(this)->complex();}
/// 返回旋转矩阵。///SOPHUS_FUNC Transformation rotationMatrix() const {  ComplexTemporaryType norm_quad = complex();  norm_quad.normalize();  return SO2<Scalar>(norm_quad).matrix();}
/// 返回缩放因子。///SOPHUS_FUNC Scalar scale() const {  using std::hypot;  return hypot(complex().x(), complex().y());}
/// 设置旋转角度,保持缩放不变。///SOPHUS_FUNC void setAngle(Scalar const& theta) {  setSO2(SO2<Scalar>(theta));}
/// 使用旋转矩阵 ``R`` 设置复数,保持缩放不变。////// 前提条件:``R`` 必须是行列式为一的正交矩阵。///SOPHUS_FUNC void setRotationMatrix(Transformation const& R) {  setSO2(SO2<Scalar>(R));}
/// 设置缩放因子,保持旋转不变。///SOPHUS_FUNC void setScale(Scalar const& scale) {  using std::sqrt;  complex_nonconst().normalize();  complex_nonconst() *= scale;}
/// 使用缩放的旋转矩阵 ``sR`` 设置复数。////// 前提条件:这个 2x2 矩阵必须是“缩放正交”的并且具有正行列式。///SOPHUS_FUNC void setScaledRotationMatrix(Transformation const& sR) {  SOPHUS_ENSURE(isScaledOrthogonalAndPositive(sR),                "sR must be scaled orthogonal:\n {}", (sR));  complex_nonconst() = sR.col(0);}
/// 设置 SO(2) 旋转,保持缩放不变。///SOPHUS_FUNC void setSO2(SO2<Scalar> const& so2) {  using std::sqrt;  Scalar saved_scale = scale();  complex_nonconst() = so2.unit_complex();  complex_nonconst() *= saved_scale;}
SOPHUS_FUNC SO2<Scalar> so2() const {  return SO2<Scalar>(complex());}
private:/// 修改复数(私有)以确保类不变性。///SOPHUS_FUNC ComplexType& complex_nonconst() {  return static_cast<Derived*>(this)->complex_nonconst();}};
/// 使用存储的 RxSO2;继承自 RxSO2Base。template <class Scalar_, int Options>class RxSO2 : public RxSO2Base<RxSO2<Scalar_, Options>> {public:  using Base = RxSO2Base<RxSO2<Scalar_, Options>>;  using Scalar = Scalar_;  using Transformation = typename Base::Transformation;  using Point = typename Base::Point;  using HomogeneousPoint = typename Base::HomogeneousPoint;  using Tangent = typename Base::Tangent;  using Adjoint = typename Base::Adjoint;  using ComplexMember = Eigen::Matrix<Scalar, 2, 1, Options>;
  /// ``Base`` 是友元类,因此可以从 ``Base`` 访问 complex_nonconst。  friend class RxSO2Base<RxSO2<Scalar_, Options>>;
  using Base::operator=;
  /// 明确定义拷贝赋值操作符。如果存在用户声明的拷贝构造函数,则隐式拷贝赋值操作符的定义已被弃用(clang >= 13 中的 -Wdeprecated-copy)。  SOPHUS_FUNC RxSO2& operator=(RxSO2 const& other) = default;
  static int constexpr DoF = Base::DoF;  static int constexpr num_parameters = Base::num_parameters;
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  /// 默认构造函数将复数初始化为单位旋转,缩放为 1。  ///  SOPHUS_FUNC RxSO2() : complex_(Scalar(1), Scalar(0)) {}
  /// 拷贝构造函数  ///  SOPHUS_FUNC RxSO2(RxSO2 const& other) = default;
/// 从 OtherDerived 复制构造。///template <class OtherDerived>SOPHUS_FUNC RxSO2(RxSO2Base<OtherDerived> const& other)    : complex_(other.complex()) {}
/// 使用缩放旋转矩阵的构造函数////// 前提条件:旋转矩阵需要是缩放正交矩阵,行列式为 ``s^2``。///SOPHUS_FUNC explicit RxSO2(Transformation const& sR) {  this->setScaledRotationMatrix(sR);}
/// 使用缩放因子和旋转矩阵 ``R`` 的构造函数。////// 前提条件:旋转矩阵 ``R`` 必须是行列式为 1 的正交矩阵,///           并且 ``scale`` 不能太接近零或无穷大。///SOPHUS_FUNC RxSO2(Scalar const& scale, Transformation const& R)    : RxSO2((scale * SO2<Scalar>(R).unit_complex()).eval()) {}
/// 使用缩放因子和 SO2 的构造函数////// 前提条件:``scale`` 不能太接近零或无穷大。///SOPHUS_FUNC RxSO2(Scalar const& scale, SO2<Scalar> const& so2)    : RxSO2((scale * so2.unit_complex()).eval()) {}
/// 使用复数的构造函数。////// 前提条件:复数不能太接近零或无穷大。///SOPHUS_FUNC explicit RxSO2(Vector2<Scalar> const& z) : complex_(z) {  SOPHUS_ENSURE(      complex_.squaredNorm() >=          Constants<Scalar>::epsilon() * Constants<Scalar>::epsilon(),      "Scale factor must be greater-equal epsilon: {} vs {}",      (complex_.squaredNorm()),      (Constants<Scalar>::epsilon() * Constants<Scalar>::epsilon()));  SOPHUS_ENSURE(      complex_.squaredNorm() <= Scalar(1.) / (Constants<Scalar>::epsilon() *                                              Constants<Scalar>::epsilon()),      "Inverse scale factor must be greater-equal epsilon: {} vs {}",      (Scalar(1.) / complex_.squaredNorm()),      (Constants<Scalar>::epsilon() * Constants<Scalar>::epsilon()));}
/// 使用复数的构造函数。////// 前提条件:复数不能太接近零或无穷大。///SOPHUS_FUNC explicit RxSO2(Scalar const& real, Scalar const& imag)    : RxSO2(Vector2<Scalar>(real, imag)) {}
/// 访问复数。///SOPHUS_FUNC ComplexMember const& complex() const { return complex_; }
/// 返回 exp(x) 对 ``x`` 的导数///SOPHUS_FUNC static Sophus::Matrix<Scalar, num_parameters, DoF> Dx_exp_x(    Tangent const& a) {  using std::cos;  using std::exp;  using std::sin;  Scalar const theta = a[0];  Scalar const sigma = a[1];
  Sophus::Matrix<Scalar, num_parameters, DoF> J;  J << -sin(theta), cos(theta), cos(theta), sin(theta);  return J * exp(sigma);}
/// 返回 exp(x) 对 x_i 在 x=0 处的导数。///SOPHUS_FUNC static Sophus::Matrix<Scalar, num_parameters, DoF>Dx_exp_x_at_0() {  Sophus::Matrix<Scalar, num_parameters, DoF> J;  static Scalar const i(1.);  static Scalar const o(0.);  J << o, i, i, o;  return J;}
/// 返回 exp(x) * p 对 x_i 在 x=0 处的导数。///SOPHUS_FUNC static Sophus::Matrix<Scalar, 2, DoF> Dx_exp_x_times_point_at_0(    Point const& point) {  Sophus::Matrix<Scalar, 2, DoF> j;  j << Sophus::SO2<Scalar>::Dx_exp_x_times_point_at_0(point), point;  return j;}
/// 返回 exp(x).matrix() 对 ``x_i 在 x=0`` 的导数。///SOPHUS_FUNC static Transformation Dxi_exp_x_matrix_at_0(int i) {  return generator(i);}
/// 群指数////// 这个函数接收切空间的一个元素(= 旋转角加上缩放的对数),并返回对应的群 RxSO2 的元素。////// 更具体地说,这个函数计算 ``expmat(hat(theta))``,其中 ``expmat(.)`` 是矩阵指数,``hat(.)`` 是 RSO2 的 hat() 操作符。///SOPHUS_FUNC static RxSO2<Scalar> exp(Tangent const& a) {  using std::exp;  using std::max;  using std::min;
  Scalar const theta = a[0];  Scalar const sigma = a[1];  Scalar s = exp(sigma);  // 确保缩放因子的正确性  s = max(s, Constants<Scalar>::epsilonPlus());  s = min(s, Scalar(1.) / Constants<Scalar>::epsilonPlus());  Vector2<Scalar> z = SO2<Scalar>::exp(theta).unit_complex();  z *= s;  return RxSO2<Scalar>(z);}
/// 返回 ``R+ x SO(2)`` 的第 i 个无穷小生成元。////// RxSO2 的无穷小生成元为:////// ```///         |  0 -1 |///   G_0 = |  1  0 |//////         |  1  0 |///   G_1 = |  0  1 |/// ```////// 前提条件:``i`` 必须是 0 或 1。///SOPHUS_FUNC static Transformation generator(int i) {  SOPHUS_ENSURE(i >= 0 && i <= 1, "i should be 0 or 1.");  Tangent e;  e.setZero();  e[i] = Scalar(1);  return hat(e);}
/// hat 操作符////// 它接收二维向量表示 ``a``(= 旋转角加上缩放的对数),返回对应的李代数元素的矩阵表示。////// 正式定义,RxSO2 的 hat 操作符为://////   ``hat(.): R^2 -> R^{2x2},  hat(a) = sum_i a_i * G_i``  (对 i=0,1,2)////// 其中 ``G_i`` 是 RxSO2 的第 i 个无穷小生成元。////// 对应的逆操作符是 vee(),参见下面。///SOPHUS_FUNC static Transformation hat(Tangent const& a) {  Transformation A;  // clang-format off  A << a(1), -a(0),       a(0),  a(1);  // clang-format on  return A;}
/// 李括号////// 它计算 RxSO(2) 的李括号。更具体地说,它计算//////   ``[omega_1, omega_2]_rxso2 := vee([hat(omega_1), hat(omega_2)])``////// 其中 ``[A,B] := AB-BA`` 是矩阵对易子,``hat(.)`` 是 hat 操作符,``vee(.)`` 是 RxSO2 的 vee 操作符。///SOPHUS_FUNC static Tangent lieBracket(Tangent const&, Tangent const&) {  Vector2<Scalar> res;  res.setZero();  return res;}
/// 从 RxSO(2) 流形中绘制均匀样本。////// 缩放因子在 log2 空间中从 [-1, 1] 均匀绘制,因此缩放在 [0.5, 2]。///template <class UniformRandomBitGenerator>static RxSO2 sampleUniform(UniformRandomBitGenerator& generator) {  std::uniform_real_distribution<Scalar> uniform(Scalar(-1), Scalar(1));  using std::exp2;  return RxSO2(exp2(uniform(generator)),               SO2<Scalar>::sampleUniform(generator));}
/// vee 操作符////// 它接收 2x2 矩阵表示 ``Omega``,并将其映射到相应的李代数向量表示。////// 这是 hat 操作符的逆操作,参见上文。////// 前提条件:``Omega`` 必须具有以下结构://////                |  d -x |///                |  x  d |///SOPHUS_FUNC static Tangent vee(Transformation const& Omega) {  using std::abs;  return Tangent(Omega(1, 0), Omega(0, 0));}
protected:SOPHUS_FUNC ComplexMember& complex_nonconst() { return complex_; }
ComplexMember complex_;};
}  // namespace Sophus
namespace Eigen {
/// Eigen::Map 针对 ``RxSO2`` 的特化;继承自 RxSO2Base。////// 允许我们将 RxSO2 对象包装在 POD 数组(例如外部 z 样式复数)周围。template <class Scalar_, int Options>class Map<Sophus::RxSO2<Scalar_>, Options>    : public Sophus::RxSO2Base<Map<Sophus::RxSO2<Scalar_>, Options>> {  using Base = Sophus::RxSO2Base<Map<Sophus::RxSO2<Scalar_>, Options>>;
 public:  using Scalar = Scalar_;  using Transformation = typename Base::Transformation;  using Point = typename Base::Point;  using HomogeneousPoint = typename Base::HomogeneousPoint;  using Tangent = typename Base::Tangent;  using Adjoint = typename Base::Adjoint;
  /// ``Base`` 是友元类,因此可以从 ``Base`` 访问 complex_nonconst。  friend class Sophus::RxSO2Base<Map<Sophus::RxSO2<Scalar_>, Options>>;
  using Base::operator=;  using Base::operator*=;  using Base::operator*;
  SOPHUS_FUNC explicit Map(Scalar* coeffs) : complex_(coeffs) {}
  /// 访问复数。  ///  SOPHUS_FUNC  Map<Sophus::Vector2<Scalar>, Options> const& complex() const {    return complex_;  }
 protected:  SOPHUS_FUNC Map<Sophus::Vector2<Scalar>, Options>& complex_nonconst() {    return complex_;  }
  Map<Sophus::Vector2<Scalar>, Options> complex_;};
/// Eigen::Map 针对 ``RxSO2 const`` 的特化;继承自 RxSO2Base。////// 允许我们将 RxSO2 对象包装在 POD 数组(例如外部 z 样式复数)周围。template <class Scalar_, int Options>class Map<Sophus::RxSO2<Scalar_> const, Options>    : public Sophus::RxSO2Base<Map<Sophus::RxSO2<Scalar_> const, Options>> { public:  using Base = Sophus::RxSO2Base<Map<Sophus::RxSO2<Scalar_> const, Options>>;  using Scalar = Scalar_;  using Transformation = typename Base::Transformation;  using Point = typename Base::Point;  using HomogeneousPoint = typename Base::HomogeneousPoint;  using Tangent = typename Base::Tangent;  using Adjoint = typename Base::Adjoint;
  using Base::operator*=;  using Base::operator*;
  SOPHUS_FUNC  explicit Map(Scalar const* coeffs) : complex_(coeffs) {}
  /// 访问复数。  ///  SOPHUS_FUNC  Map<Sophus::Vector2<Scalar> const, Options> const& complex() const {    return complex_;  }
 protected:  Map<Sophus::Vector2<Scalar> const, Options> const complex_;};}  // namespace Eigen

这段代码定义了 Sophus 库中的RxSO2 类,用于表示二维空间中的旋转和缩放变换。RxSO2 是正实数群 R+ 和二维特殊正交群 SO(2) 的直积。

以下是代码的中文总结:

  • 功能:RxSO2

     类表示二维空间中的旋转和缩放变换。它本质上是一个复数,其中复数的模表示缩放比例,复数的辐角表示旋转角度。

  • 数学背景:RxSO2

     对应于数学上的 R+ x SO(2) 群,即正实数群和二维特殊正交群的直积。它描述了在二维平面上先进行旋转,再进行缩放的变换。

  • 内部表示:RxSO2

     内部使用一个复数来表示。这个复数存储在complex_ 成员变量中。

  • 类结构:
    • RxSO2Base

      : 这是一个基类,实现了RxSO2 的基本功能,但不包含存储。它使用模板参数Derived 来实现静态多态性(CRTP)。

    • RxSO2

      : 这是主要的类,继承自RxSO2Base,并包含一个ComplexMember 类型的成员变量complex_ 用于存储复数。

    • Eigen::Map

      : 提供了将RxSO2 对象映射到外部内存的功能,允许使用例如 C 风格的数组来表示RxSO2 对象。这对于与其他库的接口非常有用。

  • 主要方法:
    • angle()

      : 返回旋转角度。

    • inverse()

      : 返回逆变换。

    • log()

      : 计算对数映射,将RxSO2 元素映射到李代数。

    • exp()

      : 计算指数映射,将李代数元素映射回RxSO2 群。

    • matrix()

      : 返回 2x2 的变换矩阵。

    • operator*()

      : 重载了乘法运算符,用于群乘法(变换的复合)和变换点/向量。

    • hat()

      : 帽算子,将李代数向量映射到李代数矩阵。

    • vee()

      : 楔算子,帽算子的逆运算,将李代数矩阵映射到李代数向量。

    • generator()

      : 返回李代数的生成元。

    • setAngle()

      ,setScale(),setRotationMatrix(),setScaledRotationMatrix(),setSO2(): 设置旋转角度、缩放比例、旋转矩阵等。

  • 关键特性:
    • 饱和:

       在群乘法中,为了保证数值稳定性,对缩放比例进行了饱和处理,避免接近零或无穷大。

    • 李代数:

       提供了李代数相关的操作,如log()exp()hat()vee() 和lieBracket(),这对于优化和插值等应用非常重要。

    • Eigen 集成:

       使用 Eigen 库进行矩阵和向量运算,并提供了Eigen::Map 的特化,方便与其他使用 Eigen 的代码集成。

  • 模板:

     使用模板允许使用不同的标量类型(例如float 或double)。

总而言之,这段代码提供了一个高效且功能完善的RxSO2 类,用于在二维空间中进行旋转和缩放变换,并提供了李代数相关的操作,方便进行更高级的几何计算。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值