├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── Thirdparty
├── Sophus
│ ├── .clang-format
│ ├── CMakeLists.txt
│ ├── LICENSE.txt
│ ├── README.rst
│ ├── Sophus.code-workspace
│ ├── SophusConfig.cmake.in
│ ├── appveyor.yml
│ ├── cmake_modules
│ │ └── FindEigen3.cmake
│ ├── doxyfile
│ ├── doxyrest-config.lua
│ ├── examples
│ │ ├── CMakeLists.txt
│ │ └── HelloSO3.cpp
│ ├── generate_stubs.py
│ ├── make_docs.sh
│ ├── package.xml
│ ├── rst-dir
│ │ ├── conf.py
│ │ ├── page_index.rst
│ │ └── pysophus.rst
│ ├── run_format.sh
│ ├── scripts
│ │ ├── install_docs_deps.sh
│ │ ├── install_linux_deps.sh
│ │ ├── install_linux_fmt_deps.sh
│ │ ├── install_osx_deps.sh
│ │ └── run_cpp_tests.sh
│ ├── setup.py
│ ├── sophus
│ │ ├── average.hpp
│ │ ├── cartesian.hpp
│ │ ├── ceres_local_parameterization.hpp
│ │ ├── ceres_manifold.hpp
│ │ ├── ceres_typetraits.hpp
│ │ ├── common.hpp
│ │ ├── example_ensure_handler.cpp
│ │ ├── geometry.hpp
│ │ ├── interpolate.hpp
│ │ ├── interpolate_details.hpp
│ │ ├── num_diff.hpp
│ │ ├── rotation_matrix.hpp
│ │ ├── rxso2.hpp
│ │ ├── rxso3.hpp
│ │ ├── se2.hpp
│ │ ├── se3.hpp
│ │ ├── sim2.hpp
│ │ ├── sim3.hpp
│ │ ├── sim_details.hpp
│ │ ├── so2.hpp
│ │ ├── so3.hpp
│ │ ├── spline.hpp
│ │ ├── test_macros.hpp
│ │ ├── types.hpp
│ │ └── velocities.hpp
│ ├── sophus_pybind-stubs
│ │ ├── py.typed
│ │ └── sophus_pybind.pyi
│ ├── sophus_pybind
│ │ ├── README
│ │ ├── SE3PyBind.h
│ │ ├── SO3PyBind.h
│ │ ├── SophusPyBind.h
│ │ ├── bindings.cpp
│ │ ├── examples
│ │ │ └── sophus_quickstart_tutorial.ipynb
│ │ └── tests
│ │ │ └── sophusPybindTests.py
│ ├── sympy
│ │ ├── cpp_gencode
│ │ │ ├── Se2_Dx_exp_x.cpp
│ │ │ ├── Se2_Dx_log_this.cpp
│ │ │ ├── Se2_Dx_this_mul_exp_x_at_0.cpp
│ │ │ ├── Se3_Dx_exp_x.cpp
│ │ │ ├── Se3_Dx_log_this.cpp
│ │ │ ├── Se3_Dx_this_mul_exp_x_at_0.cpp
│ │ │ ├── So2_Dx_exp_x.cpp
│ │ │ ├── So2_Dx_log_exp_x_times_this_at_0.cpp
│ │ │ ├── So2_Dx_log_this.cpp
│ │ │ ├── So2_Dx_this_mul_exp_x_at_0.cpp
│ │ │ ├── So3_Dx_exp_x.cpp
│ │ │ ├── So3_Dx_log_exp_x_times_this_at_0.cpp
│ │ │ ├── So3_Dx_log_this.cpp
│ │ │ └── So3_Dx_this_mul_exp_x_at_0.cpp
│ │ ├── run_tests.sh
│ │ └── sophus
│ │ │ ├── __init__.py
│ │ │ ├── complex.py
│ │ │ ├── cse_codegen.py
│ │ │ ├── dual_quaternion.py
│ │ │ ├── matrix.py
│ │ │ ├── quaternion.py
│ │ │ ├── se2.py
│ │ │ ├── se3.py
│ │ │ ├── so2.py
│ │ │ └── so3.py
│ └── test
│ │ ├── CMakeLists.txt
│ │ ├── ceres
│ │ ├── CMakeLists.txt
│ │ ├── test_ceres_rxso2.cpp
│ │ ├── test_ceres_rxso3.cpp
│ │ ├── test_ceres_se2.cpp
│ │ ├── test_ceres_se3.cpp
│ │ ├── test_ceres_sim2.cpp
│ │ ├── test_ceres_sim3.cpp
│ │ ├── test_ceres_so2.cpp
│ │ ├── test_ceres_so3.cpp
│ │ └── tests.hpp
│ │ └── core
│ │ ├── CMakeLists.txt
│ │ ├── test_cartesian2.cpp
│ │ ├── test_cartesian3.cpp
│ │ ├── test_common.cpp
│ │ ├── test_geometry.cpp
│ │ ├── test_rxso2.cpp
│ │ ├── test_rxso3.cpp
│ │ ├── test_se2.cpp
│ │ ├── test_se3.cpp
│ │ ├── test_sim2.cpp
│ │ ├── test_sim3.cpp
│ │ ├── test_so2.cpp
│ │ ├── test_so3.cpp
│ │ ├── test_velocities.cpp
│ │ └── tests.hpp
└── tessil-src
│ ├── CMakeLists.txt
│ ├── LICENSE
│ ├── README.md
│ ├── appveyor.yml
│ ├── cmake
│ └── tsl-robin-mapConfig.cmake.in
│ ├── doxygen.conf
│ ├── include
│ └── tsl
│ │ ├── robin_growth_policy.h
│ │ ├── robin_hash.h
│ │ ├── robin_map.h
│ │ └── robin_set.h
│ ├── tests
│ ├── CMakeLists.txt
│ ├── custom_allocator_tests.cpp
│ ├── main.cpp
│ ├── policy_tests.cpp
│ ├── robin_map_tests.cpp
│ ├── robin_set_tests.cpp
│ └── utils.h
│ └── tsl-robin-map.natvis
├── config
├── avia.yaml
├── horizon.yaml
├── mid360.yaml
├── ouster.yaml
├── pandar.yaml
├── robosense.yaml
└── velodyne.yaml
├── image
├── overview.png
└── video_cover.png
├── include
├── color.h
├── common_lib.h
├── ikd-Tree
│ ├── README.md
│ ├── ikd_Tree.cpp
│ └── ikd_Tree.h
├── matplotlibcpp.h
├── scope_timer.hpp
└── so3_math.h
├── launch
├── hesai_pandarXT.launch
├── livox_avia.launch
├── livox_horizon.launch
├── livox_mid360.launch
├── ouster.launch
├── robosense.launch
└── velodyne.launch
├── msg
├── Pose6D.msg
└── States.msg
├── package.xml
├── rviz_cfg
├── .gitignore
├── fast_lo.rviz
└── spinning.rviz
└── src
├── IMU_Processing.hpp
├── laserMapping.cpp
├── preprocess.cpp
└── preprocess.h
/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YWL0720/I2EKF-LO/8d2158cda30ed9b261e668b9ab6f75f5ab424624/.gitignore
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.3)
2 | project(i2ekf_lo)
3 |
4 | SET(CMAKE_BUILD_TYPE "Release")
5 |
6 | ADD_COMPILE_OPTIONS(-std=c++14 )
7 | ADD_COMPILE_OPTIONS(-std=c++14 )
8 | set( CMAKE_CXX_FLAGS "-std=c++14 -O3" )
9 |
10 | add_definitions(-DROOT_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/\")
11 |
12 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions" )
13 | set(CMAKE_CXX_STANDARD 14)
14 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
15 | set(CMAKE_CXX_EXTENSIONS OFF)
16 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -pthread -std=c++0x -std=c++14 -fexceptions")
17 |
18 | message("Current CPU architecture: ${CMAKE_SYSTEM_PROCESSOR}")
19 | if(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)" )
20 | include(ProcessorCount)
21 | ProcessorCount(N)
22 | message("Processer number: ${N}")
23 | if(N GREATER 4)
24 | add_definitions(-DMP_EN)
25 | add_definitions(-DMP_PROC_NUM=3)
26 | message("core for MP: 3")
27 | elseif(N GREATER 3)
28 | add_definitions(-DMP_EN)
29 | add_definitions(-DMP_PROC_NUM=2)
30 | message("core for MP: 2")
31 | else()
32 | add_definitions(-DMP_PROC_NUM=1)
33 | endif()
34 | else()
35 | add_definitions(-DMP_PROC_NUM=1)
36 | endif()
37 |
38 | add_subdirectory(Thirdparty/Sophus)
39 | add_subdirectory(Thirdparty/tessil-src)
40 |
41 | find_package(OpenMP QUIET)
42 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
43 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
44 |
45 | find_package(PythonLibs REQUIRED)
46 | find_path(MATPLOTLIB_CPP_INCLUDE_DIRS "matplotlibcpp.h")
47 |
48 | find_package(catkin REQUIRED COMPONENTS
49 | geometry_msgs
50 | nav_msgs
51 | sensor_msgs
52 | roscpp
53 | rospy
54 | std_msgs
55 | pcl_ros
56 | tf
57 | livox_ros_driver
58 | message_generation
59 | eigen_conversions
60 | )
61 |
62 | find_package(Eigen3 REQUIRED)
63 | find_package(PCL 1.8 REQUIRED)
64 | find_package(Ceres REQUIRED)
65 |
66 | message(Eigen: ${EIGEN3_INCLUDE_DIR})
67 |
68 | include_directories(
69 | ../../devel/include
70 | ${catkin_INCLUDE_DIRS}
71 | ${EIGEN3_INCLUDE_DIR}
72 | ${PCL_INCLUDE_DIRS}
73 | ${PYTHON_INCLUDE_DIRS}
74 | include)
75 |
76 | add_message_files(
77 | FILES
78 | Pose6D.msg
79 | States.msg
80 | )
81 |
82 | generate_messages(
83 | DEPENDENCIES
84 | geometry_msgs
85 | )
86 |
87 | catkin_package(
88 | CATKIN_DEPENDS geometry_msgs nav_msgs roscpp rospy std_msgs message_runtime
89 | DEPENDS EIGEN3 PCL
90 | INCLUDE_DIRS
91 | )
92 |
93 | add_executable(i2ekf_lo_mapping
94 | src/laserMapping.cpp
95 | include/ikd-Tree/ikd_Tree.cpp
96 | src/preprocess.cpp)
97 |
98 | add_dependencies(i2ekf_lo_mapping ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
99 |
100 | target_link_libraries(i2ekf_lo_mapping ${catkin_LIBRARIES} ${PCL_LIBRARIES} ${PYTHON_LIBRARIES} ${CERES_LIBRARIES} Sophus::Sophus tsl::robin_map)
101 | target_include_directories(i2ekf_lo_mapping PRIVATE ${PYTHON_INCLUDE_DIRS})
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
I2EKF-LO
3 |
A Dual-Iteration Extended Kalman Filter Based LiDAR Odometry
4 |
5 |
IROS 2024 Oral
6 |
7 |

8 |
9 |
10 |
11 | ### Introduction
12 | LiDAR odometry is a pivotal technology in the fields of autonomous driving and autonomous mobile robotics. However, most of the current works focuse on nonlinear optimization methods, and there are still many challenges in using the traditional Iterative Extended Kalman Filter (IEKF) framework to tackle the problem: IEKF only iterates over the observation equation, relying on a rough estimate of the initial state, which is insufficient to fully eliminate motion distortion in the input point cloud; the system process noise is difficult to be determined during state estimation of the complex motions; and the varying motion models across different sensor carriers. To address these issues, we propose the Dual-Iteration Extended Kalman Filter (I2EKF) and the LiDAR odometry based on I2EKF (I2EKF-LO). This approach not only iterates over the observation equation but also leverages state updates to iteratively mitigate motion distortion in LiDAR point clouds. Moreover, it dynamically adjusts process noise based on the confidence level of prior predictions during state estimation and establishes motion models for different sensor carriers to achieve accurate and efficient state estimation. Comprehensive experiments demonstrate that I2EKF-LO achieves outstanding levels of accuracy and computational efficiency in the realm of LiDAR odometry.
13 |
14 | **Developers**: The codes of this repo are contributed by [Wenlu Yu (于文录)](https://github.com/YWL0720), [Jie Xu (徐杰)](https://github.com/jiejie567), [Chengwei Zhao (赵成伟)](https://github.com/chengwei0427)
15 |
16 | ### News
17 | * **[30/06/2024]**: I2EKF-LO is accepted to IROS 2024.
18 | * **[01/07/2024]**: We are currently working on organizing and refining the complete code. The full version will be released soon.
19 | * **[02/07/2024]**: Updated the video link and submitted the paper to arxiv.
20 |
21 | ### Related Paper
22 |
23 | Related paper available on arxiv: [I2EKF-LO: A Dual-Iteration Extended Kalman Filter Based LiDAR Odometry](https://arxiv.org/abs/2407.02190)
24 |
25 | ### Related Video:
26 |
27 |
28 |
29 |

30 |
31 |
32 | ## 1. Prerequisites
33 |
34 | ### 1.1 **Ubuntu** and **ROS**
35 |
36 | Ubuntu >= 18.04.
37 |
38 | ROS >= Melodic. [ROS Installation](http://wiki.ros.org/ROS/Installation)
39 |
40 | ### 1.2. **PCL && Eigen**
41 |
42 | PCL >= 1.8, Follow [PCL Installation](http://www.pointclouds.org/downloads/linux.html).
43 |
44 | Eigen >= 3.3.4, Follow [Eigen Installation](http://eigen.tuxfamily.org/index.php?title=Main_Page).
45 |
46 | ### 1.3. **livox_ros_driver**
47 |
48 | Follow [livox_ros_driver Installation](https://github.com/Livox-SDK/livox_ros_driver).
49 |
50 |
51 | ## 2. Build
52 |
53 | Clone the repository and catkin_make:
54 |
55 | ```
56 | cd ~/catkin_ws/src
57 | git clone https://github.com/YWL0720/I2EKF-LO
58 | cd ..
59 | catkin_make -j
60 | source devel/setup.bash
61 | ```
62 |
63 | ## 3. Directly run
64 |
65 | ```bash
66 | cd ~/$I2EKF_LO_ROS_DIR$
67 | source devel/setup.bash
68 | roslaunch i2ekf_lo xxx.launch
69 | ```
70 | ## 4. Rosbag Example
71 | Download our test bags here: [HIT-TIB Datasets](https://drive.google.com/drive/folders/1L5cX9uyAiZei17oq7ELyd8WyIRReHq8u?usp=drive_link).
72 |
73 | ## 5. Acknowledgments
74 |
75 | Thanks for [Fast-LIO2](https://github.com/hku-mars/FAST_LIO) (Fast Direct LiDAR-inertial Odometry) and [LI-INIT](https://github.com/hku-mars/LiDAR_IMU_Init)(Robust Real-time LiDAR-inertial Initialization).
76 |
77 | ## 6. License
78 |
79 | The source code is released under [GPLv2](http://www.gnu.org/licenses/) license.
80 |
81 | ## 7. TODO(s)
82 | - [ ] Updated video link
83 | - [ ] Upload a preprint of our paper
84 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/.clang-format:
--------------------------------------------------------------------------------
1 | Language: Cpp
2 | # BasedOnStyle: Google
3 | AccessModifierOffset: -1
4 | AlignAfterOpenBracket: Align
5 | AlignConsecutiveAssignments: false
6 | AlignConsecutiveDeclarations: false
7 | AlignEscapedNewlinesLeft: true
8 | AlignOperands: true
9 | AlignTrailingComments: true
10 | AllowAllParametersOfDeclarationOnNextLine: true
11 | AllowShortBlocksOnASingleLine: false
12 | AllowShortCaseLabelsOnASingleLine: false
13 | AllowShortFunctionsOnASingleLine: All
14 | AllowShortIfStatementsOnASingleLine: true
15 | AllowShortLoopsOnASingleLine: true
16 | AlwaysBreakAfterDefinitionReturnType: None
17 | AlwaysBreakAfterReturnType: None
18 | AlwaysBreakBeforeMultilineStrings: true
19 | AlwaysBreakTemplateDeclarations: true
20 | BinPackArguments: true
21 | BinPackParameters: true
22 | BraceWrapping:
23 | AfterClass: false
24 | AfterControlStatement: false
25 | AfterEnum: false
26 | AfterFunction: false
27 | AfterNamespace: false
28 | AfterObjCDeclaration: false
29 | AfterStruct: false
30 | AfterUnion: false
31 | BeforeCatch: false
32 | BeforeElse: false
33 | IndentBraces: false
34 | BreakBeforeBinaryOperators: None
35 | BreakBeforeBraces: Attach
36 | BreakBeforeTernaryOperators: true
37 | BreakConstructorInitializersBeforeComma: false
38 | ColumnLimit: 80
39 | CommentPragmas: '^ IWYU pragma:'
40 | ConstructorInitializerAllOnOneLineOrOnePerLine: true
41 | ConstructorInitializerIndentWidth: 4
42 | ContinuationIndentWidth: 4
43 | Cpp11BracedListStyle: true
44 | DerivePointerAlignment: true
45 | DisableFormat: false
46 | ExperimentalAutoDetectBinPacking: false
47 | ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
48 | IncludeCategories:
49 | - Regex: '^<.*\.h>'
50 | Priority: 1
51 | - Regex: '^<.*'
52 | Priority: 2
53 | - Regex: '.*'
54 | Priority: 3
55 | IndentCaseLabels: true
56 | IndentWidth: 2
57 | IndentWrappedFunctionNames: false
58 | KeepEmptyLinesAtTheStartOfBlocks: false
59 | MacroBlockBegin: ''
60 | MacroBlockEnd: ''
61 | MaxEmptyLinesToKeep: 1
62 | NamespaceIndentation: None
63 | ObjCBlockIndentWidth: 2
64 | ObjCSpaceAfterProperty: false
65 | ObjCSpaceBeforeProtocolList: false
66 | PenaltyBreakBeforeFirstCallParameter: 1
67 | PenaltyBreakComment: 300
68 | PenaltyBreakFirstLessLess: 120
69 | PenaltyBreakString: 1000
70 | PenaltyExcessCharacter: 1000000
71 | PenaltyReturnTypeOnItsOwnLine: 200
72 | PointerAlignment: Left
73 | ReflowComments: true
74 | SortIncludes: true
75 | SpaceAfterCStyleCast: false
76 | SpaceBeforeAssignmentOperators: true
77 | SpaceBeforeParens: ControlStatements
78 | SpaceInEmptyParentheses: false
79 | SpacesBeforeTrailingComments: 2
80 | SpacesInAngles: false
81 | SpacesInContainerLiterals: true
82 | SpacesInCStyleCastParentheses: false
83 | SpacesInParentheses: false
84 | SpacesInSquareBrackets: false
85 | Standard: Auto
86 | TabWidth: 8
87 | UseTab: Never
88 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright 2011-2017 Hauke Strasdat
2 | 2012-2017 Steven Lovegrove
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to
6 | deal in the Software without restriction, including without limitation the
7 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 | sell copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | IN THE SOFTWARE.
--------------------------------------------------------------------------------
/Thirdparty/Sophus/README.rst:
--------------------------------------------------------------------------------
1 | |GithubCICpp|_ windows: |AppVeyor|_ |GithubCISympy|_ |ci_cov|_
2 |
3 |
4 | Sophus
5 | ======
6 |
7 | Overview
8 | --------
9 |
10 | This is a c++ implementation of Lie groups commonly used for 2d and 3d
11 | geometric problems (i.e. for Computer Vision or Robotics applications).
12 | Among others, this package includes the special orthogonal groups SO(2) and
13 | SO(3) to present rotations in 2d and 3d as well as the special Euclidean group
14 | SE(2) and SE(3) to represent rigid body transformations (i.e. rotations and
15 | translations) in 2d and 3d.
16 |
17 | API documentation: https://strasdat.github.io/Sophus/
18 |
19 | Cross platform support
20 | ----------------------
21 |
22 | Sophus compiles with clang and gcc on Linux and OS X as well as msvc on Windows.
23 | The specific compiler and operating system versions which are supported are
24 | the ones which are used in the Continuous Integration (CI): See GitHubCI_ and
25 | AppVeyor_ for details.
26 |
27 | However, it should work (with no to minor modification) on many other
28 | modern configurations as long they support c++14, CMake, Eigen 3.3.X and
29 | (optionally) fmt. The fmt dependency can be eliminated by passing
30 | "-DUSE_BASIC_LOGGING=ON" to cmake when configuring Sophus.
31 |
32 | .. _GitHubCI: https://github.com/strasdat/Sophus/actions
33 |
34 | .. |AppVeyor| image:: https://ci.appveyor.com/api/projects/status/um4285lwhs8ci7pt/branch/master?svg=true
35 | .. _AppVeyor: https://ci.appveyor.com/project/strasdat/sophus/branch/master
36 |
37 | .. |ci_cov| image:: https://coveralls.io/repos/github/strasdat/Sophus/badge.svg?branch=master
38 | .. _ci_cov: https://coveralls.io/github/strasdat/Sophus?branch=master
39 |
40 | .. |GithubCICpp| image:: https://github.com/strasdat/Sophus/actions/workflows/main.yml/badge.svg?branch=master
41 | .. _GithubCICpp: https://github.com/strasdat/Sophus/actions/workflows/main.yml?query=branch%3Amaster
42 |
43 | .. |GithubCISympy| image:: https://github.com/strasdat/Sophus/actions/workflows/sympy.yml/badge.svg?branch=master
44 | .. _GithubCISympy: https://github.com/strasdat/Sophus/actions/workflows/sympy.yml?query=branch%3Amaster
45 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/Sophus.code-workspace:
--------------------------------------------------------------------------------
1 | {
2 | "folders": [
3 | {
4 | "path": "."
5 | }
6 | ],
7 | "settings": {}
8 | }
--------------------------------------------------------------------------------
/Thirdparty/Sophus/SophusConfig.cmake.in:
--------------------------------------------------------------------------------
1 | @PACKAGE_INIT@
2 |
3 | include (CMakeFindDependencyMacro)
4 |
5 | @Eigen3_DEPENDENCY@
6 | @fmt_DEPENDENCY@
7 |
8 | include ("${CMAKE_CURRENT_LIST_DIR}/SophusTargets.cmake")
9 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/appveyor.yml:
--------------------------------------------------------------------------------
1 | branches:
2 | only:
3 | - master
4 |
5 | os: Visual Studio 2015
6 |
7 | clone_folder: c:\projects\sophus
8 |
9 | platform: x64
10 | configuration: Debug
11 |
12 | build:
13 | project: c:\projects\sophus\build\Sophus.sln
14 |
15 | install:
16 | - ps: wget https://gitlab.com/libeigen/eigen/-/archive/3.3.4/eigen-3.3.4.zip -outfile eigen3.zip
17 | - cmd: 7z x eigen3.zip -o"C:\projects" -y > nul
18 | - git clone https://github.com/fmtlib/fmt.git
19 | - cd fmt
20 | - git checkout 5.3.0
21 | - mkdir build
22 | - cd build
23 | - cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE=Debug ..
24 | - cmake --build .
25 | - cmake --build . --target install
26 | - cd ../..
27 |
28 | before_build:
29 | - cd c:\projects\sophus
30 | - mkdir build
31 | - cd build
32 | - cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE=Debug -D EIGEN3_INCLUDE_DIR=C:\projects\eigen-3.3.4 ..
33 |
34 | after_build:
35 | - ctest --output-on-failure
36 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/cmake_modules/FindEigen3.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find Eigen3 lib
2 | #
3 | # This module supports requiring a minimum version, e.g. you can do
4 | # find_package(Eigen3 3.1.2)
5 | # to require version 3.1.2 or newer of Eigen3.
6 | #
7 | # Once done this will define
8 | #
9 | # EIGEN3_FOUND - system has eigen lib with correct version
10 | # EIGEN3_INCLUDE_DIR - the eigen include directory
11 | # EIGEN3_VERSION - eigen version
12 | #
13 | # and the following imported target:
14 | #
15 | # Eigen3::Eigen - The header-only Eigen library
16 | #
17 | # This module reads hints about search locations from
18 | # the following environment variables:
19 | #
20 | # EIGEN3_ROOT
21 | # EIGEN3_ROOT_DIR
22 |
23 | # Copyright (c) 2006, 2007 Montel Laurent,
24 | # Copyright (c) 2008, 2009 Gael Guennebaud,
25 | # Copyright (c) 2009 Benoit Jacob
26 | # Redistribution and use is allowed according to the terms of the 2-clause BSD license.
27 |
28 | if(NOT Eigen3_FIND_VERSION)
29 | if(NOT Eigen3_FIND_VERSION_MAJOR)
30 | set(Eigen3_FIND_VERSION_MAJOR 2)
31 | endif()
32 | if(NOT Eigen3_FIND_VERSION_MINOR)
33 | set(Eigen3_FIND_VERSION_MINOR 91)
34 | endif()
35 | if(NOT Eigen3_FIND_VERSION_PATCH)
36 | set(Eigen3_FIND_VERSION_PATCH 0)
37 | endif()
38 |
39 | set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}")
40 | endif()
41 |
42 | macro(_eigen3_check_version)
43 | file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header)
44 |
45 | string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}")
46 | set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}")
47 | string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}")
48 | set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}")
49 | string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}")
50 | set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}")
51 |
52 | set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION})
53 | if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
54 | set(EIGEN3_VERSION_OK FALSE)
55 | else()
56 | set(EIGEN3_VERSION_OK TRUE)
57 | endif()
58 |
59 | if(NOT EIGEN3_VERSION_OK)
60 |
61 | message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, "
62 | "but at least version ${Eigen3_FIND_VERSION} is required")
63 | endif()
64 | endmacro()
65 |
66 | if (EIGEN3_INCLUDE_DIR)
67 |
68 | # in cache already
69 | _eigen3_check_version()
70 | set(EIGEN3_FOUND ${EIGEN3_VERSION_OK})
71 | set(Eigen3_FOUND ${EIGEN3_VERSION_OK})
72 |
73 | else ()
74 |
75 | # search first if an Eigen3Config.cmake is available in the system,
76 | # if successful this would set EIGEN3_INCLUDE_DIR and the rest of
77 | # the script will work as usual
78 | find_package(Eigen3 ${Eigen3_FIND_VERSION} NO_MODULE QUIET)
79 |
80 | if(NOT EIGEN3_INCLUDE_DIR)
81 | find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library
82 | HINTS
83 | ENV EIGEN3_ROOT
84 | ENV EIGEN3_ROOT_DIR
85 | PATHS
86 | ${CMAKE_INSTALL_PREFIX}/include
87 | ${KDE4_INCLUDE_DIR}
88 | PATH_SUFFIXES eigen3 eigen
89 | )
90 | endif()
91 |
92 | if(EIGEN3_INCLUDE_DIR)
93 | _eigen3_check_version()
94 | endif()
95 |
96 | include(FindPackageHandleStandardArgs)
97 | find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK)
98 |
99 | mark_as_advanced(EIGEN3_INCLUDE_DIR)
100 |
101 | endif()
102 |
103 | if(EIGEN3_FOUND AND NOT TARGET Eigen3::Eigen)
104 | add_library(Eigen3::Eigen INTERFACE IMPORTED)
105 | set_target_properties(Eigen3::Eigen PROPERTIES
106 | INTERFACE_INCLUDE_DIRECTORIES "${EIGEN3_INCLUDE_DIR}")
107 | endif()
108 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/doxyfile:
--------------------------------------------------------------------------------
1 | DOXYFILE_ENCODING = UTF-8
2 | PROJECT_NAME = "Sophus"
3 | INPUT = sophus
4 | EXTRACT_ALL = YES
5 | ENABLE_PREPROCESSING = YES
6 | MACRO_EXPANSION = YES
7 | WARN_AS_ERROR = YES
8 | EXPAND_ONLY_PREDEF = NO
9 | SKIP_FUNCTION_MACROS = NO
10 | AUTOLINK_SUPPORT = YES
11 | MULTILINE_CPP_IS_BRIEF = YES
12 | MARKDOWN_SUPPORT = YES
13 | INLINE_INHERITED_MEMB = NO
14 | EXCLUDE_SYMBOLS = Eigen::internal Sophus::details Sophus::interp_details Sophus::experimental
15 | GENERATE_LATEX = NO
16 | STRIP_CODE_COMMENTS = NO
17 |
18 | GENERATE_XML = YES
19 | GENERATE_HTML = NO
20 | XML_OUTPUT = xml-dir
21 | XML_PROGRAMLISTING = NO
22 | CASE_SENSE_NAMES = NO
23 | HIDE_UNDOC_RELATIONS = YES
24 | EXTRACT_ALL = YES
--------------------------------------------------------------------------------
/Thirdparty/Sophus/doxyrest-config.lua:
--------------------------------------------------------------------------------
1 | FRAME_DIR_LIST = { "doxyrest_b/doxyrest/frame/cfamily", "doxyrest_b/doxyrest/frame/common" }
2 | FRAME_FILE = "index.rst.in"
3 | INPUT_FILE = "xml-dir/index.xml"
4 | OUTPUT_FILE = "rst-dir/index.rst"
5 | INTRO_FILE = "page_index.rst"
6 | SORT_GROUPS_BY = "title"
7 | GLOBAL_AUX_COMPOUND_ID = "group_global"
8 | LANGUAGE = cpp
9 | VERBATIM_TO_CODE_BLOCK = "cpp"
10 | ESCAPE_ASTERISKS = true
11 | ESCAPE_PIPES = true
12 | ESCAPE_TRAILING_UNDERSCORES = true
13 | PROTECTION_FILTER = "protected"
14 | EXCLUDE_EMPTY_DEFINES = true
15 | EXCLUDE_DEFAULT_CONSTRUCTORS = false
16 | EXCLUDE_DESTRUCTORS = false
17 | EXCLUDE_PRIMITIVE_TYPEDEFS = true
18 | SHOW_DIRECT_DESCENDANTS = true
19 | TYPEDEF_TO_USING = true
20 | ML_PARAM_LIST_LENGTH_THRESHOLD = 80
--------------------------------------------------------------------------------
/Thirdparty/Sophus/examples/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Tests to run
2 | SET( EXAMPLE_SOURCES HelloSO3)
3 |
4 | FOREACH(example_src ${EXAMPLE_SOURCES})
5 | ADD_EXECUTABLE( ${example_src} ${example_src}.cpp)
6 | TARGET_LINK_LIBRARIES( ${example_src} sophus)
7 | ENDFOREACH(example_src)
8 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/examples/HelloSO3.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "sophus/geometry.hpp"
3 |
4 | int main() {
5 | // The following demonstrates the group multiplication of rotation matrices
6 |
7 | // Create rotation matrices from rotations around the x and y and z axes:
8 | const double kPi = Sophus::Constants::pi();
9 | Sophus::SO3d R1 = Sophus::SO3d::rotX(kPi / 4);
10 | Sophus::SO3d R2 = Sophus::SO3d::rotY(kPi / 6);
11 | Sophus::SO3d R3 = Sophus::SO3d::rotZ(-kPi / 3);
12 |
13 | std::cout << "The rotation matrices are" << std::endl;
14 | std::cout << "R1:\n" << R1.matrix() << std::endl;
15 | std::cout << "R2:\n" << R2.matrix() << std::endl;
16 | std::cout << "R3:\n" << R3.matrix() << std::endl;
17 | std::cout << "Their product R1*R2*R3:\n"
18 | << (R1 * R2 * R3).matrix() << std::endl;
19 | std::cout << std::endl;
20 |
21 | // Rotation matrices can act on vectors
22 | Eigen::Vector3d x;
23 | x << 0.0, 0.0, 1.0;
24 | std::cout << "Rotation matrices can act on vectors" << std::endl;
25 | std::cout << "x\n" << x << std::endl;
26 | std::cout << "R2*x\n" << R2 * x << std::endl;
27 | std::cout << "R1*(R2*x)\n" << R1 * (R2 * x) << std::endl;
28 | std::cout << "(R1*R2)*x\n" << (R1 * R2) * x << std::endl;
29 | std::cout << std::endl;
30 |
31 | // SO(3) are internally represented as unit quaternions.
32 | std::cout << "R1 in matrix form:\n" << R1.matrix() << std::endl;
33 | std::cout << "R1 in unit quaternion form:\n"
34 | << R1.unit_quaternion().coeffs() << std::endl;
35 | // Note that the order of coefficients of Eigen's quaternion class is
36 | // (imag0, imag1, imag2, real)
37 | std::cout << std::endl;
38 | }
--------------------------------------------------------------------------------
/Thirdparty/Sophus/generate_stubs.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 |
3 | subprocess.run(
4 | "pybind11-stubgen sophus_pybind -o sophus_pybind-stubs/",
5 | shell=True,
6 | check=True,
7 | )
8 |
9 | subprocess.run("touch sophus_pybind-stubs/py.typed", shell=True, check=True)
10 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/make_docs.sh:
--------------------------------------------------------------------------------
1 | doxygen doxyfile
2 | doxyrest_b/build/doxyrest/bin/Release/doxyrest -c doxyrest-config.lua
3 | sphinx-build -b html rst-dir html-dir
--------------------------------------------------------------------------------
/Thirdparty/Sophus/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | sophus
4 | 1.22.10
5 |
6 | C++ implementation of Lie Groups using Eigen.
7 |
8 | https://github.com/strasdat/sophus
9 | https://github.com/strasdat/sophus/issues
10 | Daniel Stonier
11 | Hauke Strasdat
12 | MIT
13 |
14 | cmake
15 |
16 | eigen
17 | eigen
18 |
19 |
20 | cmake
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/rst-dir/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # This file only contains a selection of the most common options. For a full
4 | # list see the documentation:
5 | # http://www.sphinx-doc.org/en/master/config
6 |
7 | # -- Path setup --------------------------------------------------------------
8 |
9 | # If extensions (or modules to document with autodoc) are in another directory,
10 | # add these directories to sys.path here. If the directory is relative to the
11 | # documentation root, use os.path.abspath to make it absolute, like shown here.
12 | #
13 | import os
14 | import sys
15 | sys.path.insert(0, os.path.abspath('../sympy'))
16 |
17 |
18 | sys.path.insert(1, os.path.abspath('../doxyrest_b/doxyrest/sphinx'))
19 | extensions = ['doxyrest', 'cpplexer', 'sphinx.ext.autodoc']
20 |
21 | # -- Project information -----------------------------------------------------
22 |
23 | project = 'Sophus'
24 | copyright = '2019, Hauke Strasdat'
25 | author = 'Hauke Strasdat'
26 |
27 |
28 | # Tell sphinx what the primary language being documented is.
29 | primary_domain = 'cpp'
30 |
31 | # Tell sphinx what the pygments highlight language should be.
32 | highlight_language = 'cpp'
33 |
34 |
35 | # Add any paths that contain templates here, relative to this directory.
36 | templates_path = ['_templates']
37 |
38 | # List of patterns, relative to source directory, that match files and
39 | # directories to ignore when looking for source files.
40 | # This pattern also affects html_static_path and html_extra_path.
41 | exclude_patterns = []
42 |
43 |
44 | # -- Options for HTML output -------------------------------------------------
45 |
46 | # The theme to use for HTML and HTML Help pages. See the documentation for
47 | # a list of builtin themes.
48 | #
49 | html_theme = "sphinx_rtd_theme"
50 |
51 | # Add any paths that contain custom static files (such as style sheets) here,
52 | # relative to this directory. They are copied after the builtin static files,
53 | # so a file named "default.css" will overwrite the builtin "default.css".
54 | html_static_path = ['_static']
55 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/rst-dir/page_index.rst:
--------------------------------------------------------------------------------
1 | Sophus - Lie groups for 2d/3d Geometry
2 | =======================================
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 | :caption: Contents:
7 |
8 | GitHub Page
9 | pysophus
--------------------------------------------------------------------------------
/Thirdparty/Sophus/rst-dir/pysophus.rst:
--------------------------------------------------------------------------------
1 | Python API
2 | ==========
3 |
4 | .. automodule:: sophus.matrix
5 | :members:
6 |
7 | .. automodule:: sophus.complex
8 | :members:
9 |
10 | .. automodule:: sophus.quaternion
11 | :members:
12 |
13 | .. automodule:: sophus.so2
14 | :members:
15 |
16 | .. automodule:: sophus.so3
17 | :members:
18 |
19 | .. automodule:: sophus.se2
20 | :members:
21 |
22 | .. automodule:: sophus.se3
23 | :members:
--------------------------------------------------------------------------------
/Thirdparty/Sophus/run_format.sh:
--------------------------------------------------------------------------------
1 | find . -type d \( -path ./sympy -o -path ./doxyrest_b -o -path "./*/CMakeFiles/*" \) -prune -o \( -iname "*.hpp" -o -iname "*.cpp" \) -print | xargs clang-format -i
2 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/scripts/install_docs_deps.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -x # echo on
4 | set -e # exit on error
5 |
6 | sudo apt-get -qq update
7 | sudo apt-get install doxygen liblua5.3-dev ragel
8 | pip3 install 'sphinx==2.0.1'
9 | pip3 install sphinx_rtd_theme
10 | pip3 install sympy
11 |
12 | git clone https://github.com/vovkos/doxyrest_b
13 | cd doxyrest_b
14 | git reset --hard ad45c064d1199e71b8cae5aa66d4251c4228b958
15 | git submodule update --init
16 | mkdir build
17 | cd build
18 | cmake ..
19 | cmake --build .
20 |
21 | cd ../..
22 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/scripts/install_linux_deps.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -x # echo on
4 | set -e # exit on error
5 |
6 | cmake --version
7 |
8 | sudo apt-get -qq update
9 | sudo apt-get install gfortran libc++-dev libgoogle-glog-dev libatlas-base-dev libsuitesparse-dev libceres-dev ccache
10 | wget https://gitlab.com/libeigen/eigen/-/archive/3.3.4/eigen-3.3.4.tar.bz2
11 | tar xvf eigen-3.3.4.tar.bz2
12 | mkdir build-eigen
13 | cd build-eigen
14 | cmake ../eigen-3.3.4 -DEIGEN_DEFAULT_TO_ROW_MAJOR=$ROW_MAJOR_DEFAULT
15 | sudo make install
16 | cd ..
17 |
18 | git clone https://ceres-solver.googlesource.com/ceres-solver ceres-solver
19 | cd ceres-solver
20 | git reset --hard b0aef211db734379319c19c030e734d6e23436b0
21 | mkdir build
22 | cd build
23 | ccache -s
24 | cmake -DCMAKE_CXX_COMPILER_LAUNCHER=ccache ..
25 | make -j8
26 | sudo make install
27 | cd ../..
28 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/scripts/install_linux_fmt_deps.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -x # echo on
4 | set -e # exit on error
5 |
6 | git clone https://github.com/fmtlib/fmt.git
7 | cd fmt
8 | git checkout 5.3.0
9 | mkdir build
10 | cd build
11 | cmake -DCMAKE_CXX_COMPILER_LAUNCHER=ccache ..
12 | make -j8
13 | sudo make install
14 | cd ../..
15 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/scripts/install_osx_deps.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -x # echo on
4 | set -e # exit on error
5 |
6 | brew update
7 | brew install fmt
8 | brew install ccache
9 |
10 | # Build a specific version of ceres-solver instead of one shipped over brew
11 | curl https://raw.githubusercontent.com/Homebrew/homebrew-core/b0792ccba6e71cd028263ca7621db894afc602d2/Formula/ceres-solver.rb -o ceres-solver.rb
12 | patch <
4 |
5 | #include
6 |
7 | namespace Sophus {
8 |
9 | /// Templated local parameterization for LieGroup [with implemented
10 | /// LieGroup::Dx_this_mul_exp_x_at_0() ]
11 | template class LieGroup>
12 | class LocalParameterization : public ceres::LocalParameterization {
13 | public:
14 | using LieGroupd = LieGroup;
15 | using Tangent = typename LieGroupd::Tangent;
16 | using TangentMap = typename Sophus::Mapper::ConstMap;
17 | static int constexpr DoF = LieGroupd::DoF;
18 | static int constexpr num_parameters = LieGroupd::num_parameters;
19 |
20 | /// LieGroup plus operation for Ceres
21 | ///
22 | /// T * exp(x)
23 | ///
24 | bool Plus(double const* T_raw, double const* delta_raw,
25 | double* T_plus_delta_raw) const override {
26 | Eigen::Map const T(T_raw);
27 | TangentMap delta = Sophus::Mapper::map(delta_raw);
28 | Eigen::Map T_plus_delta(T_plus_delta_raw);
29 | T_plus_delta = T * LieGroupd::exp(delta);
30 | return true;
31 | }
32 |
33 | /// Jacobian of LieGroup plus operation for Ceres
34 | ///
35 | /// Dx T * exp(x) with x=0
36 | ///
37 | bool ComputeJacobian(double const* T_raw,
38 | double* jacobian_raw) const override {
39 | Eigen::Map T(T_raw);
40 | Eigen::Map>
42 | jacobian(jacobian_raw);
43 | jacobian = T.Dx_this_mul_exp_x_at_0();
44 | return true;
45 | }
46 |
47 | int GlobalSize() const override { return LieGroupd::num_parameters; }
48 |
49 | int LocalSize() const override { return LieGroupd::DoF; }
50 | };
51 |
52 | } // namespace Sophus
53 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sophus/ceres_manifold.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace Sophus {
7 |
8 | /// Templated local parameterization for LieGroup [with implemented
9 | /// LieGroup::Dx_this_mul_exp_x_at_0() ]
10 | template class LieGroup>
11 | class Manifold : public ceres::Manifold {
12 | public:
13 | using LieGroupd = LieGroup;
14 | using Tangent = typename LieGroupd::Tangent;
15 | using TangentMap = typename Sophus::Mapper::Map;
16 | using TangentConstMap = typename Sophus::Mapper::ConstMap;
17 | static int constexpr DoF = LieGroupd::DoF;
18 | static int constexpr num_parameters = LieGroupd::num_parameters;
19 |
20 | /// LieGroup plus operation for Ceres
21 | ///
22 | /// T * exp(x)
23 | ///
24 | bool Plus(double const* T_raw, double const* delta_raw,
25 | double* T_plus_delta_raw) const override {
26 | Eigen::Map const T(T_raw);
27 | TangentConstMap delta = Sophus::Mapper::map(delta_raw);
28 | Eigen::Map T_plus_delta(T_plus_delta_raw);
29 | T_plus_delta = T * LieGroupd::exp(delta);
30 | return true;
31 | }
32 |
33 | /// Jacobian of LieGroup plus operation for Ceres
34 | ///
35 | /// Dx T * exp(x) with x=0
36 | ///
37 | bool PlusJacobian(double const* T_raw, double* jacobian_raw) const override {
38 | Eigen::Map T(T_raw);
39 | Eigen::Map>
41 | jacobian(jacobian_raw);
42 | jacobian = T.Dx_this_mul_exp_x_at_0();
43 | return true;
44 | }
45 |
46 | bool Minus(double const* y_raw, double const* x_raw,
47 | double* y_minus_x_raw) const override {
48 | Eigen::Map y(y_raw), x(x_raw);
49 | TangentMap y_minus_x = Sophus::Mapper::map(y_minus_x_raw);
50 |
51 | y_minus_x = (x.inverse() * y).log();
52 | return true;
53 | }
54 |
55 | bool MinusJacobian(double const* x_raw, double* jacobian_raw) const override {
56 | Eigen::Map x(x_raw);
57 | Eigen::Map>
58 | jacobian(jacobian_raw);
59 | jacobian = x.Dx_log_this_inv_by_x_at_this();
60 | return true;
61 | }
62 |
63 | int AmbientSize() const override { return LieGroupd::num_parameters; }
64 |
65 | int TangentSize() const override { return LieGroupd::DoF; }
66 | };
67 |
68 | } // namespace Sophus
69 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sophus/ceres_typetraits.hpp:
--------------------------------------------------------------------------------
1 | #ifndef SOPHUS_CERES_TYPETRAITS_HPP
2 | #define SOPHUS_CERES_TYPETRAITS_HPP
3 |
4 | namespace Sophus {
5 |
6 | template
7 | constexpr std::true_type complete(T*);
8 | constexpr std::false_type complete(...);
9 |
10 | template
11 | using IsSpecialized = decltype(complete(std::declval()));
12 |
13 | /// Type trait used to distinguish mappable vector types from scalars
14 | ///
15 | /// We use this class to distinguish Sophus::Vector from Scalar types
16 | /// in LieGroup::Tangent
17 | ///
18 | /// Primary use is mapping LieGroup::Tangent over raw data, with 2 options:
19 | /// - LieGroup::Tangent is "scalar" (for SO2), then we just dereference pointer
20 | /// - LieGroup::Tangent is Sophus::Vector<...>, then we need to use Eigen::Map
21 | ///
22 | /// Specialization of Eigen::internal::traits for T is crucial for
23 | /// for constructing Eigen::Map, thus we use that property for distinguishing
24 | /// between those two options.
25 | /// At this moment there seem to be no option to check this using only
26 | /// "external" API of Eigen
27 | template
28 | using IsMappable = IsSpecialized>>;
29 |
30 | template
31 | constexpr bool IsMappableV = IsMappable::value;
32 |
33 | /// Helper for mapping tangent vectors (scalars) over pointers to data
34 | template
35 | struct Mapper {
36 | using Scalar = T;
37 | using Map = Scalar&;
38 | using ConstMap = const Scalar&;
39 |
40 | static Map map(Scalar* ptr) noexcept { return *ptr; }
41 | static ConstMap map(const Scalar* ptr) noexcept { return *ptr; }
42 | };
43 |
44 | template
45 | struct Mapper>::type> {
46 | using Scalar = typename T::Scalar;
47 | using Map = Eigen::Map;
48 | using ConstMap = Eigen::Map;
49 |
50 | static Map map(Scalar* ptr) noexcept { return Map(ptr); }
51 | static ConstMap map(const Scalar* ptr) noexcept { return ConstMap(ptr); }
52 | };
53 |
54 | } // namespace Sophus
55 |
56 | #endif
57 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sophus/example_ensure_handler.cpp:
--------------------------------------------------------------------------------
1 | #include "common.hpp"
2 |
3 | #include
4 | #include
5 |
6 | namespace Sophus {
7 | void ensureFailed(char const* function, char const* file, int line,
8 | char const* description) {
9 | std::printf("Sophus ensure failed in function '%s', file '%s', line %d.\n",
10 | file, function, line);
11 | std::printf("Description: %s\n", description);
12 | std::abort();
13 | }
14 | } // namespace Sophus
15 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sophus/geometry.hpp:
--------------------------------------------------------------------------------
1 | /// @file
2 | /// Transformations between poses and hyperplanes.
3 |
4 | #pragma once
5 |
6 | #include "se2.hpp"
7 | #include "se3.hpp"
8 | #include "so2.hpp"
9 | #include "so3.hpp"
10 | #include "types.hpp"
11 |
12 | namespace Sophus {
13 |
14 | /// Takes in a rotation ``R_foo_plane`` and returns the corresponding line
15 | /// normal along the y-axis (in reference frame ``foo``).
16 | ///
17 | template
18 | Vector2 normalFromSO2(SO2 const& R_foo_line) {
19 | return R_foo_line.matrix().col(1);
20 | }
21 |
22 | /// Takes in line normal in reference frame foo and constructs a corresponding
23 | /// rotation matrix ``R_foo_line``.
24 | ///
25 | /// Precondition: ``normal_foo`` must not be close to zero.
26 | ///
27 | template
28 | SO2 SO2FromNormal(Vector2 normal_foo) {
29 | SOPHUS_ENSURE(normal_foo.squaredNorm() > Constants::epsilon(), "{}",
30 | SOPHUS_FMT_ARG(normal_foo.transpose()));
31 | normal_foo.normalize();
32 | return SO2(normal_foo.y(), -normal_foo.x());
33 | }
34 |
35 | /// Takes in a rotation ``R_foo_plane`` and returns the corresponding plane
36 | /// normal along the z-axis
37 | /// (in reference frame ``foo``).
38 | ///
39 | template
40 | Vector3 normalFromSO3(SO3 const& R_foo_plane) {
41 | return R_foo_plane.matrix().col(2);
42 | }
43 |
44 | /// Takes in plane normal in reference frame foo and constructs a corresponding
45 | /// rotation matrix ``R_foo_plane``.
46 | ///
47 | /// Note: The ``plane`` frame is defined as such that the normal points along
48 | /// the positive z-axis. One can specify hints for the x-axis and y-axis
49 | /// of the ``plane`` frame.
50 | ///
51 | /// Preconditions:
52 | /// - ``normal_foo``, ``xDirHint_foo``, ``yDirHint_foo`` must not be close to
53 | /// zero.
54 | /// - ``xDirHint_foo`` and ``yDirHint_foo`` must be approx. perpendicular.
55 | ///
56 | template
57 | Matrix3 rotationFromNormal(Vector3 const& normal_foo,
58 | Vector3 xDirHint_foo = Vector3(T(1), T(0),
59 | T(0)),
60 | Vector3 yDirHint_foo = Vector3(T(0), T(1),
61 | T(0))) {
62 | SOPHUS_ENSURE(xDirHint_foo.dot(yDirHint_foo) < Constants::epsilon(),
63 | "xDirHint ({}) and yDirHint ({}) must be perpendicular.",
64 | SOPHUS_FMT_ARG(xDirHint_foo.transpose()),
65 | SOPHUS_FMT_ARG(yDirHint_foo.transpose()));
66 | using std::abs;
67 | using std::sqrt;
68 | T const xDirHint_foo_sqr_length = xDirHint_foo.squaredNorm();
69 | T const yDirHint_foo_sqr_length = yDirHint_foo.squaredNorm();
70 | T const normal_foo_sqr_length = normal_foo.squaredNorm();
71 | SOPHUS_ENSURE(xDirHint_foo_sqr_length > Constants::epsilon(), "{}",
72 | SOPHUS_FMT_ARG(xDirHint_foo.transpose()));
73 | SOPHUS_ENSURE(yDirHint_foo_sqr_length > Constants::epsilon(), "{}",
74 | SOPHUS_FMT_ARG(yDirHint_foo.transpose()));
75 | SOPHUS_ENSURE(normal_foo_sqr_length > Constants::epsilon(), "{}",
76 | SOPHUS_FMT_ARG(normal_foo.transpose()));
77 |
78 | Matrix3 basis_foo;
79 | basis_foo.col(2) = normal_foo;
80 |
81 | if (abs(xDirHint_foo_sqr_length - T(1)) > Constants::epsilon()) {
82 | xDirHint_foo.normalize();
83 | }
84 | if (abs(yDirHint_foo_sqr_length - T(1)) > Constants::epsilon()) {
85 | yDirHint_foo.normalize();
86 | }
87 | if (abs(normal_foo_sqr_length - T(1)) > Constants::epsilon()) {
88 | basis_foo.col(2).normalize();
89 | }
90 |
91 | T abs_x_dot_z = abs(basis_foo.col(2).dot(xDirHint_foo));
92 | T abs_y_dot_z = abs(basis_foo.col(2).dot(yDirHint_foo));
93 | if (abs_x_dot_z < abs_y_dot_z) {
94 | // basis_foo.z and xDirHint are far from parallel.
95 | basis_foo.col(1) = basis_foo.col(2).cross(xDirHint_foo).normalized();
96 | basis_foo.col(0) = basis_foo.col(1).cross(basis_foo.col(2));
97 | } else {
98 | // basis_foo.z and yDirHint are far from parallel.
99 | basis_foo.col(0) = yDirHint_foo.cross(basis_foo.col(2)).normalized();
100 | basis_foo.col(1) = basis_foo.col(2).cross(basis_foo.col(0));
101 | }
102 | T det = basis_foo.determinant();
103 | // sanity check
104 | SOPHUS_ENSURE(abs(det - T(1)) < Constants::epsilon(),
105 | "Determinant of basis is not 1, but {}. Basis is \n{}\n",
106 | SOPHUS_FMT_ARG(det), SOPHUS_FMT_ARG(basis_foo));
107 | return basis_foo;
108 | }
109 |
110 | /// Takes in plane normal in reference frame foo and constructs a corresponding
111 | /// rotation matrix ``R_foo_plane``.
112 | ///
113 | /// See ``rotationFromNormal`` for details.
114 | ///
115 | template
116 | SO3 SO3FromNormal(Vector3 const& normal_foo) {
117 | return SO3(rotationFromNormal(normal_foo));
118 | }
119 |
120 | /// Returns a line (wrt. to frame ``foo``), given a pose of the ``line`` in
121 | /// reference frame ``foo``.
122 | ///
123 | /// Note: The plane is defined by X-axis of the ``line`` frame.
124 | ///
125 | template
126 | Line2 lineFromSE2(SE2 const& T_foo_line) {
127 | return Line2(normalFromSO2(T_foo_line.so2()), T_foo_line.translation());
128 | }
129 |
130 | /// Returns the pose ``T_foo_line``, given a line in reference frame ``foo``.
131 | ///
132 | /// Note: The line is defined by X-axis of the frame ``line``.
133 | ///
134 | template
135 | SE2 SE2FromLine(Line2 const& line_foo) {
136 | T const d = line_foo.offset();
137 | Vector2 const n = line_foo.normal();
138 | SO2 const R_foo_plane = SO2FromNormal(n);
139 | return SE2(R_foo_plane, -d * n);
140 | }
141 |
142 | /// Returns a plane (wrt. to frame ``foo``), given a pose of the ``plane`` in
143 | /// reference frame ``foo``.
144 | ///
145 | /// Note: The plane is defined by XY-plane of the frame ``plane``.
146 | ///
147 | template
148 | Plane3 planeFromSE3(SE3 const& T_foo_plane) {
149 | return Plane3(normalFromSO3(T_foo_plane.so3()), T_foo_plane.translation());
150 | }
151 |
152 | /// Returns the pose ``T_foo_plane``, given a plane in reference frame ``foo``.
153 | ///
154 | /// Note: The plane is defined by XY-plane of the frame ``plane``.
155 | ///
156 | template
157 | SE3 SE3FromPlane(Plane3 const& plane_foo) {
158 | T const d = plane_foo.offset();
159 | Vector3 const n = plane_foo.normal();
160 | SO3 const R_foo_plane = SO3FromNormal(n);
161 | return SE3(R_foo_plane, -d * n);
162 | }
163 |
164 | /// Takes in a hyperplane and returns unique representation by ensuring that the
165 | /// ``offset`` is not negative.
166 | ///
167 | template
168 | Eigen::Hyperplane makeHyperplaneUnique(
169 | Eigen::Hyperplane const& plane) {
170 | if (plane.offset() >= 0) {
171 | return plane;
172 | }
173 |
174 | return Eigen::Hyperplane(-plane.normal(), -plane.offset());
175 | }
176 |
177 | } // namespace Sophus
178 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sophus/interpolate.hpp:
--------------------------------------------------------------------------------
1 | /// @file
2 | /// Interpolation for Lie groups.
3 |
4 | #pragma once
5 |
6 | #include
7 |
8 | #include "interpolate_details.hpp"
9 |
10 | namespace Sophus {
11 |
12 | /// This function interpolates between two Lie group elements ``foo_T_bar``
13 | /// and ``foo_T_baz`` with an interpolation factor of ``alpha`` in [0, 1].
14 | ///
15 | /// It returns a pose ``foo_T_quiz`` with ``quiz`` being a frame between ``bar``
16 | /// and ``baz``. If ``alpha=0`` it returns ``foo_T_bar``. If it is 1, it returns
17 | /// ``foo_T_baz``.
18 | ///
19 | /// (Since interpolation on Lie groups is inverse-invariant, we can equivalently
20 | /// think of the input arguments as being ``bar_T_foo``, ``baz_T_foo`` and the
21 | /// return value being ``quiz_T_foo``.)
22 | ///
23 | /// Precondition: ``p`` must be in [0, 1].
24 | ///
25 | template
26 | enable_if_t::supported, G> interpolate(
27 | G const& foo_T_bar, G const& foo_T_baz, Scalar2 p = Scalar2(0.5f)) {
28 | using Scalar = typename G::Scalar;
29 | Scalar inter_p(p);
30 | SOPHUS_ENSURE(inter_p >= Scalar(0) && inter_p <= Scalar(1),
31 | "p ({}) must in [0, 1].", SOPHUS_FMT_ARG(inter_p));
32 | return foo_T_bar * G::exp(inter_p * (foo_T_bar.inverse() * foo_T_baz).log());
33 | }
34 |
35 | } // namespace Sophus
36 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sophus/interpolate_details.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "cartesian.hpp"
4 | #include "rxso2.hpp"
5 | #include "rxso3.hpp"
6 | #include "se2.hpp"
7 | #include "se3.hpp"
8 | #include "sim2.hpp"
9 | #include "sim3.hpp"
10 | #include "so2.hpp"
11 | #include "so3.hpp"
12 |
13 | namespace Sophus {
14 | namespace interp_details {
15 |
16 | template
17 | struct Traits;
18 |
19 | template
20 | struct Traits> {
21 | static bool constexpr supported = true;
22 |
23 | static bool hasShortestPathAmbiguity(Cartesian const&) {
24 | return false;
25 | }
26 | };
27 |
28 | template
29 | struct Traits> {
30 | static bool constexpr supported = true;
31 |
32 | static bool hasShortestPathAmbiguity(SO2 const& foo_T_bar) {
33 | using std::abs;
34 | Scalar angle = abs(foo_T_bar.log());
35 | Scalar const kPi = Constants::pi();
36 | return abs(angle - kPi) / (angle + kPi) < Constants::epsilon();
37 | }
38 | };
39 |
40 | template
41 | struct Traits> {
42 | static bool constexpr supported = true;
43 |
44 | static bool hasShortestPathAmbiguity(RxSO2 const& foo_T_bar) {
45 | return Traits>::hasShortestPathAmbiguity(foo_T_bar.so2());
46 | }
47 | };
48 |
49 | template
50 | struct Traits> {
51 | static bool constexpr supported = true;
52 |
53 | static bool hasShortestPathAmbiguity(SO3 const& foo_T_bar) {
54 | using std::abs;
55 | Scalar angle = abs(foo_T_bar.logAndTheta().theta);
56 | Scalar const kPi = Constants::pi();
57 | return abs(angle - kPi) / (angle + kPi) < Constants::epsilon();
58 | }
59 | };
60 |
61 | template
62 | struct Traits> {
63 | static bool constexpr supported = true;
64 |
65 | static bool hasShortestPathAmbiguity(RxSO3 const& foo_T_bar) {
66 | return Traits>::hasShortestPathAmbiguity(foo_T_bar.so3());
67 | }
68 | };
69 |
70 | template
71 | struct Traits> {
72 | static bool constexpr supported = true;
73 |
74 | static bool hasShortestPathAmbiguity(SE2 const& foo_T_bar) {
75 | return Traits>::hasShortestPathAmbiguity(foo_T_bar.so2());
76 | }
77 | };
78 |
79 | template
80 | struct Traits> {
81 | static bool constexpr supported = true;
82 |
83 | static bool hasShortestPathAmbiguity(SE3 const& foo_T_bar) {
84 | return Traits>::hasShortestPathAmbiguity(foo_T_bar.so3());
85 | }
86 | };
87 |
88 | template
89 | struct Traits> {
90 | static bool constexpr supported = true;
91 |
92 | static bool hasShortestPathAmbiguity(Sim2 const& foo_T_bar) {
93 | return Traits>::hasShortestPathAmbiguity(
94 | foo_T_bar.rxso2().so2());
95 | ;
96 | }
97 | };
98 |
99 | template
100 | struct Traits> {
101 | static bool constexpr supported = true;
102 |
103 | static bool hasShortestPathAmbiguity(Sim3 const& foo_T_bar) {
104 | return Traits>::hasShortestPathAmbiguity(
105 | foo_T_bar.rxso3().so3());
106 | ;
107 | }
108 | };
109 |
110 | } // namespace interp_details
111 | } // namespace Sophus
112 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sophus/num_diff.hpp:
--------------------------------------------------------------------------------
1 | /// @file
2 | /// Numerical differentiation using finite differences
3 |
4 | #pragma once
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #include "types.hpp"
11 |
12 | namespace Sophus {
13 |
14 | namespace details {
15 | template
16 | class Curve {
17 | public:
18 | template
19 | static auto num_diff(Fn curve, Scalar t, Scalar h) -> decltype(curve(t)) {
20 | using ReturnType = decltype(curve(t));
21 | static_assert(std::is_floating_point::value,
22 | "Scalar must be a floating point type.");
23 | static_assert(IsFloatingPoint::value,
24 | "ReturnType must be either a floating point scalar, "
25 | "vector or matrix.");
26 |
27 | return (curve(t + h) - curve(t - h)) / (Scalar(2) * h);
28 | }
29 | };
30 |
31 | template
32 | class VectorField {
33 | public:
34 | static Eigen::Matrix num_diff(
35 | std::function(Sophus::Vector)>
36 | vector_field,
37 | Sophus::Vector const& a, Scalar eps) {
38 | static_assert(std::is_floating_point::value,
39 | "Scalar must be a floating point type.");
40 | Eigen::Matrix J;
41 | Sophus::Vector h;
42 | h.setZero();
43 | for (int i = 0; i < M; ++i) {
44 | h[i] = eps;
45 | J.col(i) =
46 | (vector_field(a + h) - vector_field(a - h)) / (Scalar(2) * eps);
47 | h[i] = Scalar(0);
48 | }
49 |
50 | return J;
51 | }
52 | };
53 |
54 | template
55 | class VectorField {
56 | public:
57 | static Eigen::Matrix num_diff(
58 | std::function(Scalar)> vector_field,
59 | Scalar const& a, Scalar eps) {
60 | return details::Curve::num_diff(std::move(vector_field), a, eps);
61 | }
62 | };
63 | } // namespace details
64 |
65 | /// Calculates the derivative of a curve at a point ``t``.
66 | ///
67 | /// Here, a curve is a function from a Scalar to a Euclidean space. Thus, it
68 | /// returns either a Scalar, a vector or a matrix.
69 | ///
70 | template
71 | auto curveNumDiff(Fn curve, Scalar t,
72 | Scalar h = Constants::epsilonSqrt())
73 | -> decltype(details::Curve::num_diff(std::move(curve), t, h)) {
74 | return details::Curve::num_diff(std::move(curve), t, h);
75 | }
76 |
77 | /// Calculates the derivative of a vector field at a point ``a``.
78 | ///
79 | /// Here, a vector field is a function from a vector space to another vector
80 | /// space.
81 | ///
82 | template
83 | Eigen::Matrix vectorFieldNumDiff(
84 | Fn vector_field, ScalarOrVector const& a,
85 | Scalar eps = Constants::epsilonSqrt()) {
86 | return details::VectorField::num_diff(std::move(vector_field),
87 | a, eps);
88 | }
89 |
90 | } // namespace Sophus
91 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sophus/rotation_matrix.hpp:
--------------------------------------------------------------------------------
1 | /// @file
2 | /// Rotation matrix helper functions.
3 |
4 | #pragma once
5 |
6 | #include
7 | #include
8 |
9 | #include "types.hpp"
10 |
11 | namespace Sophus {
12 |
13 | /// Takes in arbitrary square matrix and returns true if it is
14 | /// orthogonal.
15 | template
16 | SOPHUS_FUNC bool isOrthogonal(Eigen::MatrixBase const& R) {
17 | using Scalar = typename D::Scalar;
18 | static int const N = D::RowsAtCompileTime;
19 | static int const M = D::ColsAtCompileTime;
20 |
21 | static_assert(N == M, "must be a square matrix");
22 | static_assert(N >= 2, "must have compile time dimension >= 2");
23 |
24 | return (R * R.transpose() - Matrix::Identity()).norm() <
25 | Constants::epsilon();
26 | }
27 |
28 | /// Takes in arbitrary square matrix and returns true if it is
29 | /// "scaled-orthogonal" with positive determinant.
30 | ///
31 | template
32 | SOPHUS_FUNC bool isScaledOrthogonalAndPositive(Eigen::MatrixBase const& sR) {
33 | using Scalar = typename D::Scalar;
34 | static int const N = D::RowsAtCompileTime;
35 | static int const M = D::ColsAtCompileTime;
36 | using std::pow;
37 | using std::sqrt;
38 |
39 | Scalar det = sR.determinant();
40 |
41 | if (det <= Scalar(0)) {
42 | return false;
43 | }
44 |
45 | Scalar scale_sqr = pow(det, Scalar(2. / N));
46 |
47 | static_assert(N == M, "must be a square matrix");
48 | static_assert(N >= 2, "must have compile time dimension >= 2");
49 |
50 | return (sR * sR.transpose() - scale_sqr * Matrix::Identity())
51 | .template lpNorm() <
52 | sqrt(Constants::epsilon());
53 | }
54 |
55 | /// Takes in arbitrary square matrix (2x2 or larger) and returns closest
56 | /// orthogonal matrix with positive determinant.
57 | template
58 | SOPHUS_FUNC enable_if_t<
59 | std::is_floating_point::value,
60 | Matrix>
61 | makeRotationMatrix(Eigen::MatrixBase const& R) {
62 | using Scalar = typename D::Scalar;
63 | static int const N = D::RowsAtCompileTime;
64 | static int const M = D::ColsAtCompileTime;
65 |
66 | static_assert(N == M, "must be a square matrix");
67 | static_assert(N >= 2, "must have compile time dimension >= 2");
68 |
69 | Eigen::JacobiSVD> svd(
70 | R, Eigen::ComputeFullU | Eigen::ComputeFullV);
71 |
72 | // Determine determinant of orthogonal matrix U*V'.
73 | Scalar d = (svd.matrixU() * svd.matrixV().transpose()).determinant();
74 | // Starting from the identity matrix D, set the last entry to d (+1 or
75 | // -1), so that det(U*D*V') = 1.
76 | Matrix Diag = Matrix::Identity();
77 | Diag(N - 1, N - 1) = d;
78 | return svd.matrixU() * Diag * svd.matrixV().transpose();
79 | }
80 |
81 | } // namespace Sophus
82 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sophus/velocities.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "num_diff.hpp"
6 | #include "se3.hpp"
7 |
8 | namespace Sophus {
9 | namespace experimental {
10 | // Experimental since the API will certainly change drastically in the future.
11 |
12 | // Transforms velocity vector by rotation ``foo_R_bar``.
13 | //
14 | // Note: vel_bar can be either a linear or a rotational velocity vector.
15 | //
16 | template
17 | Vector3 transformVelocity(SO3 const& foo_R_bar,
18 | Vector3 const& vel_bar) {
19 | // For rotational velocities note that:
20 | //
21 | // vel_bar = vee(foo_R_bar * hat(vel_bar) * foo_R_bar^T)
22 | // = vee(hat(Adj(foo_R_bar) * vel_bar))
23 | // = Adj(foo_R_bar) * vel_bar
24 | // = foo_R_bar * vel_bar.
25 | //
26 | return foo_R_bar * vel_bar;
27 | }
28 |
29 | // Transforms velocity vector by pose ``foo_T_bar``.
30 | //
31 | // Note: vel_bar can be either a linear or a rotational velocity vector.
32 | //
33 | template
34 | Vector3 transformVelocity(SE3 const& foo_T_bar,
35 | Vector3 const& vel_bar) {
36 | return transformVelocity(foo_T_bar.so3(), vel_bar);
37 | }
38 |
39 | // finite difference approximation of instantaneous velocity in frame foo
40 | //
41 | template
42 | Vector3 finiteDifferenceRotationalVelocity(
43 | std::function(Scalar)> const& foo_R_bar, Scalar t,
44 | Scalar h = Constants::epsilon()) {
45 | // https://en.wikipedia.org/w/index.php?title=Angular_velocity&oldid=791867792#Angular_velocity_tensor
46 | //
47 | // W = dR(t)/dt * R^{-1}(t)
48 | Matrix3 dR_dt_in_frame_foo = curveNumDiff(
49 | [&foo_R_bar](Scalar t0) -> Matrix3 {
50 | return foo_R_bar(t0).matrix();
51 | },
52 | t, h);
53 | // velocity tensor
54 | Matrix3 W_in_frame_foo =
55 | dR_dt_in_frame_foo * (foo_R_bar(t)).inverse().matrix();
56 | return SO3::vee(W_in_frame_foo);
57 | }
58 |
59 | // finite difference approximation of instantaneous velocity in frame foo
60 | //
61 | template
62 | Vector3 finiteDifferenceRotationalVelocity(
63 | std::function(Scalar)> const& foo_T_bar, Scalar t,
64 | Scalar h = Constants::epsilon()) {
65 | return finiteDifferenceRotationalVelocity(
66 | [&foo_T_bar](Scalar t) -> SO3 { return foo_T_bar(t).so3(); }, t,
67 | h);
68 | }
69 |
70 | } // namespace experimental
71 | } // namespace Sophus
72 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sophus_pybind-stubs/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YWL0720/I2EKF-LO/8d2158cda30ed9b261e668b9ab6f75f5ab424624/Thirdparty/Sophus/sophus_pybind-stubs/py.typed
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sophus_pybind-stubs/sophus_pybind.pyi:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 | import numpy
3 | import typing
4 | __all__ = ['SE3', 'SO3', 'interpolate', 'iterativeMean']
5 | class SE3:
6 | @staticmethod
7 | @typing.overload
8 | def exp(arg0: numpy.ndarray[numpy.float64[3, 1]], arg1: numpy.ndarray[numpy.float64[3, 1]]) -> SE3:
9 | """
10 | Create SE3 from a translational_part (3x1) and a rotation vector (3x1) of magnitude in rad. NOTE: translational_part is not translation vector in SE3
11 | """
12 | @staticmethod
13 | @typing.overload
14 | def exp(arg0: numpy.ndarray[numpy.float64[m, 3]], arg1: numpy.ndarray[numpy.float64[m, 3]]) -> SE3:
15 | """
16 | Create a set of SE3 from translational_parts (Nx3) and rotation vectors (Nx3) of magnitude in rad. NOTE: translational_part is not translation vector in SE3
17 | """
18 | @staticmethod
19 | @typing.overload
20 | def from_matrix(arg0: numpy.ndarray[numpy.float64[4, 4]]) -> SE3:
21 | ...
22 | @staticmethod
23 | @typing.overload
24 | def from_matrix(arg0: numpy.ndarray[numpy.float64]) -> SE3:
25 | ...
26 | @staticmethod
27 | @typing.overload
28 | def from_matrix3x4(arg0: numpy.ndarray[numpy.float64[3, 4]]) -> SE3:
29 | ...
30 | @staticmethod
31 | @typing.overload
32 | def from_matrix3x4(arg0: numpy.ndarray[numpy.float64]) -> SE3:
33 | ...
34 | def __copy__(self) -> SE3:
35 | ...
36 | def __getitem__(self, arg0: typing.Any) -> SE3:
37 | ...
38 | def __imatmul__(self, arg0: SE3) -> SE3:
39 | ...
40 | @typing.overload
41 | def __init__(self) -> None:
42 | """
43 | Default Constructor initializing a group containing 1 identity element
44 | """
45 | @typing.overload
46 | def __init__(self, arg0: SE3) -> None:
47 | """
48 | Copy constructor from single element
49 | """
50 | def __len__(self) -> int:
51 | ...
52 | @typing.overload
53 | def __matmul__(self, arg0: SE3) -> SE3:
54 | ...
55 | @typing.overload
56 | def __matmul__(self, arg0: numpy.ndarray[numpy.float64[3, n]]) -> numpy.ndarray[numpy.float64[3, n]]:
57 | ...
58 | def __repr__(self) -> str:
59 | ...
60 | def __setitem__(self, arg0: typing.Any, arg1: SE3) -> None:
61 | ...
62 | def __str__(self) -> str:
63 | ...
64 | @typing.overload
65 | def from_quat_and_translation(self, arg0: numpy.ndarray[numpy.float64[3, 1]], arg1: numpy.ndarray[numpy.float64[3, 1]]) -> SE3:
66 | """
67 | Create SE3 from a quaternion as w, [x, y, z], and translation vector
68 | """
69 | @typing.overload
70 | def from_quat_and_translation(self, arg0: numpy.ndarray[numpy.float64[m, 3]], arg1: numpy.ndarray[numpy.float64[m, 3]]) -> SE3:
71 | """
72 | Create SE3 from a list of quaternion as w_vec: Nx1, xyz_vec: Nx3, and a list of translation vectors: Nx3
73 | """
74 | def inverse(self) -> SE3:
75 | """
76 | Compute the inverse of the transformations.
77 | """
78 | def log(self) -> numpy.ndarray[numpy.float64[m, 6]]:
79 | """
80 | Return the log of SE3 as [translational_part, rotation_vector] of dimension Nx6.
81 | """
82 | def rotation(self) -> SO3:
83 | """
84 | Get the rotation component of the transformation.
85 | """
86 | def to_matrix(self) -> numpy.ndarray[numpy.float64]:
87 | """
88 | Convert an array of SE3 into an array of transformation matrices of size 4x4
89 | """
90 | def to_matrix3x4(self) -> numpy.ndarray[numpy.float64]:
91 | """
92 | Convert an array of SE3 into an array of transformation matrices of size 3x4
93 | """
94 | def to_quat_and_translation(self) -> numpy.ndarray[numpy.float64[m, 7]]:
95 | """
96 | Return quaternion and translation as Nx7 vectors of [quat (w, x, y, z), translation]
97 | """
98 | def translation(self) -> numpy.ndarray[numpy.float64[m, 3]]:
99 | """
100 | Get the translation component of the transformation.
101 | """
102 | class SO3:
103 | @staticmethod
104 | def exp(arg0: numpy.ndarray[numpy.float64[m, 3]]) -> SO3:
105 | """
106 | Create rotations from rotations vectors of size Nx3 in rad
107 | """
108 | @staticmethod
109 | @typing.overload
110 | def from_matrix(arg0: numpy.ndarray[numpy.float64[3, 3]]) -> SO3:
111 | ...
112 | @staticmethod
113 | @typing.overload
114 | def from_matrix(arg0: numpy.ndarray[numpy.float64]) -> SO3:
115 | ...
116 | @staticmethod
117 | @typing.overload
118 | def from_quat(arg0: float, arg1: numpy.ndarray[numpy.float64[3, 1]]) -> SO3:
119 | """
120 | Create a rotation from a quaternion as w, [x, y, z]
121 | """
122 | @staticmethod
123 | @typing.overload
124 | def from_quat(arg0: list[float], arg1: numpy.ndarray[numpy.float64[m, 3]]) -> SO3:
125 | """
126 | Create rotations from a list of quaternions as w_vec: Nx1, xyz_vec: Nx3
127 | """
128 | def __copy__(self) -> SO3:
129 | ...
130 | def __getitem__(self, arg0: typing.Any) -> SO3:
131 | ...
132 | def __imatmul__(self, arg0: SO3) -> SO3:
133 | ...
134 | @typing.overload
135 | def __init__(self) -> None:
136 | """
137 | Default Constructor initializing a group containing 1 identity element
138 | """
139 | @typing.overload
140 | def __init__(self, arg0: SO3) -> None:
141 | """
142 | Copy constructor from single element
143 | """
144 | def __len__(self) -> int:
145 | ...
146 | @typing.overload
147 | def __matmul__(self, arg0: SO3) -> SO3:
148 | ...
149 | @typing.overload
150 | def __matmul__(self, arg0: numpy.ndarray[numpy.float64[3, n]]) -> numpy.ndarray[numpy.float64[3, n]]:
151 | ...
152 | def __repr__(self) -> str:
153 | ...
154 | def __setitem__(self, arg0: typing.Any, arg1: SO3) -> None:
155 | ...
156 | def __str__(self) -> str:
157 | ...
158 | def inverse(self) -> SO3:
159 | """
160 | Compute the inverse of the rotations.
161 | """
162 | def log(self) -> numpy.ndarray[numpy.float64[m, 3]]:
163 | """
164 | Return the rotations vector representation by taking the log operator.
165 | """
166 | def to_matrix(self) -> numpy.ndarray[numpy.float64]:
167 | """
168 | Convert an array of SO3 into an array of rotation matrices
169 | """
170 | def to_quat(self) -> numpy.ndarray[numpy.float64[m, 4]]:
171 | """
172 | Return quaternion as Nx4 vectors with the order [w x y z].
173 | """
174 | def interpolate(arg0: SE3, arg1: SE3, arg2: float) -> SE3:
175 | """
176 | Interpolate two SE3s of size 1.
177 | """
178 | def iterativeMean(arg0: SE3) -> SE3:
179 | """
180 | Compute the iterative mean of a sequence.
181 | """
182 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sophus_pybind/README:
--------------------------------------------------------------------------------
1 | # Python binding for Sophus library: sophus-pybind
2 | sophus-pybind implement python binding for sophus that provides access to SO3, SE3, interpolate and iterativeMean features.
3 | The user interface is inspired by scipy.spacial.transform.Rotation.
4 | Here is a specific list of features.
5 |
6 | ## Feature list
7 | * SO3
8 | * Initialize with from_quat(), from_matrix(), exp()
9 | * Convert to functions: to_quat(), to_matrix(), log()
10 | * Multiplication with SO3 or 3D points
11 | * Operator [] for setting/getting items with index or slices
12 | * Inverse, copy, print, and len
13 | * Function vectorization
14 | * SE3
15 | * Initialize with from_quat_and_translation(), from_matrix(), from_matrix3x4(), exp()
16 | * Convert to functions to_quat_and_translation(), to_matrix(), to_matrix3x4(), log()
17 | * Multiplication with SE3 or 3D points
18 | * Operator [] for setting/getting items with index or slices
19 | * Function vectorization
20 | * Inverse, copy, print, and len
21 | * Interpolate between two SE3
22 | * Iterative mean of a group of SE3
23 |
24 | ## Python module (pysophus) installation step
25 | ```
26 | # Create virtual environment
27 | python3 -m venv ~/sophus_venv
28 | source ~/sophus_venv/bin/activate
29 |
30 | # Install package
31 | git clone
32 | cd Sophus
33 | pip install .
34 | ```
35 |
36 | ## Example code
37 | Example code is provided in `sophus_pybind/examples/sophus_quickstart_tutorial.ipynb`
38 | ```
39 | cd Sophus
40 | python3 -m jupyter notebook sophus_pybind/examples/sophus_quickstart_tutorial.ipynb
41 | ```
42 | `python3 -m jupyter` ensures that the jupyter comes from the virtual environment that contains the sophus-pybind module.
43 |
44 |
45 | ## Re-generate stub files (.pyi) for annotation
46 | ```
47 | cd Sophus
48 | # install pybind11-stubgen that will create stub file for a python module
49 | pip3 install pybind11-stubgen
50 |
51 | # Create stub files (Requires sophus-pybind to be installed in prior)
52 | python3 generate_stubs.py
53 |
54 | # Re-install the sophus-pybind project with the stub file
55 | pip install .
56 | ```
57 |
58 | ## Vectorization detail
59 | In python, we choose to export our Sophus::SO3 as a vector of SO3 objects by binding the cpp object `SO3Group` defined below. This is because numerical code in python tends to work with array of values to get efficient program. This approach is inspired by scipy.spatial.transform.Rotation.
60 | ```
61 | class SO3Group : public std::vector>
62 | class SE3Group : public std::vector>
63 | ```
64 |
65 | ### Passing a single SO3/SE3 object to c++ code in python binding
66 | To allow other python binding c++ code to take in a single SO3/SE3 object, we also build a caster so that, even if we wrap SO3Group/SE3Group in python, those can be implicitly converted to the c++ Sophus::SO3/SE3 object at boundaries between languages.
67 | This is so we can pass python SO3/SE3 object to c++ function as if they were regular 1-element Sophus::SO3/SE3 object. This simplifies binding the rest of c++ code. The implicit cast fails if the python object is not a 1-element object.
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sophus_pybind/SophusPyBind.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "SE3PyBind.h"
4 | #include "SO3PyBind.h"
5 |
6 | #include
7 | // By default, Sophus calls std::abort when a pre-condition fails. Register a handler that raises
8 | // an exception so we don't crash the Python process.
9 | #ifdef SOPHUS_DISABLE_ENSURES
10 | #undef SOPHUS_DISABLE_ENSURES
11 | #endif
12 | #ifndef SOPHUS_ENABLE_ENSURE_HANDLER
13 | #define SOPHUS_ENABLE_ENSURE_HANDLER
14 | #endif
15 |
16 | namespace Sophus {
17 | inline void
18 | ensureFailed(char const* function, char const* file, int line, char const* description) {
19 | std::stringstream message;
20 | message << "'SOPHUS_ENSURE' failed in function '" << function << "', on line '" << line
21 | << "' of file '" << file << "'. Full description:" << std::endl
22 | << description;
23 | throw std::domain_error(message.str());
24 | }
25 |
26 | inline void exportSophus(pybind11::module& module) {
27 | exportSO3Group(module, "SO3");
28 | exportSE3Transformation(module, "SE3");
29 |
30 | exportSE3Average(module);
31 | exportSE3Interpolate(module);
32 | }
33 |
34 | } // namespace Sophus
35 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sophus_pybind/bindings.cpp:
--------------------------------------------------------------------------------
1 | #include "SophusPyBind.h"
2 |
3 | PYBIND11_MODULE(sophus_pybind, m) { Sophus::exportSophus(m); }
4 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/cpp_gencode/Se2_Dx_exp_x.cpp:
--------------------------------------------------------------------------------
1 | Scalar const c0 = sin(theta);
2 | Scalar const c1 = cos(theta);
3 | Scalar const c2 = 1.0/theta;
4 | Scalar const c3 = c0*c2;
5 | Scalar const c4 = 1 - c1;
6 | Scalar const c5 = c2*c4;
7 | Scalar const c6 = c1*c2;
8 | Scalar const c7 = pow(theta, -2);
9 | Scalar const c8 = c0*c7;
10 | Scalar const c9 = c4*c7;
11 | result[0] = 0;
12 | result[1] = 0;
13 | result[2] = -c0;
14 | result[3] = 0;
15 | result[4] = 0;
16 | result[5] = c1;
17 | result[6] = c3;
18 | result[7] = -c5;
19 | result[8] = -c3*upsilon[1] + c6*upsilon[0] - c8*upsilon[0] + c9*upsilon[1];
20 | result[9] = c5;
21 | result[10] = c3;
22 | result[11] = c3*upsilon[0] + c6*upsilon[1] - c8*upsilon[1] - c9*upsilon[0];
23 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/cpp_gencode/Se2_Dx_log_this.cpp:
--------------------------------------------------------------------------------
1 | Scalar const c0 = c[0] - 1;
2 | Scalar const c1 = 0.5*atan2(c[1], c[0]);
3 | Scalar const c2 = c1*c[1]/pow(c0, 2);
4 | Scalar const c3 = pow(c[1], 2);
5 | Scalar const c4 = 1.0/(c3 + pow(c[0], 2));
6 | Scalar const c5 = c4*c[1];
7 | Scalar const c6 = 0.5*t[1];
8 | Scalar const c7 = c5*c6;
9 | Scalar const c8 = 0.5*t[0];
10 | Scalar const c9 = 1.0/c0;
11 | Scalar const c10 = c3*c4*c9;
12 | Scalar const c11 = c1*c9;
13 | Scalar const c12 = c4*c[0];
14 | Scalar const c13 = c5*c8;
15 | Scalar const c14 = c9*c[0];
16 | Scalar const c15 = -c11*c[1];
17 | result[0] = c10*c8 + c2*t[0] - c7;
18 | result[1] = -c11*t[0] + c12*c6 - c13*c14;
19 | result[2] = c15;
20 | result[3] = c1;
21 | result[4] = c10*c6 + c13 + c2*t[1];
22 | result[5] = -c11*t[1] - c12*c8 - c14*c7;
23 | result[6] = -c1;
24 | result[7] = c15;
25 | result[8] = -c5;
26 | result[9] = c12;
27 | result[10] = 0;
28 | result[11] = 0;
29 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/cpp_gencode/Se2_Dx_this_mul_exp_x_at_0.cpp:
--------------------------------------------------------------------------------
1 | Scalar const c0 = -c[1];
2 | result[0] = 0;
3 | result[1] = 0;
4 | result[2] = c0;
5 | result[3] = 0;
6 | result[4] = 0;
7 | result[5] = c[0];
8 | result[6] = c[0];
9 | result[7] = c0;
10 | result[8] = 0;
11 | result[9] = c[1];
12 | result[10] = c[0];
13 | result[11] = 0;
14 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/cpp_gencode/Se3_Dx_exp_x.cpp:
--------------------------------------------------------------------------------
1 | Scalar const c0 = pow(omega[0], 2);
2 | Scalar const c1 = pow(omega[1], 2);
3 | Scalar const c2 = pow(omega[2], 2);
4 | Scalar const c3 = c0 + c1 + c2;
5 | Scalar const c4 = sqrt(c3);
6 | Scalar const c5 = 1.0/c4;
7 | Scalar const c6 = 0.5*c4;
8 | Scalar const c7 = sin(c6);
9 | Scalar const c8 = c5*c7;
10 | Scalar const c9 = pow(c3, -3.0/2.0);
11 | Scalar const c10 = c7*c9;
12 | Scalar const c11 = 1.0/c3;
13 | Scalar const c12 = 0.5*c11*cos(c6);
14 | Scalar const c13 = c10*omega[0];
15 | Scalar const c14 = omega[0]*omega[1];
16 | Scalar const c15 = c12*c14 - c13*omega[1];
17 | Scalar const c16 = omega[0]*omega[2];
18 | Scalar const c17 = c12*c16 - c13*omega[2];
19 | Scalar const c18 = omega[1]*omega[2];
20 | Scalar const c19 = -c10*c18 + c12*c18;
21 | Scalar const c20 = 0.5*c8;
22 | Scalar const c21 = sin(c4);
23 | Scalar const c22 = -c21 + c4;
24 | Scalar const c23 = -c1;
25 | Scalar const c24 = -c2;
26 | Scalar const c25 = c23 + c24;
27 | Scalar const c26 = c25*c9;
28 | Scalar const c27 = cos(c4);
29 | Scalar const c28 = 1 - c27;
30 | Scalar const c29 = c11*c28;
31 | Scalar const c30 = c29*omega[2];
32 | Scalar const c31 = c22*c9;
33 | Scalar const c32 = c31*omega[1];
34 | Scalar const c33 = c32*omega[0];
35 | Scalar const c34 = c29*omega[1];
36 | Scalar const c35 = c31*omega[2];
37 | Scalar const c36 = c35*omega[0];
38 | Scalar const c37 = 3*c22/pow(c3, 5.0/2.0);
39 | Scalar const c38 = c25*c37;
40 | Scalar const c39 = c5*omega[0];
41 | Scalar const c40 = -c27*c39 + c39;
42 | Scalar const c41 = c40*c9;
43 | Scalar const c42 = c0*c37;
44 | Scalar const c43 = c16*c41 + c35 - c42*omega[2];
45 | Scalar const c44 = c21*c9;
46 | Scalar const c45 = c14*c44;
47 | Scalar const c46 = 2*c28/pow(c3, 2);
48 | Scalar const c47 = c14*c46;
49 | Scalar const c48 = c45 - c47;
50 | Scalar const c49 = c14*c41 + c32 - c42*omega[1];
51 | Scalar const c50 = c16*c44;
52 | Scalar const c51 = c16*c46;
53 | Scalar const c52 = -c50 + c51;
54 | Scalar const c53 = -2*c32;
55 | Scalar const c54 = c5*omega[1];
56 | Scalar const c55 = -c27*c54 + c54;
57 | Scalar const c56 = c1*c44;
58 | Scalar const c57 = c1*c46;
59 | Scalar const c58 = c55*c9;
60 | Scalar const c59 = c16*c58;
61 | Scalar const c60 = c37*omega[0];
62 | Scalar const c61 = -c18*c60;
63 | Scalar const c62 = c29 + c61;
64 | Scalar const c63 = c31*omega[0];
65 | Scalar const c64 = -c1*c60 + c14*c58 + c63;
66 | Scalar const c65 = c18*c44;
67 | Scalar const c66 = c18*c46;
68 | Scalar const c67 = -c65 + c66;
69 | Scalar const c68 = -2*c35;
70 | Scalar const c69 = c5*omega[2];
71 | Scalar const c70 = -c27*c69 + c69;
72 | Scalar const c71 = c2*c44;
73 | Scalar const c72 = c2*c46;
74 | Scalar const c73 = c70*c9;
75 | Scalar const c74 = c14*c73;
76 | Scalar const c75 = -c29 + c61;
77 | Scalar const c76 = c65 - c66;
78 | Scalar const c77 = c16*c73 - c2*c60 + c63;
79 | Scalar const c78 = -c0;
80 | Scalar const c79 = c24 + c78;
81 | Scalar const c80 = c29*omega[0];
82 | Scalar const c81 = c32*omega[2];
83 | Scalar const c82 = -2*c63;
84 | Scalar const c83 = c79*c9;
85 | Scalar const c84 = c0*c44;
86 | Scalar const c85 = c0*c46;
87 | Scalar const c86 = c18*c41;
88 | Scalar const c87 = c50 - c51;
89 | Scalar const c88 = c37*c79;
90 | Scalar const c89 = -c45 + c47;
91 | Scalar const c90 = c37*omega[2];
92 | Scalar const c91 = -c1*c90 + c18*c58 + c35;
93 | Scalar const c92 = c37*omega[1];
94 | Scalar const c93 = c18*c73 - c2*c92 + c32;
95 | Scalar const c94 = c23 + c78;
96 | Scalar const c95 = c9*c94;
97 | result[0] = 0;
98 | result[1] = 0;
99 | result[2] = 0;
100 | result[3] = -c0*c10 + c0*c12 + c8;
101 | result[4] = c15;
102 | result[5] = c17;
103 | result[6] = 0;
104 | result[7] = 0;
105 | result[8] = 0;
106 | result[9] = c15;
107 | result[10] = -c1*c10 + c1*c12 + c8;
108 | result[11] = c19;
109 | result[12] = 0;
110 | result[13] = 0;
111 | result[14] = 0;
112 | result[15] = c17;
113 | result[16] = c19;
114 | result[17] = -c10*c2 + c12*c2 + c8;
115 | result[18] = 0;
116 | result[19] = 0;
117 | result[20] = 0;
118 | result[21] = -c20*omega[0];
119 | result[22] = -c20*omega[1];
120 | result[23] = -c20*omega[2];
121 | result[24] = c22*c26 + 1;
122 | result[25] = -c30 + c33;
123 | result[26] = c34 + c36;
124 | result[27] = upsilon[0]*(c26*c40 - c38*omega[0]) + upsilon[1]*(c49 + c52) + upsilon[2]*(c43 + c48);
125 | result[28] = upsilon[0]*(c26*c55 - c38*omega[1] + c53) + upsilon[1]*(c64 + c67) + upsilon[2]*(c56 - c57 + c59 + c62);
126 | result[29] = upsilon[0]*(c26*c70 - c38*omega[2] + c68) + upsilon[1]*(-c71 + c72 + c74 + c75) + upsilon[2]*(c76 + c77);
127 | result[30] = c30 + c33;
128 | result[31] = c31*c79 + 1;
129 | result[32] = -c80 + c81;
130 | result[33] = upsilon[0]*(c49 + c87) + upsilon[1]*(c40*c83 - c60*c79 + c82) + upsilon[2]*(c75 - c84 + c85 + c86);
131 | result[34] = upsilon[0]*(c64 + c76) + upsilon[1]*(c55*c83 - c88*omega[1]) + upsilon[2]*(c89 + c91);
132 | result[35] = upsilon[0]*(c62 + c71 - c72 + c74) + upsilon[1]*(c68 + c70*c83 - c88*omega[2]) + upsilon[2]*(c52 + c93);
133 | result[36] = -c34 + c36;
134 | result[37] = c80 + c81;
135 | result[38] = c31*c94 + 1;
136 | result[39] = upsilon[0]*(c43 + c89) + upsilon[1]*(c62 + c84 - c85 + c86) + upsilon[2]*(c40*c95 - c60*c94 + c82);
137 | result[40] = upsilon[0]*(-c56 + c57 + c59 + c75) + upsilon[1]*(c48 + c91) + upsilon[2]*(c53 + c55*c95 - c92*c94);
138 | result[41] = upsilon[0]*(c67 + c77) + upsilon[1]*(c87 + c93) + upsilon[2]*(c70*c95 - c90*c94);
139 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/cpp_gencode/Se3_Dx_this_mul_exp_x_at_0.cpp:
--------------------------------------------------------------------------------
1 | Scalar const c0 = 0.5*q.w();
2 | Scalar const c1 = 0.5*q.z();
3 | Scalar const c2 = -c1;
4 | Scalar const c3 = 0.5*q.y();
5 | Scalar const c4 = 0.5*q.x();
6 | Scalar const c5 = -c4;
7 | Scalar const c6 = -c3;
8 | Scalar const c7 = pow(q.x(), 2);
9 | Scalar const c8 = pow(q.y(), 2);
10 | Scalar const c9 = -c8;
11 | Scalar const c10 = pow(q.w(), 2);
12 | Scalar const c11 = pow(q.z(), 2);
13 | Scalar const c12 = c10 - c11;
14 | Scalar const c13 = 2*q.w();
15 | Scalar const c14 = c13*q.z();
16 | Scalar const c15 = 2*q.x();
17 | Scalar const c16 = c15*q.y();
18 | Scalar const c17 = c13*q.y();
19 | Scalar const c18 = c15*q.z();
20 | Scalar const c19 = -c7;
21 | Scalar const c20 = c13*q.x();
22 | Scalar const c21 = 2*q.y()*q.z();
23 | result[0] = 0;
24 | result[1] = 0;
25 | result[2] = 0;
26 | result[3] = c0;
27 | result[4] = c2;
28 | result[5] = c3;
29 | result[6] = 0;
30 | result[7] = 0;
31 | result[8] = 0;
32 | result[9] = c1;
33 | result[10] = c0;
34 | result[11] = c5;
35 | result[12] = 0;
36 | result[13] = 0;
37 | result[14] = 0;
38 | result[15] = c6;
39 | result[16] = c4;
40 | result[17] = c0;
41 | result[18] = 0;
42 | result[19] = 0;
43 | result[20] = 0;
44 | result[21] = c5;
45 | result[22] = c6;
46 | result[23] = c2;
47 | result[24] = c12 + c7 + c9;
48 | result[25] = -c14 + c16;
49 | result[26] = c17 + c18;
50 | result[27] = 0;
51 | result[28] = 0;
52 | result[29] = 0;
53 | result[30] = c14 + c16;
54 | result[31] = c12 + c19 + c8;
55 | result[32] = -c20 + c21;
56 | result[33] = 0;
57 | result[34] = 0;
58 | result[35] = 0;
59 | result[36] = -c17 + c18;
60 | result[37] = c20 + c21;
61 | result[38] = c10 + c11 + c19 + c9;
62 | result[39] = 0;
63 | result[40] = 0;
64 | result[41] = 0;
65 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/cpp_gencode/So2_Dx_exp_x.cpp:
--------------------------------------------------------------------------------
1 | result[0] = -sin(theta);
2 | result[1] = cos(theta);
3 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/cpp_gencode/So2_Dx_log_exp_x_times_this_at_0.cpp:
--------------------------------------------------------------------------------
1 | result = 1;
2 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/cpp_gencode/So2_Dx_log_this.cpp:
--------------------------------------------------------------------------------
1 | result = -c[1]/(pow(c[0], 2) + pow(c[1], 2));
2 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/cpp_gencode/So2_Dx_this_mul_exp_x_at_0.cpp:
--------------------------------------------------------------------------------
1 | result[0] = -c[1];
2 | result[1] = c[0];
3 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/cpp_gencode/So3_Dx_exp_x.cpp:
--------------------------------------------------------------------------------
1 | Scalar const c0 = pow(omega[0], 2);
2 | Scalar const c1 = pow(omega[1], 2);
3 | Scalar const c2 = pow(omega[2], 2);
4 | Scalar const c3 = c0 + c1 + c2;
5 | Scalar const c4 = sqrt(c3);
6 | Scalar const c5 = 0.5*c4;
7 | Scalar const c6 = sin(c5);
8 | Scalar const c7 = c6/c4;
9 | Scalar const c8 = c6/pow(c3, 3.0/2.0);
10 | Scalar const c9 = 0.5*cos(c5)/c3;
11 | Scalar const c10 = c8*omega[0];
12 | Scalar const c11 = c9*omega[0];
13 | Scalar const c12 = -c10*omega[1] + c11*omega[1];
14 | Scalar const c13 = -c10*omega[2] + c11*omega[2];
15 | Scalar const c14 = omega[1]*omega[2];
16 | Scalar const c15 = -c14*c8 + c14*c9;
17 | Scalar const c16 = 0.5*c7;
18 | result[0] = -c0*c8 + c0*c9 + c7;
19 | result[1] = c12;
20 | result[2] = c13;
21 | result[3] = c12;
22 | result[4] = -c1*c8 + c1*c9 + c7;
23 | result[5] = c15;
24 | result[6] = c13;
25 | result[7] = c15;
26 | result[8] = -c2*c8 + c2*c9 + c7;
27 | result[9] = -c16*omega[0];
28 | result[10] = -c16*omega[1];
29 | result[11] = -c16*omega[2];
30 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/cpp_gencode/So3_Dx_log_exp_x_times_this_at_0.cpp:
--------------------------------------------------------------------------------
1 | Scalar const c0 = 1.0*pow(q.x(), 4);
2 | Scalar const c1 = 1.0*pow(q.y(), 4);
3 | Scalar const c2 = 1.0*pow(q.z(), 4);
4 | Scalar const c3 = pow(q.y(), 2);
5 | Scalar const c4 = pow(q.x(), 2);
6 | Scalar const c5 = 2.0*c4;
7 | Scalar const c6 = pow(q.z(), 2);
8 | Scalar const c7 = c3*c6;
9 | Scalar const c8 = 1.0/(c0 + c1 + c2 + c3*c5 + c5*c6 + 2.0*c7);
10 | Scalar const c9 = 1.0*c4;
11 | Scalar const c10 = sqrt(c3 + c4 + c6);
12 | Scalar const c11 = c10*atan(c10/q.w());
13 | Scalar const c12 = 1.0*c11;
14 | Scalar const c13 = c12*q.w();
15 | Scalar const c14 = c13*c6 + c3*c9;
16 | Scalar const c15 = c13*c3 + c6*c9;
17 | Scalar const c16 = pow(q.z(), 3);
18 | Scalar const c17 = 1.0*c16;
19 | Scalar const c18 = c11*c17;
20 | Scalar const c19 = c9*q.z();
21 | Scalar const c20 = c11*c19;
22 | Scalar const c21 = c3*q.z();
23 | Scalar const c22 = c12*c21;
24 | Scalar const c23 = pow(q.y(), 3);
25 | Scalar const c24 = 1.0*q.x();
26 | Scalar const c25 = 1.0*pow(q.x(), 3);
27 | Scalar const c26 = c6*q.y();
28 | Scalar const c27 = c11*c24;
29 | Scalar const c28 = c27*q.w();
30 | Scalar const c29 = c23*c24 + c24*c26 + c25*q.y() - c28*q.y();
31 | Scalar const c30 = 1.0*c23;
32 | Scalar const c31 = c11*c30;
33 | Scalar const c32 = c11*c9;
34 | Scalar const c33 = c32*q.y();
35 | Scalar const c34 = c12*c26;
36 | Scalar const c35 = c16*c24 + c21*c24 + c25*q.z() - c28*q.z();
37 | Scalar const c36 = c32*q.w() + 1.0*c7;
38 | Scalar const c37 = c11*c25;
39 | Scalar const c38 = c27*c3;
40 | Scalar const c39 = c27*c6;
41 | Scalar const c40 = -c13*q.y()*q.z() + c17*q.y() + c19*q.y() + c30*q.z();
42 | result[0] = c8*(c0 + c14 + c15);
43 | result[1] = c8*(c18 + c20 + c22 + c29);
44 | result[2] = c8*(-c31 - c33 - c34 + c35);
45 | result[3] = c8*(-c18 - c20 - c22 + c29);
46 | result[4] = c8*(c1 + c14 + c36);
47 | result[5] = c8*(c37 + c38 + c39 + c40);
48 | result[6] = c8*(c31 + c33 + c34 + c35);
49 | result[7] = c8*(-c37 - c38 - c39 + c40);
50 | result[8] = c8*(c15 + c2 + c36);
51 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/cpp_gencode/So3_Dx_log_this.cpp:
--------------------------------------------------------------------------------
1 | Scalar const c0 = pow(q.x(), 2);
2 | Scalar const c1 = pow(q.y(), 2);
3 | Scalar const c2 = pow(q.z(), 2);
4 | Scalar const c3 = c0 + c1 + c2;
5 | Scalar const c4 = sqrt(c3);
6 | Scalar const c5 = 1.0/q.w();
7 | Scalar const c6 = 2*atan(c4*c5);
8 | Scalar const c7 = c6/c4;
9 | Scalar const c8 = c6/pow(c3, 3.0/2.0);
10 | Scalar const c9 = 2*c5/(c3*(c3/pow(q.w(), 2) + 1));
11 | Scalar const c10 = c8*q.x();
12 | Scalar const c11 = c9*q.x();
13 | Scalar const c12 = -c10*q.y() + c11*q.y();
14 | Scalar const c13 = -c10*q.z() + c11*q.z();
15 | Scalar const c14 = q.y()*q.z();
16 | Scalar const c15 = -c14*c8 + c14*c9;
17 | result[0] = -c0*c8 + c0*c9 + c7;
18 | result[1] = c12;
19 | result[2] = c13;
20 | result[3] = c12;
21 | result[4] = -c1*c8 + c1*c9 + c7;
22 | result[5] = c15;
23 | result[6] = c13;
24 | result[7] = c15;
25 | result[8] = -c2*c8 + c2*c9 + c7;
26 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/cpp_gencode/So3_Dx_this_mul_exp_x_at_0.cpp:
--------------------------------------------------------------------------------
1 | Scalar const c0 = 0.5*q.w();
2 | Scalar const c1 = 0.5*q.z();
3 | Scalar const c2 = -c1;
4 | Scalar const c3 = 0.5*q.y();
5 | Scalar const c4 = 0.5*q.x();
6 | Scalar const c5 = -c4;
7 | Scalar const c6 = -c3;
8 | result[0] = c0;
9 | result[1] = c2;
10 | result[2] = c3;
11 | result[3] = c1;
12 | result[4] = c0;
13 | result[5] = c5;
14 | result[6] = c6;
15 | result[7] = c4;
16 | result[8] = c0;
17 | result[9] = c5;
18 | result[10] = c6;
19 | result[11] = c2;
20 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/run_tests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | EXIT=0
4 |
5 | python3 -m sophus.complex || EXIT=$?
6 | python3 -m sophus.quaternion || EXIT=$?
7 | python3 -m sophus.dual_quaternion || EXIT=$?
8 | python3 -m sophus.so2 || EXIT=$?
9 | python3 -m sophus.se2 || EXIT=$?
10 | python3 -m sophus.so3 || EXIT=$?
11 | python3 -m sophus.se3 || EXIT=$?
12 |
13 | exit $EXIT
14 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/sophus/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YWL0720/I2EKF-LO/8d2158cda30ed9b261e668b9ab6f75f5ab424624/Thirdparty/Sophus/sympy/sophus/__init__.py
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/sophus/complex.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | import sympy
4 |
5 |
6 | class Complex:
7 | """ Complex class """
8 |
9 | def __init__(self, real, imag):
10 | self.real = real
11 | self.imag = imag
12 |
13 | def __mul__(self, right):
14 | """ complex multiplication """
15 | return Complex(self.real * right.real - self.imag * right.imag,
16 | self.imag * right.real + self.real * right.imag)
17 |
18 | def __add__(self, right):
19 | return Complex(self.real + right.real, self.imag + right.imag)
20 |
21 | def __neg__(self):
22 | return Complex(-self.real, -self.image)
23 |
24 | def __truediv__(self, scalar):
25 | """ scalar division """
26 | return Complex(self.real / scalar, self.imag / scalar)
27 |
28 | def __repr__(self):
29 | return "( " + repr(self.real) + " + " + repr(self.imag) + "i )"
30 |
31 | def __getitem__(self, key):
32 | """ We use the following convention [real, imag] """
33 | if key == 0:
34 | return self.real
35 | else:
36 | return self.imag
37 |
38 | def squared_norm(self):
39 | """ squared norm when considering the complex number as tuple """
40 | return self.real**2 + self.imag**2
41 |
42 | def conj(self):
43 | """ complex conjugate """
44 | return Complex(self.real, -self.imag)
45 |
46 | def inv(self):
47 | """ complex inverse """
48 | return self.conj() / self.squared_norm()
49 |
50 | @staticmethod
51 | def identity():
52 | return Complex(1, 0)
53 |
54 | @staticmethod
55 | def zero():
56 | return Complex(0, 0)
57 |
58 | def __eq__(self, other):
59 | if isinstance(self, other.__class__):
60 | return self.real == other.real and self.imag == other.imag
61 | return False
62 |
63 | def subs(self, x, y):
64 | return Complex(self.real.subs(x, y), self.imag.subs(x, y))
65 |
66 | def simplify(self):
67 | return Complex(sympy.simplify(self.real),
68 | sympy.simplify(self.imag))
69 |
70 | @staticmethod
71 | def Da_a_mul_b(a, b):
72 | """ derivatice of complex muliplication wrt left multiplier a """
73 | return sympy.Matrix([[b.real, -b.imag],
74 | [b.imag, b.real]])
75 |
76 | @staticmethod
77 | def Db_a_mul_b(a, b):
78 | """ derivatice of complex muliplication wrt right multiplicand b """
79 | return sympy.Matrix([[a.real, -a.imag],
80 | [a.imag, a.real]])
81 |
82 |
83 | class TestComplex(unittest.TestCase):
84 | def setUp(self):
85 | x, y = sympy.symbols('x y', real=True)
86 | u, v = sympy.symbols('u v', real=True)
87 | self.a = Complex(x, y)
88 | self.b = Complex(u, v)
89 |
90 | def test_multiplications(self):
91 | product = self.a * self.a.inv()
92 | self.assertEqual(product.simplify(),
93 | Complex.identity())
94 | product = self.a.inv() * self.a
95 | self.assertEqual(product.simplify(),
96 | Complex.identity())
97 |
98 | def test_derivatives(self):
99 | d = sympy.Matrix(2, 2, lambda r, c: sympy.diff(
100 | (self.a * self.b)[r], self.a[c]))
101 | self.assertEqual(d,
102 | Complex.Da_a_mul_b(self.a, self.b))
103 | d = sympy.Matrix(2, 2, lambda r, c: sympy.diff(
104 | (self.a * self.b)[r], self.b[c]))
105 | self.assertEqual(d,
106 | Complex.Db_a_mul_b(self.a, self.b))
107 |
108 |
109 | if __name__ == '__main__':
110 | unittest.main()
111 | print('hello')
112 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/sophus/cse_codegen.py:
--------------------------------------------------------------------------------
1 | import io
2 |
3 | import sympy
4 |
5 |
6 | def cse_codegen(symbols):
7 | cse_results = sympy.cse(symbols, sympy.numbered_symbols("c"))
8 | output = io.StringIO()
9 | for helper in cse_results[0]:
10 | output.write("Scalar const ")
11 | output.write(sympy.printing.ccode(helper[1], helper[0]))
12 | output.write("\n")
13 | assert len(cse_results[1]) == 1
14 |
15 | output.write(sympy.printing.ccode(cse_results[1][0], "result"))
16 | output.write("\n")
17 | output.seek(0)
18 | return output
19 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/sophus/dual_quaternion.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | import sympy
4 |
5 | from sophus.matrix import Vector3
6 | from sophus.quaternion import Quaternion
7 |
8 |
9 | class DualQuaternion:
10 | """ Dual quaternion class """
11 |
12 | def __init__(self, real_q, inf_q):
13 | """ Dual quaternion consists of a real quaternion, and an infinitesimal
14 | quaternion """
15 | self.real_q = real_q
16 | self.inf_q = inf_q
17 |
18 | def __mul__(self, right):
19 | """ dual quaternion multiplication """
20 | return DualQuaternion(self.real_q * right.real_q,
21 | self.real_q * right.inf_q +
22 | self.inf_q * right.real_q)
23 |
24 | def __truediv__(self, scalar):
25 | """ scalar division """
26 | return DualQuaternion(self.real_q / scalar, self.inf_q / scalar)
27 |
28 | def __repr__(self):
29 | return "( " + repr(self.real_q) + \
30 | " + " + repr(self.inf_q) + ")"
31 |
32 | def __getitem__(self, key):
33 | assert (key >= 0 and key < 8)
34 | if key < 4:
35 | return self.real_q[key]
36 | else:
37 | return self.inf_q[key - 4]
38 |
39 | def squared_norm(self):
40 | """ squared norm when considering the dual quaternion as 8-tuple """
41 | return self.real_q.squared_norm() + self.inf_q.squared_norm()
42 |
43 | def conj(self):
44 | """ dual quaternion conjugate """
45 | return DualQuaternion(self.real_q.conj(), self.inf_q.conj())
46 |
47 | def inv(self):
48 | """ dual quaternion inverse """
49 | return DualQuaternion(self.real_q.inv(),
50 | -self.real_q.inv() * self.inf_q *
51 | self.real_q.inv())
52 |
53 | def simplify(self):
54 | return DualQuaternion(self.real_q.simplify(),
55 | self.inf_q.simplify())
56 |
57 | @staticmethod
58 | def identity():
59 | return DualQuaternion(Quaternion.identity(),
60 | Quaternion.zero())
61 |
62 | def __eq__(self, other):
63 | if isinstance(self, other.__class__):
64 | return self.real_q == other.real_q and self.inf_q == other.inf_q
65 | return False
66 |
67 |
68 | class TestDualQuaternion(unittest.TestCase):
69 | def setUp(self):
70 | w, s0, s1, s2 = sympy.symbols('w s0 s1 s2', real=True)
71 | x, t0, t1, t2 = sympy.symbols('x t0 t1 t2', real=True)
72 | y, u0, u1, u2 = sympy.symbols('y u0 u1 u2', real=True)
73 | z, v0, v1, v2 = sympy.symbols('z v0 v1 v2', real=True)
74 |
75 | s = Vector3(s0, s1, s2)
76 | t = Vector3(t0, t1, t2)
77 | u = Vector3(u0, u1, u2)
78 | v = Vector3(v0, v1, v2)
79 | self.a = DualQuaternion(Quaternion(w, s),
80 | Quaternion(x, t))
81 | self.b = DualQuaternion(Quaternion(y, u),
82 | Quaternion(z, v))
83 |
84 | def test_multiplications(self):
85 | product = self.a * self.a.inv()
86 | self.assertEqual(product.simplify(),
87 | DualQuaternion.identity())
88 | product = self.a.inv() * self.a
89 | self.assertEqual(product.simplify(),
90 | DualQuaternion.identity())
91 |
92 |
93 | if __name__ == '__main__':
94 | unittest.main()
95 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/sophus/matrix.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | import sympy
4 |
5 | assert sys.version_info >= (3, 5)
6 |
7 |
8 | def dot(left, right):
9 | assert(isinstance(left, sympy.Matrix))
10 | assert(isinstance(right, sympy.Matrix))
11 |
12 | sum = 0
13 | for c in range(0, left.cols):
14 | for r in range(0, left.rows):
15 | sum += left[r, c] * right[r, c]
16 | return sum
17 |
18 |
19 | def squared_norm(m):
20 | assert(isinstance(m, sympy.Matrix))
21 | return dot(m, m)
22 |
23 |
24 | def Vector2(x, y):
25 | return sympy.Matrix([x, y])
26 |
27 |
28 | def ZeroVector2():
29 | return Vector2(0, 0)
30 |
31 |
32 | def Vector3(x, y, z):
33 | return sympy.Matrix([x, y, z])
34 |
35 |
36 | def ZeroVector3():
37 | return Vector3(0, 0, 0)
38 |
39 |
40 | def Vector4(a, b, c, d):
41 | return sympy.Matrix([a, b, c, d])
42 |
43 |
44 | def ZeroVector4():
45 | return Vector4(0, 0, 0, 0)
46 |
47 |
48 | def Vector5(a, b, c, d, e):
49 | return sympy.Matrix([a, b, c, d, e])
50 |
51 |
52 | def ZeroVector5():
53 | return Vector5(0, 0, 0, 0, 0)
54 |
55 |
56 | def Vector6(a, b, c, d, e, f):
57 | return sympy.Matrix([a, b, c, d, e, f])
58 |
59 |
60 | def ZeroVector6():
61 | return Vector6(0, 0, 0, 0, 0, 0)
62 |
63 |
64 | def proj(v):
65 | m, n = v.shape
66 | assert m > 1
67 | assert n == 1
68 | list = [v[i] / v[m - 1] for i in range(0, m - 1)]
69 | r = sympy.Matrix(m - 1, 1, list)
70 | return r
71 |
72 |
73 | def unproj(v):
74 | m, n = v.shape
75 | assert m >= 1
76 | assert n == 1
77 | return v.col_join(sympy.Matrix.ones(1, 1))
78 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/sympy/sophus/quaternion.py:
--------------------------------------------------------------------------------
1 | """ run with: python3 -m sophus.quaternion """
2 |
3 | import unittest
4 |
5 | import sympy
6 |
7 | from sophus.matrix import Vector3
8 | from sophus.matrix import squared_norm
9 |
10 |
11 | class Quaternion:
12 | """ Quaternion class """
13 |
14 | def __init__(self, real, vec):
15 | """ Quaternion consists of a real scalar, and an imaginary 3-vector """
16 | assert isinstance(vec, sympy.Matrix)
17 | assert vec.shape == (3, 1), vec.shape
18 | self.real = real
19 | self.vec = vec
20 |
21 | def __mul__(self, right):
22 | """ quaternion multiplication """
23 | return Quaternion(self[3] * right[3] - self.vec.dot(right.vec),
24 | self[3] * right.vec + right[3] * self.vec +
25 | self.vec.cross(right.vec))
26 |
27 | def __add__(self, right):
28 | """ quaternion multiplication """
29 | return Quaternion(self[3] + right[3], self.vec + right.vec)
30 |
31 | def __neg__(self):
32 | return Quaternion(-self[3], -self.vec)
33 |
34 | def __truediv__(self, scalar):
35 | """ scalar division """
36 | return Quaternion(self.real / scalar, self.vec / scalar)
37 |
38 | def __repr__(self):
39 | return "( " + repr(self[3]) + " + " + repr(self.vec) + "i )"
40 |
41 | def __getitem__(self, key):
42 | """ We use the following convention [vec0, vec1, vec2, real] """
43 | assert (key >= 0 and key < 4)
44 | if key == 3:
45 | return self.real
46 | else:
47 | return self.vec[key]
48 |
49 | def squared_norm(self):
50 | """ squared norm when considering the quaternion as 4-tuple """
51 | return squared_norm(self.vec) + self.real**2
52 |
53 | def conj(self):
54 | """ quaternion conjugate """
55 | return Quaternion(self.real, -self.vec)
56 |
57 | def inv(self):
58 | """ quaternion inverse """
59 | return self.conj() / self.squared_norm()
60 |
61 | @staticmethod
62 | def identity():
63 | return Quaternion(1, Vector3(0, 0, 0))
64 |
65 | @staticmethod
66 | def zero():
67 | return Quaternion(0, Vector3(0, 0, 0))
68 |
69 | def subs(self, x, y):
70 | return Quaternion(self.real.subs(x, y), self.vec.subs(x, y))
71 |
72 | def simplify(self):
73 | v = sympy.simplify(self.vec)
74 | return Quaternion(sympy.simplify(self.real),
75 | Vector3(v[0], v[1], v[2]))
76 |
77 | def __eq__(self, other):
78 | if isinstance(self, other.__class__):
79 | return self.real == other.real and self.vec == other.vec
80 | return False
81 |
82 | @staticmethod
83 | def Da_a_mul_b(a, b):
84 | """ derivatice of quaternion muliplication wrt left multiplier a """
85 | v0 = b.vec[0]
86 | v1 = b.vec[1]
87 | v2 = b.vec[2]
88 | y = b.real
89 | return sympy.Matrix([[y, v2, -v1, v0],
90 | [-v2, y, v0, v1],
91 | [v1, -v0, y, v2],
92 | [-v0, -v1, -v2, y]])
93 |
94 | @staticmethod
95 | def Db_a_mul_b(a, b):
96 | """ derivatice of quaternion muliplication wrt right multiplicand b """
97 | u0 = a.vec[0]
98 | u1 = a.vec[1]
99 | u2 = a.vec[2]
100 | x = a.real
101 | return sympy.Matrix([[x, -u2, u1, u0],
102 | [u2, x, -u0, u1],
103 | [-u1, u0, x, u2],
104 | [-u0, -u1, -u2, x]])
105 |
106 |
107 | class TestQuaternion(unittest.TestCase):
108 | def setUp(self):
109 | x, u0, u1, u2 = sympy.symbols('x u0 u1 u2', real=True)
110 | y, v0, v1, v2 = sympy.symbols('y v0 v1 v2', real=True)
111 | u = Vector3(u0, u1, u2)
112 | v = Vector3(v0, v1, v2)
113 | self.a = Quaternion(x, u)
114 | self.b = Quaternion(y, v)
115 |
116 | def test_multiplications(self):
117 | product = self.a * self.a.inv()
118 | self.assertEqual(product.simplify(),
119 | Quaternion.identity())
120 | product = self.a.inv() * self.a
121 | self.assertEqual(product.simplify(),
122 | Quaternion.identity())
123 |
124 | def test_derivatives(self):
125 | d = sympy.Matrix(4, 4, lambda r, c: sympy.diff(
126 | (self.a * self.b)[r], self.a[c]))
127 | self.assertEqual(d,
128 | Quaternion.Da_a_mul_b(self.a, self.b))
129 | d = sympy.Matrix(4, 4, lambda r, c: sympy.diff(
130 | (self.a * self.b)[r], self.b[c]))
131 | self.assertEqual(d,
132 | Quaternion.Db_a_mul_b(self.a, self.b))
133 |
134 |
135 | if __name__ == '__main__':
136 | unittest.main()
137 | print('hello')
138 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ADD_SUBDIRECTORY(core)
2 | ADD_SUBDIRECTORY(ceres)
3 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/test/ceres/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Make sure Ceres knows where to find Eigen
2 | list(APPEND SEARCH_HEADERS ${EIGEN3_INCLUDE_DIR})
3 |
4 | # git clone https://ceres-solver.googlesource.com/ceres-solver
5 | find_package(Ceres 2.1.0 QUIET)
6 |
7 | function(add_test_ceres source postfix)
8 | add_executable(${source}_${postfix} ${source}.cpp)
9 | target_link_libraries(${source}_${postfix} sophus Ceres::ceres)
10 | target_compile_definitions(${source}_${postfix} PRIVATE ${ARGN})
11 | add_test(${source}_${postfix} ${source}_${postfix})
12 | endfunction()
13 |
14 | if(Ceres_FOUND)
15 | message(STATUS "CERES found")
16 |
17 | # Tests to run
18 | set(TEST_SOURCES
19 | test_ceres_so3
20 | test_ceres_rxso3
21 | test_ceres_se3
22 | test_ceres_sim3
23 | test_ceres_so2
24 | test_ceres_rxso2
25 | test_ceres_se2
26 | test_ceres_sim2)
27 |
28 | foreach(test_src ${TEST_SOURCES})
29 | add_test_ceres(${test_src} "local_parameterization")
30 | endforeach()
31 | foreach(test_src ${TEST_SOURCES})
32 | add_test_ceres(${test_src} "manifold")
33 | endforeach()
34 | endif(Ceres_FOUND)
35 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/test/ceres/test_ceres_rxso2.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "tests.hpp"
6 |
7 | template
8 | using StdVector = std::vector>;
9 |
10 | template <>
11 | struct RotationalPart {
12 | static double Norm(const typename Sophus::RxSO2d::Tangent &t) {
13 | return std::abs(t[0]);
14 | }
15 | };
16 |
17 | int main(int, char **) {
18 | using RxSO2d = Sophus::RxSO2d;
19 | using Tangent = RxSO2d::Tangent;
20 | using Point = RxSO2d::Point;
21 | double const kPi = Sophus::Constants::pi();
22 |
23 | StdVector rxso2_vec;
24 | rxso2_vec.push_back(RxSO2d::exp(Tangent(0.2, 1.)));
25 | rxso2_vec.push_back(RxSO2d::exp(Tangent(0.2, 1.1)));
26 | rxso2_vec.push_back(RxSO2d::exp(Tangent(0., 1.1)));
27 | rxso2_vec.push_back(RxSO2d::exp(Tangent(0.00001, 0.)));
28 | rxso2_vec.push_back(RxSO2d::exp(Tangent(0.00001, 0.00001)));
29 | rxso2_vec.push_back(RxSO2d::exp(Tangent(kPi, 0.9)));
30 | rxso2_vec.push_back(RxSO2d::exp(Tangent(0.2, 0)) *
31 | RxSO2d::exp(Tangent(kPi, 0.0)) *
32 | RxSO2d::exp(Tangent(-0.2, 0)));
33 | rxso2_vec.push_back(RxSO2d::exp(Tangent(0.3, 0)) *
34 | RxSO2d::exp(Tangent(kPi, 0.001)) *
35 | RxSO2d::exp(Tangent(-0.3, 0)));
36 |
37 | StdVector point_vec;
38 | point_vec.push_back(Point(1.012, 2.73));
39 | point_vec.push_back(Point(9.2, -7.3));
40 | point_vec.push_back(Point(2.5, 0.1));
41 | point_vec.push_back(Point(12.3, 1.9));
42 | point_vec.push_back(Point(-3.21, 3.42));
43 | point_vec.push_back(Point(-8.0, 6.1));
44 | point_vec.push_back(Point(0.0, 2.5));
45 | point_vec.push_back(Point(7.1, 7.8));
46 | point_vec.push_back(Point(5.8, 9.2));
47 |
48 | std::cerr << "Test Ceres RxSO2" << std::endl;
49 | Sophus::LieGroupCeresTests(rxso2_vec, point_vec).testAll();
50 | return 0;
51 | }
52 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/test/ceres/test_ceres_rxso3.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "tests.hpp"
6 |
7 | template
8 | using StdVector = std::vector>;
9 |
10 | template <>
11 | struct RotationalPart {
12 | static double Norm(const typename Sophus::RxSO3d::Tangent &t) {
13 | return t.template head<3>().norm();
14 | }
15 | };
16 |
17 | int main(int, char **) {
18 | using RxSO3d = Sophus::RxSO3d;
19 | using Point = RxSO3d::Point;
20 | using Tangent = RxSO3d::Tangent;
21 | double const kPi = Sophus::Constants::pi();
22 |
23 | StdVector rxso3_vec;
24 | rxso3_vec.push_back(RxSO3d::exp(Tangent(0.2, 0.5, 0.0, 1.)));
25 | rxso3_vec.push_back(RxSO3d::exp(Tangent(0.2, 0.5, -1.0, 1.1)));
26 | rxso3_vec.push_back(RxSO3d::exp(Tangent(0., 0., 0., 1.1)));
27 | rxso3_vec.push_back(RxSO3d::exp(Tangent(0., 0., 0.00001, 0.)));
28 | rxso3_vec.push_back(RxSO3d::exp(Tangent(0., 0., 0.00001, 0.00001)));
29 | rxso3_vec.push_back(RxSO3d::exp(Tangent(0., 0., 0.00001, 0)));
30 |
31 | rxso3_vec.push_back(RxSO3d::exp(Tangent(kPi, 0, 0, 0.9)));
32 |
33 | rxso3_vec.push_back(RxSO3d::exp(Tangent(0.2, -0.5, 0, 0)) *
34 | RxSO3d::exp(Tangent(kPi, 0, 0, 0)) *
35 | RxSO3d::exp(Tangent(-0.2, -0.5, 0, 0)));
36 |
37 | rxso3_vec.push_back(RxSO3d::exp(Tangent(0.3, 0.5, 0.1, 0)) *
38 | RxSO3d::exp(Tangent(kPi, 0, 0, 0)) *
39 | RxSO3d::exp(Tangent(-0.3, -0.5, -0.1, 0)));
40 |
41 | StdVector point_vec;
42 | point_vec.push_back(Point(1.012, 2.73, -1.4));
43 | point_vec.push_back(Point(9.2, -7.3, -4.4));
44 | point_vec.push_back(Point(2.5, 0.1, 9.1));
45 | point_vec.push_back(Point(12.3, 1.9, 3.8));
46 | point_vec.push_back(Point(-3.21, 3.42, 2.3));
47 | point_vec.push_back(Point(-8.0, 6.1, -1.1));
48 | point_vec.push_back(Point(0.0, 2.5, 5.9));
49 | point_vec.push_back(Point(7.1, 7.8, -14));
50 | point_vec.push_back(Point(5.8, 9.2, 0.0));
51 |
52 | std::cerr << "Test Ceres RxSO2" << std::endl;
53 | Sophus::LieGroupCeresTests(rxso3_vec, point_vec).testAll();
54 | return 0;
55 | }
56 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/test/ceres/test_ceres_se2.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "tests.hpp"
6 |
7 | template
8 | using StdVector = std::vector>;
9 |
10 | template <>
11 | struct RotationalPart {
12 | static double Norm(const typename Sophus::SE2d::Tangent &t) {
13 | return std::abs(t[2]);
14 | }
15 | };
16 |
17 | int main(int, char **) {
18 | using SE2d = Sophus::SE2d;
19 | using SO2d = Sophus::SO2d;
20 | using Point = SE2d::Point;
21 | double const kPi = Sophus::Constants::pi();
22 |
23 | StdVector se2_vec;
24 | se2_vec.push_back(SE2d(SO2d(0.0), Point(0, 0)));
25 | se2_vec.push_back(SE2d(SO2d(0.2), Point(10, 0)));
26 | se2_vec.push_back(SE2d(SO2d(0.), Point(0, 100)));
27 | se2_vec.push_back(SE2d(SO2d(-1.), Point(20, -1)));
28 | se2_vec.push_back(SE2d(SO2d(0.00001), Point(-0.00000001, 0.0000000001)));
29 | se2_vec.push_back(SE2d(SO2d(0.2), Point(0, 0)) *
30 | SE2d(SO2d(kPi), Point(0, 0)) *
31 | SE2d(SO2d(-0.2), Point(0, 0)));
32 | se2_vec.push_back(SE2d(SO2d(0.3), Point(2, 0)) *
33 | SE2d(SO2d(kPi), Point(0, 0)) *
34 | SE2d(SO2d(-0.3), Point(0, 6)));
35 |
36 | StdVector point_vec;
37 | point_vec.push_back(Point(1.012, 2.73));
38 | point_vec.push_back(Point(9.2, -7.3));
39 | point_vec.push_back(Point(2.5, 0.1));
40 | point_vec.push_back(Point(12.3, 1.9));
41 | point_vec.push_back(Point(-3.21, 3.42));
42 | point_vec.push_back(Point(-8.0, 6.1));
43 | point_vec.push_back(Point(0.0, 2.5));
44 | point_vec.push_back(Point(7.1, 7.8));
45 | point_vec.push_back(Point(5.8, 9.2));
46 |
47 | std::cerr << "Test Ceres SE2" << std::endl;
48 | Sophus::LieGroupCeresTests(se2_vec, point_vec).testAll();
49 | return 0;
50 | }
51 |
--------------------------------------------------------------------------------
/Thirdparty/Sophus/test/ceres/test_ceres_se3.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include