This commit is contained in:
Ivan
2022-06-28 10:36:24 +03:00
commit e4c8529305
160 changed files with 59023 additions and 0 deletions

83
thirdparty/Sophus/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,83 @@
SET(PROJECT_NAME Sophus)
PROJECT(${PROJECT_NAME})
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
SET (CMAKE_VERBOSE_MAKEFILE ON)
# Release by default
# Turn on Debug with "-DCMAKE_BUILD_TYPE=Debug"
IF( NOT CMAKE_BUILD_TYPE )
SET( CMAKE_BUILD_TYPE Release )
ENDIF()
IF (CMAKE_COMPILER_IS_GNUCXX )
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG ")
ADD_DEFINITIONS("-Wall -Werror -Wno-unused-variable
-Wno-unused-but-set-variable -Wno-unknown-pragmas ")
ENDIF()
################################################################################
# Add local path for finding packages, set the local version first
set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" )
list( APPEND CMAKE_MODULE_PATH "${CMAKE_ROOT}/Modules" )
################################################################################
# Create variables used for exporting in SophusConfig.cmake
set( Sophus_LIBRARIES "" )
set( Sophus_INCLUDE_DIR ${PROJECT_SOURCE_DIR} )
################################################################################
include(FindEigen3.cmake)
#find_package( Eigen3 REQUIRED )
INCLUDE_DIRECTORIES( ${EIGEN3_INCLUDE_DIR} )
SET( Sophus_INCLUDE_DIR ${Sophus_INCLUDE_DIR} ${EIGEN3_INCLUDE_DIR} )
SET (SOURCE_DIR "sophus")
SET (TEMPLATES tests
so2
se2
so3
se3
rxso3
sim3
)
SET (SOURCES ${SOURCE_DIR}/sophus.hpp)
FOREACH(templ ${TEMPLATES})
LIST(APPEND SOURCES ${SOURCE_DIR}/${templ}.hpp)
ENDFOREACH(templ)
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
# Added ${SOURCES} to executables so they show up in QtCreator (and possibly
# other IDEs).
# ADD_EXECUTABLE(test_so2 sophus/test_so2.cpp ${SOURCES})
# ADD_EXECUTABLE(test_se2 sophus/test_se2.cpp ${SOURCES})
# ADD_EXECUTABLE(test_so3 sophus/test_so3.cpp ${SOURCES})
# ADD_EXECUTABLE(test_se3 sophus/test_se3.cpp ${SOURCES})
# ADD_EXECUTABLE(test_rxso3 sophus/test_rxso3.cpp ${SOURCES})
# ADD_EXECUTABLE(test_sim3 sophus/test_sim3.cpp ${SOURCES})
# ENABLE_TESTING()
#
# ADD_TEST(test_so2 test_so2)
# ADD_TEST(test_se2 test_se2)
# ADD_TEST(test_so3 test_so3)
# ADD_TEST(test_se3 test_se3)
# ADD_TEST(test_rxso3 test_rxso3)
# ADD_TEST(test_sim3 test_sim3)
################################################################################
# Create the SophusConfig.cmake file for other cmake projects.
CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/SophusConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/SophusConfig.cmake @ONLY IMMEDIATE )
export( PACKAGE Sophus )
INSTALL(DIRECTORY sophus DESTINATION ${CMAKE_INSTALL_PREFIX}/include
FILES_MATCHING PATTERN "*.hpp" )

81
thirdparty/Sophus/FindEigen3.cmake vendored Normal file
View File

@@ -0,0 +1,81 @@
# - Try to find Eigen3 lib
#
# This module supports requiring a minimum version, e.g. you can do
# find_package(Eigen3 3.1.2)
# to require version 3.1.2 or newer of Eigen3.
#
# Once done this will define
#
# EIGEN3_FOUND - system has eigen lib with correct version
# EIGEN3_INCLUDE_DIR - the eigen include directory
# EIGEN3_VERSION - eigen version
# Copyright (c) 2006, 2007 Montel Laurent, <montel@kde.org>
# Copyright (c) 2008, 2009 Gael Guennebaud, <g.gael@free.fr>
# Copyright (c) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
# Redistribution and use is allowed according to the terms of the 2-clause BSD license.
if(NOT Eigen3_FIND_VERSION)
if(NOT Eigen3_FIND_VERSION_MAJOR)
set(Eigen3_FIND_VERSION_MAJOR 2)
endif(NOT Eigen3_FIND_VERSION_MAJOR)
if(NOT Eigen3_FIND_VERSION_MINOR)
set(Eigen3_FIND_VERSION_MINOR 91)
endif(NOT Eigen3_FIND_VERSION_MINOR)
if(NOT Eigen3_FIND_VERSION_PATCH)
set(Eigen3_FIND_VERSION_PATCH 0)
endif(NOT Eigen3_FIND_VERSION_PATCH)
set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}")
endif(NOT Eigen3_FIND_VERSION)
macro(_eigen3_check_version)
file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header)
string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}")
set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}")
string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}")
set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}")
string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}")
set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}")
set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION})
if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
set(EIGEN3_VERSION_OK FALSE)
else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
set(EIGEN3_VERSION_OK TRUE)
endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
if(NOT EIGEN3_VERSION_OK)
message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, "
"but at least version ${Eigen3_FIND_VERSION} is required")
endif(NOT EIGEN3_VERSION_OK)
endmacro(_eigen3_check_version)
if (EIGEN3_INCLUDE_DIR)
# in cache already
_eigen3_check_version()
set(EIGEN3_FOUND ${EIGEN3_VERSION_OK})
else (EIGEN3_INCLUDE_DIR)
find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library
PATHS
${CMAKE_INSTALL_PREFIX}/include
${KDE4_INCLUDE_DIR}
PATH_SUFFIXES eigen3 eigen
)
if(EIGEN3_INCLUDE_DIR)
_eigen3_check_version()
endif(EIGEN3_INCLUDE_DIR)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK)
mark_as_advanced(EIGEN3_INCLUDE_DIR)
endif(EIGEN3_INCLUDE_DIR)

19
thirdparty/Sophus/README vendored Normal file
View File

@@ -0,0 +1,19 @@
Sophus (version 0.9a)
C++ implementation of Lie Groups using Eigen.
Thanks to Steven Lovegrove, Sophus is now fully templated - using the Curiously Recurring Template Pattern (CRTP).
(In order to go back to the non-templated/double-only version "git checkout a621ff".)
Installation guide:
>>>
cd Sophus
mkdir build
cd build
cmake ..
make
<<<

11
thirdparty/Sophus/SophusConfig.cmake.in vendored Normal file
View File

