Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: api-reference for sophus::manifold #188

Merged
merged 1 commit into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cpp/sophus/common/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include <random>
#include <type_traits>

// \cond HIDDEN_SYMBOLS
// BEGIN(exclude from doxygen) \cond HIDDEN_SYMBOLS
// from <farm_ng/core/logging/format.h>cd
#define SOPHUS_FORMAT(...) FARM_FORMAT(__VA_ARGS__)

Expand All @@ -47,7 +47,7 @@
// from <farm_ng/core/logging/expected.h>
#define SOPHUS_TRY(...) FARM_TRY(__VA_ARGS__)
#define SOPHUS_UNEXPECTED(...) FARM_UNEXPECTED(__VA_ARGS__)
// \endcond
// END(exclude from doxygen) \endcond

namespace sophus {

Expand Down
63 changes: 26 additions & 37 deletions cpp/sophus/linalg/vector_space_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,43 +22,6 @@ namespace sophus {
template <class TPoint>
struct PointTraits;

/// Trait for a scalar valued point.
///
/// Mathematically, we consider a point an element of a "vector space". In this
/// case, the vector space is one-dimensional.
template <concepts::ScalarType TPoint>
struct PointTraits<TPoint> {
/// Scalar type
using Scalar = TPoint;

/// Is floating point number?
static bool constexpr kIsFloatingPoint = std::is_floating_point_v<Scalar>;
/// Is integer number?
static bool constexpr kIsInteger = std::is_integral_v<Scalar>;

/// number of rows - this is a scalar hence always 1
static int constexpr kRows = 1;
/// number of columns - this is a scalar hence always 1
static int constexpr kCols = 1;

/// Point set contains infinity?
static bool constexpr kHasInfinity =
std::numeric_limits<Scalar>::has_infinity;
/// Point set contains quite NAN?
static bool constexpr kHasQuietNan =
std::numeric_limits<Scalar>::has_quiet_NaN;
/// Point set contains signaling NAN?
static bool constexpr kHasSignalingNan =
std::numeric_limits<Scalar>::has_signaling_NaN;

/// Lowest value (e.g. typically large negative number)
static TPoint lowest() { return std::numeric_limits<Scalar>::lowest(); };
/// Smallest positive value
static TPoint min() { return std::numeric_limits<Scalar>::min(); };
/// Greatest value
static TPoint max() { return std::numeric_limits<Scalar>::max(); };
};

/// Trait for a multi-dimensional point.
///
/// Mathematically, we consider a point an element of a "vector space".
Expand Down Expand Up @@ -106,4 +69,30 @@ struct PointTraits<TPoint> {
/// ... plus a bunch more if we need them
};

// BEGIN(exclude from doxygen) \cond HIDDEN_SYMBOLS

// Single scalar specialization (1-dim case) of PointTraits
template <concepts::ScalarType TPoint>
struct PointTraits<TPoint> {
using Scalar = TPoint;

static bool constexpr kIsFloatingPoint = std::is_floating_point_v<Scalar>;
static bool constexpr kIsInteger = std::is_integral_v<Scalar>;

static int constexpr kRows = 1;
static int constexpr kCols = 1;

static bool constexpr kHasInfinity =
std::numeric_limits<Scalar>::has_infinity;
static bool constexpr kHasQuietNan =
std::numeric_limits<Scalar>::has_quiet_NaN;
static bool constexpr kHasSignalingNan =
std::numeric_limits<Scalar>::has_signaling_NaN;

static TPoint lowest() { return std::numeric_limits<Scalar>::lowest(); };
static TPoint min() { return std::numeric_limits<Scalar>::min(); };
static TPoint max() { return std::numeric_limits<Scalar>::max(); };
};
// END(exclude from doxygen) \endcond

} // namespace sophus
1 change: 1 addition & 0 deletions cpp/sophus/manifold/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ set(sophus_manifold_src_prefixes
product_manifold
quaternion
unit_vector
vector_manifold
)

set(sophus_manifold_h)
Expand Down
65 changes: 65 additions & 0 deletions cpp/sophus/manifold/complex.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,45 +13,66 @@

namespace sophus {

/// Generic complex number implementation
///
/// Impl class without any storage, but only static methods.
template <class TScalar>
class ComplexImpl {
public:
/// The underlying scalar type.
using Scalar = TScalar;
/// A complex number is a tuple.
static int constexpr kNumParams = 2;
/// Complex multiplication is commutative (and it is a field itself).
static bool constexpr kIsCommutative = true;

/// Parameter storage type - to be passed to static functions.
using Params = Eigen::Vector<Scalar, kNumParams>;

/// Return type of binary operator
///
/// In particular relevant mixing different scalars (such as double and
/// ceres::Jet).
template <class TCompatibleScalar>
using ParamsReturn = Eigen::Vector<
typename Eigen::ScalarBinaryOpTraits<Scalar, TCompatibleScalar>::
ReturnType,
2>;

// factories

/// Returns zero constant which is (0, 0).
static auto zero() -> Eigen::Vector<Scalar, 2> {
return Eigen::Vector<Scalar, 2>::Zero();
}

/// Returns one constant which is (1, 0).
static auto one() -> Eigen::Vector<Scalar, 2> {
return Eigen::Vector<Scalar, 2>(1.0, 0.0);
}

/// There are no particular constraints on the complex space and this function
/// returns always true.
static auto areParamsValid(Params const& /*unused*/)
-> sophus::Expected<Success> {
return sophus::Expected<Success>{};
}

/// Returns examples of valid parameters.
static auto paramsExamples() -> std::vector<Params> {
return pointExamples<Scalar, 2>();
}

/// Since there are no invalid parameters, this return an empty list.
static auto invalidParamsExamples() -> std::vector<Params> {
return std::vector<Params>({});
}

// operations

/// Complex addition given two complex numbers (a,i) and (b,j).
///
/// Returns (a+b, i+j).
template <class TCompatibleScalar>
static auto addition(
Eigen::Vector<Scalar, 2> const& lhs_real_imag,
Expand All @@ -60,6 +81,9 @@ class ComplexImpl {
return lhs_real_imag + rhs_real_imag;
}

/// Complex multiplication given two complex numbers (a,i) and (b,j).
///
/// Returns (a+b-i*j, a*j+b*i).
template <class TCompatibleScalar>
static auto multiplication(
Eigen::Vector<Scalar, 2> const& lhs_real_imag,
Expand All @@ -73,93 +97,134 @@ class ComplexImpl {
lhs_real_imag.y() * rhs_real_imag.x());
}

/// Given input (a,i), return complex conjugate (a, -i).
static auto conjugate(Eigen::Vector<Scalar, 2> const& a)
-> Eigen::Vector<Scalar, 2> {
return Eigen::Vector<Scalar, 2>(a.x(), -a.y());
}

/// Given input (a,i) return complex inverse (a, -i) / (a**2 + i**2).
static auto inverse(Eigen::Vector<Scalar, 2> const& real_imag)
-> Eigen::Vector<Scalar, 2> {
return conjugate(real_imag) / squaredNorm(real_imag);
}

/// Given input (a,i), returns complex norm sqrt(a**2 + i**2).
static auto norm(Eigen::Vector<Scalar, 2> const& real_imag) -> Scalar {
using std::hypot;
return hypot(real_imag.x(), real_imag.y());
}

/// Given input (a,i), returns square of complex norm a**2 + i**2.
static auto squaredNorm(Eigen::Vector<Scalar, 2> const& real_imag) -> Scalar {
return real_imag.squaredNorm();
}
};

/// Complex number class template.
///
/// A complex number is manifold with additional structure. In particular,
/// it is - like the quaternion numbers - a division ring and fulfills the
/// sophus::concepts::DivisionRingConcept. Furthermore, it is has commutative
/// multiplication (as opposed to the quaternion numbers) and hence is a field.
/// The complex numbers are the only other field of real numbers in addition to
/// the real numbers itself.
template <class TScalar>
class Complex {
public:
/// The underlying scalar type.
using Scalar = TScalar;
/// Type of the imaginary part is also a Scalar and hence has the some type
/// than the real part.
using Imag = Scalar;
/// The stateless implementation.
using Impl = ComplexImpl<Scalar>;

/// A complex number is a tuple.
static int constexpr kNumParams = 2;

/// Parameter storage type.
using Params = Eigen::Vector<Scalar, kNumParams>;

/// Return type of binary operator
///
/// In particular relevant mixing different scalars (such as double and
/// ceres::Jet).
template <class TCompatibleScalar>
using ComplexReturn =
Complex<typename Eigen::ScalarBinaryOpTraits<Scalar, TCompatibleScalar>::
ReturnType>;

// constructors and factories

/// Default constructor creates a zero complex number (0, 0).
Complex() : params_(Impl::zero()) {}

/// Copy constructor
Complex(Complex const&) = default;
/// Copy assignment
auto operator=(Complex const&) -> Complex& = default;

/// Returns zero complex number (0, 0).
static auto zero() -> Complex { return Complex::fromParams(Impl::zero()); }

/// Returns identity complex number (1, 0).
static auto one() -> Complex { return Complex::fromParams(Impl::one()); }

/// Constructs complex number from params tuple.
static auto fromParams(Params const& params) -> Complex {
Complex z(UninitTag{});
z.setParams(params);
return z;
}

/// Returns params tuple.
[[nodiscard]] auto params() const -> Params const& { return params_; }

/// Set state using params tuple.
void setParams(Params const& params) { params_ = params; }

/// Returns reference to real scalar.
auto real() -> Scalar& { return params_[0]; }
/// Returns reference to real scalar.
[[nodiscard]] auto real() const -> Scalar const& { return params_[0]; }

/// Returns reference to imaginary scalar.
auto imag() -> Scalar& { return params_[1]; }
/// Returns reference to imaginary scalar.
[[nodiscard]] auto imag() const -> Scalar const& { return params_[1]; }

/// Complex addition
template <class TCompatibleScalar>
auto operator+(Complex<TCompatibleScalar> const& other) const
-> ComplexReturn<TCompatibleScalar> {
return Complex::fromParams(Impl::addition(this->params_, other.params()));
}

/// Complex multiplication
template <class TCompatibleScalar>
auto operator*(Complex<TCompatibleScalar> const& other) const
-> ComplexReturn<TCompatibleScalar> {
return ComplexReturn<TCompatibleScalar>::fromParams(
Impl::multiplication(this->params_, other.params()));
}

/// Complex conjugate
[[nodiscard]] auto conjugate() const -> Complex {
return Complex::fromParams(Impl::conjugate(this->params_));
}

/// Complex inverse
[[nodiscard]] auto inverse() const -> Complex {
return Complex::fromParams(Impl::inverse(this->params_));
}

/// Complex norm
[[nodiscard]] auto norm() const -> Scalar {
return Impl::norm(this->params_);
}

/// Square of complex norm
[[nodiscard]] auto squaredNorm() const -> Scalar {
return Impl::squaredNorm(this->params_);
}
Expand Down
Loading