├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── demo.rviz
├── figure
└── shortIntroduction.png
├── include
├── ESDFMap.h
├── Fiesta.h
├── parameters.h
├── raycast.h
└── timing.h
├── launch
├── cow_and_lady.launch
└── demo.launch
├── package.xml
├── src
├── ESDFMap.cpp
├── parameters.cpp
├── raycast.cpp
└── timing.cc
└── test
├── test_ESDF_Map.cpp
└── test_fiesta.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | cmake-build-debug
2 | cmake-build-releasei
3 | .idea
4 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.3)
2 | project(fiesta)
3 |
4 | find_package(catkin REQUIRED COMPONENTS
5 | roscpp
6 | std_msgs
7 | nav_msgs
8 | visualization_msgs
9 | tf
10 | cv_bridge
11 | )
12 |
13 | find_package(Eigen3 REQUIRED)
14 | find_package(PCL 1.7 REQUIRED)
15 | find_package(OpenCV REQUIRED)
16 | set(Eigen3_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR})
17 |
18 | catkin_package(
19 | INCLUDE_DIRS include
20 | )
21 |
22 |
23 | include_directories(${PROJECT_SOURCE_DIR}/include)
24 |
25 | include_directories(
26 | include
27 | SYSTEM
28 | ${catkin_INCLUDE_DIRS}
29 | ${Eigen3_INCLUDE_DIRS}
30 | ${PCL_INCLUDE_DIRS}
31 | ${OpenCV_INCLUDE_DIRS}
32 | )
33 |
34 | link_directories(${PCL_LIBRARY_DIRS})
35 |
36 | set(CMAKE_CXX_FLAGS "-std=c++17 ${CMAKE_CXX_FLAGS} -O3 -Wall -pthread") # -Wextra -Werror
37 | set(CMAKE_BUILD_TYPE "RELEASE")
38 | #add_executable(test_esdf_map
39 | # include/ESDFMap.h
40 | # src/ESDFMap.cpp
41 | # include/timing.h
42 | # src/timing.cc
43 | # test/test_ESDF_Map.cpp
44 | # )
45 | #target_link_libraries(test_esdf_map
46 | # ${catkin_LIBRARIES}
47 | # )
48 | #FIND_PACKAGE( OpenMP REQUIRED)
49 | #if(OPENMP_FOUND)
50 | #message("OPENMP FOUND")
51 | #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
52 | #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
53 | #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
54 | #endif()
55 |
56 | add_executable(test_fiesta
57 | include/parameters.h
58 | src/parameters.cpp
59 | include/timing.h
60 | src/timing.cc
61 | include/raycast.h
62 | src/raycast.cpp
63 | include/ESDFMap.h
64 | src/ESDFMap.cpp
65 | include/Fiesta.h
66 | test/test_fiesta.cpp
67 | )
68 | target_link_libraries(test_fiesta
69 | ${catkin_LIBRARIES}
70 | ${PCL_LIBRARIES}
71 | ${OpenCV_LIBS}
72 | )
73 |
74 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 hlx1996
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Fiesta
2 | > Incremental ESDF Map for motion planning
3 |
4 | Euclidean Signed Distance Field (ESDF) is useful for online motion planning of aerial robots
5 | since it can easily query the distance_ and gradient information against obstacles.
6 | Fast incrementally built ESDF map is the bottleneck for conducting real-time motion planning.
7 | In this paper, we investigate this problem and propose a mapping system called *Fiesta* to build
8 | global ESDF map incrementally. By introducing two independent updating queues for inserting and
9 | deleting obstacles separately, and using Indexing Data Structures and Doubly Linked Lists for
10 | map maintenance, our algorithm updates as few as possible nodes using a BFS framework. Our ESDF
11 | map has high computational performance and produces near-optimal results.
12 | We show our method outperforms other up-to-date methods in term of performance and accuracy
13 | by both theory and experiments. We integrate Fiesta into a completed quadrotor system and validate
14 | it by both simulation and onboard experiments. We release our method as open-source software for the community.
15 |
16 | The paper of this method is submitted to the 2019 IEEE/RSJ International Conference on
17 | Intelligent Robots and Systems (IROS 2019). The draft is shown on arxiv
18 | [here](https://arxiv.org/abs/1903.02144).
19 |
20 |
21 |
24 |
25 |
26 | ## Installation
27 | ### Required Library
28 | - Eigen3
29 | - PCL 1.7
30 | - OpenCV
31 | - ROS
32 |
33 | Note: C++ 17 is required to run FIESTA. Please install and configure C++ 17.
34 | ```bash
35 | sudo add-apt-repository ppa:ubuntu-toolchain-r/test
36 | sudo apt-get update
37 | sudo apt-get install gcc-7 g++-7
38 | ```
39 |
40 | use the following command to check your gcc compilers
41 |
42 | ```
43 | $ ls -lh /usr/bin/g++*
44 | ```
45 |
46 | for **ubuntu 14.04**:
47 |
48 | ```
49 | $ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 60 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8
50 | ```
51 |
52 | for **ubuntu 16.04**:
53 | ```
54 | $ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 60 --slave /usr/bin/g++ g++ /usr/bin/g++-5
55 | ```
56 |
57 | then
58 |
59 | ```
60 | $ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 70 --slave /usr/bin/g++ g++ /usr/bin/g++-7
61 | ```
62 |
63 | use the folling command to change the default compiler (choose 0 as default)
64 |
65 | ```
66 | $ sudo update-alternatives --config gcc
67 | ```
68 |
69 | check your current gcc compiler
70 |
71 | ```
72 | $ gcc --version
73 | ```
74 |
75 |
76 |
77 | ### Download & Compile
78 | ```sh
79 | cd ~/catkin_ws/src
80 | git clone https://github.com/hlx1996/Fiesta.git
81 | cd ../
82 | catkin_make
83 | source ~/catkin_ws/devel/setup.bash
84 | ```
85 |
86 |
87 |
88 | ## Usage example
89 |
90 | ```sh
91 | roslaunch fiesta cow_and_lady.launch
92 | rosbag play data.bag
93 | ```
94 |
95 | Cow and lady data set can be downloaded [here](http://robotics.ethz.ch/~asl-datasets/iros_2017_voxblox/data.bag).
96 | A `rviz` will be opened with the visualization of occupancy grid map and a slice of esdf map.
97 |
98 | _For more examples, usage and FAQ, please refer to the [Wiki][wiki].
99 |
100 |
101 |
102 | ## Release History
103 | Prediction: 1.0.0 will be our first elegant version.
104 | * 0.6.0
105 | * CHANGE: Refactor code according Google C++ Code Style
106 | * 0.5.3
107 | * CHANGE: Improve the performance of the depth conversion process
108 | * 0.5.2
109 | * ADD: Support local map
110 | * ADD: Support raw depth image as input, and depth filter of consistency
111 | * 0.5.1
112 | * CHANGE: Improve performance of raycasting a lot
113 | * 0.5.0
114 | * ADD: Give Local / global update / visualization options
115 | * ADD: Show Performance visualization directly on rviz
116 | * CHANGE: Deprecate older visualization, will be deleted in next release
117 | * 0.4.1
118 | * CHANGE: Give better Visualization based on a slice of ESDF and pointcloud of obstacles
119 | * 0.4.0
120 | * ADD: Support LIDAR Input
121 | * ADD: Support Deterministic Occupancy Grid Map
122 | * 0.3.2
123 | * ADD: Implement Multi-thread Raycasting for array implementation
124 | * 0.3.1
125 | * ADD: Implement Hash table with blocks
126 | * 0.3.0
127 | * ADD: Implement Hash table
128 | * 0.2.0
129 | * ADD: Support Raycasting from point cloud_
130 | * ADD: Support Probabilistic Occupancy Grid Map Fusion
131 | * CHANGE: Patch code for limited observations
132 | * 0.1.0
133 | * The first proper release, support ESDF for fully dynamic case and implemented in array
134 | * 0.0.1
135 | * Support ESDF for insert-only case
136 |
137 | ## Meta
138 |
139 | [hlx1996](https://github.com/hlx1996/) – hlx1996@example.com
140 |
141 | Distributed under the MIT license. See ``LICENSE`` for more information.
142 |
143 | ## Contributing
144 |
145 | 1. Fork it ()
146 | 2. Create your feature branch (`git checkout -b feature/fooBar`)
147 | 3. Commit your changes (`git commit -am 'Add some fooBar'`)
148 | 4. Push to the branch (`git push origin feature/fooBar`)
149 | 5. Create a new Pull Request
150 |
151 |
152 | [wiki]: https://github.com/hlx1996/Fiesta/wiki
153 |
--------------------------------------------------------------------------------
/demo.rviz:
--------------------------------------------------------------------------------
1 | Panels:
2 | - Class: rviz/Displays
3 | Help Height: 78
4 | Name: Displays
5 | Property Tree Widget:
6 | Expanded:
7 | - /Global Options1
8 | - /Status1
9 | - /PointCloud1
10 | - /Marker1
11 | Splitter Ratio: 0.5
12 | Tree Height: 774
13 | - Class: rviz/Selection
14 | Name: Selection
15 | - Class: rviz/Tool Properties
16 | Expanded:
17 | - /2D Pose Estimate1
18 | - /2D Nav Goal1
19 | - /Publish Point1
20 | Name: Tool Properties
21 | Splitter Ratio: 0.588679016
22 | - Class: rviz/Views
23 | Expanded:
24 | - /Current View1
25 | - /Current View1/Focal Point1
26 | Name: Views
27 | Splitter Ratio: 0.5
28 | - Class: rviz/Time
29 | Experimental: false
30 | Name: Time
31 | SyncMode: 0
32 | SyncSource: PointCloud
33 | Toolbars:
34 | toolButtonStyle: 2
35 | Visualization Manager:
36 | Class: ""
37 | Displays:
38 | - Alpha: 0.5
39 | Cell Size: 1
40 | Class: rviz/Grid
41 | Color: 160; 160; 164
42 | Enabled: true
43 | Line Style:
44 | Line Width: 0.0299999993
45 | Value: Lines
46 | Name: Grid
47 | Normal Cell Count: 0
48 | Offset:
49 | X: 0
50 | Y: 0
51 | Z: 0
52 | Plane: XY
53 | Plane Cell Count: 10
54 | Reference Frame:
55 | Value: true
56 | - Alpha: 1
57 | Autocompute Intensity Bounds: true
58 | Autocompute Value Bounds:
59 | Max Value: 2.9749999
60 | Min Value: -0.275000006
61 | Value: true
62 | Axis: Z
63 | Channel Name: intensity
64 | Class: rviz/PointCloud
65 | Color: 255; 255; 255
66 | Color Transformer: AxisColor
67 | Decay Time: 0
68 | Enabled: true
69 | Invert Rainbow: false
70 | Max Color: 255; 255; 255
71 | Max Intensity: 4096
72 | Min Color: 0; 0; 0
73 | Min Intensity: 0
74 | Name: PointCloud
75 | Position Transformer: XYZ
76 | Queue Size: 10
77 | Selectable: true
78 | Size (Pixels): 3
79 | Size (m): 0.0500000007
80 | Style: Squares
81 | Topic: /fiesta/ESDFMap/occ_pc
82 | Unreliable: false
83 | Use Fixed Frame: true
84 | Use rainbow: true
85 | Value: true
86 | - Class: rviz/Marker
87 | Enabled: true
88 | Marker Topic: /fiesta/ESDFMap/slice
89 | Name: Marker
90 | Namespaces:
91 | "": true
92 | Queue Size: 100
93 | Value: true
94 | Enabled: true
95 | Global Options:
96 | Background Color: 255; 255; 127
97 | Default Light: true
98 | Fixed Frame: world
99 | Frame Rate: 30
100 | Name: root
101 | Tools:
102 | - Class: rviz/Interact
103 | Hide Inactive Objects: true
104 | - Class: rviz/MoveCamera
105 | - Class: rviz/Select
106 | - Class: rviz/FocusCamera
107 | - Class: rviz/Measure
108 | - Class: rviz/SetInitialPose
109 | Topic: /initialpose
110 | - Class: rviz/SetGoal
111 | Topic: /move_base_simple/goal
112 | - Class: rviz/PublishPoint
113 | Single click: true
114 | Topic: /clicked_point
115 | Value: true
116 | Views:
117 | Current:
118 | Class: rviz/Orbit
119 | Distance: 10.7248745
120 | Enable Stereo Rendering:
121 | Stereo Eye Separation: 0.0599999987
122 | Stereo Focal Distance: 1
123 | Swap Stereo Eyes: false
124 | Value: false
125 | Focal Point:
126 | X: 1.16496587
127 | Y: 0.201870233
128 | Z: 0.447906345
129 | Focal Shape Fixed Size: true
130 | Focal Shape Size: 0.0500000007
131 | Invert Z Axis: false
132 | Name: Current View
133 | Near Clip Distance: 0.00999999978
134 | Pitch: 0.274794996
135 | Target Frame:
136 | Value: Orbit (rviz)
137 | Yaw: 3.01372385
138 | Saved: ~
139 | Window Geometry:
140 | Displays:
141 | collapsed: false
142 | Height: 1056
143 | Hide Left Dock: false
144 | Hide Right Dock: true
145 | QMainWindow State: 000000ff00000000fd00000004000000000000016a00000395fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000006100fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000002800000395000000d700fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f00000396fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000002800000396000000ad00fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000007800000003ffc0100000002fb0000000800540069006d00650100000000000007800000030000fffffffb0000000800540069006d00650100000000000004500000000000000000000006100000039500000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
146 | Selection:
147 | collapsed: false
148 | Time:
149 | collapsed: false
150 | Tool Properties:
151 | collapsed: false
152 | Views:
153 | collapsed: true
154 | Width: 1920
155 | X: 0
156 | Y: 24
157 |
--------------------------------------------------------------------------------
/figure/shortIntroduction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HKUST-Aerial-Robotics/FIESTA/d01ce1b4602340a417a68ec7bb5f6b5a6790207e/figure/shortIntroduction.png
--------------------------------------------------------------------------------
/include/ESDFMap.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by tommy on 12/17/18.
3 | //
4 |
5 | #ifndef ESDF_MAP_H
6 | #define ESDF_MAP_H
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include "parameters.h"
18 |
19 | namespace fiesta {
20 | #ifdef HASH_TABLE
21 | // Eigen::Matrix hashing function
22 | template
23 | struct MatrixHash : std::unary_function {
24 | std::size_t operator()(transform_ const &matrix) const {
25 | // Note that it is oblivious to the storage order of Eigen matrix (column- or
26 | // row-major). It will give you the same hash value for two different matrices if they
27 | // are the transpose of each other in different storage order.
28 | size_t seed = 0;
29 | for (size_t i = 0; i < matrix.size(); ++i) {
30 | auto elem = *(matrix.data() + i);
31 | seed ^= std::hash()(elem) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
32 | }
33 | return seed;
34 | }
35 | };
36 | #endif
37 | class ESDFMap {
38 | // Type of queue element to be used in priority queue
39 | struct QueueElement {
40 | Eigen::Vector3i point_;
41 | double distance_;
42 | bool operator<(const QueueElement &element) const {
43 | return distance_ > element.distance_;
44 | }
45 | };
46 |
47 |
48 | private:
49 | // parameters & method for occupancy information updating
50 | double prob_hit_log_, prob_miss_log_, clamp_min_log_, clamp_max_log_, min_occupancy_log_;
51 | const double Logit(const double &x) const;
52 | bool Exist(const int &idx);
53 | double Dist(Eigen::Vector3i a, Eigen::Vector3i b);
54 |
55 | // parameters & methods for conversion between Pos, Vox & Idx
56 | bool PosInMap(Eigen::Vector3d pos);
57 | bool VoxInRange(Eigen::Vector3i vox, bool current_vec = true);
58 | void Vox2Pos(Eigen::Vector3i vox, Eigen::Vector3d &pos);
59 | int Vox2Idx(Eigen::Vector3i vox);
60 | int Vox2Idx(Eigen::Vector3i vox, int sub_sampling_factor);
61 | void Pos2Vox(Eigen::Vector3d pos, Eigen::Vector3i &vox);
62 | Eigen::Vector3i Idx2Vox(int idx);
63 |
64 | // HASH TABLE related
65 | #ifdef HASH_TABLE
66 | // Increase the capacity from old_size to new_size, and change the old_size to new_size.
67 | void IncreaseCapacity(int &old_size, int new_size);
68 | int FindAndInsert(Eigen::Vector3i hash_key);
69 | std::unordered_map> hash_table_;
70 | int count, reserve_size_;
71 | #ifdef BLOCK
72 | int block_, block_size_, block_bit_;
73 | #endif
74 | std::vector vox_buffer_;
75 | #else // #ifndef HASH_TABLE
76 | Eigen::Vector3d map_size_;
77 | Eigen::Vector3d min_range_, max_range_; // map range in pos
78 | Eigen::Vector3i grid_size_; // map range in index
79 | int grid_size_yz_;
80 | #endif
81 |
82 | // data are saved in vector
83 | #ifdef PROBABILISTIC
84 | std::vector occupancy_buffer_; // 0 is free, 1 is occupied
85 | #else
86 | std::vector occupancy_buffer_; // 0 is free, 1 is occupied
87 | #endif
88 | std::vector distance_buffer_;
89 | std::vector num_hit_, num_miss_;
90 | std::vector closest_obstacle_;
91 | std::vector head_, prev_, next_;
92 |
93 | std::queue insert_queue_;
94 | std::queue delete_queue_;
95 | std::queue update_queue_;
96 | std::queue occupancy_queue_;
97 |
98 | // Map Properties
99 | Eigen::Vector3d origin_;
100 | int reserved_idx_4_undefined_;
101 | int total_time_ = 0;
102 | int infinity_, undefined_;
103 | double resolution_, resolution_inv_;
104 | Eigen::Vector3i max_vec_, min_vec_, last_max_vec_, last_min_vec_;
105 |
106 |
107 | // DLL Operations
108 | void DeleteFromList(int link, int idx);
109 | void InsertIntoList(int link, int idx);
110 |
111 | public:
112 | #ifdef HASH_TABLE
113 | ESDFMap(Eigen::Vector3d origin, double resolution, int reserve_size = 0);
114 | #else
115 | int grid_total_size_;
116 | ESDFMap(Eigen::Vector3d origin, double resolution, Eigen::Vector3d map_size);
117 | #endif
118 |
119 | ~ESDFMap() {
120 | //TODO: implement this
121 | }
122 |
123 | #ifdef PROBABILISTIC
124 | void SetParameters(double p_hit, double p_miss, double p_min, double p_max, double p_occ);
125 | #endif
126 |
127 |
128 | bool CheckUpdate();
129 | bool UpdateOccupancy(bool global_map);
130 | void UpdateESDF();
131 |
132 | // Occupancy Management
133 | int SetOccupancy(Eigen::Vector3d pos, int occ);
134 | int SetOccupancy(Eigen::Vector3i vox, int occ);
135 | int GetOccupancy(Eigen::Vector3d pos);
136 | int GetOccupancy(Eigen::Vector3i pos_id);
137 |
138 | // Distance Field Management
139 | double GetDistance(Eigen::Vector3d pos);
140 | double GetDistance(Eigen::Vector3i vox);
141 | double GetDistWithGradTrilinear(Eigen::Vector3d pos, Eigen::Vector3d &grad);
142 |
143 | // Visualization
144 | void GetPointCloud(sensor_msgs::PointCloud &m, int vis_lower_bound, int vis_upper_bound);
145 | void GetSliceMarker(visualization_msgs::Marker &m, int slice, int id, Eigen::Vector4d color, double max_dist);
146 |
147 | // Local Range
148 | void SetUpdateRange(Eigen::Vector3d min_pos, Eigen::Vector3d max_pos, bool new_vec = true);
149 | void SetOriginalRange();
150 |
151 | #ifndef PROBABILISTIC
152 | // For Deterministic Occupancy Grid
153 | void SetAway();
154 | void SetAway(Eigen::Vector3i left, Eigen::Vector3i right);
155 | void SetBack();
156 | void SetBack(Eigen::Vector3i left, Eigen::Vector3i right);
157 | #endif
158 |
159 | #ifdef DEBUG
160 | // only for test, check whether consistent
161 | bool CheckConsistency();
162 | // only for test, check between Ground Truth calculated by k-d tree
163 | bool CheckWithGroundTruth();
164 | #endif
165 |
166 | };
167 | }
168 |
169 | #endif //ESDF_MAP_H
170 |
--------------------------------------------------------------------------------
/include/Fiesta.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by tommy on 4/25/19.
3 | //
4 |
5 | #ifndef ESDF_TOOLS_INCLUDE_FIESTA_H_
6 | #define ESDF_TOOLS_INCLUDE_FIESTA_H_
7 | #include "ESDFMap.h"
8 | #include "raycast.h"
9 | #include "timing.h"
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | namespace fiesta {
27 |
28 | // sensor_msgs::PointCloud2::ConstPtr
29 | // sensor_msgs::Image::ConstPtr
30 |
31 | // geometry_msgs::PoseStamped::ConstPtr
32 | // nav_msgs::Odometry::ConstPtr
33 | // geometry_msgs::TransformStamped::ConstPtr
34 | template
35 | class Fiesta {
36 | private:
37 | Parameters parameters_;
38 | ESDFMap *esdf_map_;
39 | #ifdef SIGNED_NEEDED
40 | ESDFMap *inv_esdf_map_;
41 | #endif
42 | bool new_msg_ = false;
43 | pcl::PointCloud cloud_;
44 | #ifndef PROBABILISTIC
45 | sensor_msgs::PointCloud2::ConstPtr sync_pc_;
46 | #endif
47 | ros::Publisher slice_pub_, occupancy_pub_, text_pub_;
48 | ros::Subscriber transform_sub_, depth_sub_;
49 | ros::Timer update_mesh_timer_;
50 | Eigen::Vector3d sync_pos_, raycast_origin_, cur_pos_;
51 | Eigen::Quaterniond sync_q_;
52 |
53 | std::queue> transform_queue_;
54 | std::queue depth_queue_;
55 | DepthMsgType sync_depth_;
56 |
57 | cv::Mat img_[2];
58 | Eigen::Matrix4d transform_, last_transform_;
59 | uint image_cnt_ = 0, esdf_cnt_ = 0, tot_ = 0;
60 | #ifdef HASH_TABLE
61 | std::unordered_set set_free_, set_occ_;
62 | #else
63 | std::vector set_free_, set_occ_;
64 | #endif
65 | void Visualization(ESDFMap *esdf_map, bool global_vis, const std::string &text);
66 | #ifdef PROBABILISTIC
67 | void RaycastProcess(int i, int part, int tt);
68 | void RaycastMultithread();
69 | #endif
70 |
71 | double GetInterpolation(const cv::Mat &img, double u, double v);
72 |
73 | void DepthConversion();
74 |
75 | void SynchronizationAndProcess();
76 |
77 | void DepthCallback(const DepthMsgType &depth_map);
78 |
79 | void PoseCallback(const PoseMsgType &msg);
80 |
81 | void UpdateEsdfEvent(const ros::TimerEvent & /*event*/);
82 | public:
83 | Fiesta(ros::NodeHandle node);
84 | ~Fiesta();
85 | };
86 |
87 | template
88 | Fiesta::Fiesta(ros::NodeHandle node) {
89 | parameters_.SetParameters(node);
90 | #ifdef HASH_TABLE
91 | esdf_map_ = new ESDFMap(Eigen::Vector3d(0, 0, 0), parameters_.resolution_, parameters_.reserved_size_);
92 | #ifdef SIGNED_NEEDED
93 | inv_esdf_map_ = new ESDFMap(Eigen::Vector3d(0, 0, 0), parameters_.resolution_, parameters_.reserved_size_);
94 | #endif
95 | #else
96 | esdf_map_ = new ESDFMap(parameters_.l_cornor_, parameters_.resolution_, parameters_.map_size_);
97 | #ifdef SIGNED_NEEDED
98 | inv_esdf_map_ = new ESDFMap(parameters_.l_cornor_, parameters_.resolution_, parameters_.map_size_);
99 | #endif
100 | #endif
101 |
102 | #ifdef PROBABILISTIC
103 | esdf_map_->SetParameters(parameters_.p_hit_, parameters_.p_miss_,
104 | parameters_.p_min_, parameters_.p_max_, parameters_.p_occ_);
105 | #endif
106 | #ifndef HASH_TABLE
107 | set_free_.resize(esdf_map_->grid_total_size_);
108 | set_occ_.resize(esdf_map_->grid_total_size_);
109 | std::fill(set_free_.begin(), set_free_.end(), 0);
110 | std::fill(set_occ_.begin(), set_occ_.end(), 0);
111 | #endif
112 | // For Jie Bao
113 | // transform_sub_ = node.subscribe("/vins_estimator/camera_pose", 10, &Fiesta::PoseCallback, this);
114 | // depth_sub_ = node.subscribe("/camera/depth/image_rect_raw", 10, &Fiesta::DepthCallback, this);
115 | transform_sub_ = node.subscribe("transform", 10, &Fiesta::PoseCallback, this);
116 | depth_sub_ = node.subscribe("depth", 10, &Fiesta::DepthCallback, this);
117 |
118 | // Cow_and_Lady
119 | // depth_sub_ = node.subscribe("/camera/depth_registered/points", 1000, PointcloudCallback);
120 | // transform_sub_ = node.subscribe("/kinect/vrpn_client/estimated_transform", 1000, PoseCallback);
121 |
122 | //EuRoC
123 | // depth_sub_ = node.subscribe("/dense_stereo/pointcloud", 1000, PointcloudCallback);
124 | // transform_sub_ = node.subscribe("/vicon/firefly_sbx/firefly_sbx", 1000, PoseCallback);
125 |
126 | slice_pub_ = node.advertise("ESDFMap/slice", 1, true);
127 | occupancy_pub_ = node.advertise("ESDFMap/occ_pc", 1, true);
128 | text_pub_ = node.advertise("ESDFMap/text", 1, true);
129 |
130 | update_mesh_timer_ =
131 | node.createTimer(ros::Duration(parameters_.update_esdf_every_n_sec_),
132 | &Fiesta::UpdateEsdfEvent, this);
133 | }
134 |
135 | template
136 | Fiesta::~Fiesta() {
137 | delete esdf_map_;
138 | #ifdef SIGNED_NEEDED
139 | delete inv_esdf_map_;
140 | #endif
141 | }
142 |
143 | template
144 | void Fiesta::Visualization(ESDFMap *esdf_map, bool global_vis, const std::string &text) {
145 | if (esdf_map!=nullptr) {
146 | std::cout << "Visualization" << std::endl;
147 | if (global_vis)
148 | esdf_map->SetOriginalRange();
149 | else
150 | esdf_map->SetUpdateRange(cur_pos_ - parameters_.radius_, cur_pos_ + parameters_.radius_, false);
151 |
152 | sensor_msgs::PointCloud pc;
153 | esdf_map->GetPointCloud(pc, parameters_.vis_lower_bound_, parameters_.vis_upper_bound_);
154 | occupancy_pub_.publish(pc);
155 |
156 | visualization_msgs::Marker slice_marker;
157 | esdf_map->GetSliceMarker(slice_marker, parameters_.slice_vis_level_, 100,
158 | Eigen::Vector4d(0, 1.0, 0, 1), parameters_.slice_vis_max_dist_);
159 | slice_pub_.publish(slice_marker);
160 | }
161 | if (!text.empty()) {
162 | visualization_msgs::Marker marker;
163 | marker.header.frame_id = "world";
164 | marker.header.stamp = ros::Time::now();
165 | marker.id = 3456;
166 | marker.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
167 | marker.action = visualization_msgs::Marker::MODIFY;
168 |
169 | marker.pose.position.x = 8.0;
170 | marker.pose.position.y = 2.0;
171 | marker.pose.position.z = 3.0;
172 | marker.pose.orientation.x = 0.0;
173 | marker.pose.orientation.y = 0.0;
174 | marker.pose.orientation.z = 0.0;
175 | marker.pose.orientation.w = 1.0;
176 |
177 | marker.text = text;
178 |
179 | marker.scale.x = 0.3;
180 | marker.scale.y = 0.3;
181 | marker.scale.z = 0.6;
182 |
183 | marker.color.r = 0.0f;
184 | marker.color.g = 0.0f;
185 | marker.color.b = 1.0f;
186 | marker.color.a = 1.0f;
187 | text_pub_.publish(marker);
188 | }
189 | }
190 |
191 | #ifdef PROBABILISTIC
192 |
193 | template
194 | void Fiesta::RaycastProcess(int i, int part, int tt) {
195 | Eigen::Vector3d half = Eigen::Vector3d(0.5, 0.5, 0.5);
196 | for (int idx = part*i; idx < part*(i + 1); idx++) {
197 | std::vector output;
198 | if (idx > cloud_.points.size())
199 | break;
200 | pcl::PointXYZ pt = cloud_.points[idx];
201 | int cnt = 0;
202 | if (std::isnan(pt.x) || std::isnan(pt.y) || std::isnan(pt.z))
203 | continue;
204 | Eigen::Vector4d tmp = transform_*Eigen::Vector4d(pt.x, pt.y, pt.z, 1);
205 | Eigen::Vector3d point = Eigen::Vector3d(tmp(0), tmp(1), tmp(2))/tmp(3);
206 |
207 | int tmp_idx;
208 | double length = (point - raycast_origin_).norm();
209 | if (length < parameters_.min_ray_length_)
210 | continue;
211 | else if (length > parameters_.max_ray_length_) {
212 | point = (point - raycast_origin_)/length*parameters_.max_ray_length_ + raycast_origin_;
213 | tmp_idx = esdf_map_->SetOccupancy((Eigen::Vector3d) point, 0);
214 | } else
215 | tmp_idx = esdf_map_->SetOccupancy((Eigen::Vector3d) point, 1);
216 | #ifdef SIGNED_NEEDED
217 | tmp_idx = inv_esdf_map_->SetOccupancy((Eigen::Vector3d) point, 0);
218 | #endif
219 | // //TODO: -10000 ?
220 |
221 | if (tmp_idx!=-10000) {
222 | #ifdef HASH_TABLE
223 | if (set_occ_.find(tmp_idx) != set_occ_.end())
224 | continue;
225 | else set_occ_.insert(tmp_idx);
226 | #else
227 | if (set_occ_[tmp_idx]==tt)
228 | continue;
229 | else
230 | set_occ_[tmp_idx] = tt;
231 | #endif
232 | }
233 | Raycast(raycast_origin_/parameters_.resolution_,
234 | point/parameters_.resolution_,
235 | parameters_.l_cornor_/parameters_.resolution_,
236 | parameters_.r_cornor_/parameters_.resolution_,
237 | &output);
238 |
239 | for (int i = output.size() - 2; i >= 0; i--) {
240 | Eigen::Vector3d tmp = (output[i] + half)*parameters_.resolution_;
241 |
242 | length = (tmp - raycast_origin_).norm();
243 | if (length < parameters_.min_ray_length_)
244 | break;
245 | if (length > parameters_.max_ray_length_)
246 | continue;
247 | int tmp_idx;
248 | tmp_idx = esdf_map_->SetOccupancy(tmp, 0);
249 | #ifdef SIGNED_NEEDED
250 | tmp_idx = inv_esdf_map_->SetOccupancy(tmp, 1);
251 | #endif
252 | //TODO: -10000 ?
253 | if (tmp_idx!=-10000) {
254 | #ifdef HASH_TABLE
255 | if (set_free_.find(tmp_idx) != set_free_.end()) {
256 | if (++cnt >= 1) {
257 | cnt = 0;
258 | break;
259 | }
260 | } else {
261 | set_free_.insert(tmp_idx);
262 | cnt = 0;
263 | }
264 | #else
265 | if (set_free_[tmp_idx]==tt) {
266 | if (++cnt >= 1) {
267 | cnt = 0;
268 | break;
269 | }
270 | } else {
271 | set_free_[tmp_idx] = tt;
272 | cnt = 0;
273 | }
274 | #endif
275 | }
276 | }
277 | }
278 | }
279 |
280 | template
281 | void Fiesta::RaycastMultithread() {
282 | // TODO: when using vector, this is not needed
283 | #ifdef HASH_TABLE
284 | set_free_.clear();
285 | set_occ_.clear();
286 | #endif
287 | int tt = ++tot_;
288 | timing::Timer raycastingTimer("raycasting");
289 |
290 | if (parameters_.ray_cast_num_thread_==0) {
291 | RaycastProcess(0, cloud_.points.size(), tt);
292 | } else {
293 | int part = cloud_.points.size()/parameters_.ray_cast_num_thread_;
294 | std::list integration_threads = std::list();
295 | for (size_t i = 0; i < parameters_.ray_cast_num_thread_; ++i) {
296 | integration_threads.emplace_back(&Fiesta::RaycastProcess, this, i, part, tt);
297 | }
298 | for (std::thread &thread : integration_threads) {
299 | thread.join();
300 | }
301 | }
302 | raycastingTimer.Stop();
303 | }
304 |
305 | #endif // PROBABILISTIC
306 |
307 | template
308 | double Fiesta::GetInterpolation(const cv::Mat &img, double u, double v) {
309 | int vu = img.at(v, u);
310 | int v1u = img.at(v + 1, u);
311 | int vu1 = img.at(v, u + 1);
312 | int v1u1 = img.at(v + 1, u + 1);
313 | float a = u - (float) u;
314 | float c = v - (float) v;
315 | return (vu*(1.f - a) + vu1*a)*(1.f - c) + (v1u*(1.f - a) + v1u1*a)*c;
316 | }
317 |
318 | template
319 | void Fiesta::DepthConversion() {
320 | timing::Timer depth_timer("depth");
321 | ++image_cnt_;
322 | cv::Mat ¤t_img = img_[image_cnt_ & 1];
323 | cv::Mat &last_img = img_[!(image_cnt_ & 1)];
324 |
325 | cv_bridge::CvImagePtr cv_ptr;
326 | cv_ptr = cv_bridge::toCvCopy(depth_queue_.front(), depth_queue_.front()->encoding);
327 | // TODO: make it a parameter
328 | constexpr double k_depth_scaling_factor = 1000.0;
329 | if (depth_queue_.front()->encoding==sensor_msgs::image_encodings::TYPE_32FC1) {
330 | (cv_ptr->image).convertTo(cv_ptr->image, CV_16UC1, k_depth_scaling_factor);
331 | }
332 | cv_ptr->image.copyTo(current_img);
333 |
334 | double depth;
335 | cloud_.clear();
336 | double uu, vv;
337 |
338 | uint16_t *row_ptr;
339 | int cols = current_img.cols, rows = current_img.rows;
340 | if (!parameters_.use_depth_filter_) {
341 | for (int v = 0; v < rows; v++) {
342 | row_ptr = current_img.ptr(v);
343 | for (int u = 0; u < cols; u++) {
344 | depth = (*row_ptr++)/k_depth_scaling_factor;
345 | pcl::PointXYZ point;
346 | point.x = (u - parameters_.center_x_)*depth/parameters_.focal_x_;
347 | point.y = (v - parameters_.center_y_)*depth/parameters_.focal_y_;
348 | point.z = depth;
349 | cloud_.push_back(point);
350 | }
351 | }
352 | } else {
353 | if (image_cnt_!=1) {
354 | Eigen::Vector4d coord_h;
355 | Eigen::Vector3d coord;
356 | for (int v = parameters_.depth_filter_margin_; v < rows - parameters_.depth_filter_margin_; v++) {
357 | row_ptr = current_img.ptr(v) + parameters_.depth_filter_margin_;
358 | for (int u = parameters_.depth_filter_margin_; u < cols - parameters_.depth_filter_margin_; u++) {
359 | depth = (*row_ptr++)/k_depth_scaling_factor;
360 | pcl::PointXYZ point;
361 | point.x = (u - parameters_.center_x_)*depth/parameters_.focal_x_;
362 | point.y = (v - parameters_.center_y_)*depth/parameters_.focal_y_;
363 | point.z = depth;
364 | if (depth > parameters_.depth_filter_max_dist_ || depth < parameters_.depth_filter_min_dist_)
365 | continue;
366 | coord_h = last_transform_.inverse()*transform_*Eigen::Vector4d(point.x, point.y, point.z, 1);
367 | coord = Eigen::Vector3d(coord_h(0), coord_h(1), coord_h(2))/coord_h(3);
368 | uu = coord.x()*parameters_.focal_x_/coord.z() + parameters_.center_x_;
369 | vv = coord.y()*parameters_.focal_y_/coord.z() + parameters_.center_y_;
370 | if (uu >= 0 && uu < cols && vv >= 0 && vv < rows) {
371 | // getInterpolation(last_img, uu, vv)
372 | if (fabs(last_img.at((int) vv, (int) uu)/k_depth_scaling_factor - coord.z())
373 | < parameters_.depth_filter_tolerance_) {
374 | cloud_.push_back(point);
375 | }
376 | } //else cloud_.push_back(point_);
377 | }
378 | }
379 | }
380 | }
381 | depth_timer.Stop();
382 | }
383 |
384 | template
385 | void Fiesta::SynchronizationAndProcess() {
386 | ros::Time depth_time;
387 | double time_delay = 3e-3;
388 | while (!depth_queue_.empty()) {
389 | bool new_pos = false;
390 | depth_time = depth_queue_.front()->header.stamp;
391 | while (transform_queue_.size() > 1 &&
392 | std::get<0>(transform_queue_.front()) <= depth_time + ros::Duration(time_delay)) {
393 | sync_pos_ = std::get<1>(transform_queue_.front());
394 | sync_q_ = std::get<2>(transform_queue_.front());
395 | transform_queue_.pop();
396 | new_pos = true;
397 | }
398 | if (transform_queue_.empty()
399 | || std::get<0>(transform_queue_.front()) <= depth_time + ros::Duration(time_delay)) {
400 | break;
401 | }
402 | if (!new_pos) {
403 | depth_queue_.pop();
404 | continue;
405 | }
406 |
407 | new_msg_ = true;
408 | #ifndef PROBABILISTIC
409 | // TODO: sync_depth_ must be PointCloud2
410 | sync_depth_ = depth_queue_.front();
411 | return;
412 | #else
413 | if (parameters_.use_depth_filter_)
414 | last_transform_ = transform_;
415 | transform_.block<3, 3>(0, 0) = sync_q_.toRotationMatrix();
416 | transform_.block<3, 1>(0, 3) = sync_pos_;
417 | transform_(3, 0) = transform_(3, 1) = transform_(3, 2) = 0;
418 | transform_(3, 3) = 1;
419 | transform_ = transform_*parameters_.T_D_B_*parameters_.T_B_C_;
420 | raycast_origin_ = Eigen::Vector3d(transform_(0, 3), transform_(1, 3), transform_(2, 3))/transform_(3, 3);
421 |
422 | if constexpr(std::is_same::value) {
423 | DepthConversion();
424 | } else if constexpr(std::is_same::value) {
425 | sensor_msgs::PointCloud2::ConstPtr tmp = depth_queue_.front();
426 | pcl::fromROSMsg(*tmp, cloud_);
427 | }
428 |
429 | std::cout << "Pointcloud Size:\t" << cloud_.points.size() << std::endl;
430 | if ((int) cloud_.points.size()==0) {
431 | depth_queue_.pop();
432 | continue;
433 | }
434 |
435 | RaycastMultithread();
436 | depth_queue_.pop();
437 | #endif
438 | }
439 | }
440 |
441 | template
442 | void Fiesta::PoseCallback(const PoseMsgType &msg) {
443 | Eigen::Vector3d pos;
444 | Eigen::Quaterniond q;
445 |
446 | if constexpr(std::is_same::value) {
447 | pos = Eigen::Vector3d(msg->pose.position.x,
448 | msg->pose.position.y,
449 | msg->pose.position.z);
450 | q = Eigen::Quaterniond(msg->pose.orientation.w,
451 | msg->pose.orientation.x,
452 | msg->pose.orientation.y,
453 | msg->pose.orientation.z);
454 | } else if constexpr(std::is_same::value) {
455 | pos = Eigen::Vector3d(msg->pose.pose.position.x,
456 | msg->pose.pose.position.y,
457 | msg->pose.pose.position.z);
458 | q = Eigen::Quaterniond(msg->pose.pose.orientation.w,
459 | msg->pose.pose.orientation.x,
460 | msg->pose.pose.orientation.y,
461 | msg->pose.pose.orientation.z);
462 | } else if constexpr(std::is_same::value) {
463 | pos = Eigen::Vector3d(msg->transform.translation.x,
464 | msg->transform.translation.y,
465 | msg->transform.translation.z);
466 | q = Eigen::Quaterniond(msg->transform.rotation.w,
467 | msg->transform.rotation.x,
468 | msg->transform.rotation.y,
469 | msg->transform.rotation.z);
470 | }
471 |
472 | transform_queue_.push(std::make_tuple(msg->header.stamp, pos, q));
473 | }
474 |
475 | template
476 | void Fiesta::DepthCallback(const DepthMsgType &depth_map) {
477 | depth_queue_.push(depth_map);
478 | SynchronizationAndProcess();
479 | }
480 |
481 | template
482 | void Fiesta::UpdateEsdfEvent(const ros::TimerEvent & /*event*/) {
483 | if (!new_msg_)
484 | return;
485 | new_msg_ = false;
486 | cur_pos_ = sync_pos_;
487 |
488 | #ifndef PROBABILISTIC
489 | timing::Timer handlePCTimer("handlePointCloud");
490 | pcl::fromROSMsg(*sync_pc_, cloud_);
491 |
492 | esdf_map_->SetUpdateRange(cur_pos_ - parameters_.radius_, cur_pos_ + parameters_.radius_, false);
493 | esdf_map_->SetAway();
494 |
495 | Eigen::Vector3i tmp_vox;
496 | Eigen::Vector3d tmp_pos;
497 | for (int i = 0; i < cloud_.size(); i++) {
498 | tmp_pos = Eigen::Vector3d(cloud_[i].x, cloud_[i].y, cloud_[i].z);
499 | esdf_map_->SetOccupancy(tmp_pos, 1);
500 | }
501 | esdf_map_->SetBack();
502 | handlePCTimer.Stop();
503 | #endif
504 | esdf_cnt_++;
505 | std::cout << "Running " << esdf_cnt_ << " updates." << std::endl;
506 | // ros::Time t1 = ros::Time::now();
507 | if (esdf_map_->CheckUpdate()) {
508 | timing::Timer update_esdf_timer("UpdateESDF");
509 | if (parameters_.global_update_)
510 | esdf_map_->SetOriginalRange();
511 | else
512 | esdf_map_->SetUpdateRange(cur_pos_ - parameters_.radius_, cur_pos_ + parameters_.radius_);
513 | esdf_map_->UpdateOccupancy(parameters_.global_update_);
514 | esdf_map_->UpdateESDF();
515 | #ifdef SIGNED_NEEDED
516 | // TODO: Complete this SIGNED_NEEDED
517 | inv_esdf_map_->UpdateOccupancy();
518 | inv_esdf_map_->UpdateESDF();
519 | #endif
520 | update_esdf_timer.Stop();
521 | timing::Timing::Print(std::cout);
522 | }
523 | // ros::Time t2 = ros::Time::now();
524 |
525 | // std::string text = "Fiesta\nCurrent update Time\n"
526 | // + timing::Timing::SecondsToTimeString((t2 - t1).toSec() * 1000)
527 | // + " ms\n" + "Average update Time\n" +
528 | // timing::Timing::SecondsToTimeString(timing::Timing::GetMeanSeconds("UpdateESDF") * 1000)
529 | // + " ms";
530 |
531 | if (parameters_.visualize_every_n_updates_!=0 && esdf_cnt_%parameters_.visualize_every_n_updates_==0) {
532 | // std::thread(Visualization, esdf_map_, text).detach();
533 | Visualization(esdf_map_, parameters_.global_vis_, "");
534 | }
535 | // else {
536 | // std::thread(Visualization, nullptr, text).detach();
537 | // Visualization(nullptr, globalVis, "");
538 | // }
539 | }
540 | }
541 | #endif //ESDF_TOOLS_INCLUDE_FIESTA_H_
542 |
--------------------------------------------------------------------------------
/include/parameters.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by tommy on 4/25/19.
3 | //
4 |
5 | #ifndef ESDF_TOOLS_INCLUDE_PARAMETERS_H_
6 | #define ESDF_TOOLS_INCLUDE_PARAMETERS_H_
7 | #include
8 | #include
9 | #define PROBABILISTIC
10 | //#define HASH_TABLE
11 | #define BLOCK
12 | #define BITWISE
13 | #define DEBUG
14 | //#define SIGNED_NEEDED
15 |
16 | namespace fiesta {
17 |
18 | // Connectivity used in BFS
19 | // region DIRECTION
20 | // const static int num_dirs_ = 6; // only faces
21 | // const Eigen::Vector3i dirs_[num_dirs_] = {Eigen::Vector3i(-1, 0, 0), Eigen::Vector3i(1, 0, 0),
22 | // Eigen::Vector3i(0, -1, 0), Eigen::Vector3i(0, 1, 0),
23 | // Eigen::Vector3i(0, 0, -1), Eigen::Vector3i(0, 0, 1)};
24 |
25 | // const static int num_dirs_ = 18; // faces & enges
26 | // const Eigen::Vector3i dirs_[num_dirs_] = {Eigen::Vector3i(-1, 0, 0), Eigen::Vector3i(1, 0, 0),
27 | // Eigen::Vector3i(0, -1, 0), Eigen::Vector3i(0, 1, 0),
28 | // Eigen::Vector3i(0, 0, -1), Eigen::Vector3i(0, 0, 1),
29 | //
30 | // Eigen::Vector3i(-1, -1, 0), Eigen::Vector3i(1, 1, 0),
31 | // Eigen::Vector3i(0, -1, -1), Eigen::Vector3i(0, 1, 1),
32 | // Eigen::Vector3i(-1, 0, -1), Eigen::Vector3i(1, 0, 1),
33 | // Eigen::Vector3i(-1, 1, 0), Eigen::Vector3i(1, -1, 0),
34 | // Eigen::Vector3i(0, -1, 1), Eigen::Vector3i(0, 1, -1),
35 | // Eigen::Vector3i(1, 0, -1), Eigen::Vector3i(-1, 0, 1)};
36 |
37 | // const static int num_dirs_ = 26; // faces & edges & vertices
38 | // const Eigen::Vector3i dirs_[num_dirs_] = {Eigen::Vector3i(-1, 0, 0), Eigen::Vector3i(1, 0, 0),
39 | // Eigen::Vector3i(0, -1, 0), Eigen::Vector3i(0, 1, 0),
40 | // Eigen::Vector3i(0, 0, -1), Eigen::Vector3i(0, 0, 1),
41 | //
42 | // Eigen::Vector3i(-1, -1, 0), Eigen::Vector3i(1, 1, 0),
43 | // Eigen::Vector3i(0, -1, -1), Eigen::Vector3i(0, 1, 1),
44 | // Eigen::Vector3i(-1, 0, -1), Eigen::Vector3i(1, 0, 1),
45 | // Eigen::Vector3i(-1, 1, 0), Eigen::Vector3i(1, -1, 0),
46 | // Eigen::Vector3i(0, -1, 1), Eigen::Vector3i(0, 1, -1),
47 | // Eigen::Vector3i(1, 0, -1), Eigen::Vector3i(-1, 0, 1),
48 | //
49 | // Eigen::Vector3i(-1, -1, -1), Eigen::Vector3i(1, 1, 1),
50 | // Eigen::Vector3i(-1, -1, 1), Eigen::Vector3i(1, 1, -1),
51 | // Eigen::Vector3i(-1, 1, -1), Eigen::Vector3i(1, -1, 1),
52 | // Eigen::Vector3i(1, -1, -1), Eigen::Vector3i(-1, 1, 1)};
53 |
54 | const static int num_dirs_ = 24; // faces 2 steps
55 | const Eigen::Vector3i dirs_[num_dirs_] = {Eigen::Vector3i(-1, 0, 0), Eigen::Vector3i(1, 0, 0),
56 | Eigen::Vector3i(0, -1, 0), Eigen::Vector3i(0, 1, 0),
57 | Eigen::Vector3i(0, 0, -1), Eigen::Vector3i(0, 0, 1),
58 |
59 | Eigen::Vector3i(-1, -1, 0), Eigen::Vector3i(1, 1, 0),
60 | Eigen::Vector3i(0, -1, -1), Eigen::Vector3i(0, 1, 1),
61 | Eigen::Vector3i(-1, 0, -1), Eigen::Vector3i(1, 0, 1),
62 | Eigen::Vector3i(-1, 1, 0), Eigen::Vector3i(1, -1, 0),
63 | Eigen::Vector3i(0, -1, 1), Eigen::Vector3i(0, 1, -1),
64 | Eigen::Vector3i(1, 0, -1), Eigen::Vector3i(-1, 0, 1),
65 |
66 | Eigen::Vector3i(-2, 0, 0), Eigen::Vector3i(2, 0, 0),
67 | Eigen::Vector3i(0, -2, 0), Eigen::Vector3i(0, 2, 0),
68 | Eigen::Vector3i(0, 0, -2), Eigen::Vector3i(0, 0, 2)};
69 |
70 | // const static int num_dirs_ = 32; // faces 2 steps & cornor
71 | // const Eigen::Vector3i dirs_[num_dirs_] = {Eigen::Vector3i(-1, 0, 0), Eigen::Vector3i(1, 0, 0),
72 | // Eigen::Vector3i(0, -1, 0), Eigen::Vector3i(0, 1, 0),
73 | // Eigen::Vector3i(0, 0, -1), Eigen::Vector3i(0, 0, 1),
74 | //
75 | // Eigen::Vector3i(-1, -1, 0), Eigen::Vector3i(1, 1, 0),
76 | // Eigen::Vector3i(0, -1, -1), Eigen::Vector3i(0, 1, 1),
77 | // Eigen::Vector3i(-1, 0, -1), Eigen::Vector3i(1, 0, 1),
78 | // Eigen::Vector3i(-1, 1, 0), Eigen::Vector3i(1, -1, 0),
79 | // Eigen::Vector3i(0, -1, 1), Eigen::Vector3i(0, 1, -1),
80 | // Eigen::Vector3i(1, 0, -1), Eigen::Vector3i(-1, 0, 1),
81 | //
82 | // Eigen::Vector3i(-2, 0, 0), Eigen::Vector3i(2, 0, 0),
83 | // Eigen::Vector3i(0, -2, 0), Eigen::Vector3i(0, 2, 0),
84 | // Eigen::Vector3i(0, 0, -2), Eigen::Vector3i(0, 0, 2),
85 | //
86 | // Eigen::Vector3i(-1, -1, -1), Eigen::Vector3i(1, 1, 1),
87 | // Eigen::Vector3i(-1, -1, 1), Eigen::Vector3i(1, 1, -1),
88 | // Eigen::Vector3i(-1, 1, -1), Eigen::Vector3i(1, -1, 1),
89 | // Eigen::Vector3i(1, -1, -1), Eigen::Vector3i(-1, 1, 1)
90 | // };
91 |
92 | // const static int num_dirs_ = 62; // faces 3 steps
93 | // const Eigen::Vector3i dirs_[num_dirs_] = {Eigen::Vector3i(-1, 0, 0), Eigen::Vector3i(1, 0, 0),
94 | // Eigen::Vector3i(0, -1, 0), Eigen::Vector3i(0, 1, 0),
95 | // Eigen::Vector3i(0, 0, -1), Eigen::Vector3i(0, 0, 1),
96 | //
97 | // Eigen::Vector3i(-1, -1, 0), Eigen::Vector3i(1, 1, 0),
98 | // Eigen::Vector3i(0, -1, -1), Eigen::Vector3i(0, 1, 1),
99 | // Eigen::Vector3i(-1, 0, -1), Eigen::Vector3i(1, 0, 1),
100 | // Eigen::Vector3i(-1, 1, 0), Eigen::Vector3i(1, -1, 0),
101 | // Eigen::Vector3i(0, -1, 1), Eigen::Vector3i(0, 1, -1),
102 | // Eigen::Vector3i(1, 0, -1), Eigen::Vector3i(-1, 0, 1),
103 | //
104 | // Eigen::Vector3i(-1, -1, -1), Eigen::Vector3i(1, 1, 1),
105 | // Eigen::Vector3i(-1, -1, 1), Eigen::Vector3i(1, 1, -1),
106 | // Eigen::Vector3i(-1, 1, -1), Eigen::Vector3i(1, -1, 1),
107 | // Eigen::Vector3i(1, -1, -1), Eigen::Vector3i(-1, 1, 1),
108 | //
109 | // Eigen::Vector3i(-2, 0, 0), Eigen::Vector3i(2, 0, 0),
110 | // Eigen::Vector3i(0, -2, 0), Eigen::Vector3i(0, 2, 0),
111 | // Eigen::Vector3i(0, 0, -2), Eigen::Vector3i(0, 0, 2),
112 | //
113 | // Eigen::Vector3i(-2, -1, 0), Eigen::Vector3i(2, 1, 0),
114 | // Eigen::Vector3i(0, -2, -1), Eigen::Vector3i(0, 2, 1),
115 | // Eigen::Vector3i(-2, 0, -1), Eigen::Vector3i(2, 0, 1),
116 | // Eigen::Vector3i(-2, 1, 0), Eigen::Vector3i(2, -1, 0),
117 | // Eigen::Vector3i(0, -2, 1), Eigen::Vector3i(0, 2, -1),
118 | // Eigen::Vector3i(2, 0, -1), Eigen::Vector3i(-2, 0, 1),
119 | //
120 | // Eigen::Vector3i(-1, -2, 0), Eigen::Vector3i(1, 2, 0),
121 | // Eigen::Vector3i(0, -1, -2), Eigen::Vector3i(0, 1, 2),
122 | // Eigen::Vector3i(-1, 0, -2), Eigen::Vector3i(1, 0, 2),
123 | // Eigen::Vector3i(-1, 2, 0), Eigen::Vector3i(1, -2, 0),
124 | // Eigen::Vector3i(0, -1, 2), Eigen::Vector3i(0, 1, -2),
125 | // Eigen::Vector3i(1, 0, -2), Eigen::Vector3i(-1, 0, 2),
126 | //
127 | // Eigen::Vector3i(-3, 0, 0), Eigen::Vector3i(3, 0, 0),
128 | // Eigen::Vector3i(0, -3, 0), Eigen::Vector3i(0, 3, 0),
129 | // Eigen::Vector3i(0, 0, -3), Eigen::Vector3i(0, 0, 3)};
130 |
131 | // endregion
132 |
133 | struct Parameters {
134 | // resolution
135 | double resolution_;
136 | // hash table implementation only
137 | int reserved_size_;
138 | // array implementation only
139 | Eigen::Vector3d l_cornor_, r_cornor_, map_size_;
140 | // intrinsic parameters of camera, only used if your input is depth image
141 | double center_x_, center_y_, focal_x_, focal_y_;
142 | // parameters of probabilistic occupancy updating
143 | double p_hit_, p_miss_, p_min_, p_max_, p_occ_;
144 | //depth filter
145 | bool use_depth_filter_;
146 | double depth_filter_max_dist_, depth_filter_min_dist_, depth_filter_tolerance_;
147 | int depth_filter_margin_;
148 | // ray cast parameters
149 | double min_ray_length_, max_ray_length_;
150 | // visualization
151 | double slice_vis_max_dist_;
152 | int slice_vis_level_, vis_lower_bound_, vis_upper_bound_;
153 | // frequency of updating
154 | double update_esdf_every_n_sec_;
155 | // frequency of visualization
156 | int visualize_every_n_updates_;
157 | // number of thread used
158 | int ray_cast_num_thread_;
159 | // local map
160 | bool global_vis_, global_update_, global_map_;
161 | Eigen::Vector3d radius_;
162 | // transforms
163 | Eigen::Matrix4d T_B_C_, T_D_B_;
164 |
165 |
166 | void SetParameters(const ros::NodeHandle &node);
167 | };
168 | }
169 | #endif //ESDF_TOOLS_INCLUDE_PARAMETERS_H_
170 |
--------------------------------------------------------------------------------
/include/raycast.h:
--------------------------------------------------------------------------------
1 | #ifndef RAYCAST_H_
2 | #define RAYCAST_H_
3 |
4 | #include
5 | #include
6 |
7 | double signum(double x);
8 |
9 | double mod(double value, double modulus);
10 |
11 | double intbound(double s, double ds);
12 |
13 | bool RayIntersectsAABB(const Eigen::Vector3d &start, const Eigen::Vector3d &end,
14 | const Eigen::Vector3d &lb, const Eigen::Vector3d &rt);
15 |
16 | void Raycast(const Eigen::Vector3d &start, const Eigen::Vector3d &end,
17 | const Eigen::Vector3d &min, const Eigen::Vector3d &max,
18 | std::vector *output);
19 |
20 | #endif // RAYCAST_H_
--------------------------------------------------------------------------------
/include/timing.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012-2013 Simon Lynen, ASL, ETH Zurich, Switzerland
3 | * You can contact the author at
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /* Adapted from Paul Furgale Schweizer Messer sm_timing */
19 |
20 | #ifndef VOXBLOX_UTILS_TIMING_H_
21 | #define VOXBLOX_UTILS_TIMING_H_
22 |
23 | #include
24 | #include
25 | #include
26 | #include