@@ -0,0 +1,11 @@
################################################################################
# Sophus source dir
set( Sophus_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@")
################################################################################
# Sophus build dir
set( Sophus_DIR "@CMAKE_CURRENT_BINARY_DIR@")
################################################################################
set( Sophus_INCLUDE_DIR "@Sophus_INCLUDE_DIR@" )
set( Sophus_INCLUDE_DIRS "@Sophus_INCLUDE_DIR@" )

View File

@@ -0,0 +1,26 @@
# - Try to find Eigen3 lib
# Once done this will define
#
# EIGEN3_FOUND - system has eigen lib
# EIGEN3_INCLUDE_DIR - the eigen include directory
# Copyright (c) 2006, 2007 Montel Laurent, <montel@kde.org>
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
if( EIGEN3_INCLUDE_DIR )
# in cache already
set( EIGEN3_FOUND TRUE )
else (EIGEN3_INCLUDE_DIR)
find_path( EIGEN3_INCLUDE_DIR NAMES Eigen/Core
PATH_SUFFIXES eigen3/
HINTS
${INCLUDE_INSTALL_DIR}
/usr/local/include
${KDE4_INCLUDE_DIR}
)
include( FindPackageHandleStandardArgs )
find_package_handle_standard_args( Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR )
mark_as_advanced( EIGEN3_INCLUDE_DIR )
endif(EIGEN3_INCLUDE_DIR)

838
thirdparty/Sophus/sophus/rxso3.hpp vendored Normal file
View File

@@ -0,0 +1,838 @@
// This file is part of Sophus.
//
// Copyright 2012-2013 Hauke Strasdat
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#ifndef SOPHUS_RXSO3_HPP
#define RXSO3_HPP
#include "sophus.hpp"
#include "so3.hpp"
////////////////////////////////////////////////////////////////////////////
// Forward Declarations / typedefs
////////////////////////////////////////////////////////////////////////////
namespace Sophus {
template<typename _Scalar, int _Options=0> class RxSO3Group;
typedef RxSO3Group<double> ScSO3 EIGEN_DEPRECATED;
typedef RxSO3Group<double> RxSO3d; /**< double precision RxSO3 */
typedef RxSO3Group<float> RxSO3f; /**< single precision RxSO3 */
}
////////////////////////////////////////////////////////////////////////////
// Eigen Traits (For querying derived types in CRTP hierarchy)
////////////////////////////////////////////////////////////////////////////
namespace Eigen {
namespace internal {
template<typename _Scalar, int _Options>
struct traits<Sophus::RxSO3Group<_Scalar,_Options> > {
typedef _Scalar Scalar;
typedef Quaternion<Scalar> QuaternionType;
};
template<typename _Scalar, int _Options>
struct traits<Map<Sophus::RxSO3Group<_Scalar>, _Options> >
: traits<Sophus::RxSO3Group<_Scalar, _Options> > {
typedef _Scalar Scalar;
typedef Map<Quaternion<Scalar>,_Options> QuaternionType;
};
template<typename _Scalar, int _Options>
struct traits<Map<const Sophus::RxSO3Group<_Scalar>, _Options> >
: traits<const Sophus::RxSO3Group<_Scalar, _Options> > {
typedef _Scalar Scalar;
typedef Map<const Quaternion<Scalar>,_Options> QuaternionType;
};
}
}
namespace Sophus {
using namespace Eigen;
class ScaleNotPositive : public SophusException {
public:
ScaleNotPositive ()
: SophusException("Scale factor is not positive") {
}
};
/**
* \brief RxSO3 base type - implements RxSO3 class but is storage agnostic
*
* This class implements the group \f$ R^{+} \times SO3 \f$ (RxSO3), the direct
* product of the group of positive scalar matrices (=isomorph to the positive
* real numbers) and the three-dimensional special orthogonal group SO3.
* Geometrically, it is the group of rotation and scaling in three dimensions.
* As a matrix groups, RxSO3 consists of matrices of the form \f$ s\cdot R \f$
* where \f$ R \f$ is an orthognal matrix with \f$ det(R)=1 \f$ and \f$ s>0 \f$
* be a positive real number.
*
* Internally, RxSO3 is represented by the group of non-zero quaternions. This
* is a most compact representation since the degrees of freedom (DoF) of RxSO3
* (=4) equals the number of internal parameters (=4).
*
* [add more detailed description/tutorial]
*/
template<typename Derived>
class RxSO3GroupBase {
public:
/** \brief scalar type, use with care since this might be a Map type */
typedef typename internal::traits<Derived>::Scalar Scalar;
/** \brief quaternion reference type */
typedef typename internal::traits<Derived>::QuaternionType &
QuaternionReference;
/** \brief quaternion const reference type */
typedef const typename internal::traits<Derived>::QuaternionType &
ConstQuaternionReference;
/** \brief degree of freedom of group
* (three for rotation and one for scaling) */
static const int DoF = 4;
/** \brief number of internal parameters used
* (quaternion for rotation and scaling) */
static const int num_parameters = 4;
/** \brief group transformations are NxN matrices */
static const int N = 3;
/** \brief group transfomation type */
typedef Matrix<Scalar,N,N> Transformation;
/** \brief point type */
typedef Matrix<Scalar,3,1> Point;
/** \brief tangent vector type */
typedef Matrix<Scalar,DoF,1> Tangent;
/** \brief adjoint transformation type */
typedef Matrix<Scalar,DoF,DoF> Adjoint;
/**
* \brief Adjoint transformation
*
* This function return the adjoint transformation \f$ Ad \f$ of the
* group instance \f$ A \f$ such that for all \f$ x \f$
* it holds that \f$ \widehat{Ad_A\cdot x} = A\widehat{x}A^{-1} \f$
* with \f$\ \widehat{\cdot} \f$ being the hat()-operator.
*
* For RxSO3, it simply returns the rotation matrix corresponding to
* \f$ A \f$.
*/
inline
const Adjoint Adj() const {
Adjoint res;
res.setIdentity();
res.template topLeftCorner<3,3>() = rotationMatrix();
return res;
}
/**
* \returns copy of instance casted to NewScalarType
*/
template<typename NewScalarType>
inline RxSO3Group<NewScalarType> cast() const {
return RxSO3Group<NewScalarType>(quaternion()
.template cast<NewScalarType>() );
}
/**
* \returns pointer to internal data
*
* This provides direct read/write access to internal data. RxSO3 is
* represented by an Eigen::Quaternion (four parameters).
*
* Note: The first three Scalars represent the imaginary parts, while the
* forth Scalar represent the real part.
*/
inline Scalar* data() {
return quaternion().coeffs().data();
}
/**
* \returns const pointer to internal data
*
* Const version of data().
*/
inline const Scalar* data() const {
return quaternion().coeffs().data();
}
/**
* \brief In-place group multiplication
*
* Same as operator*=() for RxSO3.
*
* \see operator*=()
*/
inline
void fastMultiply(const RxSO3Group<Scalar>& other) {
quaternion() *= other.quaternion();
}
/**
* \returns group inverse of instance
*/
inline
const RxSO3Group<Scalar> inverse() const {
if(quaternion().squaredNorm() <= static_cast<Scalar>(0)) {
throw ScaleNotPositive();
}
return RxSO3Group<Scalar>(quaternion().inverse());
}
/**
* \brief Logarithmic map
*
* \returns tangent space representation (=rotation vector) of instance
*
* \see log().
*/
inline
const Tangent log() const {
return RxSO3Group<Scalar>::log(*this);
}
/**
* \returns 3x3 matrix representation of instance
*
* For RxSO3, the matrix representation is a scaled orthogonal
* matrix \f$ sR \f$ with \f$ det(sR)=s^3 \f$, thus a scaled rotation
* matrix \f$ R \f$ with scale s.
*/
inline
const Transformation matrix() const {
//ToDO: implement this directly!
Scalar scale = quaternion().norm();
Quaternion<Scalar> norm_quad = quaternion();
norm_quad.coeffs() /= scale;
return scale*norm_quad.toRotationMatrix();
}
/**
* \brief Assignment operator
*/
template<typename OtherDerived> inline
RxSO3GroupBase<Derived>& operator=
(const RxSO3GroupBase<OtherDerived> & other) {
quaternion() = other.quaternion();
return *this;
}
/**
* \brief Group multiplication
* \see operator*=()
*/
inline
const RxSO3Group<Scalar> operator*(const RxSO3Group<Scalar>& other) const {
RxSO3Group<Scalar> result(*this);
result *= other;
return result;
}
/**
* \brief Group action on \f$ \mathbf{R}^3 \f$
*
* \param p point \f$p \in \mathbf{R}^3 \f$
* \returns point \f$p' \in \mathbf{R}^3 \f$,
* rotated and scaled version of \f$p\f$
*
* This function rotates and scales a point \f$ p \f$ in \f$ \mathbf{R}^3 \f$
* by the RxSO3 transformation \f$sR\f$ (=rotation matrix)
* : \f$ p' = sR\cdot p \f$.
*/
inline
const Point operator*(const Point & p) const {
//ToDO: implement this directly!
Scalar scale = quaternion().norm();
Quaternion<Scalar> norm_quad = quaternion();
norm_quad.coeffs() /= scale;
return scale*norm_quad._transformVector(p);
}
/**
* \brief In-place group multiplication
* \see operator*=()
*/
inline
void operator*=(const RxSO3Group<Scalar>& other) {
quaternion() *= other.quaternion();
}
/**
* \brief Mutator of quaternion
*/
EIGEN_STRONG_INLINE
QuaternionReference quaternion() {
return static_cast<Derived*>(this)->quaternion();
}
/**
* \brief Accessor of quaternion
*/
EIGEN_STRONG_INLINE
ConstQuaternionReference quaternion() const {
return static_cast<const Derived*>(this)->quaternion();
}
/**
* \returns rotation matrix
*/
inline
Transformation rotationMatrix() const {
Scalar scale = quaternion().norm();
Quaternion<Scalar> norm_quad = quaternion();
norm_quad.coeffs() /= scale;
return norm_quad.toRotationMatrix();
}
/**
* \returns scale
*/
EIGEN_STRONG_INLINE
const Scalar scale() const {
return quaternion().norm();
}
/**
* \brief Setter of quaternion using rotation matrix, leaves scale untouched
*
* \param R a 3x3 rotation matrix
* \pre the 3x3 matrix should be orthogonal and have a determinant of 1
*/
inline
void setRotationMatrix(const Transformation & R) {
Scalar saved_scale = scale();
quaternion() = R;
quaternion().coeffs() *= saved_scale;
}
/**
* \brief Scale setter
*/
EIGEN_STRONG_INLINE
void setScale(const Scalar & scale) {
quaternion().normalize();
quaternion().coeffs() *= scale;
}
/**
* \brief Setter of quaternion using scaled rotation matrix
*
* \param sR a 3x3 scaled rotation matrix
* \pre the 3x3 matrix should be "scaled orthogonal"
* and have a positive determinant
*/
inline
void setScaledRotationMatrix
(const Transformation & sR) {
Transformation squared_sR = sR*sR.transpose();
Scalar squared_scale
= static_cast<Scalar>(1./3.)
*(squared_sR(0,0)+squared_sR(1,1)+squared_sR(2,2));
if (squared_scale <= static_cast<Scalar>(0)) {
throw ScaleNotPositive();
}
Scalar scale = std::sqrt(squared_scale);
if (scale <= static_cast<Scalar>(0)) {
throw ScaleNotPositive();
}
quaternion() = sR/scale;
quaternion().coeffs() *= scale;
}
////////////////////////////////////////////////////////////////////////////
// public static functions
////////////////////////////////////////////////////////////////////////////
/**
* \param b 4-vector representation of Lie algebra element
* \returns derivative of Lie bracket
*
* This function returns \f$ \frac{\partial}{\partial a} [a, b]_{rxso3} \f$
* with \f$ [a, b]_{rxso3} \f$ being the lieBracket() of the Lie
* algebra rxso3.
*
* \see lieBracket()
*/
inline static
const Adjoint d_lieBracketab_by_d_a(const Tangent & b) {
Adjoint res;
res.setZero();
res.template topLeftCorner<3,3>() = -SO3::hat(b.template head<3>());
return res;
}
/**
* \brief Group exponential
*
* \param a tangent space element
* (rotation vector \f$ \omega \f$ and logarithm of scale)
* \returns corresponding element of the group RxSO3
*
* To be more specific, this function computes \f$ \exp(\widehat{a}) \f$
* with \f$ \exp(\cdot) \f$ being the matrix exponential
* and \f$ \widehat{\cdot} \f$ the hat()-operator of RxSO3.
*
* \see expAndTheta()
* \see hat()
* \see log()
*/
inline static
const RxSO3Group<Scalar> exp(const Tangent & a) {
Scalar theta;
return expAndTheta(a, &theta);
}
/**
* \brief Group exponential and theta
*
* \param a tangent space element
* (rotation vector \f$ \omega \f$ and logarithm of scale )
* \param[out] theta angle of rotation \f$ \theta = |\omega| \f$
* \returns corresponding element of the group RxSO3
*
* \see exp() for details
*/
inline static
const RxSO3Group<Scalar> expAndTheta(const Tangent & a,
Scalar * theta) {
const Matrix<Scalar,3,1> & omega = a.template head<3>();
Scalar sigma = a[3];
Scalar scale = std::exp(sigma);
Quaternion<Scalar> quat
= SO3Group<Scalar>::expAndTheta(omega, theta).unit_quaternion();
quat.coeffs() *= scale;
return RxSO3Group<Scalar>(quat);
}
/**
* \brief Generators
*
* \pre \f$ i \in \{0,1,2,3\} \f$
* \returns \f$ i \f$th generator \f$ G_i \f$ of RxSO3
*
* The infinitesimal generators of RxSO3
* are \f$
* G_0 = \left( \begin{array}{ccc}
* 0& 0& 0& \\
* 0& 0& -1& \\
* 0& 1& 0&
* \end{array} \right),
* G_1 = \left( \begin{array}{ccc}
* 0& 0& 1& \\
* 0& 0& 0& \\
* -1& 0& 0&
* \end{array} \right),
* G_2 = \left( \begin{array}{ccc}
* 0& -1& 0& \\
* 1& 0& 0& \\
* 0& 0& 0&
* \end{array} \right),
* G_3 = \left( \begin{array}{ccc}
* 1& 0& 0& \\
* 0& 1& 0& \\
* 0& 0& 1&
* \end{array} \right).
* \f$
* \see hat()
*/
inline static
const Transformation generator(int i) {
if (i<0 || i>3) {
throw SophusException("i is not in range [0,3].");
}
Tangent e;
e.setZero();
e[i] = static_cast<Scalar>(1);
return hat(e);
}
/**
* \brief hat-operator
*
* \param a 4-vector representation of Lie algebra element
* \returns 3x3-matrix representatin of Lie algebra element
*
* Formally, the hat-operator of RxSO3 is defined
* as \f$ \widehat{\cdot}: \mathbf{R}^4 \rightarrow \mathbf{R}^{3\times 3},
* \quad \widehat{a} = \sum_{i=0}^3 G_i a_i \f$
* with \f$ G_i \f$ being the ith infinitesial generator().
*
* \see generator()
* \see vee()
*/
inline static
const Transformation hat(const Tangent & a) {
Transformation A;
A << a(3), -a(2), a(1)
, a(2), a(3), -a(0)
,-a(1), a(0), a(3);
return A;
}
/**
* \brief Lie bracket
*
* \param a 4-vector representation of Lie algebra element
* \param b 4-vector representation of Lie algebra element
* \returns 4-vector representation of Lie algebra element
*
* It computes the bracket of RxSO3. To be more specific, it
* computes \f$ [a, 2]_{rxso3}
* := [\widehat{a}, \widehat{b}]^\vee \f$
* with \f$ [A,B] = AB-BA \f$ being the matrix
* commutator, \f$ \widehat{\cdot} \f$ the
* hat()-operator and \f$ (\cdot)^\vee \f$ the vee()-operator of RxSO3.
*
* \see hat()
* \see vee()
*/
inline static
const Tangent lieBracket(const Tangent & a,
const Tangent & b) {
const Matrix<Scalar,3,1> & omega1 = a.template head<3>();
const Matrix<Scalar,3,1> & omega2 = b.template head<3>();
Matrix<Scalar,4,1> res;
res.template head<3>() = omega1.cross(omega2);
res[3] = static_cast<Scalar>(0);
return res;
}
/**
* \brief Logarithmic map
*
* \param other element of the group RxSO3
* \returns corresponding tangent space element
* (rotation vector \f$ \omega \f$ and logarithm of scale)
*
* Computes the logarithmic, the inverse of the group exponential.
* To be specific, this function computes \f$ \log({\cdot})^\vee \f$
* with \f$ \vee(\cdot) \f$ being the matrix logarithm
* and \f$ \vee{\cdot} \f$ the vee()-operator of RxSO3.
*
* \see exp()
* \see logAndTheta()
* \see vee()
*/
inline static
const Tangent log(const RxSO3Group<Scalar> & other) {
Scalar theta;
return logAndTheta(other, &theta);
}
/**
* \brief Logarithmic map and theta
*
* \param other element of the group RxSO3
* \param[out] theta angle of rotation \f$ \theta = |\omega| \f$
* \returns corresponding tangent space element
* (rotation vector \f$ \omega \f$ and logarithm of scale)
*
* \see log() for details
*/
inline static
const Tangent logAndTheta(const RxSO3Group<Scalar> & other,
Scalar * theta) {
const Scalar & scale = other.quaternion().norm();
Tangent omega_sigma;
omega_sigma[3] = std::log(scale);
omega_sigma.template head<3>()
= SO3Group<Scalar>::logAndTheta(SO3Group<Scalar>(other.quaternion()),
theta);
return omega_sigma;
}
/**
* \brief vee-operator
*
* \param Omega 3x3-matrix representation of Lie algebra element
* \returns 4-vector representatin of Lie algebra element
*
* This is the inverse of the hat()-operator.
*
* \see hat()
*/
inline static
const Tangent vee(const Transformation & Omega) {
return Tangent( static_cast<Scalar>(0.5) * (Omega(2,1) - Omega(1,2)),
static_cast<Scalar>(0.5) * (Omega(0,2) - Omega(2,0)),
static_cast<Scalar>(0.5) * (Omega(1,0) - Omega(0,1)),
static_cast<Scalar>(1./3.)
* (Omega(0,0) + Omega(1,1) + Omega(2,2)) );
}
};
/**
* \brief RxSO3 default type - Constructors and default storage for RxSO3 Type
*/
template<typename _Scalar, int _Options>
class RxSO3Group : public RxSO3GroupBase<RxSO3Group<_Scalar,_Options> > {
typedef RxSO3GroupBase<RxSO3Group<_Scalar,_Options> > Base;
public:
/** \brief scalar type */
typedef typename internal::traits<SO3Group<_Scalar,_Options> >
::Scalar Scalar;
/** \brief quaternion reference type */
typedef typename internal::traits<SO3Group<_Scalar,_Options> >
::QuaternionType & QuaternionReference;
/** \brief quaternion const reference type */
typedef const typename internal::traits<SO3Group<_Scalar,_Options> >
::QuaternionType & ConstQuaternionReference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
/**
* \brief Default constructor
*
* Initialize Quaternion to identity rotation and scale.
*/
inline RxSO3Group()
: quaternion_(static_cast<Scalar>(1), static_cast<Scalar>(0),
static_cast<Scalar>(0), static_cast<Scalar>(0)) {
}
/**
* \brief Copy constructor
*/
template<typename OtherDerived> inline
RxSO3Group(const RxSO3GroupBase<OtherDerived> & other)
: quaternion_(other.quaternion()) {
}
/**
* \brief Constructor from scaled rotation matrix
*
* \pre matrix need to be "scaled orthogonal" with positive determinant
*/
inline explicit
RxSO3Group(const Transformation & sR) {
this->setScaledRotationMatrix(sR);
}
/**
* \brief Constructor from scale factor and rotation matrix
*
* \pre rotation matrix need to be orthogonal with determinant of 1
* \pre scale need to be not zero
*/
inline
RxSO3Group(const Scalar & scale, const Transformation & R)
: quaternion_(R) {
if(scale <= static_cast<Scalar>(0)) {
throw ScaleNotPositive();
}
quaternion_.normalize();
quaternion_.coeffs() *= scale;
}
/**
* \brief Constructor from scale factor and SO3
*
* \pre scale need to be not zero
*/
inline
RxSO3Group(const Scalar & scale, const SO3Group<Scalar> & so3)
: quaternion_(so3.unit_quaternion()) {
if (scale <= static_cast<Scalar>(0)) {
throw ScaleNotPositive();
}
quaternion_.normalize();
quaternion_.coeffs() *= scale;
}
/**
* \brief Constructor from quaternion
*
* \pre quaternion must not be zero
*/
inline explicit
RxSO3Group(const Quaternion<Scalar> & quat) : quaternion_(quat) {
if(quaternion_.squaredNorm() <= SophusConstants<Scalar>::epsilon()) {
throw ScaleNotPositive();
}
}
/**
* \brief Mutator of quaternion
*/
EIGEN_STRONG_INLINE
QuaternionReference quaternion() {
return quaternion_;
}
/**
* \brief Accessor of quaternion
*/
EIGEN_STRONG_INLINE
ConstQuaternionReference quaternion() const {
return quaternion_;
}
protected:
Quaternion<Scalar> quaternion_;
};
} // end namespace
namespace Eigen {
/**
* \brief Specialisation of Eigen::Map for RxSO3GroupBase
*
* Allows us to wrap RxSO3 Objects around POD array
* (e.g. external c style quaternion)
*/
template<typename _Scalar, int _Options>
class Map<Sophus::RxSO3Group<_Scalar>, _Options>
: public Sophus::RxSO3GroupBase<
Map<Sophus::RxSO3Group<_Scalar>,_Options> > {
typedef Sophus::RxSO3GroupBase<Map<Sophus::RxSO3Group<_Scalar>, _Options> >
Base;
public:
/** \brief scalar type */
typedef typename internal::traits<Map>::Scalar Scalar;
/** \brief quaternion reference type */
typedef typename internal::traits<Map>::QuaternionType &
QuaternionReference;
/** \brief quaternion const reference type */
typedef const typename internal::traits<Map>::QuaternionType &
ConstQuaternionReference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
using Base::operator*=;
using Base::operator*;
EIGEN_STRONG_INLINE
Map(Scalar* coeffs) : quaternion_(coeffs) {
}
/**
* \brief Mutator of quaternion
*/
EIGEN_STRONG_INLINE
QuaternionReference quaternion() {
return quaternion_;
}
/**
* \brief Accessor of quaternion
*/
EIGEN_STRONG_INLINE
ConstQuaternionReference quaternion() const {
return quaternion_;
}
protected:
Map<Quaternion<Scalar>,_Options> quaternion_;
};
/**
* \brief Specialisation of Eigen::Map for const RxSO3GroupBase
*
* Allows us to wrap RxSO3 Objects around POD array
* (e.g. external c style quaternion)
*/
template<typename _Scalar, int _Options>
class Map<const Sophus::RxSO3Group<_Scalar>, _Options>
: public Sophus::RxSO3GroupBase<
Map<const Sophus::RxSO3Group<_Scalar>, _Options> > {
typedef Sophus::RxSO3GroupBase<
Map<const Sophus::RxSO3Group<_Scalar>, _Options> > Base;
public:
/** \brief scalar type */
typedef typename internal::traits<Map>::Scalar Scalar;
/** \brief quaternion const reference type */
typedef const typename internal::traits<Map>::QuaternionType &
ConstQuaternionReference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
using Base::operator*=;
using Base::operator*;
EIGEN_STRONG_INLINE
Map(const Scalar* coeffs) : quaternion_(coeffs) {
}
/**
* \brief Accessor of unit quaternion
*
* No direct write access is given to ensure the quaternion stays normalized.
*/
EIGEN_STRONG_INLINE
ConstQuaternionReference quaternion() const {
return quaternion_;
}
protected:
const Map<const Quaternion<Scalar>,_Options> quaternion_;
};
}
#endif // SOPHUS_RXSO3_HPP

907
thirdparty/Sophus/sophus/se2.hpp vendored Normal file
View File

@@ -0,0 +1,907 @@
// This file is part of Sophus.
//
// Copyright 2012-2013 Hauke Strasdat
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#ifndef SOPHUS_SE2_HPP
#define SOPHUS_SE2_HPP
#include "so2.hpp"
////////////////////////////////////////////////////////////////////////////
// Forward Declarations / typedefs
////////////////////////////////////////////////////////////////////////////
namespace Sophus {
template<typename _Scalar, int _Options=0> class SE2Group;
typedef SE2Group<double> SE2 EIGEN_DEPRECATED;
typedef SE2Group<double> SE2d; /**< double precision SE2 */
typedef SE2Group<float> SE2f; /**< single precision SE2 */
}
////////////////////////////////////////////////////////////////////////////
// Eigen Traits (For querying derived types in CRTP hierarchy)
////////////////////////////////////////////////////////////////////////////
namespace Eigen {
namespace internal {
template<typename _Scalar, int _Options>
struct traits<Sophus::SE2Group<_Scalar,_Options> > {
typedef _Scalar Scalar;
typedef Matrix<Scalar,2,1> TranslationType;
typedef Sophus::SO2Group<Scalar> SO2Type;
};
template<typename _Scalar, int _Options>
struct traits<Map<Sophus::SE2Group<_Scalar>, _Options> >
: traits<Sophus::SE2Group<_Scalar, _Options> > {
typedef _Scalar Scalar;
typedef Map<Matrix<Scalar,2,1>,_Options> TranslationType;
typedef Map<Sophus::SO2Group<Scalar>,_Options> SO2Type;
};
template<typename _Scalar, int _Options>
struct traits<Map<const Sophus::SE2Group<_Scalar>, _Options> >
: traits<const Sophus::SE2Group<_Scalar, _Options> > {
typedef _Scalar Scalar;
typedef Map<const Matrix<Scalar,2,1>,_Options> TranslationType;
typedef Map<const Sophus::SO2Group<Scalar>,_Options> SO2Type;
};
}
}
namespace Sophus {
using namespace Eigen;
using namespace std;
/**
* \brief SE2 base type - implements SE2 class but is storage agnostic
*
* [add more detailed description/tutorial]
*/
template<typename Derived>
class SE2GroupBase {
public:
/** \brief scalar type */
typedef typename internal::traits<Derived>::Scalar Scalar;
/** \brief translation reference type */
typedef typename internal::traits<Derived>::TranslationType &
TranslationReference;
/** \brief translation const reference type */
typedef const typename internal::traits<Derived>::TranslationType &
ConstTranslationReference;
/** \brief SO2 reference type */
typedef typename internal::traits<Derived>::SO2Type &
SO2Reference;
/** \brief SO2 type */
typedef const typename internal::traits<Derived>::SO2Type &
ConstSO2Reference;
/** \brief degree of freedom of group
* (two for translation, one for in-plane rotation) */
static const int DoF = 3;
/** \brief number of internal parameters used
* (unit complex number for rotation + translation 2-vector) */
static const int num_parameters = 4;
/** \brief group transformations are NxN matrices */
static const int N = 3;
/** \brief group transfomation type */
typedef Matrix<Scalar,N,N> Transformation;
/** \brief point type */
typedef Matrix<Scalar,2,1> Point;
/** \brief tangent vector type */
typedef Matrix<Scalar,DoF,1> Tangent;
/** \brief adjoint transformation type */
typedef Matrix<Scalar,DoF,DoF> Adjoint;
/**
* \brief Adjoint transformation
*
* This function return the adjoint transformation \f$ Ad \f$ of the
* group instance \f$ A \f$ such that for all \f$ x \f$
* it holds that \f$ \widehat{Ad_A\cdot x} = A\widehat{x}A^{-1} \f$
* with \f$\ \widehat{\cdot} \f$ being the hat()-operator.
*/
inline
const Adjoint Adj() const {
const Matrix<Scalar,2,2> & R = so2().matrix();
Transformation res;
res.setIdentity();
res.template topLeftCorner<2,2>() = R;
res(0,2) = translation()[1];
res(1,2) = -translation()[0];
return res;
}
/**
* \returns copy of instance casted to NewScalarType
*/
template<typename NewScalarType>
inline SE2Group<NewScalarType> cast() const {
return
SE2Group<NewScalarType>(so2().template cast<NewScalarType>(),
translation().template cast<NewScalarType>() );
}
/**
* \brief Fast group multiplication
*
* This method is a fast version of operator*=(), since it does not perform
* normalization. It is up to the user to call normalize() once in a while.
*
* \see operator*=()
*/
inline
void fastMultiply(const SE2Group<Scalar>& other) {
translation() += so2()*(other.translation());
so2().fastMultiply(other.so2());
}
/**
* \returns Group inverse of instance
*/
inline
const SE2Group<Scalar> inverse() const {
const SO2Group<Scalar> invR = so2().inverse();
return SE2Group<Scalar>(invR, invR*(translation()
*static_cast<Scalar>(-1) ) );
}
/**
* \brief Logarithmic map
*
* \returns tangent space representation
* (translational part and rotation angle) of instance
*
* \see log().
*/
inline
const Tangent log() const {
return log(*this);
}
/**
* \brief Normalize SO2 element
*
* It re-normalizes the SO2 element. This method only needs to
* be called in conjunction with fastMultiply() or data() write access.
*/
inline
void normalize() {
so2().normalize();
}
/**
* \returns 3x3 matrix representation of instance
*/
inline
const Transformation matrix() const {
Transformation homogenious_matrix;
homogenious_matrix.setIdentity();
homogenious_matrix.block(0,0,2,2) = rotationMatrix();
homogenious_matrix.col(2).head(2) = translation();
return homogenious_matrix;
}
/**
* \returns 2x3 matrix representation of instance
*
* It returns the three first row of matrix().
*/
inline
const Matrix<Scalar,2,3> matrix2x3() const {
Matrix<Scalar,2,3> matrix;
matrix.block(0,0,2,2) = rotationMatrix();
matrix.col(2) = translation();
return matrix;
}
/**
* \brief Assignment operator
*/
template<typename OtherDerived> inline
SE2GroupBase<Derived>& operator= (const SE2GroupBase<OtherDerived> & other) {
so2() = other.so2();
translation() = other.translation();
return *this;
}
/**
* \brief Group multiplication
* \see operator*=()
*/
inline
const SE2Group<Scalar> operator*(const SE2Group<Scalar>& other) const {
SE2Group<Scalar> result(*this);
result *= other;
return result;
}
/**
* \brief Group action on \f$ \mathbf{R}^2 \f$
*
* \param p point \f$p \in \mathbf{R}^2 \f$
* \returns point \f$p' \in \mathbf{R}^2 \f$,
* rotated and translated version of \f$p\f$
*
* This function rotates and translates point \f$ p \f$
* in \f$ \mathbf{R}^2 \f$ by the SE2 transformation \f$R,t\f$
* (=rotation matrix, translation vector): \f$ p' = R\cdot p + t \f$.
*/
inline
const Point operator*(const Point & p) const {
return so2()*p + translation();
}
/**
* \brief In-place group multiplication
*
* \see fastMultiply()
* \see operator*()
*/
inline
void operator*=(const SE2Group<Scalar>& other) {
fastMultiply(other);
normalize();
}
/**
* \returns Rotation matrix
*/
inline
const Matrix<Scalar,2,2> rotationMatrix() const {
return so2().matrix();
}
/**
* \brief Setter of internal unit complex number representation
*
* \param complex
* \pre the complex number must not be zero
*
* The complex number is normalized to unit length.
*/
inline
void setComplex(const Matrix<Scalar,2,1> & complex) {
return so2().setComplex(complex);
}
/**
* \brief Setter of unit complex number using rotation matrix
*
* \param R a 2x2 matrix
* \pre the 2x2 matrix should be orthogonal and have a determinant of 1
*/
inline
void setRotationMatrix(const Matrix<Scalar,2,2> & R) {
so2().setComplex(static_cast<Scalar>(0.5)*(R(0,0)+R(1,1)),
static_cast<Scalar>(0.5)*(R(1,0)-R(0,1)));
}
/**
* \brief Mutator of SO2 group
*/
EIGEN_STRONG_INLINE
SO2Reference so2() {
return static_cast<Derived*>(this)->so2();
}
/**
* \brief Accessor of SO2 group
*/
EIGEN_STRONG_INLINE
ConstSO2Reference so2() const {
return static_cast<const Derived*>(this)->so2();
}
/**
* \brief Mutator of translation vector
*/
EIGEN_STRONG_INLINE
TranslationReference translation() {
return static_cast<Derived*>(this)->translation();
}
/**
* \brief Accessor of translation vector
*/
EIGEN_STRONG_INLINE
ConstTranslationReference translation() const {
return static_cast<const Derived*>(this)->translation();
}
/**
* \brief Accessor of unit complex number
*
* No direct write access is given to ensure the complex number stays
* normalized.
*/
inline
typename internal::traits<Derived>::SO2Type::ConstComplexReference
unit_complex() const {
return so2().unit_complex();
}
////////////////////////////////////////////////////////////////////////////
// public static functions
////////////////////////////////////////////////////////////////////////////
/**
* \param b 3-vector representation of Lie algebra element
* \returns derivative of Lie bracket
*
* This function returns \f$ \frac{\partial}{\partial a} [a, b]_{se2} \f$
* with \f$ [a, b]_{se2} \f$ being the lieBracket() of the Lie algebra se2.
*
* \see lieBracket()
*/
inline static
const Transformation d_lieBracketab_by_d_a(const Tangent & b) {
static const Scalar zero = static_cast<Scalar>(0);
Matrix<Scalar,2,1> upsilon2 = b.template head<2>();
Scalar theta2 = b[2];
Transformation res;
res << zero, theta2, -upsilon2[1]
, -theta2, zero, upsilon2[0]
, zero, zero, zero;
return res;
}
/**
* \brief Group exponential
*
* \param a tangent space element (3-vector)
* \returns corresponding element of the group SE2
*
* The first two components of \f$ a \f$ represent the translational
* part \f$ \upsilon \f$ in the tangent space of SE2, while the last
* components of \f$ a \f$ is the rotation angle \f$ \theta \f$.
*
* To be more specific, this function computes \f$ \exp(\widehat{a}) \f$
* with \f$ \exp(\cdot) \f$ being the matrix exponential
* and \f$ \widehat{\cdot} \f$ the hat()-operator of SE2.
*
* \see hat()
* \see log()
*/
inline static
const SE2Group<Scalar> exp(const Tangent & a) {
Scalar theta = a[2];
const SO2Group<Scalar> & so2 = SO2Group<Scalar>::exp(theta);
Scalar sin_theta_by_theta;
Scalar one_minus_cos_theta_by_theta;
if(std::abs(theta)<SophusConstants<Scalar>::epsilon()) {
Scalar theta_sq = theta*theta;
sin_theta_by_theta
= static_cast<Scalar>(1.) - static_cast<Scalar>(1./6.)*theta_sq;
one_minus_cos_theta_by_theta
= static_cast<Scalar>(0.5)*theta
- static_cast<Scalar>(1./24.)*theta*theta_sq;
} else {
sin_theta_by_theta = so2.unit_complex().y()/theta;
one_minus_cos_theta_by_theta
= (static_cast<Scalar>(1.) - so2.unit_complex().x())/theta;
}
Matrix<Scalar,2,1> trans
(sin_theta_by_theta*a[0] - one_minus_cos_theta_by_theta*a[1],
one_minus_cos_theta_by_theta * a[0]+sin_theta_by_theta*a[1]);
return SE2Group<Scalar>(so2, trans);
}
/**
* \brief Generators
*
* \pre \f$ i \in \{0,1,2\} \f$
* \returns \f$ i \f$th generator \f$ G_i \f$ of SE2
*
* The infinitesimal generators of SE2 are: \f[
* G_0 = \left( \begin{array}{ccc}
* 0& 0& 1\\
* 0& 0& 0\\
* 0& 0& 0\\
* \end{array} \right),
* G_1 = \left( \begin{array}{cccc}
* 0& 0& 0\\
* 0& 0& 1\\
* 0& 0& 0\\
* \end{array} \right),
* G_2 = \left( \begin{array}{cccc}
* 0& 0& 0&\\
* 0& 0& -1&\\
* 0& 1& 0&\\
* \end{array} \right),
* \f]
* \see hat()
*/
inline static
const Transformation generator(int i) {
if (i<0 || i>2) {
throw SophusException("i is not in range [0,2].");
}
Tangent e;
e.setZero();
e[i] = static_cast<Scalar>(1);
return hat(e);
}
/**
* \brief hat-operator
*
* \param omega 3-vector representation of Lie algebra element
* \returns 3x3-matrix representatin of Lie algebra element
*
* Formally, the hat-operator of SE2 is defined
* as \f$ \widehat{\cdot}: \mathbf{R}^3 \rightarrow \mathbf{R}^{2\times 2},
* \quad \widehat{\omega} = \sum_{i=0}^2 G_i \omega_i \f$
* with \f$ G_i \f$ being the ith infinitesial generator().
*
* \see generator()
* \see vee()
*/
inline static
const Transformation hat(const Tangent & v) {
Transformation Omega;
Omega.setZero();
Omega.template topLeftCorner<2,2>() = SO2Group<Scalar>::hat(v[2]);
Omega.col(2).template head<2>() = v.template head<2>();
return Omega;
}
/**
* \brief Lie bracket
*
* \param a 3-vector representation of Lie algebra element
* \param b 3-vector representation of Lie algebra element
* \returns 3-vector representation of Lie algebra element
*
* It computes the bracket of SE2. To be more specific, it
* computes \f$ [a, b]_{se2}
* := [\widehat{a_1}, \widehat{b_2}]^\vee \f$
* with \f$ [A,B] = AB-BA \f$ being the matrix
* commutator, \f$ \widehat{\cdot} \f$ the
* hat()-operator and \f$ (\cdot)^\vee \f$ the vee()-operator of SE2.
*
* \see hat()
* \see vee()
*/
inline static
const Tangent lieBracket(const Tangent & a,
const Tangent & b) {
Matrix<Scalar,2,1> upsilon1 = a.template head<2>();
Matrix<Scalar,2,1> upsilon2 = b.template head<2>();
Scalar theta1 = a[2];
Scalar theta2 = b[2];
return Tangent(-theta1*upsilon2[1] + theta2*upsilon1[1],
theta1*upsilon2[0] - theta2*upsilon1[0],
static_cast<Scalar>(0));
}
/**
* \brief Logarithmic map
*
* \param other element of the group SE2
* \returns corresponding tangent space element
* (translational part \f$ \upsilon \f$
* and rotation vector \f$ \omega \f$)
*
* Computes the logarithmic, the inverse of the group exponential.
* To be specific, this function computes \f$ \log({\cdot})^\vee \f$
* with \f$ \vee(\cdot) \f$ being the matrix logarithm
* and \f$ \vee{\cdot} \f$ the vee()-operator of SE2.
*
* \see exp()
* \see vee()
*/
inline static
const Tangent log(const SE2Group<Scalar> & other) {
Tangent upsilon_theta;
const SO2Group<Scalar> & so2 = other.so2();
Scalar theta = SO2Group<Scalar>::log(so2);
upsilon_theta[2] = theta;
Scalar halftheta = static_cast<Scalar>(0.5)*theta;
Scalar halftheta_by_tan_of_halftheta;
const Matrix<Scalar,2,1> & z = so2.unit_complex();
Scalar real_minus_one = z.x()-static_cast<Scalar>(1.);
if (std::abs(real_minus_one)<SophusConstants<Scalar>::epsilon()) {
halftheta_by_tan_of_halftheta
= static_cast<Scalar>(1.)
- static_cast<Scalar>(1./12)*theta*theta;
} else {
halftheta_by_tan_of_halftheta
= -(halftheta*z.y())/(real_minus_one);
}
Matrix<Scalar,2,2> V_inv;
V_inv << halftheta_by_tan_of_halftheta, halftheta
, -halftheta, halftheta_by_tan_of_halftheta;
upsilon_theta.template head<2>() = V_inv*other.translation();
return upsilon_theta;
}
/**
* \brief vee-operator
*
* \param Omega 3x3-matrix representation of Lie algebra element
* \returns 3-vector representatin of Lie algebra element
*
* This is the inverse of the hat()-operator.
*
* \see hat()
*/
inline static
const Tangent vee(const Transformation & Omega) {
Tangent upsilon_omega;
upsilon_omega.template head<2>() = Omega.col(2).template head<2>();
upsilon_omega[2]
= SO2Group<Scalar>::vee(Omega.template topLeftCorner<2,2>());
return upsilon_omega;
}
};
/**
* \brief SE2 default type - Constructors and default storage for SE2 Type
*/
template<typename _Scalar, int _Options>
class SE2Group : public SE2GroupBase<SE2Group<_Scalar,_Options> > {
typedef SE2GroupBase<SE2Group<_Scalar,_Options> > Base;
public:
/** \brief scalar type */
typedef typename internal::traits<SE2Group<_Scalar,_Options> >
::Scalar Scalar;
/** \brief translation reference type */
typedef typename internal::traits<SE2Group<_Scalar,_Options> >
::TranslationType & TranslationReference;
typedef const typename internal::traits<SE2Group<_Scalar,_Options> >
::TranslationType & ConstTranslationReference;
/** \brief SO2 reference type */
typedef typename internal::traits<SE2Group<_Scalar,_Options> >
::SO2Type & SO2Reference;
/** \brief SO2 const reference type */
typedef const typename internal::traits<SE2Group<_Scalar,_Options> >
::SO2Type & ConstSO2Reference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
/**
* \brief Default constructor
*
* Initialize Complex to identity rotation and translation to zero.
*/
inline
SE2Group()
: translation_( Matrix<Scalar,2,1>::Zero() )
{
}
/**
* \brief Copy constructor
*/
template<typename OtherDerived> inline
SE2Group(const SE2GroupBase<OtherDerived> & other)
: so2_(other.so2()), translation_(other.translation()) {
}
/**
* \brief Constructor from SO2 and translation vector
*/
template<typename OtherDerived> inline
SE2Group(const SO2GroupBase<OtherDerived> & so2,
const Point & translation)
: so2_(so2), translation_(translation) {
}
/**
* \brief Constructor from rotation matrix and translation vector
*
* \pre rotation matrix need to be orthogonal with determinant of 1
*/
inline
SE2Group(const typename SO2Group<Scalar>::Transformation & rotation_matrix,
const Point & translation)
: so2_(rotation_matrix), translation_(translation) {
}
/**
* \brief Constructor from rotation angle and translation vector
*/
inline
SE2Group(const Scalar & theta,
const Point & translation)
: so2_(theta), translation_(translation) {
}
/**
* \brief Constructor from complex number and translation vector
*
* \pre complex must not be zero
*/
inline
SE2Group(const std::complex<Scalar> & complex,
const Point & translation)
: so2_(complex), translation_(translation) {
}
/**
* \brief Constructor from 3x3 matrix
*
* \pre 2x2 sub-matrix need to be orthogonal with determinant of 1
*/
inline explicit
SE2Group(const Transformation & T)
: so2_(T.template topLeftCorner<2,2>()),
translation_(T.template block<2,1>(0,2)) {
}
/**
* \returns pointer to internal data
*
* This provides unsafe read/write access to internal data. SE2 is represented
* by a pair of an SO2 element (two parameters) and a translation vector (two
* parameters). The user needs to take care of that the complex
* stays normalized.
*
* /see normalize()
*/
EIGEN_STRONG_INLINE
Scalar* data() {
// so2_ and translation_ are layed out sequentially with no padding
return so2_.data();
}
/**
* \returns const pointer to internal data
*
* Const version of data().
*/
EIGEN_STRONG_INLINE
const Scalar* data() const {
// so2_ and translation_ are layed out sequentially with no padding
return so2_.data();
}
/**
* \brief Accessor of SO2
*/
EIGEN_STRONG_INLINE
SO2Reference so2() {
return so2_;
}
/**
* \brief Mutator of SO2
*/
EIGEN_STRONG_INLINE
ConstSO2Reference so2() const {
return so2_;
}
/**
* \brief Mutator of translation vector
*/
EIGEN_STRONG_INLINE
TranslationReference translation() {
return translation_;
}
/**
* \brief Accessor of translation vector
*/
EIGEN_STRONG_INLINE
ConstTranslationReference translation() const {
return translation_;
}
protected:
Sophus::SO2Group<Scalar> so2_;
Matrix<Scalar,2,1> translation_;
};
} // end namespace
namespace Eigen {
/**
* \brief Specialisation of Eigen::Map for SE2GroupBase
*
* Allows us to wrap SE2 Objects around POD array
* (e.g. external c style complex)
*/
template<typename _Scalar, int _Options>
class Map<Sophus::SE2Group<_Scalar>, _Options>
: public Sophus::SE2GroupBase<Map<Sophus::SE2Group<_Scalar>, _Options> >
{
typedef Sophus::SE2GroupBase<Map<Sophus::SE2Group<_Scalar>, _Options> > Base;
public:
/** \brief scalar type */
typedef typename internal::traits<Map>::Scalar Scalar;
/** \brief translation reference type */
typedef typename internal::traits<Map>::TranslationType &
TranslationReference;
/** \brief translation reference type */
typedef const typename internal::traits<Map>::TranslationType &
ConstTranslationReference;
/** \brief SO2 reference type */
typedef typename internal::traits<Map>::SO2Type & SO2Reference;
/** \brief SO2 const reference type */
typedef const typename internal::traits<Map>::SO2Type & ConstSO2Reference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
using Base::operator*=;
using Base::operator*;
EIGEN_STRONG_INLINE
Map(Scalar* coeffs)
: so2_(coeffs),
translation_(coeffs+Sophus::SO2Group<Scalar>::num_parameters) {
}
/**
* \brief Mutator of SO2
*/
EIGEN_STRONG_INLINE
SO2Reference so2() {
return so2_;
}
/**
* \brief Accessor of SO2
*/
EIGEN_STRONG_INLINE
ConstSO2Reference so2() const {
return so2_;
}
/**
* \brief Mutator of translation vector
*/
EIGEN_STRONG_INLINE
TranslationReference translation() {
return translation_;
}
/**
* \brief Accessor of translation vector
*/
EIGEN_STRONG_INLINE
ConstTranslationReference translation() const {
return translation_;
}
protected:
Map<Sophus::SO2Group<Scalar>,_Options> so2_;
Map<Matrix<Scalar,2,1>,_Options> translation_;
};
/**
* \brief Specialisation of Eigen::Map for const SE2GroupBase
*
* Allows us to wrap SE2 Objects around POD array
* (e.g. external c style complex)
*/
template<typename _Scalar, int _Options>
class Map<const Sophus::SE2Group<_Scalar>, _Options>
: public Sophus::SE2GroupBase<
Map<const Sophus::SE2Group<_Scalar>, _Options> > {
typedef Sophus::SE2GroupBase<Map<const Sophus::SE2Group<_Scalar>, _Options> >
Base;
public:
/** \brief scalar type */
typedef typename internal::traits<Map>::Scalar Scalar;
/** \brief translation reference type */
typedef const typename internal::traits<Map>::TranslationType &
ConstTranslationReference;
/** \brief SO2 const reference type */
typedef const typename internal::traits<Map>::SO2Type & ConstSO2Reference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
using Base::operator*=;
using Base::operator*;
EIGEN_STRONG_INLINE
Map(const Scalar* coeffs)
: so2_(coeffs),
translation_(coeffs+Sophus::SO2Group<Scalar>::num_parameters) {
}
EIGEN_STRONG_INLINE
Map(const Scalar* trans_coeffs, const Scalar* rot_coeffs)
: translation_(trans_coeffs), so2_(rot_coeffs){
}
/**
* \brief Accessor of SO2
*/
EIGEN_STRONG_INLINE
ConstSO2Reference so2() const {
return so2_;
}
/**
* \brief Accessor of translation vector
*/
EIGEN_STRONG_INLINE
ConstTranslationReference translation() const {
return translation_;
}
protected:
const Map<const Sophus::SO2Group<Scalar>,_Options> so2_;
const Map<const Matrix<Scalar,2,1>,_Options> translation_;
};
}
#endif

947
thirdparty/Sophus/sophus/se3.hpp vendored Normal file
View File

@@ -0,0 +1,947 @@
// This file is part of Sophus.
//
// Copyright 2011-2013 Hauke Strasdat
// 2012-2013 Steven Lovegrove
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#ifndef SOPHUS_SE3_HPP
#define SOPHUS_SE3_HPP
#include "so3.hpp"
////////////////////////////////////////////////////////////////////////////
// Forward Declarations / typedefs
////////////////////////////////////////////////////////////////////////////
namespace Sophus {
template<typename _Scalar, int _Options=0> class SE3Group;
typedef SE3Group<double> SE3 EIGEN_DEPRECATED;
typedef SE3Group<double> SE3d; /**< double precision SE3 */
typedef SE3Group<float> SE3f; /**< single precision SE3 */
typedef Matrix<double,6,1> Vector6d;
typedef Matrix<double,6,6> Matrix6d;
typedef Matrix<float,6,1> Vector6f;
typedef Matrix<float,6,6> Matrix6f;
}
////////////////////////////////////////////////////////////////////////////
// Eigen Traits (For querying derived types in CRTP hierarchy)
////////////////////////////////////////////////////////////////////////////
namespace Eigen {
namespace internal {
template<typename _Scalar, int _Options>
struct traits<Sophus::SE3Group<_Scalar,_Options> > {
typedef _Scalar Scalar;
typedef Matrix<Scalar,3,1> TranslationType;
typedef Sophus::SO3Group<Scalar> SO3Type;
};
template<typename _Scalar, int _Options>
struct traits<Map<Sophus::SE3Group<_Scalar>, _Options> >
: traits<Sophus::SE3Group<_Scalar, _Options> > {
typedef _Scalar Scalar;
typedef Map<Matrix<Scalar,3,1>,_Options> TranslationType;
typedef Map<Sophus::SO3Group<Scalar>,_Options> SO3Type;
};
template<typename _Scalar, int _Options>
struct traits<Map<const Sophus::SE3Group<_Scalar>, _Options> >
: traits<const Sophus::SE3Group<_Scalar, _Options> > {
typedef _Scalar Scalar;
typedef Map<const Matrix<Scalar,3,1>,_Options> TranslationType;
typedef Map<const Sophus::SO3Group<Scalar>,_Options> SO3Type;
};
}
}
namespace Sophus {
using namespace Eigen;
using namespace std;
/**
* \brief SE3 base type - implements SE3 class but is storage agnostic
*
* [add more detailed description/tutorial]
*/
template<typename Derived>
class SE3GroupBase {
public:
/** \brief scalar type */
typedef typename internal::traits<Derived>::Scalar Scalar;
/** \brief translation reference type */
typedef typename internal::traits<Derived>::TranslationType &
TranslationReference;
/** \brief translation const reference type */
typedef const typename internal::traits<Derived>::TranslationType &
ConstTranslationReference;
/** \brief SO3 reference type */
typedef typename internal::traits<Derived>::SO3Type &
SO3Reference;
/** \brief SO3 const reference type */
typedef const typename internal::traits<Derived>::SO3Type &
ConstSO3Reference;
/** \brief degree of freedom of group
* (three for translation, three for rotation) */
static const int DoF = 6;
/** \brief number of internal parameters used
* (unit quaternion for rotation + translation 3-vector) */
static const int num_parameters = 7;
/** \brief group transformations are NxN matrices */
static const int N = 4;
/** \brief group transfomation type */
typedef Matrix<Scalar,N,N> Transformation;
/** \brief point type */
typedef Matrix<Scalar,3,1> Point;
/** \brief tangent vector type */
typedef Matrix<Scalar,DoF,1> Tangent;
/** \brief adjoint transformation type */
typedef Matrix<Scalar,DoF,DoF> Adjoint;
/**
* \brief Adjoint transformation
*
* This function return the adjoint transformation \f$ Ad \f$ of the
* group instance \f$ A \f$ such that for all \f$ x \f$
* it holds that \f$ \widehat{Ad_A\cdot x} = A\widehat{x}A^{-1} \f$
* with \f$\ \widehat{\cdot} \f$ being the hat()-operator.
*/
inline
const Adjoint Adj() const {
const Matrix<Scalar,3,3> & R = so3().matrix();
Adjoint res;
res.block(0,0,3,3) = R;
res.block(3,3,3,3) = R;
res.block(0,3,3,3) = SO3Group<Scalar>::hat(translation())*R;
res.block(3,0,3,3) = Matrix<Scalar,3,3>::Zero(3,3);
return res;
}
/**
* \returns copy of instance casted to NewScalarType
*/
template<typename NewScalarType>
inline SE3Group<NewScalarType> cast() const {
return
SE3Group<NewScalarType>(so3().template cast<NewScalarType>(),
translation().template cast<NewScalarType>() );
}
/**
* \brief Fast group multiplication
*
* This method is a fast version of operator*=(), since it does not perform
* normalization. It is up to the user to call normalize() once in a while.
*
* \see operator*=()
*/
inline
void fastMultiply(const SE3Group<Scalar>& other) {
translation() += so3()*(other.translation());
so3().fastMultiply(other.so3());
}
/**
* \returns Group inverse of instance
*/
inline
const SE3Group<Scalar> inverse() const {
const SO3Group<Scalar> invR = so3().inverse();
return SE3Group<Scalar>(invR, invR*(translation()
*static_cast<Scalar>(-1) ) );
}
/**
* \brief Logarithmic map
*
* \returns tangent space representation
* (translational part and rotation vector) of instance
*
* \see log().
*/
inline
const Tangent log() const {
return log(*this);
}
/**
* \brief Normalize SO3 element
*
* It re-normalizes the SO3 element. This method only needs to
* be called in conjunction with fastMultiply() or data() write access.
*/
inline
void normalize() {
so3().normalize();
}
/**
* \returns 4x4 matrix representation of instance
*/
inline
const Transformation matrix() const {
Transformation homogenious_matrix;
homogenious_matrix.setIdentity();
homogenious_matrix.block(0,0,3,3) = rotationMatrix();
homogenious_matrix.col(3).head(3) = translation();
return homogenious_matrix;
}
/**
* \returns 3x4 matrix representation of instance
*
* It returns the three first row of matrix().
*/
inline
const Matrix<Scalar,3,4> matrix3x4() const {
Matrix<Scalar,3,4> matrix;
matrix.block(0,0,3,3) = rotationMatrix();
matrix.col(3) = translation();
return matrix;
}
/**
* \brief Assignment operator
*/
template<typename OtherDerived> inline
SE3GroupBase<Derived>& operator= (const SE3GroupBase<OtherDerived> & other) {
so3() = other.so3();
translation() = other.translation();
return *this;
}
/**
* \brief Group multiplication
* \see operator*=()
*/
inline
const SE3Group<Scalar> operator*(const SE3Group<Scalar>& other) const {
SE3Group<Scalar> result(*this);
result *= other;
return result;
}
/**
* \brief Group action on \f$ \mathbf{R}^3 \f$
*
* \param p point \f$p \in \mathbf{R}^3 \f$
* \returns point \f$p' \in \mathbf{R}^3 \f$,
* rotated and translated version of \f$p\f$
*
* This function rotates and translates point \f$ p \f$
* in \f$ \mathbf{R}^3 \f$ by the SE3 transformation \f$R,t\f$
* (=rotation matrix, translation vector): \f$ p' = R\cdot p + t \f$.
*/
inline
const Point operator*(const Point & p) const {
return so3()*p + translation();
}
/**
* \brief In-place group multiplication
*
* \see fastMultiply()
* \see operator*()
*/
inline
void operator*=(const SE3Group<Scalar>& other) {
fastMultiply(other);
normalize();
}
/**
* \returns Rotation matrix
*
* deprecated: use rotationMatrix() instead.
*/
typedef Transformation M3_marcos_dont_like_commas;
inline
EIGEN_DEPRECATED const M3_marcos_dont_like_commas rotation_matrix() const {
return so3().matrix();
}
/**
* \returns Rotation matrix
*/
inline
const Matrix<Scalar,3,3> rotationMatrix() const {
return so3().matrix();
}
/**
* \brief Mutator of SO3 group
*/
EIGEN_STRONG_INLINE
SO3Reference so3() {
return static_cast<Derived*>(this)->so3();
}
/**
* \brief Accessor of SO3 group
*/
EIGEN_STRONG_INLINE
ConstSO3Reference so3() const {
return static_cast<const Derived*>(this)->so3();
}
/**
* \brief Setter of internal unit quaternion representation
*
* \param quaternion
* \pre the quaternion must not be zero
*
* The quaternion is normalized to unit length.
*/
inline
void setQuaternion(const Quaternion<Scalar> & quat) {
return so3().setQuaternion(quat);
}
/**
* \brief Setter of unit quaternion using rotation matrix
*
* \param rotation_matrix a 3x3 rotation matrix
* \pre the 3x3 matrix should be orthogonal and have a determinant of 1
*/
inline
void setRotationMatrix
(const Matrix<Scalar,3,3> & rotation_matrix) {
so3().setQuaternion(Quaternion<Scalar>(rotation_matrix));
}
/**
* \brief Mutator of translation vector
*/
EIGEN_STRONG_INLINE
TranslationReference translation() {
return static_cast<Derived*>(this)->translation();
}
/**
* \brief Accessor of translation vector
*/
EIGEN_STRONG_INLINE
ConstTranslationReference translation() const {
return static_cast<const Derived*>(this)->translation();
}
/**
* \brief Accessor of unit quaternion
*
* No direct write access is given to ensure the quaternion stays normalized.
*/
inline
typename internal::traits<Derived>::SO3Type::ConstQuaternionReference
unit_quaternion() const {
return so3().unit_quaternion();
}
////////////////////////////////////////////////////////////////////////////
// public static functions
////////////////////////////////////////////////////////////////////////////
/**
* \param b 6-vector representation of Lie algebra element
* \returns derivative of Lie bracket
*
* This function returns \f$ \frac{\partial}{\partial a} [a, b]_{se3} \f$
* with \f$ [a, b]_{se3} \f$ being the lieBracket() of the Lie algebra se3.
*
* \see lieBracket()
*/
inline static
const Adjoint d_lieBracketab_by_d_a(const Tangent & b) {
Adjoint res;
res.setZero();
const Matrix<Scalar,3,1> & upsilon2 = b.template head<3>();
const Matrix<Scalar,3,1> & omega2 = b.template tail<3>();
res.template topLeftCorner<3,3>() = -SO3Group<Scalar>::hat(omega2);
res.template topRightCorner<3,3>() = -SO3Group<Scalar>::hat(upsilon2);
res.template bottomRightCorner<3,3>() = -SO3Group<Scalar>::hat(omega2);
return res;
}
/**
* \brief Group exponential
*
* \param a tangent space element (6-vector)
* \returns corresponding element of the group SE3
*
* The first three components of \f$ a \f$ represent the translational
* part \f$ \upsilon \f$ in the tangent space of SE3, while the last three
* components of \f$ a \f$ represents the rotation vector \f$ \omega \f$.
*
* To be more specific, this function computes \f$ \exp(\widehat{a}) \f$
* with \f$ \exp(\cdot) \f$ being the matrix exponential
* and \f$ \widehat{\cdot} \f$ the hat()-operator of SE3.
*
* \see hat()
* \see log()
*/
inline static
const SE3Group<Scalar> exp(const Tangent & a) {
const Matrix<Scalar,3,1> & omega = a.template tail<3>();
Scalar theta;
const SO3Group<Scalar> & so3
= SO3Group<Scalar>::expAndTheta(omega, &theta);
const Matrix<Scalar,3,3> & Omega = SO3Group<Scalar>::hat(omega);
const Matrix<Scalar,3,3> & Omega_sq = Omega*Omega;
Matrix<Scalar,3,3> V;
if(theta<SophusConstants<Scalar>::epsilon()) {
V = so3.matrix();
//Note: That is an accurate expansion!
} else {
Scalar theta_sq = theta*theta;
V = (Matrix<Scalar,3,3>::Identity()
+ (static_cast<Scalar>(1)-std::cos(theta))/(theta_sq)*Omega
+ (theta-std::sin(theta))/(theta_sq*theta)*Omega_sq);
}
return SE3Group<Scalar>(so3,V*a.template head<3>());
}
/**
* \brief Generators
*
* \pre \f$ i \in \{0,1,2,3,4,5\} \f$
* \returns \f$ i \f$th generator \f$ G_i \f$ of SE3
*
* The infinitesimal generators of SE3 are: \f[
* G_0 = \left( \begin{array}{cccc}
* 0& 0& 0& 1\\
* 0& 0& 0& 0\\
* 0& 0& 0& 0\\
* 0& 0& 0& 0\\
* \end{array} \right),
* G_1 = \left( \begin{array}{cccc}
* 0& 0& 0& 0\\
* 0& 0& 0& 1\\
* 0& 0& 0& 0\\
* 0& 0& 0& 0\\
* \end{array} \right),
* G_2 = \left( \begin{array}{cccc}
* 0& 0& 0& 0\\
* 0& 0& 0& 0\\
* 0& 0& 0& 1\\
* 0& 0& 0& 0\\
* \end{array} \right).
* G_3 = \left( \begin{array}{cccc}
* 0& 0& 0& 0\\
* 0& 0& -1& 0\\
* 0& 1& 0& 0\\
* 0& 0& 0& 0\\
* \end{array} \right),
* G_4 = \left( \begin{array}{cccc}
* 0& 0& 1& 0\\
* 0& 0& 0& 0\\
* -1& 0& 0& 0\\
* 0& 0& 0& 0\\
* \end{array} \right),
* G_5 = \left( \begin{array}{cccc}
* 0& -1& 0& 0\\
* 1& 0& 0& 0\\
* 0& 0& 0& 0\\
* 0& 0& 0& 0\\
* \end{array} \right).
* \f]
* \see hat()
*/
inline static
const Transformation generator(int i) {
if (i<0 || i>5) {
throw SophusException("i is not in range [0,5].");
}
Tangent e;
e.setZero();
e[i] = static_cast<Scalar>(1);
return hat(e);
}
/**
* \brief hat-operator
*
* \param omega 6-vector representation of Lie algebra element
* \returns 4x4-matrix representatin of Lie algebra element
*
* Formally, the hat-operator of SE3 is defined
* as \f$ \widehat{\cdot}: \mathbf{R}^6 \rightarrow \mathbf{R}^{4\times 4},
* \quad \widehat{\omega} = \sum_{i=0}^5 G_i \omega_i \f$
* with \f$ G_i \f$ being the ith infinitesial generator().
*
* \see generator()
* \see vee()
*/
inline static
const Transformation hat(const Tangent & v) {
Transformation Omega;
Omega.setZero();
Omega.template topLeftCorner<3,3>()
= SO3Group<Scalar>::hat(v.template tail<3>());
Omega.col(3).template head<3>() = v.template head<3>();
return Omega;
}
/**
* \brief Lie bracket
*
* \param a 6-vector representation of Lie algebra element
* \param b 6-vector representation of Lie algebra element
* \returns 6-vector representation of Lie algebra element
*
* It computes the bracket of SE3. To be more specific, it
* computes \f$ [a, b]_{se3}
* := [\widehat{a}, \widehat{b}]^\vee \f$
* with \f$ [A,B] = AB-BA \f$ being the matrix
* commutator, \f$ \widehat{\cdot} \f$ the
* hat()-operator and \f$ (\cdot)^\vee \f$ the vee()-operator of SE3.
*
* \see hat()
* \see vee()
*/
inline static
const Tangent lieBracket(const Tangent & a,
const Tangent & b) {
Matrix<Scalar,3,1> upsilon1 = a.template head<3>();
Matrix<Scalar,3,1> upsilon2 = b.template head<3>();
Matrix<Scalar,3,1> omega1 = a.template tail<3>();
Matrix<Scalar,3,1> omega2 = b.template tail<3>();
Tangent res;
res.template head<3>() = omega1.cross(upsilon2) + upsilon1.cross(omega2);
res.template tail<3>() = omega1.cross(omega2);
return res;
}
/**
* \brief Logarithmic map
*
* \param other element of the group SE3
* \returns corresponding tangent space element
* (translational part \f$ \upsilon \f$
* and rotation vector \f$ \omega \f$)
*
* Computes the logarithmic, the inverse of the group exponential.
* To be specific, this function computes \f$ \log({\cdot})^\vee \f$
* with \f$ \vee(\cdot) \f$ being the matrix logarithm
* and \f$ \vee{\cdot} \f$ the vee()-operator of SE3.
*
* \see exp()
* \see vee()
*/
inline static
const Tangent log(const SE3Group<Scalar> & se3) {
Tangent upsilon_omega;
Scalar theta;
upsilon_omega.template tail<3>()
= SO3Group<Scalar>::logAndTheta(se3.so3(), &theta);
if (std::abs(theta)<SophusConstants<Scalar>::epsilon()) {
const Matrix<Scalar,3,3> & Omega
= SO3Group<Scalar>::hat(upsilon_omega.template tail<3>());
const Matrix<Scalar,3,3> & V_inv =
Matrix<Scalar,3,3>::Identity() -
static_cast<Scalar>(0.5)*Omega
+ static_cast<Scalar>(1./12.)*(Omega*Omega);
upsilon_omega.template head<3>() = V_inv*se3.translation();
} else {
const Matrix<Scalar,3,3> & Omega
= SO3Group<Scalar>::hat(upsilon_omega.template tail<3>());
const Matrix<Scalar,3,3> & V_inv =
( Matrix<Scalar,3,3>::Identity() - static_cast<Scalar>(0.5)*Omega
+ ( static_cast<Scalar>(1)
- theta/(static_cast<Scalar>(2)*tan(theta/Scalar(2)))) /
(theta*theta)*(Omega*Omega) );
upsilon_omega.template head<3>() = V_inv*se3.translation();
}
return upsilon_omega;
}
/**
* \brief vee-operator
*
* \param Omega 4x4-matrix representation of Lie algebra element
* \returns 6-vector representatin of Lie algebra element
*
* This is the inverse of the hat()-operator.
*
* \see hat()
*/
inline static
const Tangent vee(const Transformation & Omega) {
Tangent upsilon_omega;
upsilon_omega.template head<3>() = Omega.col(3).template head<3>();
upsilon_omega.template tail<3>()
= SO3Group<Scalar>::vee(Omega.template topLeftCorner<3,3>());
return upsilon_omega;
}
};
/**
* \brief SE3 default type - Constructors and default storage for SE3 Type
*/
template<typename _Scalar, int _Options>
class SE3Group : public SE3GroupBase<SE3Group<_Scalar,_Options> > {
typedef SE3GroupBase<SE3Group<_Scalar,_Options> > Base;
public:
/** \brief scalar type */
typedef typename internal::traits<SE3Group<_Scalar,_Options> >
::Scalar Scalar;
/** \brief SO3 reference type */
typedef typename internal::traits<SE3Group<_Scalar,_Options> >
::SO3Type & SO3Reference;
/** \brief SO3 const reference type */
typedef const typename internal::traits<SE3Group<_Scalar,_Options> >
::SO3Type & ConstSO3Reference;
/** \brief translation reference type */
typedef typename internal::traits<SE3Group<_Scalar,_Options> >
::TranslationType & TranslationReference;
/** \brief translation const reference type */
typedef const typename internal::traits<SE3Group<_Scalar,_Options> >
::TranslationType & ConstTranslationReference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
/**
* \brief Default constructor
*
* Initialize Quaternion to identity rotation and translation to zero.
*/
inline
SE3Group()
: translation_( Matrix<Scalar,3,1>::Zero() )
{
}
/**
* \brief Copy constructor
*/
template<typename OtherDerived> inline
SE3Group(const SE3GroupBase<OtherDerived> & other)
: so3_(other.so3()), translation_(other.translation()) {
}
/**
* \brief Constructor from SO3 and translation vector
*/
template<typename OtherDerived> inline
SE3Group(const SO3GroupBase<OtherDerived> & so3,
const Point & translation)
: so3_(so3), translation_(translation) {
}
/**
* \brief Constructor from rotation matrix and translation vector
*
* \pre rotation matrix need to be orthogonal with determinant of 1
*/
inline
SE3Group(const Matrix<Scalar,3,3> & rotation_matrix,
const Point & translation)
: so3_(rotation_matrix), translation_(translation) {
}
/**
* \brief Constructor from quaternion and translation vector
*
* \pre quaternion must not be zero
*/
inline
SE3Group(const Quaternion<Scalar> & quaternion,
const Point & translation)
: so3_(quaternion), translation_(translation) {
}
/**
* \brief Constructor from 4x4 matrix
*
* \pre top-left 3x3 sub-matrix need to be orthogonal with determinant of 1
*/
inline explicit
SE3Group(const Eigen::Matrix<Scalar,4,4>& T)
: so3_(T.template topLeftCorner<3,3>()),
translation_(T.template block<3,1>(0,3)) {
}
/**
* \returns pointer to internal data
*
* This provides unsafe read/write access to internal data. SE3 is represented
* by a pair of an SO3 element (4 parameters) and translation vector (three
* parameters). The user needs to take care of that the quaternion
* stays normalized.
*
* Note: The first three Scalars represent the imaginary parts, while the
* forth Scalar represent the real part.
*
* /see normalize()
*/
EIGEN_STRONG_INLINE
Scalar* data() {
// so3_ and translation_ are layed out sequentially with no padding
return so3_.data();
}
/**
* \returns const pointer to internal data
*
* Const version of data().
*/
EIGEN_STRONG_INLINE
const Scalar* data() const {
// so3_ and translation_ are layed out sequentially with no padding
return so3_.data();
}
/**
* \brief Accessor of SO3
*/
EIGEN_STRONG_INLINE
SO3Reference so3() {
return so3_;
}
/**
* \brief Mutator of SO3
*/
EIGEN_STRONG_INLINE
ConstSO3Reference so3() const {
return so3_;
}
/**
* \brief Mutator of translation vector
*/
EIGEN_STRONG_INLINE
TranslationReference translation() {
return translation_;
}
/**
* \brief Accessor of translation vector
*/
EIGEN_STRONG_INLINE
ConstTranslationReference translation() const {
return translation_;
}
protected:
Sophus::SO3Group<Scalar> so3_;
Matrix<Scalar,3,1> translation_;
};
} // end namespace
namespace Eigen {
/**
* \brief Specialisation of Eigen::Map for SE3GroupBase
*
* Allows us to wrap SE3 Objects around POD array
* (e.g. external c style quaternion)
*/
template<typename _Scalar, int _Options>
class Map<Sophus::SE3Group<_Scalar>, _Options>
: public Sophus::SE3GroupBase<Map<Sophus::SE3Group<_Scalar>, _Options> > {
typedef Sophus::SE3GroupBase<Map<Sophus::SE3Group<_Scalar>, _Options> > Base;
public:
/** \brief scalar type */
typedef typename internal::traits<Map>::Scalar Scalar;
/** \brief translation reference type */
typedef typename internal::traits<Map>::TranslationType &
TranslationReference;
/** \brief translation const reference type */
typedef const typename internal::traits<Map>::TranslationType &
ConstTranslationReference;
/** \brief SO3 reference type */
typedef typename internal::traits<Map>::SO3Type &
SO3Reference;
/** \brief SO3 const reference type */
typedef const typename internal::traits<Map>::SO3Type &
ConstSO3Reference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
using Base::operator*=;
using Base::operator*;
EIGEN_STRONG_INLINE
Map(Scalar* coeffs)
: so3_(coeffs),
translation_(coeffs+Sophus::SO3Group<Scalar>::num_parameters) {
}
/**
* \brief Mutator of SO3
*/
EIGEN_STRONG_INLINE
SO3Reference so3() {
return so3_;
}
/**
* \brief Accessor of SO3
*/
EIGEN_STRONG_INLINE
ConstSO3Reference so3() const {
return so3_;
}
/**
* \brief Mutator of translation vector
*/
EIGEN_STRONG_INLINE
TranslationReference translation() {
return translation_;
}
/**
* \brief Accessor of translation vector
*/
EIGEN_STRONG_INLINE
ConstTranslationReference translation() const {
return translation_;
}
protected:
Map<Sophus::SO3Group<Scalar>,_Options> so3_;
Map<Matrix<Scalar,3,1>,_Options> translation_;
};
/**
* \brief Specialisation of Eigen::Map for const SE3GroupBase
*
* Allows us to wrap SE3 Objects around POD array
* (e.g. external c style quaternion)
*/
template<typename _Scalar, int _Options>
class Map<const Sophus::SE3Group<_Scalar>, _Options>
: public Sophus::SE3GroupBase<
Map<const Sophus::SE3Group<_Scalar>, _Options> > {
typedef Sophus::SE3GroupBase<Map<const Sophus::SE3Group<_Scalar>, _Options> >
Base;
public:
/** \brief scalar type */
typedef typename internal::traits<Map>::Scalar Scalar;
/** \brief translation const reference type */
typedef const typename internal::traits<Map>::TranslationType &
ConstTranslationReference;
/** \brief SO3 const reference type */
typedef const typename internal::traits<Map>::SO3Type &
ConstSO3Reference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
using Base::operator*=;
using Base::operator*;
EIGEN_STRONG_INLINE
Map(const Scalar* coeffs)
: so3_(coeffs),
translation_(coeffs+Sophus::SO3Group<Scalar>::num_parameters) {
}
EIGEN_STRONG_INLINE
Map(const Scalar* trans_coeffs, const Scalar* rot_coeffs)
: translation_(trans_coeffs), so3_(rot_coeffs){
}
/**
* \brief Accessor of SO3
*/
EIGEN_STRONG_INLINE
ConstSO3Reference so3() const {
return so3_;
}
/**
* \brief Accessor of translation vector
*/
EIGEN_STRONG_INLINE
ConstTranslationReference translation() const {
return translation_;
}
protected:
const Map<const Sophus::SO3Group<Scalar>,_Options> so3_;
const Map<const Matrix<Scalar,3,1>,_Options> translation_;
};
}
#endif

976
thirdparty/Sophus/sophus/sim3.hpp vendored Normal file
View File

@@ -0,0 +1,976 @@
// This file is part of Sophus.
//
// Copyright 2012-2013 Hauke Strasdat
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#ifndef SOPHUS_SIM3_HPP
#define SOPHUS_SIM3_HPP
#include "rxso3.hpp"
////////////////////////////////////////////////////////////////////////////
// Forward Declarations / typedefs
////////////////////////////////////////////////////////////////////////////
namespace Sophus {
template<typename _Scalar, int _Options=0> class Sim3Group;
typedef Sim3Group<double> Sim3 EIGEN_DEPRECATED;
typedef Sim3Group<double> Sim3d; /**< double precision Sim3 */
typedef Sim3Group<float> Sim3f; /**< single precision Sim3 */
typedef Matrix<double,7,1> Vector7d;
typedef Matrix<double,7,7> Matrix7d;
typedef Matrix<float,7,1> Vector7f;
typedef Matrix<float,7,7> Matrix7f;
}
////////////////////////////////////////////////////////////////////////////
// Eigen Traits (For querying derived types in CRTP hierarchy)
////////////////////////////////////////////////////////////////////////////
namespace Eigen {
namespace internal {
template<typename _Scalar, int _Options>
struct traits<Sophus::Sim3Group<_Scalar,_Options> > {
typedef _Scalar Scalar;
typedef Matrix<Scalar,3,1> TranslationType;
typedef Sophus::RxSO3Group<Scalar> RxSO3Type;
};
template<typename _Scalar, int _Options>
struct traits<Map<Sophus::Sim3Group<_Scalar>, _Options> >
: traits<Sophus::Sim3Group<_Scalar, _Options> > {
typedef _Scalar Scalar;
typedef Map<Matrix<Scalar,3,1>,_Options> TranslationType;
typedef Map<Sophus::RxSO3Group<Scalar>,_Options> RxSO3Type;
};
template<typename _Scalar, int _Options>
struct traits<Map<const Sophus::Sim3Group<_Scalar>, _Options> >
: traits<const Sophus::Sim3Group<_Scalar, _Options> > {
typedef _Scalar Scalar;
typedef Map<const Matrix<Scalar,3,1>,_Options> TranslationType;
typedef Map<const Sophus::RxSO3Group<Scalar>,_Options> RxSO3Type;
};
}
}
namespace Sophus {
using namespace Eigen;
using namespace std;
/**
* \brief Sim3 base type - implements Sim3 class but is storage agnostic
*
* [add more detailed description/tutorial]
*/
template<typename Derived>
class Sim3GroupBase {
public:
/** \brief scalar type */
typedef typename internal::traits<Derived>::Scalar Scalar;
/** \brief translation reference type */
typedef typename internal::traits<Derived>::TranslationType &
TranslationReference;
/** \brief translation const reference type */
typedef const typename internal::traits<Derived>::TranslationType &
ConstTranslationReference;
/** \brief RxSO3 reference type */
typedef typename internal::traits<Derived>::RxSO3Type &
RxSO3Reference;
/** \brief RxSO3 const reference type */
typedef const typename internal::traits<Derived>::RxSO3Type &
ConstRxSO3Reference;
/** \brief degree of freedom of group
* (three for translation, three for rotation, one for scale) */
static const int DoF = 7;
/** \brief number of internal parameters used
* (quaternion for rotation and scale + translation 3-vector) */
static const int num_parameters = 7;
/** \brief group transformations are NxN matrices */
static const int N = 4;
/** \brief group transfomation type */
typedef Matrix<Scalar,N,N> Transformation;
/** \brief point type */
typedef Matrix<Scalar,3,1> Point;
/** \brief tangent vector type */
typedef Matrix<Scalar,DoF,1> Tangent;
/** \brief adjoint transformation type */
typedef Matrix<Scalar,DoF,DoF> Adjoint;
/**
* \brief Adjoint transformation
*
* This function return the adjoint transformation \f$ Ad \f$ of the
* group instance \f$ A \f$ such that for all \f$ x \f$
* it holds that \f$ \widehat{Ad_A\cdot x} = A\widehat{x}A^{-1} \f$
* with \f$\ \widehat{\cdot} \f$ being the hat()-operator.
*/
inline
const Adjoint Adj() const {
const Matrix<Scalar,3,3> & R = rxso3().rotationMatrix();
Adjoint res;
res.setZero();
res.block(0,0,3,3) = scale()*R;
res.block(0,3,3,3) = SO3Group<Scalar>::hat(translation())*R;
res.block(0,6,3,1) = -translation();
res.block(3,3,3,3) = R;
res(6,6) = 1;
return res;
}
/**
* \returns copy of instance casted to NewScalarType
*/
template<typename NewScalarType>
inline Sim3Group<NewScalarType> cast() const {
return
Sim3Group<NewScalarType>(rxso3().template cast<NewScalarType>(),
translation().template cast<NewScalarType>() );
}
/**
* \brief In-place group multiplication
*
* Same as operator*=() for Sim3.
*
* \see operator*()
*/
inline
void fastMultiply(const Sim3Group<Scalar>& other) {
translation() += (rxso3() * other.translation());
rxso3() *= other.rxso3();
}
/**
* \returns Group inverse of instance
*/
inline
const Sim3Group<Scalar> inverse() const {
const RxSO3Group<Scalar> invR = rxso3().inverse();
return Sim3Group<Scalar>(invR, invR*(translation()
*static_cast<Scalar>(-1) ) );
}
/**
* \brief Logarithmic map
*
* \returns tangent space representation
* (translational part and rotation vector) of instance
*
* \see log().
*/
inline
const Tangent log() const {
return log(*this);
}
/**
* \returns 4x4 matrix representation of instance
*/
inline
const Transformation matrix() const {
Transformation homogenious_matrix;
homogenious_matrix.setIdentity();
homogenious_matrix.block(0,0,3,3) = rxso3().matrix();
homogenious_matrix.col(3).head(3) = translation();
return homogenious_matrix;
}
/**
* \returns 3x4 matrix representation of instance
*
* It returns the three first row of matrix().
*/
inline
const Matrix<Scalar,3,4> matrix3x4() const {
Matrix<Scalar,3,4> matrix;
matrix.block(0,0,3,3) = rxso3().matrix();
matrix.col(3) = translation();
return matrix;
}
/**
* \brief Assignment operator
*/
template<typename OtherDerived> inline
Sim3GroupBase<Derived>& operator=
(const Sim3GroupBase<OtherDerived> & other) {
rxso3() = other.rxso3();
translation() = other.translation();
return *this;
}
/**
* \brief Group multiplication
* \see operator*=()
*/
inline
const Sim3Group<Scalar> operator*(const Sim3Group<Scalar>& other) const {
Sim3Group<Scalar> result(*this);
result *= other;
return result;
}
/**
* \brief Group action on \f$ \mathbf{R}^3 \f$
*
* \param p point \f$p \in \mathbf{R}^3 \f$
* \returns point \f$p' \in \mathbf{R}^3 \f$,
* rotated, scaled and translated version of \f$p\f$
*
* This function scales, rotates and translates point \f$ p \f$
* in \f$ \mathbf{R}^3 \f$ by the Sim3 transformation \f$sR,t\f$
* (=scaled rotation matrix, translation vector): \f$ p' = sR\cdot p + t \f$.
*/
inline
const Point operator*(const Point & p) const {
return rxso3()*p + translation();
}
/**
* \brief In-place group multiplication
*
* \see operator*()
*/
inline
void operator*=(const Sim3Group<Scalar>& other) {
translation() += (rxso3() * other.translation());
rxso3() *= other.rxso3();
}
/**
* \brief Mutator of quaternion
*/
inline
typename internal::traits<Derived>::RxSO3Type::QuaternionReference
quaternion() {
return rxso3().quaternion();
}
/**
* \brief Accessor of quaternion
*/
inline
typename internal::traits<Derived>::RxSO3Type::ConstQuaternionReference
quaternion() const {
return rxso3().quaternion();
}
/**
* \returns Rotation matrix
*
* deprecated: use rotationMatrix() instead.
*/
inline
EIGEN_DEPRECATED const Transformation rotation_matrix() const {
return rxso3().rotationMatrix();
}
/**
* \returns Rotation matrix
*/
inline
const Matrix<Scalar,3,3> rotationMatrix() const {
return rxso3().rotationMatrix();
}
/**
* \brief Mutator of RxSO3 group
*/
EIGEN_STRONG_INLINE
RxSO3Reference rxso3() {
return static_cast<Derived*>(this)->rxso3();
}
/**
* \brief Accessor of RxSO3 group
*/
EIGEN_STRONG_INLINE
ConstRxSO3Reference rxso3() const {
return static_cast<const Derived*>(this)->rxso3();
}
/**
* \returns scale
*/
EIGEN_STRONG_INLINE
const Scalar scale() const {
return rxso3().scale();
}
/**
* \brief Setter of quaternion using rotation matrix, leaves scale untouched
*
* \param R a 3x3 rotation matrix
* \pre the 3x3 matrix should be orthogonal and have a determinant of 1
*/
inline
void setRotationMatrix
(const Matrix<Scalar,3,3> & R) {
rxso3().setRotationMatrix(R);
}
/**
* \brief Scale setter
*/
EIGEN_STRONG_INLINE
void setScale(const Scalar & scale) {
rxso3().setScale(scale);
}
/**
* \brief Setter of quaternion using scaled rotation matrix
*
* \param sR a 3x3 scaled rotation matrix
* \pre the 3x3 matrix should be "scaled orthogonal"
* and have a positive determinant
*/
inline
void setScaledRotationMatrix
(const Matrix<Scalar,3,3> & sR) {
rxso3().setScaledRotationMatrix(sR);
}
/**
* \brief Mutator of translation vector
*/
EIGEN_STRONG_INLINE
TranslationReference translation() {
return static_cast<Derived*>(this)->translation();
}
/**
* \brief Accessor of translation vector
*/
EIGEN_STRONG_INLINE
ConstTranslationReference translation() const {
return static_cast<const Derived*>(this)->translation();
}
////////////////////////////////////////////////////////////////////////////
// public static functions
////////////////////////////////////////////////////////////////////////////
/**
* \param b 7-vector representation of Lie algebra element
* \returns derivative of Lie bracket
*
* This function returns \f$ \frac{\partial}{\partial a} [a, b]_{sim3} \f$
* with \f$ [a, b]_{sim3} \f$ being the lieBracket() of the Lie algebra sim3.
*
* \see lieBracket()
*/
inline static
const Adjoint d_lieBracketab_by_d_a(const Tangent & b) {
const Matrix<Scalar,3,1> & upsilon2 = b.template head<3>();
const Matrix<Scalar,3,1> & omega2 = b.template segment<3>(3);
Scalar sigma2 = b[6];
Adjoint res;
res.setZero();
res.template topLeftCorner<3,3>()
= -SO3::hat(omega2)-sigma2*Matrix3d::Identity();
res.template block<3,3>(0,3) = -SO3::hat(upsilon2);
res.template topRightCorner<3,1>() = upsilon2;
res.template block<3,3>(3,3) = -SO3::hat(omega2);
return res;
}
/**
* \brief Group exponential
*
* \param a tangent space element (7-vector)
* \returns corresponding element of the group Sim3
*
* The first three components of \f$ a \f$ represent the translational
* part \f$ \upsilon \f$ in the tangent space of Sim3, while the last three
* components of \f$ a \f$ represents the rotation vector \f$ \omega \f$.
*
* To be more specific, this function computes \f$ \exp(\widehat{a}) \f$
* with \f$ \exp(\cdot) \f$ being the matrix exponential
* and \f$ \widehat{\cdot} \f$ the hat()-operator of Sim3.
*
* \see hat()
* \see log()
*/
inline static
const Sim3Group<Scalar> exp(const Tangent & a) {
const Matrix<Scalar,3,1> & upsilon = a.segment(0,3);
const Matrix<Scalar,3,1> & omega = a.segment(3,3);
Scalar sigma = a[6];
Scalar theta;
RxSO3Group<Scalar> rxso3
= RxSO3Group<Scalar>::expAndTheta(a.template tail<4>(), &theta);
const Matrix<Scalar,3,3> & Omega = SO3Group<Scalar>::hat(omega);
const Matrix<Scalar,3,3> & W = calcW(theta, sigma, rxso3.scale(), Omega);
return Sim3Group<Scalar>(rxso3, W*upsilon);
}
/**
* \brief Generators
*
* \pre \f$ i \in \{0,1,2,3,4,5,6\} \f$
* \returns \f$ i \f$th generator \f$ G_i \f$ of Sim3
*
* The infinitesimal generators of Sim3 are: \f[
* G_0 = \left( \begin{array}{cccc}
* 0& 0& 0& 1\\
* 0& 0& 0& 0\\
* 0& 0& 0& 0\\
* 0& 0& 0& 0\\
* \end{array} \right),
* G_1 = \left( \begin{array}{cccc}
* 0& 0& 0& 0\\
* 0& 0& 0& 1\\
* 0& 0& 0& 0\\
* 0& 0& 0& 0\\
* \end{array} \right),
* G_2 = \left( \begin{array}{cccc}
* 0& 0& 0& 0\\
* 0& 0& 0& 0\\
* 0& 0& 0& 1\\
* 0& 0& 0& 0\\
* \end{array} \right).
* G_3 = \left( \begin{array}{cccc}
* 0& 0& 0& 0\\
* 0& 0& -1& 0\\
* 0& 1& 0& 0\\
* 0& 0& 0& 0\\
* \end{array} \right),
* G_4 = \left( \begin{array}{cccc}
* 0& 0& 1& 0\\
* 0& 0& 0& 0\\
* -1& 0& 0& 0\\
* 0& 0& 0& 0\\
* \end{array} \right),
* G_5 = \left( \begin{array}{cccc}
* 0& -1& 0& 0\\
* 1& 0& 0& 0\\
* 0& 0& 0& 0\\
* 0& 0& 0& 0\\
* \end{array} \right),
* G_6 = \left( \begin{array}{cccc}
* 1& 0& 0& 0\\
* 0& 1& 0& 0\\
* 0& 0& 1& 0\\
* 0& 0& 0& 0\\
* \end{array} \right).
* \f]
* \see hat()
*/
inline static
const Transformation generator(int i) {
if (i<0 || i>6) {
throw SophusException("i is not in range [0,6].");
}
Tangent e;
e.setZero();
e[i] = static_cast<Scalar>(1);
return hat(e);
}
/**
* \brief hat-operator
*
* \param omega 7-vector representation of Lie algebra element
* \returns 4x4-matrix representatin of Lie algebra element
*
* Formally, the hat-operator of Sim3 is defined
* as \f$ \widehat{\cdot}: \mathbf{R}^7 \rightarrow \mathbf{R}^{4\times 4},
* \quad \widehat{\omega} = \sum_{i=0}^5 G_i \omega_i \f$
* with \f$ G_i \f$ being the ith infinitesial generator().
*
* \see generator()
* \see vee()
*/
inline static
const Transformation hat(const Tangent & v) {
Transformation Omega;
Omega.template topLeftCorner<3,3>()
= RxSO3Group<Scalar>::hat(v.template tail<4>());
Omega.col(3).template head<3>() = v.template head<3>();
Omega.row(3).setZero();
return Omega;
}
/**
* \brief Lie bracket
*
* \param a 7-vector representation of Lie algebra element
* \param b 7-vector representation of Lie algebra element
* \returns 7-vector representation of Lie algebra element
*
* It computes the bracket of Sim3. To be more specific, it
* computes \f$ [a, b]_{sim3}
* := [\widehat{a}, \widehat{b}]^\vee \f$
* with \f$ [A,B] = AB-BA \f$ being the matrix
* commutator, \f$ \widehat{\cdot} \f$ the
* hat()-operator and \f$ (\cdot)^\vee \f$ the vee()-operator of Sim3.
*
* \see hat()
* \see vee()
*/
inline static
const Tangent lieBracket(const Tangent & a,
const Tangent & b) {
const Matrix<Scalar,3,1> & upsilon1 = a.template head<3>();
const Matrix<Scalar,3,1> & upsilon2 = b.template head<3>();
const Matrix<Scalar,3,1> & omega1 = a.template segment<3>(3);
const Matrix<Scalar,3,1> & omega2 = b.template segment<3>(3);
Scalar sigma1 = a[6];
Scalar sigma2 = b[6];
Tangent res;
res.template head<3>() =
SO3Group<Scalar>::hat(omega1)*upsilon2
+ SO3Group<Scalar>::hat(upsilon1)*omega2
+ sigma1*upsilon2 - sigma2*upsilon1;
res.template segment<3>(3) = omega1.cross(omega2);
res[6] = static_cast<Scalar>(0);
return res;
}
/**
* \brief Logarithmic map
*
* \param other element of the group Sim3
* \returns corresponding tangent space element
* (translational part \f$ \upsilon \f$
* and rotation vector \f$ \omega \f$)
*
* Computes the logarithmic, the inverse of the group exponential.
* To be specific, this function computes \f$ \log({\cdot})^\vee \f$
* with \f$ \vee(\cdot) \f$ being the matrix logarithm
* and \f$ \vee{\cdot} \f$ the vee()-operator of Sim3.
*
* \see exp()
* \see vee()
*/
inline static
const Tangent log(const Sim3Group<Scalar> & other) {
Tangent res;
Scalar theta;
const Matrix<Scalar,4,1> & omega_sigma
= RxSO3Group<Scalar>::logAndTheta(other.rxso3(), &theta);
const Matrix<Scalar,3,1> & omega = omega_sigma.template head<3>();
Scalar sigma = omega_sigma[3];
const Matrix<Scalar,3,3> & W
= calcW(theta, sigma, other.scale(), SO3Group<Scalar>::hat(omega));
res.segment(0,3) = W.partialPivLu().solve(other.translation());
res.segment(3,3) = omega;
res[6] = sigma;
return res;
}
/**
* \brief vee-operator
*
* \param Omega 4x4-matrix representation of Lie algebra element
* \returns 7-vector representatin of Lie algebra element
*
* This is the inverse of the hat()-operator.
*
* \see hat()
*/
inline static
const Tangent vee(const Transformation & Omega) {
Tangent upsilon_omega_sigma;
upsilon_omega_sigma.template head<3>()
= Omega.col(3).template head<3>();
upsilon_omega_sigma.template tail<4>()
= RxSO3Group<Scalar>::vee(Omega.template topLeftCorner<3,3>());
return upsilon_omega_sigma;
}
private:
static
Matrix<Scalar,3,3> calcW(const Scalar & theta,
const Scalar & sigma,
const Scalar & scale,
const Matrix<Scalar,3,3> & Omega){
static const Matrix<Scalar,3,3> I
= Matrix<Scalar,3,3>::Identity();
static const Scalar one = static_cast<Scalar>(1.);
static const Scalar half = static_cast<Scalar>(1./2.);
Matrix<Scalar,3,3> Omega2 = Omega*Omega;
Scalar A,B,C;
if (std::abs(sigma)<SophusConstants<Scalar>::epsilon()) {
C = one;
if (std::abs(theta)<SophusConstants<Scalar>::epsilon()) {
A = half;
B = static_cast<Scalar>(1./6.);
} else {
Scalar theta_sq = theta*theta;
A = (one-std::cos(theta))/theta_sq;
B = (theta-std::sin(theta))/(theta_sq*theta);
}
} else {
C = (scale-one)/sigma;
if (std::abs(theta)<SophusConstants<Scalar>::epsilon()) {
Scalar sigma_sq = sigma*sigma;
A = ((sigma-one)*scale+one)/sigma_sq;
B = ((half*sigma*sigma-sigma+one)*scale)/(sigma_sq*sigma);
} else {
Scalar theta_sq = theta*theta;
Scalar a = scale*std::sin(theta);
Scalar b = scale*std::cos(theta);
Scalar c = theta_sq+sigma*sigma;
A = (a*sigma+ (one-b)*theta)/(theta*c);
B = (C-((b-one)*sigma+a*theta)/(c))*one/(theta_sq);
}
}
return A*Omega + B*Omega2 + C*I;
}
};
/**
* \brief Sim3 default type - Constructors and default storage for Sim3 Type
*/
template<typename _Scalar, int _Options>
class Sim3Group : public Sim3GroupBase<Sim3Group<_Scalar,_Options> > {
typedef Sim3GroupBase<Sim3Group<_Scalar,_Options> > Base;
public:
/** \brief scalar type */
typedef typename internal::traits<Sim3Group<_Scalar,_Options> >
::Scalar Scalar;
/** \brief RxSO3 reference type */
typedef typename internal::traits<Sim3Group<_Scalar,_Options> >
::RxSO3Type & RxSO3Reference;
/** \brief RxSO3 const reference type */
typedef const typename internal::traits<Sim3Group<_Scalar,_Options> >
::RxSO3Type & ConstRxSO3Reference;
/** \brief translation reference type */
typedef typename internal::traits<Sim3Group<_Scalar,_Options> >
::TranslationType & TranslationReference;
/** \brief translation const reference type */
typedef const typename internal::traits<Sim3Group<_Scalar,_Options> >
::TranslationType & ConstTranslationReference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
/**
* \brief Default constructor
*
* Initialize Quaternion to identity rotation and translation to zero.
*/
inline
Sim3Group()
: translation_( Matrix<Scalar,3,1>::Zero() )
{
}
/**
* \brief Copy constructor
*/
template<typename OtherDerived> inline
Sim3Group(const Sim3GroupBase<OtherDerived> & other)
: rxso3_(other.rxso3()), translation_(other.translation()) {
}
/**
* \brief Constructor from RxSO3 and translation vector
*/
template<typename OtherDerived> inline
Sim3Group(const RxSO3GroupBase<OtherDerived> & rxso3,
const Point & translation)
: rxso3_(rxso3), translation_(translation) {
}
/**
* \brief Constructor from quaternion and translation vector
*
* \pre quaternion must not be zero
*/
inline
Sim3Group(const Quaternion<Scalar> & quaternion,
const Point & translation)
: rxso3_(quaternion), translation_(translation) {
}
/**
* \brief Constructor from 4x4 matrix
*
* \pre top-left 3x3 sub-matrix need to be "scaled orthogonal"
* with positive determinant of
*/
inline explicit
Sim3Group(const Eigen::Matrix<Scalar,4,4>& T)
: rxso3_(T.template topLeftCorner<3,3>()),
translation_(T.template block<3,1>(0,3)) {
}
/**
* \returns pointer to internal data
*
* This provides unsafe read/write access to internal data. Sim3 is
* represented by a pair of an RxSO3 element (4 parameters) and translation
* vector (three parameters).
*
* Note: The first three Scalars represent the imaginary parts, while the
*/
EIGEN_STRONG_INLINE
Scalar* data() {
// rxso3_ and translation_ are layed out sequentially with no padding
return rxso3_.data();
}
/**
* \returns const pointer to internal data
*
* Const version of data().
*/
EIGEN_STRONG_INLINE
const Scalar* data() const {
// rxso3_ and translation_ are layed out sequentially with no padding
return rxso3_.data();
}
/**
* \brief Accessor of RxSO3
*/
EIGEN_STRONG_INLINE
RxSO3Reference rxso3() {
return rxso3_;
}
/**
* \brief Mutator of RxSO3
*/
EIGEN_STRONG_INLINE
ConstRxSO3Reference rxso3() const {
return rxso3_;
}
/**
* \brief Mutator of translation vector
*/
EIGEN_STRONG_INLINE
TranslationReference translation() {
return translation_;
}
/**
* \brief Accessor of translation vector
*/
EIGEN_STRONG_INLINE
ConstTranslationReference translation() const {
return translation_;
}
protected:
Sophus::RxSO3Group<Scalar> rxso3_;
Matrix<Scalar,3,1> translation_;
};
} // end namespace
namespace Eigen {
/**
* \brief Specialisation of Eigen::Map for Sim3GroupBase
*
* Allows us to wrap Sim3 Objects around POD array
* (e.g. external c style quaternion)
*/
template<typename _Scalar, int _Options>
class Map<Sophus::Sim3Group<_Scalar>, _Options>
: public Sophus::Sim3GroupBase<Map<Sophus::Sim3Group<_Scalar>, _Options> > {
typedef Sophus::Sim3GroupBase<Map<Sophus::Sim3Group<_Scalar>, _Options> >
Base;
public:
/** \brief scalar type */
typedef typename internal::traits<Map>::Scalar Scalar;
/** \brief translation reference type */
typedef typename internal::traits<Map>::TranslationType &
TranslationReference;
/** \brief translation const reference type */
typedef const typename internal::traits<Map>::TranslationType &
ConstTranslationReference;
/** \brief RxSO3 reference type */
typedef typename internal::traits<Map>::RxSO3Type &
RxSO3Reference;
/** \brief RxSO3 const reference type */
typedef const typename internal::traits<Map>::RxSO3Type &
ConstRxSO3Reference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
using Base::operator*=;
using Base::operator*;
EIGEN_STRONG_INLINE
Map(Scalar* coeffs)
: rxso3_(coeffs),
translation_(coeffs+Sophus::RxSO3Group<Scalar>::num_parameters) {
}
/**
* \brief Mutator of RxSO3
*/
EIGEN_STRONG_INLINE
RxSO3Reference rxso3() {
return rxso3_;
}
/**
* \brief Accessor of RxSO3
*/
EIGEN_STRONG_INLINE
ConstRxSO3Reference rxso3() const {
return rxso3_;
}
/**
* \brief Mutator of translation vector
*/
EIGEN_STRONG_INLINE
TranslationReference translation() {
return translation_;
}
/**
* \brief Accessor of translation vector
*/
EIGEN_STRONG_INLINE
ConstTranslationReference translation() const {
return translation_;
}
protected:
Map<Sophus::RxSO3Group<Scalar>,_Options> rxso3_;
Map<Matrix<Scalar,3,1>,_Options> translation_;
};
/**
* \brief Specialisation of Eigen::Map for const Sim3GroupBase
*
* Allows us to wrap Sim3 Objects around POD array
* (e.g. external c style quaternion)
*/
template<typename _Scalar, int _Options>
class Map<const Sophus::Sim3Group<_Scalar>, _Options>
: public Sophus::Sim3GroupBase<
Map<const Sophus::Sim3Group<_Scalar>, _Options> > {
typedef Sophus::Sim3GroupBase<
Map<const Sophus::Sim3Group<_Scalar>, _Options> > Base;
public:
/** \brief scalar type */
typedef typename internal::traits<Map>::Scalar Scalar;
/** \brief translation type */
typedef const typename internal::traits<Map>::TranslationType &
ConstTranslationReference;
/** \brief RxSO3 const reference type */
typedef const typename internal::traits<Map>::RxSO3Type &
ConstRxSO3Reference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
using Base::operator*=;
using Base::operator*;
EIGEN_STRONG_INLINE
Map(const Scalar* coeffs)
: rxso3_(coeffs),
translation_(coeffs+Sophus::RxSO3Group<Scalar>::num_parameters) {
}
EIGEN_STRONG_INLINE
Map(const Scalar* trans_coeffs, const Scalar* rot_coeffs)
: translation_(trans_coeffs), rxso3_(rot_coeffs){
}
/**
* \brief Accessor of RxSO3
*/
EIGEN_STRONG_INLINE
ConstRxSO3Reference rxso3() const {
return rxso3_;
}
/**
* \brief Accessor of translation vector
*/
EIGEN_STRONG_INLINE
ConstTranslationReference translation() const {
return translation_;
}
protected:
const Map<const Sophus::RxSO3Group<Scalar>,_Options> rxso3_;
const Map<const Matrix<Scalar,3,1>,_Options> translation_;
};
}
#endif

701
thirdparty/Sophus/sophus/so2.hpp vendored Normal file
View File

@@ -0,0 +1,701 @@
// This file is part of Sophus.
//
// Copyright 2012-2013 Hauke Strasdat
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#ifndef SOPHUS_SO2_HPP
#define SOPHUS_SO2_HPP
#include <complex>
#include "sophus.hpp"
////////////////////////////////////////////////////////////////////////////
// Forward Declarations / typedefs
////////////////////////////////////////////////////////////////////////////
namespace Sophus {
template<typename _Scalar, int _Options=0> class SO2Group;
typedef SO2Group<double> SO2 EIGEN_DEPRECATED;
typedef SO2Group<double> SO2d; /**< double precision SO2 */
typedef SO2Group<float> SO2f; /**< single precision SO2 */
}
////////////////////////////////////////////////////////////////////////////
// Eigen Traits (For querying derived types in CRTP hierarchy)
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// Eigen Traits (For querying derived types in CRTP hierarchy)
////////////////////////////////////////////////////////////////////////////
namespace Eigen {
namespace internal {
template<typename _Scalar, int _Options>
struct traits<Sophus::SO2Group<_Scalar,_Options> > {
typedef _Scalar Scalar;
typedef Matrix<Scalar,2,1> ComplexType;
};
template<typename _Scalar, int _Options>
struct traits<Map<Sophus::SO2Group<_Scalar>, _Options> >
: traits<Sophus::SO2Group<_Scalar, _Options> > {
typedef _Scalar Scalar;
typedef Map<Matrix<Scalar,2,1>,_Options> ComplexType;
};
template<typename _Scalar, int _Options>
struct traits<Map<const Sophus::SO2Group<_Scalar>, _Options> >
: traits<const Sophus::SO2Group<_Scalar, _Options> > {
typedef _Scalar Scalar;
typedef Map<const Matrix<Scalar,2,1>,_Options> ComplexType;
};
}
}
namespace Sophus {
using namespace Eigen;
/**
* \brief SO2 base type - implements SO2 class but is storage agnostic
*
* [add more detailed description/tutorial]
*/
template<typename Derived>
class SO2GroupBase {
public:
/** \brief scalar type */
typedef typename internal::traits<Derived>::Scalar Scalar;
/** \brief complex number reference type */
typedef typename internal::traits<Derived>::ComplexType &
ComplexReference;
/** \brief complex number const reference type */
typedef const typename internal::traits<Derived>::ComplexType &
ConstComplexReference;
/** \brief degree of freedom of group
* (one for in-plane rotation) */
static const int DoF = 1;
/** \brief number of internal parameters used
* (unit complex number for rotation) */
static const int num_parameters = 2;
/** \brief group transformations are NxN matrices */
static const int N = 2;
/** \brief group transfomation type */
typedef Matrix<Scalar,N,N> Transformation;
/** \brief point type */
typedef Matrix<Scalar,2,1> Point;
/** \brief tangent vector type */
typedef Scalar Tangent;
/** \brief adjoint transformation type */
typedef Scalar Adjoint;
/**
* \brief Adjoint transformation
*
* This function return the adjoint transformation \f$ Ad \f$ of the
* group instance \f$ A \f$ such that for all \f$ x \f$
* it holds that \f$ \widehat{Ad_A\cdot x} = A\widehat{x}A^{-1} \f$
* with \f$\ \widehat{\cdot} \f$ being the hat()-operator.
*
* For SO2, it simply returns 1.
*/
inline
const Adjoint Adj() const {
return 1;
}
/**
* \returns copy of instance casted to NewScalarType
*/
template<typename NewScalarType>
inline SO2Group<NewScalarType> cast() const {
return SO2Group<NewScalarType>(unit_complex()
.template cast<NewScalarType>() );
}
/**
* \returns pointer to internal data
*
* This provides unsafe read/write access to internal data. SO2 is represented
* by a complex number with unit length (two parameters). When using direct
* write access, the user needs to take care of that the complex number stays
* normalized.
*
* \see normalize()
*/
inline Scalar* data() {
return unit_complex_nonconst().data();
}
/**
* \returns const pointer to internal data
*
* Const version of data().
*/
inline const Scalar* data() const {
return unit_complex().data();
}
/**
* \brief Fast group multiplication
*
* This method is a fast version of operator*=(), since it does not perform
* normalization. It is up to the user to call normalize() once in a while.
*
* \see operator*=()
*/
inline
void fastMultiply(const SO2Group<Scalar>& other) {
Scalar lhs_real = unit_complex().x();
Scalar lhs_imag = unit_complex().y();
const Scalar & rhs_real = other.unit_complex().x();
const Scalar & rhs_imag = other.unit_complex().y();
// complex multiplication
unit_complex_nonconst().x() = lhs_real*rhs_real - lhs_imag*rhs_imag;
unit_complex_nonconst().y() = lhs_real*rhs_imag + lhs_imag*rhs_real;
}
/**
* \returns group inverse of instance
*/
inline
const SO2Group<Scalar> inverse() const {
return SO2Group<Scalar>(unit_complex().x(), -unit_complex().y());
}
/**
* \brief Logarithmic map
*
* \returns tangent space representation (=rotation angle) of instance
*
* \see log().
*/
inline
const Scalar log() const {
return SO2Group<Scalar>::log(*this);
}
/**
* \brief Normalize complex number
*
* It re-normalizes complex number to unit length. This method only needs to
* be called in conjunction with fastMultiply() or data() write access.
*/
inline
void normalize() {
Scalar length =
std::sqrt(unit_complex().x()*unit_complex().x()
+ unit_complex().y()*unit_complex().y());
if(length < SophusConstants<Scalar>::epsilon()) {
throw SophusException("Complex number is (near) zero!");
}
unit_complex_nonconst().x() /= length;
unit_complex_nonconst().y() /= length;
}
/**
* \returns 2x2 matrix representation of instance
*
* For SO2, the matrix representation is an orthogonal matrix R with det(R)=1,
* thus the so-called rotation matrix.
*/
inline
const Transformation matrix() const {
const Scalar & real = unit_complex().x();
const Scalar & imag = unit_complex().y();
Transformation R;
R << real, -imag
,imag, real;
return R;
}
/**
* \brief Assignment operator
*/
template<typename OtherDerived> inline
SO2GroupBase<Derived>& operator=(const SO2GroupBase<OtherDerived> & other) {
unit_complex_nonconst() = other.unit_complex();
return *this;
}
/**
* \brief Group multiplication
* \see operator*=()
*/
inline
const SO2Group<Scalar> operator*(const SO2Group<Scalar>& other) const {
SO2Group<Scalar> result(*this);
result *= other;
return result;
}
/**
* \brief Group action on \f$ \mathbf{R}^2 \f$
*
* \param p point \f$p \in \mathbf{R}^2 \f$
* \returns point \f$p' \in \mathbf{R}^2 \f$, rotated version of \f$p\f$
*
* This function rotates a point \f$ p \f$ in \f$ \mathbf{R}^2 \f$ by the
* SO2 transformation \f$R\f$ (=rotation matrix): \f$ p' = R\cdot p \f$.
*/
inline
const Point operator*(const Point & p) const {
const Scalar & real = unit_complex().x();
const Scalar & imag = unit_complex().y();
return Point(real*p[0] - imag*p[1], imag*p[0] + real*p[1]);
}
/**
* \brief In-place group multiplication
*
* \see fastMultiply()
* \see operator*()
*/
inline
void operator*=(const SO2Group<Scalar>& other) {
fastMultiply(other);
normalize();
}
/**
* \brief Setter of internal unit complex number representation
*
* \param complex
* \pre the complex number must not be near zero
*
* The complex number is normalized to unit length.
*/
inline
void setComplex(const Point & complex) {
unit_complex() = complex;
normalize();
}
/**
* \brief Accessor of unit complex number
*
* No direct write access is given to ensure the complex stays normalized.
*/
EIGEN_STRONG_INLINE
ConstComplexReference unit_complex() const {
return static_cast<const Derived*>(this)->unit_complex();
}
////////////////////////////////////////////////////////////////////////////
// public static functions
////////////////////////////////////////////////////////////////////////////
/**
* \brief Group exponential
*
* \param theta tangent space element (=rotation angle \f$ \theta \f$)
* \returns corresponding element of the group SO2
*
* To be more specific, this function computes \f$ \exp(\widehat{\theta}) \f$
* with \f$ \exp(\cdot) \f$ being the matrix exponential
* and \f$ \widehat{\cdot} \f$ the hat()-operator of SO2.
*
* \see hat()
* \see log()
*/
inline static
const SO2Group<Scalar> exp(const Tangent & theta) {
return SO2Group<Scalar>(std::cos(theta), std::sin(theta));
}
/**
* \brief Generator
*
* The infinitesimal generator of SO2
* is \f$
* G_0 = \left( \begin{array}{ccc}
* 0& -1& \\
* 1& 0&
* \end{array} \right).
* \f$
* \see hat()
*/
inline static
const Transformation generator() {
return hat(1);
}
/**
* \brief hat-operator
*
* \param theta scalar representation of Lie algebra element
* \returns 2x2-matrix representatin of Lie algebra element
*
* Formally, the hat-operator of SO2 is defined
* as \f$ \widehat{\cdot}: \mathbf{R}^2 \rightarrow \mathbf{R}^{2\times 2},
* \quad \widehat{\theta} = G_0\cdot \theta \f$
* with \f$ G_0 \f$ being the infinitesial generator().
*
* \see generator()
* \see vee()
*/
inline static
const Transformation hat(const Tangent & theta) {
Transformation Omega;
Omega << static_cast<Scalar>(0), -theta
, theta, static_cast<Scalar>(0);
return Omega;
}
/**
* \brief Lie bracket
*
* \param theta1 scalar representation of Lie algebra element
* \param theta2 scalar representation of Lie algebra element
* \returns zero
*
* It computes the bracket. For the Lie algebra so2, the Lie bracket is
* simply \f$ [\theta_1, \theta_2]_{so2} = 0 \f$ since SO2 is a
* commutative group.
*
* \see hat()
* \see vee()
*/
inline static
const Tangent lieBracket(const Tangent & theta1,
const Tangent & theta2) {
return static_cast<Scalar>(0);
}
/**
* \brief Logarithmic map
*
* \param other element of the group SO2
* \returns corresponding tangent space element
* (=rotation angle \f$ \theta \f$)
*
* Computes the logarithmic, the inverse of the group exponential.
* To be specific, this function computes \f$ \log({\cdot})^\vee \f$
* with \f$ \vee(\cdot) \f$ being the matrix logarithm
* and \f$ \vee{\cdot} \f$ the vee()-operator of SO2.
*
* \see exp()
* \see vee()
*/
inline static
const Tangent log(const SO2Group<Scalar> & other) {
// todo: general implementation for Scalar not being float or double.
return atan2(other.unit_complex_.y(), other.unit_complex().x());
}
/**
* \brief vee-operator
*
* \param Omega 2x2-matrix representation of Lie algebra element
* \pre Omega need to be a skew-symmetric matrix
* \returns scalar representatin of Lie algebra element
*s
* This is the inverse of the hat()-operator.
*
* \see hat()
*/
inline static
const Tangent vee(const Transformation & Omega) {
return static_cast<Scalar>(0.5)*(Omega(1,0) - Omega(0,1));
}
private:
// Mutator of complex number is private so users are hampered
// from setting non-unit complex numbers.
EIGEN_STRONG_INLINE
ComplexReference unit_complex_nonconst() {
return static_cast<Derived*>(this)->unit_complex_nonconst();
}
};
/**
* \brief SO2 default type - Constructors and default storage for SO2 Type
*/
template<typename _Scalar, int _Options>
class SO2Group : public SO2GroupBase<SO2Group<_Scalar,_Options> > {
typedef SO2GroupBase<SO2Group<_Scalar,_Options> > Base;
public:
/** \brief scalar type */
typedef typename internal::traits<SO2Group<_Scalar,_Options> >
::Scalar Scalar;
/** \brief complex number reference type */
typedef typename internal::traits<SO2Group<_Scalar,_Options> >
::ComplexType & ComplexReference;
/** \brief complex number const reference type */
typedef const typename internal::traits<SO2Group<_Scalar,_Options> >
::ComplexType & ConstComplexReference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
// base is friend so unit_complex_nonconst can be accessed from base
friend class SO2GroupBase<SO2Group<_Scalar,_Options> >;
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
/**
* \brief Default constructor
*
* Initialize complex number to identity rotation.
*/
inline SO2Group()
: unit_complex_(static_cast<Scalar>(1), static_cast<Scalar>(0)) {
}
/**
* \brief Copy constructor
*/
template<typename OtherDerived> inline
SO2Group(const SO2GroupBase<OtherDerived> & other)
: unit_complex_(other.unit_complex()) {
}
/**
* \brief Constructor from rotation matrix
*
* \pre rotation matrix need to be orthogonal with determinant of 1
*/
inline explicit
SO2Group(const Transformation & R)
: unit_complex_(static_cast<Scalar>(0.5)*(R(0,0)+R(1,1)),
static_cast<Scalar>(0.5)*(R(1,0)-R(0,1))) {
if (std::abs(R.determinant()-static_cast<Scalar>(1))
> SophusConstants<Scalar>::epsilon()) {
throw SophusException("det(R) is not near 1.");
}
}
/**
* \brief Constructor from pair of real and imaginary number
*
* \pre pair must not be zero
*/
inline SO2Group(const Scalar & real, const Scalar & imag)
: unit_complex_(real, imag) {
Base::normalize();
}
/**
* \brief Constructor from 2-vector
*
* \pre vector must not be zero
*/
inline explicit
SO2Group(const Matrix<Scalar,2,1> & complex)
: unit_complex_(complex) {
Base::normalize();
}
/**
* \brief Constructor from std::complex
*
* \pre complex number must not be zero
*/
inline explicit
SO2Group(const std::complex<Scalar> & complex)
: unit_complex_(complex.real(), complex.imag()) {
Base::normalize();
}
/**
* \brief Constructor from an angle
*/
inline explicit
SO2Group(Scalar theta) {
unit_complex_nonconst() = SO2Group<Scalar>::exp(theta).unit_complex();
}
/**
* \brief Accessor of unit complex number
*
* No direct write access is given to ensure the complex number stays
* normalized.
*/
EIGEN_STRONG_INLINE
ConstComplexReference unit_complex() const {
return unit_complex_;
}
protected:
// Mutator of complex number is protected so users are hampered
// from setting non-unit complex numbers.
EIGEN_STRONG_INLINE
ComplexReference unit_complex_nonconst() {
return unit_complex_;
}
static bool isNearZero(const Scalar & real, const Scalar & imag) {
return (real*real + imag*imag < SophusConstants<Scalar>::epsilon());
}
Matrix<Scalar,2,1> unit_complex_;
};
} // end namespace
namespace Eigen {
/**
* \brief Specialisation of Eigen::Map for SO2GroupBase
*
* Allows us to wrap SO2 Objects around POD array
* (e.g. external c style complex number)
*/
template<typename _Scalar, int _Options>
class Map<Sophus::SO2Group<_Scalar>, _Options>
: public Sophus::SO2GroupBase<Map<Sophus::SO2Group<_Scalar>, _Options> > {
typedef Sophus::SO2GroupBase<Map<Sophus::SO2Group<_Scalar>, _Options> > Base;
public:
/** \brief scalar type */
typedef typename internal::traits<Map>::Scalar Scalar;
/** \brief complex number reference type */
typedef typename internal::traits<Map>::ComplexType & ComplexReference;
/** \brief complex number const reference type */
typedef const typename internal::traits<Map>::ComplexType &
ConstComplexReference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
// base is friend so unit_complex_nonconst can be accessed from base
friend class Sophus::SO2GroupBase<Map<Sophus::SO2Group<_Scalar>, _Options> >;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
using Base::operator*=;
using Base::operator*;
EIGEN_STRONG_INLINE
Map(Scalar* coeffs) : unit_complex_(coeffs) {
}
/**
* \brief Accessor of unit complex number
*
* No direct write access is given to ensure the complex number stays
* normalized.
*/
EIGEN_STRONG_INLINE
ConstComplexReference unit_complex() const {
return unit_complex_;
}
protected:
// Mutator of complex number is protected so users are hampered
// from setting non-unit complex number.
EIGEN_STRONG_INLINE
ComplexReference unit_complex_nonconst() {
return unit_complex_;
}
Map<Matrix<Scalar,2,1>,_Options> unit_complex_;
};
/**
* \brief Specialisation of Eigen::Map for const SO2GroupBase
*
* Allows us to wrap SO2 Objects around POD array
* (e.g. external c style complex number)
*/
template<typename _Scalar, int _Options>
class Map<const Sophus::SO2Group<_Scalar>, _Options>
: public Sophus::SO2GroupBase<
Map<const Sophus::SO2Group<_Scalar>, _Options> > {
typedef Sophus::SO2GroupBase<Map<const Sophus::SO2Group<_Scalar>, _Options> >
Base;
public:
/** \brief scalar type */
typedef typename internal::traits<Map>::Scalar Scalar;
/** \brief complex number const reference type */
typedef const typename internal::traits<Map>::ComplexType &
ConstComplexReference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
using Base::operator*=;
using Base::operator*;
EIGEN_STRONG_INLINE
Map(const Scalar* coeffs) : unit_complex_(coeffs) {
}
/**
* \brief Accessor of unit complex number
*
* No direct write access is given to ensure the complex number stays
* normalized.
*/
EIGEN_STRONG_INLINE
ConstComplexReference unit_complex() const {
return unit_complex_;
}
protected:
const Map<const Matrix<Scalar,2,1>,_Options> unit_complex_;
};
}
#endif // SOPHUS_SO2_HPP

811
thirdparty/Sophus/sophus/so3.hpp vendored Normal file
View File

@@ -0,0 +1,811 @@
// This file is part of Sophus.
//
// Copyright 2011-2013 Hauke Strasdat
// Copyrifht 2012-2013 Steven Lovegrove
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#ifndef SOPHUS_SO3_HPP
#define SOPHUS_SO3_HPP
#include "sophus.hpp"
////////////////////////////////////////////////////////////////////////////
// Forward Declarations / typedefs
////////////////////////////////////////////////////////////////////////////
namespace Sophus {
template<typename _Scalar, int _Options=0> class SO3Group;
typedef EIGEN_DEPRECATED SO3Group<double> SO3;
typedef SO3Group<double> SO3d; /**< double precision SO3 */
typedef SO3Group<float> SO3f; /**< single precision SO3 */
}
////////////////////////////////////////////////////////////////////////////
// Eigen Traits (For querying derived types in CRTP hierarchy)
////////////////////////////////////////////////////////////////////////////
namespace Eigen {
namespace internal {
template<typename _Scalar, int _Options>
struct traits<Sophus::SO3Group<_Scalar,_Options> > {
typedef _Scalar Scalar;
typedef Quaternion<Scalar> QuaternionType;
};
template<typename _Scalar, int _Options>
struct traits<Map<Sophus::SO3Group<_Scalar>, _Options> >
: traits<Sophus::SO3Group<_Scalar, _Options> > {
typedef _Scalar Scalar;
typedef Map<Quaternion<Scalar>,_Options> QuaternionType;
};
template<typename _Scalar, int _Options>
struct traits<Map<const Sophus::SO3Group<_Scalar>, _Options> >
: traits<const Sophus::SO3Group<_Scalar, _Options> > {
typedef _Scalar Scalar;
typedef Map<const Quaternion<Scalar>,_Options> QuaternionType;
};
}
}
namespace Sophus {
using namespace Eigen;
/**
* \brief SO3 base type - implements SO3 class but is storage agnostic
*
* [add more detailed description/tutorial]
*/
template<typename Derived>
class SO3GroupBase {
public:
/** \brief scalar type */
typedef typename internal::traits<Derived>::Scalar Scalar;
/** \brief quaternion reference type */
typedef typename internal::traits<Derived>::QuaternionType &
QuaternionReference;
/** \brief quaternion const reference type */
typedef const typename internal::traits<Derived>::QuaternionType &
ConstQuaternionReference;
/** \brief degree of freedom of group
* (three for rotation) */
static const int DoF = 3;
/** \brief number of internal parameters used
* (unit quaternion for rotation) */
static const int num_parameters = 4;
/** \brief group transformations are NxN matrices */
static const int N = 3;
/** \brief group transfomation type */
typedef Matrix<Scalar,N,N> Transformation;
/** \brief point type */
typedef Matrix<Scalar,3,1> Point;
/** \brief tangent vector type */
typedef Matrix<Scalar,DoF,1> Tangent;
/** \brief adjoint transformation type */
typedef Matrix<Scalar,DoF,DoF> Adjoint;
/**
* \brief Adjoint transformation
*
* This function return the adjoint transformation \f$ Ad \f$ of the
* group instance \f$ A \f$ such that for all \f$ x \f$
* it holds that \f$ \widehat{Ad_A\cdot x} = A\widehat{x}A^{-1} \f$
* with \f$\ \widehat{\cdot} \f$ being the hat()-Vector4Scalaror.
*
* For SO3, it simply returns the rotation matrix corresponding to \f$ A \f$.
*/
inline
const Adjoint Adj() const {
return matrix();
}
/**
* \returns copy of instance casted to NewScalarType
*/
template<typename NewScalarType>
inline SO3Group<NewScalarType> cast() const {
return SO3Group<NewScalarType>(unit_quaternion()
.template cast<NewScalarType>() );
}
/**
* \returns pointer to internal data
*
* This provides unsafe read/write access to internal data. SO3 is represented
* by an Eigen::Quaternion (four parameters). When using direct write access,
* the user needs to take care of that the quaternion stays normalized.
*
* Note: The first three Scalars represent the imaginary parts, while the
* forth Scalar represent the real part.
*
* \see normalize()
*/
inline Scalar* data() {
return unit_quaternion_nonconst().coeffs().data();
}
/**
* \returns const pointer to internal data
*
* Const version of data().
*/
inline const Scalar* data() const {
return unit_quaternion().coeffs().data();
}
/**
* \brief Fast group multiplication
*
* This method is a fast version of operator*=(), since it does not perform
* normalization. It is up to the user to call normalize() once in a while.
*
* \see operator*=()
*/
inline
void fastMultiply(const SO3Group<Scalar>& other) {
unit_quaternion_nonconst() *= other.unit_quaternion();
}
/**
* \returns group inverse of instance
*/
inline
const SO3Group<Scalar> inverse() const {
return SO3Group<Scalar>(unit_quaternion().conjugate());
}
/**
* \brief Logarithmic map
*
* \returns tangent space representation (=rotation vector) of instance
*
* \see log().
*/
inline
const Tangent log() const {
return SO3Group<Scalar>::log(*this);
}
/**
* \brief Normalize quaternion
*
* It re-normalizes unit_quaternion to unit length. This method only needs to
* be called in conjunction with fastMultiply() or data() write access.
*/
inline
void normalize() {
Scalar length = unit_quaternion_nonconst().norm();
if (length < SophusConstants<Scalar>::epsilon()) {
throw SophusException("Quaternion is (near) zero!");
}
unit_quaternion_nonconst().coeffs() /= length;
}
/**
* \returns 3x3 matrix representation of instance
*
* For SO3, the matrix representation is an orthogonal matrix R with det(R)=1,
* thus the so-called rotation matrix.
*/
inline
const Transformation matrix() const {
return unit_quaternion().toRotationMatrix();
}
/**
* \brief Assignment operator
*/
template<typename OtherDerived> inline
SO3GroupBase<Derived>& operator=(const SO3GroupBase<OtherDerived> & other) {
unit_quaternion_nonconst() = other.unit_quaternion();
return *this;
}
/**
* \brief Group multiplication
* \see operator*=()
*/
inline
const SO3Group<Scalar> operator*(const SO3Group<Scalar>& other) const {
SO3Group<Scalar> result(*this);
result *= other;
return result;
}
/**
* \brief Group action on \f$ \mathbf{R}^3 \f$
*
* \param p point \f$p \in \mathbf{R}^3 \f$
* \returns point \f$p' \in \mathbf{R}^3 \f$, rotated version of \f$p\f$
*
* This function rotates a point \f$ p \f$ in \f$ \mathbf{R}^3 \f$ by the
* SO3 transformation \f$R\f$ (=rotation matrix): \f$ p' = R\cdot p \f$.
*
*
* Since SO3 is intenally represented by a unit quaternion \f$q\f$, it is
* implemented as \f$ p' = q\cdot p \cdot q^{*} \f$
* with \f$ q^{*} \f$ being the quaternion conjugate of \f$ q \f$.
*
* Geometrically, \f$ p \f$ is rotated by angle \f$|\omega|\f$ around the
* axis \f$\frac{\omega}{|\omega|}\f$ with \f$ \omega = \log(R)^\vee \f$.
*
* \see log()
*/
inline
const Point operator*(const Point & p) const {
return unit_quaternion()._transformVector(p);
}
/**
* \brief In-place group multiplication
*
* \see fastMultiply()
* \see operator*()
*/
inline
void operator*=(const SO3Group<Scalar>& other) {
fastMultiply(other);
normalize();
}
/**
* \brief Setter of internal unit quaternion representation
*
* \param quaternion
* \pre the quaternion must not be zero
*
* The quaternion is normalized to unit length.
*/
inline
void setQuaternion(const Quaternion<Scalar>& quaternion) {
unit_quaternion_nonconst() = quaternion;
normalize();
}
/**
* \brief Accessor of unit quaternion
*
* No direct write access is given to ensure the quaternion stays normalized.
*/
EIGEN_STRONG_INLINE
ConstQuaternionReference unit_quaternion() const {
return static_cast<const Derived*>(this)->unit_quaternion();
}
////////////////////////////////////////////////////////////////////////////
// public static functions
////////////////////////////////////////////////////////////////////////////
/**
* \param b 3-vector representation of Lie algebra element
* \returns derivative of Lie bracket
*
* This function returns \f$ \frac{\partial}{\partial a} [a, b]_{so3} \f$
* with \f$ [a, b]_{so3} \f$ being the lieBracket() of the Lie algebra so3.
*
* \see lieBracket()
*/
inline static
const Adjoint d_lieBracketab_by_d_a(const Tangent & b) {
return -hat(b);
}
/**
* \brief Group exponential
*
* \param omega tangent space element (=rotation vector \f$ \omega \f$)
* \returns corresponding element of the group SO3
*
* To be more specific, this function computes \f$ \exp(\widehat{\omega}) \f$
* with \f$ \exp(\cdot) \f$ being the matrix exponential
* and \f$ \widehat{\cdot} \f$ the hat()-operator of SO3.
*
* \see expAndTheta()
* \see hat()
* \see log()
*/
inline static
const SO3Group<Scalar> exp(const Tangent & omega) {
Scalar theta;
return expAndTheta(omega, &theta);
}
/**
* \brief Group exponential and theta
*
* \param omega tangent space element (=rotation vector \f$ \omega \f$)
* \param[out] theta angle of rotation \f$ \theta = |\omega| \f$
* \returns corresponding element of the group SO3
*
* \see exp() for details
*/
inline static
const SO3Group<Scalar> expAndTheta(const Tangent & omega,
Scalar * theta) {
const Scalar theta_sq = omega.squaredNorm();
*theta = std::sqrt(theta_sq);
const Scalar half_theta = static_cast<Scalar>(0.5)*(*theta);
Scalar imag_factor;
Scalar real_factor;;
if((*theta)<SophusConstants<Scalar>::epsilon()) {
const Scalar theta_po4 = theta_sq*theta_sq;
imag_factor = static_cast<Scalar>(0.5)
- static_cast<Scalar>(1.0/48.0)*theta_sq
+ static_cast<Scalar>(1.0/3840.0)*theta_po4;
real_factor = static_cast<Scalar>(1)
- static_cast<Scalar>(0.5)*theta_sq +
static_cast<Scalar>(1.0/384.0)*theta_po4;
} else {
const Scalar sin_half_theta = std::sin(half_theta);
imag_factor = sin_half_theta/(*theta);
real_factor = std::cos(half_theta);
}
return SO3Group<Scalar>(Quaternion<Scalar>(real_factor,
imag_factor*omega.x(),
imag_factor*omega.y(),
imag_factor*omega.z()));
}
/**
* \brief Generators
*
* \pre \f$ i \in \{0,1,2\} \f$
* \returns \f$ i \f$th generator \f$ G_i \f$ of SO3
*
* The infinitesimal generators of SO3
* are \f$
* G_0 = \left( \begin{array}{ccc}
* 0& 0& 0& \\
* 0& 0& -1& \\
* 0& 1& 0&
* \end{array} \right),
* G_1 = \left( \begin{array}{ccc}
* 0& 0& 1& \\
* 0& 0& 0& \\
* -1& 0& 0&
* \end{array} \right),
* G_2 = \left( \begin{array}{ccc}
* 0& -1& 0& \\
* 1& 0& 0& \\
* 0& 0& 0&
* \end{array} \right).
* \f$
* \see hat()
*/
inline static
const Transformation generator(int i) {
if (i<0 || i>2) {
throw SophusException("i is not in range [0,2].");
}
Tangent e;
e.setZero();
e[i] = static_cast<Scalar>(1);
return hat(e);
}
/**
* \brief hat-operator
*
* \param omega 3-vector representation of Lie algebra element
* \returns 3x3-matrix representatin of Lie algebra element
*
* Formally, the hat-operator of SO3 is defined
* as \f$ \widehat{\cdot}: \mathbf{R}^3 \rightarrow \mathbf{R}^{3\times 3},
* \quad \widehat{\omega} = \sum_{i=0}^2 G_i \omega_i \f$
* with \f$ G_i \f$ being the ith infinitesial generator().
*
* \see generator()
* \see vee()
*/
inline static
const Transformation hat(const Tangent & omega) {
Transformation Omega;
Omega << static_cast<Scalar>(0), -omega(2), omega(1)
, omega(2), static_cast<Scalar>(0), -omega(0)
, -omega(1), omega(0), static_cast<Scalar>(0);
return Omega;
}
/**
* \brief Lie bracket
*
* \param omega1 3-vector representation of Lie algebra element
* \param omega2 3-vector representation of Lie algebra element
* \returns 3-vector representation of Lie algebra element
*
* It computes the bracket of SO3. To be more specific, it
* computes \f$ [\omega_1, \omega_2]_{so3}
* := [\widehat{\omega_1}, \widehat{\omega_2}]^\vee \f$
* with \f$ [A,B] = AB-BA \f$ being the matrix
* commutator, \f$ \widehat{\cdot} \f$ the
* hat()-operator and \f$ (\cdot)^\vee \f$ the vee()-operator of SO3.
*
* For the Lie algebra so3, the Lie bracket is simply the
* cross product: \f$ [\omega_1, \omega_2]_{so3}
* = \omega_1 \times \omega_2 \f$.
*
* \see hat()
* \see vee()
*/
inline static
const Tangent lieBracket(const Tangent & omega1,
const Tangent & omega2) {
return omega1.cross(omega2);
}
/**
* \brief Logarithmic map
*
* \param other element of the group SO3
* \returns corresponding tangent space element
* (=rotation vector \f$ \omega \f$)
*
* Computes the logarithmic, the inverse of the group exponential.
* To be specific, this function computes \f$ \log({\cdot})^\vee \f$
* with \f$ \vee(\cdot) \f$ being the matrix logarithm
* and \f$ \vee{\cdot} \f$ the vee()-operator of SO3.
*
* \see exp()
* \see logAndTheta()
* \see vee()
*/
inline static
const Tangent log(const SO3Group<Scalar> & other) {
Scalar theta;
return logAndTheta(other, &theta);
}
/**
* \brief Logarithmic map and theta
*
* \param other element of the group SO3
* \param[out] theta angle of rotation \f$ \theta = |\omega| \f$
* \returns corresponding tangent space element
* (=rotation vector \f$ \omega \f$)
*
* \see log() for details
*/
inline static
const Tangent logAndTheta(const SO3Group<Scalar> & other,
Scalar * theta) {
const Scalar squared_n
= other.unit_quaternion().vec().squaredNorm();
const Scalar n = std::sqrt(squared_n);
const Scalar w = other.unit_quaternion().w();
Scalar two_atan_nbyw_by_n;
// Atan-based log thanks to
//
// C. Hertzberg et al.:
// "Integrating Generic Sensor Fusion Algorithms with Sound State
// Representation through Encapsulation of Manifolds"
// Information Fusion, 2011
if (n < SophusConstants<Scalar>::epsilon()) {
// If quaternion is normalized and n=0, then w should be 1;
// w=0 should never happen here!
if (std::abs(w) < SophusConstants<Scalar>::epsilon()) {
throw SophusException("Quaternion is not normalized!");
}
const Scalar squared_w = w*w;
two_atan_nbyw_by_n = static_cast<Scalar>(2) / w
- static_cast<Scalar>(2)*(squared_n)/(w*squared_w);
} else {
if (std::abs(w)<SophusConstants<Scalar>::epsilon()) {
if (w > static_cast<Scalar>(0)) {
two_atan_nbyw_by_n = M_PI/n;
} else {
two_atan_nbyw_by_n = -M_PI/n;
}
}else{
two_atan_nbyw_by_n = static_cast<Scalar>(2) * atan(n/w) / n;
}
}
*theta = two_atan_nbyw_by_n*n;
return two_atan_nbyw_by_n * other.unit_quaternion().vec();
}
/**
* \brief vee-operator
*
* \param Omega 3x3-matrix representation of Lie algebra element
* \pr Omega must be a skew-symmetric matrix
* \returns 3-vector representatin of Lie algebra element
*
* This is the inverse of the hat()-operator.
*
* \see hat()
*/
inline static
const Tangent vee(const Transformation & Omega) {
return static_cast<Scalar>(0.5) * Tangent(Omega(2,1) - Omega(1,2),
Omega(0,2) - Omega(2,0),
Omega(1,0) - Omega(0,1));
}
private:
// Mutator of unit_quaternion is private so users are hampered
// from setting non-unit quaternions.
EIGEN_STRONG_INLINE
QuaternionReference unit_quaternion_nonconst() {
return static_cast<Derived*>(this)->unit_quaternion_nonconst();
}
};
/**
* \brief SO3 default type - Constructors and default storage for SO3 Type
*/
template<typename _Scalar, int _Options>
class SO3Group : public SO3GroupBase<SO3Group<_Scalar,_Options> > {
typedef SO3GroupBase<SO3Group<_Scalar,_Options> > Base;
public:
/** \brief scalar type */
typedef typename internal::traits<SO3Group<_Scalar,_Options> >
::Scalar Scalar;
/** \brief quaternion type */
typedef typename internal::traits<SO3Group<_Scalar,_Options> >
::QuaternionType & QuaternionReference;
typedef const typename internal::traits<SO3Group<_Scalar,_Options> >
::QuaternionType & ConstQuaternionReference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
// base is friend so unit_quaternion_nonconst can be accessed from base
friend class SO3GroupBase<SO3Group<_Scalar,_Options> >;
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
/**
* \brief Default constructor
*
* Initialize Quaternion to identity rotation.
*/
inline
SO3Group()
: unit_quaternion_(static_cast<Scalar>(1), static_cast<Scalar>(0),
static_cast<Scalar>(0), static_cast<Scalar>(0)) {
}
/**
* \brief Copy constructor
*/
template<typename OtherDerived> inline
SO3Group(const SO3GroupBase<OtherDerived> & other)
: unit_quaternion_(other.unit_quaternion()) {
}
/**
* \brief Constructor from rotation matrix
*
* \pre rotation matrix need to be orthogonal with determinant of 1
*/
inline SO3Group(const Transformation & R)
: unit_quaternion_(R) {
}
/**
* \brief Constructor from quaternion
*
* \pre quaternion must not be zero
*/
inline explicit
SO3Group(const Quaternion<Scalar> & quat) : unit_quaternion_(quat) {
Base::normalize();
}
/**
* \brief Constructor from Euler angles
*
* \param alpha1 rotation around x-axis
* \param alpha2 rotation around y-axis
* \param alpha3 rotation around z-axis
*
* Since rotations in 3D do not commute, the order of the individual rotations
* matter. Here, the following convention is used. We calculate a SO3 member
* corresponding to the rotation matrix \f$ R \f$ such
* that \f$ R=\exp\left(\begin{array}{c}\alpha_1\\ 0\\ 0\end{array}\right)
* \cdot \exp\left(\begin{array}{c}0\\ \alpha_2\\ 0\end{array}\right)
* \cdot \exp\left(\begin{array}{c}0\\ 0\\ \alpha_3\end{array}\right)\f$.
*/
inline
SO3Group(Scalar alpha1, Scalar alpha2, Scalar alpha3) {
const static Scalar zero = static_cast<Scalar>(0);
unit_quaternion_
= ( SO3Group::exp(Tangent(alpha1, zero, zero))
*SO3Group::exp(Tangent( zero, alpha2, zero))
*SO3Group::exp(Tangent( zero, zero, alpha3)) )
.unit_quaternion_;
}
/**
* \brief Accessor of unit quaternion
*
* No direct write access is given to ensure the quaternion stays normalized.
*/
EIGEN_STRONG_INLINE
ConstQuaternionReference unit_quaternion() const {
return unit_quaternion_;
}
protected:
// Mutator of unit_quaternion is protected so users are hampered
// from setting non-unit quaternions.
EIGEN_STRONG_INLINE
QuaternionReference unit_quaternion_nonconst() {
return unit_quaternion_;
}
Quaternion<Scalar> unit_quaternion_;
};
} // end namespace
namespace Eigen {
/**
* \brief Specialisation of Eigen::Map for SO3GroupBase
*
* Allows us to wrap SO3 Objects around POD array
* (e.g. external c style quaternion)
*/
template<typename _Scalar, int _Options>
class Map<Sophus::SO3Group<_Scalar>, _Options>
: public Sophus::SO3GroupBase<Map<Sophus::SO3Group<_Scalar>, _Options> > {
typedef Sophus::SO3GroupBase<Map<Sophus::SO3Group<_Scalar>, _Options> > Base;
public:
/** \brief scalar type */
typedef typename internal::traits<Map>::Scalar Scalar;
/** \brief quaternion reference type */
typedef typename internal::traits<Map>::QuaternionType &
QuaternionReference;
/** \brief quaternion const reference type */
typedef const typename internal::traits<Map>::QuaternionType &
ConstQuaternionReference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
// base is friend so unit_quaternion_nonconst can be accessed from base
friend class Sophus::SO3GroupBase<Map<Sophus::SO3Group<_Scalar>, _Options> >;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
using Base::operator*=;
using Base::operator*;
EIGEN_STRONG_INLINE
Map(Scalar* coeffs) : unit_quaternion_(coeffs) {
}
/**
* \brief Accessor of unit quaternion
*
* No direct write access is given to ensure the quaternion stays normalized.
*/
EIGEN_STRONG_INLINE
ConstQuaternionReference unit_quaternion() const {
return unit_quaternion_;
}
protected:
// Mutator of unit_quaternion is protected so users are hampered
// from setting non-unit quaternions.
EIGEN_STRONG_INLINE
QuaternionReference unit_quaternion_nonconst() {
return unit_quaternion_;
}
Map<Quaternion<Scalar>,_Options> unit_quaternion_;
};
/**
* \brief Specialisation of Eigen::Map for const SO3GroupBase
*
* Allows us to wrap SO3 Objects around POD array
* (e.g. external c style quaternion)
*/
template<typename _Scalar, int _Options>
class Map<const Sophus::SO3Group<_Scalar>, _Options>
: public Sophus::SO3GroupBase<
Map<const Sophus::SO3Group<_Scalar>, _Options> > {
typedef Sophus::SO3GroupBase<Map<const Sophus::SO3Group<_Scalar>, _Options> >
Base;
public:
/** \brief scalar type */
typedef typename internal::traits<Map>::Scalar Scalar;
/** \brief quaternion const reference type */
typedef const typename internal::traits<Map>::QuaternionType &
ConstQuaternionReference;
/** \brief degree of freedom of group */
static const int DoF = Base::DoF;
/** \brief number of internal parameters used */
static const int num_parameters = Base::num_parameters;
/** \brief group transformations are NxN matrices */
static const int N = Base::N;
/** \brief group transfomation type */
typedef typename Base::Transformation Transformation;
/** \brief point type */
typedef typename Base::Point Point;
/** \brief tangent vector type */
typedef typename Base::Tangent Tangent;
/** \brief adjoint transformation type */
typedef typename Base::Adjoint Adjoint;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
using Base::operator*=;
using Base::operator*;
EIGEN_STRONG_INLINE
Map(const Scalar* coeffs) : unit_quaternion_(coeffs) {
}
/**
* \brief Accessor of unit quaternion
*
* No direct write access is given to ensure the quaternion stays normalized.
*/
EIGEN_STRONG_INLINE
const ConstQuaternionReference unit_quaternion() const {
return unit_quaternion_;
}
protected:
const Map<const Quaternion<Scalar>,_Options> unit_quaternion_;
};
}
#endif

77
thirdparty/Sophus/sophus/sophus.hpp vendored Normal file
View File

@@ -0,0 +1,77 @@
// This file is part of Sophus.
//
// Copyright 2013 Hauke Strasdat
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#ifndef SOPHUS_HPP
#define SOPHUS_HPP
#include <stdexcept>
// fix log1p not being found on Android in Eigen
#if defined( ANDROID )
#include <cmath>
namespace std {
using ::log1p;
}
#endif
#include <Eigen/Eigen>
#include <Eigen/Geometry>
namespace Sophus {
using namespace Eigen;
template<typename Scalar>
struct SophusConstants {
EIGEN_ALWAYS_INLINE static
const Scalar epsilon() {
return static_cast<Scalar>(1e-10);
}
EIGEN_ALWAYS_INLINE static
const Scalar pi() {
return static_cast<Scalar>(M_PI);
}
};
template<>
struct SophusConstants<float> {
EIGEN_ALWAYS_INLINE static
float epsilon() {
return static_cast<float>(1e-5);
}
EIGEN_ALWAYS_INLINE static
float pi() {
return static_cast<float>(M_PI);
}
};
class SophusException : public std::runtime_error {
public:
SophusException (const std::string& str)
: runtime_error("Sophus exception: " + str) {
}
};
}
#endif

92
thirdparty/Sophus/sophus/test_rxso3.cpp vendored Normal file
View File

@@ -0,0 +1,92 @@
// This file is part of Sophus.
//
// Copyright 2012-2013 Hauke Strasdat
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#include <iostream>
#include <vector>
#include "rxso3.hpp"
#include "tests.hpp"
using namespace Sophus;
using namespace std;
template<class Scalar>
void tests() {
typedef RxSO3Group<Scalar> RxSO3Type;
typedef typename RxSO3Group<Scalar>::Point Point;
typedef typename RxSO3Group<Scalar>::Tangent Tangent;
vector<RxSO3Type> rxso3_vec;
rxso3_vec.push_back(RxSO3Type::exp(Tangent(0.2, 0.5, 0.0, 1.)));
rxso3_vec.push_back(RxSO3Type::exp(Tangent(0.2, 0.5, -1.0, 1.1)));
rxso3_vec.push_back(RxSO3Type::exp(Tangent(0., 0., 0., 1.1)));
rxso3_vec.push_back(RxSO3Type::exp(Tangent(0., 0., 0.00001, 0.)));
rxso3_vec.push_back(RxSO3Type::exp(Tangent(0., 0., 0.00001, 0.00001)));
rxso3_vec.push_back(RxSO3Type::exp(Tangent(0., 0., 0.00001, 0)));
rxso3_vec.push_back(RxSO3Type::exp(Tangent(M_PI, 0, 0, 0.9)));
rxso3_vec.push_back(RxSO3Type::exp(Tangent(0.2, 0.5, 0.0,0))
*RxSO3Type::exp(Tangent(M_PI, 0, 0,0.0))
*RxSO3Type::exp(Tangent(-0.2, -0.5, -0.0,0)));
rxso3_vec.push_back(RxSO3Type::exp(Tangent(0.3, 0.5, 0.1,0))
*RxSO3Type::exp(Tangent(M_PI, 0, 0,0))
*RxSO3Type::exp(Tangent(-0.3, -0.5, -0.1,0)));
vector<Tangent> tangent_vec;
Tangent tmp;
tmp << 0,0,0,0;
tangent_vec.push_back(tmp);
tmp << 1,0,0,0;
tangent_vec.push_back(tmp);
tmp << 1,0,0,0.1;
tangent_vec.push_back(tmp);
tmp << 0,1,0,0.1;
tangent_vec.push_back(tmp);
tmp << 0,0,1,-0.1;
tangent_vec.push_back(tmp);
tmp << -1,1,0,-0.1;
tangent_vec.push_back(tmp);
tmp << 20,-1,0,2;
tangent_vec.push_back(tmp);
vector<Point> point_vec;
point_vec.push_back(Point(1,2,4));
Tests<RxSO3Type> tests;
tests.setGroupElements(rxso3_vec);
tests.setTangentVectors(tangent_vec);
tests.setPoints(point_vec);
tests.runAllTests();
}
int main() {
cerr << "Test RxSO3" << endl << endl;
cerr << "Double tests: " << endl;
tests<double>();
cerr << "Float tests: " << endl;
tests<float>();
return 0;
}

90
thirdparty/Sophus/sophus/test_se2.cpp vendored Normal file
View File

@@ -0,0 +1,90 @@
// This file is part of Sophus.
//
// Copyright 2012-2013 Hauke Strasdat
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#include <iostream>
#include <vector>
#include <unsupported/Eigen/MatrixFunctions>
#include "se2.hpp"
#include "tests.hpp"
using namespace Sophus;
using namespace std;
template<class Scalar>
void tests() {
typedef SO2Group<Scalar> SO2Type;
typedef SE2Group<Scalar> SE2Type;
typedef typename SE2Group<Scalar>::Point Point;
typedef typename SE2Group<Scalar>::Tangent Tangent;
vector<SE2Type> se2_vec;
se2_vec.push_back(SE2Type(SO2Type(0.0),Point(0,0)));
se2_vec.push_back(SE2Type(SO2Type(0.2),Point(10,0)));
se2_vec.push_back(SE2Type(SO2Type(0.),Point(0,100)));
se2_vec.push_back(SE2Type(SO2Type(-1.),Point(20,-1)));
se2_vec.push_back(SE2Type(SO2Type(0.00001),
Point(-0.00000001,0.0000000001)));
se2_vec.push_back(SE2Type(SO2Type(0.2),Point(0,0))
*SE2Type(SO2Type(M_PI),Point(0,0))
*SE2Type(SO2Type(-0.2),Point(0,0)));
se2_vec.push_back(SE2Type(SO2Type(0.3),Point(2,0))
*SE2Type(SO2Type(M_PI),Point(0,0))
*SE2Type(SO2Type(-0.3),Point(0,6)));
vector<Tangent> tangent_vec;
Tangent tmp;
tmp << 0,0,0;
tangent_vec.push_back(tmp);
tmp << 1,0,0;
tangent_vec.push_back(tmp);
tmp << 0,1,1;
tangent_vec.push_back(tmp);
tmp << -1,1,0;
tangent_vec.push_back(tmp);
tmp << 20,-1,-1;
tangent_vec.push_back(tmp);
tmp << 30,5,20;
tangent_vec.push_back(tmp);
vector<Point> point_vec;
point_vec.push_back(Point(1,2));
Tests<SE2Type> tests;
tests.setGroupElements(se2_vec);
tests.setTangentVectors(tangent_vec);
tests.setPoints(point_vec);
tests.runAllTests();
}
int main() {
cerr << "Test SE2" << endl << endl;
cerr << "Double tests: " << endl;
tests<double>();
cerr << "Float tests: " << endl;
tests<float>();
return 0;
}

105
thirdparty/Sophus/sophus/test_se3.cpp vendored Normal file
View File

@@ -0,0 +1,105 @@
// This file is part of Sophus.
//
// Copyright 2012-2013 Hauke Strasdat
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#include <iostream>
#include <vector>
#include "se3.hpp"
#include "tests.hpp"
using namespace Sophus;
using namespace std;
template<class Scalar>
void tests() {
typedef SO3Group<Scalar> SO3Type;
typedef SE3Group<Scalar> SE3Type;
typedef typename SE3Group<Scalar>::Point Point;
typedef typename SE3Group<Scalar>::Tangent Tangent;
vector<SE3Type> se3_vec;
se3_vec.push_back(SE3Type(SO3Type::exp(Point(0.2, 0.5, 0.0)),
Point(0,0,0)));
se3_vec.push_back(SE3Type(SO3Type::exp(Point(0.2, 0.5, -1.0)),
Point(10,0,0)));
se3_vec.push_back(SE3Type(SO3Type::exp(Point(0., 0., 0.)),
Point(0,100,5)));
se3_vec.push_back(SE3Type(SO3Type::exp(Point(0., 0., 0.00001)),
Point(0,0,0)));
se3_vec.push_back(SE3Type(SO3Type::exp(Point(0., 0., 0.00001)),
Point(0,-0.00000001,0.0000000001)));
se3_vec.push_back(SE3Type(SO3Type::exp(Point(0., 0., 0.00001)),
Point(0.01,0,0)));
se3_vec.push_back(SE3Type(SO3Type::exp(Point(M_PI, 0, 0)),
Point(4,-5,0)));
se3_vec.push_back(SE3Type(SO3Type::exp(Point(0.2, 0.5, 0.0)),
Point(0,0,0))
*SE3Type(SO3Type::exp(Point(M_PI, 0, 0)),
Point(0,0,0))
*SE3Type(SO3Type::exp(Point(-0.2, -0.5, -0.0)),
Point(0,0,0)));
se3_vec.push_back(SE3Type(SO3Type::exp(Point(0.3, 0.5, 0.1)),
Point(2,0,-7))
*SE3Type(SO3Type::exp(Point(M_PI, 0, 0)),
Point(0,0,0))
*SE3Type(SO3Type::exp(Point(-0.3, -0.5, -0.1)),
Point(0,6,0)));
vector<Tangent> tangent_vec;
Tangent tmp;
tmp << 0,0,0,0,0,0;
tangent_vec.push_back(tmp);
tmp << 1,0,0,0,0,0;
tangent_vec.push_back(tmp);
tmp << 0,1,0,1,0,0;
tangent_vec.push_back(tmp);
tmp << 0,-5,10,0,0,0;
tangent_vec.push_back(tmp);
tmp << -1,1,0,0,0,1;
tangent_vec.push_back(tmp);
tmp << 20,-1,0,-1,1,0;
tangent_vec.push_back(tmp);
tmp << 30,5,-1,20,-1,0;
tangent_vec.push_back(tmp);
vector<Point> point_vec;
point_vec.push_back(Point(1,2,4));
Tests<SE3Type> tests;
tests.setGroupElements(se3_vec);
tests.setTangentVectors(tangent_vec);
tests.setPoints(point_vec);
tests.runAllTests();
cerr << "passed." << endl << endl;
}
int main() {
cerr << "Test SE3" << endl << endl;
cerr << "Double tests: " << endl;
tests<double>();
cerr << "Float tests: " << endl;
tests<float>();
return 0;
}

109
thirdparty/Sophus/sophus/test_sim3.cpp vendored Normal file
View File

@@ -0,0 +1,109 @@
// This file is part of Sophus.
//
// Copyright 2012-2013 Hauke Strasdat
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#include <iostream>
#include <vector>
#include <unsupported/Eigen/MatrixFunctions>
#include "sim3.hpp"
#include "tests.hpp"
using namespace Sophus;
using namespace std;
template<class Scalar>
void tests() {
typedef Sim3Group<Scalar> Sim3Type;
typedef RxSO3Group<Scalar> RxSO3Type;
typedef typename Sim3Group<Scalar>::Point Point;
typedef typename Sim3Group<Scalar>::Tangent Tangent;
typedef Matrix<Scalar,4,1> Vector4Type;
vector<Sim3Type> sim3_vec;
sim3_vec.push_back(Sim3Type(RxSO3Type::exp(Vector4Type(0.2, 0.5, 0.0,1.)),
Point(0,0,0)));
sim3_vec.push_back(Sim3Type(RxSO3Type::exp(Vector4Type(0.2, 0.5, -1.0,1.1)),
Point(10,0,0)));
sim3_vec.push_back(Sim3Type(RxSO3Type::exp(Vector4Type(0., 0., 0.,1.1)),
Point(0,10,5)));
sim3_vec.push_back(Sim3Type(RxSO3Type::exp(Vector4Type(0., 0., 0.00001, 0.)),
Point(0,0,0)));
sim3_vec.push_back(Sim3Type(RxSO3Type::exp(
Vector4Type(0., 0., 0.00001, 0.0000001)),
Point(1,-1.00000001,2.0000000001)));
sim3_vec.push_back(Sim3Type(RxSO3Type::exp(Vector4Type(0., 0., 0.00001, 0)),
Point(0.01,0,0)));
sim3_vec.push_back(Sim3Type(RxSO3Type::exp(Vector4Type(M_PI, 0, 0,0.9)),
Point(4,-5,0)));
sim3_vec.push_back(Sim3Type(RxSO3Type::exp(Vector4Type(0.2, 0.5, 0.0,0)),
Point(0,0,0))
*Sim3Type(RxSO3Type::exp(Vector4Type(M_PI, 0, 0,0)),
Point(0,0,0))
*Sim3Type(RxSO3Type::exp(Vector4Type(-0.2, -0.5, -0.0,0)),
Point(0,0,0)));
sim3_vec.push_back(Sim3Type(RxSO3Type::exp(Vector4Type(0.3, 0.5, 0.1,0)),
Point(2,0,-7))
*Sim3Type(RxSO3Type::exp(Vector4Type(M_PI, 0, 0,0)),
Point(0,0,0))
*Sim3Type(RxSO3Type::exp(Vector4Type(-0.3, -0.5, -0.1,0)),
Point(0,6,0)));
vector<Tangent> tangent_vec;
Tangent tmp;
tmp << 0,0,0,0,0,0,0;
tangent_vec.push_back(tmp);
tmp << 1,0,0,0,0,0,0;
tangent_vec.push_back(tmp);
tmp << 0,1,0,1,0,0,0.1;
tangent_vec.push_back(tmp);
tmp << 0,0,1,0,1,0,0.1;
tangent_vec.push_back(tmp);
tmp << -1,1,0,0,0,1,-0.1;
tangent_vec.push_back(tmp);
tmp << 20,-1,0,-1,1,0,-0.1;
tangent_vec.push_back(tmp);
tmp << 30,5,-1,20,-1,0,1.5;
tangent_vec.push_back(tmp);
vector<Point> point_vec;
point_vec.push_back(Point(1,2,4));
Tests<Sim3Type> tests;
tests.setGroupElements(sim3_vec);
tests.setTangentVectors(tangent_vec);
tests.setPoints(point_vec);
tests.runAllTests();
}
int main() {
cerr << "Test Sim3" << endl << endl;
cerr << "Double tests: " << endl;
tests<double>();
cerr << "Float tests: " << endl;
tests<float>();
return 0;
}

91
thirdparty/Sophus/sophus/test_so2.cpp vendored Normal file
View File

@@ -0,0 +1,91 @@
// This file is part of Sophus.
//
// Copyright 2012-2013 Hauke Strasdat
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#include <iostream>
#include <vector>
#include "so2.hpp"
#include "tests.hpp"
using namespace Sophus;
using namespace std;
template<class Scalar>
void tests() {
typedef SO2Group<Scalar> SO2Type;
typedef typename SO2Group<Scalar>::Point Point;
typedef typename SO2Group<Scalar>::Tangent Tangent;
vector<SO2Type> so2_vec;
so2_vec.push_back(SO2Type::exp(0.0));
so2_vec.push_back(SO2Type::exp(0.2));
so2_vec.push_back(SO2Type::exp(10.));
so2_vec.push_back(SO2Type::exp(0.00001));
so2_vec.push_back(SO2Type::exp(M_PI));
so2_vec.push_back(SO2Type::exp(0.2)
*SO2Type::exp(M_PI)
*SO2Type::exp(-0.2));
so2_vec.push_back(SO2Type::exp(-0.3)
*SO2Type::exp(M_PI)
*SO2Type::exp(0.3));
vector<Tangent> tangent_vec;
tangent_vec.push_back(Tangent(0));
tangent_vec.push_back(Tangent(1));
tangent_vec.push_back(Tangent(M_PI_2));
tangent_vec.push_back(Tangent(-1));
tangent_vec.push_back(Tangent(20));
tangent_vec.push_back(Tangent(M_PI_2+0.0001));
vector<Point> point_vec;
point_vec.push_back(Point(1,2));
Tests<SO2Type> tests;
tests.setGroupElements(so2_vec);
tests.setTangentVectors(tangent_vec);
tests.setPoints(point_vec);
tests.runAllTests();
cerr << "Exception test: ";
try {
SO2Type so2(0., 0.);
} catch(SophusException & e) {
cerr << "passed." << endl << endl;
return;
}
cerr << "failed!" << endl << endl;
exit(-1);
}
int main() {
cerr << "Test SO2" << endl << endl;
cerr << "Double tests: " << endl;
tests<double>();
cerr << "Float tests: " << endl;
tests<float>();
return 0;
}

84
thirdparty/Sophus/sophus/test_so3.cpp vendored Normal file
View File

@@ -0,0 +1,84 @@
// This file is part of Sophus.
//
// Copyright 2012-2013 Hauke Strasdat
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#include <iostream>
#include <vector>
#include "so3.hpp"
#include "tests.hpp"
using namespace Sophus;
using namespace std;
template<class Scalar>
void tests() {
typedef SO3Group<Scalar> SO3Type;
typedef typename SO3Group<Scalar>::Point Point;
typedef typename SO3Group<Scalar>::Tangent Tangent;
vector<SO3Type> so3_vec;
so3_vec.push_back(SO3Type(Quaternion<Scalar>(0.1e-11, 0., 1., 0.)));
so3_vec.push_back(SO3Type(Quaternion<Scalar>(-1,0.00001,0.0,0.0)));
so3_vec.push_back(SO3Type::exp(Point(0.2, 0.5, 0.0)));
so3_vec.push_back(SO3Type::exp(Point(0.2, 0.5, -1.0)));
so3_vec.push_back(SO3Type::exp(Point(0., 0., 0.)));
so3_vec.push_back(SO3Type::exp(Point(0., 0., 0.00001)));
so3_vec.push_back(SO3Type::exp(Point(M_PI, 0, 0)));
so3_vec.push_back(SO3Type::exp(Point(0.2, 0.5, 0.0))
*SO3Type::exp(Point(M_PI, 0, 0))
*SO3Type::exp(Point(-0.2, -0.5, -0.0)));
so3_vec.push_back(SO3Type::exp(Point(0.3, 0.5, 0.1))
*SO3Type::exp(Point(M_PI, 0, 0))
*SO3Type::exp(Point(-0.3, -0.5, -0.1)));
vector<Tangent> tangent_vec;
tangent_vec.push_back(Tangent(0,0,0));
tangent_vec.push_back(Tangent(1,0,0));
tangent_vec.push_back(Tangent(0,1,0));
tangent_vec.push_back(Tangent(M_PI_2,M_PI_2,0.0));
tangent_vec.push_back(Tangent(-1,1,0));
tangent_vec.push_back(Tangent(20,-1,0));
tangent_vec.push_back(Tangent(30,5,-1));
vector<Point> point_vec;
point_vec.push_back(Point(1,2,4));
Tests<SO3Type> tests;
tests.setGroupElements(so3_vec);
tests.setTangentVectors(tangent_vec);
tests.setPoints(point_vec);
tests.runAllTests();
}
int main() {
cerr << "Test SO3" << endl << endl;
cerr << "Double tests: " << endl;
tests<double>();
cerr << "Float tests: " << endl;
tests<float>();
return 0;
}

264
thirdparty/Sophus/sophus/tests.hpp vendored Normal file
View File

@@ -0,0 +1,264 @@
#ifndef SOPUHS_TESTS_HPP
#define SOPUHS_TESTS_HPP
#include <vector>
#include <unsupported/Eigen/MatrixFunctions>
#include "sophus.hpp"
namespace Sophus {
using namespace std;
using namespace Eigen;
template <class LieGroup>
class Tests {
public:
typedef typename LieGroup::Scalar Scalar;
typedef typename LieGroup::Transformation Transformation;
typedef typename LieGroup::Tangent Tangent;
typedef typename LieGroup::Point Point;
typedef typename LieGroup::Adjoint Adjoint;
static const int N = LieGroup::N;
static const int DoF = LieGroup::DoF;
const Scalar SMALL_EPS;
Tests() : SMALL_EPS(SophusConstants<Scalar>::epsilon()) {
}
void setGroupElements(const vector<LieGroup> & group_vec) {
group_vec_ = group_vec;
}
void setTangentVectors(const vector<Tangent> & tangent_vec) {
tangent_vec_ = tangent_vec;
}
void setPoints(const vector<Point> & point_vec) {
point_vec_ = point_vec;
}
bool adjointTest() {
bool passed = true;
for (size_t i=0; i<group_vec_.size(); ++i) {
Transformation T = group_vec_[i].matrix();
Adjoint Ad = group_vec_[i].Adj();
for (size_t j=0; j<tangent_vec_.size(); ++j) {
Tangent x = tangent_vec_[j];
Transformation I;
I.setIdentity();
Tangent ad1 = Ad*x;
Tangent ad2 = LieGroup::vee(T*LieGroup::hat(x)
*group_vec_[i].inverse().matrix());
Scalar nrm = norm(ad1-ad2);
if (isnan(nrm) || nrm>20.*SMALL_EPS) {
cerr << "Adjoint" << endl;
cerr << "Test case: " << i << "," << j <<endl;
cerr << (ad1-ad2) <<endl;
cerr << endl;
passed = false;
}
}
}
return passed;
}
bool expLogTest() {
bool passed = true;
for (size_t i=0; i<group_vec_.size(); ++i) {
Transformation T1 = group_vec_[i].matrix();
Transformation T2 = LieGroup::exp(group_vec_[i].log()).matrix();
Transformation DiffT = T1-T2;
Scalar nrm = DiffT.norm();
if (isnan(nrm) || nrm>SMALL_EPS) {
cerr << "G - exp(log(G))" << endl;
cerr << "Test case: " << i << endl;
cerr << DiffT <<endl;
cerr << endl;
passed = false;
}
}
return passed;
}
bool expMapTest() {
bool passed = true;
for (size_t i=0; i<tangent_vec_.size(); ++i) {
Tangent omega = tangent_vec_[i];
Transformation exp_x = LieGroup::exp(omega).matrix();
Transformation expmap_hat_x = (LieGroup::hat(omega)).exp();
Transformation DiffR = exp_x-expmap_hat_x;
Scalar nrm = DiffR.norm();
if (isnan(nrm) || nrm>10.*SMALL_EPS) {
cerr << "expmap(hat(x)) - exp(x)" << endl;
cerr << "Test case: " << i << endl;
cerr << exp_x <<endl;
cerr << expmap_hat_x <<endl;
cerr << DiffR <<endl;
cerr << endl;
passed = false;
}
}
return passed;
}
bool groupActionTest() {
bool passed = true;
for (size_t i=0; i<group_vec_.size(); ++i) {
for (size_t j=0; j<point_vec_.size(); ++j) {
const Point & p = point_vec_[j];
Transformation T = group_vec_[i].matrix();
Point res1 = group_vec_[i]*p;
Point res2 = map(T, p);
Scalar nrm = (res1-res2).norm();
if (isnan(nrm) || nrm>SMALL_EPS) {
cerr << "Transform vector" << endl;
cerr << "Test case: " << i << endl;
cerr << (res1-res2) <<endl;
cerr << endl;
passed = false;
}
}
}
return passed;
}
bool lieBracketTest() {
bool passed = true;
for (size_t i=0; i<tangent_vec_.size(); ++i) {
for (size_t j=0; j<tangent_vec_.size(); ++j) {
Tangent res1 = LieGroup::lieBracket(tangent_vec_[i],tangent_vec_[j]);
Transformation hati = LieGroup::hat(tangent_vec_[i]);
Transformation hatj = LieGroup::hat(tangent_vec_[j]);
Tangent res2 = LieGroup::vee(hati*hatj-hatj*hati);
Tangent resDiff = res1-res2;
if (norm(resDiff)>SMALL_EPS) {
cerr << "Lie Bracket Test" << endl;
cerr << "Test case: " << i << ", " <<j<< endl;
cerr << resDiff << endl;
cerr << endl;
passed = false;
}
}
}
return passed;
}
bool mapAndMultTest() {
bool passed = true;
for (size_t i=0; i<group_vec_.size(); ++i) {
for (size_t j=0; j<group_vec_.size(); ++j) {
Transformation mul_resmat = (group_vec_[i]*group_vec_[j]).matrix();
Scalar fastmul_res_raw[LieGroup::num_parameters];
Eigen::Map<LieGroup> fastmul_res(fastmul_res_raw);
Eigen::Map<const LieGroup> group_j_constmap(group_vec_[j].data());
fastmul_res = group_vec_[i];
fastmul_res.fastMultiply(group_j_constmap);
Transformation diff = mul_resmat-fastmul_res.matrix();
Scalar nrm = diff.norm();
if (isnan(nrm) || nrm>SMALL_EPS) {
cerr << "Map & Multiply" << endl;
cerr << "Test case: " << i << "," << j << endl;
cerr << diff <<endl;
cerr << endl;
passed = false;
}
}
}
return passed;
}
bool veeHatTest() {
bool passed = true;
for (size_t i=0; i<tangent_vec_.size(); ++i) {
Tangent resDiff
= tangent_vec_[i] - LieGroup::vee(LieGroup::hat(tangent_vec_[i]));
if (norm(resDiff)>SMALL_EPS) {
cerr << "Hat-vee Test" << endl;
cerr << "Test case: " << i << endl;
cerr << resDiff << endl;
cerr << endl;
passed = false;
}
}
return passed;
}
void runAllTests() {
bool passed = adjointTest();
if (!passed) {
cerr << "failed!" << endl << endl;
exit(-1);
}
passed = expLogTest();
if (!passed) {
cerr << "failed!" << endl << endl;
exit(-1);
}
passed = expMapTest();
if (!passed) {
cerr << "failed!" << endl << endl;
exit(-1);
}
passed = groupActionTest();
if (!passed) {
cerr << "failed!" << endl << endl;
exit(-1);
}
passed = lieBracketTest();
if (!passed) {
cerr << "failed!" << endl << endl;
exit(-1);
}
passed = mapAndMultTest();
if (!passed) {
cerr << "failed!" << endl << endl;
exit(-1);
}
passed = veeHatTest();
if (!passed) {
cerr << "failed!" << endl << endl;
exit(-1);
}
cerr << "passed." << endl << endl;
}
private:
Matrix<Scalar,N-1,1> map(const Matrix<Scalar,N,N> & T,
const Matrix<Scalar,N-1,1> & p) {
return T.template topLeftCorner<N-1,N-1>()*p
+ T.template topRightCorner<N-1,1>();
}
Matrix<Scalar,N,1> map(const Matrix<Scalar,N,N> & T,
const Matrix<Scalar,N,1> & p) {
return T*p;
}
Scalar norm(const Scalar & v) {
return std::abs(v);
}
Scalar norm(const Matrix<Scalar,DoF,1> & T) {
return T.norm();
}
std::vector<LieGroup> group_vec_;
std::vector<Tangent> tangent_vec_;
std::vector<Point> point_vec_;
};
}
#endif // TESTS_HPP

BIN
thirdparty/libzip-1.1.1.tar.gz vendored Executable file

Binary file not shown.

1497
thirdparty/sse2neon/SSE2NEON.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SSE2NEON", "SSE2NEON\SSE2NEON.vcxproj", "{82052143-B781-40EA-BFB0-491904834B89}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Tegra-Android = Debug|Tegra-Android
Release|Tegra-Android = Release|Tegra-Android
Shipping|Tegra-Android = Shipping|Tegra-Android
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{82052143-B781-40EA-BFB0-491904834B89}.Debug|Tegra-Android.ActiveCfg = Debug|Tegra-Android
{82052143-B781-40EA-BFB0-491904834B89}.Debug|Tegra-Android.Build.0 = Debug|Tegra-Android
{82052143-B781-40EA-BFB0-491904834B89}.Release|Tegra-Android.ActiveCfg = Release|Tegra-Android
{82052143-B781-40EA-BFB0-491904834B89}.Release|Tegra-Android.Build.0 = Release|Tegra-Android
{82052143-B781-40EA-BFB0-491904834B89}.Shipping|Tegra-Android.ActiveCfg = Shipping|Tegra-Android
{82052143-B781-40EA-BFB0-491904834B89}.Shipping|Tegra-Android.Build.0 = Shipping|Tegra-Android
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,2 @@
C:\NVPACK\jdk1.8.0_77\jre
1490807943647

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="sse2neon.test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="15" />
<application android:label="@string/app_name"
android:hasCode="True">
<activity android:name=".SSE2NEON"
android:label="@string/app_name">
<meta-data android:name="android.app.lib_name"
android:value="SSE2NEON" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="NsightTegraProject">
<NsightTegraProjectRevisionNumber>11</NsightTegraProjectRevisionNumber>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Tegra-Android">
<Configuration>Debug</Configuration>
<Platform>Tegra-Android</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Tegra-Android">
<Configuration>Release</Configuration>
<Platform>Tegra-Android</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Shipping|Tegra-Android">
<Configuration>Shipping</Configuration>
<Platform>Tegra-Android</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{82052143-B781-40EA-BFB0-491904834B89}</ProjectGuid>
<RootNamespace>SSE2NEON</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Tegra-Android'">
<AndroidTargetAPI>android-15</AndroidTargetAPI>
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Tegra-Android'">
<AndroidTargetAPI>android-15</AndroidTargetAPI>
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Shipping|Tegra-Android'">
<AndroidTargetAPI>android-15</AndroidTargetAPI>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<PropertyGroup Label="UserMacros">
</PropertyGroup>
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Tegra-Android'">
<ClCompile>
<CppLanguageStandard>gnu++11</CppLanguageStandard>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Tegra-Android'">
<ClCompile>
<CppLanguageStandard>gnu++11</CppLanguageStandard>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Shipping|Tegra-Android'">
<ClCompile>
<CppLanguageStandard>gnu++11</CppLanguageStandard>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<AndroidBuild Include="AndroidManifest.xml" />
<AndroidBuild Include="res\values\strings.xml" />
</ItemGroup>
<ItemGroup>
<JCompile Include="src\sse2neon\test\SSE2NEON.java" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\SSE2NEONBinding.cpp" />
<ClCompile Include="..\..\SSE2NEONTEST.cpp" />
<ClCompile Include="jni\SSE2NEON_TEST.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\SSE2NEON.h" />
<ClInclude Include="..\..\SSE2NEONBinding.h" />
<ClInclude Include="..\..\SSE2NEONTEST.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="res">
<UniqueIdentifier>1809a5b3-0e48-4552-907e-2b1b920e5948</UniqueIdentifier>
</Filter>
<Filter Include="res\values">
<UniqueIdentifier>f663d0da-a8fc-4457-bf5e-aab7f1904d2e</UniqueIdentifier>
</Filter>
<Filter Include="src">
<UniqueIdentifier>{32a44a3b-1ece-48ec-a181-de7a49d1c972}</UniqueIdentifier>
</Filter>
<Filter Include="src\sse2neon">
<UniqueIdentifier>{d64092f0-bd97-42f3-8e5a-e3dbc448ef62}</UniqueIdentifier>
</Filter>
<Filter Include="src\sse2neon\test">
<UniqueIdentifier>{dfa22a06-6da7-446e-a1dd-8bd921238984}</UniqueIdentifier>
</Filter>
<Filter Include="jni">
<UniqueIdentifier>{cd15bd6d-0b7f-4bc8-83bc-ff8b30f022ca}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<AndroidBuild Include="AndroidManifest.xml" />
<AndroidBuild Include="res\values\strings.xml">
<Filter>res\values</Filter>
</AndroidBuild>
</ItemGroup>
<ItemGroup>
<JCompile Include="src\sse2neon\test\SSE2NEON.java">
<Filter>src\sse2neon\test</Filter>
</JCompile>
</ItemGroup>
<ItemGroup>
<ClCompile Include="jni\SSE2NEON_TEST.cpp">
<Filter>jni</Filter>
</ClCompile>
<ClCompile Include="..\..\SSE2NEONBinding.cpp">
<Filter>jni</Filter>
</ClCompile>
<ClCompile Include="..\..\SSE2NEONTEST.cpp">
<Filter>jni</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\SSE2NEON.h">
<Filter>jni</Filter>
</ClInclude>
<ClInclude Include="..\..\SSE2NEONBinding.h">
<Filter>jni</Filter>
</ClInclude>
<ClInclude Include="..\..\SSE2NEONTEST.h">
<Filter>jni</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,46 @@
/**********************************
Java Native Interface library
**********************************/
#include <jni.h>
#include <android/log.h>
#include "../../../SSE2NEONTEST.h"
#include <stdint.h>
/** This is the C++ implementation of the Java native method.
@param env Pointer to JVM environment
@param thiz Reference to Java this object
*/
extern "C"
JNIEXPORT void JNICALL
Java_sse2neon_test_SSE2NEON_sse2neonNative( JNIEnv* env, jobject thiz )
{
// Enter code here
__android_log_print(ANDROID_LOG_INFO, "SSE2NEON", "%s\n", "SSE2NEON");
SSE2NEON::SSE2NEONTest *test = SSE2NEON::SSE2NEONTest::create();
uint32_t passCount = 0;
uint32_t failedCount = 0;
for (uint32_t i = 0; i < SSE2NEON::IT_LAST; i++)
{
SSE2NEON::InstructionTest it = SSE2NEON::InstructionTest(i);
__android_log_print(ANDROID_LOG_INFO, "SSE2NEON", "Running Test %s\n", SSE2NEON::SSE2NEONTest::getInstructionTestString(it));
bool ok = test->runTest(it);
// If the test fails, we will run it again so we can step into the debugger and figure out why!
if (!ok)
{
__android_log_print(ANDROID_LOG_INFO, "SSE2NEON", "**FAILURE** SSE2NEONTest %s", SSE2NEON::SSE2NEONTest::getInstructionTestString(it));
// test->runTest(it); // Uncomment this to step through the code to find the failure case
}
if (ok)
{
passCount++;
}
else
{
failedCount++;
}
}
test->release();
__android_log_print(ANDROID_LOG_INFO, "SSE2NEON", "SSE2NEONTest Complete: Passed %d tests : Failed %d\n", passCount, failedCount);
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">SSE2NEON</string>
</resources>

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sse2neon.test;
import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;
/**
* This class loads the Java Native Interface (JNI)
* library, 'libSSE2NEON.so', and provides access to the
* exposed C functions.
* The library is packaged and installed with the application.
* See the C file, /jni/SSE2NEON.c file for the
* implementations of the native methods.
*
* For more information on JNI, see: http://java.sun.com/docs/books/jni/
*/
public class SSE2NEON extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Enter code here
sse2neonNative();
}
/**
* An example native method. See the library function,
* <code>Java_sse2neon_test_SSE2NEON_sse2neonNative</code>
* for the implementation.
*/
public native void sse2neonNative();
/* This is the static constructor used to load the
* 'SSE2NEON' library when the class is
* loaded.
*/
static {
System.loadLibrary("SSE2NEON");
}
}

