【C++】sophus : cartesian.hpp 将欧几里得向量空间(即笛卡尔坐标系)实现为一个李群 (六)...

这段代码定义了一个名为Cartesian 的类,它将欧几里得向量空间(即笛卡尔坐标系)实现为一个李群。它旨在用于教育目的,展示李群如何推广欧几里得向量空间,并用于针对李群接口实现的模板/通用算法。

以下是代码的详细解释:

1. 命名空间和基本定义:

  • 定义了Sophus 命名空间,并在其中定义了Cartesian 类模板,以及Cartesian2Cartesian3Cartesian2d 和Cartesian3d 等常用类型的别名。

2. Eigen traits 特化:

  • Sophus::Cartesian 及其Map 版本特化了Eigen::traits,以便 Eigen 库能够正确处理Cartesian 对象,并将其视为具有特定标量类型和参数类型的对象。这允许Cartesian 对象与 Eigen 的其他类型无缝集成。

3.CartesianBase 类模板:

这是Cartesian 类的基类,包含所有核心功能。

  • 类型定义:

     定义了ScalarParamsTypeDoF(自由度)、num_parameters(参数数量)、N(变换矩阵的维度)、Dim(向量维度)、Transformation(变换矩阵类型)、Point(点类型)、HomogeneousPoint(齐次点类型)、Tangent(切向量类型)、Adjoint(伴随矩阵类型)等类型别名。

  • 伴随变换 (Adj):

     对于交换群(如笛卡尔群),伴随变换始终是单位矩阵。

  • 类型转换 (cast):

     将Cartesian 对象转换为具有不同标量类型的对象。

  • 导数计算:

     提供了计算this * exp(x) 在 x=0 处的导数 (Dx_this_mul_exp_x_at_0) 和log(this^{-1} * x) 在 x=this 处关于 x 的导数 (Dx_log_this_inv_by_x_at_this) 的函数。

  • 求逆 (inverse):

     计算群的逆元,对于笛卡尔群,即向量的加法逆元。

  • 对数映射 (log):

     对于欧几里得向量空间,对数映射只是恒等映射,或者更准确地说,它只是从 NxN 矩阵中提取重要的 M 维向量。

  • 矩阵表示 (matrix):

     返回实例的 (M+1)x(M+1) 矩阵表示,形式为:| I p || o 1 |

  • 群乘法 (operator*):

     对于笛卡尔群,群乘法即向量加法。

  • 群作用于点 (operator*):

     定义了群作用于点和齐次点的操作,本质上也是向量加法。

  • 群作用于直线和平面:

     定义了群作用于直线和超平面的操作。

  • 原地群乘法 (operator*=):

     定义了原地群乘法操作。

  • 参数访问 (params):

     提供了访问内部参数向量的接口。

4.Cartesian 类模板:

这是Cartesian 类的主要实现,继承自CartesianBase

  • 构造函数:

     提供了默认构造函数(初始化为零向量)、拷贝构造函数、从其他CartesianBase 类型的构造函数,以及从 M 维向量或 (M+1)x(M+1) 矩阵构造的构造函数。

  • 数据访问 (data):

     提供了对内部数据的直接读写访问。

  • 指数映射的导数 (Dx_exp_x_at_0,Dx_exp_x,Dx_exp_x_times_point_at_0,Dxi_exp_x_matrix_at_0):

     提供了计算指数映射及其相关导数的函数。

  • 生成器 (generator):

     返回Cartesian(M) 的第 i 个无穷小生成器。

  • 指数映射 (exp):

     对于欧几里得向量空间,指数映射只是构造 (M+1)x(M+1) 齐次矩阵表示。

  • hat 算子 (hat):

     定义了 hat 算子,将切向量映射到李代数。

  • 李括号 (lieBracket):

     对于交换群,李括号始终为 0。

  • 均匀采样 (sampleUniform):

     在每个坐标的 [-1, 1] 范围内进行均匀采样。

  • vee 算子 (vee):

     定义了 vee 算子,是 hat 算子的逆运算。

5.Eigen::Map 特化:

Cartesian 和Cartesian const 特化了Eigen::Map,允许将Cartesian 对象包装在原始数据数组周围,而无需进行复制。

