├── LICENCE
├── README.md
├── camera_model
├── CMakeLists.txt
├── cmake
│ └── FindEigen.cmake
├── include
│ └── camodocal
│ │ ├── calib
│ │ └── CameraCalibration.h
│ │ ├── camera_models
│ │ ├── Camera.h
│ │ ├── CameraFactory.h
│ │ ├── CataCamera.h
│ │ ├── CostFunctionFactory.h
│ │ ├── EquidistantCamera.h
│ │ ├── PinholeCamera.h
│ │ └── ScaramuzzaCamera.h
│ │ ├── chessboard
│ │ ├── Chessboard.h
│ │ ├── ChessboardCorner.h
│ │ ├── ChessboardQuad.h
│ │ └── Spline.h
│ │ ├── gpl
│ │ ├── EigenQuaternionParameterization.h
│ │ ├── EigenUtils.h
│ │ └── gpl.h
│ │ └── sparse_graph
│ │ └── Transform.h
├── instruction
├── package.xml
├── readme.md
└── src
│ ├── calib
│ └── CameraCalibration.cc
│ ├── camera_models
│ ├── Camera.cc
│ ├── CameraFactory.cc
│ ├── CataCamera.cc
│ ├── CostFunctionFactory.cc
│ ├── EquidistantCamera.cc
│ ├── PinholeCamera.cc
│ └── ScaramuzzaCamera.cc
│ ├── chessboard
│ └── Chessboard.cc
│ ├── gpl
│ ├── EigenQuaternionParameterization.cc
│ └── gpl.cc
│ ├── intrinsic_calib.cc
│ └── sparse_graph
│ └── Transform.cc
├── config
├── gvins_rviz_config.rviz
├── simulator
│ └── simulator_config.yaml
└── visensor_f9p
│ └── visensor_left_f9p_config.yaml
├── docker
├── Dockerfile
├── Makefile
└── run.sh
├── estimator
├── CMakeLists.txt
├── cmake
│ └── FindEigen.cmake
├── launch
│ ├── simulator.launch
│ └── visensor_f9p.launch
├── msg
│ └── LocalSensorExternalTrigger.msg
├── package.xml
└── src
│ ├── estimator.cpp
│ ├── estimator.h
│ ├── estimator_node.cpp
│ ├── factor
│ ├── gnss_ddt_smooth_factor.cpp
│ ├── gnss_ddt_smooth_factor.hpp
│ ├── gnss_dt_anchor_factor.cpp
│ ├── gnss_dt_anchor_factor.hpp
│ ├── gnss_dt_ddt_factor.cpp
│ ├── gnss_dt_ddt_factor.hpp
│ ├── gnss_psr_dopp_factor.cpp
│ ├── gnss_psr_dopp_factor.hpp
│ ├── imu_factor.h
│ ├── integration_base.h
│ ├── marginalization_factor.cpp
│ ├── marginalization_factor.h
│ ├── pos_vel_factor.cpp
│ ├── pos_vel_factor.hpp
│ ├── pose_anchor_factor.cpp
│ ├── pose_anchor_factor.h
│ ├── pose_local_parameterization.cpp
│ ├── pose_local_parameterization.h
│ ├── projection_factor.cpp
│ ├── projection_factor.h
│ ├── projection_td_factor.cpp
│ └── projection_td_factor.h
│ ├── feature_manager.cpp
│ ├── feature_manager.h
│ ├── initial
│ ├── gnss_vi_initializer.cpp
│ ├── gnss_vi_initializer.h
│ ├── initial_aligment.cpp
│ ├── initial_alignment.h
│ ├── initial_ex_rotation.cpp
│ ├── initial_ex_rotation.h
│ ├── initial_sfm.cpp
│ ├── initial_sfm.h
│ ├── solve_5pts.cpp
│ └── solve_5pts.h
│ ├── parameters.cpp
│ ├── parameters.h
│ └── utility
│ ├── CameraPoseVisualization.cpp
│ ├── CameraPoseVisualization.h
│ ├── tic_toc.h
│ ├── utility.cpp
│ ├── utility.h
│ ├── visualization.cpp
│ └── visualization.h
├── feature_tracker
├── CMakeLists.txt
├── cmake
│ └── FindEigen.cmake
├── package.xml
└── src
│ ├── feature_tracker.cpp
│ ├── feature_tracker.h
│ ├── feature_tracker_node.cpp
│ ├── parameters.cpp
│ ├── parameters.h
│ └── tic_toc.h
└── figures
└── system_snapshot.png
/README.md:
--------------------------------------------------------------------------------
1 | 相关原理推导,详见知乎:https://zhuanlan.zhihu.com/p/566273634
2 |
3 | # GVINS
4 |
5 | roslaunch gvins visensor_f9p.launch
6 | rviz -d /home/SLAM/GVINS/catkin_ws/src/GVINS/config/gvins_rviz_config.rviz
7 | rosbag play sports_field.bag
8 |
9 | GVINS: Tightly Coupled GNSS-Visual-Inertial Fusion for Smooth and Consistent State Estimation. [paper link](https://arxiv.org/pdf/2103.07899.pdf)
10 |
11 | Authors: Shaozu CAO, Xiuyuan LU and Shaojie SHEN
12 |
13 | 
14 |
15 | **GVINS** is a non-linear optimization based system that tightly fuses GNSS raw measurements with visual and inertial information for real-time and drift-free state estimation. By incorporating GNSS pseudorange and Doppler shift measurements, GVINS is capable to provide smooth and consistent 6-DoF global localization in complex environment. The system framework and VIO part are adapted from [VINS-Mono](https://github.com/HKUST-Aerial-Robotics/VINS-Mono). Our system contains the following features:
16 |
17 | - global 6-DoF estimation in ECEF frame;
18 | - multi-constellation support (GPS, GLONASS, Galileo, BeiDou);
19 | - online local-ENU frame alignment;
20 | - global pose recovery in GNSS-unfriendly or even GNSS-denied area.
21 |
22 | **Video:**
23 |
24 | [](https://www.youtube.com/watch?v=TebAal1ARnk "GVINS Video")
25 |
26 | ## 1. Prerequisites
27 | ### 1.1 C++11 Compiler
28 | This package requires some features of C++11.
29 |
30 | ### 1.2 ROS
31 | This package is developed under [ROS Kinetic](http://wiki.ros.org/kinetic) environment.
32 |
33 | ### 1.3 Eigen
34 | Our code uses [Eigen 3.3.3](https://gitlab.com/libeigen/eigen/-/archive/3.3.3/eigen-3.3.3.zip) for matrix manipulation.
35 |
36 | ### 1.4 Ceres
37 | We use [ceres](https://ceres-solver.googlesource.com/ceres-solver) 1.12.0 to solve the non-linear optimization problem.
38 |
39 | ### 1.5 gnss_comm
40 | This package also requires [gnss_comm](https://github.com/HKUST-Aerial-Robotics/gnss_comm) for ROS message definitions and some utility functions. Follow [those instructions](https://github.com/HKUST-Aerial-Robotics/gnss_comm#2-build-gnss_comm-library) to build the *gnss_comm* package.
41 |
42 | ## 2. Build GVINS
43 | Clone the repository to your catkin workspace (for example `~/catkin_ws/`):
44 | ```
45 | cd ~/catkin_ws/src/
46 | git clone https://github.com/HKUST-Aerial-Robotics/GVINS.git
47 | ```
48 | Then build the package with:
49 | ```
50 | cd ~/catkin_ws/
51 | catkin_make
52 | source ~/catkin_ws/devel/setup.bash
53 | ```
54 | If you encounter any problem during the building of GVINS, we recommend you to [try docker](#docker_section) first.
55 |
56 | ## 3. Docker Support
57 | To simplify the building process, we add docker in our code. Docker is like a sandbox so it can isolate our code from your local environment. To run with docker, first make sure [ros](http://wiki.ros.org/ROS/Installation) and [docker](https://docs.docker.com/get-docker/) are installed on your machine. Then add your account to `docker` group by `sudo usermod -aG docker $USER`. **Logout and re-login to avoid the *Permission denied* error**, then type:
58 | ```
59 | cd ~/catkin_ws/src/GVINS/docker
60 | make build
61 | ```
62 | The docker image `gvins:latest` should be successfully built after a while. Then you can run GVINS with:
63 | ```
64 | ./run.sh LAUNCH_FILE
65 | ```
66 | (for example `./run.sh visensor_f9p.launch`). Open another terminal and play your rosbag file, then you should be able to see the result. If you modify the code, simply re-run `./run.sh LAUNCH_FILE` to update.
67 |
68 |
69 | ## 4. Run GVINS with our dataset
70 | Download our [GVINS-Dataset](https://github.com/HKUST-Aerial-Robotics/GVINS-Dataset) and launch GVINS via:
71 | ```
72 | roslaunch gvins visensor_f9p.launch
73 | ```
74 | Open another terminal and launch the rviz by:
75 | ```
76 | rviz -d ~/catkin_ws/src/GVINS/config/gvins_rviz_config.rviz
77 | ```
78 | Then play the bag:
79 | ```
80 | rosbag play sports_field.bag
81 | ```
82 |
83 | ## 5. Run GVINS with your device
84 |
85 |
86 | 1. Setup the visual-inertial sensor suit according to [these instructions](https://github.com/HKUST-Aerial-Robotics/VINS-Mono#5-run-with-your-device);
87 | 2. Configure your GNSS receiver to output raw measurement and ephemeris and convert them as ros messages. If you are using u-blox receiver, please checkout our [ublox_driver](https://github.com/HKUST-Aerial-Robotics/ublox_driver) package;
88 | 3. Deal with the synchronization between visual-inertial sensor and GNSS receiver. A coarse synchronization can be done via [ublox_driver](https://github.com/HKUST-Aerial-Robotics/ublox_driver) but the accuracy is not guaranteed. For better performance, we recommend hardware synchronization via receiver's PPS signal;
89 | 4. Change the topic name in the config file and create a launch file pointing to the corresponding config file. Launch the GVINS with `roslaunch gvins YOUR_LAUNCH_FILE.launch`.
90 |
91 |
92 | ## 6. Acknowledgements
93 | The system framework and VIO part are adapted from [VINS-Mono](https://github.com/HKUST-Aerial-Robotics/VINS-Mono). We use [camodocal](https://github.com/hengli/camodocal) for camera modelling and [ceres](http://ceres-solver.org/) to solve the optimization problem.
94 |
95 | ## 7. Licence
96 | The source code is released under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) license.
97 | # GVINS_NotedByLSY
98 | # GVINS_Noted_ByLSY
99 | # GVINS_Noted_ByLSY
100 |
--------------------------------------------------------------------------------
/camera_model/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.3)
2 | project(gvins_camera_model)
3 |
4 | set(CMAKE_BUILD_TYPE "Release")
5 | set(CMAKE_CXX_FLAGS "-std=c++11")
6 | set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fPIC")
7 |
8 | find_package(catkin REQUIRED COMPONENTS
9 | roscpp
10 | std_msgs
11 | )
12 |
13 | find_package(Boost REQUIRED COMPONENTS filesystem program_options system)
14 | include_directories(${Boost_INCLUDE_DIRS})
15 |
16 | find_package(OpenCV REQUIRED)
17 |
18 | # set(EIGEN_INCLUDE_DIR "/usr/local/include/eigen3")
19 | find_package(Ceres REQUIRED)
20 | include_directories(${CERES_INCLUDE_DIRS})
21 |
22 |
23 | catkin_package(
24 | INCLUDE_DIRS include
25 | LIBRARIES gvins_camera_model
26 | CATKIN_DEPENDS roscpp std_msgs
27 | # DEPENDS system_lib
28 | )
29 |
30 | include_directories(
31 | ${catkin_INCLUDE_DIRS}
32 | )
33 |
34 | include_directories("include")
35 |
36 |
37 | add_executable(gvins_Calibration
38 | src/intrinsic_calib.cc
39 | src/chessboard/Chessboard.cc
40 | src/calib/CameraCalibration.cc
41 | src/camera_models/Camera.cc
42 | src/camera_models/CameraFactory.cc
43 | src/camera_models/CostFunctionFactory.cc
44 | src/camera_models/PinholeCamera.cc
45 | src/camera_models/CataCamera.cc
46 | src/camera_models/EquidistantCamera.cc
47 | src/camera_models/ScaramuzzaCamera.cc
48 | src/sparse_graph/Transform.cc
49 | src/gpl/gpl.cc
50 | src/gpl/EigenQuaternionParameterization.cc)
51 |
52 | add_library(gvins_camera_model
53 | src/chessboard/Chessboard.cc
54 | src/calib/CameraCalibration.cc
55 | src/camera_models/Camera.cc
56 | src/camera_models/CameraFactory.cc
57 | src/camera_models/CostFunctionFactory.cc
58 | src/camera_models/PinholeCamera.cc
59 | src/camera_models/CataCamera.cc
60 | src/camera_models/EquidistantCamera.cc
61 | src/camera_models/ScaramuzzaCamera.cc
62 | src/sparse_graph/Transform.cc
63 | src/gpl/gpl.cc
64 | src/gpl/EigenQuaternionParameterization.cc)
65 |
66 | target_link_libraries(gvins_Calibration ${Boost_LIBRARIES} ${OpenCV_LIBS} ${CERES_LIBRARIES})
67 | target_link_libraries(gvins_camera_model ${Boost_LIBRARIES} ${OpenCV_LIBS} ${CERES_LIBRARIES})
68 |
--------------------------------------------------------------------------------
/camera_model/cmake/FindEigen.cmake:
--------------------------------------------------------------------------------
1 | # Ceres Solver - A fast non-linear least squares minimizer
2 | # Copyright 2015 Google Inc. All rights reserved.
3 | # http://ceres-solver.org/
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions are met:
7 | #
8 | # * Redistributions of source code must retain the above copyright notice,
9 | # this list of conditions and the following disclaimer.
10 | # * Redistributions in binary form must reproduce the above copyright notice,
11 | # this list of conditions and the following disclaimer in the documentation
12 | # and/or other materials provided with the distribution.
13 | # * Neither the name of Google Inc. nor the names of its contributors may be
14 | # used to endorse or promote products derived from this software without
15 | # specific prior written permission.
16 | #
17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 | # POSSIBILITY OF SUCH DAMAGE.
28 | #
29 | # Author: alexs.mac@gmail.com (Alex Stewart)
30 | #
31 |
32 | # FindEigen.cmake - Find Eigen library, version >= 3.
33 | #
34 | # This module defines the following variables:
35 | #
36 | # EIGEN_FOUND: TRUE iff Eigen is found.
37 | # EIGEN_INCLUDE_DIRS: Include directories for Eigen.
38 | #
39 | # EIGEN_VERSION: Extracted from Eigen/src/Core/util/Macros.h
40 | # EIGEN_WORLD_VERSION: Equal to 3 if EIGEN_VERSION = 3.2.0
41 | # EIGEN_MAJOR_VERSION: Equal to 2 if EIGEN_VERSION = 3.2.0
42 | # EIGEN_MINOR_VERSION: Equal to 0 if EIGEN_VERSION = 3.2.0
43 | #
44 | # The following variables control the behaviour of this module:
45 | #
46 | # EIGEN_INCLUDE_DIR_HINTS: List of additional directories in which to
47 | # search for eigen includes, e.g: /timbuktu/eigen3.
48 | #
49 | # The following variables are also defined by this module, but in line with
50 | # CMake recommended FindPackage() module style should NOT be referenced directly
51 | # by callers (use the plural variables detailed above instead). These variables
52 | # do however affect the behaviour of the module via FIND_[PATH/LIBRARY]() which
53 | # are NOT re-called (i.e. search for library is not repeated) if these variables
54 | # are set with valid values _in the CMake cache_. This means that if these
55 | # variables are set directly in the cache, either by the user in the CMake GUI,
56 | # or by the user passing -DVAR=VALUE directives to CMake when called (which
57 | # explicitly defines a cache variable), then they will be used verbatim,
58 | # bypassing the HINTS variables and other hard-coded search locations.
59 | #
60 | # EIGEN_INCLUDE_DIR: Include directory for CXSparse, not including the
61 | # include directory of any dependencies.
62 |
63 | # Called if we failed to find Eigen or any of it's required dependencies,
64 | # unsets all public (designed to be used externally) variables and reports
65 | # error message at priority depending upon [REQUIRED/QUIET/] argument.
66 | macro(EIGEN_REPORT_NOT_FOUND REASON_MSG)
67 | unset(EIGEN_FOUND)
68 | unset(EIGEN_INCLUDE_DIRS)
69 | # Make results of search visible in the CMake GUI if Eigen has not
70 | # been found so that user does not have to toggle to advanced view.
71 | mark_as_advanced(CLEAR EIGEN_INCLUDE_DIR)
72 | # Note _FIND_[REQUIRED/QUIETLY] variables defined by FindPackage()
73 | # use the camelcase library name, not uppercase.
74 | if (Eigen_FIND_QUIETLY)
75 | message(STATUS "Failed to find Eigen - " ${REASON_MSG} ${ARGN})
76 | elseif (Eigen_FIND_REQUIRED)
77 | message(FATAL_ERROR "Failed to find Eigen - " ${REASON_MSG} ${ARGN})
78 | else()
79 | # Neither QUIETLY nor REQUIRED, use no priority which emits a message
80 | # but continues configuration and allows generation.
81 | message("-- Failed to find Eigen - " ${REASON_MSG} ${ARGN})
82 | endif ()
83 | return()
84 | endmacro(EIGEN_REPORT_NOT_FOUND)
85 |
86 | # Protect against any alternative find_package scripts for this library having
87 | # been called previously (in a client project) which set EIGEN_FOUND, but not
88 | # the other variables we require / set here which could cause the search logic
89 | # here to fail.
90 | unset(EIGEN_FOUND)
91 |
92 | # Search user-installed locations first, so that we prefer user installs
93 | # to system installs where both exist.
94 | list(APPEND EIGEN_CHECK_INCLUDE_DIRS
95 | /usr/local/include
96 | /usr/local/homebrew/include # Mac OS X
97 | /opt/local/var/macports/software # Mac OS X.
98 | /opt/local/include
99 | /usr/include)
100 | # Additional suffixes to try appending to each search path.
101 | list(APPEND EIGEN_CHECK_PATH_SUFFIXES
102 | eigen3 # Default root directory for Eigen.
103 | Eigen/include/eigen3 # Windows (for C:/Program Files prefix) < 3.3
104 | Eigen3/include/eigen3 ) # Windows (for C:/Program Files prefix) >= 3.3
105 |
106 | # Search supplied hint directories first if supplied.
107 | find_path(EIGEN_INCLUDE_DIR
108 | NAMES Eigen/Core
109 | PATHS ${EIGEN_INCLUDE_DIR_HINTS}
110 | ${EIGEN_CHECK_INCLUDE_DIRS}
111 | PATH_SUFFIXES ${EIGEN_CHECK_PATH_SUFFIXES})
112 |
113 | if (NOT EIGEN_INCLUDE_DIR OR
114 | NOT EXISTS ${EIGEN_INCLUDE_DIR})
115 | eigen_report_not_found(
116 | "Could not find eigen3 include directory, set EIGEN_INCLUDE_DIR to "
117 | "path to eigen3 include directory, e.g. /usr/local/include/eigen3.")
118 | endif (NOT EIGEN_INCLUDE_DIR OR
119 | NOT EXISTS ${EIGEN_INCLUDE_DIR})
120 |
121 | # Mark internally as found, then verify. EIGEN_REPORT_NOT_FOUND() unsets
122 | # if called.
123 | set(EIGEN_FOUND TRUE)
124 |
125 | # Extract Eigen version from Eigen/src/Core/util/Macros.h
126 | if (EIGEN_INCLUDE_DIR)
127 | set(EIGEN_VERSION_FILE ${EIGEN_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h)
128 | if (NOT EXISTS ${EIGEN_VERSION_FILE})
129 | eigen_report_not_found(
130 | "Could not find file: ${EIGEN_VERSION_FILE} "
131 | "containing version information in Eigen install located at: "
132 | "${EIGEN_INCLUDE_DIR}.")
133 | else (NOT EXISTS ${EIGEN_VERSION_FILE})
134 | file(READ ${EIGEN_VERSION_FILE} EIGEN_VERSION_FILE_CONTENTS)
135 |
136 | string(REGEX MATCH "#define EIGEN_WORLD_VERSION [0-9]+"
137 | EIGEN_WORLD_VERSION "${EIGEN_VERSION_FILE_CONTENTS}")
138 | string(REGEX REPLACE "#define EIGEN_WORLD_VERSION ([0-9]+)" "\\1"
139 | EIGEN_WORLD_VERSION "${EIGEN_WORLD_VERSION}")
140 |
141 | string(REGEX MATCH "#define EIGEN_MAJOR_VERSION [0-9]+"
142 | EIGEN_MAJOR_VERSION "${EIGEN_VERSION_FILE_CONTENTS}")
143 | string(REGEX REPLACE "#define EIGEN_MAJOR_VERSION ([0-9]+)" "\\1"
144 | EIGEN_MAJOR_VERSION "${EIGEN_MAJOR_VERSION}")
145 |
146 | string(REGEX MATCH "#define EIGEN_MINOR_VERSION [0-9]+"
147 | EIGEN_MINOR_VERSION "${EIGEN_VERSION_FILE_CONTENTS}")
148 | string(REGEX REPLACE "#define EIGEN_MINOR_VERSION ([0-9]+)" "\\1"
149 | EIGEN_MINOR_VERSION "${EIGEN_MINOR_VERSION}")
150 |
151 | # This is on a single line s/t CMake does not interpret it as a list of
152 | # elements and insert ';' separators which would result in 3.;2.;0 nonsense.
153 | set(EIGEN_VERSION "${EIGEN_WORLD_VERSION}.${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION}")
154 | endif (NOT EXISTS ${EIGEN_VERSION_FILE})
155 | endif (EIGEN_INCLUDE_DIR)
156 |
157 | # Set standard CMake FindPackage variables if found.
158 | if (EIGEN_FOUND)
159 | set(EIGEN_INCLUDE_DIRS ${EIGEN_INCLUDE_DIR})
160 | endif (EIGEN_FOUND)
161 |
162 | # Handle REQUIRED / QUIET optional arguments and version.
163 | include(FindPackageHandleStandardArgs)
164 | find_package_handle_standard_args(Eigen
165 | REQUIRED_VARS EIGEN_INCLUDE_DIRS
166 | VERSION_VAR EIGEN_VERSION)
167 |
168 | # Only mark internal variables as advanced if we found Eigen, otherwise
169 | # leave it visible in the standard GUI for the user to set manually.
170 | if (EIGEN_FOUND)
171 | mark_as_advanced(FORCE EIGEN_INCLUDE_DIR)
172 | endif (EIGEN_FOUND)
173 |
--------------------------------------------------------------------------------
/camera_model/include/camodocal/calib/CameraCalibration.h:
--------------------------------------------------------------------------------
1 | #ifndef CAMERACALIBRATION_H
2 | #define CAMERACALIBRATION_H
3 |
4 | #include
5 |
6 | #include "camodocal/camera_models/Camera.h"
7 |
8 | namespace camodocal
9 | {
10 |
11 | class CameraCalibration
12 | {
13 | public:
14 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW
15 | CameraCalibration();
16 |
17 | CameraCalibration(Camera::ModelType modelType,
18 | const std::string& cameraName,
19 | const cv::Size& imageSize,
20 | const cv::Size& boardSize,
21 | float squareSize);
22 |
23 | void clear(void);
24 |
25 | void addChessboardData(const std::vector& corners);
26 |
27 | bool calibrate(void);
28 |
29 | int sampleCount(void) const;
30 | std::vector >& imagePoints(void);
31 | const std::vector >& imagePoints(void) const;
32 | std::vector >& scenePoints(void);
33 | const std::vector >& scenePoints(void) const;
34 | CameraPtr& camera(void);
35 | const CameraConstPtr camera(void) const;
36 |
37 | Eigen::Matrix2d& measurementCovariance(void);
38 | const Eigen::Matrix2d& measurementCovariance(void) const;
39 |
40 | cv::Mat& cameraPoses(void);
41 | const cv::Mat& cameraPoses(void) const;
42 |
43 | void drawResults(std::vector& images) const;
44 |
45 | void writeParams(const std::string& filename) const;
46 |
47 | bool writeChessboardData(const std::string& filename) const;
48 | bool readChessboardData(const std::string& filename);
49 |
50 | void setVerbose(bool verbose);
51 |
52 | private:
53 | bool calibrateHelper(CameraPtr& camera,
54 | std::vector& rvecs, std::vector& tvecs) const;
55 |
56 | void optimize(CameraPtr& camera,
57 | std::vector& rvecs, std::vector& tvecs) const;
58 |
59 | template
60 | void readData(std::ifstream& ifs, T& data) const;
61 |
62 | template
63 | void writeData(std::ofstream& ofs, T data) const;
64 |
65 | cv::Size m_boardSize;
66 | float m_squareSize;
67 |
68 | CameraPtr m_camera;
69 | cv::Mat m_cameraPoses;
70 |
71 | std::vector > m_imagePoints;
72 | std::vector > m_scenePoints;
73 |
74 | Eigen::Matrix2d m_measurementCovariance;
75 |
76 | bool m_verbose;
77 | };
78 |
79 | }
80 |
81 | #endif
82 |
--------------------------------------------------------------------------------
/camera_model/include/camodocal/camera_models/Camera.h:
--------------------------------------------------------------------------------
1 | #ifndef CAMERA_H
2 | #define CAMERA_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | namespace camodocal
10 | {
11 |
12 | class Camera
13 | {
14 | public:
15 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW
16 | enum ModelType
17 | {
18 | KANNALA_BRANDT,
19 | MEI,
20 | PINHOLE,
21 | SCARAMUZZA
22 | };
23 |
24 | class Parameters
25 | {
26 | public:
27 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW
28 | Parameters(ModelType modelType);
29 |
30 | Parameters(ModelType modelType, const std::string& cameraName,
31 | int w, int h);
32 |
33 | ModelType& modelType(void);
34 | std::string& cameraName(void);
35 | int& imageWidth(void);
36 | int& imageHeight(void);
37 |
38 | ModelType modelType(void) const;
39 | const std::string& cameraName(void) const;
40 | int imageWidth(void) const;
41 | int imageHeight(void) const;
42 |
43 | int nIntrinsics(void) const;
44 |
45 | virtual bool readFromYamlFile(const std::string& filename) = 0;
46 | virtual void writeToYamlFile(const std::string& filename) const = 0;
47 |
48 | protected:
49 | ModelType m_modelType;
50 | int m_nIntrinsics;
51 | std::string m_cameraName;
52 | int m_imageWidth;
53 | int m_imageHeight;
54 | };
55 |
56 | virtual ModelType modelType(void) const = 0;
57 | virtual const std::string& cameraName(void) const = 0;
58 | virtual int imageWidth(void) const = 0;
59 | virtual int imageHeight(void) const = 0;
60 |
61 | virtual cv::Mat& mask(void);
62 | virtual const cv::Mat& mask(void) const;
63 |
64 | virtual void estimateIntrinsics(const cv::Size& boardSize,
65 | const std::vector< std::vector >& objectPoints,
66 | const std::vector< std::vector >& imagePoints) = 0;
67 | virtual void estimateExtrinsics(const std::vector& objectPoints,
68 | const std::vector& imagePoints,
69 | cv::Mat& rvec, cv::Mat& tvec) const;
70 |
71 | // Lift points from the image plane to the sphere
72 | virtual void liftSphere(const Eigen::Vector2d& p, Eigen::Vector3d& P) const = 0;
73 | //%output P
74 |
75 | // Lift points from the image plane to the projective space
76 | virtual void liftProjective(const Eigen::Vector2d& p, Eigen::Vector3d& P) const = 0;
77 | //%output P
78 |
79 | // Projects 3D points to the image plane (Pi function)
80 | virtual void spaceToPlane(const Eigen::Vector3d& P, Eigen::Vector2d& p) const = 0;
81 | //%output p
82 |
83 | // Projects 3D points to the image plane (Pi function)
84 | // and calculates jacobian
85 | //virtual void spaceToPlane(const Eigen::Vector3d& P, Eigen::Vector2d& p,
86 | // Eigen::Matrix& J) const = 0;
87 | //%output p
88 | //%output J
89 |
90 | virtual void undistToPlane(const Eigen::Vector2d& p_u, Eigen::Vector2d& p) const = 0;
91 | //%output p
92 |
93 | //virtual void initUndistortMap(cv::Mat& map1, cv::Mat& map2, double fScale = 1.0) const = 0;
94 | virtual cv::Mat initUndistortRectifyMap(cv::Mat& map1, cv::Mat& map2,
95 | float fx = -1.0f, float fy = -1.0f,
96 | cv::Size imageSize = cv::Size(0, 0),
97 | float cx = -1.0f, float cy = -1.0f,
98 | cv::Mat rmat = cv::Mat::eye(3, 3, CV_32F)) const = 0;
99 |
100 | virtual int parameterCount(void) const = 0;
101 |
102 | virtual void readParameters(const std::vector& parameters) = 0;
103 | virtual void writeParameters(std::vector& parameters) const = 0;
104 |
105 | virtual void writeParametersToYamlFile(const std::string& filename) const = 0;
106 |
107 | virtual std::string parametersToString(void) const = 0;
108 |
109 | /**
110 | * \brief Calculates the reprojection distance between points
111 | *
112 | * \param P1 first 3D point coordinates
113 | * \param P2 second 3D point coordinates
114 | * \return euclidean distance in the plane
115 | */
116 | double reprojectionDist(const Eigen::Vector3d& P1, const Eigen::Vector3d& P2) const;
117 |
118 | double reprojectionError(const std::vector< std::vector >& objectPoints,
119 | const std::vector< std::vector >& imagePoints,
120 | const std::vector& rvecs,
121 | const std::vector& tvecs,
122 | cv::OutputArray perViewErrors = cv::noArray()) const;
123 |
124 | double reprojectionError(const Eigen::Vector3d& P,
125 | const Eigen::Quaterniond& camera_q,
126 | const Eigen::Vector3d& camera_t,
127 | const Eigen::Vector2d& observed_p) const;
128 |
129 | void projectPoints(const std::vector& objectPoints,
130 | const cv::Mat& rvec,
131 | const cv::Mat& tvec,
132 | std::vector& imagePoints) const;
133 | protected:
134 | cv::Mat m_mask;
135 | };
136 |
137 | typedef boost::shared_ptr CameraPtr;
138 | typedef boost::shared_ptr CameraConstPtr;
139 |
140 | }
141 |
142 | #endif
143 |
--------------------------------------------------------------------------------
/camera_model/include/camodocal/camera_models/CameraFactory.h:
--------------------------------------------------------------------------------
1 | #ifndef CAMERAFACTORY_H
2 | #define CAMERAFACTORY_H
3 |
4 | #include
5 | #include
6 |
7 | #include "camodocal/camera_models/Camera.h"
8 |
9 | namespace camodocal
10 | {
11 |
12 | class CameraFactory
13 | {
14 | public:
15 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW
16 | CameraFactory();
17 |
18 | static boost::shared_ptr instance(void);
19 |
20 | CameraPtr generateCamera(Camera::ModelType modelType,
21 | const std::string& cameraName,
22 | cv::Size imageSize) const;
23 |
24 | CameraPtr generateCameraFromYamlFile(const std::string& filename);
25 |
26 | private:
27 | static boost::shared_ptr m_instance;
28 | };
29 |
30 | }
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/camera_model/include/camodocal/camera_models/CataCamera.h:
--------------------------------------------------------------------------------
1 | #ifndef CATACAMERA_H
2 | #define CATACAMERA_H
3 |
4 | #include
5 | #include
6 |
7 | #include "ceres/rotation.h"
8 | #include "Camera.h"
9 |
10 | namespace camodocal
11 | {
12 |
13 | /**
14 | * C. Mei, and P. Rives, Single View Point Omnidirectional Camera Calibration
15 | * from Planar Grids, ICRA 2007
16 | */
17 |
18 | class CataCamera: public Camera
19 | {
20 | public:
21 | class Parameters: public Camera::Parameters
22 | {
23 | public:
24 | Parameters();
25 | Parameters(const std::string& cameraName,
26 | int w, int h,
27 | double xi,
28 | double k1, double k2, double p1, double p2,
29 | double gamma1, double gamma2, double u0, double v0);
30 |
31 | double& xi(void);
32 | double& k1(void);
33 | double& k2(void);
34 | double& p1(void);
35 | double& p2(void);
36 | double& gamma1(void);
37 | double& gamma2(void);
38 | double& u0(void);
39 | double& v0(void);
40 |
41 | double xi(void) const;
42 | double k1(void) const;
43 | double k2(void) const;
44 | double p1(void) const;
45 | double p2(void) const;
46 | double gamma1(void) const;
47 | double gamma2(void) const;
48 | double u0(void) const;
49 | double v0(void) const;
50 |
51 | bool readFromYamlFile(const std::string& filename);
52 | void writeToYamlFile(const std::string& filename) const;
53 |
54 | Parameters& operator=(const Parameters& other);
55 | friend std::ostream& operator<< (std::ostream& out, const Parameters& params);
56 |
57 | private:
58 | double m_xi;
59 | double m_k1;
60 | double m_k2;
61 | double m_p1;
62 | double m_p2;
63 | double m_gamma1;
64 | double m_gamma2;
65 | double m_u0;
66 | double m_v0;
67 | };
68 |
69 | CataCamera();
70 |
71 | /**
72 | * \brief Constructor from the projection model parameters
73 | */
74 | CataCamera(const std::string& cameraName,
75 | int imageWidth, int imageHeight,
76 | double xi, double k1, double k2, double p1, double p2,
77 | double gamma1, double gamma2, double u0, double v0);
78 | /**
79 | * \brief Constructor from the projection model parameters
80 | */
81 | CataCamera(const Parameters& params);
82 |
83 | Camera::ModelType modelType(void) const;
84 | const std::string& cameraName(void) const;
85 | int imageWidth(void) const;
86 | int imageHeight(void) const;
87 |
88 | void estimateIntrinsics(const cv::Size& boardSize,
89 | const std::vector< std::vector >& objectPoints,
90 | const std::vector< std::vector >& imagePoints);
91 |
92 | // Lift points from the image plane to the sphere
93 | void liftSphere(const Eigen::Vector2d& p, Eigen::Vector3d& P) const;
94 | //%output P
95 |
96 | // Lift points from the image plane to the projective space
97 | void liftProjective(const Eigen::Vector2d& p, Eigen::Vector3d& P) const;
98 | //%output P
99 |
100 | // Projects 3D points to the image plane (Pi function)
101 | void spaceToPlane(const Eigen::Vector3d& P, Eigen::Vector2d& p) const;
102 | //%output p
103 |
104 | // Projects 3D points to the image plane (Pi function)
105 | // and calculates jacobian
106 | void spaceToPlane(const Eigen::Vector3d& P, Eigen::Vector2d& p,
107 | Eigen::Matrix& J) const;
108 | //%output p
109 | //%output J
110 |
111 | void undistToPlane(const Eigen::Vector2d& p_u, Eigen::Vector2d& p) const;
112 | //%output p
113 |
114 | template
115 | static void spaceToPlane(const T* const params,
116 | const T* const q, const T* const t,
117 | const Eigen::Matrix& P,
118 | Eigen::Matrix& p);
119 |
120 | void distortion(const Eigen::Vector2d& p_u, Eigen::Vector2d& d_u) const;
121 | void distortion(const Eigen::Vector2d& p_u, Eigen::Vector2d& d_u,
122 | Eigen::Matrix2d& J) const;
123 |
124 | void initUndistortMap(cv::Mat& map1, cv::Mat& map2, double fScale = 1.0) const;
125 | cv::Mat initUndistortRectifyMap(cv::Mat& map1, cv::Mat& map2,
126 | float fx = -1.0f, float fy = -1.0f,
127 | cv::Size imageSize = cv::Size(0, 0),
128 | float cx = -1.0f, float cy = -1.0f,
129 | cv::Mat rmat = cv::Mat::eye(3, 3, CV_32F)) const;
130 |
131 | int parameterCount(void) const;
132 |
133 | const Parameters& getParameters(void) const;
134 | void setParameters(const Parameters& parameters);
135 |
136 | void readParameters(const std::vector& parameterVec);
137 | void writeParameters(std::vector& parameterVec) const;
138 |
139 | void writeParametersToYamlFile(const std::string& filename) const;
140 |
141 | std::string parametersToString(void) const;
142 |
143 | private:
144 | Parameters mParameters;
145 |
146 | double m_inv_K11, m_inv_K13, m_inv_K22, m_inv_K23;
147 | bool m_noDistortion;
148 | };
149 |
150 | typedef boost::shared_ptr CataCameraPtr;
151 | typedef boost::shared_ptr CataCameraConstPtr;
152 |
153 | template
154 | void
155 | CataCamera::spaceToPlane(const T* const params,
156 | const T* const q, const T* const t,
157 | const Eigen::Matrix& P,
158 | Eigen::Matrix& p)
159 | {
160 | T P_w[3];
161 | P_w[0] = T(P(0));
162 | P_w[1] = T(P(1));
163 | P_w[2] = T(P(2));
164 |
165 | // Convert quaternion from Eigen convention (x, y, z, w)
166 | // to Ceres convention (w, x, y, z)
167 | T q_ceres[4] = {q[3], q[0], q[1], q[2]};
168 |
169 | T P_c[3];
170 | ceres::QuaternionRotatePoint(q_ceres, P_w, P_c);
171 |
172 | P_c[0] += t[0];
173 | P_c[1] += t[1];
174 | P_c[2] += t[2];
175 |
176 | // project 3D object point to the image plane
177 | T xi = params[0];
178 | T k1 = params[1];
179 | T k2 = params[2];
180 | T p1 = params[3];
181 | T p2 = params[4];
182 | T gamma1 = params[5];
183 | T gamma2 = params[6];
184 | T alpha = T(0); //cameraParams.alpha();
185 | T u0 = params[7];
186 | T v0 = params[8];
187 |
188 | // Transform to model plane
189 | T len = sqrt(P_c[0] * P_c[0] + P_c[1] * P_c[1] + P_c[2] * P_c[2]);
190 | P_c[0] /= len;
191 | P_c[1] /= len;
192 | P_c[2] /= len;
193 |
194 | T u = P_c[0] / (P_c[2] + xi);
195 | T v = P_c[1] / (P_c[2] + xi);
196 |
197 | T rho_sqr = u * u + v * v;
198 | T L = T(1.0) + k1 * rho_sqr + k2 * rho_sqr * rho_sqr;
199 | T du = T(2.0) * p1 * u * v + p2 * (rho_sqr + T(2.0) * u * u);
200 | T dv = p1 * (rho_sqr + T(2.0) * v * v) + T(2.0) * p2 * u * v;
201 |
202 | u = L * u + du;
203 | v = L * v + dv;
204 | p(0) = gamma1 * (u + alpha * v) + u0;
205 | p(1) = gamma2 * v + v0;
206 | }
207 |
208 | }
209 |
210 | #endif
211 |
--------------------------------------------------------------------------------
/camera_model/include/camodocal/camera_models/CostFunctionFactory.h:
--------------------------------------------------------------------------------
1 | #ifndef COSTFUNCTIONFACTORY_H
2 | #define COSTFUNCTIONFACTORY_H
3 |
4 | #include
5 | #include
6 |
7 | #include "camodocal/camera_models/Camera.h"
8 |
9 | namespace ceres
10 | {
11 | class CostFunction;
12 | }
13 |
14 | namespace camodocal
15 | {
16 |
17 | enum
18 | {
19 | CAMERA_INTRINSICS = 1 << 0,
20 | CAMERA_POSE = 1 << 1,
21 | POINT_3D = 1 << 2,
22 | ODOMETRY_INTRINSICS = 1 << 3,
23 | ODOMETRY_3D_POSE = 1 << 4,
24 | ODOMETRY_6D_POSE = 1 << 5,
25 | CAMERA_ODOMETRY_TRANSFORM = 1 << 6
26 | };
27 |
28 | class CostFunctionFactory
29 | {
30 | public:
31 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW
32 | CostFunctionFactory();
33 |
34 | static boost::shared_ptr instance(void);
35 |
36 | ceres::CostFunction* generateCostFunction(const CameraConstPtr& camera,
37 | const Eigen::Vector3d& observed_P,
38 | const Eigen::Vector2d& observed_p,
39 | int flags) const;
40 |
41 | ceres::CostFunction* generateCostFunction(const CameraConstPtr& camera,
42 | const Eigen::Vector3d& observed_P,
43 | const Eigen::Vector2d& observed_p,
44 | const Eigen::Matrix2d& sqrtPrecisionMat,
45 | int flags) const;
46 |
47 | ceres::CostFunction* generateCostFunction(const CameraConstPtr& camera,
48 | const Eigen::Vector2d& observed_p,
49 | int flags, bool optimize_cam_odo_z = true) const;
50 |
51 | ceres::CostFunction* generateCostFunction(const CameraConstPtr& camera,
52 | const Eigen::Vector2d& observed_p,
53 | const Eigen::Matrix2d& sqrtPrecisionMat,
54 | int flags, bool optimize_cam_odo_z = true) const;
55 |
56 | ceres::CostFunction* generateCostFunction(const CameraConstPtr& camera,
57 | const Eigen::Vector3d& odo_pos,
58 | const Eigen::Vector3d& odo_att,
59 | const Eigen::Vector2d& observed_p,
60 | int flags, bool optimize_cam_odo_z = true) const;
61 |
62 | ceres::CostFunction* generateCostFunction(const CameraConstPtr& camera,
63 | const Eigen::Quaterniond& cam_odo_q,
64 | const Eigen::Vector3d& cam_odo_t,
65 | const Eigen::Vector3d& odo_pos,
66 | const Eigen::Vector3d& odo_att,
67 | const Eigen::Vector2d& observed_p,
68 | int flags) const;
69 |
70 | ceres::CostFunction* generateCostFunction(const CameraConstPtr& cameraLeft,
71 | const CameraConstPtr& cameraRight,
72 | const Eigen::Vector3d& observed_P,
73 | const Eigen::Vector2d& observed_p_left,
74 | const Eigen::Vector2d& observed_p_right) const;
75 |
76 | private:
77 | static boost::shared_ptr m_instance;
78 | };
79 |
80 | }
81 |
82 | #endif
83 |
--------------------------------------------------------------------------------
/camera_model/include/camodocal/camera_models/EquidistantCamera.h:
--------------------------------------------------------------------------------
1 | #ifndef EQUIDISTANTCAMERA_H
2 | #define EQUIDISTANTCAMERA_H
3 |
4 | #include
5 | #include
6 |
7 | #include "ceres/rotation.h"
8 | #include "Camera.h"
9 |
10 | namespace camodocal
11 | {
12 |
13 | /**
14 | * J. Kannala, and S. Brandt, A Generic Camera Model and Calibration Method
15 | * for Conventional, Wide-Angle, and Fish-Eye Lenses, PAMI 2006
16 | */
17 |
18 | class EquidistantCamera: public Camera
19 | {
20 | public:
21 | class Parameters: public Camera::Parameters
22 | {
23 | public:
24 | Parameters();
25 | Parameters(const std::string& cameraName,
26 | int w, int h,
27 | double k2, double k3, double k4, double k5,
28 | double mu, double mv,
29 | double u0, double v0);
30 |
31 | double& k2(void);
32 | double& k3(void);
33 | double& k4(void);
34 | double& k5(void);
35 | double& mu(void);
36 | double& mv(void);
37 | double& u0(void);
38 | double& v0(void);
39 |
40 | double k2(void) const;
41 | double k3(void) const;
42 | double k4(void) const;
43 | double k5(void) const;
44 | double mu(void) const;
45 | double mv(void) const;
46 | double u0(void) const;
47 | double v0(void) const;
48 |
49 | bool readFromYamlFile(const std::string& filename);
50 | void writeToYamlFile(const std::string& filename) const;
51 |
52 | Parameters& operator=(const Parameters& other);
53 | friend std::ostream& operator<< (std::ostream& out, const Parameters& params);
54 |
55 | private:
56 | // projection
57 | double m_k2;
58 | double m_k3;
59 | double m_k4;
60 | double m_k5;
61 |
62 | double m_mu;
63 | double m_mv;
64 | double m_u0;
65 | double m_v0;
66 | };
67 |
68 | EquidistantCamera();
69 |
70 | /**
71 | * \brief Constructor from the projection model parameters
72 | */
73 | EquidistantCamera(const std::string& cameraName,
74 | int imageWidth, int imageHeight,
75 | double k2, double k3, double k4, double k5,
76 | double mu, double mv,
77 | double u0, double v0);
78 | /**
79 | * \brief Constructor from the projection model parameters
80 | */
81 | EquidistantCamera(const Parameters& params);
82 |
83 | Camera::ModelType modelType(void) const;
84 | const std::string& cameraName(void) const;
85 | int imageWidth(void) const;
86 | int imageHeight(void) const;
87 |
88 | void estimateIntrinsics(const cv::Size& boardSize,
89 | const std::vector< std::vector >& objectPoints,
90 | const std::vector< std::vector >& imagePoints);
91 |
92 | // Lift points from the image plane to the sphere
93 | virtual void liftSphere(const Eigen::Vector2d& p, Eigen::Vector3d& P) const;
94 | //%output P
95 |
96 | // Lift points from the image plane to the projective space
97 | void liftProjective(const Eigen::Vector2d& p, Eigen::Vector3d& P) const;
98 | //%output P
99 |
100 | // Projects 3D points to the image plane (Pi function)
101 | void spaceToPlane(const Eigen::Vector3d& P, Eigen::Vector2d& p) const;
102 | //%output p
103 |
104 | // Projects 3D points to the image plane (Pi function)
105 | // and calculates jacobian
106 | void spaceToPlane(const Eigen::Vector3d& P, Eigen::Vector2d& p,
107 | Eigen::Matrix& J) const;
108 | //%output p
109 | //%output J
110 |
111 | void undistToPlane(const Eigen::Vector2d& p_u, Eigen::Vector2d& p) const;
112 | //%output p
113 |
114 | template
115 | static void spaceToPlane(const T* const params,
116 | const T* const q, const T* const t,
117 | const Eigen::Matrix& P,
118 | Eigen::Matrix& p);
119 |
120 | void initUndistortMap(cv::Mat& map1, cv::Mat& map2, double fScale = 1.0) const;
121 | cv::Mat initUndistortRectifyMap(cv::Mat& map1, cv::Mat& map2,
122 | float fx = -1.0f, float fy = -1.0f,
123 | cv::Size imageSize = cv::Size(0, 0),
124 | float cx = -1.0f, float cy = -1.0f,
125 | cv::Mat rmat = cv::Mat::eye(3, 3, CV_32F)) const;
126 |
127 | int parameterCount(void) const;
128 |
129 | const Parameters& getParameters(void) const;
130 | void setParameters(const Parameters& parameters);
131 |
132 | void readParameters(const std::vector& parameterVec);
133 | void writeParameters(std::vector& parameterVec) const;
134 |
135 | void writeParametersToYamlFile(const std::string& filename) const;
136 |
137 | std::string parametersToString(void) const;
138 |
139 | private:
140 | template
141 | static T r(T k2, T k3, T k4, T k5, T theta);
142 |
143 |
144 | void fitOddPoly(const std::vector& x, const std::vector& y,
145 | int n, std::vector& coeffs) const;
146 |
147 | void backprojectSymmetric(const Eigen::Vector2d& p_u,
148 | double& theta, double& phi) const;
149 |
150 | Parameters mParameters;
151 |
152 | double m_inv_K11, m_inv_K13, m_inv_K22, m_inv_K23;
153 | };
154 |
155 | typedef boost::shared_ptr EquidistantCameraPtr;
156 | typedef boost::shared_ptr EquidistantCameraConstPtr;
157 |
158 | template
159 | T
160 | EquidistantCamera::r(T k2, T k3, T k4, T k5, T theta)
161 | {
162 | // k1 = 1
163 | return theta +
164 | k2 * theta * theta * theta +
165 | k3 * theta * theta * theta * theta * theta +
166 | k4 * theta * theta * theta * theta * theta * theta * theta +
167 | k5 * theta * theta * theta * theta * theta * theta * theta * theta * theta;
168 | }
169 |
170 | template
171 | void
172 | EquidistantCamera::spaceToPlane(const T* const params,
173 | const T* const q, const T* const t,
174 | const Eigen::Matrix& P,
175 | Eigen::Matrix& p)
176 | {
177 | T P_w[3];
178 | P_w[0] = T(P(0));
179 | P_w[1] = T(P(1));
180 | P_w[2] = T(P(2));
181 |
182 | // Convert quaternion from Eigen convention (x, y, z, w)
183 | // to Ceres convention (w, x, y, z)
184 | T q_ceres[4] = {q[3], q[0], q[1], q[2]};
185 |
186 | T P_c[3];
187 | ceres::QuaternionRotatePoint(q_ceres, P_w, P_c);
188 |
189 | P_c[0] += t[0];
190 | P_c[1] += t[1];
191 | P_c[2] += t[2];
192 |
193 | // project 3D object point to the image plane;
194 | T k2 = params[0];
195 | T k3 = params[1];
196 | T k4 = params[2];
197 | T k5 = params[3];
198 | T mu = params[4];
199 | T mv = params[5];
200 | T u0 = params[6];
201 | T v0 = params[7];
202 |
203 | T len = sqrt(P_c[0] * P_c[0] + P_c[1] * P_c[1] + P_c[2] * P_c[2]);
204 | T theta = acos(P_c[2] / len);
205 | T phi = atan2(P_c[1], P_c[0]);
206 |
207 | Eigen::Matrix p_u = r(k2, k3, k4, k5, theta) * Eigen::Matrix(cos(phi), sin(phi));
208 |
209 | p(0) = mu * p_u(0) + u0;
210 | p(1) = mv * p_u(1) + v0;
211 | }
212 |
213 | }
214 |
215 | #endif
216 |
--------------------------------------------------------------------------------
/camera_model/include/camodocal/camera_models/PinholeCamera.h:
--------------------------------------------------------------------------------
1 | #ifndef PINHOLECAMERA_H
2 | #define PINHOLECAMERA_H
3 |
4 | #include
5 | #include
6 |
7 | #include "ceres/rotation.h"
8 | #include "Camera.h"
9 |
10 | namespace camodocal
11 | {
12 |
13 | class PinholeCamera: public Camera
14 | {
15 | public:
16 | class Parameters: public Camera::Parameters
17 | {
18 | public:
19 | Parameters();
20 | Parameters(const std::string& cameraName,
21 | int w, int h,
22 | double k1, double k2, double p1, double p2,
23 | double fx, double fy, double cx, double cy);
24 |
25 | double& k1(void);
26 | double& k2(void);
27 | double& p1(void);
28 | double& p2(void);
29 | double& fx(void);
30 | double& fy(void);
31 | double& cx(void);
32 | double& cy(void);
33 |
34 | double xi(void) const;
35 | double k1(void) const;
36 | double k2(void) const;
37 | double p1(void) const;
38 | double p2(void) const;
39 | double fx(void) const;
40 | double fy(void) const;
41 | double cx(void) const;
42 | double cy(void) const;
43 |
44 | bool readFromYamlFile(const std::string& filename);
45 | void writeToYamlFile(const std::string& filename) const;
46 |
47 | Parameters& operator=(const Parameters& other);
48 | friend std::ostream& operator<< (std::ostream& out, const Parameters& params);
49 |
50 | private:
51 | double m_k1;
52 | double m_k2;
53 | double m_p1;
54 | double m_p2;
55 | double m_fx;
56 | double m_fy;
57 | double m_cx;
58 | double m_cy;
59 | };
60 |
61 | PinholeCamera();
62 |
63 | /**
64 | * \brief Constructor from the projection model parameters
65 | */
66 | PinholeCamera(const std::string& cameraName,
67 | int imageWidth, int imageHeight,
68 | double k1, double k2, double p1, double p2,
69 | double fx, double fy, double cx, double cy);
70 | /**
71 | * \brief Constructor from the projection model parameters
72 | */
73 | PinholeCamera(const Parameters& params);
74 |
75 | Camera::ModelType modelType(void) const;
76 | const std::string& cameraName(void) const;
77 | int imageWidth(void) const;
78 | int imageHeight(void) const;
79 |
80 | void estimateIntrinsics(const cv::Size& boardSize,
81 | const std::vector< std::vector >& objectPoints,
82 | const std::vector< std::vector >& imagePoints);
83 |
84 | // Lift points from the image plane to the sphere
85 | virtual void liftSphere(const Eigen::Vector2d& p, Eigen::Vector3d& P) const;
86 | //%output P
87 |
88 | // Lift points from the image plane to the projective space
89 | void liftProjective(const Eigen::Vector2d& p, Eigen::Vector3d& P) const;
90 | //%output P
91 |
92 | // Projects 3D points to the image plane (Pi function)
93 | void spaceToPlane(const Eigen::Vector3d& P, Eigen::Vector2d& p) const;
94 | //%output p
95 |
96 | // Projects 3D points to the image plane (Pi function)
97 | // and calculates jacobian
98 | void spaceToPlane(const Eigen::Vector3d& P, Eigen::Vector2d& p,
99 | Eigen::Matrix& J) const;
100 | //%output p
101 | //%output J
102 |
103 | void undistToPlane(const Eigen::Vector2d& p_u, Eigen::Vector2d& p) const;
104 | //%output p
105 |
106 | template
107 | static void spaceToPlane(const T* const params,
108 | const T* const q, const T* const t,
109 | const Eigen::Matrix& P,
110 | Eigen::Matrix& p);
111 |
112 | void distortion(const Eigen::Vector2d& p_u, Eigen::Vector2d& d_u) const;
113 | void distortion(const Eigen::Vector2d& p_u, Eigen::Vector2d& d_u,
114 | Eigen::Matrix2d& J) const;
115 |
116 | void initUndistortMap(cv::Mat& map1, cv::Mat& map2, double fScale = 1.0) const;
117 | cv::Mat initUndistortRectifyMap(cv::Mat& map1, cv::Mat& map2,
118 | float fx = -1.0f, float fy = -1.0f,
119 | cv::Size imageSize = cv::Size(0, 0),
120 | float cx = -1.0f, float cy = -1.0f,
121 | cv::Mat rmat = cv::Mat::eye(3, 3, CV_32F)) const;
122 |
123 | int parameterCount(void) const;
124 |
125 | const Parameters& getParameters(void) const;
126 | void setParameters(const Parameters& parameters);
127 |
128 | void readParameters(const std::vector& parameterVec);
129 | void writeParameters(std::vector& parameterVec) const;
130 |
131 | void writeParametersToYamlFile(const std::string& filename) const;
132 |
133 | std::string parametersToString(void) const;
134 |
135 | private:
136 | Parameters mParameters;
137 |
138 | double m_inv_K11, m_inv_K13, m_inv_K22, m_inv_K23;
139 | bool m_noDistortion;
140 | };
141 |
142 | typedef boost::shared_ptr PinholeCameraPtr;
143 | typedef boost::shared_ptr PinholeCameraConstPtr;
144 |
145 | template
146 | void
147 | PinholeCamera::spaceToPlane(const T* const params,
148 | const T* const q, const T* const t,
149 | const Eigen::Matrix& P,
150 | Eigen::Matrix& p)
151 | {
152 | T P_w[3];
153 | P_w[0] = T(P(0));
154 | P_w[1] = T(P(1));
155 | P_w[2] = T(P(2));
156 |
157 | // Convert quaternion from Eigen convention (x, y, z, w)
158 | // to Ceres convention (w, x, y, z)
159 | T q_ceres[4] = {q[3], q[0], q[1], q[2]};
160 |
161 | T P_c[3];
162 | ceres::QuaternionRotatePoint(q_ceres, P_w, P_c);
163 |
164 | P_c[0] += t[0];
165 | P_c[1] += t[1];
166 | P_c[2] += t[2];
167 |
168 | // project 3D object point to the image plane
169 | T k1 = params[0];
170 | T k2 = params[1];
171 | T p1 = params[2];
172 | T p2 = params[3];
173 | T fx = params[4];
174 | T fy = params[5];
175 | T alpha = T(0); //cameraParams.alpha();
176 | T cx = params[6];
177 | T cy = params[7];
178 |
179 | // Transform to model plane
180 | T u = P_c[0] / P_c[2];
181 | T v = P_c[1] / P_c[2];
182 |
183 | T rho_sqr = u * u + v * v;
184 | T L = T(1.0) + k1 * rho_sqr + k2 * rho_sqr * rho_sqr;
185 | T du = T(2.0) * p1 * u * v + p2 * (rho_sqr + T(2.0) * u * u);
186 | T dv = p1 * (rho_sqr + T(2.0) * v * v) + T(2.0) * p2 * u * v;
187 |
188 | u = L * u + du;
189 | v = L * v + dv;
190 | p(0) = fx * (u + alpha * v) + cx;
191 | p(1) = fy * v + cy;
192 | }
193 |
194 | }
195 |
196 | #endif
197 |
--------------------------------------------------------------------------------
/camera_model/include/camodocal/chessboard/Chessboard.h:
--------------------------------------------------------------------------------
1 | #ifndef CHESSBOARD_H
2 | #define CHESSBOARD_H
3 |
4 | #include
5 | #include
6 |
7 | namespace camodocal
8 | {
9 |
10 | // forward declarations
11 | class ChessboardCorner;
12 | typedef boost::shared_ptr ChessboardCornerPtr;
13 | class ChessboardQuad;
14 | typedef boost::shared_ptr ChessboardQuadPtr;
15 |
16 | class Chessboard
17 | {
18 | public:
19 | Chessboard(cv::Size boardSize, cv::Mat& image);
20 |
21 | void findCorners(bool useOpenCV = false);
22 | const std::vector& getCorners(void) const;
23 | bool cornersFound(void) const;
24 |
25 | const cv::Mat& getImage(void) const;
26 | const cv::Mat& getSketch(void) const;
27 |
28 | private:
29 | bool findChessboardCorners(const cv::Mat& image,
30 | const cv::Size& patternSize,
31 | std::vector& corners,
32 | int flags, bool useOpenCV);
33 |
34 | bool findChessboardCornersImproved(const cv::Mat& image,
35 | const cv::Size& patternSize,
36 | std::vector& corners,
37 | int flags);
38 |
39 | void cleanFoundConnectedQuads(std::vector& quadGroup, cv::Size patternSize);
40 |
41 | void findConnectedQuads(std::vector& quads,
42 | std::vector& group,
43 | int group_idx, int dilation);
44 |
45 | // int checkQuadGroup(std::vector& quadGroup,
46 | // std::vector& outCorners,
47 | // cv::Size patternSize);
48 |
49 | void labelQuadGroup(std::vector& quad_group,
50 | cv::Size patternSize, bool firstRun);
51 |
52 | void findQuadNeighbors(std::vector& quads, int dilation);
53 |
54 | int augmentBestRun(std::vector& candidateQuads, int candidateDilation,
55 | std::vector& existingQuads, int existingDilation);
56 |
57 | void generateQuads(std::vector& quads,
58 | cv::Mat& image, int flags,
59 | int dilation, bool firstRun);
60 |
61 | bool checkQuadGroup(std::vector& quads,
62 | std::vector& corners,
63 | cv::Size patternSize);
64 |
65 | void getQuadrangleHypotheses(const std::vector< std::vector >& contours,
66 | std::vector< std::pair >& quads,
67 | int classId) const;
68 |
69 | bool checkChessboard(const cv::Mat& image, cv::Size patternSize) const;
70 |
71 | bool checkBoardMonotony(std::vector& corners,
72 | cv::Size patternSize);
73 |
74 | bool matchCorners(ChessboardQuadPtr& quad1, int corner1,
75 | ChessboardQuadPtr& quad2, int corner2) const;
76 |
77 | cv::Mat mImage;
78 | cv::Mat mSketch;
79 | std::vector mCorners;
80 | cv::Size mBoardSize;
81 | bool mCornersFound;
82 | };
83 |
84 | }
85 |
86 | #endif
87 |
--------------------------------------------------------------------------------
/camera_model/include/camodocal/chessboard/ChessboardCorner.h:
--------------------------------------------------------------------------------
1 | #ifndef CHESSBOARDCORNER_H
2 | #define CHESSBOARDCORNER_H
3 |
4 | #include
5 | #include
6 |
7 | namespace camodocal
8 | {
9 |
10 | class ChessboardCorner;
11 | typedef boost::shared_ptr ChessboardCornerPtr;
12 |
13 | class ChessboardCorner
14 | {
15 | public:
16 | ChessboardCorner() : row(0), column(0), needsNeighbor(true), count(0) {}
17 |
18 | float meanDist(int &n) const
19 | {
20 | float sum = 0;
21 | n = 0;
22 | for (int i = 0; i < 4; ++i)
23 | {
24 | if (neighbors[i].get())
25 | {
26 | float dx = neighbors[i]->pt.x - pt.x;
27 | float dy = neighbors[i]->pt.y - pt.y;
28 | sum += sqrt(dx*dx + dy*dy);
29 | n++;
30 | }
31 | }
32 | return sum / std::max(n, 1);
33 | }
34 |
35 | cv::Point2f pt; // X and y coordinates
36 | int row; // Row and column of the corner
37 | int column; // in the found pattern
38 | bool needsNeighbor; // Does the corner require a neighbor?
39 | int count; // number of corner neighbors
40 | ChessboardCornerPtr neighbors[4]; // pointer to all corner neighbors
41 | };
42 |
43 | }
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/camera_model/include/camodocal/chessboard/ChessboardQuad.h:
--------------------------------------------------------------------------------
1 | #ifndef CHESSBOARDQUAD_H
2 | #define CHESSBOARDQUAD_H
3 |
4 | #include
5 |
6 | #include "camodocal/chessboard/ChessboardCorner.h"
7 |
8 | namespace camodocal
9 | {
10 |
11 | class ChessboardQuad;
12 | typedef boost::shared_ptr ChessboardQuadPtr;
13 |
14 | class ChessboardQuad
15 | {
16 | public:
17 | ChessboardQuad() : count(0), group_idx(-1), edge_len(FLT_MAX), labeled(false) {}
18 |
19 | int count; // Number of quad neighbors
20 | int group_idx; // Quad group ID
21 | float edge_len; // Smallest side length^2
22 | ChessboardCornerPtr corners[4]; // Coordinates of quad corners
23 | ChessboardQuadPtr neighbors[4]; // Pointers of quad neighbors
24 | bool labeled; // Has this corner been labeled?
25 | };
26 |
27 | }
28 |
29 | #endif
30 |
--------------------------------------------------------------------------------
/camera_model/include/camodocal/gpl/EigenQuaternionParameterization.h:
--------------------------------------------------------------------------------
1 | #ifndef EIGENQUATERNIONPARAMETERIZATION_H
2 | #define EIGENQUATERNIONPARAMETERIZATION_H
3 |
4 | #include "ceres/local_parameterization.h"
5 |
6 | namespace camodocal
7 | {
8 |
9 | class EigenQuaternionParameterization : public ceres::LocalParameterization
10 | {
11 | public:
12 | virtual ~EigenQuaternionParameterization() {}
13 | virtual bool Plus(const double* x,
14 | const double* delta,
15 | double* x_plus_delta) const;
16 | virtual bool ComputeJacobian(const double* x,
17 | double* jacobian) const;
18 | virtual int GlobalSize() const { return 4; }
19 | virtual int LocalSize() const { return 3; }
20 |
21 | private:
22 | template
23 | void EigenQuaternionProduct(const T z[4], const T w[4], T zw[4]) const;
24 | };
25 |
26 |
27 | template
28 | void
29 | EigenQuaternionParameterization::EigenQuaternionProduct(const T z[4], const T w[4], T zw[4]) const
30 | {
31 | zw[0] = z[3] * w[0] + z[0] * w[3] + z[1] * w[2] - z[2] * w[1];
32 | zw[1] = z[3] * w[1] - z[0] * w[2] + z[1] * w[3] + z[2] * w[0];
33 | zw[2] = z[3] * w[2] + z[0] * w[1] - z[1] * w[0] + z[2] * w[3];
34 | zw[3] = z[3] * w[3] - z[0] * w[0] - z[1] * w[1] - z[2] * w[2];
35 | }
36 |
37 | }
38 |
39 | #endif
40 |
41 |
--------------------------------------------------------------------------------
/camera_model/include/camodocal/gpl/gpl.h:
--------------------------------------------------------------------------------
1 | #ifndef GPL_H
2 | #define GPL_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | namespace camodocal
9 | {
10 |
11 | template
12 | const T clamp(const T& v, const T& a, const T& b)
13 | {
14 | return std::min(b, std::max(a, v));
15 | }
16 |
17 | double hypot3(double x, double y, double z);
18 | float hypot3f(float x, float y, float z);
19 |
20 | template
21 | const T normalizeTheta(const T& theta)
22 | {
23 | T normTheta = theta;
24 |
25 | while (normTheta < - M_PI)
26 | {
27 | normTheta += 2.0 * M_PI;
28 | }
29 | while (normTheta > M_PI)
30 | {
31 | normTheta -= 2.0 * M_PI;
32 | }
33 |
34 | return normTheta;
35 | }
36 |
37 | double d2r(double deg);
38 | float d2r(float deg);
39 | double r2d(double rad);
40 | float r2d(float rad);
41 |
42 | double sinc(double theta);
43 |
44 | template
45 | const T square(const T& x)
46 | {
47 | return x * x;
48 | }
49 |
50 | template
51 | const T cube(const T& x)
52 | {
53 | return x * x * x;
54 | }
55 |
56 | template
57 | const T random(const T& a, const T& b)
58 | {
59 | return static_cast(rand()) / RAND_MAX * (b - a) + a;
60 | }
61 |
62 | template
63 | const T randomNormal(const T& sigma)
64 | {
65 | T x1, x2, w;
66 |
67 | do
68 | {
69 | x1 = 2.0 * random(0.0, 1.0) - 1.0;
70 | x2 = 2.0 * random(0.0, 1.0) - 1.0;
71 | w = x1 * x1 + x2 * x2;
72 | }
73 | while (w >= 1.0 || w == 0.0);
74 |
75 | w = sqrt((-2.0 * log(w)) / w);
76 |
77 | return x1 * w * sigma;
78 | }
79 |
80 | unsigned long long timeInMicroseconds(void);
81 |
82 | double timeInSeconds(void);
83 |
84 | void colorDepthImage(cv::Mat& imgDepth,
85 | cv::Mat& imgColoredDepth,
86 | float minRange, float maxRange);
87 |
88 | bool colormap(const std::string& name, unsigned char idx,
89 | float& r, float& g, float& b);
90 |
91 | std::vector bresLine(int x0, int y0, int x1, int y1);
92 | std::vector bresCircle(int x0, int y0, int r);
93 |
94 | void fitCircle(const std::vector& points,
95 | double& centerX, double& centerY, double& radius);
96 |
97 | std::vector intersectCircles(double x1, double y1, double r1,
98 | double x2, double y2, double r2);
99 |
100 | void LLtoUTM(double latitude, double longitude,
101 | double& utmNorthing, double& utmEasting,
102 | std::string& utmZone);
103 | void UTMtoLL(double utmNorthing, double utmEasting,
104 | const std::string& utmZone,
105 | double& latitude, double& longitude);
106 |
107 | long int timestampDiff(uint64_t t1, uint64_t t2);
108 |
109 | }
110 |
111 | #endif
112 |
--------------------------------------------------------------------------------
/camera_model/include/camodocal/sparse_graph/Transform.h:
--------------------------------------------------------------------------------
1 | #ifndef TRANSFORM_H
2 | #define TRANSFORM_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | namespace camodocal
9 | {
10 |
11 | class Transform
12 | {
13 | public:
14 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW
15 |
16 | Transform();
17 | Transform(const Eigen::Matrix4d& H);
18 |
19 | Eigen::Quaterniond& rotation(void);
20 | const Eigen::Quaterniond& rotation(void) const;
21 | double* rotationData(void);
22 | const double* const rotationData(void) const;
23 |
24 | Eigen::Vector3d& translation(void);
25 | const Eigen::Vector3d& translation(void) const;
26 | double* translationData(void);
27 | const double* const translationData(void) const;
28 |
29 | Eigen::Matrix4d toMatrix(void) const;
30 |
31 | private:
32 | Eigen::Quaterniond m_q;
33 | Eigen::Vector3d m_t;
34 | };
35 |
36 | }
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/camera_model/instruction:
--------------------------------------------------------------------------------
1 | rosrun camera_model Calibration -w 8 -h 11 -s 70 -i ~/bag/PX/calib/
2 |
--------------------------------------------------------------------------------
/camera_model/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | gvins_camera_model
4 | 0.0.0
5 | The camera_model package
6 |
7 |
8 |
9 |
10 | dvorak
11 |
12 |
13 |
14 |
15 |
16 | TODO
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | catkin
43 | roscpp
44 | std_msgs
45 | roscpp
46 | std_msgs
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/camera_model/readme.md:
--------------------------------------------------------------------------------
1 | part of [camodocal](https://github.com/hengli/camodocal)
2 |
3 | [Google Ceres](http://ceres-solver.org) is needed.
4 |
5 | # Calibration:
6 |
7 | Use [intrinsic_calib.cc](https://github.com/dvorak0/camera_model/blob/master/src/intrinsic_calib.cc) to calibrate your camera.
8 |
9 | # Undistortion:
10 |
11 | See [Camera.h](https://github.com/dvorak0/camera_model/blob/master/include/camodocal/camera_models/Camera.h) for general interface:
12 |
13 | - liftProjective: Lift points from the image plane to the projective space.
14 | - spaceToPlane: Projects 3D points to the image plane (Pi function)
15 |
16 |
--------------------------------------------------------------------------------
/camera_model/src/camera_models/Camera.cc:
--------------------------------------------------------------------------------
1 | #include "camodocal/camera_models/Camera.h"
2 | #include "camodocal/camera_models/ScaramuzzaCamera.h"
3 |
4 | #include
5 |
6 | namespace camodocal
7 | {
8 |
9 | Camera::Parameters::Parameters(ModelType modelType)
10 | : m_modelType(modelType)
11 | , m_imageWidth(0)
12 | , m_imageHeight(0)
13 | {
14 | switch (modelType)
15 | {
16 | case KANNALA_BRANDT:
17 | m_nIntrinsics = 8;
18 | break;
19 | case PINHOLE:
20 | m_nIntrinsics = 8;
21 | break;
22 | case SCARAMUZZA:
23 | m_nIntrinsics = SCARAMUZZA_CAMERA_NUM_PARAMS;
24 | break;
25 | case MEI:
26 | default:
27 | m_nIntrinsics = 9;
28 | }
29 | }
30 |
31 | Camera::Parameters::Parameters(ModelType modelType,
32 | const std::string& cameraName,
33 | int w, int h)
34 | : m_modelType(modelType)
35 | , m_cameraName(cameraName)
36 | , m_imageWidth(w)
37 | , m_imageHeight(h)
38 | {
39 | switch (modelType)
40 | {
41 | case KANNALA_BRANDT:
42 | m_nIntrinsics = 8;
43 | break;
44 | case PINHOLE:
45 | m_nIntrinsics = 8;
46 | break;
47 | case SCARAMUZZA:
48 | m_nIntrinsics = SCARAMUZZA_CAMERA_NUM_PARAMS;
49 | break;
50 | case MEI:
51 | default:
52 | m_nIntrinsics = 9;
53 | }
54 | }
55 |
56 | Camera::ModelType&
57 | Camera::Parameters::modelType(void)
58 | {
59 | return m_modelType;
60 | }
61 |
62 | std::string&
63 | Camera::Parameters::cameraName(void)
64 | {
65 | return m_cameraName;
66 | }
67 |
68 | int&
69 | Camera::Parameters::imageWidth(void)
70 | {
71 | return m_imageWidth;
72 | }
73 |
74 | int&
75 | Camera::Parameters::imageHeight(void)
76 | {
77 | return m_imageHeight;
78 | }
79 |
80 | Camera::ModelType
81 | Camera::Parameters::modelType(void) const
82 | {
83 | return m_modelType;
84 | }
85 |
86 | const std::string&
87 | Camera::Parameters::cameraName(void) const
88 | {
89 | return m_cameraName;
90 | }
91 |
92 | int
93 | Camera::Parameters::imageWidth(void) const
94 | {
95 | return m_imageWidth;
96 | }
97 |
98 | int
99 | Camera::Parameters::imageHeight(void) const
100 | {
101 | return m_imageHeight;
102 | }
103 |
104 | int
105 | Camera::Parameters::nIntrinsics(void) const
106 | {
107 | return m_nIntrinsics;
108 | }
109 |
110 | cv::Mat&
111 | Camera::mask(void)
112 | {
113 | return m_mask;
114 | }
115 |
116 | const cv::Mat&
117 | Camera::mask(void) const
118 | {
119 | return m_mask;
120 | }
121 |
122 | void
123 | Camera::estimateExtrinsics(const std::vector& objectPoints,
124 | const std::vector& imagePoints,
125 | cv::Mat& rvec, cv::Mat& tvec) const
126 | {
127 | std::vector Ms(imagePoints.size());
128 | for (size_t i = 0; i < Ms.size(); ++i)
129 | {
130 | Eigen::Vector3d P;
131 | liftProjective(Eigen::Vector2d(imagePoints.at(i).x, imagePoints.at(i).y), P);
132 |
133 | P /= P(2);
134 |
135 | Ms.at(i).x = P(0);
136 | Ms.at(i).y = P(1);
137 | }
138 |
139 | // assume unit focal length, zero principal point, and zero distortion
140 | cv::solvePnP(objectPoints, Ms, cv::Mat::eye(3, 3, CV_64F), cv::noArray(), rvec, tvec);
141 | }
142 |
143 | double
144 | Camera::reprojectionDist(const Eigen::Vector3d& P1, const Eigen::Vector3d& P2) const
145 | {
146 | Eigen::Vector2d p1, p2;
147 |
148 | spaceToPlane(P1, p1);
149 | spaceToPlane(P2, p2);
150 |
151 | return (p1 - p2).norm();
152 | }
153 |
154 | double
155 | Camera::reprojectionError(const std::vector< std::vector >& objectPoints,
156 | const std::vector< std::vector >& imagePoints,
157 | const std::vector& rvecs,
158 | const std::vector& tvecs,
159 | cv::OutputArray _perViewErrors) const
160 | {
161 | int imageCount = objectPoints.size();
162 | size_t pointsSoFar = 0;
163 | double totalErr = 0.0;
164 |
165 | bool computePerViewErrors = _perViewErrors.needed();
166 | cv::Mat perViewErrors;
167 | if (computePerViewErrors)
168 | {
169 | _perViewErrors.create(imageCount, 1, CV_64F);
170 | perViewErrors = _perViewErrors.getMat();
171 | }
172 |
173 | for (int i = 0; i < imageCount; ++i)
174 | {
175 | size_t pointCount = imagePoints.at(i).size();
176 |
177 | pointsSoFar += pointCount;
178 |
179 | std::vector estImagePoints;
180 | projectPoints(objectPoints.at(i), rvecs.at(i), tvecs.at(i),
181 | estImagePoints);
182 |
183 | double err = 0.0;
184 | for (size_t j = 0; j < imagePoints.at(i).size(); ++j)
185 | {
186 | err += cv::norm(imagePoints.at(i).at(j) - estImagePoints.at(j));
187 | }
188 |
189 | if (computePerViewErrors)
190 | {
191 | perViewErrors.at(i) = err / pointCount;
192 | }
193 |
194 | totalErr += err;
195 | }
196 |
197 | return totalErr / pointsSoFar;
198 | }
199 |
200 | double
201 | Camera::reprojectionError(const Eigen::Vector3d& P,
202 | const Eigen::Quaterniond& camera_q,
203 | const Eigen::Vector3d& camera_t,
204 | const Eigen::Vector2d& observed_p) const
205 | {
206 | Eigen::Vector3d P_cam = camera_q.toRotationMatrix() * P + camera_t;
207 |
208 | Eigen::Vector2d p;
209 | spaceToPlane(P_cam, p);
210 |
211 | return (p - observed_p).norm();
212 | }
213 |
214 | void
215 | Camera::projectPoints(const std::vector& objectPoints,
216 | const cv::Mat& rvec,
217 | const cv::Mat& tvec,
218 | std::vector& imagePoints) const
219 | {
220 | // project 3D object points to the image plane
221 | imagePoints.reserve(objectPoints.size());
222 |
223 | //double
224 | cv::Mat R0;
225 | cv::Rodrigues(rvec, R0);
226 |
227 | Eigen::MatrixXd R(3,3);
228 | R << R0.at(0,0), R0.at(0,1), R0.at(0,2),
229 | R0.at(1,0), R0.at(1,1), R0.at(1,2),
230 | R0.at(2,0), R0.at(2,1), R0.at(2,2);
231 |
232 | Eigen::Vector3d t;
233 | t << tvec.at(0), tvec.at(1), tvec.at(2);
234 |
235 | for (size_t i = 0; i < objectPoints.size(); ++i)
236 | {
237 | const cv::Point3f& objectPoint = objectPoints.at(i);
238 |
239 | // Rotate and translate
240 | Eigen::Vector3d P;
241 | P << objectPoint.x, objectPoint.y, objectPoint.z;
242 |
243 | P = R * P + t;
244 |
245 | Eigen::Vector2d p;
246 | spaceToPlane(P, p);
247 |
248 | imagePoints.push_back(cv::Point2f(p(0), p(1)));
249 | }
250 | }
251 |
252 | }
253 |
--------------------------------------------------------------------------------
/camera_model/src/camera_models/CameraFactory.cc:
--------------------------------------------------------------------------------
1 | #include "camodocal/camera_models/CameraFactory.h"
2 |
3 | #include
4 |
5 |
6 | #include "camodocal/camera_models/CataCamera.h"
7 | #include "camodocal/camera_models/EquidistantCamera.h"
8 | #include "camodocal/camera_models/PinholeCamera.h"
9 | #include "camodocal/camera_models/ScaramuzzaCamera.h"
10 |
11 | #include "ceres/ceres.h"
12 |
13 | namespace camodocal
14 | {
15 |
16 | boost::shared_ptr CameraFactory::m_instance;
17 |
18 | CameraFactory::CameraFactory()
19 | {
20 |
21 | }
22 |
23 | boost::shared_ptr
24 | CameraFactory::instance(void)
25 | {
26 | if (m_instance.get() == 0)
27 | {
28 | m_instance.reset(new CameraFactory);
29 | }
30 |
31 | return m_instance;
32 | }
33 |
34 | CameraPtr
35 | CameraFactory::generateCamera(Camera::ModelType modelType,
36 | const std::string& cameraName,
37 | cv::Size imageSize) const
38 | {
39 | switch (modelType)
40 | {
41 | case Camera::KANNALA_BRANDT:
42 | {
43 | EquidistantCameraPtr camera(new EquidistantCamera);
44 |
45 | EquidistantCamera::Parameters params = camera->getParameters();
46 | params.cameraName() = cameraName;
47 | params.imageWidth() = imageSize.width;
48 | params.imageHeight() = imageSize.height;
49 | camera->setParameters(params);
50 | return camera;
51 | }
52 | case Camera::PINHOLE:
53 | {
54 | PinholeCameraPtr camera(new PinholeCamera);
55 |
56 | PinholeCamera::Parameters params = camera->getParameters();
57 | params.cameraName() = cameraName;
58 | params.imageWidth() = imageSize.width;
59 | params.imageHeight() = imageSize.height;
60 | camera->setParameters(params);
61 | return camera;
62 | }
63 | case Camera::SCARAMUZZA:
64 | {
65 | OCAMCameraPtr camera(new OCAMCamera);
66 |
67 | OCAMCamera::Parameters params = camera->getParameters();
68 | params.cameraName() = cameraName;
69 | params.imageWidth() = imageSize.width;
70 | params.imageHeight() = imageSize.height;
71 | camera->setParameters(params);
72 | return camera;
73 | }
74 | case Camera::MEI:
75 | default:
76 | {
77 | CataCameraPtr camera(new CataCamera);
78 |
79 | CataCamera::Parameters params = camera->getParameters();
80 | params.cameraName() = cameraName;
81 | params.imageWidth() = imageSize.width;
82 | params.imageHeight() = imageSize.height;
83 | camera->setParameters(params);
84 | return camera;
85 | }
86 | }
87 | }
88 |
89 | CameraPtr
90 | CameraFactory::generateCameraFromYamlFile(const std::string& filename)
91 | {
92 | cv::FileStorage fs(filename, cv::FileStorage::READ);
93 |
94 | if (!fs.isOpened())
95 | {
96 | return CameraPtr();
97 | }
98 |
99 | Camera::ModelType modelType = Camera::MEI;
100 | if (!fs["model_type"].isNone())
101 | {
102 | std::string sModelType;
103 | fs["model_type"] >> sModelType;
104 |
105 | if (boost::iequals(sModelType, "kannala_brandt"))
106 | {
107 | modelType = Camera::KANNALA_BRANDT;
108 | }
109 | else if (boost::iequals(sModelType, "mei"))
110 | {
111 | modelType = Camera::MEI;
112 | }
113 | else if (boost::iequals(sModelType, "scaramuzza"))
114 | {
115 | modelType = Camera::SCARAMUZZA;
116 | }
117 | else if (boost::iequals(sModelType, "pinhole"))
118 | {
119 | modelType = Camera::PINHOLE;
120 | }
121 | else
122 | {
123 | std::cerr << "# ERROR: Unknown camera model: " << sModelType << std::endl;
124 | return CameraPtr();
125 | }
126 | }
127 |
128 | switch (modelType)
129 | {
130 | case Camera::KANNALA_BRANDT:
131 | {
132 | EquidistantCameraPtr camera(new EquidistantCamera);
133 |
134 | EquidistantCamera::Parameters params = camera->getParameters();
135 | params.readFromYamlFile(filename);
136 | camera->setParameters(params);
137 | return camera;
138 | }
139 | case Camera::PINHOLE:
140 | {
141 | PinholeCameraPtr camera(new PinholeCamera);
142 |
143 | PinholeCamera::Parameters params = camera->getParameters();
144 | params.readFromYamlFile(filename);
145 | camera->setParameters(params);
146 | return camera;
147 | }
148 | case Camera::SCARAMUZZA:
149 | {
150 | OCAMCameraPtr camera(new OCAMCamera);
151 |
152 | OCAMCamera::Parameters params = camera->getParameters();
153 | params.readFromYamlFile(filename);
154 | camera->setParameters(params);
155 | return camera;
156 | }
157 | case Camera::MEI:
158 | default:
159 | {
160 | CataCameraPtr camera(new CataCamera);
161 |
162 | CataCamera::Parameters params = camera->getParameters();
163 | params.readFromYamlFile(filename);
164 | camera->setParameters(params);
165 | return camera;
166 | }
167 | }
168 |
169 | return CameraPtr();
170 | }
171 |
172 | }
173 |
174 |
--------------------------------------------------------------------------------
/camera_model/src/gpl/EigenQuaternionParameterization.cc:
--------------------------------------------------------------------------------
1 | #include "camodocal/gpl/EigenQuaternionParameterization.h"
2 |
3 | #include
4 |
5 | namespace camodocal
6 | {
7 |
8 | bool
9 | EigenQuaternionParameterization::Plus(const double* x,
10 | const double* delta,
11 | double* x_plus_delta) const
12 | {
13 | const double norm_delta =
14 | sqrt(delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2]);
15 | if (norm_delta > 0.0)
16 | {
17 | const double sin_delta_by_delta = (sin(norm_delta) / norm_delta);
18 | double q_delta[4];
19 | q_delta[0] = sin_delta_by_delta * delta[0];
20 | q_delta[1] = sin_delta_by_delta * delta[1];
21 | q_delta[2] = sin_delta_by_delta * delta[2];
22 | q_delta[3] = cos(norm_delta);
23 | EigenQuaternionProduct(q_delta, x, x_plus_delta);
24 | }
25 | else
26 | {
27 | for (int i = 0; i < 4; ++i)
28 | {
29 | x_plus_delta[i] = x[i];
30 | }
31 | }
32 | return true;
33 | }
34 |
35 | bool
36 | EigenQuaternionParameterization::ComputeJacobian(const double* x,
37 | double* jacobian) const
38 | {
39 | jacobian[0] = x[3]; jacobian[1] = x[2]; jacobian[2] = -x[1]; // NOLINT
40 | jacobian[3] = -x[2]; jacobian[4] = x[3]; jacobian[5] = x[0]; // NOLINT
41 | jacobian[6] = x[1]; jacobian[7] = -x[0]; jacobian[8] = x[3]; // NOLINT
42 | jacobian[9] = -x[0]; jacobian[10] = -x[1]; jacobian[11] = -x[2]; // NOLINT
43 | return true;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/camera_model/src/sparse_graph/Transform.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | namespace camodocal
4 | {
5 |
6 | Transform::Transform()
7 | {
8 | m_q.setIdentity();
9 | m_t.setZero();
10 | }
11 |
12 | Transform::Transform(const Eigen::Matrix4d& H)
13 | {
14 | m_q = Eigen::Quaterniond(H.block<3,3>(0,0));
15 | m_t = H.block<3,1>(0,3);
16 | }
17 |
18 | Eigen::Quaterniond&
19 | Transform::rotation(void)
20 | {
21 | return m_q;
22 | }
23 |
24 | const Eigen::Quaterniond&
25 | Transform::rotation(void) const
26 | {
27 | return m_q;
28 | }
29 |
30 | double*
31 | Transform::rotationData(void)
32 | {
33 | return m_q.coeffs().data();
34 | }
35 |
36 | const double* const
37 | Transform::rotationData(void) const
38 | {
39 | return m_q.coeffs().data();
40 | }
41 |
42 | Eigen::Vector3d&
43 | Transform::translation(void)
44 | {
45 | return m_t;
46 | }
47 |
48 | const Eigen::Vector3d&
49 | Transform::translation(void) const
50 | {
51 | return m_t;
52 | }
53 |
54 | double*
55 | Transform::translationData(void)
56 | {
57 | return m_t.data();
58 | }
59 |
60 | const double* const
61 | Transform::translationData(void) const
62 | {
63 | return m_t.data();
64 | }
65 |
66 | Eigen::Matrix4d
67 | Transform::toMatrix(void) const
68 | {
69 | Eigen::Matrix4d H;
70 | H.setIdentity();
71 | H.block<3,3>(0,0) = m_q.toRotationMatrix();
72 | H.block<3,1>(0,3) = m_t;
73 |
74 | return H;
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/config/gvins_rviz_config.rviz:
--------------------------------------------------------------------------------
1 | Panels:
2 | - Class: rviz/Displays
3 | Help Height: 78
4 | Name: Displays
5 | Property Tree Widget:
6 | Expanded: ~
7 | Splitter Ratio: 0.5
8 | Tree Height: 236
9 | - Class: rviz/Selection
10 | Name: Selection
11 | - Class: rviz/Tool Properties
12 | Expanded:
13 | - /2D Pose Estimate1
14 | - /2D Nav Goal1
15 | - /Publish Point1
16 | Name: Tool Properties
17 | Splitter Ratio: 0.588679016
18 | - Class: rviz/Views
19 | Expanded:
20 | - /Current View1
21 | Name: Views
22 | Splitter Ratio: 0.5
23 | - Class: rviz/Time
24 | Experimental: false
25 | Name: Time
26 | SyncMode: 0
27 | SyncSource: Image
28 | Toolbars:
29 | toolButtonStyle: 2
30 | Visualization Manager:
31 | Class: ""
32 | Displays:
33 | - Alpha: 0.5
34 | Cell Size: 10
35 | Class: rviz/Grid
36 | Color: 160; 160; 164
37 | Enabled: true
38 | Line Style:
39 | Line Width: 0.0299999993
40 | Value: Lines
41 | Name: Grid
42 | Normal Cell Count: 0
43 | Offset:
44 | X: 0
45 | Y: 0
46 | Z: 0
47 | Plane: XY
48 | Plane Cell Count: 50
49 | Reference Frame:
50 | Value: true
51 | - Class: rviz/Axes
52 | Enabled: true
53 | Length: 5
54 | Name: Axes
55 | Radius: 0.300000012
56 | Reference Frame:
57 | Value: true
58 | - Class: rviz/Image
59 | Enabled: true
60 | Image Topic: /cam1/image_raw
61 | Max Value: 1
62 | Median window: 5
63 | Min Value: 0
64 | Name: Image
65 | Normalize Range: true
66 | Queue Size: 2
67 | Transport Hint: raw
68 | Unreliable: false
69 | Value: true
70 | - Class: rviz/Image
71 | Enabled: true
72 | Image Topic: /gvins_feature_tracker/feature_img
73 | Max Value: 1
74 | Median window: 5
75 | Min Value: 0
76 | Name: Image
77 | Normalize Range: true
78 | Queue Size: 2
79 | Transport Hint: raw
80 | Unreliable: false
81 | Value: true
82 | - Alpha: 1
83 | Buffer Length: 1
84 | Class: rviz/Path
85 | Color: 0; 85; 255
86 | Enabled: true
87 | Head Diameter: 0.300000012
88 | Head Length: 0.200000003
89 | Length: 0.300000012
90 | Line Style: Lines
91 | Line Width: 0.0299999993
92 | Name: Path
93 | Offset:
94 | X: 0
95 | Y: 0
96 | Z: 0
97 | Pose Color: 255; 85; 255
98 | Pose Style: None
99 | Radius: 0.0299999993
100 | Shaft Diameter: 0.100000001
101 | Shaft Length: 0.100000001
102 | Topic: /gvins/gnss_enu_path
103 | Unreliable: false
104 | Value: true
105 | - Alpha: 1
106 | Buffer Length: 1
107 | Class: rviz/Path
108 | Color: 25; 255; 0
109 | Enabled: true
110 | Head Diameter: 0.300000012
111 | Head Length: 0.200000003
112 | Length: 0.300000012
113 | Line Style: Lines
114 | Line Width: 0.0299999993
115 | Name: Path
116 | Offset:
117 | X: 0
118 | Y: 0
119 | Z: 0
120 | Pose Color: 255; 85; 255
121 | Pose Style: None
122 | Radius: 0.0299999993
123 | Shaft Diameter: 0.100000001
124 | Shaft Length: 0.100000001
125 | Topic: /gvins/path
126 | Unreliable: false
127 | Value: true
128 | Enabled: true
129 | Global Options:
130 | Background Color: 48; 48; 48
131 | Default Light: true
132 | Fixed Frame: world
133 | Frame Rate: 30
134 | Name: root
135 | Tools:
136 | - Class: rviz/Interact
137 | Hide Inactive Objects: true
138 | - Class: rviz/MoveCamera
139 | - Class: rviz/Select
140 | - Class: rviz/FocusCamera
141 | - Class: rviz/Measure
142 | - Class: rviz/SetInitialPose
143 | Topic: /initialpose
144 | - Class: rviz/SetGoal
145 | Topic: /move_base_simple/goal
146 | - Class: rviz/PublishPoint
147 | Single click: true
148 | Topic: /clicked_point
149 | Value: true
150 | Views:
151 | Current:
152 | Class: rviz/Orbit
153 | Distance: 305.921631
154 | Enable Stereo Rendering:
155 | Stereo Eye Separation: 0.0599999987
156 | Stereo Focal Distance: 1
157 | Swap Stereo Eyes: false
158 | Value: false
159 | Focal Point:
160 | X: 16.1296978
161 | Y: 25.7230911
162 | Z: -1.10709679
163 | Focal Shape Fixed Size: true
164 | Focal Shape Size: 0.0500000007
165 | Invert Z Axis: false
166 | Name: Current View
167 | Near Clip Distance: 0.00999999978
168 | Pitch: 1.56979632
169 | Target Frame:
170 | Value: Orbit (rviz)
171 | Yaw: 5.08356237
172 | Saved: ~
173 | Window Geometry:
174 | Displays:
175 | collapsed: false
176 | Height: 1056
177 | Hide Left Dock: false
178 | Hide Right Dock: true
179 | Image:
180 | collapsed: false
181 | QMainWindow State: 000000ff00000000fd0000000400000000000001d200000391fc020000000afb0000001200530065006c0065006300740069006f006e00000001e10000009b0000006200fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb0000000a0049006d006100670065010000002b000000f60000001700fffffffb0000000a0049006d0061006700650100000127000001110000001700fffffffb000000100044006900730070006c006100790073010000023e0000017e000000da00fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f00000391fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000002b00000391000000b200fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000007800000003efc0100000002fb0000000800540069006d00650100000000000007800000035200fffffffb0000000800540069006d00650100000000000004500000000000000000000005a80000039100000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
182 | Selection:
183 | collapsed: false
184 | Time:
185 | collapsed: false
186 | Tool Properties:
187 | collapsed: false
188 | Views:
189 | collapsed: true
190 | Width: 1920
191 | X: 0
192 | Y: 464
193 |
--------------------------------------------------------------------------------
/config/simulator/simulator_config.yaml:
--------------------------------------------------------------------------------
1 | %YAML:1.0
2 |
3 | #common parameters
4 | imu_topic: "/simulator/imu0"
5 | image_topic: "/cam0/image_raw"
6 | output_path: "/home/shaozu/output/"
7 |
8 | #camera calibration
9 | model_type: PINHOLE
10 | camera_name: camera
11 | image_width: 752
12 | image_height: 480
13 | distortion_parameters:
14 | k1: -2.917e-01
15 | k2: 8.228e-02
16 | p1: 5.333e-05
17 | p2: -1.578e-04
18 | projection_parameters:
19 | fx: 4.616e+02
20 | fy: 4.603e+02
21 | cx: 3.630e+02
22 | cy: 2.481e+02
23 |
24 | gnss_enable: 1
25 | gnss_meas_topic: "/simulator/gnss0_meas"
26 | gnss_ephem_topic: "/simulator/gnss0_ephem"
27 | gnss_glo_ephem_topic: "/simulator/gnss0_gloephem"
28 |
29 | # Extrinsic parameter between IMU and Camera.
30 | estimate_extrinsic: 0 # 0 Have an accurate extrinsic parameters. We will trust the following imu^R_cam, imu^T_cam, don't change it.
31 | # 1 Have an initial guess about extrinsic parameters. We will optimize around your initial guess.
32 | # 2 Don't know anything about extrinsic parameters. You don't need to give R,T. We will try to calibrate it. Do some rotation movement at beginning.
33 | #If you choose 0 or 1, you should write down the following matrix.
34 | #Rotation from camera frame to imu frame, imu^R_cam
35 | extrinsicRotation: !!opencv-matrix
36 | rows: 3
37 | cols: 3
38 | dt: d
39 | data: [0.0148655429818, -0.999880929698, 0.00414029679422,
40 | 0.999557249008, 0.0149672133247, 0.025715529948,
41 | -0.0257744366974, 0.00375618835797, 0.999660727178]
42 | #Translation from camera frame to imu frame, imu^T_cam
43 | extrinsicTranslation: !!opencv-matrix
44 | rows: 3
45 | cols: 1
46 | dt: d
47 | data: [0.03,-0.05, 0]
48 |
49 | #feature traker paprameters
50 | max_cnt: 150 # max feature number in feature tracking
51 | min_dist: 30 # min distance between two features
52 | freq: 10 # frequence (Hz) of publish tracking result. At least 10Hz for good estimation. If set 0, the frequence will be same as raw image
53 | F_threshold: 1.0 # ransac threshold (pixel)
54 | show_track: 1 # publish tracking image as topic
55 | equalize: 1 # if image is too dark or light, trun on equalize to find enough features
56 | fisheye: 0 # if using fisheye, trun on it. A circle mask will be loaded to remove edge noisy points
57 |
58 | #optimization parameters
59 | max_solver_time: 0.04 # max solver itration time (ms), to guarantee real time
60 | max_num_iterations: 8 # max solver itrations, to guarantee real time
61 | keyframe_parallax: 10.0 # keyframe selection threshold (pixel)
62 |
63 | #imu parameters The more accurate parameters you provide, the better performance
64 | acc_n: 0.1 # accelerometer measurement noise standard deviation. #0.2 0.04
65 | gyr_n: 0.01 # gyroscope measurement noise standard deviation. #0.05 0.004
66 | acc_w: 0.001 # accelerometer bias random work noise standard deviation. #0.02
67 | gyr_w: 0.0001 # gyroscope bias random work noise standard deviation. #4.0e-5
68 | g_norm: 9.805 # gravity magnitude
69 |
70 | #unsynchronization parameters
71 | estimate_td: 0 # online estimate time offset between camera and imu
72 | td: 0.0 # initial value of time offset. unit: s. readed image clock + td = real image clock (IMU clock)
73 |
--------------------------------------------------------------------------------
/config/visensor_f9p/visensor_left_f9p_config.yaml:
--------------------------------------------------------------------------------
1 | %YAML:1.0
2 |
3 | #common parameters
4 | imu_topic: "/imu0"
5 | image_topic: "/cam1/image_raw"
6 | output_dir: "/home/SLAM/GVINS/output/"
7 |
8 | #camera calibration
9 | model_type: MEI
10 | camera_name: camera
11 | image_width: 752
12 | image_height: 480
13 | mirror_parameters:
14 | xi: 1.8476540167437447
15 | distortion_parameters:
16 | k1: -0.06597811223735722
17 | k2: 0.8559479340704287
18 | p1: -0.0006445829733139821
19 | p2: 0.0015137487236065916
20 | projection_parameters:
21 | gamma1: 1338.1845333957547
22 | gamma2: 1340.1190112672946
23 | u0: 378.7909740462579
24 | v0: 217.69105287172025
25 |
26 | gnss_enable: 1
27 | gnss_meas_topic: "/ublox_driver/range_meas" # GNSS raw measurement topic
28 | gnss_ephem_topic: "/ublox_driver/ephem" # GPS, Galileo, BeiDou ephemeris
29 | gnss_glo_ephem_topic: "/ublox_driver/glo_ephem" # GLONASS ephemeris
30 | gnss_iono_params_topic: "/ublox_driver/iono_params" # GNSS broadcast ionospheric parameters
31 | gnss_tp_info_topic: "/ublox_driver/time_pulse_info" # PPS time info
32 | gnss_elevation_thres: 30 # satellite elevation threshold (degree)
33 | gnss_psr_std_thres: 2.0 # pseudo-range std threshold
34 | gnss_dopp_std_thres: 2.0 # doppler std threshold
35 | gnss_track_num_thres: 20 # number of satellite tracking epochs before entering estimator
36 | gnss_ddt_sigma: 0.1
37 |
38 | gnss_local_online_sync: 1 # if perform online synchronization betwen GNSS and local time
39 | local_trigger_info_topic: "/external_trigger" # external trigger info of the local sensor, if `gnss_local_online_sync` is 1
40 | gnss_local_time_diff: 18.0 # difference between GNSS and local time (s), if `gnss_local_online_sync` is 0
41 |
42 | gnss_iono_default_parameters: !!opencv-matrix
43 | rows: 1
44 | cols: 8
45 | dt: d
46 | data: [0.1118E-07, 0.2235E-07, -0.4172E-06, 0.6557E-06,
47 | 0.1249E+06, -0.4424E+06, 0.1507E+07, -0.2621E+06]
48 |
49 | # Extrinsic parameter between IMU and Camera.
50 | estimate_extrinsic: 0 # 0 Have an accurate extrinsic parameters. We will trust the following imu^R_cam, imu^T_cam, don't change it.
51 | # 1 Have an initial guess about extrinsic parameters. We will optimize around your initial guess.
52 | # 2 Don't know anything about extrinsic parameters. You don't need to give R,T. We will try to calibrate it. Do some rotation movement at beginning.
53 | #If you choose 0 or 1, you should write down the following matrix.
54 | #Rotation from camera frame to imu frame, imu^R_cam
55 | extrinsicRotation: !!opencv-matrix
56 | rows: 3
57 | cols: 3
58 | dt: d
59 | data: [0.9999890386957373, -0.0043227774403168, 0.0017989117755288,
60 | 0.0043276579084841, 0.9999869417854389, -0.0027180205355500,
61 | -0.0017871388870994, 0.0027257758172719, 0.9999946881262878]
62 | #Translation from camera frame to imu frame, imu^T_cam
63 | extrinsicTranslation: !!opencv-matrix
64 | rows: 3
65 | cols: 1
66 | dt: d
67 | data: [-0.0759472920952561, -0.0039320527565750, -0.0016395029500217]
68 |
69 | #feature traker paprameters
70 | max_cnt: 150 # max feature number in feature tracking
71 | min_dist: 30 # min distance between two features
72 | freq: 0 # frequence (Hz) of publish tracking result. At least 10Hz for good estimation. If set 0, the frequence will be same as raw image
73 | F_threshold: 1.0 # ransac threshold (pixel)
74 | show_track: 1 # publish tracking image as topic
75 | equalize: 1 # if image is too dark or light, trun on equalize to find enough features
76 | fisheye: 0 # if using fisheye, trun on it. A circle mask will be loaded to remove edge noisy points
77 |
78 | #optimization parameters
79 | max_solver_time: 0.04 # max solver itration time (ms), to guarantee real time
80 | max_num_iterations: 8 # max solver itrations, to guarantee real time
81 | keyframe_parallax: 10.0 # keyframe selection threshold (pixel)
82 |
83 | #imu parameters The more accurate parameters you provide, the better performance
84 | acc_n: 0.08 # accelerometer measurement noise standard deviation. #0.2 0.04
85 | gyr_n: 0.004 # gyroscope measurement noise standard deviation. #0.05 0.004
86 | acc_w: 0.00004 # accelerometer bias random work noise standard deviation. #0.02
87 | gyr_w: 2.0e-6 # gyroscope bias random work noise standard deviation. #4.0e-5
88 | g_norm: 9.787561 # gravity magnitude
89 |
90 | #unsynchronization parameters
91 | estimate_td: 0 # online estimate time offset between camera and imu
92 | td: 0.0 # initial value of time offset. unit: s. readed image clock + td = real image clock (IMU clock)
93 |
--------------------------------------------------------------------------------
/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ros:kinetic-perception
2 |
3 | ENV EIGEN_VERSION="3.3.3"
4 | ENV CERES_VERSION="1.12.0"
5 | ENV CATKIN_WS=/root/catkin_ws
6 |
7 | # set up thread number for building
8 | RUN if [ "x$(nproc)" = "x1" ] ; then export USE_PROC=1 ; \
9 | else export USE_PROC=$(($(nproc)/2)) ; fi && \
10 | apt-get update && apt-get install -y \
11 | git \
12 | cmake \
13 | libatlas-base-dev \
14 | libgoogle-glog-dev \
15 | libsuitesparse-dev \
16 | python-catkin-tools \
17 | ros-${ROS_DISTRO}-cv-bridge \
18 | ros-${ROS_DISTRO}-image-transport \
19 | ros-${ROS_DISTRO}-message-filters \
20 | ros-${ROS_DISTRO}-tf && \
21 | rm -rf /var/lib/apt/lists/* && \
22 | # install eigen
23 | git clone https://gitlab.com/libeigen/eigen.git && \
24 | cd eigen && \
25 | git checkout tags/${EIGEN_VERSION} && \
26 | mkdir build && cd build && \
27 | cmake .. && make install && \
28 | cd ../.. && rm -rf eigen && \
29 | # Build and install Ceres
30 | git clone https://ceres-solver.googlesource.com/ceres-solver && \
31 | cd ceres-solver && \
32 | git checkout tags/${CERES_VERSION} && \
33 | mkdir build && cd build && \
34 | cmake .. && \
35 | make -j$(USE_PROC) install && \
36 | cd ../.. && rm -rf ceres-solver && \
37 | # create GVINS directory
38 | mkdir -p $CATKIN_WS/src/GVINS/ && \
39 | cd $CATKIN_WS/src && \
40 | # clone gnss_comm repo
41 | git clone https://github.com/HKUST-Aerial-Robotics/gnss_comm.git
42 |
43 | # Copy the local replica of GVINS
44 | COPY ./ $CATKIN_WS/src/GVINS/
45 | # comment the above line and use the following command if you only have this dockerfile
46 | # RUN git clone https://github.com/HKUST-Aerial-Robotics/GVINS.git
47 |
48 | # Build GVINS
49 | WORKDIR $CATKIN_WS
50 | ENV TERM xterm
51 | ENV PYTHONIOENCODING UTF-8
52 | RUN catkin config \
53 | --extend /opt/ros/$ROS_DISTRO \
54 | --cmake-args \
55 | -DCMAKE_BUILD_TYPE=Release && \
56 | catkin build && \
57 | sed -i '/exec "$@"/i \
58 | source "/root/catkin_ws/devel/setup.bash"' /ros_entrypoint.sh
59 |
--------------------------------------------------------------------------------
/docker/Makefile:
--------------------------------------------------------------------------------
1 | all: help
2 |
3 | help:
4 | @echo ""
5 | @echo "-- Help Menu"
6 | @echo ""
7 | @echo " 1. make build - build all images"
8 | @echo " 1. make clean - remove all images"
9 | @echo ""
10 |
11 | build:
12 | @docker build --tag gvins -f ./Dockerfile ..
13 |
14 | clean:
15 | @docker rmi -f gvins
16 |
--------------------------------------------------------------------------------
/docker/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | trap : SIGTERM SIGINT
3 |
4 | function abspath() {
5 | # generate absolute path from relative path
6 | # $1 : relative filename
7 | # return : absolute path
8 | if [ -d "$1" ]; then
9 | # dir
10 | (cd "$1"; pwd)
11 | elif [ -f "$1" ]; then
12 | # file
13 | if [[ $1 = /* ]]; then
14 | echo "$1"
15 | elif [[ $1 == */* ]]; then
16 | echo "$(cd "${1%/*}"; pwd)/${1##*/}"
17 | else
18 | echo "$(pwd)/$1"
19 | fi
20 | fi
21 | }
22 |
23 | if [ "$#" -ne 1 ]; then
24 | echo "Usage: $0 LAUNCH_FILE" >&2
25 | exit 1
26 | fi
27 |
28 | roscore &
29 | ROSCORE_PID=$!
30 | sleep 1
31 |
32 | rviz -d ../config/gvins_rviz_config.rviz &
33 | RVIZ_PID=$!
34 |
35 | GVINS_DIR=$(abspath "..")
36 |
37 | docker run \
38 | -it \
39 | --rm \
40 | --net=host \
41 | -v ${GVINS_DIR}:/root/catkin_ws/src/GVINS/ \
42 | gvins:latest \
43 | /bin/bash -c \
44 | "cd /root/catkin_ws/; \
45 | catkin config \
46 | --env-cache \
47 | --extend /opt/ros/$ROS_DISTRO \
48 | --cmake-args \
49 | -DCMAKE_BUILD_TYPE=Release; \
50 | catkin build; \
51 | source devel/setup.bash; \
52 | roslaunch gvins ${1}"
53 |
54 | wait $ROSCORE_PID
55 | wait $RVIZ_PID
56 |
57 | if [[ $? -gt 128 ]]
58 | then
59 | kill $ROSCORE_PID
60 | kill $RVIZ_PID
61 | fi
62 |
--------------------------------------------------------------------------------
/estimator/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.3)
2 | project(gvins)
3 |
4 | set(CMAKE_BUILD_TYPE "Release")
5 | set(CMAKE_CXX_FLAGS "-std=c++11")
6 | set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wall -g")
7 |
8 | find_package(catkin REQUIRED COMPONENTS
9 | roscpp
10 | std_msgs
11 | geometry_msgs
12 | nav_msgs
13 | tf
14 | cv_bridge
15 | rosbag
16 | message_generation
17 | gnss_comm
18 | )
19 |
20 | add_message_files(
21 | DIRECTORY msg
22 | FILES LocalSensorExternalTrigger.msg
23 | )
24 | generate_messages(DEPENDENCIES std_msgs)
25 |
26 | find_package(OpenCV REQUIRED)
27 |
28 | find_package(Ceres REQUIRED)
29 |
30 | include_directories(${catkin_INCLUDE_DIRS} ${CERES_INCLUDE_DIRS})
31 |
32 | set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
33 | find_package(Eigen3)
34 | include_directories(
35 | ${catkin_INCLUDE_DIRS}
36 | ${EIGEN3_INCLUDE_DIR}
37 | )
38 |
39 | catkin_package()
40 |
41 | add_executable(${PROJECT_NAME}
42 | src/estimator_node.cpp
43 | src/parameters.cpp
44 | src/estimator.cpp
45 | src/feature_manager.cpp
46 | src/factor/pose_local_parameterization.cpp
47 | src/factor/projection_factor.cpp
48 | src/factor/projection_td_factor.cpp
49 | src/factor/marginalization_factor.cpp
50 | src/factor/gnss_psr_dopp_factor.cpp
51 | src/factor/gnss_dt_ddt_factor.cpp
52 | src/factor/gnss_dt_anchor_factor.cpp
53 | src/factor/gnss_ddt_smooth_factor.cpp
54 | src/factor/pos_vel_factor.cpp
55 | src/factor/pose_anchor_factor.cpp
56 | src/utility/utility.cpp
57 | src/utility/visualization.cpp
58 | src/utility/CameraPoseVisualization.cpp
59 | src/initial/solve_5pts.cpp
60 | src/initial/initial_aligment.cpp
61 | src/initial/initial_sfm.cpp
62 | src/initial/initial_ex_rotation.cpp
63 | src/initial/gnss_vi_initializer.cpp
64 | )
65 |
66 | target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES} ${OpenCV_LIBS} ${CERES_LIBRARIES})
67 | add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}_generate_messages_cpp)
68 | # add_dependencies(${PROJECT_NAME} ${catkin_EXPORTED_TARGETS})
69 |
--------------------------------------------------------------------------------
/estimator/cmake/FindEigen.cmake:
--------------------------------------------------------------------------------
1 | # Ceres Solver - A fast non-linear least squares minimizer
2 | # Copyright 2015 Google Inc. All rights reserved.
3 | # http://ceres-solver.org/
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions are met:
7 | #
8 | # * Redistributions of source code must retain the above copyright notice,
9 | # this list of conditions and the following disclaimer.
10 | # * Redistributions in binary form must reproduce the above copyright notice,
11 | # this list of conditions and the following disclaimer in the documentation
12 | # and/or other materials provided with the distribution.
13 | # * Neither the name of Google Inc. nor the names of its contributors may be
14 | # used to endorse or promote products derived from this software without
15 | # specific prior written permission.
16 | #
17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 | # POSSIBILITY OF SUCH DAMAGE.
28 | #
29 | # Author: alexs.mac@gmail.com (Alex Stewart)
30 | #
31 |
32 | # FindEigen.cmake - Find Eigen library, version >= 3.
33 | #
34 | # This module defines the following variables:
35 | #
36 | # EIGEN_FOUND: TRUE iff Eigen is found.
37 | # EIGEN_INCLUDE_DIRS: Include directories for Eigen.
38 | #
39 | # EIGEN_VERSION: Extracted from Eigen/src/Core/util/Macros.h
40 | # EIGEN_WORLD_VERSION: Equal to 3 if EIGEN_VERSION = 3.2.0
41 | # EIGEN_MAJOR_VERSION: Equal to 2 if EIGEN_VERSION = 3.2.0
42 | # EIGEN_MINOR_VERSION: Equal to 0 if EIGEN_VERSION = 3.2.0
43 | #
44 | # The following variables control the behaviour of this module:
45 | #
46 | # EIGEN_INCLUDE_DIR_HINTS: List of additional directories in which to
47 | # search for eigen includes, e.g: /timbuktu/eigen3.
48 | #
49 | # The following variables are also defined by this module, but in line with
50 | # CMake recommended FindPackage() module style should NOT be referenced directly
51 | # by callers (use the plural variables detailed above instead). These variables
52 | # do however affect the behaviour of the module via FIND_[PATH/LIBRARY]() which
53 | # are NOT re-called (i.e. search for library is not repeated) if these variables
54 | # are set with valid values _in the CMake cache_. This means that if these
55 | # variables are set directly in the cache, either by the user in the CMake GUI,
56 | # or by the user passing -DVAR=VALUE directives to CMake when called (which
57 | # explicitly defines a cache variable), then they will be used verbatim,
58 | # bypassing the HINTS variables and other hard-coded search locations.
59 | #
60 | # EIGEN_INCLUDE_DIR: Include directory for CXSparse, not including the
61 | # include directory of any dependencies.
62 |
63 | # Called if we failed to find Eigen or any of it's required dependencies,
64 | # unsets all public (designed to be used externally) variables and reports
65 | # error message at priority depending upon [REQUIRED/QUIET/] argument.
66 | macro(EIGEN_REPORT_NOT_FOUND REASON_MSG)
67 | unset(EIGEN_FOUND)
68 | unset(EIGEN_INCLUDE_DIRS)
69 | # Make results of search visible in the CMake GUI if Eigen has not
70 | # been found so that user does not have to toggle to advanced view.
71 | mark_as_advanced(CLEAR EIGEN_INCLUDE_DIR)
72 | # Note _FIND_[REQUIRED/QUIETLY] variables defined by FindPackage()
73 | # use the camelcase library name, not uppercase.
74 | if (Eigen_FIND_QUIETLY)
75 | message(STATUS "Failed to find Eigen - " ${REASON_MSG} ${ARGN})
76 | elseif (Eigen_FIND_REQUIRED)
77 | message(FATAL_ERROR "Failed to find Eigen - " ${REASON_MSG} ${ARGN})
78 | else()
79 | # Neither QUIETLY nor REQUIRED, use no priority which emits a message
80 | # but continues configuration and allows generation.
81 | message("-- Failed to find Eigen - " ${REASON_MSG} ${ARGN})
82 | endif ()
83 | return()
84 | endmacro(EIGEN_REPORT_NOT_FOUND)
85 |
86 | # Protect against any alternative find_package scripts for this library having
87 | # been called previously (in a client project) which set EIGEN_FOUND, but not
88 | # the other variables we require / set here which could cause the search logic
89 | # here to fail.
90 | unset(EIGEN_FOUND)
91 |
92 | # Search user-installed locations first, so that we prefer user installs
93 | # to system installs where both exist.
94 | list(APPEND EIGEN_CHECK_INCLUDE_DIRS
95 | /usr/local/include
96 | /usr/local/homebrew/include # Mac OS X
97 | /opt/local/var/macports/software # Mac OS X.
98 | /opt/local/include
99 | /usr/include)
100 | # Additional suffixes to try appending to each search path.
101 | list(APPEND EIGEN_CHECK_PATH_SUFFIXES
102 | eigen3 # Default root directory for Eigen.
103 | Eigen/include/eigen3 # Windows (for C:/Program Files prefix) < 3.3
104 | Eigen3/include/eigen3 ) # Windows (for C:/Program Files prefix) >= 3.3
105 |
106 | # Search supplied hint directories first if supplied.
107 | find_path(EIGEN_INCLUDE_DIR
108 | NAMES Eigen/Core
109 | PATHS ${EIGEN_INCLUDE_DIR_HINTS}
110 | ${EIGEN_CHECK_INCLUDE_DIRS}
111 | PATH_SUFFIXES ${EIGEN_CHECK_PATH_SUFFIXES})
112 |
113 | if (NOT EIGEN_INCLUDE_DIR OR
114 | NOT EXISTS ${EIGEN_INCLUDE_DIR})
115 | eigen_report_not_found(
116 | "Could not find eigen3 include directory, set EIGEN_INCLUDE_DIR to "
117 | "path to eigen3 include directory, e.g. /usr/local/include/eigen3.")
118 | endif (NOT EIGEN_INCLUDE_DIR OR
119 | NOT EXISTS ${EIGEN_INCLUDE_DIR})
120 |
121 | # Mark internally as found, then verify. EIGEN_REPORT_NOT_FOUND() unsets
122 | # if called.
123 | set(EIGEN_FOUND TRUE)
124 |
125 | # Extract Eigen version from Eigen/src/Core/util/Macros.h
126 | if (EIGEN_INCLUDE_DIR)
127 | set(EIGEN_VERSION_FILE ${EIGEN_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h)
128 | if (NOT EXISTS ${EIGEN_VERSION_FILE})
129 | eigen_report_not_found(
130 | "Could not find file: ${EIGEN_VERSION_FILE} "
131 | "containing version information in Eigen install located at: "
132 | "${EIGEN_INCLUDE_DIR}.")
133 | else (NOT EXISTS ${EIGEN_VERSION_FILE})
134 | file(READ ${EIGEN_VERSION_FILE} EIGEN_VERSION_FILE_CONTENTS)
135 |
136 | string(REGEX MATCH "#define EIGEN_WORLD_VERSION [0-9]+"
137 | EIGEN_WORLD_VERSION "${EIGEN_VERSION_FILE_CONTENTS}")
138 | string(REGEX REPLACE "#define EIGEN_WORLD_VERSION ([0-9]+)" "\\1"
139 | EIGEN_WORLD_VERSION "${EIGEN_WORLD_VERSION}")
140 |
141 | string(REGEX MATCH "#define EIGEN_MAJOR_VERSION [0-9]+"
142 | EIGEN_MAJOR_VERSION "${EIGEN_VERSION_FILE_CONTENTS}")
143 | string(REGEX REPLACE "#define EIGEN_MAJOR_VERSION ([0-9]+)" "\\1"
144 | EIGEN_MAJOR_VERSION "${EIGEN_MAJOR_VERSION}")
145 |
146 | string(REGEX MATCH "#define EIGEN_MINOR_VERSION [0-9]+"
147 | EIGEN_MINOR_VERSION "${EIGEN_VERSION_FILE_CONTENTS}")
148 | string(REGEX REPLACE "#define EIGEN_MINOR_VERSION ([0-9]+)" "\\1"
149 | EIGEN_MINOR_VERSION "${EIGEN_MINOR_VERSION}")
150 |
151 | # This is on a single line s/t CMake does not interpret it as a list of
152 | # elements and insert ';' separators which would result in 3.;2.;0 nonsense.
153 | set(EIGEN_VERSION "${EIGEN_WORLD_VERSION}.${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION}")
154 | endif (NOT EXISTS ${EIGEN_VERSION_FILE})
155 | endif (EIGEN_INCLUDE_DIR)
156 |
157 | # Set standard CMake FindPackage variables if found.
158 | if (EIGEN_FOUND)
159 | set(EIGEN_INCLUDE_DIRS ${EIGEN_INCLUDE_DIR})
160 | endif (EIGEN_FOUND)
161 |
162 | # Handle REQUIRED / QUIET optional arguments and version.
163 | include(FindPackageHandleStandardArgs)
164 | find_package_handle_standard_args(Eigen
165 | REQUIRED_VARS EIGEN_INCLUDE_DIRS
166 | VERSION_VAR EIGEN_VERSION)
167 |
168 | # Only mark internal variables as advanced if we found Eigen, otherwise
169 | # leave it visible in the standard GUI for the user to set manually.
170 | if (EIGEN_FOUND)
171 | mark_as_advanced(FORCE EIGEN_INCLUDE_DIR)
172 | endif (EIGEN_FOUND)
173 |
--------------------------------------------------------------------------------
/estimator/launch/simulator.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/estimator/launch/visensor_f9p.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/estimator/msg/LocalSensorExternalTrigger.msg:
--------------------------------------------------------------------------------
1 | # This message contains essential time information of the
2 | # local sensor (visual/inertial sensor) when get triggered
3 | Header header # local timestamp of the trigger
4 | uint32 trigger_id
5 | uint32 event_id
6 | time timestamp_host # corresponding timestamp of the Host PC, not used in GVINS
--------------------------------------------------------------------------------
/estimator/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | gvins
4 | 1.0.0
5 | The GVINS package
6 |
7 | CAO Shaozu
8 |
9 | GPLv3
10 |
11 | catkin
12 | roscpp
13 | message_generation
14 | gnss_comm
15 |
16 | roscpp
17 | message_generation
18 | gnss_comm
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/estimator/src/estimator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include "parameters.h"
5 | #include "feature_manager.h"
6 | #include "utility/utility.h"
7 | #include "utility/tic_toc.h"
8 | #include "initial/solve_5pts.h"
9 | #include "initial/initial_sfm.h"
10 | #include "initial/initial_alignment.h"
11 | #include "initial/initial_ex_rotation.h"
12 | #include "initial/gnss_vi_initializer.h"
13 | #include
14 |
15 | #include
16 | #include "factor/imu_factor.h"
17 | #include "factor/pose_local_parameterization.h"
18 | #include "factor/projection_factor.h"
19 | #include "factor/projection_td_factor.h"
20 | #include "factor/marginalization_factor.h"
21 | #include "factor/gnss_psr_dopp_factor.hpp"
22 | #include "factor/gnss_dt_ddt_factor.hpp"
23 | #include "factor/gnss_dt_anchor_factor.hpp"
24 | #include "factor/gnss_ddt_smooth_factor.hpp"
25 | #include "factor/pos_vel_factor.hpp"
26 | #include "factor/pose_anchor_factor.h"
27 |
28 | #include
29 |
30 | #include
31 | #include
32 | #include
33 |
34 | using namespace gnss_comm;
35 |
36 | class Estimator
37 | {
38 | public:
39 | Estimator();
40 |
41 | void setParameter();
42 |
43 | // interface
44 | void processIMU(double t, const Vector3d &linear_acceleration, const Vector3d &angular_velocity);
45 | void processGNSS(const std::vector &gnss_mea);
46 | void inputEphem(EphemBasePtr ephem_ptr);
47 | void inputIonoParams(double ts, const std::vector &iono_params);
48 | void inputGNSSTimeDiff(const double t_diff);
49 |
50 | void processImage(const map>>> &image, const std_msgs::Header &header);
51 |
52 | // internal
53 | void clearState();
54 | bool initialStructure();
55 | bool visualInitialAlign();
56 | // GNSS related
57 | bool GNSSVIAlign();
58 |
59 | void updateGNSSStatistics();
60 |
61 | bool relativePose(Matrix3d &relative_R, Vector3d &relative_T, int &l);
62 | void slideWindow();
63 | void solveOdometry();
64 | void slideWindowNew();
65 | void slideWindowOld();
66 | void optimization();
67 | void vector2double();
68 | void double2vector();
69 | bool failureDetection();
70 |
71 | enum SolverFlag
72 | {
73 | INITIAL,
74 | NON_LINEAR
75 | };
76 |
77 | enum MarginalizationFlag
78 | {
79 | MARGIN_OLD = 0,
80 | MARGIN_SECOND_NEW = 1
81 | };
82 |
83 | SolverFlag solver_flag;
84 | MarginalizationFlag marginalization_flag;
85 | Vector3d g;
86 | // MatrixXd Ap[2];
87 | // VectorXd bp[2];
88 |
89 | Matrix3d ric[NUM_OF_CAM];
90 | Vector3d tic[NUM_OF_CAM];
91 |
92 | Vector3d Ps[(WINDOW_SIZE + 1)];
93 | Vector3d Vs[(WINDOW_SIZE + 1)];
94 | Matrix3d Rs[(WINDOW_SIZE + 1)];
95 | Vector3d Bas[(WINDOW_SIZE + 1)];
96 | Vector3d Bgs[(WINDOW_SIZE + 1)];
97 | double td;
98 |
99 | Matrix3d back_R0, last_R, last_R0;
100 | Vector3d back_P0, last_P, last_P0;
101 | std_msgs::Header Headers[(WINDOW_SIZE + 1)];
102 |
103 | IntegrationBase *pre_integrations[(WINDOW_SIZE + 1)];
104 | Vector3d acc_0, gyr_0;
105 |
106 | vector dt_buf[(WINDOW_SIZE + 1)];
107 | vector linear_acceleration_buf[(WINDOW_SIZE + 1)];
108 | vector angular_velocity_buf[(WINDOW_SIZE + 1)];
109 |
110 | // GNSS related
111 | bool gnss_ready;
112 | Eigen::Vector3d anc_ecef;
113 | Eigen::Matrix3d R_ecef_enu;
114 | double yaw_enu_local;
115 | std::vector gnss_meas_buf[(WINDOW_SIZE+1)];
116 | std::vector gnss_ephem_buf[(WINDOW_SIZE+1)];
117 | std::vector latest_gnss_iono_params;
118 | std::map> sat2ephem;
119 | std::map> sat2time_index;
120 | std::map sat_track_status;
121 | double para_anc_ecef[3];
122 | double para_yaw_enu_local[1];
123 | double para_rcv_dt[(WINDOW_SIZE+1)*4];
124 | double para_rcv_ddt[WINDOW_SIZE+1];
125 | // GNSS statistics
126 | double diff_t_gnss_local;
127 | Eigen::Matrix3d R_enu_local;
128 | Eigen::Vector3d ecef_pos, enu_pos, enu_vel, enu_ypr;
129 |
130 | int frame_count;
131 | int sum_of_outlier, sum_of_back, sum_of_front, sum_of_invalid;
132 |
133 | FeatureManager f_manager;
134 | MotionEstimator m_estimator;
135 | InitialEXRotation initial_ex_rotation;
136 |
137 | bool first_imu;
138 | bool is_valid, is_key;
139 | bool failure_occur;
140 |
141 | vector point_cloud;
142 | vector margin_cloud;
143 | vector key_poses;
144 | double initial_timestamp;
145 |
146 | double para_Pose[WINDOW_SIZE + 1][SIZE_POSE];
147 | double para_SpeedBias[WINDOW_SIZE + 1][SIZE_SPEEDBIAS];
148 | double para_Feature[NUM_OF_F][SIZE_FEATURE];
149 | double para_Ex_Pose[NUM_OF_CAM][SIZE_POSE];
150 | double para_Td[1][1];
151 |
152 | MarginalizationInfo *last_marginalization_info;
153 | vector last_marginalization_parameter_blocks;
154 |
155 | map all_image_frame;
156 | IntegrationBase *tmp_pre_integration;
157 |
158 | bool first_optimization;
159 | };
160 |
--------------------------------------------------------------------------------
/estimator/src/factor/gnss_ddt_smooth_factor.cpp:
--------------------------------------------------------------------------------
1 | #include "gnss_ddt_smooth_factor.hpp"
2 |
3 | bool DdtSmoothFactor::Evaluate(double const *const *parameters, double *residuals, double **jacobians) const
4 | {
5 | double rcv_ddt_i = parameters[0][0];
6 | double rcv_ddt_j = parameters[1][0];
7 |
8 | residuals[0] = (rcv_ddt_i - rcv_ddt_j) * weight_;
9 |
10 | if (jacobians)
11 | {
12 | if (jacobians[0])
13 | {
14 | jacobians[0][0] = weight_;
15 | }
16 | if (jacobians[1])
17 | {
18 | jacobians[1][0] = -weight_;
19 | }
20 | }
21 | return true;
22 | }
--------------------------------------------------------------------------------
/estimator/src/factor/gnss_ddt_smooth_factor.hpp:
--------------------------------------------------------------------------------
1 | #ifndef DDT_SMOOTH_FACTOR_H_
2 | #define DDT_SMOOTH_FACTOR_H_
3 |
4 | #include
5 | #include
6 |
7 | /*
8 | ** parameters[0]: rev_ddt (t) in light travelling distance (m)
9 | ** parameters[1]: rev_ddt (t+1) in light travelling distance (m)
10 | */
11 | class DdtSmoothFactor : public ceres::SizedCostFunction<1, 1, 1>
12 | {
13 | public:
14 | DdtSmoothFactor(const double weight=1) : weight_(weight) {}
15 | virtual bool Evaluate(double const *const *parameters, double *residuals, double **jacobians) const;
16 | private:
17 | double weight_;
18 | };
19 |
20 | #endif
--------------------------------------------------------------------------------
/estimator/src/factor/gnss_dt_anchor_factor.cpp:
--------------------------------------------------------------------------------
1 | #include "gnss_dt_anchor_factor.hpp"
2 |
3 | bool DtAnchorFactor::Evaluate(double const *const *parameters, double *residuals, double **jacobians) const
4 | {
5 | double rev_dt_i = parameters[0][0];
6 |
7 | residuals[0] = (rev_dt_i - 0.0) * dt_anchor_coeff_; // anchor to 0
8 |
9 | if (jacobians)
10 | {
11 | if (jacobians[0])
12 | {
13 | jacobians[0][0] = dt_anchor_coeff_;
14 | }
15 | }
16 |
17 | return true;
18 | }
--------------------------------------------------------------------------------
/estimator/src/factor/gnss_dt_anchor_factor.hpp:
--------------------------------------------------------------------------------
1 | #ifndef DT_ANCHOR_FACTOR_H_
2 | #define DT_ANCHOR_FACTOR_H_
3 |
4 | #include
5 |
6 | /*
7 | ** parameters[0]: rev_dt (t) in light travelling distance (m)
8 | */
9 | class DtAnchorFactor : public ceres::SizedCostFunction<1, 1>
10 | {
11 | public:
12 | DtAnchorFactor(const double dt_anchor_coeff=1000) : dt_anchor_coeff_(dt_anchor_coeff) {}
13 | virtual bool Evaluate(double const *const *parameters, double *residuals, double **jacobians) const;
14 | private:
15 | double dt_anchor_coeff_;
16 | };
17 |
18 | #endif
--------------------------------------------------------------------------------
/estimator/src/factor/gnss_dt_ddt_factor.cpp:
--------------------------------------------------------------------------------
1 | #include "gnss_dt_ddt_factor.hpp"
2 |
3 | DtDdtFactor::DtDdtFactor(const double delta_t_) : delta_t(delta_t_), dt_info_coeff(50) {}
4 |
5 | bool DtDdtFactor::Evaluate(double const *const *parameters, double *residuals, double **jacobians) const
6 | {
7 | double rev_dt_i = parameters[0][0];
8 | double rev_dt_j = parameters[1][0];
9 | double rev_ddt_i = parameters[2][0];
10 | double rev_ddt_j = parameters[3][0];
11 |
12 | double average_ddt = 0.5 * (rev_ddt_i + rev_ddt_j);
13 | residuals[0] = (rev_dt_j - rev_dt_i - average_ddt * delta_t) * dt_info_coeff;
14 |
15 | if (jacobians)
16 | {
17 | if (jacobians[0])
18 | {
19 | jacobians[0][0] = -dt_info_coeff;
20 | }
21 | if (jacobians[1])
22 | {
23 | jacobians[1][0] = dt_info_coeff;
24 | }
25 | if (jacobians[2])
26 | {
27 | jacobians[2][0] = -0.5 * delta_t * dt_info_coeff;
28 | }
29 | if (jacobians[3])
30 | {
31 | jacobians[3][0] = -0.5 * delta_t * dt_info_coeff;
32 | }
33 | }
34 |
35 | return true;
36 | }
--------------------------------------------------------------------------------
/estimator/src/factor/gnss_dt_ddt_factor.hpp:
--------------------------------------------------------------------------------
1 |
2 | #ifndef DT_DDT_FACTOR_H_
3 | #define DT_DDT_FACTOR_H_
4 |
5 | #include