47
thirdparty/sse2neon/SSE2NEONBinding.cpp vendored Normal file
View File

@@ -0,0 +1,47 @@
#include "SSE2NEONBinding.h"
#ifdef WIN32
#include <xmmintrin.h>
#include <emmintrin.h>
#include <malloc.h>
#include <crtdbg.h>
#else
#include <stdlib.h>
#endif
namespace SSE2NEON
{
#ifdef WIN32
void* platformAlignedAlloc(size_t size)
{
return _aligned_malloc(size, 16);
}
void platformAlignedFree(void* ptr)
{
_aligned_free(ptr);
}
#else
void* platformAlignedAlloc(size_t size)
{
return ::memalign(16, size);
}
void platformAlignedFree(void* ptr)
{
::free(ptr);
}
#endif
} // end of SSE2NEON namespace

20
thirdparty/sse2neon/SSE2NEONBinding.h vendored Normal file
View File

@@ -0,0 +1,20 @@
#ifndef SSE2NEONBINDING_H
#define SSE2NEONBINDING_H
#include <stdlib.h>
// The SSE2NEON unit tests run both within our own internal project
// as well as within the open source framework.
// This header file is used to abstract any distinctions between
// those two build environments.
//
// Initially, this is for how 16 byte aligned memory is allocated
namespace SSE2NEON
{
void* platformAlignedAlloc(size_t size);
void platformAlignedFree(void* ptr);
}
#endif

