├── .gitignore
├── CMakeLists.txt
├── Doxyfile.in
├── LICENSE
├── README.md
├── manifest.xml
└── src
├── CMakeLists.txt
├── EDS.h
├── bundles
├── AccumulatedSCHessian.cpp
├── AccumulatedSCHessian.h
├── AccumulatedTopHessian.cpp
├── AccumulatedTopHessian.h
├── Config.hpp
├── EnergyFunctional.cpp
├── EnergyFunctional.h
├── EnergyFunctionalStructs.cpp
├── EnergyFunctionalStructs.h
├── MatrixAccumulators.h
└── RawResidualJacobian.h
├── eds.pc.in
├── init
├── CoarseInitializer.cpp
└── CoarseInitializer.h
├── io
├── ImageConvert.cpp
├── ImageConvert.h
├── ImageRW.cpp
├── ImageRW.h
├── OutputMaps.cpp
└── OutputMaps.h
├── mapping
├── Config.hpp
├── DepthPoints.cpp
├── DepthPoints.hpp
├── PixelSelector.cpp
├── PixelSelector.h
└── Types.hpp
├── sophus
├── rxso3.hpp
├── se2.hpp
├── se3.hpp
├── sim3.hpp
├── so2.hpp
├── so3.hpp
└── sophus.hpp
├── tracking
├── CoarseTracker.cpp
├── CoarseTracker.h
├── Config.hpp
├── EventFrame.cpp
├── EventFrame.hpp
├── HessianBlocks.cpp
├── HessianBlocks.h
├── ImmaturePoint.cpp
├── ImmaturePoint.h
├── KeyFrame.cpp
├── KeyFrame.hpp
├── PhotometricError.hpp
├── PhotometricErrorNC.hpp
├── ResidualProjections.h
├── Residuals.cpp
├── Residuals.h
├── Tracker.cpp
├── Tracker.hpp
└── Types.hpp
└── utils
├── Calib.cpp
├── Calib.hpp
├── Colormap.cpp
├── Colormap.hpp
├── Config.hpp
├── FrameShell.h
├── ImageAndExposure.h
├── IndexThreadReduce.h
├── KDTree.hpp
├── MinimalImage.h
├── NumType.h
├── Transforms.hpp
├── Undistort.cpp
├── Undistort.h
├── Utils.cpp
├── Utils.hpp
├── globalCalib.cpp
├── globalCalib.h
├── globalFuncs.h
├── nanoflann.h
├── settings.cpp
└── settings.h
/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | tags
3 | *.sw?
4 | Doxyfile
5 | *.pc
6 | *.orig
7 | CMakeFiles
8 | CMakeCache.txt
9 | *.kdev4
10 | *.*~
11 | patches-*-stamp
12 | .vscode
13 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # CMakeLists.txt has to be located in the project folder and cmake has to be
2 | # executed from 'project/build' with 'cmake ../'.
3 | cmake_minimum_required(VERSION 3.9)
4 | project(eds
5 | VERSION 0.1
6 | DESCRIPTION "Event-based Sparse Odometry")
7 | find_package(Rock)
8 |
9 | set(CMAKE_CXX_STANDARD 14)
10 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
11 | set(ROCK_TEST_ENABLED OFF)
12 |
13 | if(COVERAGE)
14 | if(CMAKE_BUILD_TYPE MATCHES Debug)
15 | add_definitions(-fprofile-arcs -ftest-coverage)
16 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -lgcov")
17 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -lgcov")
18 | set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -lgcov")
19 |
20 | add_custom_target(coverage
21 | COMMAND lcov --directory . --capture --output-file cov.info
22 | COMMAND lcov --remove cov.info 'tests/*' '/usr/*' '*/install/include/*' --output-file cov.info.cleaned
23 | COMMAND genhtml -o ./cov cov.info.cleaned
24 | COMMAND cmake -E remove cov.info cov.info.cleaned
25 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
26 | )
27 | else()
28 | message(FATAL_ERROR "Code coverage only works in Debug versions" )
29 | endif()
30 | endif()
31 |
32 | rock_init()
33 | rock_opencv_autodetect(OPENCV_PACKAGE)
34 | rock_standard_layout()
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | Event-aided Direct Sparse Odometry (EDS)
3 | =============
4 | Direct visual odometry approach using events and frames (CVPR 2022)
5 |
6 | License
7 | -------
8 | See LICENSE file
9 |
10 |
11 | Installation
12 | ------------
13 | The easiest way to build and install this package is to use Rock's build system.
14 | See [this page](http://rock-robotics.org/documentation/installation.html)
15 | on how to install Rock. You can use the [EDS builconf](https://github.com/uzh-rpg/eds-buildconf)
16 | which tells you how to install and use this library from scratch. There is also the option
17 | to build and use this library in a Docker container.
18 |
19 | However, if you feel that it's too heavy for your needs, Rock aims at having
20 | most of its "library" packages (such as this one) to follow best practices. See
21 | [this page](http://rock-robotics.org/documentation/packages/outside_of_rock.html)
22 | for installation instructions outside of Rock. It means this library and
23 | its dependencies are standard C++ libraries. Therefore you can build your own
24 | EDS system based on this code which is out of the Rock ecosystem.
25 |
26 | Dependencies
27 | -----------------
28 | This is an standard C++ library which generates a shared library by default.
29 | Dependencies are listed in the manifest file, those are:
30 |
31 | * [base/cmake](https://github.com/rock-core/base-cmake): the CMake pure function to build this library
32 | * [base/types](https://github.com/rock-core/base-types): C++ basic types (types depends on std C++ and Eigen)
33 | * [base/logging](https://github.com/rock-core/base-logging): C++ library for logging (similar to Google glog)
34 | * [slam/ceres_solver](https://github.com/ceres-solver/ceres-solver): the Ceres solver library
35 | * [slam/pcl](https://pointclouds.org): the point cloud library
36 | * [opencv](https://github.com/opencv/opencv/tree/4.2.0): Open source Computer Vision library. Ubuntu 20.04 uses 4.2.0
37 | * [yaml-cpp](https://github.com/jbeder/yaml-cpp): YAML config parser for the configuration parameters
38 |
39 |
40 | Rock CMake Macros
41 | -----------------
42 | This package uses a set of CMake helper shipped as the Rock CMake macros.
43 | Documentations is available on [this page](http://rock-robotics.org/documentation/packages/cmake_macros.html).
44 | These macros are pure CMake functions, so they are totally independent of the Rock
45 | ecosystem.
46 |
47 | Library Standard Layout
48 | --------------------
49 | This directory structure follows some simple rules, to allow for generic build
50 | processes and simplify reuse of this project. Following these rules ensures that
51 | the Rock CMake macros automatically handle the project's build process and
52 | install setup properly.
53 |
54 | ### EDS Folder Structure
55 |
56 | | directory | purpose |
57 | | ----------------- | ------------------------------------------------------ |
58 | | src/ | Contains all header (*.h/*.hpp) and source files |
59 | | src/bundles | This is the backend optimation from DSO |
60 | | src/init | This is the DSO initializer class |
61 | | src/io | I/O wrapper from images and maps different types |
62 | | src/mapping | This is the pixel selector based on DSO |
63 | | src/sophus | The Sophus template header-only library based on Eigen |
64 | | src/tracking | This is the EDS tracker to perform Events to Model alignment |
65 | | src/utils | Some utils functions |
66 | | build/ * | The target directory for the build process, temporary content |
67 | | test/ | Boost Unit test to check basic class functionalities |
68 |
--------------------------------------------------------------------------------
/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Events-based Sparse Odometry. Direct approach using events and frames
4 |
5 | Javier Hidalgo-Carrió/havyhidalgo@gmail.com
6 | GPL v3 or higher (see LICENSE file)
7 | https://rpg.ifi.uzh.ch/eds
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | needs_opt
18 |
19 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | rock_find_pkgconfig(EIGEN3 eigen3 REQUIRED)
2 | find_package(Boost REQUIRED COMPONENTS filesystem thread system)
3 | find_package(OpenCV REQUIRED core imgproc calib3d highgui)
4 | find_package(Ceres REQUIRED)
5 | find_package(PCL 1.7 REQUIRED COMPONENTS common filters)
6 |
7 | rock_library(eds
8 | SOURCES
9 | bundles/AccumulatedSCHessian.cpp
10 | bundles/AccumulatedTopHessian.cpp
11 | bundles/EnergyFunctional.cpp
12 | bundles/EnergyFunctionalStructs.cpp
13 | init/CoarseInitializer.cpp
14 | io/ImageRW.cpp
15 | io/ImageConvert.cpp
16 | io/OutputMaps.cpp
17 | mapping/PixelSelector.cpp
18 | mapping/DepthPoints.cpp
19 | tracking/CoarseTracker.cpp
20 | tracking/EventFrame.cpp
21 | tracking/HessianBlocks.cpp
22 | tracking/ImmaturePoint.cpp
23 | tracking/KeyFrame.cpp
24 | tracking/Residuals.cpp
25 | tracking/Tracker.cpp
26 | utils/Calib.cpp
27 | utils/Colormap.cpp
28 | utils/globalCalib.cpp
29 | utils/settings.cpp
30 | utils/Undistort.cpp
31 | utils/Utils.cpp
32 |
33 | HEADERS
34 | bundles/Config.hpp
35 | bundles/AccumulatedSCHessian.h
36 | bundles/AccumulatedTopHessian.h
37 | bundles/EnergyFunctional.h
38 | bundles/EnergyFunctionalStructs.h
39 | bundles/MatrixAccumulators.h
40 | bundles/RawResidualJacobian.h
41 | init/CoarseInitializer.h
42 | io/ImageRW.h
43 | io/ImageConvert.h
44 | io/OutputMaps.h
45 | mapping/Config.hpp
46 | mapping/DepthPoints.hpp
47 | mapping/Types.hpp
48 | mapping/PixelSelector.h
49 | sophus/rxso3.hpp
50 | sophus/se2.hpp
51 | sophus/se3.hpp
52 | sophus/sim3.hpp
53 | sophus/so2.hpp
54 | sophus/so3.hpp
55 | sophus/sophus.hpp
56 | tracking/Config.hpp
57 | tracking/EventFrame.hpp
58 | tracking/KeyFrame.hpp
59 | tracking/PhotometricError.hpp
60 | tracking/PhotometricErrorNC.hpp
61 | tracking/Tracker.hpp
62 | tracking/Types.hpp
63 | tracking/CoarseTracker.h
64 | tracking/HessianBlocks.h
65 | tracking/ImmaturePoint.h
66 | tracking/ResidualProjections.h
67 | tracking/Residuals.h
68 | utils/Calib.hpp
69 | utils/Colormap.hpp
70 | utils/Config.hpp
71 | utils/KDTree.hpp
72 | utils/Transforms.hpp
73 | utils/Utils.hpp
74 | utils/FrameShell.h
75 | utils/globalCalib.h
76 | utils/globalFuncs.h
77 | utils/ImageAndExposure.h
78 | utils/IndexThreadReduce.h
79 | utils/MinimalImage.h
80 | utils/nanoflann.h
81 | utils/NumType.h
82 | utils/settings.h
83 | utils/Undistort.h
84 | EDS.h
85 | DEPS_TARGET
86 | ceres
87 | DEPS_PKGCONFIG
88 | base-types
89 | base-logging
90 | yaml-cpp
91 | frame_helper
92 | pcl_common-${PCL_VERSION_MAJOR}.${PCL_VERSION_MINOR}
93 | pcl_filters-${PCL_VERSION_MAJOR}.${PCL_VERSION_MINOR}
94 | ${OPENCV_PACKAGE}
95 | DEPS_PLAIN Boost_SYSTEM Boost_FILESYSTEM Boost_THREAD
96 | )
97 |
--------------------------------------------------------------------------------
/src/EDS.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EDS: Event-aided Direct Sparse Odometry
3 | * (https://rpg.ifi.uzh.ch/eds.html)
4 | *
5 | * Copyright (c) 2022 Javier Hidalgo-Carrió, Robotics and Perception
6 | * Group (RPG) University of Zurich.
7 | *
8 | * EDS is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, version 3.
11 | *
12 | * EDS is distributed in the hope that it will be useful, but
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 |
21 | #ifndef EDS_EDS_H
22 | #define EDS_EDS_H
23 |
24 | /** Base types **/
25 | #include
26 |
27 | /** Settings **/
28 | #include
29 |
30 | /** Utils **/
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 |
41 | /** I/O **/
42 | #include
43 | #include
44 | #include
45 |
46 | /** Initialization **/
47 | #include
48 |
49 | /** Event Tracker (EDS) **/
50 | #include
51 | #include
52 | #include
53 |
54 | /** Frame Tracker (DSO) **/
55 | #include
56 | #include
57 | #include
58 | #include
59 |
60 | /** Mapping **/
61 | #include
62 | #include
63 | #include
64 |
65 | /** Bundles **/
66 | #include
67 | #include
68 | #include
69 | #include
70 |
71 | #endif //EDS_EDS_H
--------------------------------------------------------------------------------
/src/bundles/AccumulatedSCHessian.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of DSO.
3 | *
4 | * Copyright 2016 Technical University of Munich and Intel.
5 | * Developed by Jakob Engel ,
6 | * for more information see .
7 | * If you use this code, please cite the respective publications as
8 | * listed on the above website.
9 | *
10 | * DSO is free software: you can redistribute it and/or modify
11 | * it under the terms of the GNU General Public License as published by
12 | * the Free Software Foundation, either version 3 of the License, or
13 | * (at your option) any later version.
14 | *
15 | * DSO is distributed in the hope that it will be useful,
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | * GNU General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with DSO. If not, see .
22 | */
23 |
24 |
25 | #include "eds/bundles/AccumulatedSCHessian.h"
26 | #include "eds/bundles/EnergyFunctional.h"
27 | #include "eds/bundles/EnergyFunctionalStructs.h"
28 |
29 | #include "eds/tracking/HessianBlocks.h"
30 |
31 | namespace dso
32 | {
33 |
34 | void AccumulatedSCHessianSSE::addPoint(EFPoint* p, bool shiftPriorToZero, int tid)
35 | {
36 | int ngoodres = 0;
37 | for(EFResidual* r : p->residualsAll) if(r->isActive()) ngoodres++;
38 | if(ngoodres==0)
39 | {
40 | p->HdiF=0;
41 | p->bdSumF=0;
42 | p->data->idepth_hessian=0;
43 | p->data->maxRelBaseline=0;
44 | return;
45 | }
46 |
47 | float H = p->Hdd_accAF+p->Hdd_accLF+p->priorF;
48 | if(H < 1e-10) H = 1e-10;
49 |
50 | p->data->idepth_hessian=H;
51 |
52 | p->HdiF = 1.0 / H;
53 | p->bdSumF = p->bd_accAF + p->bd_accLF;
54 | if(shiftPriorToZero) p->bdSumF += p->priorF*p->deltaF;
55 | VecCf Hcd = p->Hcd_accAF + p->Hcd_accLF;
56 | accHcc[tid].update(Hcd,Hcd,p->HdiF);
57 | accbc[tid].update(Hcd, p->bdSumF * p->HdiF);
58 |
59 | assert(std::isfinite((float)(p->HdiF)));
60 |
61 | int nFrames2 = nframes[tid]*nframes[tid];
62 | for(EFResidual* r1 : p->residualsAll)
63 | {
64 | if(!r1->isActive()) continue;
65 | int r1ht = r1->hostIDX + r1->targetIDX*nframes[tid];
66 |
67 | for(EFResidual* r2 : p->residualsAll)
68 | {
69 | if(!r2->isActive()) continue;
70 |
71 | accD[tid][r1ht+r2->targetIDX*nFrames2].update(r1->JpJdF, r2->JpJdF, p->HdiF);
72 | }
73 |
74 | accE[tid][r1ht].update(r1->JpJdF, Hcd, p->HdiF);
75 | accEB[tid][r1ht].update(r1->JpJdF,p->HdiF*p->bdSumF);
76 | }
77 | }
78 | void AccumulatedSCHessianSSE::stitchDoubleInternal(
79 | MatXX* H, VecX* b, EnergyFunctional const * const EF,
80 | int min, int max, Vec10* stats, int tid)
81 | {
82 | int toAggregate = NUM_THREADS;
83 | if(tid == -1) { toAggregate = 1; tid = 0; } // special case: if we dont do multithreading, dont aggregate.
84 | if(min==max) return;
85 |
86 |
87 | int nf = nframes[0];
88 | int nframes2 = nf*nf;
89 |
90 | for(int k=min;k();
107 | bp += accEB[tid2][ijIdx].A1m.cast();
108 | }
109 |
110 | H[tid].block<8,CPARS>(iIdx,0) += EF->adHost[ijIdx] * Hpc;
111 | H[tid].block<8,CPARS>(jIdx,0) += EF->adTarget[ijIdx] * Hpc;
112 | b[tid].segment<8>(iIdx) += EF->adHost[ijIdx] * bp;
113 | b[tid].segment<8>(jIdx) += EF->adTarget[ijIdx] * bp;
114 |
115 |
116 |
117 | for(int k=0;k();
130 | }
131 |
132 | H[tid].block<8,8>(iIdx, iIdx) += EF->adHost[ijIdx] * accDM * EF->adHost[ikIdx].transpose();
133 | H[tid].block<8,8>(jIdx, kIdx) += EF->adTarget[ijIdx] * accDM * EF->adTarget[ikIdx].transpose();
134 | H[tid].block<8,8>(jIdx, iIdx) += EF->adTarget[ijIdx] * accDM * EF->adHost[ikIdx].transpose();
135 | H[tid].block<8,8>(iIdx, kIdx) += EF->adHost[ijIdx] * accDM * EF->adTarget[ikIdx].transpose();
136 | }
137 | }
138 |
139 | if(min==0)
140 | {
141 | for(int tid2=0;tid2 < toAggregate;tid2++)
142 | {
143 | accHcc[tid2].finish();
144 | accbc[tid2].finish();
145 | H[tid].topLeftCorner() += accHcc[tid2].A1m.cast();
146 | b[tid].head() += accbc[tid2].A1m.cast();
147 | }
148 | }
149 |
150 |
151 | // // ----- new: copy transposed parts for calibration only.
152 | // for(int h=0;h(0,hIdx).noalias() = H.block<8,4>(hIdx,0).transpose();
156 | // }
157 | }
158 |
159 | void AccumulatedSCHessianSSE::stitchDouble(MatXX &H, VecX &b, EnergyFunctional const * const EF, int tid)
160 | {
161 |
162 | int nf = nframes[0];
163 | int nframes2 = nf*nf;
164 |
165 | H = MatXX::Zero(nf*8+CPARS, nf*8+CPARS);
166 | b = VecX::Zero(nf*8+CPARS);
167 |
168 |
169 | for(int i=0;i();
180 | Vec8 accEBV = accEB[tid][ijIdx].A1m.cast();
181 |
182 | H.block<8,CPARS>(iIdx,0) += EF->adHost[ijIdx] * accEM;
183 | H.block<8,CPARS>(jIdx,0) += EF->adTarget[ijIdx] * accEM;
184 |
185 | b.segment<8>(iIdx) += EF->adHost[ijIdx] * accEBV;
186 | b.segment<8>(jIdx) += EF->adTarget[ijIdx] * accEBV;
187 |
188 | for(int k=0;k();
197 |
198 | H.block<8,8>(iIdx, iIdx) += EF->adHost[ijIdx] * accDM * EF->adHost[ikIdx].transpose();
199 |
200 | H.block<8,8>(jIdx, kIdx) += EF->adTarget[ijIdx] * accDM * EF->adTarget[ikIdx].transpose();
201 |
202 | H.block<8,8>(jIdx, iIdx) += EF->adTarget[ijIdx] * accDM * EF->adHost[ikIdx].transpose();
203 |
204 | H.block<8,8>(iIdx, kIdx) += EF->adHost[ijIdx] * accDM * EF->adTarget[ikIdx].transpose();
205 | }
206 | }
207 |
208 | accHcc[tid].finish();
209 | accbc[tid].finish();
210 | H.topLeftCorner() = accHcc[tid].A1m.cast();
211 | b.head() = accbc[tid].A1m.cast();
212 |
213 | // ----- new: copy transposed parts for calibration only.
214 | for(int h=0;h(0,hIdx).noalias() = H.block<8,CPARS>(hIdx,0).transpose();
218 | }
219 | }
220 |
221 | }
222 |
--------------------------------------------------------------------------------
/src/bundles/AccumulatedSCHessian.h:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of DSO.
3 | *
4 | * Copyright 2016 Technical University of Munich and Intel.
5 | * Developed by Jakob Engel ,
6 | * for more information see .
7 | * If you use this code, please cite the respective publications as
8 | * listed on the above website.
9 | *
10 | * DSO is free software: you can redistribute it and/or modify
11 | * it under the terms of the GNU General Public License as published by
12 | * the Free Software Foundation, either version 3 of the License, or
13 | * (at your option) any later version.
14 | *
15 | * DSO is distributed in the hope that it will be useful,
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | * GNU General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with DSO. If not, see .
22 | */
23 |
24 |
25 | #pragma once
26 |
27 |
28 | #include "eds/utils/NumType.h"
29 | #include "eds/utils/IndexThreadReduce.h"
30 | #include "eds/bundles/MatrixAccumulators.h"
31 | #include "vector"
32 | #include
33 |
34 | namespace dso
35 | {
36 |
37 | class EFPoint;
38 | class EnergyFunctional;
39 |
40 |
41 | class AccumulatedSCHessianSSE
42 | {
43 | public:
44 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
45 | inline AccumulatedSCHessianSSE()
46 | {
47 | for(int i=0;i[n*n];
73 | accEB[tid] = new AccumulatorX<8>[n*n];
74 | accD[tid] = new AccumulatorXX<8,8>[n*n*n];
75 | }
76 | accbc[tid].initialize();
77 | accHcc[tid].initialize();
78 |
79 | for(int i=0;i* red, MatXX &H, VecX &b, EnergyFunctional const * const EF, bool MT)
94 | {
95 | // sum up, splitting by bock in square.
96 | if(MT)
97 | {
98 | MatXX Hs[NUM_THREADS];
99 | VecX bs[NUM_THREADS];
100 | for(int i=0;ireduce(boost::bind(&AccumulatedSCHessianSSE::stitchDoubleInternal,
108 | this,Hs, bs, EF, _1, _2, _3, _4), 0, nframes[0]*nframes[0], 0);
109 |
110 | // sum up results
111 | H = Hs[0];
112 | b = bs[0];
113 |
114 | for(int i=1;i(0,hIdx).noalias() = H.block<8,CPARS>(hIdx,0).transpose();
132 | }
133 | }
134 |
135 |
136 | AccumulatorXX<8,CPARS>* accE[NUM_THREADS];
137 | AccumulatorX<8>* accEB[NUM_THREADS];
138 | AccumulatorXX<8,8>* accD[NUM_THREADS];
139 | AccumulatorXX accHcc[NUM_THREADS];
140 | AccumulatorX accbc[NUM_THREADS];
141 | int nframes[NUM_THREADS];
142 |
143 |
144 | void addPointsInternal(
145 | std::vector* points, bool shiftPriorToZero,
146 | int min=0, int max=1, Vec10* stats=0, int tid=0)
147 | {
148 | for(int i=min;i,
6 | * for more information see .
7 | * If you use this code, please cite the respective publications as
8 | * listed on the above website.
9 | *
10 | * DSO is free software: you can redistribute it and/or modify
11 | * it under the terms of the GNU General Public License as published by
12 | * the Free Software Foundation, either version 3 of the License, or
13 | * (at your option) any later version.
14 | *
15 | * DSO is distributed in the hope that it will be useful,
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | * GNU General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with DSO. If not, see .
22 | */
23 |
24 |
25 | #include "eds/bundles/AccumulatedTopHessian.h"
26 | #include "eds/bundles/EnergyFunctional.h"
27 | #include "eds/bundles/EnergyFunctionalStructs.h"
28 | #include
29 |
30 | #if !defined(__SSE3__) && !defined(__SSE2__) && !defined(__SSE1__)
31 | #include "SSE2NEON.h"
32 | #endif
33 |
34 | namespace dso
35 | {
36 |
37 |
38 |
39 | template
40 | void AccumulatedTopHessianSSE::addPoint(EFPoint* p, EnergyFunctional const * const ef, int tid) // 0 = active, 1 = linearized, 2=marginalize
41 | {
42 |
43 |
44 | assert(mode==0 || mode==1 || mode==2);
45 |
46 | VecCf dc = ef->cDeltaF;
47 | float dd = p->deltaF;
48 |
49 | float bd_acc=0;
50 | float Hdd_acc=0;
51 | VecCf Hcd_acc = VecCf::Zero();
52 |
53 | for(EFResidual* r : p->residualsAll)
54 | {
55 | if(mode==0)
56 | {
57 | if(r->isLinearized || !r->isActive()) continue;
58 | }
59 | if(mode==1)
60 | {
61 | if(!r->isLinearized || !r->isActive()) continue;
62 | }
63 | if(mode==2)
64 | {
65 | if(!r->isActive()) continue;
66 | assert(r->isLinearized);
67 | }
68 |
69 |
70 | RawResidualJacobian* rJ = r->J;
71 | int htIDX = r->hostIDX + r->targetIDX*nframes[tid];
72 | Mat18f dp = ef->adHTdeltaF[htIDX];
73 |
74 |
75 |
76 | VecNRf resApprox;
77 | if(mode==0)
78 | resApprox = rJ->resF;
79 | if(mode==2)
80 | resApprox = r->res_toZeroF;
81 | if(mode==1)
82 | {
83 | // compute Jp*delta
84 | __m128 Jp_delta_x = _mm_set1_ps(rJ->Jpdxi[0].dot(dp.head<6>())+rJ->Jpdc[0].dot(dc)+rJ->Jpdd[0]*dd);
85 | __m128 Jp_delta_y = _mm_set1_ps(rJ->Jpdxi[1].dot(dp.head<6>())+rJ->Jpdc[1].dot(dc)+rJ->Jpdd[1]*dd);
86 | __m128 delta_a = _mm_set1_ps((float)(dp[6]));
87 | __m128 delta_b = _mm_set1_ps((float)(dp[7]));
88 |
89 | for(int i=0;ires_toZeroF)+i);
93 | rtz = _mm_add_ps(rtz,_mm_mul_ps(_mm_load_ps(((float*)(rJ->JIdx))+i),Jp_delta_x));
94 | rtz = _mm_add_ps(rtz,_mm_mul_ps(_mm_load_ps(((float*)(rJ->JIdx+1))+i),Jp_delta_y));
95 | rtz = _mm_add_ps(rtz,_mm_mul_ps(_mm_load_ps(((float*)(rJ->JabF))+i),delta_a));
96 | rtz = _mm_add_ps(rtz,_mm_mul_ps(_mm_load_ps(((float*)(rJ->JabF+1))+i),delta_b));
97 | _mm_store_ps(((float*)&resApprox)+i, rtz);
98 | }
99 | }
100 |
101 | // need to compute JI^T * r, and Jab^T * r. (both are 2-vectors).
102 | Vec2f JI_r(0,0);
103 | Vec2f Jab_r(0,0);
104 | float rr=0;
105 | for(int i=0;iJIdx[0][i];
108 | JI_r[1] += resApprox[i] *rJ->JIdx[1][i];
109 | Jab_r[0] += resApprox[i] *rJ->JabF[0][i];
110 | Jab_r[1] += resApprox[i] *rJ->JabF[1][i];
111 | rr += resApprox[i]*resApprox[i];
112 | }
113 |
114 |
115 | acc[tid][htIDX].update(
116 | rJ->Jpdc[0].data(), rJ->Jpdxi[0].data(),
117 | rJ->Jpdc[1].data(), rJ->Jpdxi[1].data(),
118 | rJ->JIdx2(0,0),rJ->JIdx2(0,1),rJ->JIdx2(1,1));
119 |
120 | acc[tid][htIDX].updateBotRight(
121 | rJ->Jab2(0,0), rJ->Jab2(0,1), Jab_r[0],
122 | rJ->Jab2(1,1), Jab_r[1],rr);
123 |
124 | acc[tid][htIDX].updateTopRight(
125 | rJ->Jpdc[0].data(), rJ->Jpdxi[0].data(),
126 | rJ->Jpdc[1].data(), rJ->Jpdxi[1].data(),
127 | rJ->JabJIdx(0,0), rJ->JabJIdx(0,1),
128 | rJ->JabJIdx(1,0), rJ->JabJIdx(1,1),
129 | JI_r[0], JI_r[1]);
130 |
131 |
132 | Vec2f Ji2_Jpdd = rJ->JIdx2 * rJ->Jpdd;
133 | bd_acc += JI_r[0]*rJ->Jpdd[0] + JI_r[1]*rJ->Jpdd[1];
134 | Hdd_acc += Ji2_Jpdd.dot(rJ->Jpdd);
135 | Hcd_acc += rJ->Jpdc[0]*Ji2_Jpdd[0] + rJ->Jpdc[1]*Ji2_Jpdd[1];
136 |
137 | nres[tid]++;
138 | }
139 |
140 | if(mode==0)
141 | {
142 | p->Hdd_accAF = Hdd_acc;
143 | p->bd_accAF = bd_acc;
144 | p->Hcd_accAF = Hcd_acc;
145 | }
146 | if(mode==1 || mode==2)
147 | {
148 | p->Hdd_accLF = Hdd_acc;
149 | p->bd_accLF = bd_acc;
150 | p->Hcd_accLF = Hcd_acc;
151 | }
152 | if(mode==2)
153 | {
154 | p->Hcd_accAF.setZero();
155 | p->Hdd_accAF = 0;
156 | p->bd_accAF = 0;
157 | }
158 |
159 | }
160 | template void AccumulatedTopHessianSSE::addPoint<0>(EFPoint* p, EnergyFunctional const * const ef, int tid);
161 | template void AccumulatedTopHessianSSE::addPoint<1>(EFPoint* p, EnergyFunctional const * const ef, int tid);
162 | template void AccumulatedTopHessianSSE::addPoint<2>(EFPoint* p, EnergyFunctional const * const ef, int tid);
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 | void AccumulatedTopHessianSSE::stitchDouble(MatXX &H, VecX &b, EnergyFunctional const * const EF, bool usePrior, bool useDelta, int tid)
172 | {
173 | H = MatXX::Zero(nframes[tid]*8+CPARS, nframes[tid]*8+CPARS);
174 | b = VecX::Zero(nframes[tid]*8+CPARS);
175 |
176 |
177 | for(int h=0;h();
190 |
191 |
192 | H.block<8,8>(hIdx, hIdx).noalias() += EF->adHost[aidx] * accH.block<8,8>(CPARS,CPARS) * EF->adHost[aidx].transpose();
193 |
194 | H.block<8,8>(tIdx, tIdx).noalias() += EF->adTarget[aidx] * accH.block<8,8>(CPARS,CPARS) * EF->adTarget[aidx].transpose();
195 |
196 | H.block<8,8>(hIdx, tIdx).noalias() += EF->adHost[aidx] * accH.block<8,8>(CPARS,CPARS) * EF->adTarget[aidx].transpose();
197 |
198 | H.block<8,CPARS>(hIdx,0).noalias() += EF->adHost[aidx] * accH.block<8,CPARS>(CPARS,0);
199 |
200 | H.block<8,CPARS>(tIdx,0).noalias() += EF->adTarget[aidx] * accH.block<8,CPARS>(CPARS,0);
201 |
202 | H.topLeftCorner().noalias() += accH.block(0,0);
203 |
204 | b.segment<8>(hIdx).noalias() += EF->adHost[aidx] * accH.block<8,1>(CPARS,8+CPARS);
205 |
206 | b.segment<8>(tIdx).noalias() += EF->adTarget[aidx] * accH.block<8,1>(CPARS,8+CPARS);
207 |
208 | b.head().noalias() += accH.block(0,8+CPARS);
209 | }
210 |
211 |
212 | // ----- new: copy transposed parts.
213 | for(int h=0;h(0,hIdx).noalias() = H.block<8,CPARS>(hIdx,0).transpose();
217 |
218 | for(int t=h+1;t(hIdx, tIdx).noalias() += H.block<8,8>(tIdx, hIdx).transpose();
222 | H.block<8,8>(tIdx, hIdx).noalias() = H.block<8,8>(hIdx, tIdx).transpose();
223 | }
224 | }
225 |
226 |
227 | if(usePrior)
228 | {
229 | assert(useDelta);
230 | H.diagonal().head() += EF->cPrior;
231 | b.head() += EF->cPrior.cwiseProduct(EF->cDeltaF.cast());
232 | for(int h=0;h(CPARS+h*8) += EF->frames[h]->prior;
235 | b.segment<8>(CPARS+h*8) += EF->frames[h]->prior.cwiseProduct(EF->frames[h]->delta_prior);
236 | }
237 | }
238 | }
239 |
240 |
241 | void AccumulatedTopHessianSSE::stitchDoubleInternal(
242 | MatXX* H, VecX* b, EnergyFunctional const * const EF, bool usePrior,
243 | int min, int max, Vec10* stats, int tid)
244 | {
245 | int toAggregate = NUM_THREADS;
246 | if(tid == -1) { toAggregate = 1; tid = 0; } // special case: if we dont do multithreading, dont aggregate.
247 | if(min==max) return;
248 |
249 |
250 | for(int k=min;k();
268 | }
269 |
270 | H[tid].block<8,8>(hIdx, hIdx).noalias() += EF->adHost[aidx] * accH.block<8,8>(CPARS,CPARS) * EF->adHost[aidx].transpose();
271 |
272 | H[tid].block<8,8>(tIdx, tIdx).noalias() += EF->adTarget[aidx] * accH.block<8,8>(CPARS,CPARS) * EF->adTarget[aidx].transpose();
273 |
274 | H[tid].block<8,8>(hIdx, tIdx).noalias() += EF->adHost[aidx] * accH.block<8,8>(CPARS,CPARS) * EF->adTarget[aidx].transpose();
275 |
276 | H[tid].block<8,CPARS>(hIdx,0).noalias() += EF->adHost[aidx] * accH.block<8,CPARS>(CPARS,0);
277 |
278 | H[tid].block<8,CPARS>(tIdx,0).noalias() += EF->adTarget[aidx] * accH.block<8,CPARS>(CPARS,0);
279 |
280 | H[tid].topLeftCorner().noalias() += accH.block(0,0);
281 |
282 | b[tid].segment<8>(hIdx).noalias() += EF->adHost[aidx] * accH.block<8,1>(CPARS,CPARS+8);
283 |
284 | b[tid].segment<8>(tIdx).noalias() += EF->adTarget[aidx] * accH.block<8,1>(CPARS,CPARS+8);
285 |
286 | b[tid].head().noalias() += accH.block(0,CPARS+8);
287 |
288 | }
289 |
290 |
291 | // only do this on one thread.
292 | if(min==0 && usePrior)
293 | {
294 | H[tid].diagonal().head() += EF->cPrior;
295 | b[tid].head() += EF->cPrior.cwiseProduct(EF->cDeltaF.cast());
296 | for(int h=0;h(CPARS+h*8) += EF->frames[h]->prior;
299 | b[tid].segment<8>(CPARS+h*8) += EF->frames[h]->prior.cwiseProduct(EF->frames[h]->delta_prior);
300 |
301 | }
302 | }
303 | }
304 |
305 |
306 |
307 | }
308 |
309 |
310 |
--------------------------------------------------------------------------------
/src/bundles/AccumulatedTopHessian.h:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of DSO.
3 | *
4 | * Copyright 2016 Technical University of Munich and Intel.
5 | * Developed by Jakob Engel ,
6 | * for more information see .
7 | * If you use this code, please cite the respective publications as
8 | * listed on the above website.
9 | *
10 | * DSO is free software: you can redistribute it and/or modify
11 | * it under the terms of the GNU General Public License as published by
12 | * the Free Software Foundation, either version 3 of the License, or
13 | * (at your option) any later version.
14 | *
15 | * DSO is distributed in the hope that it will be useful,
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | * GNU General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with DSO. If not, see .
22 | */
23 |
24 |
25 | #pragma once
26 |
27 |
28 | #include "eds/utils/NumType.h"
29 | #include "eds/bundles/MatrixAccumulators.h"
30 | #include "vector"
31 | #include
32 | #include "eds/utils/IndexThreadReduce.h"
33 |
34 |
35 | namespace dso
36 | {
37 |
38 | class EFPoint;
39 | class EnergyFunctional;
40 |
41 |
42 |
43 | class AccumulatedTopHessianSSE
44 | {
45 | public:
46 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
47 | inline AccumulatedTopHessianSSE()
48 | {
49 | for(int tid=0;tid < NUM_THREADS; tid++)
50 | {
51 | nres[tid]=0;
52 | acc[tid]=0;
53 | nframes[tid]=0;
54 | }
55 |
56 | };
57 | inline ~AccumulatedTopHessianSSE()
58 | {
59 | for(int tid=0;tid < NUM_THREADS; tid++)
60 | {
61 | if(acc[tid] != 0) delete[] acc[tid];
62 | }
63 | };
64 |
65 | inline void setZero(int nFrames, int min=0, int max=1, Vec10* stats=0, int tid=0)
66 | {
67 |
68 | if(nFrames != nframes[tid])
69 | {
70 | if(acc[tid] != 0) delete[] acc[tid];
71 | #if USE_XI_MODEL
72 | acc[tid] = new Accumulator14[nFrames*nFrames];
73 | #else
74 | acc[tid] = new AccumulatorApprox[nFrames*nFrames];
75 | #endif
76 | }
77 |
78 | for(int i=0;i void addPoint(EFPoint* p, EnergyFunctional const * const ef, int tid=0);
88 |
89 |
90 |
91 | void stitchDoubleMT(IndexThreadReduce* red, MatXX &H, VecX &b, EnergyFunctional const * const EF, bool usePrior, bool MT)
92 | {
93 | // sum up, splitting by bock in square.
94 | if(MT)
95 | {
96 | MatXX Hs[NUM_THREADS];
97 | VecX bs[NUM_THREADS];
98 | for(int i=0;ireduce(boost::bind(&AccumulatedTopHessianSSE::stitchDoubleInternal,
106 | this,Hs, bs, EF, usePrior, _1, _2, _3, _4), 0, nframes[0]*nframes[0], 0);
107 |
108 | // sum up results
109 | H = Hs[0];
110 | b = bs[0];
111 |
112 | for(int i=1;i(0,hIdx).noalias() = H.block<8,CPARS>(hIdx,0).transpose();
131 |
132 | for(int t=h+1;t(hIdx, tIdx).noalias() += H.block<8,8>(tIdx, hIdx).transpose();
136 | H.block<8,8>(tIdx, hIdx).noalias() = H.block<8,8>(hIdx, tIdx).transpose();
137 | }
138 | }
139 | }
140 |
141 |
142 |
143 |
144 | int nframes[NUM_THREADS];
145 |
146 | EIGEN_ALIGN16 AccumulatorApprox* acc[NUM_THREADS];
147 |
148 |
149 | int nres[NUM_THREADS];
150 |
151 |
152 | template void addPointsInternal(
153 | std::vector* points, EnergyFunctional const * const ef,
154 | int min=0, int max=1, Vec10* stats=0, int tid=0)
155 | {
156 | for(int i=min;i((*points)[i],ef,tid);
157 | }
158 |
159 |
160 |
161 | private:
162 |
163 | void stitchDoubleInternal(
164 | MatXX* H, VecX* b, EnergyFunctional const * const EF, bool usePrior,
165 | int min, int max, Vec10* stats, int tid);
166 | };
167 | }
168 |
169 |
--------------------------------------------------------------------------------
/src/bundles/Config.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EDS: Event-aided Direct Sparse Odometry
3 | * (https://rpg.ifi.uzh.ch/eds.html)
4 | *
5 | * Copyright (c) 2022 Javier Hidalgo-Carrió, Robotics and Perception
6 | * Group (RPG) University of Zurich.
7 | *
8 | * EDS is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, version 3.
11 | *
12 | * EDS is distributed in the hope that it will be useful, but
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 |
21 |
22 | #ifndef _EDS_BUNDLES_CONFIG_HPP_
23 | #define _EDS_BUNDLES_CONFIG_HPP_
24 |
25 | #include
26 |
27 | #include
28 | #include
29 |
30 | namespace eds { namespace bundles{
31 |
32 | enum LOSS_FUNCTION{NONE, HUBER, CAUCHY};
33 | enum LINEAR_SOLVER_TYPE{DENSE_QR, DENSE_SCHUR, SPARSE_SCHUR, SPARSE_NORMAL_CHOLESKY};
34 |
35 | struct SolverOptions
36 | {
37 | LINEAR_SOLVER_TYPE linear_solver_type;
38 | int num_threads;
39 | int max_num_iterations;
40 | double function_tolerance;
41 | bool minimizer_progress_to_stdout;
42 | };
43 |
44 | struct Config
45 | {
46 | std::string type;
47 | double percent_points;
48 | double percent_marginalize_vis;
49 | uint16_t window_size;
50 | LOSS_FUNCTION loss_type;
51 | std::vector loss_params;
52 | SolverOptions options;
53 | };
54 |
55 | struct PBAInfo
56 | {
57 | base::Time time;
58 | double meas_time_ms;
59 | int num_iterations;
60 | double time_seconds;
61 | uint8_t success;
62 | };
63 |
64 | inline ::eds::bundles::LOSS_FUNCTION selectLoss(const std::string &loss_name)
65 | {
66 | if (loss_name.compare("Huber") == 0)
67 | return eds::bundles::HUBER;
68 | else if (loss_name.compare("Cauchy") == 0)
69 | return eds::bundles::CAUCHY;
70 | else
71 | return eds::bundles::NONE;
72 | };
73 |
74 | inline ::eds::bundles::LINEAR_SOLVER_TYPE selectSolver(const std::string &solver_name)
75 | {
76 | if (solver_name.compare("DENSE_QR") == 0)
77 | return eds::bundles::DENSE_QR;
78 | else if (solver_name.compare("DENSE_SCHUR") == 0)
79 | return eds::bundles::DENSE_SCHUR;
80 | else if (solver_name.compare("SPARSE_SCHUR") == 0)
81 | return eds::bundles::SPARSE_SCHUR;
82 | else
83 | return eds::bundles::SPARSE_NORMAL_CHOLESKY;
84 | };
85 |
86 | inline ::eds::bundles::Config readBundlesConfig(YAML::Node config)
87 | {
88 | ::eds::bundles::Config bundles_config;
89 |
90 | /** Number of points to optimize within the current window **/
91 | bundles_config.percent_points = config["percent_points"].as();
92 | /** Percent of visual point to seletc the kf to marginalize **/
93 | bundles_config.percent_marginalize_vis = config["percent_marginalize_vis"].as();
94 | /** BA Windows size **/
95 | bundles_config.window_size = config["window_size"].as();
96 | /** Config for tracker type (only ceres) **/
97 | bundles_config.type = config["type"].as();
98 |
99 | /** Config the loss **/
100 | YAML::Node bundles_loss = config["loss_function"];
101 | std::string loss_name = bundles_loss["type"].as();
102 | bundles_config.loss_type = ::eds::bundles::selectLoss(loss_name);
103 | bundles_config.loss_params = bundles_loss["param"].as< std::vector >();
104 |
105 | /** Config for ceres options **/
106 | YAML::Node tracker_options = config["options"];
107 | bundles_config.options.linear_solver_type = ::eds::bundles::selectSolver(tracker_options["solver_type"].as());
108 | bundles_config.options.num_threads = tracker_options["num_threads"].as();
109 | bundles_config.options.max_num_iterations = tracker_options["max_num_iterations"].as();
110 | bundles_config.options.function_tolerance = tracker_options["function_tolerance"].as();
111 | bundles_config.options.minimizer_progress_to_stdout = tracker_options["minimizer_progress_to_stdout"].as();
112 |
113 | return bundles_config;
114 | };
115 |
116 | } //bundles namespace
117 | } // end namespace
118 |
119 | #endif
--------------------------------------------------------------------------------
/src/bundles/EnergyFunctional.h:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of DSO.
3 | *
4 | * Copyright 2016 Technical University of Munich and Intel.
5 | * Developed by Jakob Engel ,
6 | * for more information see .
7 | * If you use this code, please cite the respective publications as
8 | * listed on the above website.
9 | *
10 | * DSO is free software: you can redistribute it and/or modify
11 | * it under the terms of the GNU General Public License as published by
12 | * the Free Software Foundation, either version 3 of the License, or
13 | * (at your option) any later version.
14 | *
15 | * DSO is distributed in the hope that it will be useful,
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | * GNU General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with DSO. If not, see .
22 | */
23 |
24 |
25 | #pragma once
26 |
27 |
28 | #include "eds/utils/NumType.h"
29 | #include "eds/utils/IndexThreadReduce.h"
30 | #include "vector"
31 | #include
32 | #include "map"
33 |
34 |
35 | namespace dso
36 | {
37 |
38 | class PointFrameResidual;
39 | class CalibHessian;
40 | class FrameHessian;
41 | class PointHessian;
42 |
43 |
44 | class EFResidual;
45 | class EFPoint;
46 | class EFFrame;
47 | class EnergyFunctional;
48 | class AccumulatedTopHessian;
49 | class AccumulatedTopHessianSSE;
50 | class AccumulatedSCHessian;
51 | class AccumulatedSCHessianSSE;
52 |
53 |
54 | extern bool EFAdjointsValid;
55 | extern bool EFIndicesValid;
56 | extern bool EFDeltaValid;
57 |
58 |
59 |
60 | class EnergyFunctional {
61 | public:
62 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
63 | friend class EFFrame;
64 | friend class EFPoint;
65 | friend class EFResidual;
66 | friend class AccumulatedTopHessian;
67 | friend class AccumulatedTopHessianSSE;
68 | friend class AccumulatedSCHessian;
69 | friend class AccumulatedSCHessianSSE;
70 |
71 | EnergyFunctional();
72 | ~EnergyFunctional();
73 |
74 |
75 | EFResidual* insertResidual(PointFrameResidual* r);
76 | EFFrame* insertFrame(FrameHessian* fh, CalibHessian* Hcalib);
77 | EFPoint* insertPoint(PointHessian* ph);
78 |
79 | void dropResidual(EFResidual* r);
80 | void marginalizeFrame(EFFrame* fh);
81 | void removePoint(EFPoint* ph);
82 |
83 |
84 |
85 | void marginalizePointsF();
86 | void dropPointsF();
87 | void solveSystemF(int iteration, double lambda, CalibHessian* HCalib);
88 | double calcMEnergyF();
89 | double calcLEnergyF_MT();
90 |
91 |
92 | void makeIDX();
93 |
94 | void setDeltaF(CalibHessian* HCalib);
95 |
96 | void setAdjointsF(CalibHessian* Hcalib);
97 |
98 | std::vector frames;
99 | int nPoints, nFrames, nResiduals;
100 |
101 | MatXX HM;
102 | VecX bM;
103 |
104 | int resInA, resInL, resInM;
105 | MatXX lastHS;
106 | VecX lastbS;
107 | VecX lastX;
108 | std::vector lastNullspaces_forLogging;
109 | std::vector lastNullspaces_pose;
110 | std::vector lastNullspaces_scale;
111 | std::vector lastNullspaces_affA;
112 | std::vector lastNullspaces_affB;
113 |
114 | IndexThreadReduce* red;
115 |
116 |
117 | std::map,
120 | Eigen::aligned_allocator>
121 | > connectivityMap;
122 |
123 | private:
124 |
125 | VecX getStitchedDeltaF() const;
126 |
127 | void resubstituteF_MT(VecX x, CalibHessian* HCalib, bool MT);
128 | void resubstituteFPt(const VecCf &xc, Mat18f* xAd, int min, int max, Vec10* stats, int tid);
129 |
130 | void accumulateAF_MT(MatXX &H, VecX &b, bool MT);
131 | void accumulateLF_MT(MatXX &H, VecX &b, bool MT);
132 | void accumulateSCF_MT(MatXX &H, VecX &b, bool MT);
133 |
134 | void calcLEnergyPt(int min, int max, Vec10* stats, int tid);
135 |
136 | void orthogonalize(VecX* b, MatXX* H);
137 | Mat18f* adHTdeltaF;
138 |
139 | Mat88* adHost;
140 | Mat88* adTarget;
141 |
142 | Mat88f* adHostF;
143 | Mat88f* adTargetF;
144 |
145 |
146 | VecC cPrior;
147 | VecCf cDeltaF;
148 | VecCf cPriorF;
149 |
150 | AccumulatedTopHessianSSE* accSSE_top_L;
151 | AccumulatedTopHessianSSE* accSSE_top_A;
152 |
153 |
154 | AccumulatedSCHessianSSE* accSSE_bot;
155 |
156 | std::vector allPoints;
157 | std::vector allPointsToMarg;
158 |
159 | float currentLambda;
160 | };
161 | }
162 |
163 |
--------------------------------------------------------------------------------
/src/bundles/EnergyFunctionalStructs.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of DSO.
3 | *
4 | * Copyright 2016 Technical University of Munich and Intel.
5 | * Developed by Jakob Engel ,
6 | * for more information see .
7 | * If you use this code, please cite the respective publications as
8 | * listed on the above website.
9 | *
10 | * DSO is free software: you can redistribute it and/or modify
11 | * it under the terms of the GNU General Public License as published by
12 | * the Free Software Foundation, either version 3 of the License, or
13 | * (at your option) any later version.
14 | *
15 | * DSO is distributed in the hope that it will be useful,
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | * GNU General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with DSO. If not, see .
22 | */
23 |
24 |
25 | #include "eds/bundles/EnergyFunctionalStructs.h"
26 | #include "eds/bundles/EnergyFunctional.h"
27 | #include "eds/tracking/HessianBlocks.h"
28 | #include "eds/tracking/Residuals.h"
29 |
30 | #if !defined(__SSE3__) && !defined(__SSE2__) && !defined(__SSE1__)
31 | #include "SSE2NEON.h"
32 | #endif
33 |
34 | namespace dso
35 | {
36 |
37 |
38 | void EFResidual::takeDataF()
39 | {
40 | std::swap(J, data->J);
41 |
42 | Vec2f JI_JI_Jd = J->JIdx2 * J->Jpdd;
43 |
44 | for(int i=0;i<6;i++)
45 | JpJdF[i] = J->Jpdxi[0][i]*JI_JI_Jd[0] + J->Jpdxi[1][i] * JI_JI_Jd[1];
46 |
47 | JpJdF.segment<2>(6) = J->JabJIdx*J->Jpdd;
48 | }
49 |
50 |
51 | void EFFrame::takeData()
52 | {
53 | prior = data->getPrior().head<8>();
54 | delta = data->get_state_minus_stateZero().head<8>();
55 | delta_prior = (data->get_state() - data->getPriorZero()).head<8>();
56 |
57 |
58 |
59 | // Vec10 state_zero = data->get_state_zero();
60 | // state_zero.segment<3>(0) = SCALE_XI_TRANS * state_zero.segment<3>(0);
61 | // state_zero.segment<3>(3) = SCALE_XI_ROT * state_zero.segment<3>(3);
62 | // state_zero[6] = SCALE_A * state_zero[6];
63 | // state_zero[7] = SCALE_B * state_zero[7];
64 | // state_zero[8] = SCALE_A * state_zero[8];
65 | // state_zero[9] = SCALE_B * state_zero[9];
66 | //
67 | // std::cout << "state_zero: " << state_zero.transpose() << "\n";
68 |
69 |
70 | assert(data->frameID != -1);
71 |
72 | frameID = data->frameID;
73 | }
74 |
75 |
76 |
77 |
78 | void EFPoint::takeData()
79 | {
80 | priorF = data->hasDepthPrior ? setting_idepthFixPrior*SCALE_IDEPTH*SCALE_IDEPTH : 0;
81 | if(setting_solverMode & SOLVER_REMOVE_POSEPRIOR) priorF=0;
82 |
83 | deltaF = data->idepth-data->idepth_zero;
84 | }
85 |
86 |
87 | void EFResidual::fixLinearizationF(EnergyFunctional* ef)
88 | {
89 | Vec8f dp = ef->adHTdeltaF[hostIDX+ef->nFrames*targetIDX];
90 |
91 | // compute Jp*delta
92 | __m128 Jp_delta_x = _mm_set1_ps(J->Jpdxi[0].dot(dp.head<6>())
93 | +J->Jpdc[0].dot(ef->cDeltaF)
94 | +J->Jpdd[0]*point->deltaF);
95 | __m128 Jp_delta_y = _mm_set1_ps(J->Jpdxi[1].dot(dp.head<6>())
96 | +J->Jpdc[1].dot(ef->cDeltaF)
97 | +J->Jpdd[1]*point->deltaF);
98 | __m128 delta_a = _mm_set1_ps((float)(dp[6]));
99 | __m128 delta_b = _mm_set1_ps((float)(dp[7]));
100 |
101 | for(int i=0;iresF)+i);
105 | rtz = _mm_sub_ps(rtz,_mm_mul_ps(_mm_load_ps(((float*)(J->JIdx))+i),Jp_delta_x));
106 | rtz = _mm_sub_ps(rtz,_mm_mul_ps(_mm_load_ps(((float*)(J->JIdx+1))+i),Jp_delta_y));
107 | rtz = _mm_sub_ps(rtz,_mm_mul_ps(_mm_load_ps(((float*)(J->JabF))+i),delta_a));
108 | rtz = _mm_sub_ps(rtz,_mm_mul_ps(_mm_load_ps(((float*)(J->JabF+1))+i),delta_b));
109 | _mm_store_ps(((float*)&res_toZeroF)+i, rtz);
110 | }
111 |
112 | isLinearized = true;
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/src/bundles/EnergyFunctionalStructs.h:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of DSO.
3 | *
4 | * Copyright 2016 Technical University of Munich and Intel.
5 | * Developed by Jakob Engel ,
6 | * for more information see .
7 | * If you use this code, please cite the respective publications as
8 | * listed on the above website.
9 | *
10 | * DSO is free software: you can redistribute it and/or modify
11 | * it under the terms of the GNU General Public License as published by
12 | * the Free Software Foundation, either version 3 of the License, or
13 | * (at your option) any later version.
14 | *
15 | * DSO is distributed in the hope that it will be useful,
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | * GNU General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with DSO. If not, see .
22 | */
23 |
24 |
25 | #pragma once
26 |
27 |
28 | #include "eds/utils/NumType.h"
29 | #include "eds/bundles/RawResidualJacobian.h"
30 | #include "vector"
31 | #include
32 |
33 | namespace dso
34 | {
35 |
36 | class PointFrameResidual;
37 | class CalibHessian;
38 | class FrameHessian;
39 | class PointHessian;
40 |
41 | class EFResidual;
42 | class EFPoint;
43 | class EFFrame;
44 | class EnergyFunctional;
45 |
46 |
47 |
48 |
49 |
50 |
51 | class EFResidual
52 | {
53 | public:
54 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
55 |
56 | inline EFResidual(PointFrameResidual* org, EFPoint* point_, EFFrame* host_, EFFrame* target_) :
57 | data(org), point(point_), host(host_), target(target_)
58 | {
59 | isLinearized=false;
60 | isActiveAndIsGoodNEW=false;
61 | J = new RawResidualJacobian();
62 | assert(((long)this)%16==0);
63 | assert(((long)J)%16==0);
64 | }
65 | inline ~EFResidual()
66 | {
67 | delete J;
68 | }
69 |
70 |
71 | void takeDataF();
72 |
73 |
74 | void fixLinearizationF(EnergyFunctional* ef);
75 |
76 |
77 | // structural pointers
78 | PointFrameResidual* data;
79 | int hostIDX, targetIDX;
80 | EFPoint* point;
81 | EFFrame* host;
82 | EFFrame* target;
83 | int idxInAll;
84 |
85 | RawResidualJacobian* J;
86 |
87 | VecNRf res_toZeroF;
88 | Vec8f JpJdF;
89 |
90 |
91 | // status.
92 | bool isLinearized;
93 |
94 | // if residual is not OOB & not OUTLIER & should be used during accumulations
95 | bool isActiveAndIsGoodNEW;
96 | inline const bool &isActive() const {return isActiveAndIsGoodNEW;}
97 | };
98 |
99 |
100 | enum EFPointStatus {PS_GOOD=0, PS_MARGINALIZE, PS_DROP};
101 |
102 | class EFPoint
103 | {
104 | public:
105 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
106 | EFPoint(PointHessian* d, EFFrame* host_) : data(d),host(host_)
107 | {
108 | takeData();
109 | stateFlag=EFPointStatus::PS_GOOD;
110 | }
111 | void takeData();
112 |
113 | PointHessian* data;
114 |
115 |
116 |
117 | float priorF;
118 | float deltaF;
119 |
120 |
121 | // constant info (never changes in-between).
122 | int idxInPoints;
123 | EFFrame* host;
124 |
125 | // contains all residuals.
126 | std::vector residualsAll;
127 |
128 | float bdSumF;
129 | float HdiF;
130 | float Hdd_accLF;
131 | VecCf Hcd_accLF;
132 | float bd_accLF;
133 | float Hdd_accAF;
134 | VecCf Hcd_accAF;
135 | float bd_accAF;
136 |
137 |
138 | EFPointStatus stateFlag;
139 | };
140 |
141 |
142 |
143 | class EFFrame
144 | {
145 | public:
146 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
147 | EFFrame(FrameHessian* d) : data(d)
148 | {
149 | takeData();
150 | }
151 | void takeData();
152 |
153 |
154 | Vec8 prior; // prior hessian (diagonal)
155 | Vec8 delta_prior; // = state-state_prior (E_prior = (delta_prior)' * diag(prior) * (delta_prior)
156 | Vec8 delta; // state - state_zero.
157 |
158 |
159 |
160 | std::vector points;
161 | FrameHessian* data;
162 | int idx; // idx in frames.
163 |
164 | int frameID;
165 | };
166 |
167 | }
168 |
169 |
--------------------------------------------------------------------------------
/src/bundles/RawResidualJacobian.h:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of DSO.
3 | *
4 | * Copyright 2016 Technical University of Munich and Intel.
5 | * Developed by Jakob Engel ,
6 | * for more information see .
7 | * If you use this code, please cite the respective publications as
8 | * listed on the above website.
9 | *
10 | * DSO is free software: you can redistribute it and/or modify
11 | * it under the terms of the GNU General Public License as published by
12 | * the Free Software Foundation, either version 3 of the License, or
13 | * (at your option) any later version.
14 | *
15 | * DSO is distributed in the hope that it will be useful,
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | * GNU General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with DSO. If not, see .
22 | */
23 |
24 |
25 | #pragma once
26 |
27 |
28 | #include "eds/utils/NumType.h"
29 |
30 | namespace dso
31 | {
32 | struct RawResidualJacobian
33 | {
34 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
35 | // ================== new structure: save independently =============.
36 | VecNRf resF;
37 |
38 | // the two rows of d[x,y]/d[xi].
39 | Vec6f Jpdxi[2]; // 2x6
40 |
41 | // the two rows of d[x,y]/d[C].
42 | VecCf Jpdc[2]; // 2x4
43 |
44 | // the two rows of d[x,y]/d[idepth].
45 | Vec2f Jpdd; // 2x1
46 |
47 | // the two columns of d[r]/d[x,y].
48 | VecNRf JIdx[2]; // 9x2
49 |
50 | // = the two columns of d[r] / d[ab]
51 | VecNRf JabF[2]; // 9x2
52 |
53 |
54 | // = JIdx^T * JIdx (inner product). Only as a shorthand.
55 | Mat22f JIdx2; // 2x2
56 | // = Jab^T * JIdx (inner product). Only as a shorthand.
57 | Mat22f JabJIdx; // 2x2
58 | // = Jab^T * Jab (inner product). Only as a shorthand.
59 | Mat22f Jab2; // 2x2
60 |
61 | };
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/src/eds.pc.in:
--------------------------------------------------------------------------------
1 | prefix=@CMAKE_INSTALL_PREFIX@
2 | exec_prefix=@CMAKE_INSTALL_PREFIX@
3 | libdir=${prefix}/lib
4 | includedir=${prefix}/include
5 |
6 | Name: @TARGET_NAME@
7 | Description: @PROJECT_DESCRIPTION@
8 | Version: @PROJECT_VERSION@
9 | Requires: @PKGCONFIG_REQUIRES@
10 | Libs: -L${libdir} -l@TARGET_NAME@ @PKGCONFIG_LIBS@
11 | Cflags: -I${includedir} @PKGCONFIG_CFLAGS@
12 |
13 |
--------------------------------------------------------------------------------
/src/io/ImageConvert.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EDS: Event-aided Direct Sparse Odometry
3 | * (https://rpg.ifi.uzh.ch/eds.html)
4 | *
5 | * Copyright (c) 2022 Javier Hidalgo-Carrió, Robotics and Perception
6 | * Group (RPG) University of Zurich.
7 | *
8 | * EDS is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, version 3.
11 | *
12 | * EDS is distributed in the hope that it will be useful, but
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 |
21 | #include
22 | #include
23 |
24 | namespace eds { namespace io
25 | {
26 |
27 | dso::MinimalImageB3* toMinimalImageB3(const Eigen::Vector3f *fd, const int &w, const int &h)
28 | {
29 | int wh = w*h;
30 | dso::MinimalImageB3* img_b3 = new dso::MinimalImageB3(w, h);
31 | for(int i=0;i255) c=255;
35 | img_b3->at(i) = ::dso::Vec3b(c,c,c);
36 | }
37 | return img_b3;
38 | }
39 |
40 | void MinimalImageB3ToFrame(const dso::MinimalImageB3 *img_b3, const ::base::Time ×tamp, ::base::samples::frame::Frame &frame)
41 | {
42 | cv::Mat img = cv::Mat(img_b3->h, img_b3->w, CV_8UC3, img_b3->data);
43 | //cv::imwrite("/tmp/dso_img_"+std::to_string(this->frame_idx)+".png", frame);
44 |
45 | frame.image.clear();
46 | frame_helper::FrameHelper::copyMatToFrame(img, frame);
47 | frame.time = timestamp;
48 |
49 | }
50 |
51 | }
52 | }//end of dso namespace
53 |
--------------------------------------------------------------------------------
/src/io/ImageConvert.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EDS: Event-aided Direct Sparse Odometry
3 | * (https://rpg.ifi.uzh.ch/eds.html)
4 | *
5 | * Copyright (c) 2022 Javier Hidalgo-Carrió, Robotics and Perception
6 | * Group (RPG) University of Zurich.
7 | *
8 | * EDS is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, version 3.
11 | *
12 | * EDS is distributed in the hope that it will be useful, but
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 |
21 | #pragma once
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 |
29 | namespace eds
30 | {
31 |
32 | namespace io
33 | {
34 |
35 | dso::MinimalImageB3* toMinimalImageB3(const Eigen::Vector3f *fd, const int &w, const int &h);
36 | void MinimalImageB3ToFrame(const dso::MinimalImageB3 *input, const ::base::Time ×tamp, ::base::samples::frame::Frame &frame);
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/io/ImageRW.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of DSO.
3 | *
4 | * Copyright 2016 Technical University of Munich and Intel.
5 | * Developed by Jakob Engel ,
6 | * for more information see .
7 | * If you use this code, please cite the respective publications as
8 | * listed on the above website.
9 | *
10 | * DSO is free software: you can redistribute it and/or modify
11 | * it under the terms of the GNU General Public License as published by
12 | * the Free Software Foundation, either version 3 of the License, or
13 | * (at your option) any later version.
14 | *
15 | * DSO is distributed in the hope that it will be useful,
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | * GNU General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with DSO. If not, see .
22 | */
23 |
24 |
25 |
26 | #include
27 | #include
28 |
29 |
30 | namespace dso
31 | {
32 |
33 | namespace io
34 | {
35 | MinimalImageB* readImageBW_8U(std::string filename)
36 | {
37 | cv::Mat m = cv::imread(filename, cv::IMREAD_GRAYSCALE);
38 | if(m.rows*m.cols==0)
39 | {
40 | printf("cv::imread could not read image %s! this may segfault. \n", filename.c_str());
41 | return 0;
42 | }
43 | if(m.type() != CV_8U)
44 | {
45 | printf("cv::imread did something strange! this may segfault. \n");
46 | return 0;
47 | }
48 | MinimalImageB* img = new MinimalImageB(m.cols, m.rows);
49 | memcpy(img->data, m.data, m.rows*m.cols);
50 | return img;
51 | }
52 |
53 | MinimalImageB3* readImageRGB_8U(std::string filename)
54 | {
55 | cv::Mat m = cv::imread(filename, cv::IMREAD_COLOR);
56 | if(m.rows*m.cols==0)
57 | {
58 | printf("cv::imread could not read image %s! this may segfault. \n", filename.c_str());
59 | return 0;
60 | }
61 | if(m.type() != CV_8UC3)
62 | {
63 | printf("cv::imread did something strange! this may segfault. \n");
64 | return 0;
65 | }
66 | MinimalImageB3* img = new MinimalImageB3(m.cols, m.rows);
67 | memcpy(img->data, m.data, 3*m.rows*m.cols);
68 | return img;
69 | }
70 |
71 | MinimalImage* readImageBW_16U(std::string filename)
72 | {
73 | cv::Mat m = cv::imread(filename, cv::IMREAD_UNCHANGED);
74 | if(m.rows*m.cols==0)
75 | {
76 | printf("cv::imread could not read image %s! this may segfault. \n", filename.c_str());
77 | return 0;
78 | }
79 | if(m.type() != CV_16U)
80 | {
81 | printf("readImageBW_16U called on image that is not a 16bit grayscale image. this may segfault. \n");
82 | return 0;
83 | }
84 | MinimalImage* img = new MinimalImage(m.cols, m.rows);
85 | memcpy(img->data, m.data, 2*m.rows*m.cols);
86 | return img;
87 | }
88 |
89 | MinimalImageB* readStreamBW_8U(char* data, int numBytes)
90 | {
91 | cv::Mat m = cv::imdecode(cv::Mat(numBytes,1,CV_8U, data), cv::IMREAD_GRAYSCALE);
92 | if(m.rows*m.cols==0)
93 | {
94 | printf("cv::imdecode could not read stream (%d bytes)! this may segfault. \n", numBytes);
95 | return 0;
96 | }
97 | if(m.type() != CV_8U)
98 | {
99 | printf("cv::imdecode did something strange! this may segfault. \n");
100 | return 0;
101 | }
102 | MinimalImageB* img = new MinimalImageB(m.cols, m.rows);
103 | memcpy(img->data, m.data, m.rows*m.cols);
104 | return img;
105 | }
106 |
107 |
108 |
109 | void writeImage(std::string filename, MinimalImageB* img)
110 | {
111 | cv::imwrite(filename, cv::Mat(img->h, img->w, CV_8U, img->data));
112 | }
113 | void writeImage(std::string filename, MinimalImageB3* img)
114 | {
115 | cv::imwrite(filename, cv::Mat(img->h, img->w, CV_8UC3, img->data));
116 | }
117 | void writeImage(std::string filename, MinimalImageF* img)
118 | {
119 | cv::imwrite(filename, cv::Mat(img->h, img->w, CV_32F, img->data));
120 | }
121 | void writeImage(std::string filename, MinimalImageF3* img)
122 | {
123 | cv::imwrite(filename, cv::Mat(img->h, img->w, CV_32FC3, img->data));
124 | }
125 |
126 | }
127 |
128 | }
129 |
--------------------------------------------------------------------------------
/src/io/ImageRW.h:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of DSO.
3 | *
4 | * Copyright 2016 Technical University of Munich and Intel.
5 | * Developed by Jakob Engel ,
6 | * for more information see .
7 | * If you use this code, please cite the respective publications as
8 | * listed on the above website.
9 | *
10 | * DSO is free software: you can redistribute it and/or modify
11 | * it under the terms of the GNU General Public License as published by
12 | * the Free Software Foundation, either version 3 of the License, or
13 | * (at your option) any later version.
14 | *
15 | * DSO is distributed in the hope that it will be useful,
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | * GNU General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with DSO. If not, see .
22 | */
23 |
24 |
25 |
26 | #pragma once
27 | #include "eds/utils/NumType.h"
28 | #include "eds/utils/MinimalImage.h"
29 |
30 | namespace dso
31 | {
32 | namespace io
33 | {
34 |
35 | MinimalImageB* readImageBW_8U(std::string filename);
36 | MinimalImageB3* readImageRGB_8U(std::string filename);
37 | MinimalImage* readImageBW_16U(std::string filename);
38 |
39 |
40 | MinimalImageB* readStreamBW_8U(char* data, int numBytes);
41 |
42 | void writeImage(std::string filename, MinimalImageB* img);
43 | void writeImage(std::string filename, MinimalImageB3* img);
44 | void writeImage(std::string filename, MinimalImageF* img);
45 | void writeImage(std::string filename, MinimalImageF3* img);
46 |
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/io/OutputMaps.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EDS: Event-aided Direct Sparse Odometry
3 | * (https://rpg.ifi.uzh.ch/eds.html)
4 | *
5 | * Copyright (c) 2022 Javier Hidalgo-Carrió, Robotics and Perception
6 | * Group (RPG) University of Zurich.
7 | *
8 | * EDS is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, version 3.
11 | *
12 | * EDS is distributed in the hope that it will be useful, but
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see
19 | */
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | namespace dso { namespace io
30 | {
31 |
32 | template
33 | bool is_not_nan(const Eigen::MatrixBase& x)
34 | {
35 | return ((x.array() == x.array())).all();
36 | }
37 |
38 | base::samples::Pointcloud getMap(const dso::FrameHessian *fh, dso::CalibHessian *hcalib, const base::Vector4d color, const bool &single_point)
39 | {
40 | base::samples::Pointcloud pcl;
41 |
42 | float fx = hcalib->fxl();
43 | float fy = hcalib->fyl();
44 | float cx = hcalib->cxl();
45 | float cy = hcalib->cyl();
46 |
47 | base::Transform3d T_w_kf = dso::SE3ToBaseTransform(fh->get_worldToCam_evalPT()).inverse();
48 |
49 | for(::dso::PointHessian* p : fh->pointHessians)
50 | {
51 | double d_i = 1.0/p->idepth_scaled;
52 | if (is_not_nan(color))
53 | {
54 | /** Push points in the world frame coordinate **/
55 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u-cx)/fx, d_i*(p->v-cy)/fy, d_i));
56 | pcl.colors.push_back(color);//point intensity
57 | }
58 | else
59 | {
60 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u-cx)/fx, d_i*(p->v-cy)/fy, d_i));//u-v point8
61 | //pcl.colors.push_back(::base::Vector4d(p->color[7], p->color[7], p->color[7], 1.0));//point intensity
62 | }
63 |
64 | if (!single_point)
65 | {
66 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u-cx)/fx, d_i*(p->v+2-cy)/fy, d_i));//x-y point1
67 | if (is_not_nan(color)) pcl.colors.push_back(color);//point intensity
68 | //pcl.colors.push_back(::base::Vector4d(p->color[0], p->color[0], p->color[0], 1.0));//point intensity
69 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u-1-cx)/fx, d_i*(p->v+1-cy)/fy, d_i ));//x-y point2
70 | if (is_not_nan(color)) pcl.colors.push_back(color);//point intensity
71 | //pcl.colors.push_back(::base::Vector4d(p->color[1], p->color[1], p->color[1], 1.0));//point intensity
72 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u-2-cx)/fx, d_i*(p->v-cy)/fy, d_i ));//x-y point3
73 | if (is_not_nan(color)) pcl.colors.push_back(color);//point intensity
74 | //pcl.colors.push_back(::base::Vector4d(p->color[2], p->color[2], p->color[2], 1.0));//point intensity
75 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u-1-cx)/fx, d_i*(p->v-1-cy)/fy, d_i ));//x-y point4
76 | if (is_not_nan(color)) pcl.colors.push_back(color);//point intensity
77 | //pcl.colors.push_back(::base::Vector4d(p->color[3], p->color[3], p->color[3], 1.0));//point intensity
78 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u-cx)/fx, d_i*(p->v-2-cy)/fy, d_i ));//x-y point5
79 | if (is_not_nan(color)) pcl.colors.push_back(color);//point intensity
80 | //pcl.colors.push_back(::base::Vector4d(p->color[4], p->color[4], p->color[4], 1.0));//point intensity
81 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u+1-cx)/fx, d_i*(p->v-1-cy)/fy, d_i ));//x-y point6
82 | if (is_not_nan(color)) pcl.colors.push_back(color);//point intensity
83 | //pcl.colors.push_back(::base::Vector4d(p->color[5], p->color[5], p->color[5], 1.0));//point intensity
84 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u+2-cx)/fx, d_i*(p->v-cy)/fy, d_i ));//x-y point7
85 | if (is_not_nan(color)) pcl.colors.push_back(color);//point intensity
86 | //pcl.colors.push_back(::base::Vector4d(p->color[6], p->color[6], p->color[6], 1.0));//point intensity
87 | }
88 | }
89 |
90 | return pcl;
91 | }
92 |
93 | base::samples::Pointcloud getImmatureMap(const dso::FrameHessian *fh, dso::CalibHessian *hcalib, const bool &single_point)
94 | {
95 | base::samples::Pointcloud pcl;
96 |
97 | float fx = hcalib->fxl();
98 | float fy = hcalib->fyl();
99 | float cx = hcalib->cxl();
100 | float cy = hcalib->cyl();
101 |
102 | base::Transform3d T_w_kf = dso::SE3ToBaseTransform(fh->get_worldToCam_evalPT()).inverse();
103 |
104 | for(::dso::ImmaturePoint* p : fh->immaturePoints)
105 | {
106 | /** This is the depth. Same maner as Hessian points are initialized from Immature Points **/
107 | double d_i = 1.0/(0.5 * (p->idepth_max+p->idepth_min));
108 |
109 | if (d_i < 0 || !std::isfinite(d_i)) continue;
110 |
111 | ::base::Vector4d color;
112 | if(p->lastTraceStatus==dso::ImmaturePointStatus::IPS_GOOD)
113 | color = ::base::Vector4d(0,1.0,0, 1.0);//GREEN
114 | if(p->lastTraceStatus==dso::ImmaturePointStatus::IPS_OOB)
115 | color = ::base::Vector4d(1.0,0,0,1.0);//RED
116 | if(p->lastTraceStatus==dso::ImmaturePointStatus::IPS_OUTLIER)
117 | color = ::base::Vector4d(0,0,1.0,1.0);//BLUE
118 | if(p->lastTraceStatus==dso::ImmaturePointStatus::IPS_SKIPPED)
119 | color = ::base::Vector4d(0.0,1.0,1.0,1.0);//CYAN
120 | if(p->lastTraceStatus==dso::ImmaturePointStatus::IPS_BADCONDITION)
121 | color = ::base::Vector4d(1.0,1.0,1.0,1.0); //WHITE
122 | if(p->lastTraceStatus==dso::ImmaturePointStatus::IPS_UNINITIALIZED)
123 | color = ::base::Vector4d(0,0,0,1.0);//BLACK
124 |
125 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u-cx)/fx, d_i*(p->v-cy)/fy, d_i));//u-v point8
126 | pcl.colors.push_back(color);//point intensity
127 |
128 | if (!single_point)
129 | {
130 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u-cx)/fx, d_i*(p->v+2-cy)/fy, d_i));//x-y point1
131 | pcl.colors.push_back(color);//point intensity
132 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u-1-cx)/fx, d_i*(p->v+1-cy)/fy, d_i ));//x-y point2
133 | pcl.colors.push_back(color);//point intensity
134 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u-2-cx)/fx, d_i*(p->v-cy)/fy, d_i ));//x-y point3
135 | pcl.colors.push_back(color);//point intensity
136 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u-1-cx)/fx, d_i*(p->v-1-cy)/fy, d_i ));//x-y point4
137 | pcl.colors.push_back(color);//point intensity
138 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u-cx)/fx, d_i*(p->v-2-cy)/fy, d_i ));//x-y point5
139 | pcl.colors.push_back(color);//point intensity
140 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u+1-cx)/fx, d_i*(p->v-1-cy)/fy, d_i ));//x-y point6
141 | pcl.colors.push_back(color);//point intensity
142 | pcl.points.push_back(T_w_kf * ::base::Point(d_i*(p->u+2-cx)/fx, d_i*(p->v-cy)/fy, d_i ));//x-y point7
143 | pcl.colors.push_back(color);//point intensity
144 | }
145 | }
146 |
147 | return pcl;
148 | }
149 |
150 | }
151 | }//end of dso namespace
152 |
--------------------------------------------------------------------------------
/src/io/OutputMaps.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EDS: Event-aided Direct Sparse Odometry
3 | * (https://rpg.ifi.uzh.ch/eds.html)
4 | *
5 | * Copyright (c) 2022 Javier Hidalgo-Carrió, Robotics and Perception
6 | * Group (RPG) University of Zurich.
7 | *
8 | * EDS is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, version 3.
11 | *
12 | * EDS is distributed in the hope that it will be useful, but
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see
19 | */
20 |
21 | #pragma once
22 | #include