总结:

这段代码将欧几里得向量空间实现为一个李群Cartesian。它提供了李群相关的操作,例如指数映射、对数映射、伴随变换、李括号等。通过继承和模板特化,代码实现了代码复用和类型安全。此外,通过与Eigen::Map 的集成,代码可以高效地处理原始数据数组,避免不必要的复制。这个类的主要目的是为了教学和在通用算法中使用,因为它本质上只是对向量加法的一种更复杂的表示。

/// Cartesian - 欧几里得向量空间作为李群
#pragma once // 防止头文件被重复包含#include <sophus/types.hpp> // 包含 Sophus 库中的类型定义
namespace Sophus { // 定义命名空间 Sophustemplate <class Scalar_, int M, int Options = 0>class Cartesian; // 声明 Cartesian 模板类
template <class Scalar_>using Cartesian2 = Cartesian<Scalar_, 2>; // 定义 Cartesian2 类型别名
template <class Scalar_>using Cartesian3 = Cartesian<Scalar_, 3>; // 定义 Cartesian3 类型别名
using Cartesian2d = Cartesian2<double>; // 定义双精度 Cartesian2 类型别名using Cartesian3d = Cartesian3<double>; // 定义双精度 Cartesian3 类型别名
}  // namespace Sophus
namespace Eigen { // 定义命名空间 Eigennamespace internal { // 定义内部命名空间 internal
template <class Scalar_, int M, int Options>struct traits<Sophus::Cartesian<Scalar_, M, Options>> {  using Scalar = Scalar_; // 定义标量类型  using ParamsType = Sophus::Vector<Scalar, M, Options>; // 定义参数类型};
template <class Scalar_, int M, int Options>struct traits<Map<Sophus::Cartesian<Scalar_, M>, Options>>    : traits<Sophus::Cartesian<Scalar_, M, Options>> {  using Scalar = Scalar_; // 定义标量类型  using ParamsType = Map<Sophus::Vector<Scalar, M>, Options>; // 定义参数类型};
template <class Scalar_, int M, int Options>struct traits<Map<Sophus::Cartesian<Scalar_, M> const, Options>>    : traits<Sophus::Cartesian<Scalar_, M, Options> const> {  using Scalar = Scalar_; // 定义标量类型  using ParamsType = Map<Sophus::Vector<Scalar, M> const, Options>; // 定义参数类型};}  // namespace internal}  // namespace Eigen
namespace Sophus { // 继续定义命名空间 Sophus
/// Cartesian 基类 - 实现 Cartesian 类但与存储无关。////// 欧几里得向量空间作为李群。////// 李群可以看作是欧几里得向量空间 R^M 的广义。这里,一个 N 维向量 ``p`` 表示为/// (M+1) x (M+1) 齐次矩阵://////   | I p |///   | o 1 |////// 另一方面,Cartesian(M) 可以看作是 SE(M) 的特例,具有恒等旋转,因此表示纯平移。////// 此类的目的有两个:///  - 用于教育目的,突出李群如何广义化欧几里得向量空间。///  - 用于模板化/泛型算法(如 Sophus::Spline)///    这些算法是根据李群接口实现的。////// 显然,Cartesian(M) 也可以表示为一个 M 元组。////// Cartesian 不是紧凑的,但它是一个交换群。对于向量加法,满足 `a+b = b+a`。////// 参见下面的 Cartesian 类了解更多详细信息。///template <class Derived, int M>class CartesianBase { // 定义 CartesianBase 模板类 public:  using Scalar = typename Eigen::internal::traits<Derived>::Scalar; // 定义标量类型  using ParamsType = typename Eigen::internal::traits<Derived>::ParamsType; // 定义参数类型  /// 流形的自由度,等于笛卡尔坐标的数量。  static int constexpr DoF = M;   /// 使用的内部参数数量,同样是 M。  static int constexpr num_parameters = M;  /// 群变换是 (M+1)x(M+1) 矩阵。  static int constexpr N = M + 1;  static int constexpr Dim = M;
  using Transformation = Sophus::Matrix<Scalar, N, N>; // 定义 Transformation 类型  using Point = Sophus::Vector<Scalar, M>; // 定义 Point 类型  using HomogeneousPoint = Sophus::Vector<Scalar, N>; // 定义 HomogeneousPoint 类型  using Line = ParametrizedLine<Scalar, M>; // 定义 Line 类型  using Hyperplane = Eigen::Hyperplane<Scalar, M>; // 定义 Hyperplane 类型  using Tangent = Sophus::Vector<Scalar, DoF>; // 定义 Tangent 类型  using Adjoint = Matrix<Scalar, DoF, DoF>; // 定义 Adjoint 类型
  /// 对于二元运算,返回类型由 Eigen 的 ScalarBinaryOpTraits 特性确定。  /// 这允许混合具体类型和 Map 类型,以及其他兼容的标量类型,如 Ceres::Jet 和  /// 用于笛卡尔运算的双精度标量。  template <typename OtherDerived>  using ReturnScalar = typename Eigen::ScalarBinaryOpTraits<      Scalar, typename OtherDerived::Scalar>::ReturnType;
  template <typename OtherDerived>  using CartesianSum = Cartesian<ReturnScalar<OtherDerived>, M>; // 定义 CartesianSum 类型
  template <typename PointDerived>  using PointProduct = Sophus::Vector<ReturnScalar<PointDerived>, M>; // 定义 PointProduct 类型
  template <typename HPointDerived>  using HomogeneousPointProduct =      Sophus::Vector<ReturnScalar<HPointDerived>, N>; // 定义 HomogeneousPointProduct 类型
  /// 伴随变换  ///  /// 始终是交换群的单位矩阵。  SOPHUS_FUNC Adjoint Adj() const { return Adjoint::Identity(); }
  /// 返回实例的复制并转换为新的标量类型。  ///  template <class NewScalarType>  SOPHUS_FUNC Cartesian<NewScalarType, M> cast() const {    return Cartesian<NewScalarType, M>(params().template cast<NewScalarType>());  }
  /// 返回 this * exp(x) 在 x=0 处相对于 x 的导数。  ///  SOPHUS_FUNC Matrix<Scalar, num_parameters, DoF> Dx_this_mul_exp_x_at_0()      const {    Sophus::Matrix<Scalar, num_parameters, DoF> m;    m.setIdentity();    return m;  }
  /// 返回 log(this^{-1} * x) 在 x=this 处相对于 x 的导数。  ///  SOPHUS_FUNC Matrix<Scalar, num_parameters, DoF> Dx_log_this_inv_by_x_at_this()      const {    Matrix<Scalar, DoF, num_parameters> m;    m.setIdentity();    return m;  }
  /// 返回群的逆元。  ///  /// 加性逆元。  ///  SOPHUS_FUNC Cartesian<Scalar, M> inverse() const {    return Cartesian<Scalar, M>(-params());  }
  /// 对数映射  ///  /// 对于欧几里得向量空间,直接为单位映射。更准确地说,  /// 它只从 NxN 矩阵中提取出重要的 M 向量。  ///  SOPHUS_FUNC Tangent log() const { return params(); }
  /// 返回实例的 4x4 矩阵表示。  ///  /// 形式如下:  ///  ///   | I p |  ///   | o 1 |  ///  SOPHUS_FUNC Transformation matrix() const {    Sophus::Matrix<Scalar, N, N> matrix;    matrix.setIdentity();    matrix.col(M).template head<M>() = params();    return matrix;  }
  /// 群的乘法,即向量加法。  ///  template <class OtherDerived>  SOPHUS_FUNC CartesianBase<Derived, M>& operator=(      CartesianBase<OtherDerived, M> const& other) {    params() = other.params();    return *this;  }
  /// 群的乘法,即向量加法。  ///  template <typename OtherDerived>  SOPHUS_FUNC CartesianSum<OtherDerived> operator*(      CartesianBase<OtherDerived, M> const& other) const {    return CartesianSum<OtherDerived>(params() + other.params());  }
  /// 群对点的作用,仍然是向量加法。  ///  template <typename PointDerived,            typename = typename std::enable_if_t<                IsFixedSizeVector<PointDerived, M>::value>>  SOPHUS_FUNC PointProduct<PointDerived> operator*(      Eigen::MatrixBase<PointDerived> const& p) const {    return PointProduct<PointDerived>(params() + p);  }
  /// 群对齐次点的作用。见上面的更多详细信息。  ///  template <typename HPointDerived,            typename = typename std::enable_if_t<                IsFixedSizeVector<HPointDerived, N>::value>>  SOPHUS_FUNC HomogeneousPointProduct<HPointDerived> operator*(      Eigen::MatrixBase<HPointDerived> const& p) const {    const auto rp = *this * p.template head<M>();    HomogeneousPointProduct<HPointDerived> r;    r << rp, p(M);    return r;  }
/// 群对直线的作用。  ///  SOPHUS_FUNC Line operator*(Line const& l) const {    return Line((*this) * l.origin(), l.direction()); // 返回变换后的直线  }
  /// 群对平面的作用。  ///  SOPHUS_FUNC Hyperplane operator*(Hyperplane const& p) const {    return Hyperplane(p.normal(), p.offset() - params().dot(p.normal())); // 返回变换后的超平面  }
  /// 就地群乘法。此方法仅在乘法的返回类型与此笛卡尔的标量类型兼容时有效。  ///  template <typename OtherDerived,            typename = typename std::enable_if_t<                std::is_same<Scalar, ReturnScalar<OtherDerived>>::value>>  SOPHUS_FUNC CartesianBase<Derived, M>& operator*=(      CartesianBase<OtherDerived, M> const& other) {    *static_cast<Derived*>(this) = *this * other;    return *this;  }
  /// 修改 params 向量。  ///  SOPHUS_FUNC ParamsType& params() {    return static_cast<Derived*>(this)->params(); // 返回 params 向量  }
  /// 访问 params 向量  ///  SOPHUS_FUNC ParamsType const& params() const {    return static_cast<Derived const*>(this)->params(); // 返回常量 params 向量  }};
/// 使用默认存储的 Cartesian;派生自 CartesianBase。template <class Scalar_, int M, int Options>class Cartesian : public CartesianBase<Cartesian<Scalar_, M, Options>, M> {  using Base = CartesianBase<Cartesian<Scalar_, M, Options>, M>;
 public:  static int constexpr DoF = Base::DoF; // 自由度  static int constexpr num_parameters = Base::num_parameters; // 参数数量  static int constexpr N = Base::N;  static int constexpr Dim = Base::Dim;
  using Scalar = Scalar_;  using Transformation = typename Base::Transformation;  using Point = typename Base::Point;  using HomogeneousPoint = typename Base::HomogeneousPoint;  using Tangent = typename Base::Tangent;  using ParamsMember = Sophus::Vector<Scalar, M, Options>;
  using Base::operator=;
  /// 显式定义复制赋值运算符。在存在用户声明的复制构造函数的情况下,隐式复制赋值运算符的定义已弃用(在 clang >= 13 中为 -Wdeprecated-copy)。  SOPHUS_FUNC Cartesian& operator=(Cartesian const& other) = default;
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  /// 默认构造函数初始化为零向量。  ///  SOPHUS_FUNC Cartesian() { params_.setZero(); }
  /// 复制构造函数  ///  SOPHUS_FUNC Cartesian(Cartesian const& other) = default;
  /// 类似复制的构造函数  ///  template <class OtherDerived>  SOPHUS_FUNC Cartesian(CartesianBase<OtherDerived, M> const& other)      : params_(other.params()) {    static_assert(std::is_same<typename OtherDerived::Scalar, Scalar>::value,                  "must be same Scalar type"); // 确保标量类型相同  }
  /// 接受 M 向量或 (M+1)x(M+1) 矩阵。  ///  template <class D>  explicit SOPHUS_FUNC Cartesian(Eigen::MatrixBase<D> const& m) {    static_assert(        std::is_same<typename Eigen::MatrixBase<D>::Scalar, Scalar>::value, ""); // 确保矩阵基类型的标量类型相同    if (m.rows() == DoF && m.cols() == 1) {      // 编译时的技巧      params_ = m.template block<M, 1>(0, 0);    } else if (m.rows() == N && m.cols() == N) {      params_ = m.template block<M, 1>(0, M);    } else {      SOPHUS_ENSURE(false, "{} {}", m.rows(), m.cols());    }  }
  /// 提供对内部数据的不安全读写访问。  ///  SOPHUS_FUNC Scalar* data() { return params_.data(); }
  /// 上面的 const 版本。  ///  SOPHUS_FUNC Scalar const* data() const { return params_.data(); }
  /// 返回 exp(x) 相对于 x 的导数。  ///  SOPHUS_FUNC static Sophus::Matrix<Scalar, num_parameters, DoF>  Dx_exp_x_at_0() {    Sophus::Matrix<Scalar, num_parameters, DoF> m;    m.setIdentity();    return m;  }
  /// 返回 exp(x) 相对于 x_i 在 x=0 处的导数。///SOPHUS_FUNC static Sophus::Matrix<Scalar, num_parameters, DoF> Dx_exp_x(    Tangent const&) {  return Dx_exp_x_at_0(); // 调用 Dx_exp_x_at_0 函数}
/// 返回 exp(x) * p 对 x_i 在 x=0 处的导数。///SOPHUS_FUNC static Sophus::Matrix<Scalar, Dim, DoF> Dx_exp_x_times_point_at_0(    Point const&) {  Sophus::Matrix<Scalar, Dim, DoF> J; // 创建矩阵 J  J.setIdentity(); // 将矩阵 J 设为单位矩阵  return J; // 返回单位矩阵 J}
/// 返回 exp(x).matrix() 对 ``x_i 在 x=0 处的导数。///SOPHUS_FUNC static Transformation Dxi_exp_x_matrix_at_0(int i) {  return generator(i); // 返回第 i 个生成元}
/// 修改参数向量///SOPHUS_FUNC ParamsMember& params() {  return params_; // 返回参数向量}
/// 访问参数向量///SOPHUS_FUNC ParamsMember const& params() const {  return params_; // 返回参数向量}
/// 返回 Cartesian(M) 的第 i 个无穷小生成元。////// 例如,三维情况下的无穷小生成元:////// ```///         |  0  0  0  1 |///   G_0 = |  0  0  0  0 |///         |  0  0  0  0 |///         |  0  0  0  0 |//////         |  0  0  0  0 |///   G_1 = |  0  0  0  1 |///         |  0  0  0  0 |///         |  0  0  0  0 |//////         |  0  0  0  0 |///   G_2 = |  0  0  0  0 |///         |  0  0  0  1 |///         |  0  0  0  0 |/// ```////// 前置条件: ``i`` 必须在 [0, M-1] 范围内。///SOPHUS_FUNC static Transformation generator(int i) {  SOPHUS_ENSURE(i >= 0 && i <= M, "i 应该在 [0, M-1] 范围内。"); // 检查 i 的范围  Tangent e; // 创建切线向量 e  e.setZero(); // 将 e 置零  e[i] = Scalar(1); // 设置 e 的第 i 个元素为 1  return hat(e); // 返回 hat(e)}
/// 群指数////// 对于欧几里得向量空间,仅为单位映射。更准确地说,/// 它只是从 M 向量构造 (M+1)x(M+1) 的齐次矩阵表示。///SOPHUS_FUNC static Cartesian<Scalar, M> exp(Tangent const& a) {  return Cartesian<Scalar, M>(a); // 返回 Cartesian 对象}
/// hat-运算符////// 正式地说,Cartesian(M) 的 hat() 运算符定义为//////   ``hat(.): R^M -> R^{M+1xM+1},  hat(a) = sum_i a_i * G_i``///   (对于 i=0,...,M-1)////// 其中 ``G_i`` 是 Cartesian(M) 的第 i 个无穷小生成元。////// 对应的逆运算是 vee() 运算符,见下文。///SOPHUS_FUNC static Transformation hat(Tangent const& a) {  Transformation Omega; // 创建变换矩阵 Omega  Omega.setZero(); // 将 Omega 置零  Omega.col(M).template head<M>() = a.template head<M>(); // 设置 Omega 的最后一列的前 M 个元素  return Omega; // 返回变换矩阵 Omega}
/// 李括号////// 对于交换群,总是 0。SOPHUS_FUNC static Tangent lieBracket(Tangent const&, Tangent const&) {  return Tangent::Zero(); // 返回零向量}
/// 在每个坐标范围内绘制 [-1, 1] 的均匀样本。///template <class UniformRandomBitGenerator>static Cartesian sampleUniform(UniformRandomBitGenerator& generator) {  std::uniform_real_distribution<Scalar> uniform(Scalar(-1), Scalar(1)); // 创建均匀分布对象  Vector<Scalar, M> v; // 创建向量 v  for (int i = 0; i < M; ++i) {    v[i] = uniform(generator); // 为向量 v 生成均匀样本  }  return Cartesian(v); // 返回生成的 Cartesian 对象}
/// vee-运算符////// 这是 hat() 运算符的逆运算,见上文。///SOPHUS_FUNC static Tangent vee(Transformation const& m) {  return m.col(M).template head<M>(); // 返回变换矩阵 m 的最后一列的前 M 个元素}
protected:  ParamsMember params_; // 定义参数成员变量};
}  // namespace Sophus
namespace Eigen { // 定义命名空间 Eigen
/// Eigen::Map 的 ``Cartesian`` 特化; 派生自 CartesianBase。////// 允许我们将 Cartesian 对象包装在 POD 数组周围。template <class Scalar_, int M, int Options>class Map<Sophus::Cartesian<Scalar_, M>, Options>    : public Sophus::CartesianBase<Map<Sophus::Cartesian<Scalar_, M>, Options>, M> { public:  using Base = Sophus::CartesianBase<Map<Sophus::Cartesian<Scalar_, M>, Options>, M>; // 定义基类类型  using Scalar = Scalar_; // 定义标量类型  using Transformation = typename Base::Transformation; // 定义变换类型  using Point = typename Base::Point; // 定义点类型  using HomogeneousPoint = typename Base::HomogeneousPoint; // 定义齐次点类型  using Tangent = typename Base::Tangent; // 定义切向量类型
  using Base::operator=; // 继承基类的赋值操作符  using Base::operator*=; // 继承基类的乘法赋值操作符  using Base::operator*; // 继承基类的乘法操作符
  SOPHUS_FUNC explicit Map(Scalar* coeffs) : params_(coeffs) {} // 显式构造函数,使用参数初始化
  /// 修改参数向量  ///  SOPHUS_FUNC Map<Sophus::Vector<Scalar, M, Options>>& params() {    return params_; // 返回参数向量的引用  }
  /// 访问参数向量  ///  SOPHUS_FUNC Map<Sophus::Vector<Scalar, M, Options>> const& params() const {    return params_; // 返回参数向量的常量引用  }
 protected:  Map<Sophus::Vector<Scalar, M>, Options> params_; // 参数成员变量};
/// Eigen::Map 的 ``Cartesian const`` 特化; 派生自 CartesianBase。////// 允许我们将 Cartesian 对象包装在 POD 数组周围。template <class Scalar_, int M, int Options>class Map<Sophus::Cartesian<Scalar_, M> const, Options>    : public Sophus::CartesianBase<Map<Sophus::Cartesian<Scalar_, M> const, Options>, M> { public:  using Base = Sophus::CartesianBase<Map<Sophus::Cartesian<Scalar_, M> const, Options>, M>; // 定义基类类型  using Scalar = Scalar_; // 定义标量类型  using Transformation = typename Base::Transformation; // 定义变换类型  using Point = typename Base::Point; // 定义点类型  using HomogeneousPoint = typename Base::HomogeneousPoint; // 定义齐次点类型  using Tangent = typename Base::Tangent; // 定义切向量类型
  using Base::operator*; // 继承基类的乘法操作符
  SOPHUS_FUNC Map(Scalar const* coeffs) : params_(coeffs) {} // 构造函数,使用常量参数初始化
  /// 访问参数向量  ///  SOPHUS_FUNC Map<Sophus::Vector<Scalar, M> const, Options> const& params() const {    return params_; // 返回参数向量的常量引用  }
 protected:  Map<Sophus::Vector<Scalar, M> const, Options> const params_; // 常量参数成员变量};}  // namespace Eigen
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值