1850
thirdparty/sse2neon/SSE2NEONTEST.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

133
thirdparty/sse2neon/SSE2NEONTEST.h vendored Normal file
View File

@@ -0,0 +1,133 @@
#ifndef SSE2NEONTEST_H
#define SSE2NEONTEST_H
// SSE2NEONTEST performs a set of 'unit tests' making sure that each SSE call
// provides the output we expect. If this fires an assert, then something didn't match up.
namespace SSE2NEON
{
// Currently 39 SSE intrinsics have unit tests fully implemented and verified.
// There are an additional 56 intrinsics which do not yet have a unit
// test implementation and, therefore, should not be considered fully
// verified at this time. These will be implemented as soon as possible.
// Note: The way unit tests are implemented is that 10,000 random floating point
// and integer vec4 numbers are generated as sample data.
//
// A short C implementation of every intrinsic is implemented and compared to the
// actual expected results from the corresponding SSE intrinsic against all of the
// 10,000 randomized input vectors.
// When running on ARM, then the results are compared to the NEON approximate version.
enum InstructionTest
{
IT_MM_SETZERO_SI128, // Unit test implemented and verified as fully working
IT_MM_SETZERO_PS, // Unit test implemented and verified as fully working
IT_MM_SET1_PS, // Unit test implemented and verified as fully working
IT_MM_SET_PS1, // Unit test implemented and verified as fully working
IT_MM_SET_PS, // Unit test implemented and verified as fully working
IT_MM_SET1_EPI32, // Unit test implemented and verified as fully working
IT_MM_SET_EPI32, // Unit test implemented and verified as fully working
IT_MM_STORE_PS, // Unit test implemented and verified as fully working
IT_MM_SHUFFLE_PS, // Unit test implemented and verified as fully working
IT_MM_LOAD1_PS, // Unit test implemented and verified as fully working
IT_MM_ANDNOT_PS, // Unit test implemented and verified as fully working
IT_MM_ANDNOT_SI128, // Unit test implemented and verified as fully working
IT_MM_AND_SI128, // Unit test implemented and verified as fully working
IT_MM_AND_PS, // Unit test implemented and verified as fully working
IT_MM_OR_PS, // Unit test implemented and verified as fully working
IT_MM_OR_SI128, // Unit test implemented and verified as fully working
IT_MM_MOVEMASK_PS, // Unit test implemented and verified as fully working
IT_MM_MOVEMASK_EPI8, // Unit test implemented and verified as fully working
IT_MM_SUB_PS, // Unit test implemented and verified as fully working
IT_MM_SUB_EPI32, // Unit test implemented and verified as fully working
IT_MM_ADD_PS, // Unit test implemented and verified as fully working
IT_MM_ADD_EPI32, // Unit test implemented and verified as fully working
IT_MM_MULLO_EPI16, // Unit test implemented and verified as fully working
IT_MM_MUL_PS, // Unit test implemented and verified as fully working
IT_MM_RCP_PS, // Unit test implemented and verified as fully working
IT_MM_MAX_PS, // Unit test implemented and verified as fully working
IT_MM_MIN_PS, // Unit test implemented and verified as fully working
IT_MM_MIN_EPI16, // Unit test implemented and verified as fully working
IT_MM_MULHI_EPI16, // Unit test implemented and verified as fully working
IT_MM_CMPLT_PS, // Unit test implemented and verified as fully working
IT_MM_CMPGT_PS, // Unit test implemented and verified as fully working
IT_MM_CMPGE_PS, // Unit test implemented and verified as fully working
IT_MM_CMPLE_PS, // Unit test implemented and verified as fully working
IT_MM_CMPEQ_PS, // Unit test implemented and verified as fully working
IT_MM_CMPLT_EPI32, // Unit test implemented and verified as fully working
IT_MM_CMPGT_EPI32, // Unit test implemented and verified as fully working
IT_MM_CVTTPS_EPI32, // Unit test implemented and verified as fully working
IT_MM_CVTEPI32_PS, // Unit test implemented and verified as fully working
IT_MM_CVTPS_EPI32, // Unit test implemented and verified as fully working
IT_MM_CVTSS_F32, // Unit test *not yet implemented*
IT_MM_SETR_PS, // Unit test *not yet implemented*
IT_MM_STOREU_PS, // Unit test *not yet implemented*
IT_MM_STORE_SI128, // Unit test *not yet implemented*
IT_MM_STORE_SS, // Unit test *not yet implemented*
IT_MM_STOREL_EPI64, // Unit test *not yet implemented*
IT_MM_LOAD_PS, // Unit test *not yet implemented*
IT_MM_LOADU_PS, // Unit test *not yet implemented*
IT_MM_LOAD_SS, // Unit test *not yet implemented*
IT_MM_CMPNEQ_PS, // Unit test *not yet implemented*
IT_MM_XOR_PS, // Unit test *not yet implemented*
IT_MM_XOR_SI128, // Unit test *not yet implemented*
IT_MM_SHUFFLE_EPI32_DEFAULT, // Unit test *not yet implemented*
IT_MM_SHUFFLE_EPI32_FUNCTION, // Unit test *not yet implemented*
IT_MM_SHUFFLE_EPI32_SPLAT, // Unit test *not yet implemented*
IT_MM_SHUFFLE_EPI32_SINGLE, // Unit test *not yet implemented*
IT_MM_SHUFFLEHI_EPI16_FUNCTION, // Unit test *not yet implemented*
IT_MM_ADD_SS, // Unit test *not yet implemented*
IT_MM_ADD_EPI16, // Unit test *not yet implemented*
IT_MM_MULLO_EPI32, // Unit test *not yet implemented*
IT_MM_DIV_PS, // Unit test *not yet implemented*
IT_MM_DIV_SS, // Unit test *not yet implemented*
IT_MM_SQRT_PS, // Unit test *not yet implemented*
IT_MM_SQRT_SS, // Unit test *not yet implemented*
IT_MM_RSQRT_PS, // Unit test *not yet implemented*
IT_MM_MAX_SS, // Unit test *not yet implemented*
IT_MM_MIN_SS, // Unit test *not yet implemented*
IT_MM_MAX_EPI32, // Unit test *not yet implemented*
IT_MM_MIN_EPI32, // Unit test *not yet implemented*
IT_MM_HADD_PS, // Unit test *not yet implemented*
IT_MM_CMPORD_PS, // Unit test *not yet implemented*
IT_MM_COMILT_SS, // Unit test *not yet implemented*
IT_MM_COMIGT_SS, // Unit test *not yet implemented*
IT_MM_COMILE_SS, // Unit test *not yet implemented*
IT_MM_COMIGE_SS, // Unit test *not yet implemented*
IT_MM_COMIEQ_SS, // Unit test *not yet implemented*
IT_MM_COMINEQ_SS, // Unit test *not yet implemented*
IT_MM_CVTSI128_SI32, // Unit test *not yet implemented*
IT_MM_CVTSI32_SI128, // Unit test *not yet implemented*
IT_MM_CASTPS_SI128, // Unit test *not yet implemented*
IT_MM_CASTSI128_PS, // Unit test *not yet implemented*
IT_MM_LOAD_SI128, // Unit test *not yet implemented*
IT_MM_PACKS_EPI16, // Unit test *not yet implemented*
IT_MM_PACKUS_EPI16, // Unit test *not yet implemented*
IT_MM_PACKS_EPI32, // Unit test *not yet implemented*
IT_MM_UNPACKLO_EPI8, // Unit test *not yet implemented*
IT_MM_UNPACKLO_EPI16, // Unit test *not yet implemented*
IT_MM_UNPACKLO_EPI32, // Unit test *not yet implemented*
IT_MM_UNPACKLO_PS, // Unit test *not yet implemented*
IT_MM_UNPACKHI_PS, // Unit test *not yet implemented*
IT_MM_UNPACKHI_EPI8, // Unit test *not yet implemented*
IT_MM_UNPACKHI_EPI16, // Unit test *not yet implemented*
IT_MM_UNPACKHI_EPI32, // Unit test *not yet implemented*
IT_MM_SFENCE, // Unit test *not yet implemented*
IT_MM_STREAM_SI128, // Unit test *not yet implemented*
IT_MM_CLFLUSH, // Unit test *not yet implemented*
IT_LAST
};
class SSE2NEONTest
{
public:
static SSE2NEONTest* create(void); // create the test.
static const char *getInstructionTestString(InstructionTest test);
// Run test of this instruction; return true if it passed, false if it failed
virtual bool runTest(InstructionTest test) = 0;
virtual void release(void) = 0;
};
}
#endif

View File

@@ -0,0 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 11
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SSE2NEON", "SSE2NEON.vcxproj", "{4D22D468-6380-1EC4-4643-53D05B3CA4C5}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
debug|Win32 = debug|Win32
release|Win32 = release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4D22D468-6380-1EC4-4643-53D05B3CA4C5}.debug|Win32.ActiveCfg = debug|Win32
{4D22D468-6380-1EC4-4643-53D05B3CA4C5}.debug|Win32.Build.0 = debug|Win32
{4D22D468-6380-1EC4-4643-53D05B3CA4C5}.release|Win32.ActiveCfg = release|Win32
{4D22D468-6380-1EC4-4643-53D05B3CA4C5}.release|Win32.Build.0 = release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddins) = postSolution
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="debug|Win32">
<Configuration>debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="release|Win32">
<Configuration>release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ApplicationEnvironment>title</ApplicationEnvironment>
<!-- - - - -->
<PlatformToolset>v110</PlatformToolset>
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
<ProjectGuid>{4D22D468-6380-1EC4-4643-53D05B3CA4C5}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<GenerateManifest>false</GenerateManifest>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<GenerateManifest>false</GenerateManifest>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|Win32'">
<OutDir>./../..\</OutDir>
<IntDir>./Win32/SSE2NEON/debug\</IntDir>
<TargetExt>.exe</TargetExt>
<TargetName>SSE2NEON32DEBUG</TargetName>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug|Win32'">
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
<FloatingPointModel>Fast</FloatingPointModel>
<AdditionalOptions>/W4</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>./../../config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_WINDOWS;UNICODE=1;_CRT_SECURE_NO_DEPRECATE;OPEN_SOURCE=1;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalOptions>/DEBUG</AdditionalOptions>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)SSE2NEON32DEBUG.exe</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ProgramDatabaseFile>$(OutDir)/SSE2NEON32DEBUG.exe.pdb</ProgramDatabaseFile>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)/SSE2NEON32DEBUG.exe.map</MapFileName>
<SubSystem>Console</SubSystem>
<ImportLibrary>$(OutDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<ResourceCompile>
</ResourceCompile>
<ProjectReference>
</ProjectReference>
</ItemDefinitionGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'">
<OutDir>./../..\</OutDir>
<IntDir>./Win32/SSE2NEON/release\</IntDir>
<TargetExt>.exe</TargetExt>
<TargetName>SSE2NEON32</TargetName>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'">
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
<FloatingPointModel>Fast</FloatingPointModel>
<AdditionalOptions>/W4</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<AdditionalIncludeDirectories>./../../config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_WINDOWS;UNICODE=1;_CRT_SECURE_NO_DEPRECATE;OPEN_SOURCE=1;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalOptions>/DEBUG</AdditionalOptions>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)SSE2NEON32.exe</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ProgramDatabaseFile>$(OutDir)/SSE2NEON32.exe.pdb</ProgramDatabaseFile>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)/SSE2NEON32.exe.map</MapFileName>
<SubSystem>Console</SubSystem>
<ImportLibrary>$(OutDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<ResourceCompile>
</ResourceCompile>
<ProjectReference>
</ProjectReference>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\SSE2NEON.h">
</ClInclude>
<ClInclude Include="..\..\SSE2NEONBinding.h">
</ClInclude>
<ClInclude Include="..\..\SSE2NEONTEST.h">
</ClInclude>
<ClCompile Include="..\..\main.cpp">
</ClCompile>
<ClCompile Include="..\..\SSE2NEONBinding.cpp">
</ClCompile>
<ClCompile Include="..\..\SSE2NEONTEST.cpp">
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 11
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SSE2NEON", "SSE2NEON.vcxproj", "{4D22D468-6380-1EC4-4643-53D05B3CA4C5}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
debug|x64 = debug|x64
release|x64 = release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4D22D468-6380-1EC4-4643-53D05B3CA4C5}.debug|x64.ActiveCfg = debug|x64
{4D22D468-6380-1EC4-4643-53D05B3CA4C5}.debug|x64.Build.0 = debug|x64
{4D22D468-6380-1EC4-4643-53D05B3CA4C5}.release|x64.ActiveCfg = release|x64
{4D22D468-6380-1EC4-4643-53D05B3CA4C5}.release|x64.Build.0 = release|x64
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddins) = postSolution
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="debug|x64">
<Configuration>debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="release|x64">
<Configuration>release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ApplicationEnvironment>title</ApplicationEnvironment>
<!-- - - - -->
<PlatformToolset>v110</PlatformToolset>
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<GenerateManifest>false</GenerateManifest>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<GenerateManifest>false</GenerateManifest>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
<OutDir>./../..\</OutDir>
<IntDir>./x64/SSE2NEON/debug\</IntDir>
<TargetExt>.exe</TargetExt>
<TargetName>SSE2NEON64DEBUG</TargetName>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
<FloatingPointModel>Fast</FloatingPointModel>
<AdditionalOptions>/W4</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>./../../config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_WINDOWS;UNICODE=1;_CRT_SECURE_NO_DEPRECATE;OPEN_SOURCE=1;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile></PrecompiledHeaderFile>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalOptions>/DEBUG</AdditionalOptions>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)SSE2NEON64DEBUG.exe</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ProgramDatabaseFile>$(OutDir)/SSE2NEON64DEBUG.exe.pdb</ProgramDatabaseFile>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)/SSE2NEON64DEBUG.exe.map</MapFileName>
<SubSystem>Console</SubSystem>
<ImportLibrary>$(OutDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
</Link>
<ResourceCompile>
</ResourceCompile>
<ProjectReference>
</ProjectReference>
</ItemDefinitionGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
<OutDir>./../..\</OutDir>
<IntDir>./x64/SSE2NEON/release\</IntDir>
<TargetExt>.exe</TargetExt>
<TargetName>SSE2NEON64</TargetName>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
<FloatingPointModel>Fast</FloatingPointModel>
<AdditionalOptions>/W4</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<AdditionalIncludeDirectories>./../../config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_WINDOWS;UNICODE=1;_CRT_SECURE_NO_DEPRECATE;OPEN_SOURCE=1;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile></PrecompiledHeaderFile>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalOptions>/DEBUG</AdditionalOptions>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)SSE2NEON64.exe</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ProgramDatabaseFile>$(OutDir)/SSE2NEON64.exe.pdb</ProgramDatabaseFile>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)/SSE2NEON64.exe.map</MapFileName>
<SubSystem>Console</SubSystem>
<ImportLibrary>$(OutDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
</Link>
<ResourceCompile>
</ResourceCompile>
<ProjectReference>
</ProjectReference>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\SSE2NEON.h">
</ClInclude>
<ClInclude Include="..\..\SSE2NEONBinding.h">
</ClInclude>
<ClInclude Include="..\..\SSE2NEONTEST.h">
</ClInclude>
<ClCompile Include="..\..\main.cpp">
</ClCompile>
<ClCompile Include="..\..\SSE2NEONBinding.cpp">
</ClCompile>
<ClCompile Include="..\..\SSE2NEONTEST.cpp">
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"></ImportGroup>
</Project>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="SSE2NEON"><!-- -->
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\SSE2NEON.h">
<Filter>SSE2NEON</Filter>
</ClInclude>
<ClInclude Include="..\..\SSE2NEONBinding.h">
<Filter>SSE2NEON</Filter>
</ClInclude>
<ClInclude Include="..\..\SSE2NEONTEST.h">

View File

@@ -0,0 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SSE2NEON", "SSE2NEON.vcxproj", "{4D22D468-6380-1EC4-4643-53D05B3CA4C5}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
debug|x64 = debug|x64
release|x64 = release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4D22D468-6380-1EC4-4643-53D05B3CA4C5}.debug|x64.ActiveCfg = debug|x64
{4D22D468-6380-1EC4-4643-53D05B3CA4C5}.debug|x64.Build.0 = debug|x64
{4D22D468-6380-1EC4-4643-53D05B3CA4C5}.release|x64.ActiveCfg = release|x64
{4D22D468-6380-1EC4-4643-53D05B3CA4C5}.release|x64.Build.0 = release|x64
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddins) = postSolution
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="debug|x64">
<Configuration>debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="release|x64">
<Configuration>release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<GenerateManifest>false</GenerateManifest>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<GenerateManifest>false</GenerateManifest>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
<OutDir>./../..\</OutDir>
<IntDir>./x64/SSE2NEON/debug\</IntDir>
<TargetExt>.exe</TargetExt>
<TargetName>SSE2NEON64DEBUG</TargetName>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
<FloatingPointModel>Fast</FloatingPointModel>
<AdditionalOptions>/W4</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>./../../config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_WINDOWS;UNICODE=1;_CRT_SECURE_NO_DEPRECATE;OPEN_SOURCE=1;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile></PrecompiledHeaderFile>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalOptions>/DEBUG</AdditionalOptions>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)SSE2NEON64DEBUG.exe</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ProgramDatabaseFile>$(OutDir)/SSE2NEON64DEBUG.exe.pdb</ProgramDatabaseFile>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)/SSE2NEON64DEBUG.exe.map</MapFileName>
<SubSystem>Console</SubSystem>
<ImportLibrary>$(OutDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
</Link>
<ResourceCompile>
</ResourceCompile>
<ProjectReference>
</ProjectReference>
</ItemDefinitionGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
<OutDir>./../..\</OutDir>
<IntDir>./x64/SSE2NEON/release\</IntDir>
<TargetExt>.exe</TargetExt>
<TargetName>SSE2NEON64</TargetName>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
<FloatingPointModel>Fast</FloatingPointModel>
<AdditionalOptions>/W4</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<AdditionalIncludeDirectories>./../../config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_WINDOWS;UNICODE=1;_CRT_SECURE_NO_DEPRECATE;OPEN_SOURCE=1;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile></PrecompiledHeaderFile>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalOptions>/DEBUG</AdditionalOptions>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)SSE2NEON64.exe</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ProgramDatabaseFile>$(OutDir)/SSE2NEON64.exe.pdb</ProgramDatabaseFile>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)/SSE2NEON64.exe.map</MapFileName>
<SubSystem>Console</SubSystem>
<ImportLibrary>$(OutDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
</Link>
<ResourceCompile>
</ResourceCompile>
<ProjectReference>
</ProjectReference>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\SSE2NEON.h">
</ClInclude>
<ClInclude Include="..\..\SSE2NEONBinding.h">
</ClInclude>
<ClInclude Include="..\..\SSE2NEONTEST.h">
</ClInclude>
<ClCompile Include="..\..\main.cpp">
</ClCompile>
<ClCompile Include="..\..\SSE2NEONBinding.cpp">
</ClCompile>
<ClCompile Include="..\..\SSE2NEONTEST.cpp">
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"></ImportGroup>
</Project>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="SSE2NEON"><!-- -->
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\SSE2NEON.h">
<Filter>SSE2NEON</Filter>
</ClInclude>
<ClInclude Include="..\..\SSE2NEONBinding.h">
<Filter>SSE2NEON</Filter>
</ClInclude>
<ClInclude Include="..\..\SSE2NEONTEST.h">

View File

@@ -0,0 +1,94 @@
<XPJ version="4">
<Project name="SSE2NEON" version="1">
<Export platform="win32" tool="vc9">../vc9win32</Export>
<Export platform="win32" tool="vc10">../vc10win32</Export>
<Export platform="win64" tool="vc9">../vc9win64</Export>
<Export platform="win64" tool="vc10">../vc10win64</Export>
<Target name="SSE2NEON">
<Export platform="win32" tool="vc9">../vc9win32</Export>
<Export platform="win32" tool="vc10">../vc10win32</Export>
<Export platform="win64" tool="vc9">../vc9win64</Export>
<Export platform="win64" tool="vc10">../vc10win64</Export>
<Files name="SSE2NEON" root="../../" type="header">
*.h
*.cpp
*.c
</Files>
<Configuration name="default" type="console">
<Preprocessor type="define">
WIN32
_WINDOWS
UNICODE=1
_CRT_SECURE_NO_DEPRECATE
OPEN_SOURCE=1
</Preprocessor>
<CFlags tool="vc8">/wd4996</CFlags>
<LFlags tool="vc8">/NODEFAULTLIB:libcp.lib</LFlags>
<SearchPaths type="header">
"../../config"
</SearchPaths>
<SearchPaths type="library">
</SearchPaths>
<Libraries>
</Libraries>
</Configuration>
<Configuration name="debug" platform="win32">
<OutDir>../../</OutDir>
<OutFile>SSE2NEON32DEBUG.exe</OutFile>
<CFlags>/fp:fast /W4 /WX /MTd /Zi</CFlags>
<LFlags>/DEBUG</LFlags>
<Preprocessor type="define">
_DEBUG
</Preprocessor>
<Libraries>
</Libraries>
</Configuration>
<Configuration name="release" platform="win32">
<OutDir>../../</OutDir>
<OutFile>SSE2NEON32.exe</OutFile>
<CFlags>/fp:fast /WX /W4 /MT /Zi /O2</CFlags>
<LFlags>/DEBUG</LFlags>
<Preprocessor type="define">NDEBUG</Preprocessor>
<Libraries>
</Libraries>
</Configuration>
<Configuration name="debug" platform="win64">
<OutDir>../../</OutDir>
<OutFile>SSE2NEON64DEBUG.exe</OutFile>
<CFlags>/fp:fast /W4 /WX /MTd /Zi</CFlags>
<LFlags>/DEBUG</LFlags>
<Preprocessor type="define">
_DEBUG
</Preprocessor>
<Libraries>
</Libraries>
</Configuration>
<Configuration name="release" platform="win64">
<OutDir>../../</OutDir>
<OutFile>SSE2NEON64.exe</OutFile>
<CFlags>/fp:fast /WX /W4 /MT /Zi /O2</CFlags>
<LFlags>/DEBUG</LFlags>
<Preprocessor type="define">NDEBUG</Preprocessor>
<Libraries>
</Libraries>
</Configuration>
<Libraries>
</Libraries>
<Dependencies type="link">
</Dependencies>
</Target>
</Project>
</XPJ>

View File

@@ -0,0 +1,17 @@
@echo off
set XPJ="xpj4.exe"
%XPJ% -v 1 -t VC11 -p WIN32 -x SSE2NEON.xpj
%XPJ% -v 1 -t VC11 -p WIN64 -x SSE2NEON.xpj
cd ..
cd vc11win64
goto cleanExit
:pauseExit
pause
:cleanExit

Binary file not shown.

34
thirdparty/sse2neon/main.cpp vendored Normal file
View File

@@ -0,0 +1,34 @@
#include "SSE2NEONTEST.h"
#include <stdio.h>
#include <stdint.h>
int main(int /*argc*/,const char ** /*argv*/)
{
SSE2NEON::SSE2NEONTest *test = SSE2NEON::SSE2NEONTest::create();
uint32_t passCount = 0;
uint32_t failedCount = 0;
for (uint32_t i = 0; i < SSE2NEON::IT_LAST; i++)
{
SSE2NEON::InstructionTest it = SSE2NEON::InstructionTest(i);
printf("Running Test %s\n", SSE2NEON::SSE2NEONTest::getInstructionTestString(it));
bool ok = test->runTest(it);
// If the test fails, we will run it again so we can step into the debugger and figure out why!
if (!ok)
{
printf("**FAILURE** SSE2NEONTest %s", SSE2NEON::SSE2NEONTest::getInstructionTestString(it));
// test->runTest(it); // Uncomment this to step through the code to find the failure case
}
if (ok)
{
passCount++;
}
else
{
failedCount++;
}
}
test->release();
printf("SSE2NEONTest Complete: Passed %d tests : Failed %d\n", passCount, failedCount);
return 0;
}