From ddef31d11a449c5dcbf5bc75321013a32587c6fa Mon Sep 17 00:00:00 2001 From: X-lanni Date: Tue, 13 Jan 2026 19:12:25 +0800 Subject: [PATCH] feat(slam): add lidar SLAM and pointcloud processing packages --- FAST_LIO/.github/stale.yml | 17 + FAST_LIO/.gitignore | 8 + FAST_LIO/.gitmodules | 4 + FAST_LIO/CMakeLists.txt | 128 + FAST_LIO/LICENSE | 339 +++ FAST_LIO/Log/fast_lio_time_log_analysis.m | 135 + FAST_LIO/Log/guide.md | 1 + FAST_LIO/Log/plot.py | 94 + FAST_LIO/PCD/1 | 1 + FAST_LIO/README.md | 199 ++ FAST_LIO/config/avia.yaml | 46 + FAST_LIO/config/horizon.yaml | 46 + FAST_LIO/config/mid360.yaml | 50 + FAST_LIO/config/ouster64.yaml | 47 + FAST_LIO/config/unilidar_l2.yaml | 61 + FAST_LIO/config/velodyne.yaml | 48 + FAST_LIO/include/Exp_mat.h | 103 + .../include/IKFoM_toolkit/esekfom/esekfom.hpp | 2008 +++++++++++++ .../include/IKFoM_toolkit/esekfom/util.hpp | 82 + .../IKFoM_toolkit/mtk/build_manifold.hpp | 229 ++ .../IKFoM_toolkit/mtk/src/SubManifold.hpp | 123 + .../include/IKFoM_toolkit/mtk/src/mtkmath.hpp | 294 ++ .../IKFoM_toolkit/mtk/src/vectview.hpp | 168 ++ .../include/IKFoM_toolkit/mtk/startIdx.hpp | 328 +++ .../include/IKFoM_toolkit/mtk/types/S2.hpp | 316 +++ .../include/IKFoM_toolkit/mtk/types/SOn.hpp | 317 +++ .../include/IKFoM_toolkit/mtk/types/vect.hpp | 461 +++ .../mtk/types/wrapped_cv_mat.hpp | 113 + FAST_LIO/include/common_lib.h | 270 ++ FAST_LIO/include/ikd-Tree/README.md | 2 + FAST_LIO/include/ikd-Tree/ikd_Tree.cpp | 1728 ++++++++++++ FAST_LIO/include/ikd-Tree/ikd_Tree.h | 344 +++ FAST_LIO/include/matplotlibcpp.h | 2499 +++++++++++++++++ FAST_LIO/include/so3_math.h | 111 + FAST_LIO/include/use-ikfom.hpp | 126 + FAST_LIO/launch/gdb_debug_example.launch | 22 + FAST_LIO/launch/mapping.launch.py | 70 + FAST_LIO/launch/unilidar_l2.launch.py | 70 + FAST_LIO/msg/Pose6D.msg | 7 + FAST_LIO/package.xml | 38 + FAST_LIO/rviz/fastlio.rviz | 304 ++ FAST_LIO/rviz_cfg/.gitignore | 0 FAST_LIO/rviz_cfg/loam_livox.rviz | 358 +++ FAST_LIO/src/IMU_Processing.hpp | 379 +++ FAST_LIO/src/laserMapping.cpp | 1194 ++++++++ FAST_LIO/src/preprocess.cpp | 1069 +++++++ FAST_LIO/src/preprocess.h | 196 ++ pcd2pgm/.clang-format | 18 + pcd2pgm/.clang-tidy | 62 + pcd2pgm/.docs/pcd.png | Bin 0 -> 1401655 bytes pcd2pgm/.docs/pgm.png | Bin 0 -> 87161 bytes pcd2pgm/.gitignore | 12 + pcd2pgm/.pre-commit-config.yaml | 127 + pcd2pgm/CMakeLists.txt | 54 + pcd2pgm/CONTRIBUTING.md | 63 + pcd2pgm/LICENSE | 202 ++ pcd2pgm/README.md | 79 + pcd2pgm/config/pcd2pgm.yaml | 12 + pcd2pgm/include/pcd2pgm/pcd2pgm.hpp | 72 + pcd2pgm/launch/pcd2pgm_launch.py | 88 + pcd2pgm/package.xml | 27 + pcd2pgm/rviz/pcd2pgm.rviz | 194 ++ pcd2pgm/src/pcd2pgm.cpp | 187 ++ point_lio_ros2/.gitignore | 4 + point_lio_ros2/.gitmodules | 8 + point_lio_ros2/CMakeLists.txt | 112 + point_lio_ros2/LICENSE | 339 +++ point_lio_ros2/Log/guide.md | 1 + point_lio_ros2/Log/imu.txt | 0 point_lio_ros2/Log/imu_pbp.txt | 0 point_lio_ros2/Log/mat_out.txt | 0 point_lio_ros2/Log/plot.py | 46 + point_lio_ros2/Log/plot_imu.py | 125 + point_lio_ros2/Log/plot_out.py | 178 ++ point_lio_ros2/Log/pos_log.txt | 0 point_lio_ros2/PCD/temp.txt | 1 + point_lio_ros2/README.md | 230 ++ point_lio_ros2/config/avia.yaml | 59 + point_lio_ros2/config/horizon.yaml | 59 + point_lio_ros2/config/mid360.yaml | 59 + point_lio_ros2/config/ouster64.yaml | 59 + point_lio_ros2/config/unilidar_l1.yaml | 61 + point_lio_ros2/config/unilidar_l2.yaml | 61 + point_lio_ros2/config/velody16.yaml | 65 + .../include/FOV_Checker/FOV_Checker.cpp | 472 ++++ .../include/FOV_Checker/FOV_Checker.h | 33 + point_lio_ros2/include/IKFoM/.gitignore | 32 + .../IKFoM/IKFoM_toolkit/esekfom/esekfom.hpp | 390 +++ .../IKFoM/IKFoM_toolkit/esekfom/util.hpp | 82 + .../IKFoM_toolkit/mtk/build_manifold.hpp | 248 ++ .../IKFoM_toolkit/mtk/src/SubManifold.hpp | 123 + .../IKFoM/IKFoM_toolkit/mtk/src/mtkmath.hpp | 294 ++ .../IKFoM/IKFoM_toolkit/mtk/src/vectview.hpp | 168 ++ .../IKFoM/IKFoM_toolkit/mtk/startIdx.hpp | 328 +++ .../IKFoM/IKFoM_toolkit/mtk/types/S2.hpp | 326 +++ .../IKFoM/IKFoM_toolkit/mtk/types/SEn.hpp | 334 +++ .../IKFoM/IKFoM_toolkit/mtk/types/SOn.hpp | 365 +++ .../IKFoM/IKFoM_toolkit/mtk/types/vect.hpp | 511 ++++ .../mtk/types/wrapped_cv_mat.hpp | 113 + point_lio_ros2/include/IKFoM/LICENSE | 339 +++ point_lio_ros2/include/IKFoM/README.md | 489 ++++ point_lio_ros2/include/common_lib.h | 189 ++ point_lio_ros2/include/ikd-Tree/README.md | 2 + point_lio_ros2/include/ikd-Tree/ikd_Tree.cpp | 1728 ++++++++++++ point_lio_ros2/include/ikd-Tree/ikd_Tree.h | 344 +++ point_lio_ros2/include/so3_math.h | 113 + .../launch/correct_odom_unilidar_l1.launch.py | 48 + .../launch/correct_odom_unilidar_l2.launch.py | 48 + .../launch/gdb_debug_example.launch.py | 68 + point_lio_ros2/launch/mapping_avia.launch.py | 68 + .../launch/mapping_horizon.launch.py | 68 + .../launch/mapping_mid360.launch.py | 68 + .../launch/mapping_ouster64.launch.py | 68 + .../launch/mapping_unilidar_l1.launch.py | 68 + .../launch/mapping_unilidar_l2.launch.py | 70 + .../launch/mapping_velody16.launch.py | 68 + point_lio_ros2/package.xml | 40 + point_lio_ros2/rviz_cfg/loam_livox.rviz | 326 +++ point_lio_ros2/src/Estimator.cpp | 435 +++ point_lio_ros2/src/Estimator.h | 118 + point_lio_ros2/src/IMU_Processing.hpp | 164 ++ point_lio_ros2/src/laserMapping.cpp | 1322 +++++++++ point_lio_ros2/src/parameters.cpp | 157 ++ point_lio_ros2/src/parameters.h | 46 + point_lio_ros2/src/preprocess.cpp | 732 +++++ point_lio_ros2/src/preprocess.h | 193 ++ pointcloud_to_laserscan/CHANGELOG.rst | 95 + pointcloud_to_laserscan/CMakeLists.txt | 33 + pointcloud_to_laserscan/LICENSE | 12 + pointcloud_to_laserscan/README.md | 49 + .../laserscan_to_pointcloud_node.hpp | 98 + .../pointcloud_to_laserscan_node.hpp | 102 + .../visibility_control.h | 80 + .../launch/pointcloud_to_laserscan_launch.py | 43 + .../sample_laserscan_to_pointcloud_launch.py | 47 + .../sample_pointcloud_to_laserscan_launch.py | 49 + pointcloud_to_laserscan/package.xml | 46 + .../src/dummy_pointcloud_publisher.cpp | 85 + .../src/laserscan_to_pointcloud_node.cpp | 150 + .../src/pointcloud_to_laserscan_node.cpp | 242 ++ 140 files changed, 29546 insertions(+) create mode 100644 FAST_LIO/.github/stale.yml create mode 100644 FAST_LIO/.gitignore create mode 100644 FAST_LIO/.gitmodules create mode 100644 FAST_LIO/CMakeLists.txt create mode 100644 FAST_LIO/LICENSE create mode 100644 FAST_LIO/Log/fast_lio_time_log_analysis.m create mode 100644 FAST_LIO/Log/guide.md create mode 100644 FAST_LIO/Log/plot.py create mode 100644 FAST_LIO/PCD/1 create mode 100644 FAST_LIO/README.md create mode 100644 FAST_LIO/config/avia.yaml create mode 100644 FAST_LIO/config/horizon.yaml create mode 100644 FAST_LIO/config/mid360.yaml create mode 100644 FAST_LIO/config/ouster64.yaml create mode 100644 FAST_LIO/config/unilidar_l2.yaml create mode 100644 FAST_LIO/config/velodyne.yaml create mode 100644 FAST_LIO/include/Exp_mat.h create mode 100755 FAST_LIO/include/IKFoM_toolkit/esekfom/esekfom.hpp create mode 100755 FAST_LIO/include/IKFoM_toolkit/esekfom/util.hpp create mode 100755 FAST_LIO/include/IKFoM_toolkit/mtk/build_manifold.hpp create mode 100755 FAST_LIO/include/IKFoM_toolkit/mtk/src/SubManifold.hpp create mode 100755 FAST_LIO/include/IKFoM_toolkit/mtk/src/mtkmath.hpp create mode 100755 FAST_LIO/include/IKFoM_toolkit/mtk/src/vectview.hpp create mode 100755 FAST_LIO/include/IKFoM_toolkit/mtk/startIdx.hpp create mode 100755 FAST_LIO/include/IKFoM_toolkit/mtk/types/S2.hpp create mode 100755 FAST_LIO/include/IKFoM_toolkit/mtk/types/SOn.hpp create mode 100755 FAST_LIO/include/IKFoM_toolkit/mtk/types/vect.hpp create mode 100755 FAST_LIO/include/IKFoM_toolkit/mtk/types/wrapped_cv_mat.hpp create mode 100644 FAST_LIO/include/common_lib.h create mode 100644 FAST_LIO/include/ikd-Tree/README.md create mode 100644 FAST_LIO/include/ikd-Tree/ikd_Tree.cpp create mode 100644 FAST_LIO/include/ikd-Tree/ikd_Tree.h create mode 100644 FAST_LIO/include/matplotlibcpp.h create mode 100644 FAST_LIO/include/so3_math.h create mode 100644 FAST_LIO/include/use-ikfom.hpp create mode 100644 FAST_LIO/launch/gdb_debug_example.launch create mode 100644 FAST_LIO/launch/mapping.launch.py create mode 100644 FAST_LIO/launch/unilidar_l2.launch.py create mode 100644 FAST_LIO/msg/Pose6D.msg create mode 100644 FAST_LIO/package.xml create mode 100644 FAST_LIO/rviz/fastlio.rviz create mode 100644 FAST_LIO/rviz_cfg/.gitignore create mode 100644 FAST_LIO/rviz_cfg/loam_livox.rviz create mode 100644 FAST_LIO/src/IMU_Processing.hpp create mode 100644 FAST_LIO/src/laserMapping.cpp create mode 100644 FAST_LIO/src/preprocess.cpp create mode 100644 FAST_LIO/src/preprocess.h create mode 100644 pcd2pgm/.clang-format create mode 100644 pcd2pgm/.clang-tidy create mode 100644 pcd2pgm/.docs/pcd.png create mode 100644 pcd2pgm/.docs/pgm.png create mode 100644 pcd2pgm/.gitignore create mode 100644 pcd2pgm/.pre-commit-config.yaml create mode 100644 pcd2pgm/CMakeLists.txt create mode 100644 pcd2pgm/CONTRIBUTING.md create mode 100644 pcd2pgm/LICENSE create mode 100644 pcd2pgm/README.md create mode 100644 pcd2pgm/config/pcd2pgm.yaml create mode 100644 pcd2pgm/include/pcd2pgm/pcd2pgm.hpp create mode 100644 pcd2pgm/launch/pcd2pgm_launch.py create mode 100644 pcd2pgm/package.xml create mode 100644 pcd2pgm/rviz/pcd2pgm.rviz create mode 100644 pcd2pgm/src/pcd2pgm.cpp create mode 100644 point_lio_ros2/.gitignore create mode 100644 point_lio_ros2/.gitmodules create mode 100644 point_lio_ros2/CMakeLists.txt create mode 100644 point_lio_ros2/LICENSE create mode 100644 point_lio_ros2/Log/guide.md create mode 100644 point_lio_ros2/Log/imu.txt create mode 100644 point_lio_ros2/Log/imu_pbp.txt create mode 100644 point_lio_ros2/Log/mat_out.txt create mode 100644 point_lio_ros2/Log/plot.py create mode 100644 point_lio_ros2/Log/plot_imu.py create mode 100644 point_lio_ros2/Log/plot_out.py create mode 100644 point_lio_ros2/Log/pos_log.txt create mode 100644 point_lio_ros2/PCD/temp.txt create mode 100644 point_lio_ros2/README.md create mode 100644 point_lio_ros2/config/avia.yaml create mode 100644 point_lio_ros2/config/horizon.yaml create mode 100644 point_lio_ros2/config/mid360.yaml create mode 100644 point_lio_ros2/config/ouster64.yaml create mode 100644 point_lio_ros2/config/unilidar_l1.yaml create mode 100644 point_lio_ros2/config/unilidar_l2.yaml create mode 100644 point_lio_ros2/config/velody16.yaml create mode 100644 point_lio_ros2/include/FOV_Checker/FOV_Checker.cpp create mode 100644 point_lio_ros2/include/FOV_Checker/FOV_Checker.h create mode 100644 point_lio_ros2/include/IKFoM/.gitignore create mode 100644 point_lio_ros2/include/IKFoM/IKFoM_toolkit/esekfom/esekfom.hpp create mode 100644 point_lio_ros2/include/IKFoM/IKFoM_toolkit/esekfom/util.hpp create mode 100644 point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/build_manifold.hpp create mode 100644 point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/src/SubManifold.hpp create mode 100644 point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/src/mtkmath.hpp create mode 100644 point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/src/vectview.hpp create mode 100644 point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/startIdx.hpp create mode 100644 point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/S2.hpp create mode 100644 point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/SEn.hpp create mode 100644 point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/SOn.hpp create mode 100644 point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/vect.hpp create mode 100644 point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/wrapped_cv_mat.hpp create mode 100644 point_lio_ros2/include/IKFoM/LICENSE create mode 100644 point_lio_ros2/include/IKFoM/README.md create mode 100644 point_lio_ros2/include/common_lib.h create mode 100644 point_lio_ros2/include/ikd-Tree/README.md create mode 100644 point_lio_ros2/include/ikd-Tree/ikd_Tree.cpp create mode 100644 point_lio_ros2/include/ikd-Tree/ikd_Tree.h create mode 100644 point_lio_ros2/include/so3_math.h create mode 100644 point_lio_ros2/launch/correct_odom_unilidar_l1.launch.py create mode 100644 point_lio_ros2/launch/correct_odom_unilidar_l2.launch.py create mode 100644 point_lio_ros2/launch/gdb_debug_example.launch.py create mode 100644 point_lio_ros2/launch/mapping_avia.launch.py create mode 100644 point_lio_ros2/launch/mapping_horizon.launch.py create mode 100644 point_lio_ros2/launch/mapping_mid360.launch.py create mode 100644 point_lio_ros2/launch/mapping_ouster64.launch.py create mode 100644 point_lio_ros2/launch/mapping_unilidar_l1.launch.py create mode 100644 point_lio_ros2/launch/mapping_unilidar_l2.launch.py create mode 100644 point_lio_ros2/launch/mapping_velody16.launch.py create mode 100644 point_lio_ros2/package.xml create mode 100644 point_lio_ros2/rviz_cfg/loam_livox.rviz create mode 100644 point_lio_ros2/src/Estimator.cpp create mode 100644 point_lio_ros2/src/Estimator.h create mode 100644 point_lio_ros2/src/IMU_Processing.hpp create mode 100644 point_lio_ros2/src/laserMapping.cpp create mode 100644 point_lio_ros2/src/parameters.cpp create mode 100644 point_lio_ros2/src/parameters.h create mode 100644 point_lio_ros2/src/preprocess.cpp create mode 100644 point_lio_ros2/src/preprocess.h create mode 100644 pointcloud_to_laserscan/CHANGELOG.rst create mode 100644 pointcloud_to_laserscan/CMakeLists.txt create mode 100644 pointcloud_to_laserscan/LICENSE create mode 100644 pointcloud_to_laserscan/README.md create mode 100644 pointcloud_to_laserscan/include/pointcloud_to_laserscan/laserscan_to_pointcloud_node.hpp create mode 100644 pointcloud_to_laserscan/include/pointcloud_to_laserscan/pointcloud_to_laserscan_node.hpp create mode 100644 pointcloud_to_laserscan/include/pointcloud_to_laserscan/visibility_control.h create mode 100644 pointcloud_to_laserscan/launch/pointcloud_to_laserscan_launch.py create mode 100644 pointcloud_to_laserscan/launch/sample_laserscan_to_pointcloud_launch.py create mode 100644 pointcloud_to_laserscan/launch/sample_pointcloud_to_laserscan_launch.py create mode 100644 pointcloud_to_laserscan/package.xml create mode 100644 pointcloud_to_laserscan/src/dummy_pointcloud_publisher.cpp create mode 100644 pointcloud_to_laserscan/src/laserscan_to_pointcloud_node.cpp create mode 100644 pointcloud_to_laserscan/src/pointcloud_to_laserscan_node.cpp diff --git a/FAST_LIO/.github/stale.yml b/FAST_LIO/.github/stale.yml new file mode 100644 index 0000000..4d545fe --- /dev/null +++ b/FAST_LIO/.github/stale.yml @@ -0,0 +1,17 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 21 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 1 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - security +# Label to use when marking an issue as stale +staleLabel: stale +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false diff --git a/FAST_LIO/.gitignore b/FAST_LIO/.gitignore new file mode 100644 index 0000000..eb7be62 --- /dev/null +++ b/FAST_LIO/.gitignore @@ -0,0 +1,8 @@ +build +Log/*.png +Log/*.txt +Log/*.csv +Log/*.pdf +.vscode/c_cpp_properties.json +.vscode/settings.json +PCD/*.pcd diff --git a/FAST_LIO/.gitmodules b/FAST_LIO/.gitmodules new file mode 100644 index 0000000..b8a0efa --- /dev/null +++ b/FAST_LIO/.gitmodules @@ -0,0 +1,4 @@ +[submodule "include/ikd-Tree"] + path = include/ikd-Tree + url = https://github.com/hku-mars/ikd-Tree.git + branch = fast_lio diff --git a/FAST_LIO/CMakeLists.txt b/FAST_LIO/CMakeLists.txt new file mode 100644 index 0000000..e091f3a --- /dev/null +++ b/FAST_LIO/CMakeLists.txt @@ -0,0 +1,128 @@ +cmake_minimum_required(VERSION 3.8) +project(fast_lio) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() + + ADD_COMPILE_OPTIONS(-std=c++17) + ADD_COMPILE_OPTIONS(-std=c++17) + set(CMAKE_CXX_FLAGS "-std=c++17 -O3") + + add_definitions(-DROOT_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/\") + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions") + set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -pthread -std=c++0x -std=c++14 -fexceptions") +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +message("Current CPU archtecture: ${CMAKE_SYSTEM_PROCESSOR}") + +if(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") + include(ProcessorCount) + ProcessorCount(N) + message("Processer number: ${N}") + + if(N GREATER 4) + add_definitions(-DMP_EN) + add_definitions(-DMP_PROC_NUM=3) + message("core for MP: 3") + elseif(N GREATER 3) + add_definitions(-DMP_EN) + add_definitions(-DMP_PROC_NUM=2) + message("core for MP: 2") + else() + add_definitions(-DMP_PROC_NUM=1) + endif() +else() + add_definitions(-DMP_PROC_NUM=1) +endif() + +find_package(OpenMP QUIET) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + +find_package(PythonLibs REQUIRED) +find_path(MATPLOTLIB_CPP_INCLUDE_DIRS "matplotlibcpp.h") + +# ROS dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(rclcpp_components REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(nav_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(std_msgs REQUIRED) +find_package(std_srvs REQUIRED) +find_package(visualization_msgs REQUIRED) +find_package(pcl_ros REQUIRED) +find_package(pcl_conversions REQUIRED) +find_package(livox_ros_driver2 REQUIRED) +find_package(rosidl_default_generators REQUIRED) + +set(dependencies + rclcpp + rclcpp_components + geometry_msgs + nav_msgs + sensor_msgs + std_msgs + std_srvs + visualization_msgs + pcl_ros + pcl_conversions + livox_ros_driver2 +) + +# Thirdparty libraries +find_package(Eigen3 REQUIRED) +find_package(PCL REQUIRED COMPONENTS common io) + +message(Eigen: ${EIGEN3_INCLUDE_DIR}) +message(STATUS "PCL: ${PCL_INCLUDE_DIRS}") + +set(msg_files + "msg/Pose6D.msg" +) + +rosidl_generate_interfaces(${PROJECT_NAME} + ${msg_files} +) +ament_export_dependencies(rosidl_default_runtime) + +add_executable(fastlio_mapping src/laserMapping.cpp include/ikd-Tree/ikd_Tree.cpp src/preprocess.cpp) +target_include_directories(fastlio_mapping PUBLIC + $ + $ + ${PCL_INCLUDE_DIRS} +) +target_link_libraries(fastlio_mapping ${PCL_LIBRARIES} ${PYTHON_LIBRARIES} Eigen3::Eigen) +target_include_directories(fastlio_mapping PRIVATE ${PYTHON_INCLUDE_DIRS}) + +list(APPEND EOL_LIST "foxy" "galactic" "eloquent" "dashing" "crystal") + +if($ENV{ROS_DISTRO} IN_LIST EOL_LIST) + # Custommsg to support foxy & galactic + rosidl_target_interfaces(fastlio_mapping + ${PROJECT_NAME} "rosidl_typesupport_cpp") +else() + rosidl_get_typesupport_target(cpp_typesupport_target + ${PROJECT_NAME} "rosidl_typesupport_cpp") + target_link_libraries(fastlio_mapping ${cpp_typesupport_target}) +endif() + +ament_target_dependencies(fastlio_mapping ${dependencies}) + +# ---------------- Install --------------- # +install(TARGETS fastlio_mapping + DESTINATION lib/${PROJECT_NAME} +) + +install( + DIRECTORY config launch rviz + DESTINATION share/${PROJECT_NAME} +) + +ament_package() diff --git a/FAST_LIO/LICENSE b/FAST_LIO/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/FAST_LIO/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/FAST_LIO/Log/fast_lio_time_log_analysis.m b/FAST_LIO/Log/fast_lio_time_log_analysis.m new file mode 100644 index 0000000..8a0b679 --- /dev/null +++ b/FAST_LIO/Log/fast_lio_time_log_analysis.m @@ -0,0 +1,135 @@ +clear +close all + +Color_red = [0.6350 0.0780 0.1840]; +Color_blue = [0 0.4470 0.7410]; +Color_orange = [0.8500 0.3250 0.0980]; +Color_green = [0.4660 0.6740 0.1880]; +Color_lightblue = [0.3010 0.7450 0.9330]; +Color_purple = [0.4940 0.1840 0.5560]; +Color_yellow = [0.9290 0.6940 0.1250]; + +fast_lio_ikdtree = csvread("./fast_lio_time_log.csv",1,0); +timestamp_ikd = fast_lio_ikdtree(:,1); +timestamp_ikd = timestamp_ikd - min(timestamp_ikd); +total_time_ikd = fast_lio_ikdtree(:,2)*1e3; +scan_num = fast_lio_ikdtree(:,3); +incremental_time_ikd = fast_lio_ikdtree(:,4)*1e3; +search_time_ikd = fast_lio_ikdtree(:,5)*1e3; +delete_size_ikd = fast_lio_ikdtree(:,6); +delete_time_ikd = fast_lio_ikdtree(:,7) * 1e3; +tree_size_ikd_st = fast_lio_ikdtree(:,8); +tree_size_ikd = fast_lio_ikdtree(:,9); +add_points = fast_lio_ikdtree(:,10); + +fast_lio_forest = csvread("fast_lio_time_log.csv",1,0); +fov_check_time_forest = fast_lio_forest(:,5)*1e3; +average_time_forest = fast_lio_forest(:,2)*1e3; +total_time_forest = fast_lio_forest(:,6)*1e3; +incremental_time_forest = fast_lio_forest(:,3)*1e3; +search_time_forest = fast_lio_forest(:,4)*1e3; +timestamp_forest = fast_lio_forest(:,1); + +% Use slide window to calculate average +L = 1; % Length of slide window +for i = 1:length(timestamp_ikd) + if (i 0); +search_time_ikd = search_time_ikd(index_ikd); +index_forest = find(search_time_forest > 0); +search_time_forest = search_time_forest(index_forest); + +t = nexttile; +hold on; +boxplot_data_ikd = [incremental_time_ikd,total_time_ikd]; +boxplot_data_forest = [incremental_time_forest,total_time_forest]; +Colors_ikd = [Color_blue;Color_blue;Color_blue]; +Colors_forest = [Color_orange;Color_orange;Color_orange]; +% xticks([3,8,13]) +h_search_ikd = boxplot(search_time_ikd,'Whisker',50,'Positions',1,'Colors',Color_blue,'Widths',0.3); +h_search_forest = boxplot(search_time_forest,'Whisker',50,'Positions',1.5,'Colors',Color_orange,'Widths',0.3); +h_ikd = boxplot(boxplot_data_ikd,'Whisker',50,'Positions',[3,5],'Colors',Color_blue,'Widths',0.3); +h_forest = boxplot(boxplot_data_forest,'Whisker',50,'Positions',[3.5,5.5],'Colors',Color_orange,'Widths',0.3); +ax2 = gca; +ax2.YAxis.Scale = 'log'; +xlim([0.5,6.0]) +ylim([0.0008,100]) +xticks([1.25 3.25 5.25]) +xticklabels({'Nearest Search',' Incremental Updates','Total Time'}); +yticks([1e-3,1e-2,1e-1,1e0,1e1,1e2]) +ax2.YAxis.FontSize = 12; +ax2.XAxis.FontSize = 14.5; +% ax.XAxis.FontWeight = 'bold'; +ylabel('Run Time/ms','FontSize',14,'FontName','Times New Roman') +box_vars = [findall(h_search_ikd,'Tag','Box');findall(h_ikd,'Tag','Box');findall(h_search_forest,'Tag','Box');findall(h_forest,'Tag','Box')]; +for j=1:length(box_vars) + if (j<=3) + Color = Color_blue; + else + Color = Color_orange; + end + patch(get(box_vars(j),'XData'),get(box_vars(j),'YData'),Color,'FaceAlpha',0.25,'EdgeColor',Color); +end +Lg = legend(box_vars([1,4]), {'ikd-Tree','ikd-Forest'},'Location',[0.6707 0.4305 0.265 0.07891],'fontsize',14,'fontname','Times New Roman'); +grid on +set(gca,'YMinorGrid','off') +nexttile; +hold on; +grid on; +box on; +set(gca,'FontSize',12,'FontName','Times New Roman') +plot(timestamp_ikd, alpha_bal_ikd,'-','Color',Color_blue,'LineWidth',1.2); +plot(timestamp_ikd, alpha_del_ikd,'--','Color',Color_orange, 'LineWidth', 1.2); +plot(timestamp_ikd, 0.6*ones(size(alpha_bal_ikd)), ':','Color','black','LineWidth',1.2); +lg = legend("\alpha_{bal}", "\alpha_{del}",'location',[0.7871 0.1131 0.1433 0.069],'fontsize',14,'fontname','Times New Roman') +title("Re-balancing Criterion",'FontSize',16,'FontName','Times New Roman') +xlabel("time/s",'FontSize',16,'FontName','Times New Roman') +yl = ylabel("\alpha",'FontSize',15, 'Position',[285.7 0.4250 -1]) +xlim([32,390]); +ylim([0,0.85]); +ax3 = gca; +ax3.YAxis.FontSize = 12; +ax3.XAxis.FontSize = 12; +% print('./Figures/fastlio_exp_combine','-depsc','-r1200') +% exportgraphics(f,'./Figures/fastlio_exp_combine_1.pdf','ContentType','vector') + diff --git a/FAST_LIO/Log/guide.md b/FAST_LIO/Log/guide.md new file mode 100644 index 0000000..8ff3fc1 --- /dev/null +++ b/FAST_LIO/Log/guide.md @@ -0,0 +1 @@ +Here saved the debug records which can be drew by the ../Log/plot.py. The record function can be found frm the MACRO: DEBUG_FILE_DIR(name) in common_lib.h. diff --git a/FAST_LIO/Log/plot.py b/FAST_LIO/Log/plot.py new file mode 100644 index 0000000..e4aad85 --- /dev/null +++ b/FAST_LIO/Log/plot.py @@ -0,0 +1,94 @@ +# import matplotlib +# matplotlib.use('Agg') +import numpy as np +import matplotlib.pyplot as plt + + +#######for ikfom +fig, axs = plt.subplots(4,2) +lab_pre = ['', 'pre-x', 'pre-y', 'pre-z'] +lab_out = ['', 'out-x', 'out-y', 'out-z'] +plot_ind = range(7,10) +a_pre=np.loadtxt('mat_pre.txt') +a_out=np.loadtxt('mat_out.txt') +time=a_pre[:,0] +axs[0,0].set_title('Attitude') +axs[1,0].set_title('Translation') +axs[2,0].set_title('Extrins-R') +axs[3,0].set_title('Extrins-T') +axs[0,1].set_title('Velocity') +axs[1,1].set_title('bg') +axs[2,1].set_title('ba') +axs[3,1].set_title('Gravity') +for i in range(1,4): + for j in range(8): + axs[j%4, j/4].plot(time, a_pre[:,i+j*3],'.-', label=lab_pre[i]) + axs[j%4, j/4].plot(time, a_out[:,i+j*3],'.-', label=lab_out[i]) +for j in range(8): + # axs[j].set_xlim(386,389) + axs[j%4, j/4].grid() + axs[j%4, j/4].legend() +plt.grid() +#######for ikfom####### + + +#### Draw IMU data +# fig, axs = plt.subplots(2) +# imu=np.loadtxt('imu.txt') +# time=imu[:,0] +# axs[0].set_title('Gyroscope') +# axs[1].set_title('Accelerameter') +# lab_1 = ['gyr-x', 'gyr-y', 'gyr-z'] +# lab_2 = ['acc-x', 'acc-y', 'acc-z'] +# for i in range(3): +# # if i==1: +# axs[0].plot(time, imu[:,i+1],'.-', label=lab_1[i]) +# axs[1].plot(time, imu[:,i+4],'.-', label=lab_2[i]) +# for i in range(2): +# # axs[i].set_xlim(386,389) +# axs[i].grid() +# axs[i].legend() +# plt.grid() + +# #### Draw time calculation +# plt.figure(3) +# fig = plt.figure() +# font1 = {'family' : 'Times New Roman', +# 'weight' : 'normal', +# 'size' : 12, +# } +# c="red" +# a_out1=np.loadtxt('Log/mat_out_time_indoor1.txt') +# a_out2=np.loadtxt('Log/mat_out_time_indoor2.txt') +# a_out3=np.loadtxt('Log/mat_out_time_outdoor.txt') +# # n = a_out[:,1].size +# # time_mean = a_out[:,1].mean() +# # time_se = a_out[:,1].std() / np.sqrt(n) +# # time_err = a_out[:,1] - time_mean +# # feat_mean = a_out[:,2].mean() +# # feat_err = a_out[:,2] - feat_mean +# # feat_se = a_out[:,2].std() / np.sqrt(n) +# ax1 = fig.add_subplot(111) +# ax1.set_ylabel('Effective Feature Numbers',font1) +# ax1.boxplot(a_out1[:,2], showfliers=False, positions=[0.9]) +# ax1.boxplot(a_out2[:,2], showfliers=False, positions=[1.9]) +# ax1.boxplot(a_out3[:,2], showfliers=False, positions=[2.9]) +# ax1.set_ylim([0, 3000]) + +# ax2 = ax1.twinx() +# ax2.spines['right'].set_color('red') +# ax2.set_ylabel('Compute Time (ms)',font1) +# ax2.yaxis.label.set_color('red') +# ax2.tick_params(axis='y', colors='red') +# ax2.boxplot(a_out1[:,1]*1000, showfliers=False, positions=[1.1],boxprops=dict(color=c),capprops=dict(color=c),whiskerprops=dict(color=c)) +# ax2.boxplot(a_out2[:,1]*1000, showfliers=False, positions=[2.1],boxprops=dict(color=c),capprops=dict(color=c),whiskerprops=dict(color=c)) +# ax2.boxplot(a_out3[:,1]*1000, showfliers=False, positions=[3.1],boxprops=dict(color=c),capprops=dict(color=c),whiskerprops=dict(color=c)) +# ax2.set_xlim([0.5, 3.5]) +# ax2.set_ylim([0, 100]) + +# plt.xticks([1,2,3], ('Outdoor Scene', 'Indoor Scene 1', 'Indoor Scene 2')) +# # # print(time_se) +# # # print(a_out3[:,2]) +# plt.grid() +# plt.savefig("time.pdf", dpi=1200) +plt.show() diff --git a/FAST_LIO/PCD/1 b/FAST_LIO/PCD/1 new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/FAST_LIO/PCD/1 @@ -0,0 +1 @@ +1 diff --git a/FAST_LIO/README.md b/FAST_LIO/README.md new file mode 100644 index 0000000..412d1e1 --- /dev/null +++ b/FAST_LIO/README.md @@ -0,0 +1,199 @@ +> ROS2 Fork repo maintainer: [Ericsiii](https://github.com/Ericsii) + +## Related Works and Extended Application + +**SLAM:** + +1. [ikd-Tree](https://github.com/hku-mars/ikd-Tree): A state-of-art dynamic KD-Tree for 3D kNN search. +2. [R2LIVE](https://github.com/hku-mars/r2live): A high-precision LiDAR-inertial-Vision fusion work using FAST-LIO as LiDAR-inertial front-end. +3. [LI_Init](https://github.com/hku-mars/LiDAR_IMU_Init): A robust, real-time LiDAR-IMU extrinsic initialization and synchronization package.. +4. [FAST-LIO-LOCALIZATION](https://github.com/HViktorTsoi/FAST_LIO_LOCALIZATION): The integration of FAST-LIO with **Re-localization** function module. + +**Control and Plan:** + +1. [IKFOM](https://github.com/hku-mars/IKFoM): A Toolbox for fast and high-precision on-manifold Kalman filter. +2. [UAV Avoiding Dynamic Obstacles](https://github.com/hku-mars/dyn_small_obs_avoidance): One of the implementation of FAST-LIO in robot's planning. +3. [UGV Demo](https://www.youtube.com/watch?v=wikgrQbE6Cs): Model Predictive Control for Trajectory Tracking on Differentiable Manifolds. +4. [Bubble Planner](https://arxiv.org/abs/2202.12177): Planning High-speed Smooth Quadrotor Trajectories using Receding Corridors. + + + +## FAST-LIO +**FAST-LIO** (Fast LiDAR-Inertial Odometry) is a computationally efficient and robust LiDAR-inertial odometry package. It fuses LiDAR feature points with IMU data using a tightly-coupled iterated extended Kalman filter to allow robust navigation in fast-motion, noisy or cluttered environments where degeneration occurs. Our package address many key issues: +1. Fast iterated Kalman filter for odometry optimization; +2. Automaticaly initialized at most steady environments; +3. Parallel KD-Tree Search to decrease the computation; + +## FAST-LIO 2.0 (2021-07-05 Update) + + +
+ + +
+ +**Related video:** [FAST-LIO2](https://youtu.be/2OvjGnxszf8), [FAST-LIO1](https://youtu.be/iYCY6T79oNU) + +**Pipeline:** +
+ +
+ +**New Features:** +1. Incremental mapping using [ikd-Tree](https://github.com/hku-mars/ikd-Tree), achieve faster speed and over 100Hz LiDAR rate. +2. Direct odometry (scan to map) on Raw LiDAR points (feature extraction can be disabled), achieving better accuracy. +3. Since no requirements for feature extraction, FAST-LIO2 can support many types of LiDAR including spinning (Velodyne, Ouster) and solid-state (Livox Avia, Horizon, MID-70) LiDARs, and can be easily extended to support more LiDARs. +4. Support external IMU. +5. Support ARM-based platforms including Khadas VIM3, Nivida TX2, Raspberry Pi 4B(8G RAM). + +**Related papers**: + +[FAST-LIO2: Fast Direct LiDAR-inertial Odometry](https://raw.githubusercontent.com/hku-mars/FAST_LIO/main/doc/Fast_LIO_2.pdf) + +[FAST-LIO: A Fast, Robust LiDAR-inertial Odometry Package by Tightly-Coupled Iterated Kalman Filter](https://arxiv.org/abs/2010.08196) + +**Contributors** + +[Wei Xu 徐威](https://github.com/XW-HKU),[Yixi Cai 蔡逸熙](https://github.com/Ecstasy-EC),[Dongjiao He 贺东娇](https://github.com/Joanna-HE),[Fangcheng Zhu 朱方程](https://github.com/zfc-zfc),[Jiarong Lin 林家荣](https://github.com/ziv-lin),[Zheng Liu 刘政](https://github.com/Zale-Liu), [Borong Yuan](https://github.com/borongyuan) + + + +## 1. Prerequisites +### 1.1 **Ubuntu** and **ROS** +**Ubuntu >= 20.04** + +The **default from apt** PCL and Eigen is enough for FAST-LIO to work normally. + +ROS >= Foxy (Recommend to use ROS-Humble). [ROS Installation](https://docs.ros.org/en/humble/Installation.html) + +### 1.2. **PCL && Eigen** +PCL >= 1.8, Follow [PCL Installation](https://pointclouds.org/downloads/#linux). + +Eigen >= 3.3.4, Follow [Eigen Installation](http://eigen.tuxfamily.org/index.php?title=Main_Page). + +### 1.3. **livox_ros_driver2** +Follow [livox_ros_driver2 Installation](https://github.com/Livox-SDK/livox_ros_driver2). + +You can also use the one I modified [livox_ros_driver2](https://github.com/Ericsii/livox_ros_driver2/tree/feature/use-standard-unit) + +*Remarks:* +- Since the FAST-LIO must support Livox serials LiDAR firstly, so the **livox_ros_driver** must be installed and **sourced** before run any FAST-LIO launch file. +- How to source? The easiest way is add the line ``` source $Livox_ros_driver_dir$/devel/setup.bash ``` to the end of file ``` ~/.bashrc ```, where ``` $Livox_ros_driver_dir$ ``` is the directory of the livox ros driver workspace (should be the ``` ws_livox ``` directory if you completely followed the livox official document). + + +## 2. Build +Clone the repository and colcon build: + +```bash + cd /src # cd into a ros2 workspace folder + git clone https://github.com/Ericsii/FAST_LIO_ROS2.git --recursive + cd .. + rosdep install --from-paths src --ignore-src -y + colcon build --symlink-install + . ./install/setup.bash # use setup.zsh if use zsh +``` +- **Remember to source the livox_ros_driver before build (follow [1.3 livox_ros_driver](#1.3))** +- If you want to use a custom build of PCL, add the following line to ~/.bashrc +```export PCL_ROOT={CUSTOM_PCL_PATH}``` +## 3. Directly run +Noted: + +A. Please make sure the IMU and LiDAR are **Synchronized**, that's important. + +B. The warning message "Failed to find match for field 'time'." means the timestamps of each LiDAR points are missed in the rosbag file. That is important for the forward propagation and backwark propagation. + +C. We recommend to set the **extrinsic_est_en** to false if the extrinsic is give. As for the extrinsic initiallization, please refer to our recent work: [**Robust Real-time LiDAR-inertial Initialization**](https://github.com/hku-mars/LiDAR_IMU_Init). + +### 3.1 Run use ros launch +Connect to your PC to Livox LiDAR by following [Livox-ros-driver2 installation](https://github.com/Livox-SDK/livox_ros_driver2), then +```bash +cd +. install/setup.bash # use setup.zsh if use zsh +ros2 launch fast_lio mapping.launch.py config_file:=avia.yaml +``` + +Change `config_file` parameter to other yaml file under config directory as you need. + +Launch livox ros driver. Use MID360 as an example. + +```bash +ros2 launch livox_ros_driver2 msg_MID360_launch.py +``` + +- For livox serials, FAST-LIO only support the data collected by the ``` livox_lidar_msg.launch ``` since only its ``` livox_ros_driver2/CustomMsg ``` data structure produces the timestamp of each LiDAR point which is very important for the motion undistortion. ``` livox_lidar.launch ``` can not produce it right now. +- If you want to change the frame rate, please modify the **publish_freq** parameter in the [livox_lidar_msg.launch](https://github.com/Livox-SDK/livox_ros_driver/blob/master/livox_ros_driver2/launch/livox_lidar_msg.launch) of [Livox-ros-driver](https://github.com/Livox-SDK/livox_ros_driver2) before make the livox_ros_driver pakage. + +### 3.2 For Livox serials with external IMU + +mapping_avia.launch theratically supports mid-70, mid-40 or other livox serial LiDAR, but need to setup some parameters befor run: + +Edit ``` config/avia.yaml ``` to set the below parameters: + +1. LiDAR point cloud topic name: ``` lid_topic ``` +2. IMU topic name: ``` imu_topic ``` +3. Translational extrinsic: ``` extrinsic_T ``` +4. Rotational extrinsic: ``` extrinsic_R ``` (only support rotation matrix) +- The extrinsic parameters in FAST-LIO is defined as the LiDAR's pose (position and rotation matrix) in IMU body frame (i.e. the IMU is the base frame). They can be found in the official manual. +- FAST-LIO produces a very simple software time sync for livox LiDAR, set parameter ```time_sync_en``` to ture to turn on. But turn on **ONLY IF external time synchronization is really not possible**, since the software time sync cannot make sure accuracy. + +### 3.4 PCD file save + +1. Enable `pcd_save.pcd_save_en` in the config file and set the `map_file_path` to the path where the map will be saved. +2. Launch the fastlio2 according to README. +3. Open RQt and switch to `Plugins->Services->Service Caller`. Trigger the service `/map_save`, then the pcd map file will be generated + +```pcl_viewer scans.pcd``` can visualize the point clouds. + +*Tips for pcl_viewer:* +- change what to visualize/color by pressing keyboard 1,2,3,4,5 when pcl_viewer is running. +``` + 1 is all random + 2 is X values + 3 is Y values + 4 is Z values + 5 is intensity +``` + +## 4. Rosbag Example +### 4.1 Livox Avia Rosbag +
+ + + +Files: Can be downloaded from [google drive](https://drive.google.com/drive/folders/1CGYEJ9-wWjr8INyan6q1BZz_5VtGB-fP?usp=sharing)**!!!This ros1 bag should be convert to ros2!!!** + +Run: +```bash +ros2 launch fast_lio mapping.launch.py config_path:= +ros2 bag play + +``` + +### 4.2 Velodyne HDL-32E Rosbag + +**NCLT Dataset**: Original bin file can be found [here](http://robots.engin.umich.edu/nclt/). + +We produce [Rosbag Files](https://drive.google.com/drive/folders/1VBK5idI1oyW0GC_I_Hxh63aqam3nocNK?usp=sharing) and [a python script](https://drive.google.com/file/d/1leh7DxbHx29DyS1NJkvEfeNJoccxH7XM/view) to generate Rosbag files: ```python3 sensordata_to_rosbag_fastlio.py bin_file_dir bag_name.bag```**!!!This ros1 bag should be convert to ros2!!!** To convert ros1 bag to ros2 bag, please follow the documentation [Convert rosbag versions](https://ternaris.gitlab.io/rosbags/topics/convert.html) + +Run: +``` +roslaunch fast_lio mapping_velodyne.launch +rosbag play YOUR_DOWNLOADED.bag +``` + +## 5.Implementation on UAV +In order to validate the robustness and computational efficiency of FAST-LIO in actual mobile robots, we build a small-scale quadrotor which can carry a Livox Avia LiDAR with 70 degree FoV and a DJI Manifold 2-C onboard computer with a 1.8 GHz Intel i7-8550U CPU and 8 G RAM, as shown in below. + +The main structure of this UAV is 3d printed (Aluminum or PLA), the .stl file will be open-sourced in the future. + +
+ + +
+ +## 6.Acknowledgments + +Thanks for LOAM(J. Zhang and S. Singh. LOAM: Lidar Odometry and Mapping in Real-time), [Livox_Mapping](https://github.com/Livox-SDK/livox_mapping), [LINS](https://github.com/ChaoqinRobotics/LINS---LiDAR-inertial-SLAM) and [Loam_Livox](https://github.com/hku-mars/loam_livox). diff --git a/FAST_LIO/config/avia.yaml b/FAST_LIO/config/avia.yaml new file mode 100644 index 0000000..3bbc880 --- /dev/null +++ b/FAST_LIO/config/avia.yaml @@ -0,0 +1,46 @@ +/**: + ros__parameters: + feature_extract_enable: false + point_filter_num: 3 + max_iteration: 3 + filter_size_surf: 0.5 + filter_size_map: 0.5 + cube_side_length: 1000.0 + runtime_pos_log_enable: false + map_file_path: "./test.pcd" + + common: + lid_topic: "/livox/lidar" + imu_topic: "/livox/imu" + time_sync_en: false # ONLY turn on when external time synchronization is really not possible + time_offset_lidar_to_imu: 0.0 # Time offset between lidar and IMU calibrated by other algorithms, e.g. LI-Init (can be found in README). + # This param will take effect no matter what time_sync_en is. So if the time offset is not known exactly, please set as 0.0 + + preprocess: + lidar_type: 1 # 1 for Livox serials LiDAR, 2 for Velodyne LiDAR, 3 for ouster LiDAR, + scan_line: 6 + blind: 4.0 + + mapping: + acc_cov: 0.1 + gyr_cov: 0.1 + b_acc_cov: 0.0001 + b_gyr_cov: 0.0001 + fov_degree: 90.0 + det_range: 450.0 + extrinsic_est_en: false # true: enable the online estimation of IMU-LiDAR extrinsic + extrinsic_T: [ 0.04165, 0.02326, -0.0284 ] + extrinsic_R: [ 1., 0., 0., + 0., 1., 0., + 0., 0., 1.] + + publish: + path_en: false + scan_publish_en: true # false: close all the point cloud output + dense_publish_en: true # false: low down the points number in a global-frame point clouds scan. + scan_bodyframe_pub_en: true # true: output the point cloud scans in IMU-body-frame + + pcd_save: + pcd_save_en: true + interval: -1 # how many LiDAR frames saved in each pcd file; + # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames. diff --git a/FAST_LIO/config/horizon.yaml b/FAST_LIO/config/horizon.yaml new file mode 100644 index 0000000..2ff8654 --- /dev/null +++ b/FAST_LIO/config/horizon.yaml @@ -0,0 +1,46 @@ +/**: + ros__parameters: + feature_extract_enable: false + point_filter_num: 3 + max_iteration: 3 + filter_size_surf: 0.5 + filter_size_map: 0.5 + cube_side_length: 1000.0 + runtime_pos_log_enable: false + map_file_path: "./test.pcd" + + common: + lid_topic: "/livox/lidar" + imu_topic: "/livox/imu" + time_sync_en: false # ONLY turn on when external time synchronization is really not possible + time_offset_lidar_to_imu: 0.0 # Time offset between lidar and IMU calibrated by other algorithms, e.g. LI-Init (can be found in README). + # This param will take effect no matter what time_sync_en is. So if the time offset is not known exactly, please set as 0.0 + + preprocess: + lidar_type: 1 # 1 for Livox serials LiDAR, 2 for Velodyne LiDAR, 3 for ouster LiDAR, + scan_line: 6 + blind: 4.0 + + mapping: + acc_cov: 0.1 + gyr_cov: 0.1 + b_acc_cov: 0.0001 + b_gyr_cov: 0.0001 + fov_degree: 100.0 + det_range: 260.0 + extrinsic_est_en: true # true: enable the online estimation of IMU-LiDAR extrinsic + extrinsic_T: [ 0.05512, 0.02226, -0.0297 ] + extrinsic_R: [ 1., 0., 0., + 0., 1., 0., + 0., 0., 1.] + + publish: + path_en: false + scan_publish_en: true # false: close all the point cloud output + dense_publish_en: true # false: low down the points number in a global-frame point clouds scan. + scan_bodyframe_pub_en: true # true: output the point cloud scans in IMU-body-frame + + pcd_save: + pcd_save_en: true + interval: -1 # how many LiDAR frames saved in each pcd file; + # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames. diff --git a/FAST_LIO/config/mid360.yaml b/FAST_LIO/config/mid360.yaml new file mode 100644 index 0000000..a987453 --- /dev/null +++ b/FAST_LIO/config/mid360.yaml @@ -0,0 +1,50 @@ +/**: + ros__parameters: + feature_extract_enable: false + point_filter_num: 3 + max_iteration: 3 + filter_size_surf: 0.5 + filter_size_map: 0.5 + cube_side_length: 400.0 + runtime_pos_log_enable: false + map_file_path: "./test.pcd" + + common: + lid_topic: "/livox/lidar" + imu_topic: "/livox/imu" + time_sync_en: false # ONLY turn on when external time synchronization is really not possible + time_offset_lidar_to_imu: 0.0 # Time offset between lidar and IMU calibrated by other algorithms, e.g. LI-Init (can be found in README). + # This param will take effect no matter what time_sync_en is. So if the time offset is not known exactly, please set as 0.0 + + preprocess: + lidar_type: 1 # 1 for Livox serials LiDAR, 2 for Velodyne LiDAR, 3 for ouster LiDAR, 4 for any other pointcloud input + scan_line: 4 + blind: 0.5 + timestamp_unit: 3 + scan_rate: 10 + + mapping: + acc_cov: 0.1 + gyr_cov: 0.1 + b_acc_cov: 0.0001 + b_gyr_cov: 0.0001 + fov_degree: 360.0 + det_range: 60.0 + extrinsic_est_en: true # true: enable the online estimation of IMU-LiDAR extrinsic + extrinsic_T: [ -0.011, -0.02329, 0.04412 ] + extrinsic_R: [ 1., 0., 0., + 0., 1., 0., + 0., 0., 1.] + + publish: + path_en: true # true: publish Path + effect_map_en: true # true: publish Effects + map_en: true # true: publish Map cloud + scan_publish_en: true # false: close all the point cloud output + dense_publish_en: false # false: low down the points number in a global-frame point clouds scan. + scan_bodyframe_pub_en: true # true: output the point cloud scans in IMU-body-frame + + pcd_save: + pcd_save_en: true + interval: -1 # how many LiDAR frames saved in each pcd file; + # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames. diff --git a/FAST_LIO/config/ouster64.yaml b/FAST_LIO/config/ouster64.yaml new file mode 100644 index 0000000..6f47b82 --- /dev/null +++ b/FAST_LIO/config/ouster64.yaml @@ -0,0 +1,47 @@ +/**: + ros__parameters: + feature_extract_enable: false + point_filter_num: 3 + max_iteration: 3 + filter_size_surf: 0.5 + filter_size_map: 0.5 + cube_side_length: 1000.0 + runtime_pos_log_enable: false + map_file_path: "./test.pcd" + + common: + lid_topic: "/os_cloud_node/points" + imu_topic: "/os_cloud_node/imu" + time_sync_en: false # ONLY turn on when external time synchronization is really not possible + time_offset_lidar_to_imu: 0.0 # Time offset between lidar and IMU calibrated by other algorithms, e.g. LI-Init (can be found in README). + # This param will take effect no matter what time_sync_en is. So if the time offset is not known exactly, please set as 0.0 + + preprocess: + lidar_type: 3 # 1 for Livox serials LiDAR, 2 for Velodyne LiDAR, 3 for ouster LiDAR, + scan_line: 64 + timestamp_unit: 3 # 0-second, 1-milisecond, 2-microsecond, 3-nanosecond. + blind: 4.0 + + mapping: + acc_cov: 0.1 + gyr_cov: 0.1 + b_acc_cov: 0.0001 + b_gyr_cov: 0.0001 + fov_degree: 360.0 + det_range: 150.0 + extrinsic_est_en: false # true: enable the online estimation of IMU-LiDAR extrinsic + extrinsic_T: [ 0.0, 0.0, 0.0 ] + extrinsic_R: [1., 0., 0., + 0., 1., 0., + 0., 0., 1.] + + publish: + path_en: false + scan_publish_en: true # false: close all the point cloud output + dense_publish_en: true # false: low down the points number in a global-frame point clouds scan. + scan_bodyframe_pub_en: true # true: output the point cloud scans in IMU-body-frame + + pcd_save: + pcd_save_en: true + interval: -1 # how many LiDAR frames saved in each pcd file; + # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames. diff --git a/FAST_LIO/config/unilidar_l2.yaml b/FAST_LIO/config/unilidar_l2.yaml new file mode 100644 index 0000000..ef41db6 --- /dev/null +++ b/FAST_LIO/config/unilidar_l2.yaml @@ -0,0 +1,61 @@ +/**: + ros__parameters: + # ================== Global Settings ================== + feature_extract_enable: false + max_iteration: 3 + filter_size_surf: 0.5 + filter_size_map: 0.5 + cube_side_length: 1000.0 + runtime_pos_log_enable: false + map_file_path: "./test.pcd" + + # ================== Sensor Topics ================== + common: + lid_topic: "/unilidar/cloud" # LiDAR点云话题 + imu_topic: "/unilidar/imu" # IMU话题 + time_sync_en: false # 关闭内部时间同步(若需要同步请设为true) + time_offset_lidar_to_imu: 0.0 # IMU到LiDAR时间偏移(与您配置的time_lag_imu_to_lidar取反) + + # ================== LiDAR预处理 ================== + preprocess: + lidar_type: 5 # 雷达类型(需确认类型编号对应关系) + scan_line: 18 # 扫描线数 + point_filter_num: 1 # 点云降采样率(原con_frame_num) + blind: 0.5 # 盲区过滤半径(米) + timestamp_unit: 0 # 时间戳单位:0=秒,1=毫秒,2=微秒,3=纳秒 + + # ================== SLAM核心参数 ================== + mapping: + # IMU参数 + imu_en: true # 启用IMU + imu_time_inte: 0.004 # IMU采样间隔(1/frequency) + acc_cov: 0.1 # 加速度计噪声协方差 + gyr_cov: 0.1 # 陀螺仪噪声协方差 + b_acc_cov: 0.0001 # 加速度计零偏噪声 + b_gyr_cov: 0.0001 # 陀螺仪零偏噪声 + + # 外参标定 + extrinsic_est_en: false # 关闭在线外参标定 + extrinsic_T: [0.007698, 0.014655, -0.00667] # IMU到LiDAR平移 + extrinsic_R: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0] # IMU到LiDAR旋转矩阵 + + # 环境参数 + fov_degree: 180.0 # 有效FOV角度 + det_range: 100.0 # 最大探测距离(米) + plane_thr: 0.1 # 平面拟合阈值 + + # 重力对齐 + gravity_align: true # 启用重力对齐 + gravity: [0.0, 0.0, -9.810] # 重力向量(与您配置一致) + + # ================== 输出设置 ================== + publish: + path_en: true # 发布轨迹路径 + scan_publish_en: true # 发布原始点云 + scan_bodyframe_pub_en: true # 发布IMU坐标系点云 + dense_publish_en: true # 发布稠密地图 + + # ================== 地图保存 ================== + pcd_save: + pcd_save_en: true # 启用PCD保存 + interval: -1 # 全帧保存(注意内存风险) diff --git a/FAST_LIO/config/velodyne.yaml b/FAST_LIO/config/velodyne.yaml new file mode 100644 index 0000000..24e6bf2 --- /dev/null +++ b/FAST_LIO/config/velodyne.yaml @@ -0,0 +1,48 @@ +/**: + ros__parameters: + feature_extract_enable: false + point_filter_num: 4 + max_iteration: 3 + filter_size_surf: 0.5 + filter_size_map: 0.5 + cube_side_length: 1000.0 + runtime_pos_log_enable: false + map_file_path: "./test.pcd" + + common: + lid_topic: "/velodyne_points" + imu_topic: "/imu/data" + time_sync_en: false # ONLY turn on when external time synchronization is really not possible + time_offset_lidar_to_imu: 0.0 # Time offset between lidar and IMU calibrated by other algorithms, e.g. LI-Init (can be found in README). + # This param will take effect no matter what time_sync_en is. So if the time offset is not known exactly, please set as 0.0 + + preprocess: + lidar_type: 2 # 1 for Livox serials LiDAR, 2 for Velodyne LiDAR, 3 for ouster LiDAR, + scan_line: 32 + scan_rate: 10 # only need to be set for velodyne, unit: Hz, + timestamp_unit: 2 # the unit of time/t field in the PointCloud2 rostopic: 0-second, 1-milisecond, 2-microsecond, 3-nanosecond. + blind: 2.0 + + mapping: + acc_cov: 0.1 + gyr_cov: 0.1 + b_acc_cov: 0.0001 + b_gyr_cov: 0.0001 + fov_degree: 360.0 + det_range: 100.0 + extrinsic_est_en: false # true: enable the online estimation of IMU-LiDAR extrinsic, + extrinsic_T: [ 0., 0., 0.28] + extrinsic_R: [ 1., 0., 0., + 0., 1., 0., + 0., 0., 1.] + + publish: + path_en: false + scan_publish_en: true # false: close all the point cloud output + dense_publish_en: true # false: low down the points number in a global-frame point clouds scan. + scan_bodyframe_pub_en: true # true: output the point cloud scans in IMU-body-frame + + pcd_save: + pcd_save_en: true + interval: -1 # how many LiDAR frames saved in each pcd file; + # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames. diff --git a/FAST_LIO/include/Exp_mat.h b/FAST_LIO/include/Exp_mat.h new file mode 100644 index 0000000..7ab2897 --- /dev/null +++ b/FAST_LIO/include/Exp_mat.h @@ -0,0 +1,103 @@ +#ifndef EXP_MAT_H +#define EXP_MAT_H + +#include +#include +#include +// #include + +#define SKEW_SYM_MATRX(v) 0.0,-v[2],v[1],v[2],0.0,-v[0],-v[1],v[0],0.0 + +template +Eigen::Matrix Exp(const Eigen::Matrix &&ang) +{ + T ang_norm = ang.norm(); + Eigen::Matrix Eye3 = Eigen::Matrix::Identity(); + if (ang_norm > 0.0000001) + { + Eigen::Matrix r_axis = ang / ang_norm; + Eigen::Matrix K; + K << SKEW_SYM_MATRX(r_axis); + /// Roderigous Tranformation + return Eye3 + std::sin(ang_norm) * K + (1.0 - std::cos(ang_norm)) * K * K; + } + else + { + return Eye3; + } +} + +template +Eigen::Matrix Exp(const Eigen::Matrix &ang_vel, const Ts &dt) +{ + T ang_vel_norm = ang_vel.norm(); + Eigen::Matrix Eye3 = Eigen::Matrix::Identity(); + + if (ang_vel_norm > 0.0000001) + { + Eigen::Matrix r_axis = ang_vel / ang_vel_norm; + Eigen::Matrix K; + + K << SKEW_SYM_MATRX(r_axis); + + T r_ang = ang_vel_norm * dt; + + /// Roderigous Tranformation + return Eye3 + std::sin(r_ang) * K + (1.0 - std::cos(r_ang)) * K * K; + } + else + { + return Eye3; + } +} + +template +Eigen::Matrix Exp(const T &v1, const T &v2, const T &v3) +{ + T &&norm = sqrt(v1 * v1 + v2 * v2 + v3 * v3); + Eigen::Matrix Eye3 = Eigen::Matrix::Identity(); + if (norm > 0.00001) + { + T r_ang[3] = {v1 / norm, v2 / norm, v3 / norm}; + Eigen::Matrix K; + K << SKEW_SYM_MATRX(r_ang); + + /// Roderigous Tranformation + return Eye3 + std::sin(norm) * K + (1.0 - std::cos(norm)) * K * K; + } + else + { + return Eye3; + } +} + +/* Logrithm of a Rotation Matrix */ +template +Eigen::Matrix Log(const Eigen::Matrix &R) +{ + T &&theta = std::acos(0.5 * (R.trace() - 1)); + Eigen::Matrix K(R(2,1) - R(1,2), R(0,2) - R(2,0), R(1,0) - R(0,1)); + return (std::abs(theta) < 0.001) ? (0.5 * K) : (0.5 * theta / std::sin(theta) * K); +} + +// template +// cv::Mat Exp(const T &v1, const T &v2, const T &v3) +// { + +// T norm = sqrt(v1 * v1 + v2 * v2 + v3 * v3); +// cv::Mat Eye3 = cv::Mat::eye(3, 3, CV_32F); +// if (norm > 0.0000001) +// { +// T r_ang[3] = {v1 / norm, v2 / norm, v3 / norm}; +// cv::Mat K = (cv::Mat_(3,3) << SKEW_SYM_MATRX(r_ang)); + +// /// Roderigous Tranformation +// return Eye3 + std::sin(norm) * K + (1.0 - std::cos(norm)) * K * K; +// } +// else +// { +// return Eye3; +// } +// } + +#endif diff --git a/FAST_LIO/include/IKFoM_toolkit/esekfom/esekfom.hpp b/FAST_LIO/include/IKFoM_toolkit/esekfom/esekfom.hpp new file mode 100755 index 0000000..7547584 --- /dev/null +++ b/FAST_LIO/include/IKFoM_toolkit/esekfom/esekfom.hpp @@ -0,0 +1,2008 @@ +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Author: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ESEKFOM_EKF_HPP +#define ESEKFOM_EKF_HPP + + +#include +#include + +#include +#include +#include +#include +#include + +#include "../mtk/types/vect.hpp" +#include "../mtk/types/SOn.hpp" +#include "../mtk/types/S2.hpp" +#include "../mtk/startIdx.hpp" +#include "../mtk/build_manifold.hpp" +#include "util.hpp" + +//#define USE_sparse + + +namespace esekfom { + +using namespace Eigen; + +//used for iterated error state EKF update +//for the aim to calculate measurement (z), estimate measurement (h), partial differention matrices (h_x, h_v) and the noise covariance (R) at the same time, by only one function. +//applied for measurement as a manifold. +template +struct share_datastruct +{ + bool valid; + bool converge; + M z; + Eigen::Matrix h_v; + Eigen::Matrix h_x; + Eigen::Matrix R; +}; + +//used for iterated error state EKF update +//for the aim to calculate measurement (z), estimate measurement (h), partial differention matrices (h_x, h_v) and the noise covariance (R) at the same time, by only one function. +//applied for measurement as an Eigen matrix whose dimension is changing +template +struct dyn_share_datastruct +{ + bool valid; + bool converge; + Eigen::Matrix z; + Eigen::Matrix h; + Eigen::Matrix h_v; + Eigen::Matrix h_x; + Eigen::Matrix R; +}; + +//used for iterated error state EKF update +//for the aim to calculate measurement (z), estimate measurement (h), partial differention matrices (h_x, h_v) and the noise covariance (R) at the same time, by only one function. +//applied for measurement as a dynamic manifold whose dimension or type is changing +template +struct dyn_runtime_share_datastruct +{ + bool valid; + bool converge; + //Z z; + Eigen::Matrix h_v; + Eigen::Matrix h_x; + Eigen::Matrix R; +}; + +template +class esekf{ + + typedef esekf self; + enum{ + n = state::DOF, m = state::DIM, l = measurement::DOF + }; + +public: + + typedef typename state::scalar scalar_type; + typedef Matrix cov; + typedef Matrix cov_; + typedef SparseMatrix spMt; + typedef Matrix vectorized_state; + typedef Matrix flatted_state; + typedef flatted_state processModel(state &, const input &); + typedef Eigen::Matrix processMatrix1(state &, const input &); + typedef Eigen::Matrix processMatrix2(state &, const input &); + typedef Eigen::Matrix processnoisecovariance; + typedef measurement measurementModel(state &, bool &); + typedef measurement measurementModel_share(state &, share_datastruct &); + typedef Eigen::Matrix measurementModel_dyn(state &, bool &); + //typedef Eigen::Matrix measurementModel_dyn_share(state &, dyn_share_datastruct &); + typedef void measurementModel_dyn_share(state &, dyn_share_datastruct &); + typedef Eigen::Matrix measurementMatrix1(state &, bool&); + typedef Eigen::Matrix measurementMatrix1_dyn(state &, bool&); + typedef Eigen::Matrix measurementMatrix2(state &, bool&); + typedef Eigen::Matrix measurementMatrix2_dyn(state &, bool&); + typedef Eigen::Matrix measurementnoisecovariance; + typedef Eigen::Matrix measurementnoisecovariance_dyn; + + esekf(const state &x = state(), + const cov &P = cov::Identity()): x_(x), P_(P){ + #ifdef USE_sparse + SparseMatrix ref(n, n); + ref.setIdentity(); + l_ = ref; + f_x_2 = ref; + f_x_1 = ref; + #endif + }; + + //receive system-specific models and their differentions. + //for measurement as a manifold. + void init(processModel f_in, processMatrix1 f_x_in, processMatrix2 f_w_in, measurementModel h_in, measurementMatrix1 h_x_in, measurementMatrix2 h_v_in, int maximum_iteration, scalar_type limit_vector[n]) + { + f = f_in; + f_x = f_x_in; + f_w = f_w_in; + h = h_in; + h_x = h_x_in; + h_v = h_v_in; + + maximum_iter = maximum_iteration; + for(int i=0; i f_w_ = f_w(x_, i_in); + Matrix f_w_final; + state x_before = x_; + x_.oplus(f_, dt); + + F_x1 = cov::Identity(); + for (std::vector, int> >::iterator it = x_.vect_state.begin(); it != x_.vect_state.end(); it++) { + int idx = (*it).first.first; + int dim = (*it).first.second; + int dof = (*it).second; + for(int i = 0; i < n; i++){ + for(int j=0; j res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for (std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = -1 * f_(dim + i) * dt; + } + MTK::SO3 res; + res.w() = MTK::exp(res.vec(), seg_SO3, scalar_type(1/2)); + #ifdef USE_sparse + res_temp_SO3 = res.toRotationMatrix(); + for(int i = 0; i < 3; i++){ + for(int j = 0; j < 3; j++){ + f_x_1.coeffRef(idx + i, idx + j) = res_temp_SO3(i, j); + } + } + #else + F_x1.template block<3, 3>(idx, idx) = res.toRotationMatrix(); + #endif + res_temp_SO3 = MTK::A_matrix(seg_SO3); + for(int i = 0; i < n; i++){ + f_x_final. template block<3, 1>(idx, i) = res_temp_SO3 * (f_x_. template block<3, 1>(dim, i)); + } + for(int i = 0; i < process_noise_dof; i++){ + f_w_final. template block<3, 1>(idx, i) = res_temp_SO3 * (f_w_. template block<3, 1>(dim, i)); + } + } + + + Matrix res_temp_S2; + Matrix res_temp_S2_; + MTK::vect<3, scalar_type> seg_S2; + for (std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 3; i++){ + seg_S2(i) = f_(dim + i) * dt; + } + MTK::vect<2, scalar_type> vec = MTK::vect<2, scalar_type>::Zero(); + MTK::SO3 res; + res.w() = MTK::exp(res.vec(), seg_S2, scalar_type(1/2)); + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_before.S2_Mx(Mx, vec, idx); + #ifdef USE_sparse + res_temp_S2_ = Nx * res.toRotationMatrix() * Mx; + for(int i = 0; i < 2; i++){ + for(int j = 0; j < 2; j++){ + f_x_1.coeffRef(idx + i, idx + j) = res_temp_S2_(i, j); + } + } + #else + F_x1.template block<2, 2>(idx, idx) = Nx * res.toRotationMatrix() * Mx; + #endif + + Eigen::Matrix x_before_hat; + x_before.S2_hat(x_before_hat, idx); + res_temp_S2 = -Nx * res.toRotationMatrix() * x_before_hat*MTK::A_matrix(seg_S2).transpose(); + + for(int i = 0; i < n; i++){ + f_x_final. template block<2, 1>(idx, i) = res_temp_S2 * (f_x_. template block<3, 1>(dim, i)); + + } + for(int i = 0; i < process_noise_dof; i++){ + f_w_final. template block<2, 1>(idx, i) = res_temp_S2 * (f_w_. template block<3, 1>(dim, i)); + } + } + + #ifdef USE_sparse + f_x_1.makeCompressed(); + spMt f_x2 = f_x_final.sparseView(); + spMt f_w1 = f_w_final.sparseView(); + spMt xp = f_x_1 + f_x2 * dt; + P_ = xp * P_ * xp.transpose() + (f_w1 * dt) * Q * (f_w1 * dt).transpose(); + #else + F_x1 += f_x_final * dt; + P_ = (F_x1) * P_ * (F_x1).transpose() + (dt * f_w_final) * Q * (dt * f_w_final).transpose(); + #endif + } + + //iterated error state EKF update for measurement as a manifold. + void update_iterated(measurement& z, measurementnoisecovariance &R) { + + if(!(is_same())){ + std::cerr << "the scalar type of measurment must be the same as the state" << std::endl; + std::exit(100); + } + int t = 0; + bool converg = true; + bool valid = true; + state x_propagated = x_; + cov P_propagated = P_; + + for(int i=-1; i h_x_ = h_x(x_, valid); + Matrix h_v_ = h_v(x_, valid); + #endif + if(! valid) + { + continue; + } + + P_ = P_propagated; + + Matrix res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for (std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = dx(idx+i); + } + + res_temp_SO3 = A_matrix(seg_SO3).transpose(); + dx_new.template block<3, 1>(idx, 0) = res_temp_SO3 * dx.template block<3, 1>(idx, 0); + for(int i = 0; i < n; i++){ + P_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + } + for(int i = 0; i < n; i++){ + P_. template block<1, 3>(i, idx) =(P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + } + } + + + Matrix res_temp_S2; + MTK::vect<2, scalar_type> seg_S2; + for (std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 2; i++){ + seg_S2(i) = dx(idx + i); + } + + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_propagated.S2_Mx(Mx, seg_S2, idx); + res_temp_S2 = Nx * Mx; + dx_new.template block<2, 1>(idx, 0) = res_temp_S2 * dx.template block<2, 1>(idx, 0); + for(int i = 0; i < n; i++){ + P_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + } + for(int i = 0; i < n; i++){ + P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + } + } + + Matrix K_; + if(n > l) + { + #ifdef USE_sparse + Matrix K_temp = h_x_ * P_ * h_x_.transpose(); + spMt R_temp = h_v_ * R_ * h_v_.transpose(); + K_temp += R_temp; + K_ = P_ * h_x_.transpose() * K_temp.inverse(); + #else + K_= P_ * h_x_.transpose() * (h_x_ * P_ * h_x_.transpose() + h_v_ * R * h_v_.transpose()).inverse(); + #endif + } + else + { + #ifdef USE_sparse + measurementnoisecovariance b = measurementnoisecovariance::Identity(); + Eigen::SparseQR, Eigen::COLAMDOrdering> solver; + solver.compute(R_); + measurementnoisecovariance R_in_temp = solver.solve(b); + spMt R_in = R_in_temp.sparseView(); + spMt K_temp = h_x_.transpose() * R_in * h_x_; + cov P_temp = P_.inverse(); + P_temp += K_temp; + K_ = P_temp.inverse() * h_x_.transpose() * R_in; + #else + measurementnoisecovariance R_in = (h_v_*R*h_v_.transpose()).inverse(); + K_ = (h_x_.transpose() * R_in * h_x_ + P_.inverse()).inverse() * h_x_.transpose() * R_in; + #endif + } + Matrix innovation; + z.boxminus(innovation, h(x_, valid)); + cov K_x = K_ * h_x_; + Matrix dx_ = K_ * innovation + (K_x - Matrix::Identity()) * dx_new; + state x_before = x_; + x_.boxplus(dx_); + + converg = true; + for(int i = 0; i < n ; i++) + { + if(std::fabs(dx_[i]) > limit[i]) + { + converg = false; + break; + } + } + + if(converg) t++; + + if(t > 1 || i == maximum_iter - 1) + { + L_ = P_; + + Matrix res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for(typename std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = dx_(i + idx); + } + res_temp_SO3 = A_matrix(seg_SO3).transpose(); + for(int i = 0; i < n; i++){ + L_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + } + if(n > l) + { + for(int i = 0; i < l; i++){ + K_. template block<3, 1>(idx, i) = res_temp_SO3 * (K_. template block<3, 1>(idx, i)); + } + } + else + { + for(int i = 0; i < n; i++){ + K_x. template block<3, 1>(idx, i) = res_temp_SO3 * (K_x. template block<3, 1>(idx, i)); + } + } + for(int i = 0; i < n; i++){ + L_. template block<1, 3>(i, idx) = (L_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + P_. template block<1, 3>(i, idx) = (P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + } + } + + Matrix res_temp_S2; + MTK::vect<2, scalar_type> seg_S2; + for(typename std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + + for(int i = 0; i < 2; i++){ + seg_S2(i) = dx_(i + idx); + } + + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_propagated.S2_Mx(Mx, seg_S2, idx); + res_temp_S2 = Nx * Mx; + + for(int i = 0; i < n; i++){ + L_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + } + if(n > l) + { + for(int i = 0; i < l; i++){ + K_. template block<2, 1>(idx, i) = res_temp_S2 * (K_. template block<2, 1>(idx, i)); + } + } + else + { + for(int i = 0; i < n; i++){ + K_x. template block<2, 1>(idx, i) = res_temp_S2 * (K_x. template block<2, 1>(idx, i)); + } + } + for(int i = 0; i < n; i++){ + L_. template block<1, 2>(i, idx) = (L_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + } + } + if(n > l) + { + P_ = L_ - K_ * h_x_ * P_; + } + else + { + P_ = L_ - K_x * P_; + } + return; + } + } + } + + //iterated error state EKF update for measurement as a manifold. + //calculate measurement (z), estimate measurement (h), partial differention matrices (h_x, h_v) and the noise covariance (R) at the same time, by only one function. + void update_iterated_share() { + + if(!(is_same())){ + std::cerr << "the scalar type of measurment must be the same as the state" << std::endl; + std::exit(100); + } + + int t = 0; + share_datastruct _share; + _share.valid = true; + _share.converge = true; + state x_propagated = x_; + cov P_propagated = P_; + + for(int i=-1; i h_x_ = _share.h_x; + Matrix h_v_ = _share.h_v; + #endif + if(! _share.valid) + { + continue; + } + + P_ = P_propagated; + + Matrix res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for (std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = dx(idx+i); + } + + res_temp_SO3 = A_matrix(seg_SO3).transpose(); + dx_new.template block<3, 1>(idx, 0) = res_temp_SO3 * dx.template block<3, 1>(idx, 0); + for(int i = 0; i < n; i++){ + P_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + } + for(int i = 0; i < n; i++){ + P_. template block<1, 3>(i, idx) =(P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + } + } + + + Matrix res_temp_S2; + MTK::vect<2, scalar_type> seg_S2; + for (std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 2; i++){ + seg_S2(i) = dx(idx + i); + } + + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_propagated.S2_Mx(Mx, seg_S2, idx); + res_temp_S2 = Nx * Mx; + dx_new.template block<2, 1>(idx, 0) = res_temp_S2 * dx.template block<2, 1>(idx, 0); + for(int i = 0; i < n; i++){ + P_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + } + for(int i = 0; i < n; i++){ + P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + } + } + + Matrix K_; + if(n > l) + { + #ifdef USE_sparse + Matrix K_temp = h_x_ * P_ * h_x_.transpose(); + spMt R_temp = h_v_ * R_ * h_v_.transpose(); + K_temp += R_temp; + K_ = P_ * h_x_.transpose() * K_temp.inverse(); + #else + K_= P_ * h_x_.transpose() * (h_x_ * P_ * h_x_.transpose() + h_v_ * R * h_v_.transpose()).inverse(); + #endif + } + else + { + #ifdef USE_sparse + measurementnoisecovariance b = measurementnoisecovariance::Identity(); + Eigen::SparseQR, Eigen::COLAMDOrdering> solver; + solver.compute(R_); + measurementnoisecovariance R_in_temp = solver.solve(b); + spMt R_in = R_in_temp.sparseView(); + spMt K_temp = h_x_.transpose() * R_in * h_x_; + cov P_temp = P_.inverse(); + P_temp += K_temp; + K_ = P_temp.inverse() * h_x_.transpose() * R_in; + #else + measurementnoisecovariance R_in = (h_v_*R*h_v_.transpose()).inverse(); + K_ = (h_x_.transpose() * R_in * h_x_ + P_.inverse()).inverse() * h_x_.transpose() * R_in; + #endif + } + Matrix innovation; + z.boxminus(innovation, h); + cov K_x = K_ * h_x_; + Matrix dx_ = K_ * innovation + (K_x - Matrix::Identity()) * dx_new; + state x_before = x_; + x_.boxplus(dx_); + + _share.converge = true; + for(int i = 0; i < n ; i++) + { + if(std::fabs(dx_[i]) > limit[i]) + { + _share.converge = false; + break; + } + } + + if(_share.converge) t++; + + if(t > 1 || i == maximum_iter - 1) + { + L_ = P_; + + Matrix res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for(typename std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = dx_(i + idx); + } + res_temp_SO3 = A_matrix(seg_SO3).transpose(); + for(int i = 0; i < n; i++){ + L_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + } + if(n > l) + { + for(int i = 0; i < l; i++){ + K_. template block<3, 1>(idx, i) = res_temp_SO3 * (K_. template block<3, 1>(idx, i)); + } + } + else + { + for(int i = 0; i < n; i++){ + K_x. template block<3, 1>(idx, i) = res_temp_SO3 * (K_x. template block<3, 1>(idx, i)); + } + } + for(int i = 0; i < n; i++){ + L_. template block<1, 3>(i, idx) = (L_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + P_. template block<1, 3>(i, idx) = (P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + } + } + + Matrix res_temp_S2; + MTK::vect<2, scalar_type> seg_S2; + for(typename std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + + for(int i = 0; i < 2; i++){ + seg_S2(i) = dx_(i + idx); + } + + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_propagated.S2_Mx(Mx, seg_S2, idx); + res_temp_S2 = Nx * Mx; + + for(int i = 0; i < n; i++){ + L_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + } + if(n > l) + { + for(int i = 0; i < l; i++){ + K_. template block<2, 1>(idx, i) = res_temp_S2 * (K_. template block<2, 1>(idx, i)); + } + } + else + { + for(int i = 0; i < n; i++){ + K_x. template block<2, 1>(idx, i) = res_temp_S2 * (K_x. template block<2, 1>(idx, i)); + } + } + for(int i = 0; i < n; i++){ + L_. template block<1, 2>(i, idx) = (L_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + } + } + if(n > l) + { + P_ = L_ - K_ * h_x_ * P_; + } + else + { + P_ = L_ - K_x * P_; + } + return; + } + } + } + + //iterated error state EKF update for measurement as an Eigen matrix whose dimension is changing. + void update_iterated_dyn(Eigen::Matrix z, measurementnoisecovariance_dyn R) { + + int t = 0; + bool valid = true; + bool converg = true; + state x_propagated = x_; + cov P_propagated = P_; + int dof_Measurement; + int dof_Measurement_noise = R.rows(); + for(int i=-1; i h_x_ = h_x_dyn(x_, valid); + Matrix h_v_ = h_v_dyn(x_, valid); + #endif + Matrix h_ = h_dyn(x_, valid); + dof_Measurement = h_.rows(); + vectorized_state dx, dx_new; + x_.boxminus(dx, x_propagated); + dx_new = dx; + if(! valid) + { + continue; + } + + P_ = P_propagated; + Matrix res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for (std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = dx(idx+i); + } + + res_temp_SO3 = MTK::A_matrix(seg_SO3).transpose(); + dx_new.template block<3, 1>(idx, 0) = res_temp_SO3 * dx_new.template block<3, 1>(idx, 0); + for(int i = 0; i < n; i++){ + P_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + } + for(int i = 0; i < n; i++){ + P_. template block<1, 3>(i, idx) =(P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + } + } + + Matrix res_temp_S2; + MTK::vect<2, scalar_type> seg_S2; + for (std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 2; i++){ + seg_S2(i) = dx(idx + i); + } + + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_propagated.S2_Mx(Mx, seg_S2, idx); + res_temp_S2 = Nx * Mx; + dx_new.template block<2, 1>(idx, 0) = res_temp_S2 * dx_new.template block<2, 1>(idx, 0); + for(int i = 0; i < n; i++){ + P_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + } + for(int i = 0; i < n; i++){ + P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + } + } + + Matrix K_; + if(n > dof_Measurement) + { + #ifdef USE_sparse + Matrix K_temp = h_x_ * P_ * h_x_.transpose(); + spMt R_temp = h_v_ * R_ * h_v_.transpose(); + K_temp += R_temp; + K_ = P_ * h_x_.transpose() * K_temp.inverse(); + #else + K_= P_ * h_x_.transpose() * (h_x_ * P_ * h_x_.transpose() + h_v_ * R * h_v_.transpose()).inverse(); + #endif + } + else + { + #ifdef USE_sparse + Eigen::Matrix b = Eigen::Matrix::Identity(dof_Measurement_noise, dof_Measurement_noise); + Eigen::SparseQR, Eigen::COLAMDOrdering> solver; + solver.compute(R_); + Eigen::Matrix R_in_temp = solver.solve(b); + spMt R_in = R_in_temp.sparseView(); + spMt K_temp = h_x_.transpose() * R_in * h_x_; + cov P_temp = P_.inverse(); + P_temp += K_temp; + K_ = P_temp.inverse() * h_x_.transpose() * R_in; + #else + Eigen::Matrix R_in = (h_v_*R*h_v_.transpose()).inverse(); + K_ = (h_x_.transpose() * R_in * h_x_ + P_.inverse()).inverse() * h_x_.transpose() * R_in; + #endif + } + cov K_x = K_ * h_x_; + Matrix dx_ = K_ * (z - h_) + (K_x - Matrix::Identity()) * dx_new; + state x_before = x_; + x_.boxplus(dx_); + converg = true; + for(int i = 0; i < n ; i++) + { + if(std::fabs(dx_[i]) > limit[i]) + { + converg = false; + break; + } + } + if(converg) t++; + if(t > 1 || i == maximum_iter - 1) + { + L_ = P_; + std::cout << "iteration time:" << t << "," << i << std::endl; + + Matrix res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for(typename std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = dx_(i + idx); + } + res_temp_SO3 = MTK::A_matrix(seg_SO3).transpose(); + for(int i = 0; i < n; i++){ + L_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + } + if(n > dof_Measurement) + { + for(int i = 0; i < dof_Measurement; i++){ + K_. template block<3, 1>(idx, i) = res_temp_SO3 * (K_. template block<3, 1>(idx, i)); + } + } + else + { + for(int i = 0; i < n; i++){ + K_x. template block<3, 1>(idx, i) = res_temp_SO3 * (K_x. template block<3, 1>(idx, i)); + } + } + for(int i = 0; i < n; i++){ + L_. template block<1, 3>(i, idx) = (L_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + P_. template block<1, 3>(i, idx) = (P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + } + } + + Matrix res_temp_S2; + MTK::vect<2, scalar_type> seg_S2; + for(typename std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + + for(int i = 0; i < 2; i++){ + seg_S2(i) = dx_(i + idx); + } + + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_propagated.S2_Mx(Mx, seg_S2, idx); + res_temp_S2 = Nx * Mx; + + for(int i = 0; i < n; i++){ + L_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + } + if(n > dof_Measurement) + { + for(int i = 0; i < dof_Measurement; i++){ + K_. template block<2, 1>(idx, i) = res_temp_S2 * (K_. template block<2, 1>(idx, i)); + } + } + else + { + for(int i = 0; i < n; i++){ + K_x. template block<2, 1>(idx, i) = res_temp_S2 * (K_x. template block<2, 1>(idx, i)); + } + } + for(int i = 0; i < n; i++){ + L_. template block<1, 2>(i, idx) = (L_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + } + } + if(n > dof_Measurement) + { + P_ = L_ - K_*h_x_*P_; + } + else + { + P_ = L_ - K_x * P_; + } + return; + } + } + } + //iterated error state EKF update for measurement as an Eigen matrix whose dimension is changing. + //calculate measurement (z), estimate measurement (h), partial differention matrices (h_x, h_v) and the noise covariance (R) at the same time, by only one function. + void update_iterated_dyn_share() { + + int t = 0; + dyn_share_datastruct dyn_share; + dyn_share.valid = true; + dyn_share.converge = true; + state x_propagated = x_; + cov P_propagated = P_; + int dof_Measurement; + int dof_Measurement_noise; + for(int i=-1; i h = h_dyn_share (x_, dyn_share); + Matrix z = dyn_share.z; + Matrix h = dyn_share.h; + #ifdef USE_sparse + spMt h_x = dyn_share.h_x.sparseView(); + spMt h_v = dyn_share.h_v.sparseView(); + spMt R_ = dyn_share.R.sparseView(); + #else + Matrix R = dyn_share.R; + Matrix h_x = dyn_share.h_x; + Matrix h_v = dyn_share.h_v; + #endif + dof_Measurement = h_x.rows(); + dof_Measurement_noise = dyn_share.R.rows(); + vectorized_state dx, dx_new; + x_.boxminus(dx, x_propagated); + dx_new = dx; + if(! (dyn_share.valid)) + { + continue; + } + + P_ = P_propagated; + Matrix res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for (std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = dx(idx+i); + } + + res_temp_SO3 = MTK::A_matrix(seg_SO3).transpose(); + dx_new.template block<3, 1>(idx, 0) = res_temp_SO3 * dx_new.template block<3, 1>(idx, 0); + for(int i = 0; i < n; i++){ + P_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + } + for(int i = 0; i < n; i++){ + P_. template block<1, 3>(i, idx) =(P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + } + } + + Matrix res_temp_S2; + MTK::vect<2, scalar_type> seg_S2; + for (std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 2; i++){ + seg_S2(i) = dx(idx + i); + } + + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_propagated.S2_Mx(Mx, seg_S2, idx); + res_temp_S2 = Nx * Mx; + dx_new.template block<2, 1>(idx, 0) = res_temp_S2 * dx_new.template block<2, 1>(idx, 0); + for(int i = 0; i < n; i++){ + P_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + } + for(int i = 0; i < n; i++){ + P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + } + } + + Matrix K_; + if(n > dof_Measurement) + { + #ifdef USE_sparse + Matrix K_temp = h_x * P_ * h_x.transpose(); + spMt R_temp = h_v * R_ * h_v.transpose(); + K_temp += R_temp; + K_ = P_ * h_x.transpose() * K_temp.inverse(); + #else + K_= P_ * h_x.transpose() * (h_x * P_ * h_x.transpose() + h_v * R * h_v.transpose()).inverse(); + #endif + } + else + { + #ifdef USE_sparse + Eigen::Matrix b = Eigen::Matrix::Identity(dof_Measurement_noise, dof_Measurement_noise); + Eigen::SparseQR, Eigen::COLAMDOrdering> solver; + solver.compute(R_); + Eigen::Matrix R_in_temp = solver.solve(b); + spMt R_in = R_in_temp.sparseView(); + spMt K_temp = h_x.transpose() * R_in * h_x; + cov P_temp = P_.inverse(); + P_temp += K_temp; + K_ = P_temp.inverse() * h_x.transpose() * R_in; + #else + Eigen::Matrix R_in = (h_v*R*h_v.transpose()).inverse(); + K_ = (h_x.transpose() * R_in * h_x + P_.inverse()).inverse() * h_x.transpose() * R_in; + #endif + } + + cov K_x = K_ * h_x; + Matrix dx_ = K_ * (z - h) + (K_x - Matrix::Identity()) * dx_new; + state x_before = x_; + x_.boxplus(dx_); + dyn_share.converge = true; + for(int i = 0; i < n ; i++) + { + if(std::fabs(dx_[i]) > limit[i]) + { + dyn_share.converge = false; + break; + } + } + if(dyn_share.converge) t++; + if(t > 1 || i == maximum_iter - 1) + { + L_ = P_; + std::cout << "iteration time:" << t << "," << i << std::endl; + + Matrix res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for(typename std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = dx_(i + idx); + } + res_temp_SO3 = MTK::A_matrix(seg_SO3).transpose(); + for(int i = 0; i < int(n); i++){ + L_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + } + if(n > dof_Measurement) + { + for(int i = 0; i < dof_Measurement; i++){ + K_. template block<3, 1>(idx, i) = res_temp_SO3 * (K_. template block<3, 1>(idx, i)); + } + } + else + { + for(int i = 0; i < n; i++){ + K_x. template block<3, 1>(idx, i) = res_temp_SO3 * (K_x. template block<3, 1>(idx, i)); + } + } + for(int i = 0; i < n; i++){ + L_. template block<1, 3>(i, idx) = (L_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + P_. template block<1, 3>(i, idx) = (P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + } + } + + Matrix res_temp_S2; + MTK::vect<2, scalar_type> seg_S2; + for(typename std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + + for(int i = 0; i < 2; i++){ + seg_S2(i) = dx_(i + idx); + } + + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_propagated.S2_Mx(Mx, seg_S2, idx); + res_temp_S2 = Nx * Mx; + + for(int i = 0; i < n; i++){ + L_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + } + if(n > dof_Measurement) + { + for(int i = 0; i < dof_Measurement; i++){ + K_. template block<2, 1>(idx, i) = res_temp_S2 * (K_. template block<2, 1>(idx, i)); + } + } + else + { + for(int i = 0; i < n; i++){ + K_x. template block<2, 1>(idx, i) = res_temp_S2 * (K_x. template block<2, 1>(idx, i)); + } + } + for(int i = 0; i < n; i++){ + L_. template block<1, 2>(i, idx) = (L_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + } + } + if(n > dof_Measurement) + { + P_ = L_ - K_*h_x*P_; + } + else + { + P_ = L_ - K_x * P_; + } + return; + } + } + } + + //iterated error state EKF update for measurement as a dynamic manifold, whose dimension or type is changing. + //the measurement and the measurement model are received in a dynamic manner. + template + void update_iterated_dyn_runtime(measurement_runtime z, measurementnoisecovariance_dyn R, measurementModel_runtime h_runtime) { + + int t = 0; + bool valid = true; + bool converg = true; + state x_propagated = x_; + cov P_propagated = P_; + int dof_Measurement; + int dof_Measurement_noise; + for(int i=-1; i h_x_ = h_x_dyn(x_, valid); + Matrix h_v_ = h_v_dyn(x_, valid); + #endif + measurement_runtime h_ = h_runtime(x_, valid); + dof_Measurement = measurement_runtime::DOF; + dof_Measurement_noise = R.rows(); + vectorized_state dx, dx_new; + x_.boxminus(dx, x_propagated); + dx_new = dx; + if(! valid) + { + continue; + } + + P_ = P_propagated; + Matrix res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for (std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = dx(idx+i); + } + + res_temp_SO3 = MTK::A_matrix(seg_SO3).transpose(); + dx_new.template block<3, 1>(idx, 0) = res_temp_SO3 * dx_new.template block<3, 1>(idx, 0); + for(int i = 0; i < n; i++){ + P_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + } + for(int i = 0; i < n; i++){ + P_. template block<1, 3>(i, idx) =(P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + } + } + + Matrix res_temp_S2; + MTK::vect<2, scalar_type> seg_S2; + for (std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 2; i++){ + seg_S2(i) = dx(idx + i); + } + + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_propagated.S2_Mx(Mx, seg_S2, idx); + res_temp_S2 = Nx * Mx; + dx_new.template block<2, 1>(idx, 0) = res_temp_S2 * dx_new.template block<2, 1>(idx, 0); + for(int i = 0; i < n; i++){ + P_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + } + for(int i = 0; i < n; i++){ + P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + } + } + + Matrix K_; + if(n > dof_Measurement) + { + #ifdef USE_sparse + Matrix K_temp = h_x_ * P_ * h_x_.transpose(); + spMt R_temp = h_v_ * R_ * h_v_.transpose(); + K_temp += R_temp; + K_ = P_ * h_x_.transpose() * K_temp.inverse(); + #else + K_= P_ * h_x_.transpose() * (h_x_ * P_ * h_x_.transpose() + h_v_ * R * h_v_.transpose()).inverse(); + #endif + } + else + { + #ifdef USE_sparse + Eigen::Matrix b = Eigen::Matrix::Identity(dof_Measurement_noise, dof_Measurement_noise); + Eigen::SparseQR, Eigen::COLAMDOrdering> solver; + solver.compute(R_); + Eigen::Matrix R_in_temp = solver.solve(b); + spMt R_in = R_in_temp.sparseView(); + spMt K_temp = h_x_.transpose() * R_in * h_x_; + cov P_temp = P_.inverse(); + P_temp += K_temp; + K_ = P_temp.inverse() * h_x_.transpose() * R_in; + #else + Eigen::Matrix R_in = (h_v_*R*h_v_.transpose()).inverse(); + K_ = (h_x_.transpose() * R_in * h_x_ + P_.inverse()).inverse() * h_x_.transpose() * R_in; + #endif + } + cov K_x = K_ * h_x_; + Eigen::Matrix innovation; + z.boxminus(innovation, h_); + Matrix dx_ = K_ * innovation + (K_x - Matrix::Identity()) * dx_new; + state x_before = x_; + x_.boxplus(dx_); + converg = true; + for(int i = 0; i < n ; i++) + { + if(std::fabs(dx_[i]) > limit[i]) + { + converg = false; + break; + } + } + if(converg) t++; + if(t > 1 || i == maximum_iter - 1) + { + L_ = P_; + std::cout << "iteration time:" << t << "," << i << std::endl; + + Matrix res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for(typename std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = dx_(i + idx); + } + res_temp_SO3 = MTK::A_matrix(seg_SO3).transpose(); + for(int i = 0; i < n; i++){ + L_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + } + if(n > dof_Measurement) + { + for(int i = 0; i < dof_Measurement; i++){ + K_. template block<3, 1>(idx, i) = res_temp_SO3 * (K_. template block<3, 1>(idx, i)); + } + } + else + { + for(int i = 0; i < n; i++){ + K_x. template block<3, 1>(idx, i) = res_temp_SO3 * (K_x. template block<3, 1>(idx, i)); + } + } + for(int i = 0; i < n; i++){ + L_. template block<1, 3>(i, idx) = (L_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + P_. template block<1, 3>(i, idx) = (P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + } + } + + Matrix res_temp_S2; + MTK::vect<2, scalar_type> seg_S2; + for(typename std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + + for(int i = 0; i < 2; i++){ + seg_S2(i) = dx_(i + idx); + } + + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_propagated.S2_Mx(Mx, seg_S2, idx); + res_temp_S2 = Nx * Mx; + + for(int i = 0; i < n; i++){ + L_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + } + if(n > dof_Measurement) + { + for(int i = 0; i < dof_Measurement; i++){ + K_. template block<2, 1>(idx, i) = res_temp_S2 * (K_. template block<2, 1>(idx, i)); + } + } + else + { + for(int i = 0; i < n; i++){ + K_x. template block<2, 1>(idx, i) = res_temp_S2 * (K_x. template block<2, 1>(idx, i)); + } + } + for(int i = 0; i < n; i++){ + L_. template block<1, 2>(i, idx) = (L_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + } + } + if(n > dof_Measurement) + { + P_ = L_ - K_*h_x_*P_; + } + else + { + P_ = L_ - K_x * P_; + } + return; + } + } + } + + //iterated error state EKF update for measurement as a dynamic manifold, whose dimension or type is changing. + //the measurement and the measurement model are received in a dynamic manner. + //calculate measurement (z), estimate measurement (h), partial differention matrices (h_x, h_v) and the noise covariance (R) at the same time, by only one function. + template + void update_iterated_dyn_runtime_share(measurement_runtime z, measurementModel_dyn_runtime_share h) { + + int t = 0; + dyn_runtime_share_datastruct dyn_share; + dyn_share.valid = true; + dyn_share.converge = true; + state x_propagated = x_; + cov P_propagated = P_; + int dof_Measurement; + int dof_Measurement_noise; + for(int i=-1; i R = dyn_share.R; + Matrix h_x = dyn_share.h_x; + Matrix h_v = dyn_share.h_v; + #endif + dof_Measurement = measurement_runtime::DOF; + dof_Measurement_noise = dyn_share.R.rows(); + vectorized_state dx, dx_new; + x_.boxminus(dx, x_propagated); + dx_new = dx; + if(! (dyn_share.valid)) + { + continue; + } + + P_ = P_propagated; + Matrix res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for (std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = dx(idx+i); + } + + res_temp_SO3 = MTK::A_matrix(seg_SO3).transpose(); + dx_new.template block<3, 1>(idx, 0) = res_temp_SO3 * dx_new.template block<3, 1>(idx, 0); + for(int i = 0; i < n; i++){ + P_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + } + for(int i = 0; i < n; i++){ + P_. template block<1, 3>(i, idx) =(P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + } + } + + Matrix res_temp_S2; + MTK::vect<2, scalar_type> seg_S2; + for (std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 2; i++){ + seg_S2(i) = dx(idx + i); + } + + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_propagated.S2_Mx(Mx, seg_S2, idx); + res_temp_S2 = Nx * Mx; + dx_new.template block<2, 1>(idx, 0) = res_temp_S2 * dx_new.template block<2, 1>(idx, 0); + for(int i = 0; i < n; i++){ + P_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + } + for(int i = 0; i < n; i++){ + P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + } + } + + Matrix K_; + if(n > dof_Measurement) + { + #ifdef USE_sparse + Matrix K_temp = h_x * P_ * h_x.transpose(); + spMt R_temp = h_v * R_ * h_v.transpose(); + K_temp += R_temp; + K_ = P_ * h_x.transpose() * K_temp.inverse(); + #else + K_= P_ * h_x.transpose() * (h_x * P_ * h_x.transpose() + h_v * R * h_v.transpose()).inverse(); + #endif + } + else + { + #ifdef USE_sparse + Eigen::Matrix b = Eigen::Matrix::Identity(dof_Measurement_noise, dof_Measurement_noise); + Eigen::SparseQR, Eigen::COLAMDOrdering> solver; + solver.compute(R_); + Eigen::Matrix R_in_temp = solver.solve(b); + spMt R_in =R_in_temp.sparseView(); + spMt K_temp = h_x.transpose() * R_in * h_x; + cov P_temp = P_.inverse(); + P_temp += K_temp; + K_ = P_temp.inverse() * h_x.transpose() * R_in; + #else + Eigen::Matrix R_in = (h_v*R*h_v.transpose()).inverse(); + K_ = (h_x.transpose() * R_in * h_x + P_.inverse()).inverse() * h_x.transpose() * R_in; + #endif + } + cov K_x = K_ * h_x; + Eigen::Matrix innovation; + z.boxminus(innovation, h_); + Matrix dx_ = K_ * innovation + (K_x - Matrix::Identity()) * dx_new; + state x_before = x_; + x_.boxplus(dx_); + dyn_share.converge = true; + for(int i = 0; i < n ; i++) + { + if(std::fabs(dx_[i]) > limit[i]) + { + dyn_share.converge = false; + break; + } + } + if(dyn_share.converge) t++; + if(t > 1 || i == maximum_iter - 1) + { + L_ = P_; + std::cout << "iteration time:" << t << "," << i << std::endl; + + Matrix res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for(typename std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = dx_(i + idx); + } + res_temp_SO3 = MTK::A_matrix(seg_SO3).transpose(); + for(int i = 0; i < int(n); i++){ + L_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + } + if(n > dof_Measurement) + { + for(int i = 0; i < dof_Measurement; i++){ + K_. template block<3, 1>(idx, i) = res_temp_SO3 * (K_. template block<3, 1>(idx, i)); + } + } + else + { + for(int i = 0; i < n; i++){ + K_x. template block<3, 1>(idx, i) = res_temp_SO3 * (K_x. template block<3, 1>(idx, i)); + } + } + for(int i = 0; i < n; i++){ + L_. template block<1, 3>(i, idx) = (L_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + P_. template block<1, 3>(i, idx) = (P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + } + } + + Matrix res_temp_S2; + MTK::vect<2, scalar_type> seg_S2; + for(typename std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + + for(int i = 0; i < 2; i++){ + seg_S2(i) = dx_(i + idx); + } + + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_propagated.S2_Mx(Mx, seg_S2, idx); + res_temp_S2 = Nx * Mx; + + for(int i = 0; i < n; i++){ + L_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + } + if(n > dof_Measurement) + { + for(int i = 0; i < dof_Measurement; i++){ + K_. template block<2, 1>(idx, i) = res_temp_S2 * (K_. template block<2, 1>(idx, i)); + } + } + else + { + for(int i = 0; i < n; i++){ + K_x. template block<2, 1>(idx, i) = res_temp_S2 * (K_x. template block<2, 1>(idx, i)); + } + } + for(int i = 0; i < n; i++){ + L_. template block<1, 2>(i, idx) = (L_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + } + } + if(n > dof_Measurement) + { + P_ = L_ - K_*h_x * P_; + } + else + { + P_ = L_ - K_x * P_; + } + return; + } + } + } + + //iterated error state EKF update modified for one specific system. + void update_iterated_dyn_share_modified(double R, double &solve_time) { + + dyn_share_datastruct dyn_share; + dyn_share.valid = true; + dyn_share.converge = true; + int t = 0; + state x_propagated = x_; + cov P_propagated = P_; + int dof_Measurement; + + Matrix K_h; + Matrix K_x; + + vectorized_state dx_new = vectorized_state::Zero(); + for(int i=-1; i h = h_dyn_share(x_, dyn_share); + #ifdef USE_sparse + spMt h_x_ = dyn_share.h_x.sparseView(); + #else + Eigen::Matrix h_x_ = dyn_share.h_x; + #endif + double solve_start = omp_get_wtime(); + dof_Measurement = h_x_.rows(); + vectorized_state dx; + x_.boxminus(dx, x_propagated); + dx_new = dx; + + + + P_ = P_propagated; + + Matrix res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for (std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = dx(idx+i); + } + + res_temp_SO3 = MTK::A_matrix(seg_SO3).transpose(); + dx_new.template block<3, 1>(idx, 0) = res_temp_SO3 * dx_new.template block<3, 1>(idx, 0); + for(int i = 0; i < n; i++){ + P_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + } + for(int i = 0; i < n; i++){ + P_. template block<1, 3>(i, idx) =(P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + } + } + + Matrix res_temp_S2; + MTK::vect<2, scalar_type> seg_S2; + for (std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 2; i++){ + seg_S2(i) = dx(idx + i); + } + + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_propagated.S2_Mx(Mx, seg_S2, idx); + res_temp_S2 = Nx * Mx; + dx_new.template block<2, 1>(idx, 0) = res_temp_S2 * dx_new.template block<2, 1>(idx, 0); + for(int i = 0; i < n; i++){ + P_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + } + for(int i = 0; i < n; i++){ + P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + } + } + //Matrix K_; + //Matrix K_h; + //Matrix K_x; + + /* + if(n > dof_Measurement) + { + K_= P_ * h_x_.transpose() * (h_x_ * P_ * h_x_.transpose()/R + Eigen::Matrix::Identity(dof_Measurement, dof_Measurement)).inverse()/R; + } + else + { + K_= (h_x_.transpose() * h_x_ + (P_/R).inverse()).inverse()*h_x_.transpose(); + } + */ + + if(n > dof_Measurement) + { + //#ifdef USE_sparse + //Matrix K_temp = h_x * P_ * h_x.transpose(); + //spMt R_temp = h_v * R_ * h_v.transpose(); + //K_temp += R_temp; + Eigen::Matrix h_x_cur = Eigen::Matrix::Zero(dof_Measurement, n); + h_x_cur.topLeftCorner(dof_Measurement, 12) = h_x_; + /* + h_x_cur.col(0) = h_x_.col(0); + h_x_cur.col(1) = h_x_.col(1); + h_x_cur.col(2) = h_x_.col(2); + h_x_cur.col(3) = h_x_.col(3); + h_x_cur.col(4) = h_x_.col(4); + h_x_cur.col(5) = h_x_.col(5); + h_x_cur.col(6) = h_x_.col(6); + h_x_cur.col(7) = h_x_.col(7); + h_x_cur.col(8) = h_x_.col(8); + h_x_cur.col(9) = h_x_.col(9); + h_x_cur.col(10) = h_x_.col(10); + h_x_cur.col(11) = h_x_.col(11); + */ + + Matrix K_ = P_ * h_x_cur.transpose() * (h_x_cur * P_ * h_x_cur.transpose()/R + Eigen::Matrix::Identity(dof_Measurement, dof_Measurement)).inverse()/R; + K_h = K_ * dyn_share.h; + K_x = K_ * h_x_cur; + //#else + // K_= P_ * h_x.transpose() * (h_x * P_ * h_x.transpose() + h_v * R * h_v.transpose()).inverse(); + //#endif + } + else + { + #ifdef USE_sparse + //Eigen::Matrix b = Eigen::Matrix::Identity(); + //Eigen::SparseQR, Eigen::COLAMDOrdering> solver; + spMt A = h_x_.transpose() * h_x_; + cov P_temp = (P_/R).inverse(); + P_temp. template block<12, 12>(0, 0) += A; + P_temp = P_temp.inverse(); + /* + Eigen::Matrix h_x_cur = Eigen::Matrix::Zero(dof_Measurement, n); + h_x_cur.col(0) = h_x_.col(0); + h_x_cur.col(1) = h_x_.col(1); + h_x_cur.col(2) = h_x_.col(2); + h_x_cur.col(3) = h_x_.col(3); + h_x_cur.col(4) = h_x_.col(4); + h_x_cur.col(5) = h_x_.col(5); + h_x_cur.col(6) = h_x_.col(6); + h_x_cur.col(7) = h_x_.col(7); + h_x_cur.col(8) = h_x_.col(8); + h_x_cur.col(9) = h_x_.col(9); + h_x_cur.col(10) = h_x_.col(10); + h_x_cur.col(11) = h_x_.col(11); + */ + K_ = P_temp. template block(0, 0) * h_x_.transpose(); + K_x = cov::Zero(); + K_x. template block(0, 0) = P_inv. template block(0, 0) * HTH; + /* + solver.compute(R_); + Eigen::Matrix R_in_temp = solver.solve(b); + spMt R_in =R_in_temp.sparseView(); + spMt K_temp = h_x.transpose() * R_in * h_x; + cov P_temp = P_.inverse(); + P_temp += K_temp; + K_ = P_temp.inverse() * h_x.transpose() * R_in; + */ + #else + cov P_temp = (P_/R).inverse(); + //Eigen::Matrix h_T = h_x_.transpose(); + Eigen::Matrix HTH = h_x_.transpose() * h_x_; + P_temp. template block<12, 12>(0, 0) += HTH; + /* + Eigen::Matrix h_x_cur = Eigen::Matrix::Zero(dof_Measurement, n); + //std::cout << "line 1767" << std::endl; + h_x_cur.col(0) = h_x_.col(0); + h_x_cur.col(1) = h_x_.col(1); + h_x_cur.col(2) = h_x_.col(2); + h_x_cur.col(3) = h_x_.col(3); + h_x_cur.col(4) = h_x_.col(4); + h_x_cur.col(5) = h_x_.col(5); + h_x_cur.col(6) = h_x_.col(6); + h_x_cur.col(7) = h_x_.col(7); + h_x_cur.col(8) = h_x_.col(8); + h_x_cur.col(9) = h_x_.col(9); + h_x_cur.col(10) = h_x_.col(10); + h_x_cur.col(11) = h_x_.col(11); + */ + cov P_inv = P_temp.inverse(); + //std::cout << "line 1781" << std::endl; + K_h = P_inv. template block(0, 0) * h_x_.transpose() * dyn_share.h; + //std::cout << "line 1780" << std::endl; + //cov HTH_cur = cov::Zero(); + //HTH_cur. template block<12, 12>(0, 0) = HTH; + K_x.setZero(); // = cov::Zero(); + K_x. template block(0, 0) = P_inv. template block(0, 0) * HTH; + //K_= (h_x_.transpose() * h_x_ + (P_/R).inverse()).inverse()*h_x_.transpose(); + #endif + } + + //K_x = K_ * h_x_; + Matrix dx_ = K_h + (K_x - Matrix::Identity()) * dx_new; + state x_before = x_; + x_.boxplus(dx_); + dyn_share.converge = true; + for(int i = 0; i < n ; i++) + { + if(std::fabs(dx_[i]) > limit[i]) + { + dyn_share.converge = false; + break; + } + } + if(dyn_share.converge) t++; + + if(!t && i == maximum_iter - 2) + { + dyn_share.converge = true; + } + + if(t > 1 || i == maximum_iter - 1) + { + L_ = P_; + //std::cout << "iteration time" << t << "," << i << std::endl; + Matrix res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for(typename std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = dx_(i + idx); + } + res_temp_SO3 = MTK::A_matrix(seg_SO3).transpose(); + for(int i = 0; i < n; i++){ + L_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + } + // if(n > dof_Measurement) + // { + // for(int i = 0; i < dof_Measurement; i++){ + // K_.template block<3, 1>(idx, i) = res_temp_SO3 * (K_. template block<3, 1>(idx, i)); + // } + // } + // else + // { + for(int i = 0; i < 12; i++){ + K_x. template block<3, 1>(idx, i) = res_temp_SO3 * (K_x. template block<3, 1>(idx, i)); + } + //} + for(int i = 0; i < n; i++){ + L_. template block<1, 3>(i, idx) = (L_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + P_. template block<1, 3>(i, idx) = (P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + } + } + + Matrix res_temp_S2; + MTK::vect<2, scalar_type> seg_S2; + for(typename std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + int idx = (*it).first; + + for(int i = 0; i < 2; i++){ + seg_S2(i) = dx_(i + idx); + } + + Eigen::Matrix Nx; + Eigen::Matrix Mx; + x_.S2_Nx_yy(Nx, idx); + x_propagated.S2_Mx(Mx, seg_S2, idx); + res_temp_S2 = Nx * Mx; + for(int i = 0; i < n; i++){ + L_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + } + // if(n > dof_Measurement) + // { + // for(int i = 0; i < dof_Measurement; i++){ + // K_. template block<2, 1>(idx, i) = res_temp_S2 * (K_. template block<2, 1>(idx, i)); + // } + // } + // else + // { + for(int i = 0; i < 12; i++){ + K_x. template block<2, 1>(idx, i) = res_temp_S2 * (K_x. template block<2, 1>(idx, i)); + } + //} + for(int i = 0; i < n; i++){ + L_. template block<1, 2>(i, idx) = (L_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + } + } + + // if(n > dof_Measurement) + // { + // Eigen::Matrix h_x_cur = Eigen::Matrix::Zero(dof_Measurement, n); + // h_x_cur.topLeftCorner(dof_Measurement, 12) = h_x_; + // /* + // h_x_cur.col(0) = h_x_.col(0); + // h_x_cur.col(1) = h_x_.col(1); + // h_x_cur.col(2) = h_x_.col(2); + // h_x_cur.col(3) = h_x_.col(3); + // h_x_cur.col(4) = h_x_.col(4); + // h_x_cur.col(5) = h_x_.col(5); + // h_x_cur.col(6) = h_x_.col(6); + // h_x_cur.col(7) = h_x_.col(7); + // h_x_cur.col(8) = h_x_.col(8); + // h_x_cur.col(9) = h_x_.col(9); + // h_x_cur.col(10) = h_x_.col(10); + // h_x_cur.col(11) = h_x_.col(11); + // */ + // P_ = L_ - K_*h_x_cur * P_; + // } + // else + //{ + P_ = L_ - K_x.template block(0, 0) * P_.template block<12, n>(0, 0); + //} + solve_time += omp_get_wtime() - solve_start; + return; + } + solve_time += omp_get_wtime() - solve_start; + } + } + + void change_x(state &input_state) + { + x_ = input_state; + if((!x_.vect_state.size())&&(!x_.SO3_state.size())&&(!x_.S2_state.size())) + { + x_.build_S2_state(); + x_.build_SO3_state(); + x_.build_vect_state(); + } + } + + void change_P(cov &input_cov) + { + P_ = input_cov; + } + + const state& get_x() const { + return x_; + } + const cov& get_P() const { + return P_; + } +private: + state x_; + measurement m_; + cov P_; + spMt l_; + spMt f_x_1; + spMt f_x_2; + cov F_x1 = cov::Identity(); + cov F_x2 = cov::Identity(); + cov L_ = cov::Identity(); + + processModel *f; + processMatrix1 *f_x; + processMatrix2 *f_w; + + measurementModel *h; + measurementMatrix1 *h_x; + measurementMatrix2 *h_v; + + measurementModel_dyn *h_dyn; + measurementMatrix1_dyn *h_x_dyn; + measurementMatrix2_dyn *h_v_dyn; + + measurementModel_share *h_share; + measurementModel_dyn_share *h_dyn_share; + + int maximum_iter = 0; + scalar_type limit[n]; + + template + T check_safe_update( T _temp_vec ) + { + T temp_vec = _temp_vec; + if ( std::isnan( temp_vec(0, 0) ) ) + { + temp_vec.setZero(); + return temp_vec; + } + double angular_dis = temp_vec.block( 0, 0, 3, 1 ).norm() * 57.3; + double pos_dis = temp_vec.block( 3, 0, 3, 1 ).norm(); + if ( angular_dis >= 20 || pos_dis > 1 ) + { + printf( "Angular dis = %.2f, pos dis = %.2f\r\n", angular_dis, pos_dis ); + temp_vec.setZero(); + } + return temp_vec; + } +public: + EIGEN_MAKE_ALIGNED_OPERATOR_NEW +}; + +} // namespace esekfom + +#endif // ESEKFOM_EKF_HPP diff --git a/FAST_LIO/include/IKFoM_toolkit/esekfom/util.hpp b/FAST_LIO/include/IKFoM_toolkit/esekfom/util.hpp new file mode 100755 index 0000000..ab39fc4 --- /dev/null +++ b/FAST_LIO/include/IKFoM_toolkit/esekfom/util.hpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Author: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MEKFOM_UTIL_HPP__ +#define __MEKFOM_UTIL_HPP__ + +#include +#include "../mtk/src/mtkmath.hpp" +namespace esekfom { + +template +class is_same { +public: + operator bool() { + return false; + } +}; +template +class is_same { +public: + operator bool() { + return true; + } +}; + +template +class is_double { +public: + operator bool() { + return false; + } +}; + +template<> +class is_double { +public: + operator bool() { + return true; + } +}; + +template +static T +id(const T &x) +{ + return x; +} + +} // namespace esekfom + +#endif // __MEKFOM_UTIL_HPP__ diff --git a/FAST_LIO/include/IKFoM_toolkit/mtk/build_manifold.hpp b/FAST_LIO/include/IKFoM_toolkit/mtk/build_manifold.hpp new file mode 100755 index 0000000..2cdb106 --- /dev/null +++ b/FAST_LIO/include/IKFoM_toolkit/mtk/build_manifold.hpp @@ -0,0 +1,229 @@ +// This is an advanced implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/build_manifold.hpp + * @brief Macro to automatically construct compound manifolds. + * + */ +#ifndef MTK_AUTOCONSTRUCT_HPP_ +#define MTK_AUTOCONSTRUCT_HPP_ + +#include + +#include +#include +#include + +#include "src/SubManifold.hpp" +#include "startIdx.hpp" + +#ifndef PARSED_BY_DOXYGEN +//////// internals ////// + +#define MTK_APPLY_MACRO_ON_TUPLE(r, macro, tuple) macro tuple + +#define MTK_TRANSFORM_COMMA(macro, entries) BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM_S(1, MTK_APPLY_MACRO_ON_TUPLE, macro, entries)) + +#define MTK_TRANSFORM(macro, entries) BOOST_PP_SEQ_FOR_EACH_R(1, MTK_APPLY_MACRO_ON_TUPLE, macro, entries) + +#define MTK_CONSTRUCTOR_ARG( type, id) const type& id = type() +#define MTK_CONSTRUCTOR_COPY( type, id) id(id) +#define MTK_BOXPLUS( type, id) id.boxplus(MTK::subvector(__vec, &self::id), __scale); +#define MTK_OPLUS( type, id) id.oplus(MTK::subvector_(__vec, &self::id), __scale); +#define MTK_BOXMINUS( type, id) id.boxminus(MTK::subvector(__res, &self::id), __oth.id); +#define MTK_S2_hat( type, id) if(id.IDX == idx){id.S2_hat(res);} +#define MTK_S2_Nx_yy( type, id) if(id.IDX == idx){id.S2_Nx_yy(res);} +#define MTK_S2_Mx( type, id) if(id.IDX == idx){id.S2_Mx(res, dx);} +#define MTK_OSTREAM( type, id) << __var.id << " " +#define MTK_ISTREAM( type, id) >> __var.id +#define MTK_S2_state( type, id) if(id.TYP == 1){S2_state.push_back(std::make_pair(id.IDX, id.DIM));} +#define MTK_SO3_state( type, id) if(id.TYP == 2){(SO3_state).push_back(std::make_pair(id.IDX, id.DIM));} +#define MTK_vect_state( type, id) if(id.TYP == 0){(vect_state).push_back(std::make_pair(std::make_pair(id.IDX, id.DIM), type::DOF));} + +#define MTK_SUBVARLIST(seq, S2state, SO3state) \ +BOOST_PP_FOR_1( \ + ( \ + BOOST_PP_SEQ_SIZE(seq), \ + BOOST_PP_SEQ_HEAD(seq), \ + BOOST_PP_SEQ_TAIL(seq) (~), \ + 0,\ + 0,\ + S2state,\ + SO3state ),\ + MTK_ENTRIES_TEST, MTK_ENTRIES_NEXT, MTK_ENTRIES_OUTPUT) + +#define MTK_PUT_TYPE(type, id, dof, dim, S2state, SO3state) \ + MTK::SubManifold id; +#define MTK_PUT_TYPE_AND_ENUM(type, id, dof, dim, S2state, SO3state) \ + MTK_PUT_TYPE(type, id, dof, dim, S2state, SO3state) \ + enum {DOF = type::DOF + dof}; \ + enum {DIM = type::DIM+dim}; \ + typedef type::scalar scalar; + +#define MTK_ENTRIES_OUTPUT(r, state) MTK_ENTRIES_OUTPUT_I state +#define MTK_ENTRIES_OUTPUT_I(s, head, seq, dof, dim, S2state, SO3state) \ + MTK_APPLY_MACRO_ON_TUPLE(~, \ + BOOST_PP_IF(BOOST_PP_DEC(s), MTK_PUT_TYPE, MTK_PUT_TYPE_AND_ENUM), \ + ( BOOST_PP_TUPLE_REM_2 head, dof, dim, S2state, SO3state)) + +#define MTK_ENTRIES_TEST(r, state) MTK_TUPLE_ELEM_4_0 state + +//! this used to be BOOST_PP_TUPLE_ELEM_4_0: +#define MTK_TUPLE_ELEM_4_0(a,b,c,d,e,f, g) a + +#define MTK_ENTRIES_NEXT(r, state) MTK_ENTRIES_NEXT_I state +#define MTK_ENTRIES_NEXT_I(len, head, seq, dof, dim, S2state, SO3state) ( \ + BOOST_PP_DEC(len), \ + BOOST_PP_SEQ_HEAD(seq), \ + BOOST_PP_SEQ_TAIL(seq), \ + dof + BOOST_PP_TUPLE_ELEM_2_0 head::DOF,\ + dim + BOOST_PP_TUPLE_ELEM_2_0 head::DIM,\ + S2state,\ + SO3state) + +#endif /* not PARSED_BY_DOXYGEN */ + + +/** + * Construct a manifold. + * @param name is the class-name of the manifold, + * @param entries is the list of sub manifolds + * + * Entries must be given in a list like this: + * @code + * typedef MTK::trafo > Pose; + * typedef MTK::vect Vec3; + * MTK_BUILD_MANIFOLD(imu_state, + * ((Pose, pose)) + * ((Vec3, vel)) + * ((Vec3, acc_bias)) + * ) + * @endcode + * Whitespace is optional, but the double parentheses are necessary. + * Construction is done entirely in preprocessor. + * After construction @a name is also a manifold. Its members can be + * accessed by names given in @a entries. + * + * @note Variable types are not allowed to have commas, thus types like + * @c vect need to be typedef'ed ahead. + */ +#define MTK_BUILD_MANIFOLD(name, entries) \ +struct name { \ + typedef name self; \ + std::vector > S2_state;\ + std::vector > SO3_state;\ + std::vector, int> > vect_state;\ + MTK_SUBVARLIST(entries, S2_state, SO3_state) \ + name ( \ + MTK_TRANSFORM_COMMA(MTK_CONSTRUCTOR_ARG, entries) \ + ) : \ + MTK_TRANSFORM_COMMA(MTK_CONSTRUCTOR_COPY, entries) {}\ + int getDOF() const { return DOF; } \ + void boxplus(const MTK::vectview & __vec, scalar __scale = 1 ) { \ + MTK_TRANSFORM(MTK_BOXPLUS, entries)\ + } \ + void oplus(const MTK::vectview & __vec, scalar __scale = 1 ) { \ + MTK_TRANSFORM(MTK_OPLUS, entries)\ + } \ + void boxminus(MTK::vectview __res, const name& __oth) const { \ + MTK_TRANSFORM(MTK_BOXMINUS, entries)\ + } \ + friend std::ostream& operator<<(std::ostream& __os, const name& __var){ \ + return __os MTK_TRANSFORM(MTK_OSTREAM, entries); \ + } \ + void build_S2_state(){\ + MTK_TRANSFORM(MTK_S2_state, entries)\ + }\ + void build_vect_state(){\ + MTK_TRANSFORM(MTK_vect_state, entries)\ + }\ + void build_SO3_state(){\ + MTK_TRANSFORM(MTK_SO3_state, entries)\ + }\ + void S2_hat(Eigen::Matrix &res, int idx) {\ + MTK_TRANSFORM(MTK_S2_hat, entries)\ + }\ + void S2_Nx_yy(Eigen::Matrix &res, int idx) {\ + MTK_TRANSFORM(MTK_S2_Nx_yy, entries)\ + }\ + void S2_Mx(Eigen::Matrix &res, Eigen::Matrix dx, int idx) {\ + MTK_TRANSFORM(MTK_S2_Mx, entries)\ + }\ + friend std::istream& operator>>(std::istream& __is, name& __var){ \ + return __is MTK_TRANSFORM(MTK_ISTREAM, entries); \ + } \ +}; + + + +#endif /*MTK_AUTOCONSTRUCT_HPP_*/ diff --git a/FAST_LIO/include/IKFoM_toolkit/mtk/src/SubManifold.hpp b/FAST_LIO/include/IKFoM_toolkit/mtk/src/SubManifold.hpp new file mode 100755 index 0000000..a1b13de --- /dev/null +++ b/FAST_LIO/include/IKFoM_toolkit/mtk/src/SubManifold.hpp @@ -0,0 +1,123 @@ +// This is an advanced implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/src/SubManifold.hpp + * @brief Defines the SubManifold class + */ + + +#ifndef SUBMANIFOLD_HPP_ +#define SUBMANIFOLD_HPP_ + + +#include "vectview.hpp" + + +namespace MTK { + +/** + * @ingroup SubManifolds + * Helper class for compound manifolds. + * This class wraps a manifold T and provides an enum IDX refering to the + * index of the SubManifold within the compound manifold. + * + * Memberpointers to a submanifold can be used for @ref SubManifolds "functions accessing submanifolds". + * + * @tparam T The manifold type of the sub-type + * @tparam idx The index of the sub-type within the compound manifold + */ +template +struct SubManifold : public T +{ + enum {IDX = idx, DIM = dim /*!< index of the sub-type within the compound manifold */ }; + //! manifold type + typedef T type; + + //! Construct from derived type + template + explicit + SubManifold(const X& t) : T(t) {}; + + //! Construct from internal type + //explicit + SubManifold(const T& t) : T(t) {}; + + //! inherit assignment operator + using T::operator=; + +}; + +} // namespace MTK + + +#endif /* SUBMANIFOLD_HPP_ */ diff --git a/FAST_LIO/include/IKFoM_toolkit/mtk/src/mtkmath.hpp b/FAST_LIO/include/IKFoM_toolkit/mtk/src/mtkmath.hpp new file mode 100755 index 0000000..e3420d1 --- /dev/null +++ b/FAST_LIO/include/IKFoM_toolkit/mtk/src/mtkmath.hpp @@ -0,0 +1,294 @@ +// This is an advanced implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/src/mtkmath.hpp + * @brief several math utility functions. + */ + +#ifndef MTKMATH_H_ +#define MTKMATH_H_ + +#include + +#include + +#include "../types/vect.hpp" + +#ifndef M_PI +#define M_PI 3.1415926535897932384626433832795 +#endif + + +namespace MTK { + +namespace internal { + +template +struct traits { + typedef typename Manifold::scalar scalar; + enum {DOF = Manifold::DOF}; + typedef vect vectorized_type; + typedef Eigen::Matrix matrix_type; +}; + +template<> +struct traits : traits > {}; +template<> +struct traits : traits > {}; + +} // namespace internal + +/** + * \defgroup MTKMath Mathematical helper functions + */ +//@{ + +//! constant @f$ \pi @f$ +const double pi = M_PI; + +template inline scalar tolerance(); + +template<> inline float tolerance() { return 1e-5f; } +template<> inline double tolerance() { return 1e-11; } + + +/** + * normalize @a x to @f$[-bound, bound] @f$. + * + * result for @f$ x = bound + 2\cdot n\cdot bound @f$ is arbitrary @f$\pm bound @f$. + */ +template +inline scalar normalize(scalar x, scalar bound){ //not used + if(std::fabs(x) <= bound) return x; + int r = (int)(x *(scalar(1.0)/ bound)); + return x - ((r + (r>>31) + 1) & ~1)*bound; +} + +/** + * Calculate cosine and sinc of sqrt(x2). + * @param x2 the squared angle must be non-negative + * @return a pair containing cos and sinc of sqrt(x2) + */ +template +std::pair cos_sinc_sqrt(const scalar &x2){ + using std::sqrt; + using std::cos; + using std::sin; + static scalar const taylor_0_bound = boost::math::tools::epsilon(); + static scalar const taylor_2_bound = sqrt(taylor_0_bound); + static scalar const taylor_n_bound = sqrt(taylor_2_bound); + + assert(x2>=0 && "argument must be non-negative"); + + // FIXME check if bigger bounds are possible + if(x2>=taylor_n_bound) { + // slow fall-back solution + scalar x = sqrt(x2); + return std::make_pair(cos(x), sin(x)/x); // x is greater than 0. + } + + // FIXME Replace by Horner-Scheme (4 instead of 5 FLOP/term, numerically more stable, theoretically cos and sinc can be calculated in parallel using SSE2 mulpd/addpd) + // TODO Find optimal coefficients using Remez algorithm + static scalar const inv[] = {1/3., 1/4., 1/5., 1/6., 1/7., 1/8., 1/9.}; + scalar cosi = 1., sinc=1; + scalar term = -1/2. * x2; + for(int i=0; i<3; ++i) { + cosi += term; + term *= inv[2*i]; + sinc += term; + term *= -inv[2*i+1] * x2; + } + + return std::make_pair(cosi, sinc); + +} + +template +Eigen::Matrix hat(const Base& v) { + Eigen::Matrix res; + res << 0, -v[2], v[1], + v[2], 0, -v[0], + -v[1], v[0], 0; + return res; +} + +template +Eigen::Matrix A_inv_trans(const Base& v){ + Eigen::Matrix res; + if(v.norm() > MTK::tolerance()) + { + res = Eigen::Matrix::Identity() + 0.5 * hat(v) + (1 - v.norm() * std::cos(v.norm() / 2) / 2 / std::sin(v.norm() / 2)) * hat(v) * hat(v) / v.squaredNorm(); + + } + else + { + res = Eigen::Matrix::Identity(); + } + + return res; +} + +template +Eigen::Matrix A_inv(const Base& v){ + Eigen::Matrix res; + if(v.norm() > MTK::tolerance()) + { + res = Eigen::Matrix::Identity() - 0.5 * hat(v) + (1 - v.norm() * std::cos(v.norm() / 2) / 2 / std::sin(v.norm() / 2)) * hat(v) * hat(v) / v.squaredNorm(); + + } + else + { + res = Eigen::Matrix::Identity(); + } + + return res; +} + +template +Eigen::Matrix S2_w_expw_( Eigen::Matrix v, scalar length) + { + Eigen::Matrix res; + scalar norm = std::sqrt(v[0]*v[0] + v[1]*v[1]); + if(norm < MTK::tolerance()){ + res = Eigen::Matrix::Zero(); + res(0, 1) = 1; + res(1, 2) = 1; + res /= length; + } + else{ + res << -v[0]*(1/norm-1/std::tan(norm))/std::sin(norm), norm/std::sin(norm), 0, + -v[1]*(1/norm-1/std::tan(norm))/std::sin(norm), 0, norm/std::sin(norm); + res /= length; + } + } + +template +Eigen::Matrix A_matrix(const Base & v){ + Eigen::Matrix res; + double squaredNorm = v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; + double norm = std::sqrt(squaredNorm); + if(norm < MTK::tolerance()){ + res = Eigen::Matrix::Identity(); + } + else{ + res = Eigen::Matrix::Identity() + (1 - std::cos(norm)) / squaredNorm * hat(v) + (1 - std::sin(norm) / norm) / squaredNorm * hat(v) * hat(v); + } + return res; +} + +template +scalar exp(vectview result, vectview vec, const scalar& scale = 1) { + scalar norm2 = vec.squaredNorm(); + std::pair cos_sinc = cos_sinc_sqrt(scale*scale * norm2); + scalar mult = cos_sinc.second * scale; + result = mult * vec; + return cos_sinc.first; +} + + +/** + * Inverse function to @c exp. + * + * @param result @c vectview to the result + * @param w scalar part of input + * @param vec vector part of input + * @param scale scale result by this value + * @param plus_minus_periodicity if true values @f$[w, vec]@f$ and @f$[-w, -vec]@f$ give the same result + */ +template +void log(vectview result, + const scalar &w, const vectview vec, + const scalar &scale, bool plus_minus_periodicity) +{ + // FIXME implement optimized case for vec.squaredNorm() <= tolerance() * (w*w) via Rational Remez approximation ~> only one division + scalar nv = vec.norm(); + if(nv < tolerance()) { + if(!plus_minus_periodicity && w < 0) { + // find the maximal entry: + int i; + nv = vec.cwiseAbs().maxCoeff(&i); + result = scale * std::atan2(nv, w) * vect::Unit(i); + return; + } + nv = tolerance(); + } + scalar s = scale / nv * (plus_minus_periodicity ? std::atan(nv / w) : std::atan2(nv, w) ); + + result = s * vec; +} + + +} // namespace MTK + + +#endif /* MTKMATH_H_ */ diff --git a/FAST_LIO/include/IKFoM_toolkit/mtk/src/vectview.hpp b/FAST_LIO/include/IKFoM_toolkit/mtk/src/vectview.hpp new file mode 100755 index 0000000..5025071 --- /dev/null +++ b/FAST_LIO/include/IKFoM_toolkit/mtk/src/vectview.hpp @@ -0,0 +1,168 @@ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/src/vectview.hpp + * @brief Wrapper class around a pointer used as interface for plain vectors. + */ + +#ifndef VECTVIEW_HPP_ +#define VECTVIEW_HPP_ + +#include + +namespace MTK { + +/** + * A view to a vector. + * Essentially, @c vectview is only a pointer to @c scalar but can be used directly in @c Eigen expressions. + * The dimension of the vector is given as template parameter and type-checked when used in expressions. + * Data has to be modifiable. + * + * @tparam scalar Scalar type of the vector. + * @tparam dim Dimension of the vector. + * + * @todo @c vectview can be replaced by simple inheritance of @c Eigen::Map, as soon as they get const-correct + */ +namespace internal { + template + struct CovBlock { + typedef typename Eigen::Block, T1::DOF, T2::DOF> Type; + typedef typename Eigen::Block, T1::DOF, T2::DOF> ConstType; + }; + + template + struct CovBlock_ { + typedef typename Eigen::Block, T1::DIM, T2::DIM> Type; + typedef typename Eigen::Block, T1::DIM, T2::DIM> ConstType; + }; + + template + struct CrossCovBlock { + typedef typename Eigen::Block, T1::DOF, T2::DOF> Type; + typedef typename Eigen::Block, T1::DOF, T2::DOF> ConstType; + }; + + template + struct CrossCovBlock_ { + typedef typename Eigen::Block, T1::DIM, T2::DIM> Type; + typedef typename Eigen::Block, T1::DIM, T2::DIM> ConstType; + }; + + template + struct VectviewBase { + typedef Eigen::Matrix matrix_type; + typedef typename matrix_type::MapType Type; + typedef typename matrix_type::ConstMapType ConstType; + }; + + template + struct UnalignedType { + typedef T type; + }; +} + +template +class vectview : public internal::VectviewBase::Type { + typedef internal::VectviewBase VectviewBase; +public: + //! plain matrix type + typedef typename VectviewBase::matrix_type matrix_type; + //! base type + typedef typename VectviewBase::Type base; + //! construct from pointer + explicit + vectview(scalar* data, int dim_=dim) : base(data, dim_) {} + //! construct from plain matrix + vectview(matrix_type& m) : base(m.data(), m.size()) {} + //! construct from another @c vectview + vectview(const vectview &v) : base(v) {} + //! construct from Eigen::Block: + template + vectview(Eigen::VectorBlock block) : base(&block.coeffRef(0), block.size()) {} + template + vectview(Eigen::Block block) : base(&block.coeffRef(0), block.size()) {} + + //! inherit assignment operator + using base::operator=; + //! data pointer + scalar* data() {return const_cast(base::data());} +}; + +/** + * @c const version of @c vectview. + * Compared to @c Eigen::Map this implementation is const correct, i.e., + * data will not be modifiable using this view. + * + * @tparam scalar Scalar type of the vector. + * @tparam dim Dimension of the vector. + * + * @sa vectview + */ +template +class vectview : public internal::VectviewBase::ConstType { + typedef internal::VectviewBase VectviewBase; +public: + //! plain matrix type + typedef typename VectviewBase::matrix_type matrix_type; + //! base type + typedef typename VectviewBase::ConstType base; + //! construct from const pointer + explicit + vectview(const scalar* data, int dim_ = dim) : base(data, dim_) {} + //! construct from column vector + template + vectview(const Eigen::Matrix& m) : base(m.data()) {} + //! construct from row vector + template + vectview(const Eigen::Matrix& m) : base(m.data()) {} + //! construct from another @c vectview + vectview(vectview x) : base(x.data()) {} + //! construct from base + vectview(const base &x) : base(x) {} + /** + * Construct from Block + * @todo adapt this, when Block gets const-correct + */ + template + vectview(Eigen::VectorBlock block) : base(&block.coeffRef(0)) {} + template + vectview(Eigen::Block block) : base(&block.coeffRef(0)) {} + +}; + + +} // namespace MTK + +#endif /* VECTVIEW_HPP_ */ diff --git a/FAST_LIO/include/IKFoM_toolkit/mtk/startIdx.hpp b/FAST_LIO/include/IKFoM_toolkit/mtk/startIdx.hpp new file mode 100755 index 0000000..4dc2958 --- /dev/null +++ b/FAST_LIO/include/IKFoM_toolkit/mtk/startIdx.hpp @@ -0,0 +1,328 @@ +// This is an advanced implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/startIdx.hpp + * @brief Tools to access sub-elements of compound manifolds. + */ +#ifndef GET_START_INDEX_H_ +#define GET_START_INDEX_H_ + +#include + +#include "src/SubManifold.hpp" +#include "src/vectview.hpp" + +namespace MTK { + + +/** + * \defgroup SubManifolds Accessing Submanifolds + * For compound manifolds constructed using MTK_BUILD_MANIFOLD, member pointers + * can be used to get sub-vectors or matrix-blocks of a corresponding big matrix. + * E.g. for a type @a pose consisting of @a orient and @a trans the member pointers + * @c &pose::orient and @c &pose::trans give all required information and are still + * valid if the base type gets extended or the actual types of @a orient and @a trans + * change (e.g. from 2D to 3D). + * + * @todo Maybe require manifolds to typedef MatrixType and VectorType, etc. + */ +//@{ + +/** + * Determine the index of a sub-variable within a compound variable. + */ +template +int getStartIdx( MTK::SubManifold Base::*) +{ + return idx; +} + +template +int getStartIdx_( MTK::SubManifold Base::*) +{ + return dim; +} + +/** + * Determine the degrees of freedom of a sub-variable within a compound variable. + */ +template +int getDof( MTK::SubManifold Base::*) +{ + return T::DOF; +} +template +int getDim( MTK::SubManifold Base::*) +{ + return T::DIM; +} + +/** + * set the diagonal elements of a covariance matrix corresponding to a sub-variable + */ +template +void setDiagonal(Eigen::Matrix &cov, + MTK::SubManifold Base::*, const typename Base::scalar &val) +{ + cov.diagonal().template segment(idx).setConstant(val); +} + +template +void setDiagonal_(Eigen::Matrix &cov, + MTK::SubManifold Base::*, const typename Base::scalar &val) +{ + cov.diagonal().template segment(dim).setConstant(val); +} + +/** + * Get the subblock of corresponding to two members, i.e. + * \code + * Eigen::Matrix m; + * MTK::subblock(m, &Pose::orient, &Pose::trans) = some_expression; + * MTK::subblock(m, &Pose::trans, &Pose::orient) = some_expression.trans(); + * \endcode + * lets you modify mixed covariance entries in a bigger covariance matrix. + */ +template +typename MTK::internal::CovBlock::Type +subblock(Eigen::Matrix &cov, + MTK::SubManifold Base::*, MTK::SubManifold Base::*) +{ + return cov.template block(idx1, idx2); +} + +template +typename MTK::internal::CovBlock_::Type +subblock_(Eigen::Matrix &cov, + MTK::SubManifold Base::*, MTK::SubManifold Base::*) +{ + return cov.template block(dim1, dim2); +} + +template +typename MTK::internal::CrossCovBlock::Type +subblock(Eigen::Matrix &cov, MTK::SubManifold Base1::*, MTK::SubManifold Base2::*) +{ + return cov.template block(idx1, idx2); +} + +template +typename MTK::internal::CrossCovBlock_::Type +subblock_(Eigen::Matrix &cov, MTK::SubManifold Base1::*, MTK::SubManifold Base2::*) +{ + return cov.template block(dim1, dim2); +} +/** + * Get the subblock of corresponding to a member, i.e. + * \code + * Eigen::Matrix m; + * MTK::subblock(m, &Pose::orient) = some_expression; + * \endcode + * lets you modify covariance entries in a bigger covariance matrix. + */ +template +typename MTK::internal::CovBlock_::Type +subblock_(Eigen::Matrix &cov, + MTK::SubManifold Base::*) +{ + return cov.template block(dim, dim); +} + +template +typename MTK::internal::CovBlock::Type +subblock(Eigen::Matrix &cov, + MTK::SubManifold Base::*) +{ + return cov.template block(idx, idx); +} + +template +class get_cov { +public: + typedef Eigen::Matrix type; + typedef const Eigen::Matrix const_type; +}; + +template +class get_cov_ { +public: + typedef Eigen::Matrix type; + typedef const Eigen::Matrix const_type; +}; + +template +class get_cross_cov { +public: + typedef Eigen::Matrix type; + typedef const type const_type; +}; + +template +class get_cross_cov_ { +public: + typedef Eigen::Matrix type; + typedef const type const_type; +}; + + +template +vectview +subvector_impl_(vectview vec, SubManifold Base::*) +{ + return vec.template segment(dim); +} + +template +vectview +subvector_impl(vectview vec, SubManifold Base::*) +{ + return vec.template segment(idx); +} + +/** + * Get the subvector corresponding to a sub-manifold from a bigger vector. + */ + template +vectview +subvector_(vectview vec, SubManifold Base::* ptr) +{ + return subvector_impl_(vec, ptr); +} + +template +vectview +subvector(vectview vec, SubManifold Base::* ptr) +{ + return subvector_impl(vec, ptr); +} + +/** + * @todo This should be covered already by subvector(vectview vec,SubManifold Base::*) + */ +template +vectview +subvector(Eigen::Matrix& vec, SubManifold Base::* ptr) +{ + return subvector_impl(vectview(vec), ptr); +} + +template +vectview +subvector_(Eigen::Matrix& vec, SubManifold Base::* ptr) +{ + return subvector_impl_(vectview(vec), ptr); +} + +template +vectview +subvector_(const Eigen::Matrix& vec, SubManifold Base::* ptr) +{ + return subvector_impl_(vectview(vec), ptr); +} + +template +vectview +subvector(const Eigen::Matrix& vec, SubManifold Base::* ptr) +{ + return subvector_impl(vectview(vec), ptr); +} + + +/** + * const version of subvector(vectview vec,SubManifold Base::*) + */ +template +vectview +subvector_impl(const vectview cvec, SubManifold Base::*) +{ + return cvec.template segment(idx); +} + +template +vectview +subvector_impl_(const vectview cvec, SubManifold Base::*) +{ + return cvec.template segment(dim); +} + +template +vectview +subvector(const vectview cvec, SubManifold Base::* ptr) +{ + return subvector_impl(cvec, ptr); +} + + +} // namespace MTK + +#endif // GET_START_INDEX_H_ diff --git a/FAST_LIO/include/IKFoM_toolkit/mtk/types/S2.hpp b/FAST_LIO/include/IKFoM_toolkit/mtk/types/S2.hpp new file mode 100755 index 0000000..789ebd9 --- /dev/null +++ b/FAST_LIO/include/IKFoM_toolkit/mtk/types/S2.hpp @@ -0,0 +1,316 @@ +// This is a NEW implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/types/S2.hpp + * @brief Unit vectors on the sphere, or directions in 3D. + */ +#ifndef S2_H_ +#define S2_H_ + + +#include "vect.hpp" + +#include "SOn.hpp" +#include "../src/mtkmath.hpp" + + + + +namespace MTK { + +/** + * Manifold representation of @f$ S^2 @f$. + * Used for unit vectors on the sphere or directions in 3D. + * + * @todo add conversions from/to polar angles? + */ +template +struct S2 { + + typedef _scalar scalar; + typedef vect<3, scalar> vect_type; + typedef SO3 SO3_type; + typedef typename vect_type::base vec3; + scalar length = scalar(den)/scalar(num); + enum {DOF=2, TYP = 1, DIM = 3}; + +//private: + /** + * Unit vector on the sphere, or vector pointing in a direction + */ + vect_type vec; + +public: + S2() { + if(S2_typ == 3) vec=length * vec3(0, 0, std::sqrt(1)); + if(S2_typ == 2) vec=length * vec3(0, std::sqrt(1), 0); + if(S2_typ == 1) vec=length * vec3(std::sqrt(1), 0, 0); + } + S2(const scalar &x, const scalar &y, const scalar &z) : vec(vec3(x, y, z)) { + vec.normalize(); + vec = vec * length; + } + + S2(const vect_type &_vec) : vec(_vec) { + vec.normalize(); + vec = vec * length; + } + + void oplus(MTK::vectview delta, scalar scale = 1) + { + SO3_type res; + res.w() = MTK::exp(res.vec(), delta, scalar(scale/2)); + vec = res.toRotationMatrix() * vec; + } + + void boxplus(MTK::vectview delta, scalar scale=1) { + Eigen::Matrix Bx; + S2_Bx(Bx); + vect_type Bu = Bx*delta;SO3_type res; + res.w() = MTK::exp(res.vec(), Bu, scalar(scale/2)); + vec = res.toRotationMatrix() * vec; + } + + void boxminus(MTK::vectview res, const S2& other) const { + scalar v_sin = (MTK::hat(vec)*other.vec).norm(); + scalar v_cos = vec.transpose() * other.vec; + scalar theta = std::atan2(v_sin, v_cos); + if(v_sin < MTK::tolerance()) + { + if(std::fabs(theta) > MTK::tolerance() ) + { + res[0] = 3.1415926; + res[1] = 0; + } + else{ + res[0] = 0; + res[1] = 0; + } + } + else + { + S2 other_copy = other; + Eigen::MatrixBx; + other_copy.S2_Bx(Bx); + res = theta/v_sin * Bx.transpose() * MTK::hat(other.vec)*vec; + } + } + + void S2_hat(Eigen::Matrix &res) + { + Eigen::Matrix skew_vec; + skew_vec << scalar(0), -vec[2], vec[1], + vec[2], scalar(0), -vec[0], + -vec[1], vec[0], scalar(0); + res = skew_vec; + } + + + void S2_Bx(Eigen::Matrix &res) + { + if(S2_typ == 3) + { + if(vec[2] + length > tolerance()) + { + + res << length - vec[0]*vec[0]/(length+vec[2]), -vec[0]*vec[1]/(length+vec[2]), + -vec[0]*vec[1]/(length+vec[2]), length-vec[1]*vec[1]/(length+vec[2]), + -vec[0], -vec[1]; + res /= length; + } + else + { + res = Eigen::Matrix::Zero(); + res(1, 1) = -1; + res(2, 0) = 1; + } + } + else if(S2_typ == 2) + { + if(vec[1] + length > tolerance()) + { + + res << length - vec[0]*vec[0]/(length+vec[1]), -vec[0]*vec[2]/(length+vec[1]), + -vec[0], -vec[2], + -vec[0]*vec[2]/(length+vec[1]), length-vec[2]*vec[2]/(length+vec[1]); + res /= length; + } + else + { + res = Eigen::Matrix::Zero(); + res(1, 1) = -1; + res(2, 0) = 1; + } + } + else + { + if(vec[0] + length > tolerance()) + { + + res << -vec[1], -vec[2], + length - vec[1]*vec[1]/(length+vec[0]), -vec[2]*vec[1]/(length+vec[0]), + -vec[2]*vec[1]/(length+vec[0]), length-vec[2]*vec[2]/(length+vec[0]); + res /= length; + } + else + { + res = Eigen::Matrix::Zero(); + res(1, 1) = -1; + res(2, 0) = 1; + } + } + } + + void S2_Nx(Eigen::Matrix &res, S2& subtrahend) + { + if((vec+subtrahend.vec).norm() > tolerance()) + { + Eigen::Matrix Bx; + S2_Bx(Bx); + if((vec-subtrahend.vec).norm() > tolerance()) + { + scalar v_sin = (MTK::hat(vec)*subtrahend.vec).norm(); + scalar v_cos = vec.transpose() * subtrahend.vec; + + res = Bx.transpose() * (std::atan2(v_sin, v_cos)/v_sin*MTK::hat(vec)+MTK::hat(vec)*subtrahend.vec*((-v_cos/v_sin/v_sin/length/length/length/length+std::atan2(v_sin, v_cos)/v_sin/v_sin/v_sin)*subtrahend.vec.transpose()*MTK::hat(vec)*MTK::hat(vec)-vec.transpose()/length/length/length/length)); + } + else + { + res = 1/length/length*Bx.transpose()*MTK::hat(vec); + } + } + else + { + std::cerr << "No N(x, y) for x=-y" << std::endl; + std::exit(100); + } + } + + void S2_Nx_yy(Eigen::Matrix &res) + { + Eigen::Matrix Bx; + S2_Bx(Bx); + res = 1/length/length*Bx.transpose()*MTK::hat(vec); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + Eigen::Matrix Bx; + S2_Bx(Bx); + if(delta.norm() < tolerance()) + { + res = -MTK::hat(vec)*Bx; + } + else{ + vect_type Bu = Bx*delta; + SO3_type exp_delta; + exp_delta.w() = MTK::exp(exp_delta.vec(), Bu, scalar(1/2)); + res = -exp_delta.toRotationMatrix()*MTK::hat(vec)*MTK::A_matrix(Bu).transpose()*Bx; + } + } + + operator const vect_type&() const{ + return vec; + } + + const vect_type& get_vect() const { + return vec; + } + + friend S2 operator*(const SO3& rot, const S2& dir) + { + S2 ret; + ret.vec = rot * dir.vec; + return ret; + } + + scalar operator[](int idx) const {return vec[idx]; } + + friend std::ostream& operator<<(std::ostream &os, const S2& vec){ + return os << vec.vec.transpose() << " "; + } + friend std::istream& operator>>(std::istream &is, S2& vec){ + for(int i=0; i<3; ++i) + is >> vec.vec[i]; + vec.vec.normalize(); + vec.vec = vec.vec * vec.length; + return is; + + } +}; + + +} // namespace MTK + + +#endif /*S2_H_*/ diff --git a/FAST_LIO/include/IKFoM_toolkit/mtk/types/SOn.hpp b/FAST_LIO/include/IKFoM_toolkit/mtk/types/SOn.hpp new file mode 100755 index 0000000..31005e6 --- /dev/null +++ b/FAST_LIO/include/IKFoM_toolkit/mtk/types/SOn.hpp @@ -0,0 +1,317 @@ +// This is an advanced implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/types/SOn.hpp + * @brief Standard Orthogonal Groups i.e.\ rotatation groups. + */ +#ifndef SON_H_ +#define SON_H_ + +#include + +#include "vect.hpp" +#include "../src/mtkmath.hpp" + + +namespace MTK { + + +/** + * Two-dimensional orientations represented as scalar. + * There is no guarantee that the representing scalar is within any interval, + * but the result of boxminus will always have magnitude @f$\le\pi @f$. + */ +template +struct SO2 : public Eigen::Rotation2D<_scalar> { + enum {DOF = 1, DIM = 2, TYP = 3}; + + typedef _scalar scalar; + typedef Eigen::Rotation2D base; + typedef vect vect_type; + + //! Construct from angle + SO2(const scalar& angle = 0) : base(angle) { } + + //! Construct from Eigen::Rotation2D + SO2(const base& src) : base(src) {} + + /** + * Construct from 2D vector. + * Resulting orientation will rotate the first unit vector to point to vec. + */ + SO2(const vect_type &vec) : base(atan2(vec[1], vec[0])) {}; + + + //! Calculate @c this->inverse() * @c r + SO2 operator%(const base &r) const { + return base::inverse() * r; + } + + //! Calculate @c this->inverse() * @c r + template + vect_type operator%(const Eigen::MatrixBase &vec) const { + return base::inverse() * vec; + } + + //! Calculate @c *this * @c r.inverse() + SO2 operator/(const SO2 &r) const { + return *this * r.inverse(); + } + + //! Gets the angle as scalar. + operator scalar() const { + return base::angle(); + } + void S2_hat(Eigen::Matrix &res) + { + res = Eigen::Matrix::Zero(); + } + //! @name Manifold requirements + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void oplus(MTK::vectview vec, scalar scale = 1) { + base::angle() += scale * vec[0]; + } + + void boxplus(MTK::vectview vec, scalar scale = 1) { + base::angle() += scale * vec[0]; + } + void boxminus(MTK::vectview res, const SO2& other) const { + res[0] = MTK::normalize(base::angle() - other.angle(), scalar(MTK::pi)); + } + + friend std::istream& operator>>(std::istream &is, SO2& ang){ + return is >> ang.angle(); + } + +}; + + +/** + * Three-dimensional orientations represented as Quaternion. + * It is assumed that the internal Quaternion always stays normalized, + * should this not be the case, call inherited member function @c normalize(). + */ +template +struct SO3 : public Eigen::Quaternion<_scalar, Options> { + enum {DOF = 3, DIM = 3, TYP = 2}; + typedef _scalar scalar; + typedef Eigen::Quaternion base; + typedef Eigen::Quaternion Quaternion; + typedef vect vect_type; + + //! Calculate @c this->inverse() * @c r + template EIGEN_STRONG_INLINE + Quaternion operator%(const Eigen::QuaternionBase &r) const { + return base::conjugate() * r; + } + + //! Calculate @c this->inverse() * @c r + template + vect_type operator%(const Eigen::MatrixBase &vec) const { + return base::conjugate() * vec; + } + + //! Calculate @c this * @c r.conjugate() + template EIGEN_STRONG_INLINE + Quaternion operator/(const Eigen::QuaternionBase &r) const { + return *this * r.conjugate(); + } + + /** + * Construct from real part and three imaginary parts. + * Quaternion is normalized after construction. + */ + SO3(const scalar& w, const scalar& x, const scalar& y, const scalar& z) : base(w, x, y, z) { + base::normalize(); + } + + /** + * Construct from Eigen::Quaternion. + * @note Non-normalized input may result result in spurious behavior. + */ + SO3(const base& src = base::Identity()) : base(src) {} + + /** + * Construct from rotation matrix. + * @note Invalid rotation matrices may lead to spurious behavior. + */ + template + SO3(const Eigen::MatrixBase& matrix) : base(matrix) {} + + /** + * Construct from arbitrary rotation type. + * @note Invalid rotation matrices may lead to spurious behavior. + */ + template + SO3(const Eigen::RotationBase& rotation) : base(rotation.derived()) {} + + //! @name Manifold requirements + + void boxplus(MTK::vectview vec, scalar scale=1) { + SO3 delta = exp(vec, scale); + *this = *this * delta; + } + void boxminus(MTK::vectview res, const SO3& other) const { + res = SO3::log(other.conjugate() * *this); + } + //} + + void oplus(MTK::vectview vec, scalar scale=1) { + SO3 delta = exp(vec, scale); + *this = *this * delta; + } + + void S2_hat(Eigen::Matrix &res) + { + res = Eigen::Matrix::Zero(); + } + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + friend std::ostream& operator<<(std::ostream &os, const SO3& q){ + return os << q.coeffs().transpose() << " "; + } + + friend std::istream& operator>>(std::istream &is, SO3& q){ + vect<4,scalar> coeffs; + is >> coeffs; + q.coeffs() = coeffs.normalized(); + return is; + } + + //! @name Helper functions + //{ + /** + * Calculate the exponential map. In matrix terms this would correspond + * to the Rodrigues formula. + */ + // FIXME vectview<> can't be constructed from every MatrixBase<>, use const Vector3x& as workaround +// static SO3 exp(MTK::vectview dvec, scalar scale = 1){ + static SO3 exp(const Eigen::Matrix& dvec, scalar scale = 1){ + SO3 res; + res.w() = MTK::exp(res.vec(), dvec, scalar(scale/2)); + return res; + } + /** + * Calculate the inverse of @c exp. + * Only guarantees that exp(log(x)) == x + */ + static typename base::Vector3 log(const SO3 &orient){ + typename base::Vector3 res; + MTK::log(res, orient.w(), orient.vec(), scalar(2), true); + return res; + } +}; + +namespace internal { +template +struct UnalignedType >{ + typedef SO2 type; +}; + +template +struct UnalignedType >{ + typedef SO3 type; +}; + +} // namespace internal + + +} // namespace MTK + +#endif /*SON_H_*/ + diff --git a/FAST_LIO/include/IKFoM_toolkit/mtk/types/vect.hpp b/FAST_LIO/include/IKFoM_toolkit/mtk/types/vect.hpp new file mode 100755 index 0000000..0e5b9ce --- /dev/null +++ b/FAST_LIO/include/IKFoM_toolkit/mtk/types/vect.hpp @@ -0,0 +1,461 @@ +// This is an advanced implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/types/vect.hpp + * @brief Basic vectors interpreted as manifolds. + * + * This file also implements a simple wrapper for matrices, for arbitrary scalars + * and for positive scalars. + */ +#ifndef VECT_H_ +#define VECT_H_ + +#include +#include +#include + +#include "../src/vectview.hpp" + +namespace MTK { + +static const Eigen::IOFormat IO_no_spaces(Eigen::StreamPrecision, Eigen::DontAlignCols, ",", ",", "", "", "[", "]"); + + +/** + * A simple vector class. + * Implementation is basically a wrapper around Eigen::Matrix with manifold + * requirements added. + */ +template +struct vect : public Eigen::Matrix<_scalar, D, 1, _Options> { + typedef Eigen::Matrix<_scalar, D, 1, _Options> base; + enum {DOF = D, DIM = D, TYP = 0}; + typedef _scalar scalar; + + //using base::operator=; + + /** Standard constructor. Sets all values to zero. */ + vect(const base &src = base::Zero()) : base(src) {} + + /** Constructor copying the value of the expression \a other */ + template + EIGEN_STRONG_INLINE vect(const Eigen::DenseBase& other) : base(other) {} + + /** Construct from memory. */ + vect(const scalar* src, int size = DOF) : base(base::Map(src, size)) { } + + void boxplus(MTK::vectview vec, scalar scale=1) { + *this += scale * vec; + } + void boxminus(MTK::vectview res, const vect& other) const { + res = *this - other; + } + + void oplus(MTK::vectview vec, scalar scale=1) { + *this += scale * vec; + } + + void S2_hat(Eigen::Matrix &res) + { + res = Eigen::Matrix::Zero(); + } + + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + friend std::ostream& operator<<(std::ostream &os, const vect& v){ + // Eigen sometimes messes with the streams flags, so output manually: + for(int i=0; i>(std::istream &is, vect& v){ + char term=0; + is >> std::ws; // skip whitespace + switch(is.peek()) { + case '(': term=')'; is.ignore(1); break; + case '[': term=']'; is.ignore(1); break; + case '{': term='}'; is.ignore(1); break; + default: break; + } + if(D==Eigen::Dynamic) { + assert(term !=0 && "Dynamic vectors must be embraced"); + std::vector temp; + while(is.good() && is.peek() != term) { + scalar x; + is >> x; + temp.push_back(x); + if(is.peek()==',') is.ignore(1); + } + v = vect::Map(temp.data(), temp.size()); + } else + for(int i=0; i> v[i]; + if(is.peek()==',') { // ignore commas between values + is.ignore(1); + } + } + if(term!=0) { + char x; + is >> x; + if(x!=term) { + is.setstate(is.badbit); +// assert(x==term && "start and end bracket do not match!"); + } + } + return is; + } + + template + vectview tail(){ + BOOST_STATIC_ASSERT(0< dim && dim <= DOF); + return base::template tail(); + } + template + vectview tail() const{ + BOOST_STATIC_ASSERT(0< dim && dim <= DOF); + return base::template tail(); + } + template + vectview head(){ + BOOST_STATIC_ASSERT(0< dim && dim <= DOF); + return base::template head(); + } + template + vectview head() const{ + BOOST_STATIC_ASSERT(0< dim && dim <= DOF); + return base::template head(); + } +}; + + +/** + * A simple matrix class. + * Implementation is basically a wrapper around Eigen::Matrix with manifold + * requirements added, i.e., matrix is viewed as a plain vector for that. + */ +template::Options> +struct matrix : public Eigen::Matrix<_scalar, M, N, _Options> { + typedef Eigen::Matrix<_scalar, M, N, _Options> base; + enum {DOF = M * N, TYP = 4, DIM=0}; + typedef _scalar scalar; + + using base::operator=; + + /** Standard constructor. Sets all values to zero. */ + matrix() { + base::setZero(); + } + + /** Constructor copying the value of the expression \a other */ + template + EIGEN_STRONG_INLINE matrix(const Eigen::MatrixBase& other) : base(other) {} + + /** Construct from memory. */ + matrix(const scalar* src) : base(src) { } + + void boxplus(MTK::vectview vec, scalar scale = 1) { + *this += scale * base::Map(vec.data()); + } + void boxminus(MTK::vectview res, const matrix& other) const { + base::Map(res.data()) = *this - other; + } + + void S2_hat(Eigen::Matrix &res) + { + res = Eigen::Matrix::Zero(); + } + + void oplus(MTK::vectview vec, scalar scale = 1) { + *this += scale * base::Map(vec.data()); + } + + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + friend std::ostream& operator<<(std::ostream &os, const matrix& mat){ + for(int i=0; i>(std::istream &is, matrix& mat){ + for(int i=0; i> mat.data()[i]; + } + return is; + } +};// @todo What if M / N = Eigen::Dynamic? + + + +/** + * A simple scalar type. + */ +template +struct Scalar { + enum {DOF = 1, TYP = 5, DIM=0}; + typedef _scalar scalar; + + scalar value; + + Scalar(const scalar& value = scalar(0)) : value(value) {} + operator const scalar&() const { return value; } + operator scalar&() { return value; } + Scalar& operator=(const scalar& val) { value = val; return *this; } + + void S2_hat(Eigen::Matrix &res) + { + res = Eigen::Matrix::Zero(); + } + + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void oplus(MTK::vectview vec, scalar scale=1) { + value += scale * vec[0]; + } + + void boxplus(MTK::vectview vec, scalar scale=1) { + value += scale * vec[0]; + } + void boxminus(MTK::vectview res, const Scalar& other) const { + res[0] = *this - other; + } +}; + +/** + * Positive scalars. + * Boxplus is implemented using multiplication by @f$x\boxplus\delta = x\cdot\exp(\delta) @f$. + */ +template +struct PositiveScalar { + enum {DOF = 1, TYP = 6, DIM=0}; + typedef _scalar scalar; + + scalar value; + + PositiveScalar(const scalar& value = scalar(1)) : value(value) { + assert(value > scalar(0)); + } + operator const scalar&() const { return value; } + PositiveScalar& operator=(const scalar& val) { assert(val>0); value = val; return *this; } + + void boxplus(MTK::vectview vec, scalar scale = 1) { + value *= std::exp(scale * vec[0]); + } + void boxminus(MTK::vectview res, const PositiveScalar& other) const { + res[0] = std::log(*this / other); + } + + void oplus(MTK::vectview vec, scalar scale = 1) { + value *= std::exp(scale * vec[0]); + } + + void S2_hat(Eigen::Matrix &res) + { + res = Eigen::Matrix::Zero(); + } + + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + + friend std::istream& operator>>(std::istream &is, PositiveScalar& s){ + is >> s.value; + assert(s.value > 0); + return is; + } +}; + +template +struct Complex : public std::complex<_scalar>{ + enum {DOF = 2, TYP = 7, DIM=0}; + typedef _scalar scalar; + + typedef std::complex Base; + + Complex(const Base& value) : Base(value) {} + Complex(const scalar& re = 0.0, const scalar& im = 0.0) : Base(re, im) {} + Complex(const MTK::vectview &in) : Base(in[0], in[1]) {} + template + Complex(const Eigen::DenseBase &in) : Base(in[0], in[1]) {} + + void boxplus(MTK::vectview vec, scalar scale = 1) { + Base::real() += scale * vec[0]; + Base::imag() += scale * vec[1]; + }; + void boxminus(MTK::vectview res, const Complex& other) const { + Complex diff = *this - other; + res << diff.real(), diff.imag(); + } + + void S2_hat(Eigen::Matrix &res) + { + res = Eigen::Matrix::Zero(); + } + + void oplus(MTK::vectview vec, scalar scale = 1) { + Base::real() += scale * vec[0]; + Base::imag() += scale * vec[1]; + }; + + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + scalar squaredNorm() const { + return std::pow(Base::real(),2) + std::pow(Base::imag(),2); + } + + const scalar& operator()(int i) const { + assert(0<=i && i<2 && "Index out of range"); + return i==0 ? Base::real() : Base::imag(); + } + scalar& operator()(int i){ + assert(0<=i && i<2 && "Index out of range"); + return i==0 ? Base::real() : Base::imag(); + } +}; + + +namespace internal { + +template +struct UnalignedType >{ + typedef vect type; +}; + +} // namespace internal + + +} // namespace MTK + + + + +#endif /*VECT_H_*/ diff --git a/FAST_LIO/include/IKFoM_toolkit/mtk/types/wrapped_cv_mat.hpp b/FAST_LIO/include/IKFoM_toolkit/mtk/types/wrapped_cv_mat.hpp new file mode 100755 index 0000000..b6643f1 --- /dev/null +++ b/FAST_LIO/include/IKFoM_toolkit/mtk/types/wrapped_cv_mat.hpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2010--2011, Universitaet Bremen and DFKI GmbH + * All rights reserved. + * + * Author: Rene Wagner + * Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the DFKI GmbH + * nor the names of its contributors may be used to endorse or + * promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WRAPPED_CV_MAT_HPP_ +#define WRAPPED_CV_MAT_HPP_ + +#include +#include + +namespace MTK { + +template +struct cv_f_type; + +template<> +struct cv_f_type +{ + enum {value = CV_64F}; +}; + +template<> +struct cv_f_type +{ + enum {value = CV_32F}; +}; + +/** + * cv_mat wraps a CvMat around an Eigen Matrix + */ +template +class cv_mat : public matrix +{ + typedef matrix base_type; + enum {type_ = cv_f_type::value}; + CvMat cv_mat_; + +public: + cv_mat() + { + cv_mat_ = cvMat(rows, cols, type_, base_type::data()); + } + + cv_mat(const cv_mat& oth) : base_type(oth) + { + cv_mat_ = cvMat(rows, cols, type_, base_type::data()); + } + + template + cv_mat(const Eigen::MatrixBase &value) : base_type(value) + { + cv_mat_ = cvMat(rows, cols, type_, base_type::data()); + } + + template + cv_mat& operator=(const Eigen::MatrixBase &value) + { + base_type::operator=(value); + return *this; + } + + cv_mat& operator=(const cv_mat& value) + { + base_type::operator=(value); + return *this; + } + + // FIXME: Maybe overloading operator& is not a good idea ... + CvMat* operator&() + { + return &cv_mat_; + } + const CvMat* operator&() const + { + return &cv_mat_; + } +}; + +} // namespace MTK + +#endif /* WRAPPED_CV_MAT_HPP_ */ diff --git a/FAST_LIO/include/common_lib.h b/FAST_LIO/include/common_lib.h new file mode 100644 index 0000000..69365e3 --- /dev/null +++ b/FAST_LIO/include/common_lib.h @@ -0,0 +1,270 @@ +#ifndef COMMON_LIB_H +#define COMMON_LIB_H + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace Eigen; + +#define USE_IKFOM + +#define PI_M (3.14159265358) +#define G_m_s2 (9.81) // Gravaty const in GuangDong/China +#define DIM_STATE (18) // Dimension of states (Let Dim(SO(3)) = 3) +#define DIM_PROC_N (12) // Dimension of process noise (Let Dim(SO(3)) = 3) +#define CUBE_LEN (6.0) +#define LIDAR_SP_LEN (2) +#define INIT_COV (1) +#define NUM_MATCH_POINTS (5) +#define MAX_MEAS_DIM (10000) + +#define VEC_FROM_ARRAY(v) v[0],v[1],v[2] +#define MAT_FROM_ARRAY(v) v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8] +#define CONSTRAIN(v,min,max) ((v>min)?((v (mat.data(), mat.data() + mat.rows() * mat.cols()) +#define DEBUG_FILE_DIR(name) (string(string(ROOT_DIR) + "Log/"+ name)) + +typedef fast_lio::msg::Pose6D Pose6D; +typedef pcl::PointXYZINormal PointType; +typedef pcl::PointCloud PointCloudXYZI; +typedef vector> PointVector; +typedef Vector3d V3D; +typedef Matrix3d M3D; +typedef Vector3f V3F; +typedef Matrix3f M3F; + +#define MD(a,b) Matrix +#define VD(a) Matrix +#define MF(a,b) Matrix +#define VF(a) Matrix + +M3D Eye3d(M3D::Identity()); +M3F Eye3f(M3F::Identity()); +V3D Zero3d(0, 0, 0); +V3F Zero3f(0, 0, 0); + +struct MeasureGroup // Lidar data and imu dates for the curent process +{ + MeasureGroup() + { + lidar_beg_time = 0.0; + this->lidar.reset(new PointCloudXYZI()); + }; + double lidar_beg_time; + double lidar_end_time; + PointCloudXYZI::Ptr lidar; + deque imu; +}; + +struct StatesGroup +{ + StatesGroup() { + this->rot_end = M3D::Identity(); + this->pos_end = Zero3d; + this->vel_end = Zero3d; + this->bias_g = Zero3d; + this->bias_a = Zero3d; + this->gravity = Zero3d; + this->cov = MD(DIM_STATE,DIM_STATE)::Identity() * INIT_COV; + this->cov.block<9,9>(9,9) = MD(9,9)::Identity() * 0.00001; + }; + + StatesGroup(const StatesGroup& b) { + this->rot_end = b.rot_end; + this->pos_end = b.pos_end; + this->vel_end = b.vel_end; + this->bias_g = b.bias_g; + this->bias_a = b.bias_a; + this->gravity = b.gravity; + this->cov = b.cov; + }; + + StatesGroup& operator=(const StatesGroup& b) + { + this->rot_end = b.rot_end; + this->pos_end = b.pos_end; + this->vel_end = b.vel_end; + this->bias_g = b.bias_g; + this->bias_a = b.bias_a; + this->gravity = b.gravity; + this->cov = b.cov; + return *this; + }; + + StatesGroup operator+(const Matrix &state_add) + { + StatesGroup a; + a.rot_end = this->rot_end * Exp(state_add(0,0), state_add(1,0), state_add(2,0)); + a.pos_end = this->pos_end + state_add.block<3,1>(3,0); + a.vel_end = this->vel_end + state_add.block<3,1>(6,0); + a.bias_g = this->bias_g + state_add.block<3,1>(9,0); + a.bias_a = this->bias_a + state_add.block<3,1>(12,0); + a.gravity = this->gravity + state_add.block<3,1>(15,0); + a.cov = this->cov; + return a; + }; + + StatesGroup& operator+=(const Matrix &state_add) + { + this->rot_end = this->rot_end * Exp(state_add(0,0), state_add(1,0), state_add(2,0)); + this->pos_end += state_add.block<3,1>(3,0); + this->vel_end += state_add.block<3,1>(6,0); + this->bias_g += state_add.block<3,1>(9,0); + this->bias_a += state_add.block<3,1>(12,0); + this->gravity += state_add.block<3,1>(15,0); + return *this; + }; + + Matrix operator-(const StatesGroup& b) + { + Matrix a; + M3D rotd(b.rot_end.transpose() * this->rot_end); + a.block<3,1>(0,0) = Log(rotd); + a.block<3,1>(3,0) = this->pos_end - b.pos_end; + a.block<3,1>(6,0) = this->vel_end - b.vel_end; + a.block<3,1>(9,0) = this->bias_g - b.bias_g; + a.block<3,1>(12,0) = this->bias_a - b.bias_a; + a.block<3,1>(15,0) = this->gravity - b.gravity; + return a; + }; + + void resetpose() + { + this->rot_end = M3D::Identity(); + this->pos_end = Zero3d; + this->vel_end = Zero3d; + } + + M3D rot_end; // the estimated attitude (rotation matrix) at the end lidar point + V3D pos_end; // the estimated position at the end lidar point (world frame) + V3D vel_end; // the estimated velocity at the end lidar point (world frame) + V3D bias_g; // gyroscope bias + V3D bias_a; // accelerator bias + V3D gravity; // the estimated gravity acceleration + Matrix cov; // states covariance +}; + +template +T rad2deg(T radians) +{ + return radians * 180.0 / PI_M; +} + +template +T deg2rad(T degrees) +{ + return degrees * PI_M / 180.0; +} + +template +auto set_pose6d(const double t, const Matrix &a, const Matrix &g, \ + const Matrix &v, const Matrix &p, const Matrix &R) +{ + Pose6D rot_kp; + rot_kp.offset_time = t; + for (int i = 0; i < 3; i++) + { + rot_kp.acc[i] = a(i); + rot_kp.gyr[i] = g(i); + rot_kp.vel[i] = v(i); + rot_kp.pos[i] = p(i); + for (int j = 0; j < 3; j++) rot_kp.rot[i*3+j] = R(i,j); + } + return move(rot_kp); +} + +/* comment +plane equation: Ax + By + Cz + D = 0 +convert to: A/D*x + B/D*y + C/D*z = -1 +solve: A0*x0 = b0 +where A0_i = [x_i, y_i, z_i], x0 = [A/D, B/D, C/D]^T, b0 = [-1, ..., -1]^T +normvec: normalized x0 +*/ +template +bool esti_normvector(Matrix &normvec, const PointVector &point, const T &threshold, const int &point_num) +{ + MatrixXf A(point_num, 3); + MatrixXf b(point_num, 1); + b.setOnes(); + b *= -1.0f; + + for (int j = 0; j < point_num; j++) + { + A(j,0) = point[j].x; + A(j,1) = point[j].y; + A(j,2) = point[j].z; + } + normvec = A.colPivHouseholderQr().solve(b); + + for (int j = 0; j < point_num; j++) + { + if (fabs(normvec(0) * point[j].x + normvec(1) * point[j].y + normvec(2) * point[j].z + 1.0f) > threshold) + { + return false; + } + } + + normvec.normalize(); + return true; +} + +float calc_dist(PointType p1, PointType p2){ + float d = (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z); + return d; +} + +template +bool esti_plane(Matrix &pca_result, const PointVector &point, const T &threshold) +{ + Matrix A; + Matrix b; + A.setZero(); + b.setOnes(); + b *= -1.0f; + + for (int j = 0; j < NUM_MATCH_POINTS; j++) + { + A(j,0) = point[j].x; + A(j,1) = point[j].y; + A(j,2) = point[j].z; + } + + Matrix normvec = A.colPivHouseholderQr().solve(b); + + T n = normvec.norm(); + pca_result(0) = normvec(0) / n; + pca_result(1) = normvec(1) / n; + pca_result(2) = normvec(2) / n; + pca_result(3) = 1.0 / n; + + for (int j = 0; j < NUM_MATCH_POINTS; j++) + { + if (fabs(pca_result(0) * point[j].x + pca_result(1) * point[j].y + pca_result(2) * point[j].z + pca_result(3)) > threshold) + { + return false; + } + } + return true; +} + +double get_time_sec(const builtin_interfaces::msg::Time &time) +{ + return rclcpp::Time(time).seconds(); +} + +rclcpp::Time get_ros_time(double timestamp) +{ + int32_t sec = std::floor(timestamp); + auto nanosec_d = (timestamp - std::floor(timestamp)) * 1e9; + uint32_t nanosec = nanosec_d; + return rclcpp::Time(sec, nanosec); +} + +#endif \ No newline at end of file diff --git a/FAST_LIO/include/ikd-Tree/README.md b/FAST_LIO/include/ikd-Tree/README.md new file mode 100644 index 0000000..e113a91 --- /dev/null +++ b/FAST_LIO/include/ikd-Tree/README.md @@ -0,0 +1,2 @@ +# ikd-Tree +ikd-Tree is an incremental k-d tree for robotic applications. diff --git a/FAST_LIO/include/ikd-Tree/ikd_Tree.cpp b/FAST_LIO/include/ikd-Tree/ikd_Tree.cpp new file mode 100644 index 0000000..e8c4e86 --- /dev/null +++ b/FAST_LIO/include/ikd-Tree/ikd_Tree.cpp @@ -0,0 +1,1728 @@ +#include "ikd_Tree.h" + +/* +Description: ikd-Tree: an incremental k-d tree for robotic applications +Author: Yixi Cai +email: yixicai@connect.hku.hk +*/ + +template +KD_TREE::KD_TREE(float delete_param, float balance_param, float box_length) +{ + delete_criterion_param = delete_param; + balance_criterion_param = balance_param; + downsample_size = box_length; + Rebuild_Logger.clear(); + termination_flag = false; + start_thread(); +} + +template +KD_TREE::~KD_TREE() +{ + stop_thread(); + Delete_Storage_Disabled = true; + delete_tree_nodes(&Root_Node); + PointVector().swap(PCL_Storage); + Rebuild_Logger.clear(); +} + + + +template +void KD_TREE::InitializeKDTree(float delete_param, float balance_param, float box_length) +{ + Set_delete_criterion_param(delete_param); + Set_balance_criterion_param(balance_param); + set_downsample_param(box_length); +} + +template +void KD_TREE::InitTreeNode(KD_TREE_NODE *root) +{ + root->point.x = 0.0f; + root->point.y = 0.0f; + root->point.z = 0.0f; + root->node_range_x[0] = 0.0f; + root->node_range_x[1] = 0.0f; + root->node_range_y[0] = 0.0f; + root->node_range_y[1] = 0.0f; + root->node_range_z[0] = 0.0f; + root->node_range_z[1] = 0.0f; + root->radius_sq = 0.0f; + root->division_axis = 0; + root->father_ptr = nullptr; + root->left_son_ptr = nullptr; + root->right_son_ptr = nullptr; + root->TreeSize = 0; + root->invalid_point_num = 0; + root->down_del_num = 0; + root->point_deleted = false; + root->tree_deleted = false; + root->need_push_down_to_left = false; + root->need_push_down_to_right = false; + root->point_downsample_deleted = false; + root->working_flag = false; + pthread_mutex_init(&(root->push_down_mutex_lock), NULL); +} + +template +int KD_TREE::size() +{ + int s = 0; + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + if (Root_Node != nullptr) + { + return Root_Node->TreeSize; + } + else + { + return 0; + } + } + else + { + if (!pthread_mutex_trylock(&working_flag_mutex)) + { + s = Root_Node->TreeSize; + pthread_mutex_unlock(&working_flag_mutex); + return s; + } + else + { + return Treesize_tmp; + } + } +} + +template +BoxPointType KD_TREE::tree_range() +{ + BoxPointType range; + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + if (Root_Node != nullptr) + { + range.vertex_min[0] = Root_Node->node_range_x[0]; + range.vertex_min[1] = Root_Node->node_range_y[0]; + range.vertex_min[2] = Root_Node->node_range_z[0]; + range.vertex_max[0] = Root_Node->node_range_x[1]; + range.vertex_max[1] = Root_Node->node_range_y[1]; + range.vertex_max[2] = Root_Node->node_range_z[1]; + } + else + { + memset(&range, 0, sizeof(range)); + } + } + else + { + if (!pthread_mutex_trylock(&working_flag_mutex)) + { + range.vertex_min[0] = Root_Node->node_range_x[0]; + range.vertex_min[1] = Root_Node->node_range_y[0]; + range.vertex_min[2] = Root_Node->node_range_z[0]; + range.vertex_max[0] = Root_Node->node_range_x[1]; + range.vertex_max[1] = Root_Node->node_range_y[1]; + range.vertex_max[2] = Root_Node->node_range_z[1]; + pthread_mutex_unlock(&working_flag_mutex); + } + else + { + memset(&range, 0, sizeof(range)); + } + } + return range; +} + +template +int KD_TREE::validnum() +{ + int s = 0; + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + if (Root_Node != nullptr) + return (Root_Node->TreeSize - Root_Node->invalid_point_num); + else + return 0; + } + else + { + if (!pthread_mutex_trylock(&working_flag_mutex)) + { + s = Root_Node->TreeSize - Root_Node->invalid_point_num; + pthread_mutex_unlock(&working_flag_mutex); + return s; + } + else + { + return -1; + } + } +} + +template +void KD_TREE::root_alpha(float &alpha_bal, float &alpha_del) +{ + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + alpha_bal = Root_Node->alpha_bal; + alpha_del = Root_Node->alpha_del; + return; + } + else + { + if (!pthread_mutex_trylock(&working_flag_mutex)) + { + alpha_bal = Root_Node->alpha_bal; + alpha_del = Root_Node->alpha_del; + pthread_mutex_unlock(&working_flag_mutex); + return; + } + else + { + alpha_bal = alpha_bal_tmp; + alpha_del = alpha_del_tmp; + return; + } + } +} + +template +void KD_TREE::start_thread() +{ + pthread_mutex_init(&termination_flag_mutex_lock, NULL); + pthread_mutex_init(&rebuild_ptr_mutex_lock, NULL); + pthread_mutex_init(&rebuild_logger_mutex_lock, NULL); + pthread_mutex_init(&points_deleted_rebuild_mutex_lock, NULL); + pthread_mutex_init(&working_flag_mutex, NULL); + pthread_mutex_init(&search_flag_mutex, NULL); + pthread_create(&rebuild_thread, NULL, multi_thread_ptr, (void *)this); + printf("Multi thread started \n"); +} + +template +void KD_TREE::stop_thread() +{ + pthread_mutex_lock(&termination_flag_mutex_lock); + termination_flag = true; + pthread_mutex_unlock(&termination_flag_mutex_lock); + if (rebuild_thread) + pthread_join(rebuild_thread, NULL); + pthread_mutex_destroy(&termination_flag_mutex_lock); + pthread_mutex_destroy(&rebuild_logger_mutex_lock); + pthread_mutex_destroy(&rebuild_ptr_mutex_lock); + pthread_mutex_destroy(&points_deleted_rebuild_mutex_lock); + pthread_mutex_destroy(&working_flag_mutex); + pthread_mutex_destroy(&search_flag_mutex); +} + +template +void *KD_TREE::multi_thread_ptr(void *arg) +{ + KD_TREE *handle = (KD_TREE *)arg; + handle->multi_thread_rebuild(); + return nullptr; +} + +template +void KD_TREE::multi_thread_rebuild() +{ + bool terminated = false; + KD_TREE_NODE *father_ptr, **new_node_ptr; + pthread_mutex_lock(&termination_flag_mutex_lock); + terminated = termination_flag; + pthread_mutex_unlock(&termination_flag_mutex_lock); + while (!terminated) + { + pthread_mutex_lock(&rebuild_ptr_mutex_lock); + pthread_mutex_lock(&working_flag_mutex); + if (Rebuild_Ptr != nullptr) + { + /* Traverse and copy */ + if (!Rebuild_Logger.empty()) + { + printf("\n\n\n\n\n\n\n\n\n\n\n ERROR!!! \n\n\n\n\n\n\n\n\n"); + } + rebuild_flag = true; + if (*Rebuild_Ptr == Root_Node) + { + Treesize_tmp = Root_Node->TreeSize; + Validnum_tmp = Root_Node->TreeSize - Root_Node->invalid_point_num; + alpha_bal_tmp = Root_Node->alpha_bal; + alpha_del_tmp = Root_Node->alpha_del; + } + KD_TREE_NODE *old_root_node = (*Rebuild_Ptr); + father_ptr = (*Rebuild_Ptr)->father_ptr; + PointVector().swap(Rebuild_PCL_Storage); + // Lock Search + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter != 0) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter = -1; + pthread_mutex_unlock(&search_flag_mutex); + // Lock deleted points cache + pthread_mutex_lock(&points_deleted_rebuild_mutex_lock); + flatten(*Rebuild_Ptr, Rebuild_PCL_Storage, MULTI_THREAD_REC); + // Unlock deleted points cache + pthread_mutex_unlock(&points_deleted_rebuild_mutex_lock); + // Unlock Search + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter = 0; + pthread_mutex_unlock(&search_flag_mutex); + pthread_mutex_unlock(&working_flag_mutex); + /* Rebuild and update missed operations*/ + Operation_Logger_Type Operation; + KD_TREE_NODE *new_root_node = nullptr; + if (int(Rebuild_PCL_Storage.size()) > 0) + { + BuildTree(&new_root_node, 0, Rebuild_PCL_Storage.size() - 1, Rebuild_PCL_Storage); + // Rebuild has been done. Updates the blocked operations into the new tree + pthread_mutex_lock(&working_flag_mutex); + pthread_mutex_lock(&rebuild_logger_mutex_lock); + int tmp_counter = 0; + while (!Rebuild_Logger.empty()) + { + Operation = Rebuild_Logger.front(); + max_queue_size = max(max_queue_size, Rebuild_Logger.size()); + Rebuild_Logger.pop(); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + pthread_mutex_unlock(&working_flag_mutex); + run_operation(&new_root_node, Operation); + tmp_counter++; + if (tmp_counter % 10 == 0) + usleep(1); + pthread_mutex_lock(&working_flag_mutex); + pthread_mutex_lock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + /* Replace to original tree*/ + // pthread_mutex_lock(&working_flag_mutex); + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter != 0) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter = -1; + pthread_mutex_unlock(&search_flag_mutex); + if (father_ptr->left_son_ptr == *Rebuild_Ptr) + { + father_ptr->left_son_ptr = new_root_node; + } + else if (father_ptr->right_son_ptr == *Rebuild_Ptr) + { + father_ptr->right_son_ptr = new_root_node; + } + else + { + throw "Error: Father ptr incompatible with current node\n"; + } + if (new_root_node != nullptr) + new_root_node->father_ptr = father_ptr; + (*Rebuild_Ptr) = new_root_node; + int valid_old = old_root_node->TreeSize - old_root_node->invalid_point_num; + int valid_new = new_root_node->TreeSize - new_root_node->invalid_point_num; + if (father_ptr == STATIC_ROOT_NODE) + Root_Node = STATIC_ROOT_NODE->left_son_ptr; + KD_TREE_NODE *update_root = *Rebuild_Ptr; + while (update_root != nullptr && update_root != Root_Node) + { + update_root = update_root->father_ptr; + if (update_root->working_flag) + break; + if (update_root == update_root->father_ptr->left_son_ptr && update_root->father_ptr->need_push_down_to_left) + break; + if (update_root == update_root->father_ptr->right_son_ptr && update_root->father_ptr->need_push_down_to_right) + break; + Update(update_root); + } + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter = 0; + pthread_mutex_unlock(&search_flag_mutex); + Rebuild_Ptr = nullptr; + pthread_mutex_unlock(&working_flag_mutex); + rebuild_flag = false; + /* Delete discarded tree nodes */ + delete_tree_nodes(&old_root_node); + } + else + { + pthread_mutex_unlock(&working_flag_mutex); + } + pthread_mutex_unlock(&rebuild_ptr_mutex_lock); + pthread_mutex_lock(&termination_flag_mutex_lock); + terminated = termination_flag; + pthread_mutex_unlock(&termination_flag_mutex_lock); + usleep(100); + } + printf("Rebuild thread terminated normally\n"); +} + +template +void KD_TREE::run_operation(KD_TREE_NODE **root, Operation_Logger_Type operation) +{ + switch (operation.op) + { + case ADD_POINT: + Add_by_point(root, operation.point, false, (*root)->division_axis); + break; + case ADD_BOX: + Add_by_range(root, operation.boxpoint, false); + break; + case DELETE_POINT: + Delete_by_point(root, operation.point, false); + break; + case DELETE_BOX: + Delete_by_range(root, operation.boxpoint, false, false); + break; + case DOWNSAMPLE_DELETE: + Delete_by_range(root, operation.boxpoint, false, true); + break; + case PUSH_DOWN: + (*root)->tree_downsample_deleted |= operation.tree_downsample_deleted; + (*root)->point_downsample_deleted |= operation.tree_downsample_deleted; + (*root)->tree_deleted = operation.tree_deleted || (*root)->tree_downsample_deleted; + (*root)->point_deleted = (*root)->tree_deleted || (*root)->point_downsample_deleted; + if (operation.tree_downsample_deleted) + (*root)->down_del_num = (*root)->TreeSize; + if (operation.tree_deleted) + (*root)->invalid_point_num = (*root)->TreeSize; + else + (*root)->invalid_point_num = (*root)->down_del_num; + (*root)->need_push_down_to_left = true; + (*root)->need_push_down_to_right = true; + break; + default: + break; + } +} + +template +void KD_TREE::Build(PointVector point_cloud) +{ + if (Root_Node != nullptr) + { + delete_tree_nodes(&Root_Node); + } + if (point_cloud.size() == 0) + return; + STATIC_ROOT_NODE = new KD_TREE_NODE; + InitTreeNode(STATIC_ROOT_NODE); + BuildTree(&STATIC_ROOT_NODE->left_son_ptr, 0, point_cloud.size() - 1, point_cloud); + Update(STATIC_ROOT_NODE); + STATIC_ROOT_NODE->TreeSize = 0; + Root_Node = STATIC_ROOT_NODE->left_son_ptr; +} + +template +void KD_TREE::Nearest_Search(PointType point, int k_nearest, PointVector &Nearest_Points, vector &Point_Distance, float max_dist) +{ + MANUAL_HEAP q(2 * k_nearest); + q.clear(); + vector().swap(Point_Distance); + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + Search(Root_Node, k_nearest, point, q, max_dist); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter == -1) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter += 1; + pthread_mutex_unlock(&search_flag_mutex); + Search(Root_Node, k_nearest, point, q, max_dist); + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter -= 1; + pthread_mutex_unlock(&search_flag_mutex); + } + int k_found = min(k_nearest, int(q.size())); + PointVector().swap(Nearest_Points); + vector().swap(Point_Distance); + for (int i = 0; i < k_found; i++) + { + Nearest_Points.insert(Nearest_Points.begin(), q.top().point); + Point_Distance.insert(Point_Distance.begin(), q.top().dist); + q.pop(); + } + return; +} + +template +void KD_TREE::Box_Search(const BoxPointType &Box_of_Point, PointVector &Storage) +{ + Storage.clear(); + Search_by_range(Root_Node, Box_of_Point, Storage); +} + +template +void KD_TREE::Radius_Search(PointType point, const float radius, PointVector &Storage) +{ + Storage.clear(); + Search_by_radius(Root_Node, point, radius, Storage); +} + +template +int KD_TREE::Add_Points(PointVector &PointToAdd, bool downsample_on) +{ + int NewPointSize = PointToAdd.size(); + int tree_size = size(); + BoxPointType Box_of_Point; + PointType downsample_result, mid_point; + bool downsample_switch = downsample_on && DOWNSAMPLE_SWITCH; + float min_dist, tmp_dist; + int tmp_counter = 0; + for (int i = 0; i < PointToAdd.size(); i++) + { + if (downsample_switch) + { + Box_of_Point.vertex_min[0] = floor(PointToAdd[i].x / downsample_size) * downsample_size; + Box_of_Point.vertex_max[0] = Box_of_Point.vertex_min[0] + downsample_size; + Box_of_Point.vertex_min[1] = floor(PointToAdd[i].y / downsample_size) * downsample_size; + Box_of_Point.vertex_max[1] = Box_of_Point.vertex_min[1] + downsample_size; + Box_of_Point.vertex_min[2] = floor(PointToAdd[i].z / downsample_size) * downsample_size; + Box_of_Point.vertex_max[2] = Box_of_Point.vertex_min[2] + downsample_size; + mid_point.x = Box_of_Point.vertex_min[0] + (Box_of_Point.vertex_max[0] - Box_of_Point.vertex_min[0]) / 2.0; + mid_point.y = Box_of_Point.vertex_min[1] + (Box_of_Point.vertex_max[1] - Box_of_Point.vertex_min[1]) / 2.0; + mid_point.z = Box_of_Point.vertex_min[2] + (Box_of_Point.vertex_max[2] - Box_of_Point.vertex_min[2]) / 2.0; + PointVector().swap(Downsample_Storage); + Search_by_range(Root_Node, Box_of_Point, Downsample_Storage); + min_dist = calc_dist(PointToAdd[i], mid_point); + downsample_result = PointToAdd[i]; + for (int index = 0; index < Downsample_Storage.size(); index++) + { + tmp_dist = calc_dist(Downsample_Storage[index], mid_point); + if (tmp_dist < min_dist) + { + min_dist = tmp_dist; + downsample_result = Downsample_Storage[index]; + } + } + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + if (Downsample_Storage.size() > 1 || same_point(PointToAdd[i], downsample_result)) + { + if (Downsample_Storage.size() > 0) + Delete_by_range(&Root_Node, Box_of_Point, true, true); + Add_by_point(&Root_Node, downsample_result, true, Root_Node->division_axis); + tmp_counter++; + } + } + else + { + if (Downsample_Storage.size() > 1 || same_point(PointToAdd[i], downsample_result)) + { + Operation_Logger_Type operation_delete, operation; + operation_delete.boxpoint = Box_of_Point; + operation_delete.op = DOWNSAMPLE_DELETE; + operation.point = downsample_result; + operation.op = ADD_POINT; + pthread_mutex_lock(&working_flag_mutex); + if (Downsample_Storage.size() > 0) + Delete_by_range(&Root_Node, Box_of_Point, false, true); + Add_by_point(&Root_Node, downsample_result, false, Root_Node->division_axis); + tmp_counter++; + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + if (Downsample_Storage.size() > 0) + Rebuild_Logger.push(operation_delete); + Rebuild_Logger.push(operation); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + }; + } + } + else + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + Add_by_point(&Root_Node, PointToAdd[i], true, Root_Node->division_axis); + } + else + { + Operation_Logger_Type operation; + operation.point = PointToAdd[i]; + operation.op = ADD_POINT; + pthread_mutex_lock(&working_flag_mutex); + Add_by_point(&Root_Node, PointToAdd[i], false, Root_Node->division_axis); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(operation); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + } + return tmp_counter; +} + +template +void KD_TREE::Add_Point_Boxes(vector &BoxPoints) +{ + for (int i = 0; i < BoxPoints.size(); i++) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + Add_by_range(&Root_Node, BoxPoints[i], true); + } + else + { + Operation_Logger_Type operation; + operation.boxpoint = BoxPoints[i]; + operation.op = ADD_BOX; + pthread_mutex_lock(&working_flag_mutex); + Add_by_range(&Root_Node, BoxPoints[i], false); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(operation); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + return; +} + +template +void KD_TREE::Delete_Points(PointVector &PointToDel) +{ + for (int i = 0; i < PointToDel.size(); i++) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + Delete_by_point(&Root_Node, PointToDel[i], true); + } + else + { + Operation_Logger_Type operation; + operation.point = PointToDel[i]; + operation.op = DELETE_POINT; + pthread_mutex_lock(&working_flag_mutex); + Delete_by_point(&Root_Node, PointToDel[i], false); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(operation); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + return; +} + +template +int KD_TREE::Delete_Point_Boxes(vector &BoxPoints) +{ + int tmp_counter = 0; + for (int i = 0; i < BoxPoints.size(); i++) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + tmp_counter += Delete_by_range(&Root_Node, BoxPoints[i], true, false); + } + else + { + Operation_Logger_Type operation; + operation.boxpoint = BoxPoints[i]; + operation.op = DELETE_BOX; + pthread_mutex_lock(&working_flag_mutex); + tmp_counter += Delete_by_range(&Root_Node, BoxPoints[i], false, false); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(operation); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + return tmp_counter; +} + +template +void KD_TREE::acquire_removed_points(PointVector &removed_points) +{ + pthread_mutex_lock(&points_deleted_rebuild_mutex_lock); + for (int i = 0; i < Points_deleted.size(); i++) + { + removed_points.push_back(Points_deleted[i]); + } + for (int i = 0; i < Multithread_Points_deleted.size(); i++) + { + removed_points.push_back(Multithread_Points_deleted[i]); + } + Points_deleted.clear(); + Multithread_Points_deleted.clear(); + pthread_mutex_unlock(&points_deleted_rebuild_mutex_lock); + return; +} + +template +void KD_TREE::BuildTree(KD_TREE_NODE **root, int l, int r, PointVector &Storage) +{ + if (l > r) + return; + *root = new KD_TREE_NODE; + InitTreeNode(*root); + int mid = (l + r) >> 1; + int div_axis = 0; + int i; + // Find the best division Axis + float min_value[3] = {INFINITY, INFINITY, INFINITY}; + float max_value[3] = {-INFINITY, -INFINITY, -INFINITY}; + float dim_range[3] = {0, 0, 0}; + for (i = l; i <= r; i++) + { + min_value[0] = min(min_value[0], Storage[i].x); + min_value[1] = min(min_value[1], Storage[i].y); + min_value[2] = min(min_value[2], Storage[i].z); + max_value[0] = max(max_value[0], Storage[i].x); + max_value[1] = max(max_value[1], Storage[i].y); + max_value[2] = max(max_value[2], Storage[i].z); + } + // Select the longest dimension as division axis + for (i = 0; i < 3; i++) + dim_range[i] = max_value[i] - min_value[i]; + for (i = 1; i < 3; i++) + if (dim_range[i] > dim_range[div_axis]) + div_axis = i; + // Divide by the division axis and recursively build. + + (*root)->division_axis = div_axis; + switch (div_axis) + { + case 0: + nth_element(begin(Storage) + l, begin(Storage) + mid, begin(Storage) + r + 1, point_cmp_x); + break; + case 1: + nth_element(begin(Storage) + l, begin(Storage) + mid, begin(Storage) + r + 1, point_cmp_y); + break; + case 2: + nth_element(begin(Storage) + l, begin(Storage) + mid, begin(Storage) + r + 1, point_cmp_z); + break; + default: + nth_element(begin(Storage) + l, begin(Storage) + mid, begin(Storage) + r + 1, point_cmp_x); + break; + } + (*root)->point = Storage[mid]; + KD_TREE_NODE *left_son = nullptr, *right_son = nullptr; + BuildTree(&left_son, l, mid - 1, Storage); + BuildTree(&right_son, mid + 1, r, Storage); + (*root)->left_son_ptr = left_son; + (*root)->right_son_ptr = right_son; + Update((*root)); + return; +} + +template +void KD_TREE::Rebuild(KD_TREE_NODE **root) +{ + KD_TREE_NODE *father_ptr; + if ((*root)->TreeSize >= Multi_Thread_Rebuild_Point_Num) + { + if (!pthread_mutex_trylock(&rebuild_ptr_mutex_lock)) + { + if (Rebuild_Ptr == nullptr || ((*root)->TreeSize > (*Rebuild_Ptr)->TreeSize)) + { + Rebuild_Ptr = root; + } + pthread_mutex_unlock(&rebuild_ptr_mutex_lock); + } + } + else + { + father_ptr = (*root)->father_ptr; + int size_rec = (*root)->TreeSize; + PCL_Storage.clear(); + flatten(*root, PCL_Storage, DELETE_POINTS_REC); + delete_tree_nodes(root); + BuildTree(root, 0, PCL_Storage.size() - 1, PCL_Storage); + if (*root != nullptr) + (*root)->father_ptr = father_ptr; + if (*root == Root_Node) + STATIC_ROOT_NODE->left_son_ptr = *root; + } + return; +} + +template +int KD_TREE::Delete_by_range(KD_TREE_NODE **root, BoxPointType boxpoint, bool allow_rebuild, bool is_downsample) +{ + if ((*root) == nullptr || (*root)->tree_deleted) + return 0; + (*root)->working_flag = true; + Push_Down(*root); + int tmp_counter = 0; + if (boxpoint.vertex_max[0] <= (*root)->node_range_x[0] || boxpoint.vertex_min[0] > (*root)->node_range_x[1]) + return 0; + if (boxpoint.vertex_max[1] <= (*root)->node_range_y[0] || boxpoint.vertex_min[1] > (*root)->node_range_y[1]) + return 0; + if (boxpoint.vertex_max[2] <= (*root)->node_range_z[0] || boxpoint.vertex_min[2] > (*root)->node_range_z[1]) + return 0; + if (boxpoint.vertex_min[0] <= (*root)->node_range_x[0] && boxpoint.vertex_max[0] > (*root)->node_range_x[1] && boxpoint.vertex_min[1] <= (*root)->node_range_y[0] && boxpoint.vertex_max[1] > (*root)->node_range_y[1] && boxpoint.vertex_min[2] <= (*root)->node_range_z[0] && boxpoint.vertex_max[2] > (*root)->node_range_z[1]) + { + (*root)->tree_deleted = true; + (*root)->point_deleted = true; + (*root)->need_push_down_to_left = true; + (*root)->need_push_down_to_right = true; + tmp_counter = (*root)->TreeSize - (*root)->invalid_point_num; + (*root)->invalid_point_num = (*root)->TreeSize; + if (is_downsample) + { + (*root)->tree_downsample_deleted = true; + (*root)->point_downsample_deleted = true; + (*root)->down_del_num = (*root)->TreeSize; + } + return tmp_counter; + } + if (!(*root)->point_deleted && boxpoint.vertex_min[0] <= (*root)->point.x && boxpoint.vertex_max[0] > (*root)->point.x && boxpoint.vertex_min[1] <= (*root)->point.y && boxpoint.vertex_max[1] > (*root)->point.y && boxpoint.vertex_min[2] <= (*root)->point.z && boxpoint.vertex_max[2] > (*root)->point.z) + { + (*root)->point_deleted = true; + tmp_counter += 1; + if (is_downsample) + (*root)->point_downsample_deleted = true; + } + Operation_Logger_Type delete_box_log; + struct timespec Timeout; + if (is_downsample) + delete_box_log.op = DOWNSAMPLE_DELETE; + else + delete_box_log.op = DELETE_BOX; + delete_box_log.boxpoint = boxpoint; + if ((Rebuild_Ptr == nullptr) || (*root)->left_son_ptr != *Rebuild_Ptr) + { + tmp_counter += Delete_by_range(&((*root)->left_son_ptr), boxpoint, allow_rebuild, is_downsample); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + tmp_counter += Delete_by_range(&((*root)->left_son_ptr), boxpoint, false, is_downsample); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(delete_box_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + if ((Rebuild_Ptr == nullptr) || (*root)->right_son_ptr != *Rebuild_Ptr) + { + tmp_counter += Delete_by_range(&((*root)->right_son_ptr), boxpoint, allow_rebuild, is_downsample); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + tmp_counter += Delete_by_range(&((*root)->right_son_ptr), boxpoint, false, is_downsample); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(delete_box_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + Update(*root); + if (Rebuild_Ptr != nullptr && *Rebuild_Ptr == *root && (*root)->TreeSize < Multi_Thread_Rebuild_Point_Num) + Rebuild_Ptr = nullptr; + bool need_rebuild = allow_rebuild & Criterion_Check((*root)); + if (need_rebuild) + Rebuild(root); + if ((*root) != nullptr) + (*root)->working_flag = false; + return tmp_counter; +} + +template +void KD_TREE::Delete_by_point(KD_TREE_NODE **root, PointType point, bool allow_rebuild) +{ + if ((*root) == nullptr || (*root)->tree_deleted) + return; + (*root)->working_flag = true; + Push_Down(*root); + if (same_point((*root)->point, point) && !(*root)->point_deleted) + { + (*root)->point_deleted = true; + (*root)->invalid_point_num += 1; + if ((*root)->invalid_point_num == (*root)->TreeSize) + (*root)->tree_deleted = true; + return; + } + Operation_Logger_Type delete_log; + struct timespec Timeout; + delete_log.op = DELETE_POINT; + delete_log.point = point; + if (((*root)->division_axis == 0 && point.x < (*root)->point.x) || ((*root)->division_axis == 1 && point.y < (*root)->point.y) || ((*root)->division_axis == 2 && point.z < (*root)->point.z)) + { + if ((Rebuild_Ptr == nullptr) || (*root)->left_son_ptr != *Rebuild_Ptr) + { + Delete_by_point(&(*root)->left_son_ptr, point, allow_rebuild); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + Delete_by_point(&(*root)->left_son_ptr, point, false); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(delete_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + else + { + if ((Rebuild_Ptr == nullptr) || (*root)->right_son_ptr != *Rebuild_Ptr) + { + Delete_by_point(&(*root)->right_son_ptr, point, allow_rebuild); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + Delete_by_point(&(*root)->right_son_ptr, point, false); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(delete_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + Update(*root); + if (Rebuild_Ptr != nullptr && *Rebuild_Ptr == *root && (*root)->TreeSize < Multi_Thread_Rebuild_Point_Num) + Rebuild_Ptr = nullptr; + bool need_rebuild = allow_rebuild & Criterion_Check((*root)); + if (need_rebuild) + Rebuild(root); + if ((*root) != nullptr) + (*root)->working_flag = false; + return; +} + +template +void KD_TREE::Add_by_range(KD_TREE_NODE **root, BoxPointType boxpoint, bool allow_rebuild) +{ + if ((*root) == nullptr) + return; + (*root)->working_flag = true; + Push_Down(*root); + if (boxpoint.vertex_max[0] <= (*root)->node_range_x[0] || boxpoint.vertex_min[0] > (*root)->node_range_x[1]) + return; + if (boxpoint.vertex_max[1] <= (*root)->node_range_y[0] || boxpoint.vertex_min[1] > (*root)->node_range_y[1]) + return; + if (boxpoint.vertex_max[2] <= (*root)->node_range_z[0] || boxpoint.vertex_min[2] > (*root)->node_range_z[1]) + return; + if (boxpoint.vertex_min[0] <= (*root)->node_range_x[0] && boxpoint.vertex_max[0] > (*root)->node_range_x[1] && boxpoint.vertex_min[1] <= (*root)->node_range_y[0] && boxpoint.vertex_max[1] > (*root)->node_range_y[1] && boxpoint.vertex_min[2] <= (*root)->node_range_z[0] && boxpoint.vertex_max[2] > (*root)->node_range_z[1]) + { + (*root)->tree_deleted = false || (*root)->tree_downsample_deleted; + (*root)->point_deleted = false || (*root)->point_downsample_deleted; + (*root)->need_push_down_to_left = true; + (*root)->need_push_down_to_right = true; + (*root)->invalid_point_num = (*root)->down_del_num; + return; + } + if (boxpoint.vertex_min[0] <= (*root)->point.x && boxpoint.vertex_max[0] > (*root)->point.x && boxpoint.vertex_min[1] <= (*root)->point.y && boxpoint.vertex_max[1] > (*root)->point.y && boxpoint.vertex_min[2] <= (*root)->point.z && boxpoint.vertex_max[2] > (*root)->point.z) + { + (*root)->point_deleted = (*root)->point_downsample_deleted; + } + Operation_Logger_Type add_box_log; + struct timespec Timeout; + add_box_log.op = ADD_BOX; + add_box_log.boxpoint = boxpoint; + if ((Rebuild_Ptr == nullptr) || (*root)->left_son_ptr != *Rebuild_Ptr) + { + Add_by_range(&((*root)->left_son_ptr), boxpoint, allow_rebuild); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + Add_by_range(&((*root)->left_son_ptr), boxpoint, false); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(add_box_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + if ((Rebuild_Ptr == nullptr) || (*root)->right_son_ptr != *Rebuild_Ptr) + { + Add_by_range(&((*root)->right_son_ptr), boxpoint, allow_rebuild); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + Add_by_range(&((*root)->right_son_ptr), boxpoint, false); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(add_box_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + Update(*root); + if (Rebuild_Ptr != nullptr && *Rebuild_Ptr == *root && (*root)->TreeSize < Multi_Thread_Rebuild_Point_Num) + Rebuild_Ptr = nullptr; + bool need_rebuild = allow_rebuild & Criterion_Check((*root)); + if (need_rebuild) + Rebuild(root); + if ((*root) != nullptr) + (*root)->working_flag = false; + return; +} + +template +void KD_TREE::Add_by_point(KD_TREE_NODE **root, PointType point, bool allow_rebuild, int father_axis) +{ + if (*root == nullptr) + { + *root = new KD_TREE_NODE; + InitTreeNode(*root); + (*root)->point = point; + (*root)->division_axis = (father_axis + 1) % 3; + Update(*root); + return; + } + (*root)->working_flag = true; + Operation_Logger_Type add_log; + struct timespec Timeout; + add_log.op = ADD_POINT; + add_log.point = point; + Push_Down(*root); + if (((*root)->division_axis == 0 && point.x < (*root)->point.x) || ((*root)->division_axis == 1 && point.y < (*root)->point.y) || ((*root)->division_axis == 2 && point.z < (*root)->point.z)) + { + if ((Rebuild_Ptr == nullptr) || (*root)->left_son_ptr != *Rebuild_Ptr) + { + Add_by_point(&(*root)->left_son_ptr, point, allow_rebuild, (*root)->division_axis); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + Add_by_point(&(*root)->left_son_ptr, point, false, (*root)->division_axis); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(add_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + else + { + if ((Rebuild_Ptr == nullptr) || (*root)->right_son_ptr != *Rebuild_Ptr) + { + Add_by_point(&(*root)->right_son_ptr, point, allow_rebuild, (*root)->division_axis); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + Add_by_point(&(*root)->right_son_ptr, point, false, (*root)->division_axis); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(add_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + Update(*root); + if (Rebuild_Ptr != nullptr && *Rebuild_Ptr == *root && (*root)->TreeSize < Multi_Thread_Rebuild_Point_Num) + Rebuild_Ptr = nullptr; + bool need_rebuild = allow_rebuild & Criterion_Check((*root)); + if (need_rebuild) + Rebuild(root); + if ((*root) != nullptr) + (*root)->working_flag = false; + return; +} + +template +void KD_TREE::Search(KD_TREE_NODE *root, int k_nearest, PointType point, MANUAL_HEAP &q, float max_dist) +{ + if (root == nullptr || root->tree_deleted) + return; + float cur_dist = calc_box_dist(root, point); + float max_dist_sqr = max_dist * max_dist; + if (cur_dist > max_dist_sqr) + return; + int retval; + if (root->need_push_down_to_left || root->need_push_down_to_right) + { + retval = pthread_mutex_trylock(&(root->push_down_mutex_lock)); + if (retval == 0) + { + Push_Down(root); + pthread_mutex_unlock(&(root->push_down_mutex_lock)); + } + else + { + pthread_mutex_lock(&(root->push_down_mutex_lock)); + pthread_mutex_unlock(&(root->push_down_mutex_lock)); + } + } + if (!root->point_deleted) + { + float dist = calc_dist(point, root->point); + if (dist <= max_dist_sqr && (q.size() < k_nearest || dist < q.top().dist)) + { + if (q.size() >= k_nearest) + q.pop(); + PointType_CMP current_point{root->point, dist}; + q.push(current_point); + } + } + int cur_search_counter; + float dist_left_node = calc_box_dist(root->left_son_ptr, point); + float dist_right_node = calc_box_dist(root->right_son_ptr, point); + if (q.size() < k_nearest || dist_left_node < q.top().dist && dist_right_node < q.top().dist) + { + if (dist_left_node <= dist_right_node) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->left_son_ptr) + { + Search(root->left_son_ptr, k_nearest, point, q, max_dist); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter == -1) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter += 1; + pthread_mutex_unlock(&search_flag_mutex); + Search(root->left_son_ptr, k_nearest, point, q, max_dist); + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter -= 1; + pthread_mutex_unlock(&search_flag_mutex); + } + if (q.size() < k_nearest || dist_right_node < q.top().dist) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->right_son_ptr) + { + Search(root->right_son_ptr, k_nearest, point, q, max_dist); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter == -1) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter += 1; + pthread_mutex_unlock(&search_flag_mutex); + Search(root->right_son_ptr, k_nearest, point, q, max_dist); + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter -= 1; + pthread_mutex_unlock(&search_flag_mutex); + } + } + } + else + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->right_son_ptr) + { + Search(root->right_son_ptr, k_nearest, point, q, max_dist); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter == -1) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter += 1; + pthread_mutex_unlock(&search_flag_mutex); + Search(root->right_son_ptr, k_nearest, point, q, max_dist); + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter -= 1; + pthread_mutex_unlock(&search_flag_mutex); + } + if (q.size() < k_nearest || dist_left_node < q.top().dist) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->left_son_ptr) + { + Search(root->left_son_ptr, k_nearest, point, q, max_dist); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter == -1) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter += 1; + pthread_mutex_unlock(&search_flag_mutex); + Search(root->left_son_ptr, k_nearest, point, q, max_dist); + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter -= 1; + pthread_mutex_unlock(&search_flag_mutex); + } + } + } + } + else + { + if (dist_left_node < q.top().dist) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->left_son_ptr) + { + Search(root->left_son_ptr, k_nearest, point, q, max_dist); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter == -1) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter += 1; + pthread_mutex_unlock(&search_flag_mutex); + Search(root->left_son_ptr, k_nearest, point, q, max_dist); + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter -= 1; + pthread_mutex_unlock(&search_flag_mutex); + } + } + if (dist_right_node < q.top().dist) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->right_son_ptr) + { + Search(root->right_son_ptr, k_nearest, point, q, max_dist); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter == -1) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter += 1; + pthread_mutex_unlock(&search_flag_mutex); + Search(root->right_son_ptr, k_nearest, point, q, max_dist); + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter -= 1; + pthread_mutex_unlock(&search_flag_mutex); + } + } + } + return; +} + +template +void KD_TREE::Search_by_range(KD_TREE_NODE *root, BoxPointType boxpoint, PointVector &Storage) +{ + if (root == nullptr) + return; + Push_Down(root); + if (boxpoint.vertex_max[0] <= root->node_range_x[0] || boxpoint.vertex_min[0] > root->node_range_x[1]) + return; + if (boxpoint.vertex_max[1] <= root->node_range_y[0] || boxpoint.vertex_min[1] > root->node_range_y[1]) + return; + if (boxpoint.vertex_max[2] <= root->node_range_z[0] || boxpoint.vertex_min[2] > root->node_range_z[1]) + return; + if (boxpoint.vertex_min[0] <= root->node_range_x[0] && boxpoint.vertex_max[0] > root->node_range_x[1] && boxpoint.vertex_min[1] <= root->node_range_y[0] && boxpoint.vertex_max[1] > root->node_range_y[1] && boxpoint.vertex_min[2] <= root->node_range_z[0] && boxpoint.vertex_max[2] > root->node_range_z[1]) + { + flatten(root, Storage, NOT_RECORD); + return; + } + if (boxpoint.vertex_min[0] <= root->point.x && boxpoint.vertex_max[0] > root->point.x && boxpoint.vertex_min[1] <= root->point.y && boxpoint.vertex_max[1] > root->point.y && boxpoint.vertex_min[2] <= root->point.z && boxpoint.vertex_max[2] > root->point.z) + { + if (!root->point_deleted) + Storage.push_back(root->point); + } + if ((Rebuild_Ptr == nullptr) || root->left_son_ptr != *Rebuild_Ptr) + { + Search_by_range(root->left_son_ptr, boxpoint, Storage); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + Search_by_range(root->left_son_ptr, boxpoint, Storage); + pthread_mutex_unlock(&search_flag_mutex); + } + if ((Rebuild_Ptr == nullptr) || root->right_son_ptr != *Rebuild_Ptr) + { + Search_by_range(root->right_son_ptr, boxpoint, Storage); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + Search_by_range(root->right_son_ptr, boxpoint, Storage); + pthread_mutex_unlock(&search_flag_mutex); + } + return; +} + +template +void KD_TREE::Search_by_radius(KD_TREE_NODE *root, PointType point, float radius, PointVector &Storage) +{ + if (root == nullptr) + return; + Push_Down(root); + PointType range_center; + range_center.x = (root->node_range_x[0] + root->node_range_x[1]) * 0.5; + range_center.y = (root->node_range_y[0] + root->node_range_y[1]) * 0.5; + range_center.z = (root->node_range_z[0] + root->node_range_z[1]) * 0.5; + float dist = sqrt(calc_dist(range_center, point)); + if (dist > radius + sqrt(root->radius_sq)) return; + if (dist <= radius - sqrt(root->radius_sq)) + { + flatten(root, Storage, NOT_RECORD); + return; + } + if (!root->point_deleted && calc_dist(root->point, point) <= radius * radius){ + Storage.push_back(root->point); + } + if ((Rebuild_Ptr == nullptr) || root->left_son_ptr != *Rebuild_Ptr) + { + Search_by_radius(root->left_son_ptr, point, radius, Storage); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + Search_by_radius(root->left_son_ptr, point, radius, Storage); + pthread_mutex_unlock(&search_flag_mutex); + } + if ((Rebuild_Ptr == nullptr) || root->right_son_ptr != *Rebuild_Ptr) + { + Search_by_radius(root->right_son_ptr, point, radius, Storage); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + Search_by_radius(root->right_son_ptr, point, radius, Storage); + pthread_mutex_unlock(&search_flag_mutex); + } + return; +} + +template +bool KD_TREE::Criterion_Check(KD_TREE_NODE *root) +{ + if (root->TreeSize <= Minimal_Unbalanced_Tree_Size) + { + return false; + } + float balance_evaluation = 0.0f; + float delete_evaluation = 0.0f; + KD_TREE_NODE *son_ptr = root->left_son_ptr; + if (son_ptr == nullptr) + son_ptr = root->right_son_ptr; + delete_evaluation = float(root->invalid_point_num) / root->TreeSize; + balance_evaluation = float(son_ptr->TreeSize) / (root->TreeSize - 1); + if (delete_evaluation > delete_criterion_param) + { + return true; + } + if (balance_evaluation > balance_criterion_param || balance_evaluation < 1 - balance_criterion_param) + { + return true; + } + return false; +} + +template +void KD_TREE::Push_Down(KD_TREE_NODE *root) +{ + if (root == nullptr) + return; + Operation_Logger_Type operation; + operation.op = PUSH_DOWN; + operation.tree_deleted = root->tree_deleted; + operation.tree_downsample_deleted = root->tree_downsample_deleted; + if (root->need_push_down_to_left && root->left_son_ptr != nullptr) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->left_son_ptr) + { + root->left_son_ptr->tree_downsample_deleted |= root->tree_downsample_deleted; + root->left_son_ptr->point_downsample_deleted |= root->tree_downsample_deleted; + root->left_son_ptr->tree_deleted = root->tree_deleted || root->left_son_ptr->tree_downsample_deleted; + root->left_son_ptr->point_deleted = root->left_son_ptr->tree_deleted || root->left_son_ptr->point_downsample_deleted; + if (root->tree_downsample_deleted) + root->left_son_ptr->down_del_num = root->left_son_ptr->TreeSize; + if (root->tree_deleted) + root->left_son_ptr->invalid_point_num = root->left_son_ptr->TreeSize; + else + root->left_son_ptr->invalid_point_num = root->left_son_ptr->down_del_num; + root->left_son_ptr->need_push_down_to_left = true; + root->left_son_ptr->need_push_down_to_right = true; + root->need_push_down_to_left = false; + } + else + { + pthread_mutex_lock(&working_flag_mutex); + root->left_son_ptr->tree_downsample_deleted |= root->tree_downsample_deleted; + root->left_son_ptr->point_downsample_deleted |= root->tree_downsample_deleted; + root->left_son_ptr->tree_deleted = root->tree_deleted || root->left_son_ptr->tree_downsample_deleted; + root->left_son_ptr->point_deleted = root->left_son_ptr->tree_deleted || root->left_son_ptr->point_downsample_deleted; + if (root->tree_downsample_deleted) + root->left_son_ptr->down_del_num = root->left_son_ptr->TreeSize; + if (root->tree_deleted) + root->left_son_ptr->invalid_point_num = root->left_son_ptr->TreeSize; + else + root->left_son_ptr->invalid_point_num = root->left_son_ptr->down_del_num; + root->left_son_ptr->need_push_down_to_left = true; + root->left_son_ptr->need_push_down_to_right = true; + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(operation); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + root->need_push_down_to_left = false; + pthread_mutex_unlock(&working_flag_mutex); + } + } + if (root->need_push_down_to_right && root->right_son_ptr != nullptr) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->right_son_ptr) + { + root->right_son_ptr->tree_downsample_deleted |= root->tree_downsample_deleted; + root->right_son_ptr->point_downsample_deleted |= root->tree_downsample_deleted; + root->right_son_ptr->tree_deleted = root->tree_deleted || root->right_son_ptr->tree_downsample_deleted; + root->right_son_ptr->point_deleted = root->right_son_ptr->tree_deleted || root->right_son_ptr->point_downsample_deleted; + if (root->tree_downsample_deleted) + root->right_son_ptr->down_del_num = root->right_son_ptr->TreeSize; + if (root->tree_deleted) + root->right_son_ptr->invalid_point_num = root->right_son_ptr->TreeSize; + else + root->right_son_ptr->invalid_point_num = root->right_son_ptr->down_del_num; + root->right_son_ptr->need_push_down_to_left = true; + root->right_son_ptr->need_push_down_to_right = true; + root->need_push_down_to_right = false; + } + else + { + pthread_mutex_lock(&working_flag_mutex); + root->right_son_ptr->tree_downsample_deleted |= root->tree_downsample_deleted; + root->right_son_ptr->point_downsample_deleted |= root->tree_downsample_deleted; + root->right_son_ptr->tree_deleted = root->tree_deleted || root->right_son_ptr->tree_downsample_deleted; + root->right_son_ptr->point_deleted = root->right_son_ptr->tree_deleted || root->right_son_ptr->point_downsample_deleted; + if (root->tree_downsample_deleted) + root->right_son_ptr->down_del_num = root->right_son_ptr->TreeSize; + if (root->tree_deleted) + root->right_son_ptr->invalid_point_num = root->right_son_ptr->TreeSize; + else + root->right_son_ptr->invalid_point_num = root->right_son_ptr->down_del_num; + root->right_son_ptr->need_push_down_to_left = true; + root->right_son_ptr->need_push_down_to_right = true; + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(operation); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + root->need_push_down_to_right = false; + pthread_mutex_unlock(&working_flag_mutex); + } + } + return; +} + +template +void KD_TREE::Update(KD_TREE_NODE *root) +{ + KD_TREE_NODE *left_son_ptr = root->left_son_ptr; + KD_TREE_NODE *right_son_ptr = root->right_son_ptr; + float tmp_range_x[2] = {INFINITY, -INFINITY}; + float tmp_range_y[2] = {INFINITY, -INFINITY}; + float tmp_range_z[2] = {INFINITY, -INFINITY}; + // Update Tree Size + if (left_son_ptr != nullptr && right_son_ptr != nullptr) + { + root->TreeSize = left_son_ptr->TreeSize + right_son_ptr->TreeSize + 1; + root->invalid_point_num = left_son_ptr->invalid_point_num + right_son_ptr->invalid_point_num + (root->point_deleted ? 1 : 0); + root->down_del_num = left_son_ptr->down_del_num + right_son_ptr->down_del_num + (root->point_downsample_deleted ? 1 : 0); + root->tree_downsample_deleted = left_son_ptr->tree_downsample_deleted & right_son_ptr->tree_downsample_deleted & root->point_downsample_deleted; + root->tree_deleted = left_son_ptr->tree_deleted && right_son_ptr->tree_deleted && root->point_deleted; + if (root->tree_deleted || (!left_son_ptr->tree_deleted && !right_son_ptr->tree_deleted && !root->point_deleted)) + { + tmp_range_x[0] = min(min(left_son_ptr->node_range_x[0], right_son_ptr->node_range_x[0]), root->point.x); + tmp_range_x[1] = max(max(left_son_ptr->node_range_x[1], right_son_ptr->node_range_x[1]), root->point.x); + tmp_range_y[0] = min(min(left_son_ptr->node_range_y[0], right_son_ptr->node_range_y[0]), root->point.y); + tmp_range_y[1] = max(max(left_son_ptr->node_range_y[1], right_son_ptr->node_range_y[1]), root->point.y); + tmp_range_z[0] = min(min(left_son_ptr->node_range_z[0], right_son_ptr->node_range_z[0]), root->point.z); + tmp_range_z[1] = max(max(left_son_ptr->node_range_z[1], right_son_ptr->node_range_z[1]), root->point.z); + } + else + { + if (!left_son_ptr->tree_deleted) + { + tmp_range_x[0] = min(tmp_range_x[0], left_son_ptr->node_range_x[0]); + tmp_range_x[1] = max(tmp_range_x[1], left_son_ptr->node_range_x[1]); + tmp_range_y[0] = min(tmp_range_y[0], left_son_ptr->node_range_y[0]); + tmp_range_y[1] = max(tmp_range_y[1], left_son_ptr->node_range_y[1]); + tmp_range_z[0] = min(tmp_range_z[0], left_son_ptr->node_range_z[0]); + tmp_range_z[1] = max(tmp_range_z[1], left_son_ptr->node_range_z[1]); + } + if (!right_son_ptr->tree_deleted) + { + tmp_range_x[0] = min(tmp_range_x[0], right_son_ptr->node_range_x[0]); + tmp_range_x[1] = max(tmp_range_x[1], right_son_ptr->node_range_x[1]); + tmp_range_y[0] = min(tmp_range_y[0], right_son_ptr->node_range_y[0]); + tmp_range_y[1] = max(tmp_range_y[1], right_son_ptr->node_range_y[1]); + tmp_range_z[0] = min(tmp_range_z[0], right_son_ptr->node_range_z[0]); + tmp_range_z[1] = max(tmp_range_z[1], right_son_ptr->node_range_z[1]); + } + if (!root->point_deleted) + { + tmp_range_x[0] = min(tmp_range_x[0], root->point.x); + tmp_range_x[1] = max(tmp_range_x[1], root->point.x); + tmp_range_y[0] = min(tmp_range_y[0], root->point.y); + tmp_range_y[1] = max(tmp_range_y[1], root->point.y); + tmp_range_z[0] = min(tmp_range_z[0], root->point.z); + tmp_range_z[1] = max(tmp_range_z[1], root->point.z); + } + } + } + else if (left_son_ptr != nullptr) + { + root->TreeSize = left_son_ptr->TreeSize + 1; + root->invalid_point_num = left_son_ptr->invalid_point_num + (root->point_deleted ? 1 : 0); + root->down_del_num = left_son_ptr->down_del_num + (root->point_downsample_deleted ? 1 : 0); + root->tree_downsample_deleted = left_son_ptr->tree_downsample_deleted & root->point_downsample_deleted; + root->tree_deleted = left_son_ptr->tree_deleted && root->point_deleted; + if (root->tree_deleted || (!left_son_ptr->tree_deleted && !root->point_deleted)) + { + tmp_range_x[0] = min(left_son_ptr->node_range_x[0], root->point.x); + tmp_range_x[1] = max(left_son_ptr->node_range_x[1], root->point.x); + tmp_range_y[0] = min(left_son_ptr->node_range_y[0], root->point.y); + tmp_range_y[1] = max(left_son_ptr->node_range_y[1], root->point.y); + tmp_range_z[0] = min(left_son_ptr->node_range_z[0], root->point.z); + tmp_range_z[1] = max(left_son_ptr->node_range_z[1], root->point.z); + } + else + { + if (!left_son_ptr->tree_deleted) + { + tmp_range_x[0] = min(tmp_range_x[0], left_son_ptr->node_range_x[0]); + tmp_range_x[1] = max(tmp_range_x[1], left_son_ptr->node_range_x[1]); + tmp_range_y[0] = min(tmp_range_y[0], left_son_ptr->node_range_y[0]); + tmp_range_y[1] = max(tmp_range_y[1], left_son_ptr->node_range_y[1]); + tmp_range_z[0] = min(tmp_range_z[0], left_son_ptr->node_range_z[0]); + tmp_range_z[1] = max(tmp_range_z[1], left_son_ptr->node_range_z[1]); + } + if (!root->point_deleted) + { + tmp_range_x[0] = min(tmp_range_x[0], root->point.x); + tmp_range_x[1] = max(tmp_range_x[1], root->point.x); + tmp_range_y[0] = min(tmp_range_y[0], root->point.y); + tmp_range_y[1] = max(tmp_range_y[1], root->point.y); + tmp_range_z[0] = min(tmp_range_z[0], root->point.z); + tmp_range_z[1] = max(tmp_range_z[1], root->point.z); + } + } + } + else if (right_son_ptr != nullptr) + { + root->TreeSize = right_son_ptr->TreeSize + 1; + root->invalid_point_num = right_son_ptr->invalid_point_num + (root->point_deleted ? 1 : 0); + root->down_del_num = right_son_ptr->down_del_num + (root->point_downsample_deleted ? 1 : 0); + root->tree_downsample_deleted = right_son_ptr->tree_downsample_deleted & root->point_downsample_deleted; + root->tree_deleted = right_son_ptr->tree_deleted && root->point_deleted; + if (root->tree_deleted || (!right_son_ptr->tree_deleted && !root->point_deleted)) + { + tmp_range_x[0] = min(right_son_ptr->node_range_x[0], root->point.x); + tmp_range_x[1] = max(right_son_ptr->node_range_x[1], root->point.x); + tmp_range_y[0] = min(right_son_ptr->node_range_y[0], root->point.y); + tmp_range_y[1] = max(right_son_ptr->node_range_y[1], root->point.y); + tmp_range_z[0] = min(right_son_ptr->node_range_z[0], root->point.z); + tmp_range_z[1] = max(right_son_ptr->node_range_z[1], root->point.z); + } + else + { + if (!right_son_ptr->tree_deleted) + { + tmp_range_x[0] = min(tmp_range_x[0], right_son_ptr->node_range_x[0]); + tmp_range_x[1] = max(tmp_range_x[1], right_son_ptr->node_range_x[1]); + tmp_range_y[0] = min(tmp_range_y[0], right_son_ptr->node_range_y[0]); + tmp_range_y[1] = max(tmp_range_y[1], right_son_ptr->node_range_y[1]); + tmp_range_z[0] = min(tmp_range_z[0], right_son_ptr->node_range_z[0]); + tmp_range_z[1] = max(tmp_range_z[1], right_son_ptr->node_range_z[1]); + } + if (!root->point_deleted) + { + tmp_range_x[0] = min(tmp_range_x[0], root->point.x); + tmp_range_x[1] = max(tmp_range_x[1], root->point.x); + tmp_range_y[0] = min(tmp_range_y[0], root->point.y); + tmp_range_y[1] = max(tmp_range_y[1], root->point.y); + tmp_range_z[0] = min(tmp_range_z[0], root->point.z); + tmp_range_z[1] = max(tmp_range_z[1], root->point.z); + } + } + } + else + { + root->TreeSize = 1; + root->invalid_point_num = (root->point_deleted ? 1 : 0); + root->down_del_num = (root->point_downsample_deleted ? 1 : 0); + root->tree_downsample_deleted = root->point_downsample_deleted; + root->tree_deleted = root->point_deleted; + tmp_range_x[0] = root->point.x; + tmp_range_x[1] = root->point.x; + tmp_range_y[0] = root->point.y; + tmp_range_y[1] = root->point.y; + tmp_range_z[0] = root->point.z; + tmp_range_z[1] = root->point.z; + } + memcpy(root->node_range_x, tmp_range_x, sizeof(tmp_range_x)); + memcpy(root->node_range_y, tmp_range_y, sizeof(tmp_range_y)); + memcpy(root->node_range_z, tmp_range_z, sizeof(tmp_range_z)); + float x_L = (root->node_range_x[1] - root->node_range_x[0]) * 0.5; + float y_L = (root->node_range_y[1] - root->node_range_y[0]) * 0.5; + float z_L = (root->node_range_z[1] - root->node_range_z[0]) * 0.5; + root->radius_sq = x_L*x_L + y_L * y_L + z_L * z_L; + if (left_son_ptr != nullptr) + left_son_ptr->father_ptr = root; + if (right_son_ptr != nullptr) + right_son_ptr->father_ptr = root; + if (root == Root_Node && root->TreeSize > 3) + { + KD_TREE_NODE *son_ptr = root->left_son_ptr; + if (son_ptr == nullptr) + son_ptr = root->right_son_ptr; + float tmp_bal = float(son_ptr->TreeSize) / (root->TreeSize - 1); + root->alpha_del = float(root->invalid_point_num) / root->TreeSize; + root->alpha_bal = (tmp_bal >= 0.5 - EPSS) ? tmp_bal : 1 - tmp_bal; + } + return; +} + +template +void KD_TREE::flatten(KD_TREE_NODE *root, PointVector &Storage, delete_point_storage_set storage_type) +{ + if (root == nullptr) + return; + Push_Down(root); + if (!root->point_deleted) + { + Storage.push_back(root->point); + } + flatten(root->left_son_ptr, Storage, storage_type); + flatten(root->right_son_ptr, Storage, storage_type); + switch (storage_type) + { + case NOT_RECORD: + break; + case DELETE_POINTS_REC: + if (root->point_deleted && !root->point_downsample_deleted) + { + Points_deleted.push_back(root->point); + } + break; + case MULTI_THREAD_REC: + if (root->point_deleted && !root->point_downsample_deleted) + { + Multithread_Points_deleted.push_back(root->point); + } + break; + default: + break; + } + return; +} + +template +void KD_TREE::delete_tree_nodes(KD_TREE_NODE **root) +{ + if (*root == nullptr) + return; + Push_Down(*root); + delete_tree_nodes(&(*root)->left_son_ptr); + delete_tree_nodes(&(*root)->right_son_ptr); + + pthread_mutex_destroy(&(*root)->push_down_mutex_lock); + delete *root; + *root = nullptr; + + return; +} + +template +bool KD_TREE::same_point(PointType a, PointType b) +{ + return (fabs(a.x - b.x) < EPSS && fabs(a.y - b.y) < EPSS && fabs(a.z - b.z) < EPSS); +} + +template +float KD_TREE::calc_dist(PointType a, PointType b) +{ + float dist = 0.0f; + dist = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z); + return dist; +} + +template +float KD_TREE::calc_box_dist(KD_TREE_NODE *node, PointType point) +{ + if (node == nullptr) + return INFINITY; + float min_dist = 0.0; + if (point.x < node->node_range_x[0]) + min_dist += (point.x - node->node_range_x[0]) * (point.x - node->node_range_x[0]); + if (point.x > node->node_range_x[1]) + min_dist += (point.x - node->node_range_x[1]) * (point.x - node->node_range_x[1]); + if (point.y < node->node_range_y[0]) + min_dist += (point.y - node->node_range_y[0]) * (point.y - node->node_range_y[0]); + if (point.y > node->node_range_y[1]) + min_dist += (point.y - node->node_range_y[1]) * (point.y - node->node_range_y[1]); + if (point.z < node->node_range_z[0]) + min_dist += (point.z - node->node_range_z[0]) * (point.z - node->node_range_z[0]); + if (point.z > node->node_range_z[1]) + min_dist += (point.z - node->node_range_z[1]) * (point.z - node->node_range_z[1]); + return min_dist; +} +template +bool KD_TREE::point_cmp_x(PointType a, PointType b) { return a.x < b.x; } +template +bool KD_TREE::point_cmp_y(PointType a, PointType b) { return a.y < b.y; } +template +bool KD_TREE::point_cmp_z(PointType a, PointType b) { return a.z < b.z; } + +// Manual heap + + + +// manual queue + + +// Manual Instatiations +template class KD_TREE; +template class KD_TREE; +template class KD_TREE; + diff --git a/FAST_LIO/include/ikd-Tree/ikd_Tree.h b/FAST_LIO/include/ikd-Tree/ikd_Tree.h new file mode 100644 index 0000000..d4b302e --- /dev/null +++ b/FAST_LIO/include/ikd-Tree/ikd_Tree.h @@ -0,0 +1,344 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EPSS 1e-6 +#define Minimal_Unbalanced_Tree_Size 10 +#define Multi_Thread_Rebuild_Point_Num 1500 +#define DOWNSAMPLE_SWITCH true +#define ForceRebuildPercentage 0.2 +#define Q_LEN 1000000 + +using namespace std; + +// typedef pcl::PointXYZINormal PointType; +// typedef vector> PointVector; + +struct BoxPointType +{ + float vertex_min[3]; + float vertex_max[3]; +}; + +enum operation_set +{ + ADD_POINT, + DELETE_POINT, + DELETE_BOX, + ADD_BOX, + DOWNSAMPLE_DELETE, + PUSH_DOWN +}; + +enum delete_point_storage_set +{ + NOT_RECORD, + DELETE_POINTS_REC, + MULTI_THREAD_REC +}; + +template +class KD_TREE +{ + // using MANUAL_Q_ = MANUAL_Q; + // using PointVector = std::vector; + + // using MANUAL_Q_ = MANUAL_Q; +public: + using PointVector = std::vector>; + using Ptr = std::shared_ptr>; + + struct KD_TREE_NODE + { + PointType point; + int division_axis; + int TreeSize = 1; + int invalid_point_num = 0; + int down_del_num = 0; + bool point_deleted = false; + bool tree_deleted = false; + bool point_downsample_deleted = false; + bool tree_downsample_deleted = false; + bool need_push_down_to_left = false; + bool need_push_down_to_right = false; + bool working_flag = false; + pthread_mutex_t push_down_mutex_lock; + float node_range_x[2], node_range_y[2], node_range_z[2]; + float radius_sq; + KD_TREE_NODE *left_son_ptr = nullptr; + KD_TREE_NODE *right_son_ptr = nullptr; + KD_TREE_NODE *father_ptr = nullptr; + // For paper data record + float alpha_del; + float alpha_bal; + }; + + struct Operation_Logger_Type + { + PointType point; + BoxPointType boxpoint; + bool tree_deleted, tree_downsample_deleted; + operation_set op; + }; + // static const PointType zeroP; + + struct PointType_CMP + { + PointType point; + float dist = 0.0; + PointType_CMP(PointType p = PointType(), float d = INFINITY) + { + this->point = p; + this->dist = d; + }; + bool operator<(const PointType_CMP &a) const + { + if (fabs(dist - a.dist) < 1e-10) + return point.x < a.point.x; + else + return dist < a.dist; + } + }; + + class MANUAL_HEAP + { + + public: + MANUAL_HEAP(int max_capacity = 100) + + { + cap = max_capacity; + heap = new PointType_CMP[max_capacity]; + heap_size = 0; + } + + ~MANUAL_HEAP() + { + delete[] heap; + } + void pop() + { + if (heap_size == 0) + return; + heap[0] = heap[heap_size - 1]; + heap_size--; + MoveDown(0); + return; + } + PointType_CMP top() + { + return heap[0]; + } + void push(PointType_CMP point) + { + if (heap_size >= cap) + return; + heap[heap_size] = point; + FloatUp(heap_size); + heap_size++; + return; + } + int size() + { + return heap_size; + } + void clear() + { + heap_size = 0; + return; + } + + private: + PointType_CMP *heap; + void MoveDown(int heap_index) + { + int l = heap_index * 2 + 1; + PointType_CMP tmp = heap[heap_index]; + while (l < heap_size) + { + if (l + 1 < heap_size && heap[l] < heap[l + 1]) + l++; + if (tmp < heap[l]) + { + heap[heap_index] = heap[l]; + heap_index = l; + l = heap_index * 2 + 1; + } + else + break; + } + heap[heap_index] = tmp; + return; + } + void FloatUp(int heap_index) + { + int ancestor = (heap_index - 1) / 2; + PointType_CMP tmp = heap[heap_index]; + while (heap_index > 0) + { + if (heap[ancestor] < tmp) + { + heap[heap_index] = heap[ancestor]; + heap_index = ancestor; + ancestor = (heap_index - 1) / 2; + } + else + break; + } + heap[heap_index] = tmp; + return; + } + int heap_size = 0; + int cap = 0; + }; + + class MANUAL_Q + { + private: + int head = 0, tail = 0, counter = 0; + Operation_Logger_Type q[Q_LEN]; + bool is_empty; + + public: + void pop() + { + if (counter == 0) + return; + head++; + head %= Q_LEN; + counter--; + if (counter == 0) + is_empty = true; + return; + } + Operation_Logger_Type front() + { + return q[head]; + } + Operation_Logger_Type back() + { + return q[tail]; + } + void clear() + { + head = 0; + tail = 0; + counter = 0; + is_empty = true; + return; + } + void push(Operation_Logger_Type op) + { + q[tail] = op; + counter++; + if (is_empty) + is_empty = false; + tail++; + tail %= Q_LEN; + } + bool empty() + { + return is_empty; + } + int size() + { + return counter; + } + }; + +private: + // Multi-thread Tree Rebuild + bool termination_flag = false; + bool rebuild_flag = false; + pthread_t rebuild_thread; + pthread_mutex_t termination_flag_mutex_lock, rebuild_ptr_mutex_lock, working_flag_mutex, search_flag_mutex; + pthread_mutex_t rebuild_logger_mutex_lock, points_deleted_rebuild_mutex_lock; + // queue Rebuild_Logger; + MANUAL_Q Rebuild_Logger; + PointVector Rebuild_PCL_Storage; + KD_TREE_NODE **Rebuild_Ptr = nullptr; + int search_mutex_counter = 0; + static void *multi_thread_ptr(void *arg); + void multi_thread_rebuild(); + void start_thread(); + void stop_thread(); + void run_operation(KD_TREE_NODE **root, Operation_Logger_Type operation); + // KD Tree Functions and augmented variables + int Treesize_tmp = 0, Validnum_tmp = 0; + float alpha_bal_tmp = 0.5, alpha_del_tmp = 0.0; + float delete_criterion_param = 0.5f; + float balance_criterion_param = 0.7f; + float downsample_size = 0.2f; + bool Delete_Storage_Disabled = false; + KD_TREE_NODE *STATIC_ROOT_NODE = nullptr; + PointVector Points_deleted; + PointVector Downsample_Storage; + PointVector Multithread_Points_deleted; + void InitTreeNode(KD_TREE_NODE *root); + void Test_Lock_States(KD_TREE_NODE *root); + void BuildTree(KD_TREE_NODE **root, int l, int r, PointVector &Storage); + void Rebuild(KD_TREE_NODE **root); + int Delete_by_range(KD_TREE_NODE **root, BoxPointType boxpoint, bool allow_rebuild, bool is_downsample); + void Delete_by_point(KD_TREE_NODE **root, PointType point, bool allow_rebuild); + void Add_by_point(KD_TREE_NODE **root, PointType point, bool allow_rebuild, int father_axis); + void Add_by_range(KD_TREE_NODE **root, BoxPointType boxpoint, bool allow_rebuild); + void Search(KD_TREE_NODE *root, int k_nearest, PointType point, MANUAL_HEAP &q, float max_dist); //priority_queue + void Search_by_range(KD_TREE_NODE *root, BoxPointType boxpoint, PointVector &Storage); + void Search_by_radius(KD_TREE_NODE *root, PointType point, float radius, PointVector &Storage); + bool Criterion_Check(KD_TREE_NODE *root); + void Push_Down(KD_TREE_NODE *root); + void Update(KD_TREE_NODE *root); + void delete_tree_nodes(KD_TREE_NODE **root); + void downsample(KD_TREE_NODE **root); + bool same_point(PointType a, PointType b); + float calc_dist(PointType a, PointType b); + float calc_box_dist(KD_TREE_NODE *node, PointType point); + static bool point_cmp_x(PointType a, PointType b); + static bool point_cmp_y(PointType a, PointType b); + static bool point_cmp_z(PointType a, PointType b); + +public: + KD_TREE(float delete_param = 0.5, float balance_param = 0.6, float box_length = 0.2); + ~KD_TREE(); + void Set_delete_criterion_param(float delete_param) + { + delete_criterion_param = delete_param; + } + void Set_balance_criterion_param(float balance_param) + { + balance_criterion_param = balance_param; + } + void set_downsample_param(float downsample_param) + { + downsample_size = downsample_param; + } + void InitializeKDTree(float delete_param = 0.5, float balance_param = 0.7, float box_length = 0.2); + int size(); + int validnum(); + void root_alpha(float &alpha_bal, float &alpha_del); + void Build(PointVector point_cloud); + void Nearest_Search(PointType point, int k_nearest, PointVector &Nearest_Points, vector &Point_Distance, float max_dist = INFINITY); + void Box_Search(const BoxPointType &Box_of_Point, PointVector &Storage); + void Radius_Search(PointType point, const float radius, PointVector &Storage); + int Add_Points(PointVector &PointToAdd, bool downsample_on); + void Add_Point_Boxes(vector &BoxPoints); + void Delete_Points(PointVector &PointToDel); + int Delete_Point_Boxes(vector &BoxPoints); + void flatten(KD_TREE_NODE *root, PointVector &Storage, delete_point_storage_set storage_type); + void acquire_removed_points(PointVector &removed_points); + BoxPointType tree_range(); + PointVector PCL_Storage; + KD_TREE_NODE *Root_Node = nullptr; + int max_queue_size = 0; +}; + +// template +// PointType KD_TREE::zeroP = PointType(0,0,0); diff --git a/FAST_LIO/include/matplotlibcpp.h b/FAST_LIO/include/matplotlibcpp.h new file mode 100644 index 0000000..6855445 --- /dev/null +++ b/FAST_LIO/include/matplotlibcpp.h @@ -0,0 +1,2499 @@ +#pragma once + +// Python headers must be included before any system headers, since +// they define _POSIX_C_SOURCE +#include + +#include +#include +#include +#include +#include +#include +#include +#include // requires c++11 support +#include + +#ifndef WITHOUT_NUMPY +# define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +# include + +# ifdef WITH_OPENCV +# include +# endif // WITH_OPENCV + +/* + * A bunch of constants were removed in OpenCV 4 in favour of enum classes, so + * define the ones we need here. + */ +# if CV_MAJOR_VERSION > 3 +# define CV_BGR2RGB cv::COLOR_BGR2RGB +# define CV_BGRA2RGBA cv::COLOR_BGRA2RGBA +# endif +#endif // WITHOUT_NUMPY + +#if PY_MAJOR_VERSION >= 3 +# define PyString_FromString PyUnicode_FromString +# define PyInt_FromLong PyLong_FromLong +# define PyString_FromString PyUnicode_FromString +#endif + + +namespace matplotlibcpp { +namespace detail { + +static std::string s_backend; + +struct _interpreter { + PyObject* s_python_function_arrow; + PyObject *s_python_function_show; + PyObject *s_python_function_close; + PyObject *s_python_function_draw; + PyObject *s_python_function_pause; + PyObject *s_python_function_save; + PyObject *s_python_function_figure; + PyObject *s_python_function_fignum_exists; + PyObject *s_python_function_plot; + PyObject *s_python_function_quiver; + PyObject* s_python_function_contour; + PyObject *s_python_function_semilogx; + PyObject *s_python_function_semilogy; + PyObject *s_python_function_loglog; + PyObject *s_python_function_fill; + PyObject *s_python_function_fill_between; + PyObject *s_python_function_hist; + PyObject *s_python_function_imshow; + PyObject *s_python_function_scatter; + PyObject *s_python_function_boxplot; + PyObject *s_python_function_subplot; + PyObject *s_python_function_subplot2grid; + PyObject *s_python_function_legend; + PyObject *s_python_function_xlim; + PyObject *s_python_function_ion; + PyObject *s_python_function_ginput; + PyObject *s_python_function_ylim; + PyObject *s_python_function_title; + PyObject *s_python_function_axis; + PyObject *s_python_function_axvline; + PyObject *s_python_function_axvspan; + PyObject *s_python_function_xlabel; + PyObject *s_python_function_ylabel; + PyObject *s_python_function_gca; + PyObject *s_python_function_xticks; + PyObject *s_python_function_yticks; + PyObject* s_python_function_margins; + PyObject *s_python_function_tick_params; + PyObject *s_python_function_grid; + PyObject* s_python_function_cla; + PyObject *s_python_function_clf; + PyObject *s_python_function_errorbar; + PyObject *s_python_function_annotate; + PyObject *s_python_function_tight_layout; + PyObject *s_python_colormap; + PyObject *s_python_empty_tuple; + PyObject *s_python_function_stem; + PyObject *s_python_function_xkcd; + PyObject *s_python_function_text; + PyObject *s_python_function_suptitle; + PyObject *s_python_function_bar; + PyObject *s_python_function_colorbar; + PyObject *s_python_function_subplots_adjust; + + + /* For now, _interpreter is implemented as a singleton since its currently not possible to have + multiple independent embedded python interpreters without patching the python source code + or starting a separate process for each. + http://bytes.com/topic/python/answers/793370-multiple-independent-python-interpreters-c-c-program + */ + + static _interpreter& get() { + static _interpreter ctx; + return ctx; + } + + PyObject* safe_import(PyObject* module, std::string fname) { + PyObject* fn = PyObject_GetAttrString(module, fname.c_str()); + + if (!fn) + throw std::runtime_error(std::string("Couldn't find required function: ") + fname); + + if (!PyFunction_Check(fn)) + throw std::runtime_error(fname + std::string(" is unexpectedly not a PyFunction.")); + + return fn; + } + +private: + +#ifndef WITHOUT_NUMPY +# if PY_MAJOR_VERSION >= 3 + + void *import_numpy() { + import_array(); // initialize C-API + return NULL; + } + +# else + + void import_numpy() { + import_array(); // initialize C-API + } + +# endif +#endif + + _interpreter() { + + // optional but recommended +#if PY_MAJOR_VERSION >= 3 + wchar_t name[] = L"plotting"; +#else + char name[] = "plotting"; +#endif + Py_SetProgramName(name); + Py_Initialize(); + +#ifndef WITHOUT_NUMPY + import_numpy(); // initialize numpy C-API +#endif + + PyObject* matplotlibname = PyString_FromString("matplotlib"); + PyObject* pyplotname = PyString_FromString("matplotlib.pyplot"); + PyObject* cmname = PyString_FromString("matplotlib.cm"); + PyObject* pylabname = PyString_FromString("pylab"); + if (!pyplotname || !pylabname || !matplotlibname || !cmname) { + throw std::runtime_error("couldnt create string"); + } + + PyObject* matplotlib = PyImport_Import(matplotlibname); + Py_DECREF(matplotlibname); + if (!matplotlib) { + PyErr_Print(); + throw std::runtime_error("Error loading module matplotlib!"); + } + + // matplotlib.use() must be called *before* pylab, matplotlib.pyplot, + // or matplotlib.backends is imported for the first time + if (!s_backend.empty()) { + PyObject_CallMethod(matplotlib, const_cast("use"), const_cast("s"), s_backend.c_str()); + } + + PyObject* pymod = PyImport_Import(pyplotname); + Py_DECREF(pyplotname); + if (!pymod) { throw std::runtime_error("Error loading module matplotlib.pyplot!"); } + + s_python_colormap = PyImport_Import(cmname); + Py_DECREF(cmname); + if (!s_python_colormap) { throw std::runtime_error("Error loading module matplotlib.cm!"); } + + PyObject* pylabmod = PyImport_Import(pylabname); + Py_DECREF(pylabname); + if (!pylabmod) { throw std::runtime_error("Error loading module pylab!"); } + + s_python_function_arrow = safe_import(pymod, "arrow"); + s_python_function_show = safe_import(pymod, "show"); + s_python_function_close = safe_import(pymod, "close"); + s_python_function_draw = safe_import(pymod, "draw"); + s_python_function_pause = safe_import(pymod, "pause"); + s_python_function_figure = safe_import(pymod, "figure"); + s_python_function_fignum_exists = safe_import(pymod, "fignum_exists"); + s_python_function_plot = safe_import(pymod, "plot"); + s_python_function_quiver = safe_import(pymod, "quiver"); + s_python_function_contour = safe_import(pymod, "contour"); + s_python_function_semilogx = safe_import(pymod, "semilogx"); + s_python_function_semilogy = safe_import(pymod, "semilogy"); + s_python_function_loglog = safe_import(pymod, "loglog"); + s_python_function_fill = safe_import(pymod, "fill"); + s_python_function_fill_between = safe_import(pymod, "fill_between"); + s_python_function_hist = safe_import(pymod,"hist"); + s_python_function_scatter = safe_import(pymod,"scatter"); + s_python_function_boxplot = safe_import(pymod,"boxplot"); + s_python_function_subplot = safe_import(pymod, "subplot"); + s_python_function_subplot2grid = safe_import(pymod, "subplot2grid"); + s_python_function_legend = safe_import(pymod, "legend"); + s_python_function_ylim = safe_import(pymod, "ylim"); + s_python_function_title = safe_import(pymod, "title"); + s_python_function_axis = safe_import(pymod, "axis"); + s_python_function_axvline = safe_import(pymod, "axvline"); + s_python_function_axvspan = safe_import(pymod, "axvspan"); + s_python_function_xlabel = safe_import(pymod, "xlabel"); + s_python_function_ylabel = safe_import(pymod, "ylabel"); + s_python_function_gca = safe_import(pymod, "gca"); + s_python_function_xticks = safe_import(pymod, "xticks"); + s_python_function_yticks = safe_import(pymod, "yticks"); + s_python_function_margins = safe_import(pymod, "margins"); + s_python_function_tick_params = safe_import(pymod, "tick_params"); + s_python_function_grid = safe_import(pymod, "grid"); + s_python_function_xlim = safe_import(pymod, "xlim"); + s_python_function_ion = safe_import(pymod, "ion"); + s_python_function_ginput = safe_import(pymod, "ginput"); + s_python_function_save = safe_import(pylabmod, "savefig"); + s_python_function_annotate = safe_import(pymod,"annotate"); + s_python_function_cla = safe_import(pymod, "cla"); + s_python_function_clf = safe_import(pymod, "clf"); + s_python_function_errorbar = safe_import(pymod, "errorbar"); + s_python_function_tight_layout = safe_import(pymod, "tight_layout"); + s_python_function_stem = safe_import(pymod, "stem"); + s_python_function_xkcd = safe_import(pymod, "xkcd"); + s_python_function_text = safe_import(pymod, "text"); + s_python_function_suptitle = safe_import(pymod, "suptitle"); + s_python_function_bar = safe_import(pymod,"bar"); + s_python_function_colorbar = PyObject_GetAttrString(pymod, "colorbar"); + s_python_function_subplots_adjust = safe_import(pymod,"subplots_adjust"); +#ifndef WITHOUT_NUMPY + s_python_function_imshow = safe_import(pymod, "imshow"); +#endif + s_python_empty_tuple = PyTuple_New(0); + } + + ~_interpreter() { + Py_Finalize(); + } +}; + +} // end namespace detail + +/// Select the backend +/// +/// **NOTE:** This must be called before the first plot command to have +/// any effect. +/// +/// Mainly useful to select the non-interactive 'Agg' backend when running +/// matplotlibcpp in headless mode, for example on a machine with no display. +/// +/// See also: https://matplotlib.org/2.0.2/api/matplotlib_configuration_api.html#matplotlib.use +inline void backend(const std::string& name) +{ + detail::s_backend = name; +} + +inline bool annotate(std::string annotation, double x, double y) +{ + detail::_interpreter::get(); + + PyObject * xy = PyTuple_New(2); + PyObject * str = PyString_FromString(annotation.c_str()); + + PyTuple_SetItem(xy,0,PyFloat_FromDouble(x)); + PyTuple_SetItem(xy,1,PyFloat_FromDouble(y)); + + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "xy", xy); + + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, str); + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_annotate, args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + + if(res) Py_DECREF(res); + + return res; +} + +namespace detail { + +#ifndef WITHOUT_NUMPY +// Type selector for numpy array conversion +template struct select_npy_type { const static NPY_TYPES type = NPY_NOTYPE; }; //Default +template <> struct select_npy_type { const static NPY_TYPES type = NPY_DOUBLE; }; +template <> struct select_npy_type { const static NPY_TYPES type = NPY_FLOAT; }; +template <> struct select_npy_type { const static NPY_TYPES type = NPY_BOOL; }; +template <> struct select_npy_type { const static NPY_TYPES type = NPY_INT8; }; +template <> struct select_npy_type { const static NPY_TYPES type = NPY_SHORT; }; +template <> struct select_npy_type { const static NPY_TYPES type = NPY_INT; }; +template <> struct select_npy_type { const static NPY_TYPES type = NPY_INT64; }; +template <> struct select_npy_type { const static NPY_TYPES type = NPY_UINT8; }; +template <> struct select_npy_type { const static NPY_TYPES type = NPY_USHORT; }; +template <> struct select_npy_type { const static NPY_TYPES type = NPY_ULONG; }; +template <> struct select_npy_type { const static NPY_TYPES type = NPY_UINT64; }; + +// Sanity checks; comment them out or change the numpy type below if you're compiling on +// a platform where they don't apply +static_assert(sizeof(long long) == 8); +template <> struct select_npy_type { const static NPY_TYPES type = NPY_INT64; }; +static_assert(sizeof(unsigned long long) == 8); +template <> struct select_npy_type { const static NPY_TYPES type = NPY_UINT64; }; +// TODO: add int, long, etc. + +template +PyObject* get_array(const std::vector& v) +{ + npy_intp vsize = v.size(); + NPY_TYPES type = select_npy_type::type; + if (type == NPY_NOTYPE) { + size_t memsize = v.size()*sizeof(double); + double* dp = static_cast(::malloc(memsize)); + for (size_t i=0; i(varray), NPY_ARRAY_OWNDATA); + return varray; + } + + PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, type, (void*)(v.data())); + return varray; +} + + +template +PyObject* get_2darray(const std::vector<::std::vector>& v) +{ + if (v.size() < 1) throw std::runtime_error("get_2d_array v too small"); + + npy_intp vsize[2] = {static_cast(v.size()), + static_cast(v[0].size())}; + + PyArrayObject *varray = + (PyArrayObject *)PyArray_SimpleNew(2, vsize, NPY_DOUBLE); + + double *vd_begin = static_cast(PyArray_DATA(varray)); + + for (const ::std::vector &v_row : v) { + if (v_row.size() != static_cast(vsize[1])) + throw std::runtime_error("Missmatched array size"); + std::copy(v_row.begin(), v_row.end(), vd_begin); + vd_begin += vsize[1]; + } + + return reinterpret_cast(varray); +} + +#else // fallback if we don't have numpy: copy every element of the given vector + +template +PyObject* get_array(const std::vector& v) +{ + PyObject* list = PyList_New(v.size()); + for(size_t i = 0; i < v.size(); ++i) { + PyList_SetItem(list, i, PyFloat_FromDouble(v.at(i))); + } + return list; +} + +#endif // WITHOUT_NUMPY + +// sometimes, for labels and such, we need string arrays +inline PyObject * get_array(const std::vector& strings) +{ + PyObject* list = PyList_New(strings.size()); + for (std::size_t i = 0; i < strings.size(); ++i) { + PyList_SetItem(list, i, PyString_FromString(strings[i].c_str())); + } + return list; +} + +// not all matplotlib need 2d arrays, some prefer lists of lists +template +PyObject* get_listlist(const std::vector>& ll) +{ + PyObject* listlist = PyList_New(ll.size()); + for (std::size_t i = 0; i < ll.size(); ++i) { + PyList_SetItem(listlist, i, get_array(ll[i])); + } + return listlist; +} + +} // namespace detail + +/// Plot a line through the given x and y data points.. +/// +/// See: https://matplotlib.org/3.2.1/api/_as_gen/matplotlib.pyplot.plot.html +template +bool plot(const std::vector &x, const std::vector &y, const std::map& keywords) +{ + assert(x.size() == y.size()); + + detail::_interpreter::get(); + + // using numpy arrays + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + // construct positional args + PyObject* args = PyTuple_New(2); + PyTuple_SetItem(args, 0, xarray); + PyTuple_SetItem(args, 1, yarray); + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for(std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) + { + PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + if(res) Py_DECREF(res); + + return res; +} + +// TODO - it should be possible to make this work by implementing +// a non-numpy alternative for `detail::get_2darray()`. +#ifndef WITHOUT_NUMPY +template +void plot_surface(const std::vector<::std::vector> &x, + const std::vector<::std::vector> &y, + const std::vector<::std::vector> &z, + const std::map &keywords = + std::map()) +{ + detail::_interpreter::get(); + + // We lazily load the modules here the first time this function is called + // because I'm not sure that we can assume "matplotlib installed" implies + // "mpl_toolkits installed" on all platforms, and we don't want to require + // it for people who don't need 3d plots. + static PyObject *mpl_toolkitsmod = nullptr, *axis3dmod = nullptr; + if (!mpl_toolkitsmod) { + detail::_interpreter::get(); + + PyObject* mpl_toolkits = PyString_FromString("mpl_toolkits"); + PyObject* axis3d = PyString_FromString("mpl_toolkits.mplot3d"); + if (!mpl_toolkits || !axis3d) { throw std::runtime_error("couldnt create string"); } + + mpl_toolkitsmod = PyImport_Import(mpl_toolkits); + Py_DECREF(mpl_toolkits); + if (!mpl_toolkitsmod) { throw std::runtime_error("Error loading module mpl_toolkits!"); } + + axis3dmod = PyImport_Import(axis3d); + Py_DECREF(axis3d); + if (!axis3dmod) { throw std::runtime_error("Error loading module mpl_toolkits.mplot3d!"); } + } + + assert(x.size() == y.size()); + assert(y.size() == z.size()); + + // using numpy arrays + PyObject *xarray = detail::get_2darray(x); + PyObject *yarray = detail::get_2darray(y); + PyObject *zarray = detail::get_2darray(z); + + // construct positional args + PyObject *args = PyTuple_New(3); + PyTuple_SetItem(args, 0, xarray); + PyTuple_SetItem(args, 1, yarray); + PyTuple_SetItem(args, 2, zarray); + + // Build up the kw args. + PyObject *kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "rstride", PyInt_FromLong(1)); + PyDict_SetItemString(kwargs, "cstride", PyInt_FromLong(1)); + + PyObject *python_colormap_coolwarm = PyObject_GetAttrString( + detail::_interpreter::get().s_python_colormap, "coolwarm"); + + PyDict_SetItemString(kwargs, "cmap", python_colormap_coolwarm); + + for (std::map::const_iterator it = keywords.begin(); + it != keywords.end(); ++it) { + PyDict_SetItemString(kwargs, it->first.c_str(), + PyString_FromString(it->second.c_str())); + } + + + PyObject *fig = + PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, + detail::_interpreter::get().s_python_empty_tuple); + if (!fig) throw std::runtime_error("Call to figure() failed."); + + PyObject *gca_kwargs = PyDict_New(); + PyDict_SetItemString(gca_kwargs, "projection", PyString_FromString("3d")); + + PyObject *gca = PyObject_GetAttrString(fig, "gca"); + if (!gca) throw std::runtime_error("No gca"); + Py_INCREF(gca); + PyObject *axis = PyObject_Call( + gca, detail::_interpreter::get().s_python_empty_tuple, gca_kwargs); + + if (!axis) throw std::runtime_error("No axis"); + Py_INCREF(axis); + + Py_DECREF(gca); + Py_DECREF(gca_kwargs); + + PyObject *plot_surface = PyObject_GetAttrString(axis, "plot_surface"); + if (!plot_surface) throw std::runtime_error("No surface"); + Py_INCREF(plot_surface); + PyObject *res = PyObject_Call(plot_surface, args, kwargs); + if (!res) throw std::runtime_error("failed surface"); + Py_DECREF(plot_surface); + + Py_DECREF(axis); + Py_DECREF(args); + Py_DECREF(kwargs); + if (res) Py_DECREF(res); +} +#endif // WITHOUT_NUMPY + +template +void plot3(const std::vector &x, + const std::vector &y, + const std::vector &z, + const std::map &keywords = + std::map()) +{ + detail::_interpreter::get(); + + // Same as with plot_surface: We lazily load the modules here the first time + // this function is called because I'm not sure that we can assume "matplotlib + // installed" implies "mpl_toolkits installed" on all platforms, and we don't + // want to require it for people who don't need 3d plots. + static PyObject *mpl_toolkitsmod = nullptr, *axis3dmod = nullptr; + if (!mpl_toolkitsmod) { + detail::_interpreter::get(); + + PyObject* mpl_toolkits = PyString_FromString("mpl_toolkits"); + PyObject* axis3d = PyString_FromString("mpl_toolkits.mplot3d"); + if (!mpl_toolkits || !axis3d) { throw std::runtime_error("couldnt create string"); } + + mpl_toolkitsmod = PyImport_Import(mpl_toolkits); + Py_DECREF(mpl_toolkits); + if (!mpl_toolkitsmod) { throw std::runtime_error("Error loading module mpl_toolkits!"); } + + axis3dmod = PyImport_Import(axis3d); + Py_DECREF(axis3d); + if (!axis3dmod) { throw std::runtime_error("Error loading module mpl_toolkits.mplot3d!"); } + } + + assert(x.size() == y.size()); + assert(y.size() == z.size()); + + PyObject *xarray = detail::get_array(x); + PyObject *yarray = detail::get_array(y); + PyObject *zarray = detail::get_array(z); + + // construct positional args + PyObject *args = PyTuple_New(3); + PyTuple_SetItem(args, 0, xarray); + PyTuple_SetItem(args, 1, yarray); + PyTuple_SetItem(args, 2, zarray); + + // Build up the kw args. + PyObject *kwargs = PyDict_New(); + + for (std::map::const_iterator it = keywords.begin(); + it != keywords.end(); ++it) { + PyDict_SetItemString(kwargs, it->first.c_str(), + PyString_FromString(it->second.c_str())); + } + + PyObject *fig = + PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, + detail::_interpreter::get().s_python_empty_tuple); + if (!fig) throw std::runtime_error("Call to figure() failed."); + + PyObject *gca_kwargs = PyDict_New(); + PyDict_SetItemString(gca_kwargs, "projection", PyString_FromString("3d")); + + PyObject *gca = PyObject_GetAttrString(fig, "gca"); + if (!gca) throw std::runtime_error("No gca"); + Py_INCREF(gca); + PyObject *axis = PyObject_Call( + gca, detail::_interpreter::get().s_python_empty_tuple, gca_kwargs); + + if (!axis) throw std::runtime_error("No axis"); + Py_INCREF(axis); + + Py_DECREF(gca); + Py_DECREF(gca_kwargs); + + PyObject *plot3 = PyObject_GetAttrString(axis, "plot"); + if (!plot3) throw std::runtime_error("No 3D line plot"); + Py_INCREF(plot3); + PyObject *res = PyObject_Call(plot3, args, kwargs); + if (!res) throw std::runtime_error("Failed 3D line plot"); + Py_DECREF(plot3); + + Py_DECREF(axis); + Py_DECREF(args); + Py_DECREF(kwargs); + if (res) Py_DECREF(res); +} + +template +bool stem(const std::vector &x, const std::vector &y, const std::map& keywords) +{ + assert(x.size() == y.size()); + + detail::_interpreter::get(); + + // using numpy arrays + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + // construct positional args + PyObject* args = PyTuple_New(2); + PyTuple_SetItem(args, 0, xarray); + PyTuple_SetItem(args, 1, yarray); + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for (std::map::const_iterator it = + keywords.begin(); it != keywords.end(); ++it) { + PyDict_SetItemString(kwargs, it->first.c_str(), + PyString_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call( + detail::_interpreter::get().s_python_function_stem, args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + if (res) + Py_DECREF(res); + + return res; +} + +template< typename Numeric > +bool fill(const std::vector& x, const std::vector& y, const std::map& keywords) +{ + assert(x.size() == y.size()); + + detail::_interpreter::get(); + + // using numpy arrays + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + // construct positional args + PyObject* args = PyTuple_New(2); + PyTuple_SetItem(args, 0, xarray); + PyTuple_SetItem(args, 1, yarray); + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for (auto it = keywords.begin(); it != keywords.end(); ++it) { + PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_fill, args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + + if (res) Py_DECREF(res); + + return res; +} + +template< typename Numeric > +bool fill_between(const std::vector& x, const std::vector& y1, const std::vector& y2, const std::map& keywords) +{ + assert(x.size() == y1.size()); + assert(x.size() == y2.size()); + + detail::_interpreter::get(); + + // using numpy arrays + PyObject* xarray = detail::get_array(x); + PyObject* y1array = detail::get_array(y1); + PyObject* y2array = detail::get_array(y2); + + // construct positional args + PyObject* args = PyTuple_New(3); + PyTuple_SetItem(args, 0, xarray); + PyTuple_SetItem(args, 1, y1array); + PyTuple_SetItem(args, 2, y2array); + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for(std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) { + PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_fill_between, args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + if(res) Py_DECREF(res); + + return res; +} + +template +bool arrow(Numeric x, Numeric y, Numeric end_x, Numeric end_y, const std::string& fc = "r", + const std::string ec = "k", Numeric head_length = 0.25, Numeric head_width = 0.1625) { + PyObject* obj_x = PyFloat_FromDouble(x); + PyObject* obj_y = PyFloat_FromDouble(y); + PyObject* obj_end_x = PyFloat_FromDouble(end_x); + PyObject* obj_end_y = PyFloat_FromDouble(end_y); + + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "fc", PyString_FromString(fc.c_str())); + PyDict_SetItemString(kwargs, "ec", PyString_FromString(ec.c_str())); + PyDict_SetItemString(kwargs, "head_width", PyFloat_FromDouble(head_width)); + PyDict_SetItemString(kwargs, "head_length", PyFloat_FromDouble(head_length)); + + PyObject* plot_args = PyTuple_New(4); + PyTuple_SetItem(plot_args, 0, obj_x); + PyTuple_SetItem(plot_args, 1, obj_y); + PyTuple_SetItem(plot_args, 2, obj_end_x); + PyTuple_SetItem(plot_args, 3, obj_end_y); + + PyObject* res = + PyObject_Call(detail::_interpreter::get().s_python_function_arrow, plot_args, kwargs); + + Py_DECREF(plot_args); + Py_DECREF(kwargs); + if (res) + Py_DECREF(res); + + return res; +} + +template< typename Numeric> +bool hist(const std::vector& y, long bins=10,std::string color="b", + double alpha=1.0, bool cumulative=false) +{ + detail::_interpreter::get(); + + PyObject* yarray = detail::get_array(y); + + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "bins", PyLong_FromLong(bins)); + PyDict_SetItemString(kwargs, "color", PyString_FromString(color.c_str())); + PyDict_SetItemString(kwargs, "alpha", PyFloat_FromDouble(alpha)); + PyDict_SetItemString(kwargs, "cumulative", cumulative ? Py_True : Py_False); + + PyObject* plot_args = PyTuple_New(1); + + PyTuple_SetItem(plot_args, 0, yarray); + + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_hist, plot_args, kwargs); + + + Py_DECREF(plot_args); + Py_DECREF(kwargs); + if(res) Py_DECREF(res); + + return res; +} + +#ifndef WITHOUT_NUMPY +namespace detail { + +inline void imshow(void *ptr, const NPY_TYPES type, const int rows, const int columns, const int colors, const std::map &keywords, PyObject** out) +{ + assert(type == NPY_UINT8 || type == NPY_FLOAT); + assert(colors == 1 || colors == 3 || colors == 4); + + detail::_interpreter::get(); + + // construct args + npy_intp dims[3] = { rows, columns, colors }; + PyObject *args = PyTuple_New(1); + PyTuple_SetItem(args, 0, PyArray_SimpleNewFromData(colors == 1 ? 2 : 3, dims, type, ptr)); + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for(std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) + { + PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); + } + + PyObject *res = PyObject_Call(detail::_interpreter::get().s_python_function_imshow, args, kwargs); + Py_DECREF(args); + Py_DECREF(kwargs); + if (!res) + throw std::runtime_error("Call to imshow() failed"); + if (out) + *out = res; + else + Py_DECREF(res); +} + +} // namespace detail + +inline void imshow(const unsigned char *ptr, const int rows, const int columns, const int colors, const std::map &keywords = {}, PyObject** out = nullptr) +{ + detail::imshow((void *) ptr, NPY_UINT8, rows, columns, colors, keywords, out); +} + +inline void imshow(const float *ptr, const int rows, const int columns, const int colors, const std::map &keywords = {}, PyObject** out = nullptr) +{ + detail::imshow((void *) ptr, NPY_FLOAT, rows, columns, colors, keywords, out); +} + +#ifdef WITH_OPENCV +void imshow(const cv::Mat &image, const std::map &keywords = {}) +{ + // Convert underlying type of matrix, if needed + cv::Mat image2; + NPY_TYPES npy_type = NPY_UINT8; + switch (image.type() & CV_MAT_DEPTH_MASK) { + case CV_8U: + image2 = image; + break; + case CV_32F: + image2 = image; + npy_type = NPY_FLOAT; + break; + default: + image.convertTo(image2, CV_MAKETYPE(CV_8U, image.channels())); + } + + // If color image, convert from BGR to RGB + switch (image2.channels()) { + case 3: + cv::cvtColor(image2, image2, CV_BGR2RGB); + break; + case 4: + cv::cvtColor(image2, image2, CV_BGRA2RGBA); + } + + detail::imshow(image2.data, npy_type, image2.rows, image2.cols, image2.channels(), keywords); +} +#endif // WITH_OPENCV +#endif // WITHOUT_NUMPY + +template +bool scatter(const std::vector& x, + const std::vector& y, + const double s=1.0, // The marker size in points**2 + const std::map & keywords = {}) +{ + detail::_interpreter::get(); + + assert(x.size() == y.size()); + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "s", PyLong_FromLong(s)); + for (const auto& it : keywords) + { + PyDict_SetItemString(kwargs, it.first.c_str(), PyString_FromString(it.second.c_str())); + } + + PyObject* plot_args = PyTuple_New(2); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_scatter, plot_args, kwargs); + + Py_DECREF(plot_args); + Py_DECREF(kwargs); + if(res) Py_DECREF(res); + + return res; +} + +template +bool boxplot(const std::vector>& data, + const std::vector& labels = {}, + const std::map & keywords = {}) +{ + detail::_interpreter::get(); + + PyObject* listlist = detail::get_listlist(data); + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, listlist); + + PyObject* kwargs = PyDict_New(); + + // kwargs needs the labels, if there are (the correct number of) labels + if (!labels.empty() && labels.size() == data.size()) { + PyDict_SetItemString(kwargs, "labels", detail::get_array(labels)); + } + + // take care of the remaining keywords + for (const auto& it : keywords) + { + PyDict_SetItemString(kwargs, it.first.c_str(), PyString_FromString(it.second.c_str())); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_boxplot, args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + + if(res) Py_DECREF(res); + + return res; +} + +template +bool boxplot(const std::vector& data, + const std::map & keywords = {}) +{ + detail::_interpreter::get(); + + PyObject* vector = detail::get_array(data); + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, vector); + + PyObject* kwargs = PyDict_New(); + for (const auto& it : keywords) + { + PyDict_SetItemString(kwargs, it.first.c_str(), PyString_FromString(it.second.c_str())); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_boxplot, args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + + if(res) Py_DECREF(res); + + return res; +} + +template +bool bar(const std::vector & x, + const std::vector & y, + std::string ec = "black", + std::string ls = "-", + double lw = 1.0, + const std::map & keywords = {}) +{ + detail::_interpreter::get(); + + PyObject * xarray = detail::get_array(x); + PyObject * yarray = detail::get_array(y); + + PyObject * kwargs = PyDict_New(); + + PyDict_SetItemString(kwargs, "ec", PyString_FromString(ec.c_str())); + PyDict_SetItemString(kwargs, "ls", PyString_FromString(ls.c_str())); + PyDict_SetItemString(kwargs, "lw", PyFloat_FromDouble(lw)); + + for (std::map::const_iterator it = + keywords.begin(); + it != keywords.end(); + ++it) { + PyDict_SetItemString( + kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); + } + + PyObject * plot_args = PyTuple_New(2); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + + PyObject * res = PyObject_Call( + detail::_interpreter::get().s_python_function_bar, plot_args, kwargs); + + Py_DECREF(plot_args); + Py_DECREF(kwargs); + if (res) Py_DECREF(res); + + return res; +} + +template +bool bar(const std::vector & y, + std::string ec = "black", + std::string ls = "-", + double lw = 1.0, + const std::map & keywords = {}) +{ + using T = typename std::remove_reference::type::value_type; + + detail::_interpreter::get(); + + std::vector x; + for (std::size_t i = 0; i < y.size(); i++) { x.push_back(i); } + + return bar(x, y, ec, ls, lw, keywords); +} + +inline bool subplots_adjust(const std::map& keywords = {}) +{ + detail::_interpreter::get(); + + PyObject* kwargs = PyDict_New(); + for (std::map::const_iterator it = + keywords.begin(); it != keywords.end(); ++it) { + PyDict_SetItemString(kwargs, it->first.c_str(), + PyFloat_FromDouble(it->second)); + } + + + PyObject* plot_args = PyTuple_New(0); + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_subplots_adjust, plot_args, kwargs); + + Py_DECREF(plot_args); + Py_DECREF(kwargs); + if(res) Py_DECREF(res); + + return res; +} + +template< typename Numeric> +bool named_hist(std::string label,const std::vector& y, long bins=10, std::string color="b", double alpha=1.0) +{ + detail::_interpreter::get(); + + PyObject* yarray = detail::get_array(y); + + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "label", PyString_FromString(label.c_str())); + PyDict_SetItemString(kwargs, "bins", PyLong_FromLong(bins)); + PyDict_SetItemString(kwargs, "color", PyString_FromString(color.c_str())); + PyDict_SetItemString(kwargs, "alpha", PyFloat_FromDouble(alpha)); + + + PyObject* plot_args = PyTuple_New(1); + PyTuple_SetItem(plot_args, 0, yarray); + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_hist, plot_args, kwargs); + + Py_DECREF(plot_args); + Py_DECREF(kwargs); + if(res) Py_DECREF(res); + + return res; +} + +template +bool plot(const std::vector& x, const std::vector& y, const std::string& s = "") +{ + assert(x.size() == y.size()); + + detail::_interpreter::get(); + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + PyObject* pystring = PyString_FromString(s.c_str()); + + PyObject* plot_args = PyTuple_New(3); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, pystring); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args); + + Py_DECREF(plot_args); + if(res) Py_DECREF(res); + + return res; +} + +template +bool contour(const std::vector& x, const std::vector& y, + const std::vector& z, + const std::map& keywords = {}) { + assert(x.size() == y.size() && x.size() == z.size()); + + PyObject* xarray = get_array(x); + PyObject* yarray = get_array(y); + PyObject* zarray = get_array(z); + + PyObject* plot_args = PyTuple_New(3); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, zarray); + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for (std::map::const_iterator it = keywords.begin(); + it != keywords.end(); ++it) { + PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); + } + + PyObject* res = + PyObject_Call(detail::_interpreter::get().s_python_function_contour, plot_args, kwargs); + + Py_DECREF(kwargs); + Py_DECREF(plot_args); + if (res) + Py_DECREF(res); + + return res; +} + +template +bool quiver(const std::vector& x, const std::vector& y, const std::vector& u, const std::vector& w, const std::map& keywords = {}) +{ + assert(x.size() == y.size() && x.size() == u.size() && u.size() == w.size()); + + detail::_interpreter::get(); + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + PyObject* uarray = detail::get_array(u); + PyObject* warray = detail::get_array(w); + + PyObject* plot_args = PyTuple_New(4); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, uarray); + PyTuple_SetItem(plot_args, 3, warray); + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for(std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) + { + PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call( + detail::_interpreter::get().s_python_function_quiver, plot_args, kwargs); + + Py_DECREF(kwargs); + Py_DECREF(plot_args); + if (res) + Py_DECREF(res); + + return res; +} + +template +bool stem(const std::vector& x, const std::vector& y, const std::string& s = "") +{ + assert(x.size() == y.size()); + + detail::_interpreter::get(); + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + PyObject* pystring = PyString_FromString(s.c_str()); + + PyObject* plot_args = PyTuple_New(3); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, pystring); + + PyObject* res = PyObject_CallObject( + detail::_interpreter::get().s_python_function_stem, plot_args); + + Py_DECREF(plot_args); + if (res) + Py_DECREF(res); + + return res; +} + +template +bool semilogx(const std::vector& x, const std::vector& y, const std::string& s = "") +{ + assert(x.size() == y.size()); + + detail::_interpreter::get(); + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + PyObject* pystring = PyString_FromString(s.c_str()); + + PyObject* plot_args = PyTuple_New(3); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, pystring); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_semilogx, plot_args); + + Py_DECREF(plot_args); + if(res) Py_DECREF(res); + + return res; +} + +template +bool semilogy(const std::vector& x, const std::vector& y, const std::string& s = "") +{ + assert(x.size() == y.size()); + + detail::_interpreter::get(); + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + PyObject* pystring = PyString_FromString(s.c_str()); + + PyObject* plot_args = PyTuple_New(3); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, pystring); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_semilogy, plot_args); + + Py_DECREF(plot_args); + if(res) Py_DECREF(res); + + return res; +} + +template +bool loglog(const std::vector& x, const std::vector& y, const std::string& s = "") +{ + assert(x.size() == y.size()); + + detail::_interpreter::get(); + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + PyObject* pystring = PyString_FromString(s.c_str()); + + PyObject* plot_args = PyTuple_New(3); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, pystring); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_loglog, plot_args); + + Py_DECREF(plot_args); + if(res) Py_DECREF(res); + + return res; +} + +template +bool errorbar(const std::vector &x, const std::vector &y, const std::vector &yerr, const std::map &keywords = {}) +{ + assert(x.size() == y.size()); + + detail::_interpreter::get(); + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + PyObject* yerrarray = detail::get_array(yerr); + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for(std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) + { + PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); + } + + PyDict_SetItemString(kwargs, "yerr", yerrarray); + + PyObject *plot_args = PyTuple_New(2); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + + PyObject *res = PyObject_Call(detail::_interpreter::get().s_python_function_errorbar, plot_args, kwargs); + + Py_DECREF(kwargs); + Py_DECREF(plot_args); + + if (res) + Py_DECREF(res); + else + throw std::runtime_error("Call to errorbar() failed."); + + return res; +} + +template +bool named_plot(const std::string& name, const std::vector& y, const std::string& format = "") +{ + detail::_interpreter::get(); + + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); + + PyObject* yarray = detail::get_array(y); + + PyObject* pystring = PyString_FromString(format.c_str()); + + PyObject* plot_args = PyTuple_New(2); + + PyTuple_SetItem(plot_args, 0, yarray); + PyTuple_SetItem(plot_args, 1, pystring); + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs); + + Py_DECREF(kwargs); + Py_DECREF(plot_args); + if (res) Py_DECREF(res); + + return res; +} + +template +bool named_plot(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "") +{ + detail::_interpreter::get(); + + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + PyObject* pystring = PyString_FromString(format.c_str()); + + PyObject* plot_args = PyTuple_New(3); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, pystring); + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs); + + Py_DECREF(kwargs); + Py_DECREF(plot_args); + if (res) Py_DECREF(res); + + return res; +} + +template +bool named_semilogx(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "") +{ + detail::_interpreter::get(); + + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + PyObject* pystring = PyString_FromString(format.c_str()); + + PyObject* plot_args = PyTuple_New(3); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, pystring); + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_semilogx, plot_args, kwargs); + + Py_DECREF(kwargs); + Py_DECREF(plot_args); + if (res) Py_DECREF(res); + + return res; +} + +template +bool named_semilogy(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "") +{ + detail::_interpreter::get(); + + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + PyObject* pystring = PyString_FromString(format.c_str()); + + PyObject* plot_args = PyTuple_New(3); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, pystring); + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_semilogy, plot_args, kwargs); + + Py_DECREF(kwargs); + Py_DECREF(plot_args); + if (res) Py_DECREF(res); + + return res; +} + +template +bool named_loglog(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "") +{ + detail::_interpreter::get(); + + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + PyObject* pystring = PyString_FromString(format.c_str()); + + PyObject* plot_args = PyTuple_New(3); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, pystring); + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_loglog, plot_args, kwargs); + + Py_DECREF(kwargs); + Py_DECREF(plot_args); + if (res) Py_DECREF(res); + + return res; +} + +template +bool plot(const std::vector& y, const std::string& format = "") +{ + std::vector x(y.size()); + for(size_t i=0; i +bool plot(const std::vector& y, const std::map& keywords) +{ + std::vector x(y.size()); + for(size_t i=0; i +bool stem(const std::vector& y, const std::string& format = "") +{ + std::vector x(y.size()); + for (size_t i = 0; i < x.size(); ++i) x.at(i) = i; + return stem(x, y, format); +} + +template +void text(Numeric x, Numeric y, const std::string& s = "") +{ + detail::_interpreter::get(); + + PyObject* args = PyTuple_New(3); + PyTuple_SetItem(args, 0, PyFloat_FromDouble(x)); + PyTuple_SetItem(args, 1, PyFloat_FromDouble(y)); + PyTuple_SetItem(args, 2, PyString_FromString(s.c_str())); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_text, args); + if(!res) throw std::runtime_error("Call to text() failed."); + + Py_DECREF(args); + Py_DECREF(res); +} + +inline void colorbar(PyObject* mappable = NULL, const std::map& keywords = {}) +{ + if (mappable == NULL) + throw std::runtime_error("Must call colorbar with PyObject* returned from an image, contour, surface, etc."); + + detail::_interpreter::get(); + + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, mappable); + + PyObject* kwargs = PyDict_New(); + for(std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) + { + PyDict_SetItemString(kwargs, it->first.c_str(), PyFloat_FromDouble(it->second)); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_colorbar, args, kwargs); + if(!res) throw std::runtime_error("Call to colorbar() failed."); + + Py_DECREF(args); + Py_DECREF(kwargs); + Py_DECREF(res); +} + + +inline long figure(long number = -1) +{ + detail::_interpreter::get(); + + PyObject *res; + if (number == -1) + res = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, detail::_interpreter::get().s_python_empty_tuple); + else { + assert(number > 0); + + // Make sure interpreter is initialised + detail::_interpreter::get(); + + PyObject *args = PyTuple_New(1); + PyTuple_SetItem(args, 0, PyLong_FromLong(number)); + res = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, args); + Py_DECREF(args); + } + + if(!res) throw std::runtime_error("Call to figure() failed."); + + PyObject* num = PyObject_GetAttrString(res, "number"); + if (!num) throw std::runtime_error("Could not get number attribute of figure object"); + const long figureNumber = PyLong_AsLong(num); + + Py_DECREF(num); + Py_DECREF(res); + + return figureNumber; +} + +inline bool fignum_exists(long number) +{ + detail::_interpreter::get(); + + PyObject *args = PyTuple_New(1); + PyTuple_SetItem(args, 0, PyLong_FromLong(number)); + PyObject *res = PyObject_CallObject(detail::_interpreter::get().s_python_function_fignum_exists, args); + if(!res) throw std::runtime_error("Call to fignum_exists() failed."); + + bool ret = PyObject_IsTrue(res); + Py_DECREF(res); + Py_DECREF(args); + + return ret; +} + +inline void figure_size(size_t w, size_t h) +{ + detail::_interpreter::get(); + + const size_t dpi = 100; + PyObject* size = PyTuple_New(2); + PyTuple_SetItem(size, 0, PyFloat_FromDouble((double)w / dpi)); + PyTuple_SetItem(size, 1, PyFloat_FromDouble((double)h / dpi)); + + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "figsize", size); + PyDict_SetItemString(kwargs, "dpi", PyLong_FromSize_t(dpi)); + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_figure, + detail::_interpreter::get().s_python_empty_tuple, kwargs); + + Py_DECREF(kwargs); + + if(!res) throw std::runtime_error("Call to figure_size() failed."); + Py_DECREF(res); +} + +inline void legend() +{ + detail::_interpreter::get(); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_legend, detail::_interpreter::get().s_python_empty_tuple); + if(!res) throw std::runtime_error("Call to legend() failed."); + + Py_DECREF(res); +} + +inline void legend(const std::map& keywords) +{ + detail::_interpreter::get(); + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for(std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) + { + PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_legend, detail::_interpreter::get().s_python_empty_tuple, kwargs); + if(!res) throw std::runtime_error("Call to legend() failed."); + + Py_DECREF(kwargs); + Py_DECREF(res); +} + +template +void ylim(Numeric left, Numeric right) +{ + detail::_interpreter::get(); + + PyObject* list = PyList_New(2); + PyList_SetItem(list, 0, PyFloat_FromDouble(left)); + PyList_SetItem(list, 1, PyFloat_FromDouble(right)); + + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, list); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_ylim, args); + if(!res) throw std::runtime_error("Call to ylim() failed."); + + Py_DECREF(args); + Py_DECREF(res); +} + +template +void xlim(Numeric left, Numeric right) +{ + detail::_interpreter::get(); + + PyObject* list = PyList_New(2); + PyList_SetItem(list, 0, PyFloat_FromDouble(left)); + PyList_SetItem(list, 1, PyFloat_FromDouble(right)); + + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, list); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_xlim, args); + if(!res) throw std::runtime_error("Call to xlim() failed."); + + Py_DECREF(args); + Py_DECREF(res); +} + + +inline double* xlim() +{ + detail::_interpreter::get(); + + PyObject* args = PyTuple_New(0); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_xlim, args); + PyObject* left = PyTuple_GetItem(res,0); + PyObject* right = PyTuple_GetItem(res,1); + + double* arr = new double[2]; + arr[0] = PyFloat_AsDouble(left); + arr[1] = PyFloat_AsDouble(right); + + if(!res) throw std::runtime_error("Call to xlim() failed."); + + Py_DECREF(res); + return arr; +} + + +inline double* ylim() +{ + detail::_interpreter::get(); + + PyObject* args = PyTuple_New(0); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_ylim, args); + PyObject* left = PyTuple_GetItem(res,0); + PyObject* right = PyTuple_GetItem(res,1); + + double* arr = new double[2]; + arr[0] = PyFloat_AsDouble(left); + arr[1] = PyFloat_AsDouble(right); + + if(!res) throw std::runtime_error("Call to ylim() failed."); + + Py_DECREF(res); + return arr; +} + +template +inline void xticks(const std::vector &ticks, const std::vector &labels = {}, const std::map& keywords = {}) +{ + assert(labels.size() == 0 || ticks.size() == labels.size()); + + detail::_interpreter::get(); + + // using numpy array + PyObject* ticksarray = detail::get_array(ticks); + + PyObject* args; + if(labels.size() == 0) { + // construct positional args + args = PyTuple_New(1); + PyTuple_SetItem(args, 0, ticksarray); + } else { + // make tuple of tick labels + PyObject* labelstuple = PyTuple_New(labels.size()); + for (size_t i = 0; i < labels.size(); i++) + PyTuple_SetItem(labelstuple, i, PyUnicode_FromString(labels[i].c_str())); + + // construct positional args + args = PyTuple_New(2); + PyTuple_SetItem(args, 0, ticksarray); + PyTuple_SetItem(args, 1, labelstuple); + } + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for(std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) + { + PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_xticks, args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + if(!res) throw std::runtime_error("Call to xticks() failed"); + + Py_DECREF(res); +} + +template +inline void xticks(const std::vector &ticks, const std::map& keywords) +{ + xticks(ticks, {}, keywords); +} + +template +inline void yticks(const std::vector &ticks, const std::vector &labels = {}, const std::map& keywords = {}) +{ + assert(labels.size() == 0 || ticks.size() == labels.size()); + + detail::_interpreter::get(); + + // using numpy array + PyObject* ticksarray = detail::get_array(ticks); + + PyObject* args; + if(labels.size() == 0) { + // construct positional args + args = PyTuple_New(1); + PyTuple_SetItem(args, 0, ticksarray); + } else { + // make tuple of tick labels + PyObject* labelstuple = PyTuple_New(labels.size()); + for (size_t i = 0; i < labels.size(); i++) + PyTuple_SetItem(labelstuple, i, PyUnicode_FromString(labels[i].c_str())); + + // construct positional args + args = PyTuple_New(2); + PyTuple_SetItem(args, 0, ticksarray); + PyTuple_SetItem(args, 1, labelstuple); + } + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for(std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) + { + PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_yticks, args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + if(!res) throw std::runtime_error("Call to yticks() failed"); + + Py_DECREF(res); +} + +template +inline void yticks(const std::vector &ticks, const std::map& keywords) +{ + yticks(ticks, {}, keywords); +} + +template inline void margins(Numeric margin) +{ + // construct positional args + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, PyFloat_FromDouble(margin)); + + PyObject* res = + PyObject_CallObject(detail::_interpreter::get().s_python_function_margins, args); + if (!res) + throw std::runtime_error("Call to margins() failed."); + + Py_DECREF(args); + Py_DECREF(res); +} + +template inline void margins(Numeric margin_x, Numeric margin_y) +{ + // construct positional args + PyObject* args = PyTuple_New(2); + PyTuple_SetItem(args, 0, PyFloat_FromDouble(margin_x)); + PyTuple_SetItem(args, 1, PyFloat_FromDouble(margin_y)); + + PyObject* res = + PyObject_CallObject(detail::_interpreter::get().s_python_function_margins, args); + if (!res) + throw std::runtime_error("Call to margins() failed."); + + Py_DECREF(args); + Py_DECREF(res); +} + + +inline void tick_params(const std::map& keywords, const std::string axis = "both") +{ + detail::_interpreter::get(); + + // construct positional args + PyObject* args; + args = PyTuple_New(1); + PyTuple_SetItem(args, 0, PyString_FromString(axis.c_str())); + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for (std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) + { + PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); + } + + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_tick_params, args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + if (!res) throw std::runtime_error("Call to tick_params() failed"); + + Py_DECREF(res); +} + +inline void subplot(long nrows, long ncols, long plot_number) +{ + detail::_interpreter::get(); + + // construct positional args + PyObject* args = PyTuple_New(3); + PyTuple_SetItem(args, 0, PyFloat_FromDouble(nrows)); + PyTuple_SetItem(args, 1, PyFloat_FromDouble(ncols)); + PyTuple_SetItem(args, 2, PyFloat_FromDouble(plot_number)); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_subplot, args); + if(!res) throw std::runtime_error("Call to subplot() failed."); + + Py_DECREF(args); + Py_DECREF(res); +} + +inline void subplot2grid(long nrows, long ncols, long rowid=0, long colid=0, long rowspan=1, long colspan=1) +{ + detail::_interpreter::get(); + + PyObject* shape = PyTuple_New(2); + PyTuple_SetItem(shape, 0, PyLong_FromLong(nrows)); + PyTuple_SetItem(shape, 1, PyLong_FromLong(ncols)); + + PyObject* loc = PyTuple_New(2); + PyTuple_SetItem(loc, 0, PyLong_FromLong(rowid)); + PyTuple_SetItem(loc, 1, PyLong_FromLong(colid)); + + PyObject* args = PyTuple_New(4); + PyTuple_SetItem(args, 0, shape); + PyTuple_SetItem(args, 1, loc); + PyTuple_SetItem(args, 2, PyLong_FromLong(rowspan)); + PyTuple_SetItem(args, 3, PyLong_FromLong(colspan)); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_subplot2grid, args); + if(!res) throw std::runtime_error("Call to subplot2grid() failed."); + + Py_DECREF(shape); + Py_DECREF(loc); + Py_DECREF(args); + Py_DECREF(res); +} + +inline void title(const std::string &titlestr, const std::map &keywords = {}) +{ + detail::_interpreter::get(); + + PyObject* pytitlestr = PyString_FromString(titlestr.c_str()); + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, pytitlestr); + + PyObject* kwargs = PyDict_New(); + for (auto it = keywords.begin(); it != keywords.end(); ++it) { + PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_title, args, kwargs); + if(!res) throw std::runtime_error("Call to title() failed."); + + Py_DECREF(args); + Py_DECREF(kwargs); + Py_DECREF(res); +} + +inline void suptitle(const std::string &suptitlestr, const std::map &keywords = {}) +{ + detail::_interpreter::get(); + + PyObject* pysuptitlestr = PyString_FromString(suptitlestr.c_str()); + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, pysuptitlestr); + + PyObject* kwargs = PyDict_New(); + for (auto it = keywords.begin(); it != keywords.end(); ++it) { + PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_suptitle, args, kwargs); + if(!res) throw std::runtime_error("Call to suptitle() failed."); + + Py_DECREF(args); + Py_DECREF(kwargs); + Py_DECREF(res); +} + +inline void axis(const std::string &axisstr) +{ + detail::_interpreter::get(); + + PyObject* str = PyString_FromString(axisstr.c_str()); + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, str); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_axis, args); + if(!res) throw std::runtime_error("Call to title() failed."); + + Py_DECREF(args); + Py_DECREF(res); +} + +inline void axvline(double x, double ymin = 0., double ymax = 1., const std::map& keywords = std::map()) +{ + detail::_interpreter::get(); + + // construct positional args + PyObject* args = PyTuple_New(3); + PyTuple_SetItem(args, 0, PyFloat_FromDouble(x)); + PyTuple_SetItem(args, 1, PyFloat_FromDouble(ymin)); + PyTuple_SetItem(args, 2, PyFloat_FromDouble(ymax)); + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for(std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) + { + PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_axvline, args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + + if(res) Py_DECREF(res); +} + +inline void axvspan(double xmin, double xmax, double ymin = 0., double ymax = 1., const std::map& keywords = std::map()) +{ + // construct positional args + PyObject* args = PyTuple_New(4); + PyTuple_SetItem(args, 0, PyFloat_FromDouble(xmin)); + PyTuple_SetItem(args, 1, PyFloat_FromDouble(xmax)); + PyTuple_SetItem(args, 2, PyFloat_FromDouble(ymin)); + PyTuple_SetItem(args, 3, PyFloat_FromDouble(ymax)); + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for(std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) + { + if (it->first == "linewidth" || it->first == "alpha") + PyDict_SetItemString(kwargs, it->first.c_str(), PyFloat_FromDouble(std::stod(it->second))); + else + PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_axvspan, args, kwargs); + Py_DECREF(args); + Py_DECREF(kwargs); + + if(res) Py_DECREF(res); +} + +inline void xlabel(const std::string &str, const std::map &keywords = {}) +{ + detail::_interpreter::get(); + + PyObject* pystr = PyString_FromString(str.c_str()); + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, pystr); + + PyObject* kwargs = PyDict_New(); + for (auto it = keywords.begin(); it != keywords.end(); ++it) { + PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_xlabel, args, kwargs); + if(!res) throw std::runtime_error("Call to xlabel() failed."); + + Py_DECREF(args); + Py_DECREF(kwargs); + Py_DECREF(res); +} + +inline void ylabel(const std::string &str, const std::map& keywords = {}) +{ + detail::_interpreter::get(); + + PyObject* pystr = PyString_FromString(str.c_str()); + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, pystr); + + PyObject* kwargs = PyDict_New(); + for (auto it = keywords.begin(); it != keywords.end(); ++it) { + PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_ylabel, args, kwargs); + if(!res) throw std::runtime_error("Call to ylabel() failed."); + + Py_DECREF(args); + Py_DECREF(kwargs); + Py_DECREF(res); +} + +inline void set_zlabel(const std::string &str, const std::map& keywords = {}) +{ + detail::_interpreter::get(); + + // Same as with plot_surface: We lazily load the modules here the first time + // this function is called because I'm not sure that we can assume "matplotlib + // installed" implies "mpl_toolkits installed" on all platforms, and we don't + // want to require it for people who don't need 3d plots. + static PyObject *mpl_toolkitsmod = nullptr, *axis3dmod = nullptr; + if (!mpl_toolkitsmod) { + PyObject* mpl_toolkits = PyString_FromString("mpl_toolkits"); + PyObject* axis3d = PyString_FromString("mpl_toolkits.mplot3d"); + if (!mpl_toolkits || !axis3d) { throw std::runtime_error("couldnt create string"); } + + mpl_toolkitsmod = PyImport_Import(mpl_toolkits); + Py_DECREF(mpl_toolkits); + if (!mpl_toolkitsmod) { throw std::runtime_error("Error loading module mpl_toolkits!"); } + + axis3dmod = PyImport_Import(axis3d); + Py_DECREF(axis3d); + if (!axis3dmod) { throw std::runtime_error("Error loading module mpl_toolkits.mplot3d!"); } + } + + PyObject* pystr = PyString_FromString(str.c_str()); + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, pystr); + + PyObject* kwargs = PyDict_New(); + for (auto it = keywords.begin(); it != keywords.end(); ++it) { + PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); + } + + PyObject *ax = + PyObject_CallObject(detail::_interpreter::get().s_python_function_gca, + detail::_interpreter::get().s_python_empty_tuple); + if (!ax) throw std::runtime_error("Call to gca() failed."); + Py_INCREF(ax); + + PyObject *zlabel = PyObject_GetAttrString(ax, "set_zlabel"); + if (!zlabel) throw std::runtime_error("Attribute set_zlabel not found."); + Py_INCREF(zlabel); + + PyObject *res = PyObject_Call(zlabel, args, kwargs); + if (!res) throw std::runtime_error("Call to set_zlabel() failed."); + Py_DECREF(zlabel); + + Py_DECREF(ax); + Py_DECREF(args); + Py_DECREF(kwargs); + if (res) Py_DECREF(res); +} + +inline void grid(bool flag) +{ + detail::_interpreter::get(); + + PyObject* pyflag = flag ? Py_True : Py_False; + Py_INCREF(pyflag); + + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, pyflag); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_grid, args); + if(!res) throw std::runtime_error("Call to grid() failed."); + + Py_DECREF(args); + Py_DECREF(res); +} + +inline void show(const bool block = true) +{ + detail::_interpreter::get(); + + PyObject* res; + if(block) + { + res = PyObject_CallObject( + detail::_interpreter::get().s_python_function_show, + detail::_interpreter::get().s_python_empty_tuple); + } + else + { + PyObject *kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "block", Py_False); + res = PyObject_Call( detail::_interpreter::get().s_python_function_show, detail::_interpreter::get().s_python_empty_tuple, kwargs); + Py_DECREF(kwargs); + } + + + if (!res) throw std::runtime_error("Call to show() failed."); + + Py_DECREF(res); +} + +inline void close() +{ + detail::_interpreter::get(); + + PyObject* res = PyObject_CallObject( + detail::_interpreter::get().s_python_function_close, + detail::_interpreter::get().s_python_empty_tuple); + + if (!res) throw std::runtime_error("Call to close() failed."); + + Py_DECREF(res); +} + +inline void xkcd() { + detail::_interpreter::get(); + + PyObject* res; + PyObject *kwargs = PyDict_New(); + + res = PyObject_Call(detail::_interpreter::get().s_python_function_xkcd, + detail::_interpreter::get().s_python_empty_tuple, kwargs); + + Py_DECREF(kwargs); + + if (!res) + throw std::runtime_error("Call to show() failed."); + + Py_DECREF(res); +} + +inline void draw() +{ + detail::_interpreter::get(); + + PyObject* res = PyObject_CallObject( + detail::_interpreter::get().s_python_function_draw, + detail::_interpreter::get().s_python_empty_tuple); + + if (!res) throw std::runtime_error("Call to draw() failed."); + + Py_DECREF(res); +} + +template +inline void pause(Numeric interval) +{ + detail::_interpreter::get(); + + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, PyFloat_FromDouble(interval)); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_pause, args); + if(!res) throw std::runtime_error("Call to pause() failed."); + + Py_DECREF(args); + Py_DECREF(res); +} + +inline void save(const std::string& filename) +{ + detail::_interpreter::get(); + + PyObject* pyfilename = PyString_FromString(filename.c_str()); + + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, pyfilename); + std::cout<<"args:"<> ginput(const int numClicks = 1, const std::map& keywords = {}) +{ + detail::_interpreter::get(); + + PyObject *args = PyTuple_New(1); + PyTuple_SetItem(args, 0, PyLong_FromLong(numClicks)); + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for(std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) + { + PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call( + detail::_interpreter::get().s_python_function_ginput, args, kwargs); + + Py_DECREF(kwargs); + Py_DECREF(args); + if (!res) throw std::runtime_error("Call to ginput() failed."); + + const size_t len = PyList_Size(res); + std::vector> out; + out.reserve(len); + for (size_t i = 0; i < len; i++) { + PyObject *current = PyList_GetItem(res, i); + std::array position; + position[0] = PyFloat_AsDouble(PyTuple_GetItem(current, 0)); + position[1] = PyFloat_AsDouble(PyTuple_GetItem(current, 1)); + out.push_back(position); + } + Py_DECREF(res); + + return out; +} + +// Actually, is there any reason not to call this automatically for every plot? +inline void tight_layout() { + detail::_interpreter::get(); + + PyObject *res = PyObject_CallObject( + detail::_interpreter::get().s_python_function_tight_layout, + detail::_interpreter::get().s_python_empty_tuple); + + if (!res) throw std::runtime_error("Call to tight_layout() failed."); + + Py_DECREF(res); +} + +// Support for variadic plot() and initializer lists: + +namespace detail { + +template +using is_function = typename std::is_function>>::type; + +template +struct is_callable_impl; + +template +struct is_callable_impl +{ + typedef is_function type; +}; // a non-object is callable iff it is a function + +template +struct is_callable_impl +{ + struct Fallback { void operator()(); }; + struct Derived : T, Fallback { }; + + template struct Check; + + template + static std::true_type test( ... ); // use a variadic function to make sure (1) it accepts everything and (2) its always the worst match + + template + static std::false_type test( Check* ); + +public: + typedef decltype(test(nullptr)) type; + typedef decltype(&Fallback::operator()) dtype; + static constexpr bool value = type::value; +}; // an object is callable iff it defines operator() + +template +struct is_callable +{ + // dispatch to is_callable_impl or is_callable_impl depending on whether T is of class type or not + typedef typename is_callable_impl::value, T>::type type; +}; + +template +struct plot_impl { }; + +template<> +struct plot_impl +{ + template + bool operator()(const IterableX& x, const IterableY& y, const std::string& format) + { + // 2-phase lookup for distance, begin, end + using std::distance; + using std::begin; + using std::end; + + auto xs = distance(begin(x), end(x)); + auto ys = distance(begin(y), end(y)); + assert(xs == ys && "x and y data must have the same number of elements!"); + + PyObject* xlist = PyList_New(xs); + PyObject* ylist = PyList_New(ys); + PyObject* pystring = PyString_FromString(format.c_str()); + + auto itx = begin(x), ity = begin(y); + for(size_t i = 0; i < xs; ++i) { + PyList_SetItem(xlist, i, PyFloat_FromDouble(*itx++)); + PyList_SetItem(ylist, i, PyFloat_FromDouble(*ity++)); + } + + PyObject* plot_args = PyTuple_New(3); + PyTuple_SetItem(plot_args, 0, xlist); + PyTuple_SetItem(plot_args, 1, ylist); + PyTuple_SetItem(plot_args, 2, pystring); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args); + + Py_DECREF(plot_args); + if(res) Py_DECREF(res); + + return res; + } +}; + +template<> +struct plot_impl +{ + template + bool operator()(const Iterable& ticks, const Callable& f, const std::string& format) + { + if(begin(ticks) == end(ticks)) return true; + + // We could use additional meta-programming to deduce the correct element type of y, + // but all values have to be convertible to double anyways + std::vector y; + for(auto x : ticks) y.push_back(f(x)); + return plot_impl()(ticks,y,format); + } +}; + +} // end namespace detail + +// recursion stop for the above +template +bool plot() { return true; } + +template +bool plot(const A& a, const B& b, const std::string& format, Args... args) +{ + return detail::plot_impl::type>()(a,b,format) && plot(args...); +} + +/* + * This group of plot() functions is needed to support initializer lists, i.e. calling + * plot( {1,2,3,4} ) + */ +inline bool plot(const std::vector& x, const std::vector& y, const std::string& format = "") { + return plot(x,y,format); +} + +inline bool plot(const std::vector& y, const std::string& format = "") { + return plot(y,format); +} + +inline bool plot(const std::vector& x, const std::vector& y, const std::map& keywords) { + return plot(x,y,keywords); +} + +/* + * This class allows dynamic plots, ie changing the plotted data without clearing and re-plotting + */ +class Plot +{ +public: + // default initialization with plot label, some data and format + template + Plot(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "") { + detail::_interpreter::get(); + + assert(x.size() == y.size()); + + PyObject* kwargs = PyDict_New(); + if(name != "") + PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + PyObject* pystring = PyString_FromString(format.c_str()); + + PyObject* plot_args = PyTuple_New(3); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, pystring); + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs); + + Py_DECREF(kwargs); + Py_DECREF(plot_args); + + if(res) + { + line= PyList_GetItem(res, 0); + + if(line) + set_data_fct = PyObject_GetAttrString(line,"set_data"); + else + Py_DECREF(line); + Py_DECREF(res); + } + } + + // shorter initialization with name or format only + // basically calls line, = plot([], []) + Plot(const std::string& name = "", const std::string& format = "") + : Plot(name, std::vector(), std::vector(), format) {} + + template + bool update(const std::vector& x, const std::vector& y) { + assert(x.size() == y.size()); + if(set_data_fct) + { + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + PyObject* plot_args = PyTuple_New(2); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + + PyObject* res = PyObject_CallObject(set_data_fct, plot_args); + if (res) Py_DECREF(res); + return res; + } + return false; + } + + // clears the plot but keep it available + bool clear() { + return update(std::vector(), std::vector()); + } + + // definitely remove this line + void remove() { + if(line) + { + auto remove_fct = PyObject_GetAttrString(line,"remove"); + PyObject* args = PyTuple_New(0); + PyObject* res = PyObject_CallObject(remove_fct, args); + if (res) Py_DECREF(res); + } + decref(); + } + + ~Plot() { + decref(); + } +private: + + void decref() { + if(line) + Py_DECREF(line); + if(set_data_fct) + Py_DECREF(set_data_fct); + } + + + PyObject* line = nullptr; + PyObject* set_data_fct = nullptr; +}; + +} // end namespace matplotlibcpp diff --git a/FAST_LIO/include/so3_math.h b/FAST_LIO/include/so3_math.h new file mode 100644 index 0000000..8530c3c --- /dev/null +++ b/FAST_LIO/include/so3_math.h @@ -0,0 +1,111 @@ +#ifndef SO3_MATH_H +#define SO3_MATH_H + +#include +#include + +#define SKEW_SYM_MATRX(v) 0.0,-v[2],v[1],v[2],0.0,-v[0],-v[1],v[0],0.0 + +template +Eigen::Matrix skew_sym_mat(const Eigen::Matrix &v) +{ + Eigen::Matrix skew_sym_mat; + skew_sym_mat<<0.0,-v[2],v[1],v[2],0.0,-v[0],-v[1],v[0],0.0; + return skew_sym_mat; +} + +template +Eigen::Matrix Exp(const Eigen::Matrix &&ang) +{ + T ang_norm = ang.norm(); + Eigen::Matrix Eye3 = Eigen::Matrix::Identity(); + if (ang_norm > 0.0000001) + { + Eigen::Matrix r_axis = ang / ang_norm; + Eigen::Matrix K; + K << SKEW_SYM_MATRX(r_axis); + /// Roderigous Tranformation + return Eye3 + std::sin(ang_norm) * K + (1.0 - std::cos(ang_norm)) * K * K; + } + else + { + return Eye3; + } +} + +template +Eigen::Matrix Exp(const Eigen::Matrix &ang_vel, const Ts &dt) +{ + T ang_vel_norm = ang_vel.norm(); + Eigen::Matrix Eye3 = Eigen::Matrix::Identity(); + + if (ang_vel_norm > 0.0000001) + { + Eigen::Matrix r_axis = ang_vel / ang_vel_norm; + Eigen::Matrix K; + + K << SKEW_SYM_MATRX(r_axis); + + T r_ang = ang_vel_norm * dt; + + /// Roderigous Tranformation + return Eye3 + std::sin(r_ang) * K + (1.0 - std::cos(r_ang)) * K * K; + } + else + { + return Eye3; + } +} + +template +Eigen::Matrix Exp(const T &v1, const T &v2, const T &v3) +{ + T &&norm = sqrt(v1 * v1 + v2 * v2 + v3 * v3); + Eigen::Matrix Eye3 = Eigen::Matrix::Identity(); + if (norm > 0.00001) + { + T r_ang[3] = {v1 / norm, v2 / norm, v3 / norm}; + Eigen::Matrix K; + K << SKEW_SYM_MATRX(r_ang); + + /// Roderigous Tranformation + return Eye3 + std::sin(norm) * K + (1.0 - std::cos(norm)) * K * K; + } + else + { + return Eye3; + } +} + +/* Logrithm of a Rotation Matrix */ +template +Eigen::Matrix Log(const Eigen::Matrix &R) +{ + T theta = (R.trace() > 3.0 - 1e-6) ? 0.0 : std::acos(0.5 * (R.trace() - 1)); + Eigen::Matrix K(R(2,1) - R(1,2), R(0,2) - R(2,0), R(1,0) - R(0,1)); + return (std::abs(theta) < 0.001) ? (0.5 * K) : (0.5 * theta / std::sin(theta) * K); +} + +template +Eigen::Matrix RotMtoEuler(const Eigen::Matrix &rot) +{ + T sy = sqrt(rot(0,0)*rot(0,0) + rot(1,0)*rot(1,0)); + bool singular = sy < 1e-6; + T x, y, z; + if(!singular) + { + x = atan2(rot(2, 1), rot(2, 2)); + y = atan2(-rot(2, 0), sy); + z = atan2(rot(1, 0), rot(0, 0)); + } + else + { + x = atan2(-rot(1, 2), rot(1, 1)); + y = atan2(-rot(2, 0), sy); + z = 0; + } + Eigen::Matrix ang(x, y, z); + return ang; +} + +#endif diff --git a/FAST_LIO/include/use-ikfom.hpp b/FAST_LIO/include/use-ikfom.hpp new file mode 100644 index 0000000..fdd8f87 --- /dev/null +++ b/FAST_LIO/include/use-ikfom.hpp @@ -0,0 +1,126 @@ +#ifndef USE_IKFOM_H +#define USE_IKFOM_H + +#include + +typedef MTK::vect<3, double> vect3; +typedef MTK::SO3 SO3; +typedef MTK::S2 S2; +typedef MTK::vect<1, double> vect1; +typedef MTK::vect<2, double> vect2; + +MTK_BUILD_MANIFOLD(state_ikfom, +((vect3, pos)) +((SO3, rot)) +((SO3, offset_R_L_I)) +((vect3, offset_T_L_I)) +((vect3, vel)) +((vect3, bg)) +((vect3, ba)) +((S2, grav)) +); + +MTK_BUILD_MANIFOLD(input_ikfom, +((vect3, acc)) +((vect3, gyro)) +); + +MTK_BUILD_MANIFOLD(process_noise_ikfom, +((vect3, ng)) +((vect3, na)) +((vect3, nbg)) +((vect3, nba)) +); + +MTK::get_cov::type process_noise_cov() +{ + MTK::get_cov::type cov = MTK::get_cov::type::Zero(); + MTK::setDiagonal(cov, &process_noise_ikfom::ng, 0.0001);// 0.03 + MTK::setDiagonal(cov, &process_noise_ikfom::na, 0.0001); // *dt 0.01 0.01 * dt * dt 0.05 + MTK::setDiagonal(cov, &process_noise_ikfom::nbg, 0.00001); // *dt 0.00001 0.00001 * dt *dt 0.3 //0.001 0.0001 0.01 + MTK::setDiagonal(cov, &process_noise_ikfom::nba, 0.00001); //0.001 0.05 0.0001/out 0.01 + return cov; +} + +//double L_offset_to_I[3] = {0.04165, 0.02326, -0.0284}; // Avia +//vect3 Lidar_offset_to_IMU(L_offset_to_I, 3); +Eigen::Matrix get_f(state_ikfom &s, const input_ikfom &in) +{ + Eigen::Matrix res = Eigen::Matrix::Zero(); + vect3 omega; + in.gyro.boxminus(omega, s.bg); + vect3 a_inertial = s.rot * (in.acc-s.ba); + for(int i = 0; i < 3; i++ ){ + res(i) = s.vel[i]; + res(i + 3) = omega[i]; + res(i + 12) = a_inertial[i] + s.grav[i]; + } + return res; +} + +Eigen::Matrix df_dx(state_ikfom &s, const input_ikfom &in) +{ + Eigen::Matrix cov = Eigen::Matrix::Zero(); + cov.template block<3, 3>(0, 12) = Eigen::Matrix3d::Identity(); + vect3 acc_; + in.acc.boxminus(acc_, s.ba); + vect3 omega; + in.gyro.boxminus(omega, s.bg); + cov.template block<3, 3>(12, 3) = -s.rot.toRotationMatrix()*MTK::hat(acc_); + cov.template block<3, 3>(12, 18) = -s.rot.toRotationMatrix(); + Eigen::Matrix vec = Eigen::Matrix::Zero(); + Eigen::Matrix grav_matrix; + s.S2_Mx(grav_matrix, vec, 21); + cov.template block<3, 2>(12, 21) = grav_matrix; + cov.template block<3, 3>(3, 15) = -Eigen::Matrix3d::Identity(); + return cov; +} + + +Eigen::Matrix df_dw(state_ikfom &s, const input_ikfom &in) +{ + Eigen::Matrix cov = Eigen::Matrix::Zero(); + cov.template block<3, 3>(12, 3) = -s.rot.toRotationMatrix(); + cov.template block<3, 3>(3, 0) = -Eigen::Matrix3d::Identity(); + cov.template block<3, 3>(15, 6) = Eigen::Matrix3d::Identity(); + cov.template block<3, 3>(18, 9) = Eigen::Matrix3d::Identity(); + return cov; +} + +vect3 SO3ToEuler(const SO3 &orient) +{ + Eigen::Matrix _ang; + Eigen::Vector4d q_data = orient.coeffs().transpose(); + //scalar w=orient.coeffs[3], x=orient.coeffs[0], y=orient.coeffs[1], z=orient.coeffs[2]; + double sqw = q_data[3]*q_data[3]; + double sqx = q_data[0]*q_data[0]; + double sqy = q_data[1]*q_data[1]; + double sqz = q_data[2]*q_data[2]; + double unit = sqx + sqy + sqz + sqw; // if normalized is one, otherwise is correction factor + double test = q_data[3]*q_data[1] - q_data[2]*q_data[0]; + + if (test > 0.49999*unit) { // singularity at north pole + + _ang << 2 * std::atan2(q_data[0], q_data[3]), M_PI/2, 0; + double temp[3] = {_ang[0] * 57.3, _ang[1] * 57.3, _ang[2] * 57.3}; + vect3 euler_ang(temp, 3); + return euler_ang; + } + if (test < -0.49999*unit) { // singularity at south pole + _ang << -2 * std::atan2(q_data[0], q_data[3]), -M_PI/2, 0; + double temp[3] = {_ang[0] * 57.3, _ang[1] * 57.3, _ang[2] * 57.3}; + vect3 euler_ang(temp, 3); + return euler_ang; + } + + _ang << + std::atan2(2*q_data[0]*q_data[3]+2*q_data[1]*q_data[2] , -sqx - sqy + sqz + sqw), + std::asin (2*test/unit), + std::atan2(2*q_data[2]*q_data[3]+2*q_data[1]*q_data[0] , sqx - sqy - sqz + sqw); + double temp[3] = {_ang[0] * 57.3, _ang[1] * 57.3, _ang[2] * 57.3}; + vect3 euler_ang(temp, 3); + // euler_ang[0] = roll, euler_ang[1] = pitch, euler_ang[2] = yaw + return euler_ang; +} + +#endif \ No newline at end of file diff --git a/FAST_LIO/launch/gdb_debug_example.launch b/FAST_LIO/launch/gdb_debug_example.launch new file mode 100644 index 0000000..d1f86ad --- /dev/null +++ b/FAST_LIO/launch/gdb_debug_example.launch @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/FAST_LIO/launch/mapping.launch.py b/FAST_LIO/launch/mapping.launch.py new file mode 100644 index 0000000..b76313d --- /dev/null +++ b/FAST_LIO/launch/mapping.launch.py @@ -0,0 +1,70 @@ +import os.path + +from ament_index_python.packages import get_package_share_directory + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution +from launch.conditions import IfCondition + +from launch_ros.actions import Node + + +def generate_launch_description(): + package_path = get_package_share_directory('fast_lio') + default_config_path = os.path.join(package_path, 'config') + default_rviz_config_path = os.path.join( + package_path, 'rviz', 'fastlio.rviz') + + use_sim_time = LaunchConfiguration('use_sim_time') + config_path = LaunchConfiguration('config_path') + config_file = LaunchConfiguration('config_file') + rviz_use = LaunchConfiguration('rviz') + rviz_cfg = LaunchConfiguration('rviz_cfg') + + declare_use_sim_time_cmd = DeclareLaunchArgument( + 'use_sim_time', default_value='false', + description='Use simulation (Gazebo) clock if true' + ) + declare_config_path_cmd = DeclareLaunchArgument( + 'config_path', default_value=default_config_path, + description='Yaml config file path' + ) + decalre_config_file_cmd = DeclareLaunchArgument( + 'config_file', default_value='mid360.yaml', + description='Config file' + ) + declare_rviz_cmd = DeclareLaunchArgument( + 'rviz', default_value='true', + description='Use RViz to monitor results' + ) + declare_rviz_config_path_cmd = DeclareLaunchArgument( + 'rviz_cfg', default_value=default_rviz_config_path, + description='RViz config file path' + ) + + fast_lio_node = Node( + package='fast_lio', + executable='fastlio_mapping', + parameters=[PathJoinSubstitution([config_path, config_file]), + {'use_sim_time': use_sim_time}], + output='screen' + ) + rviz_node = Node( + package='rviz2', + executable='rviz2', + arguments=['-d', rviz_cfg], + condition=IfCondition(rviz_use) + ) + + ld = LaunchDescription() + ld.add_action(declare_use_sim_time_cmd) + ld.add_action(declare_config_path_cmd) + ld.add_action(decalre_config_file_cmd) + ld.add_action(declare_rviz_cmd) + ld.add_action(declare_rviz_config_path_cmd) + + ld.add_action(fast_lio_node) + ld.add_action(rviz_node) + + return ld diff --git a/FAST_LIO/launch/unilidar_l2.launch.py b/FAST_LIO/launch/unilidar_l2.launch.py new file mode 100644 index 0000000..aeb51df --- /dev/null +++ b/FAST_LIO/launch/unilidar_l2.launch.py @@ -0,0 +1,70 @@ +import os.path + +from ament_index_python.packages import get_package_share_directory + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution +from launch.conditions import IfCondition + +from launch_ros.actions import Node + + +def generate_launch_description(): + package_path = get_package_share_directory('fast_lio') + default_config_path = os.path.join(package_path, 'config') + default_rviz_config_path = os.path.join( + package_path, 'rviz', 'fastlio.rviz') + + use_sim_time = LaunchConfiguration('use_sim_time') + config_path = LaunchConfiguration('config_path') + config_file = LaunchConfiguration('config_file') + rviz_use = LaunchConfiguration('rviz') + rviz_cfg = LaunchConfiguration('rviz_cfg') + + declare_use_sim_time_cmd = DeclareLaunchArgument( + 'use_sim_time', default_value='false', + description='Use simulation (Gazebo) clock if true' + ) + declare_config_path_cmd = DeclareLaunchArgument( + 'config_path', default_value=default_config_path, + description='Yaml config file path' + ) + decalre_config_file_cmd = DeclareLaunchArgument( + 'config_file', default_value='unilidar_l2.yaml', + description='Config file' + ) + declare_rviz_cmd = DeclareLaunchArgument( + 'rviz', default_value='true', + description='Use RViz to monitor results' + ) + declare_rviz_config_path_cmd = DeclareLaunchArgument( + 'rviz_cfg', default_value=default_rviz_config_path, + description='RViz config file path' + ) + + fast_lio_node = Node( + package='fast_lio', + executable='fastlio_mapping', + parameters=[PathJoinSubstitution([config_path, config_file]), + {'use_sim_time': use_sim_time}], + output='screen' + ) + rviz_node = Node( + package='rviz2', + executable='rviz2', + arguments=['-d', rviz_cfg], + condition=IfCondition(rviz_use) + ) + + ld = LaunchDescription() + ld.add_action(declare_use_sim_time_cmd) + ld.add_action(declare_config_path_cmd) + ld.add_action(decalre_config_file_cmd) + ld.add_action(declare_rviz_cmd) + ld.add_action(declare_rviz_config_path_cmd) + + ld.add_action(fast_lio_node) + ld.add_action(rviz_node) + + return ld diff --git a/FAST_LIO/msg/Pose6D.msg b/FAST_LIO/msg/Pose6D.msg new file mode 100644 index 0000000..1ebd1fd --- /dev/null +++ b/FAST_LIO/msg/Pose6D.msg @@ -0,0 +1,7 @@ +# the preintegrated Lidar states at the time of IMU measurements in a frame +float64 offset_time # the offset time of IMU measurement w.r.t the first lidar point +float64[3] acc # the preintegrated total acceleration (global frame) at the Lidar origin +float64[3] gyr # the unbiased angular velocity (body frame) at the Lidar origin +float64[3] vel # the preintegrated velocity (global frame) at the Lidar origin +float64[3] pos # the preintegrated position (global frame) at the Lidar origin +float64[9] rot # the preintegrated rotation (global frame) at the Lidar origin \ No newline at end of file diff --git a/FAST_LIO/package.xml b/FAST_LIO/package.xml new file mode 100644 index 0000000..8c39e18 --- /dev/null +++ b/FAST_LIO/package.xml @@ -0,0 +1,38 @@ + + + fast_lio + 0.0.0 + + + This is a modified version of LOAM which is original algorithm + is described in the following paper: + J. Zhang and S. Singh. LOAM: Lidar Odometry and Mapping in Real-time. + Robotics: Science and Systems Conference (RSS). Berkeley, CA, July 2014. + + + claydergc + + BSD + + Ji Zhang + + ament_cmake + rosidl_default_generators + geometry_msgs + nav_msgs + rclcpp + std_msgs + sensor_msgs + common_interfaces + tf2 + pcl_ros + pcl_conversions + livox_ros_driver2 + + rosidl_default_runtime + rosidl_interface_packages + + + ament_cmake + + diff --git a/FAST_LIO/rviz/fastlio.rviz b/FAST_LIO/rviz/fastlio.rviz new file mode 100644 index 0000000..d907d25 --- /dev/null +++ b/FAST_LIO/rviz/fastlio.rviz @@ -0,0 +1,304 @@ +Panels: + - Class: rviz_common/Displays + Help Height: 78 + Name: Displays + Property Tree Widget: + Expanded: + - /Global Options1 + - /Status1 + Splitter Ratio: 0.5 + Tree Height: 549 + - Class: rviz_common/Selection + Name: Selection + - Class: rviz_common/Tool Properties + Expanded: + - /2D Goal Pose1 + - /Publish Point1 + Name: Tool Properties + Splitter Ratio: 0.5886790156364441 + - Class: rviz_common/Views + Expanded: + - /Current View1 + Name: Views + Splitter Ratio: 0.5 + - Class: rviz_common/Time + Experimental: false + Name: Time + SyncMode: 0 + SyncSource: CloudRegistered +Visualization Manager: + Class: "" + Displays: + - Class: rviz_default_plugins/TF + Enabled: true + Frame Timeout: 15 + Frames: + All Enabled: true + body: + Value: true + camera_init: + Value: true + Marker Scale: 1 + Name: TF + Show Arrows: true + Show Axes: true + Show Names: false + Tree: + camera_init: + body: + {} + Update Interval: 0 + Value: true + - Angle Tolerance: 0.10000000149011612 + Class: rviz_default_plugins/Odometry + Covariance: + Orientation: + Alpha: 0.5 + Color: 255; 255; 127 + Color Style: Unique + Frame: Local + Offset: 1 + Scale: 1 + Value: true + Position: + Alpha: 0.30000001192092896 + Color: 204; 51; 204 + Scale: 1 + Value: true + Value: true + Enabled: true + Keep: 100 + Name: Odometry + Position Tolerance: 0.10000000149011612 + Shape: + Alpha: 1 + Axes Length: 1 + Axes Radius: 0.10000000149011612 + Color: 255; 25; 0 + Head Length: 0.30000001192092896 + Head Radius: 0.10000000149011612 + Shaft Length: 1 + Shaft Radius: 0.05000000074505806 + Value: Arrow + Topic: + Depth: 5 + Durability Policy: Volatile + Filter size: 10 + History Policy: Keep Last + Reliability Policy: Reliable + Value: /Odometry + Value: true + - Alpha: 1 + Buffer Length: 1 + Class: rviz_default_plugins/Path + Color: 25; 255; 0 + Enabled: true + Head Diameter: 0.30000001192092896 + Head Length: 0.20000000298023224 + Length: 0.30000001192092896 + Line Style: Lines + Line Width: 0.029999999329447746 + Name: Path + Offset: + X: 0 + Y: 0 + Z: 0 + Pose Color: 255; 85; 255 + Pose Style: None + Radius: 0.029999999329447746 + Shaft Diameter: 0.10000000149011612 + Shaft Length: 0.10000000149011612 + Topic: + Depth: 5 + Durability Policy: Volatile + Filter size: 10 + History Policy: Keep Last + Reliability Policy: Reliable + Value: /path + Value: true + - Alpha: 1 + Autocompute Intensity Bounds: true + Autocompute Value Bounds: + Max Value: 11.062739372253418 + Min Value: -13.864188194274902 + Value: true + Axis: Z + Channel Name: intensity + Class: rviz_default_plugins/PointCloud2 + Color: 255; 255; 255 + Color Transformer: AxisColor + Decay Time: 30 + Enabled: true + Invert Rainbow: false + Max Color: 255; 255; 255 + Max Intensity: 186 + Min Color: 0; 0; 0 + Min Intensity: 0 + Name: CloudRegistered + Position Transformer: XYZ + Selectable: true + Size (Pixels): 3 + Size (m): 0.05000000074505806 + Style: Flat Squares + Topic: + Depth: 5 + Durability Policy: Volatile + Filter size: 10 + History Policy: Keep Last + Reliability Policy: Reliable + Value: /cloud_registered + Use Fixed Frame: true + Use rainbow: true + Value: true + - Alpha: 1 + Autocompute Intensity Bounds: true + Autocompute Value Bounds: + Max Value: 10 + Min Value: -10 + Value: true + Axis: Z + Channel Name: intensity + Class: rviz_default_plugins/PointCloud2 + Color: 255; 255; 255 + Color Transformer: Intensity + Decay Time: 0 + Enabled: true + Invert Rainbow: false + Max Color: 255; 255; 255 + Max Intensity: 184 + Min Color: 0; 0; 0 + Min Intensity: 0 + Name: CloudEffected + Position Transformer: XYZ + Selectable: true + Size (Pixels): 3 + Size (m): 0.10000000149011612 + Style: Flat Squares + Topic: + Depth: 5 + Durability Policy: Volatile + Filter size: 10 + History Policy: Keep Last + Reliability Policy: Reliable + Value: /cloud_effected + Use Fixed Frame: true + Use rainbow: true + Value: true + - Alpha: 1 + Autocompute Intensity Bounds: true + Autocompute Value Bounds: + Max Value: -9999 + Min Value: 9999 + Value: true + Axis: Z + Channel Name: intensity + Class: rviz_default_plugins/PointCloud2 + Color: 255; 255; 255 + Color Transformer: AxisColor + Decay Time: 0 + Enabled: true + Invert Rainbow: false + Max Color: 255; 255; 255 + Max Intensity: 255 + Min Color: 0; 0; 0 + Min Intensity: 0 + Name: CloudMap + Position Transformer: XYZ + Selectable: true + Size (Pixels): 3 + Size (m): 0.05000000074505806 + Style: Flat Squares + Topic: + Depth: 5 + Durability Policy: Volatile + Filter size: 10 + History Policy: Keep Last + Reliability Policy: Reliable + Value: /Laser_map + Use Fixed Frame: true + Use rainbow: true + Value: true + Enabled: true + Global Options: + Background Color: 0; 0; 0 + Fixed Frame: camera_init + Frame Rate: 30 + Name: root + Tools: + - Class: rviz_default_plugins/Interact + Hide Inactive Objects: true + - Class: rviz_default_plugins/MoveCamera + - Class: rviz_default_plugins/Select + - Class: rviz_default_plugins/FocusCamera + - Class: rviz_default_plugins/Measure + Line color: 128; 128; 0 + - Class: rviz_default_plugins/SetInitialPose + Covariance x: 0.25 + Covariance y: 0.25 + Covariance yaw: 0.06853891909122467 + Topic: + Depth: 5 + Durability Policy: Volatile + History Policy: Keep Last + Reliability Policy: Reliable + Value: /initialpose + - Class: rviz_default_plugins/SetGoal + Topic: + Depth: 5 + Durability Policy: Volatile + History Policy: Keep Last + Reliability Policy: Reliable + Value: /goal_pose + - Class: rviz_default_plugins/PublishPoint + Single click: true + Topic: + Depth: 5 + Durability Policy: Volatile + History Policy: Keep Last + Reliability Policy: Reliable + Value: /clicked_point + Transformation: + Current: + Class: rviz_default_plugins/TF + Value: true + Views: + Current: + Class: rviz_default_plugins/Orbit + Distance: 216.99887084960938 + Enable Stereo Rendering: + Stereo Eye Separation: 0.05999999865889549 + Stereo Focal Distance: 1 + Swap Stereo Eyes: false + Value: false + Focal Point: + X: -0.008504047989845276 + Y: -0.0005770106799900532 + Z: 0.034441977739334106 + Focal Shape Fixed Size: true + Focal Shape Size: 0.05000000074505806 + Invert Z Axis: false + Name: Current View + Near Clip Distance: 0.009999999776482582 + Pitch: 1.5697963237762451 + Target Frame: + Value: Orbit (rviz_default_plugins) + Yaw: 4.88355827331543 + Saved: ~ +Window Geometry: + Displays: + collapsed: false + Height: 846 + Hide Left Dock: false + Hide Right Dock: false + QMainWindow State: 000000ff00000000fd000000040000000000000156000002b0fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d000002b0000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f000002b0fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003d000002b0000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000005ad0000003efc0100000002fb0000000800540069006d00650100000000000005ad000002fb00fffffffb0000000800540069006d0065010000000000000450000000000000000000000451000002b000000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000 + Selection: + collapsed: false + Time: + collapsed: false + Tool Properties: + collapsed: false + Views: + collapsed: false + Width: 1453 + X: 368 + Y: 104 diff --git a/FAST_LIO/rviz_cfg/.gitignore b/FAST_LIO/rviz_cfg/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/FAST_LIO/rviz_cfg/loam_livox.rviz b/FAST_LIO/rviz_cfg/loam_livox.rviz new file mode 100644 index 0000000..ea3cdf3 --- /dev/null +++ b/FAST_LIO/rviz_cfg/loam_livox.rviz @@ -0,0 +1,358 @@ +Panels: + - Class: rviz/Displays + Help Height: 0 + Name: Displays + Property Tree Widget: + Expanded: + - /Global Options1 + - /mapping1 + - /mapping1/surround1 + - /mapping1/currPoints1 + - /mapping1/currPoints1/Autocompute Value Bounds1 + - /Odometry1/Odometry1 + - /Odometry1/Odometry1/Shape1 + - /Odometry1/Odometry1/Covariance1 + - /Odometry1/Odometry1/Covariance1/Position1 + - /Odometry1/Odometry1/Covariance1/Orientation1 + - /MarkerArray1/Namespaces1 + Splitter Ratio: 0.6432291865348816 + Tree Height: 811 + - Class: rviz/Selection + Name: Selection + - Class: rviz/Tool Properties + Expanded: + - /2D Pose Estimate1 + - /2D Nav Goal1 + - /Publish Point1 + Name: Tool Properties + Splitter Ratio: 0.5886790156364441 + - Class: rviz/Views + Expanded: + - /Current View1 + Name: Views + Splitter Ratio: 0.5 + - Class: rviz/Time + Experimental: false + Name: Time + SyncMode: 0 + SyncSource: surround +Preferences: + PromptSaveOnExit: true +Toolbars: + toolButtonStyle: 2 +Visualization Manager: + Class: "" + Displays: + - Alpha: 1 + Cell Size: 1000 + Class: rviz/Grid + Color: 160; 160; 164 + Enabled: false + Line Style: + Line Width: 0.029999999329447746 + Value: Lines + Name: Grid + Normal Cell Count: 0 + Offset: + X: 0 + Y: 0 + Z: 0 + Plane: XY + Plane Cell Count: 40 + Reference Frame: + Value: false + - Class: rviz/Axes + Enabled: false + Length: 0.699999988079071 + Name: Axes + Radius: 0.05999999865889549 + Reference Frame: + Value: false + - Class: rviz/Group + Displays: + - Alpha: 1 + Autocompute Intensity Bounds: true + Autocompute Value Bounds: + Max Value: 10 + Min Value: -10 + Value: true + Axis: Z + Channel Name: intensity + Class: rviz/PointCloud2 + Color: 238; 238; 236 + Color Transformer: Intensity + Decay Time: 0 + Enabled: true + Invert Rainbow: false + Max Color: 255; 255; 255 + Min Color: 238; 238; 236 + Name: surround + Position Transformer: XYZ + Queue Size: 1 + Selectable: false + Size (Pixels): 3 + Size (m): 0.05000000074505806 + Style: Points + Topic: /cloud_registered + Unreliable: false + Use Fixed Frame: true + Use rainbow: true + Value: true + - Alpha: 0.10000000149011612 + Autocompute Intensity Bounds: true + Autocompute Value Bounds: + Max Value: 15 + Min Value: -5 + Value: false + Axis: Z + Channel Name: intensity + Class: rviz/PointCloud2 + Color: 255; 255; 255 + Color Transformer: Intensity + Decay Time: 1000 + Enabled: true + Invert Rainbow: true + Max Color: 255; 255; 255 + Min Color: 0; 0; 0 + Name: currPoints + Position Transformer: XYZ + Queue Size: 100000 + Selectable: true + Size (Pixels): 1 + Size (m): 0.009999999776482582 + Style: Points + Topic: /cloud_registered + Unreliable: false + Use Fixed Frame: true + Use rainbow: true + Value: true + - Alpha: 1 + Autocompute Intensity Bounds: true + Autocompute Value Bounds: + Max Value: 10 + Min Value: -10 + Value: true + Axis: Z + Channel Name: intensity + Class: rviz/PointCloud2 + Color: 255; 0; 0 + Color Transformer: FlatColor + Decay Time: 0 + Enabled: false + Invert Rainbow: false + Max Color: 255; 255; 255 + Min Color: 0; 0; 0 + Name: PointCloud2 + Position Transformer: XYZ + Queue Size: 10 + Selectable: true + Size (Pixels): 3 + Size (m): 0.10000000149011612 + Style: Flat Squares + Topic: /Laser_map + Unreliable: false + Use Fixed Frame: true + Use rainbow: true + Value: false + Enabled: true + Name: mapping + - Class: rviz/Group + Displays: + - Angle Tolerance: 0.009999999776482582 + Class: rviz/Odometry + Covariance: + Orientation: + Alpha: 0.5 + Color: 255; 255; 127 + Color Style: Unique + Frame: Local + Offset: 1 + Scale: 1 + Value: true + Position: + Alpha: 0.30000001192092896 + Color: 204; 51; 204 + Scale: 1 + Value: true + Value: true + Enabled: true + Keep: 1 + Name: Odometry + Position Tolerance: 0.0010000000474974513 + Shape: + Alpha: 1 + Axes Length: 1 + Axes Radius: 0.20000000298023224 + Color: 255; 85; 0 + Head Length: 0 + Head Radius: 0 + Shaft Length: 0.05000000074505806 + Shaft Radius: 0.05000000074505806 + Value: Axes + Topic: /Odometry + Unreliable: false + Value: true + Enabled: true + Name: Odometry + - Class: rviz/Axes + Enabled: true + Length: 0.699999988079071 + Name: Axes + Radius: 0.10000000149011612 + Reference Frame: + Value: true + - Alpha: 0 + Buffer Length: 2 + Class: rviz/Path + Color: 25; 255; 255 + Enabled: true + Head Diameter: 0 + Head Length: 0 + Length: 0.30000001192092896 + Line Style: Billboards + Line Width: 0.20000000298023224 + Name: Path + Offset: + X: 0 + Y: 0 + Z: 0 + Pose Color: 25; 255; 255 + Pose Style: None + Radius: 0.029999999329447746 + Shaft Diameter: 0.4000000059604645 + Shaft Length: 0.4000000059604645 + Topic: /path + Unreliable: false + Value: true + - Alpha: 1 + Autocompute Intensity Bounds: false + Autocompute Value Bounds: + Max Value: 10 + Min Value: -10 + Value: true + Axis: Z + Channel Name: intensity + Class: rviz/PointCloud2 + Color: 255; 255; 255 + Color Transformer: Intensity + Decay Time: 0 + Enabled: false + Invert Rainbow: false + Max Color: 239; 41; 41 + Max Intensity: 0 + Min Color: 239; 41; 41 + Min Intensity: 0 + Name: PointCloud2 + Position Transformer: XYZ + Queue Size: 10 + Selectable: true + Size (Pixels): 4 + Size (m): 0.30000001192092896 + Style: Spheres + Topic: /cloud_effected + Unreliable: false + Use Fixed Frame: true + Use rainbow: true + Value: false + - Alpha: 1 + Autocompute Intensity Bounds: true + Autocompute Value Bounds: + Max Value: 13.139549255371094 + Min Value: -32.08251953125 + Value: true + Axis: Z + Channel Name: intensity + Class: rviz/PointCloud2 + Color: 138; 226; 52 + Color Transformer: FlatColor + Decay Time: 0 + Enabled: false + Invert Rainbow: false + Max Color: 138; 226; 52 + Min Color: 138; 226; 52 + Name: PointCloud2 + Position Transformer: XYZ + Queue Size: 10 + Selectable: true + Size (Pixels): 3 + Size (m): 0.10000000149011612 + Style: Flat Squares + Topic: /Laser_map + Unreliable: false + Use Fixed Frame: true + Use rainbow: true + Value: false + - Class: rviz/MarkerArray + Enabled: false + Marker Topic: /MarkerArray + Name: MarkerArray + Namespaces: + {} + Queue Size: 100 + Value: false + Enabled: true + Global Options: + Background Color: 0; 0; 0 + Default Light: true + Fixed Frame: camera_init + Frame Rate: 10 + Name: root + Tools: + - Class: rviz/Interact + Hide Inactive Objects: true + - Class: rviz/MoveCamera + - Class: rviz/Select + - Class: rviz/FocusCamera + - Class: rviz/Measure + - Class: rviz/SetInitialPose + Theta std deviation: 0.2617993950843811 + Topic: /initialpose + X std deviation: 0.5 + Y std deviation: 0.5 + - Class: rviz/SetGoal + Topic: /move_base_simple/goal + - Class: rviz/PublishPoint + Single click: true + Topic: /clicked_point + Value: true + Views: + Current: + Class: rviz/Orbit + Distance: 46.0853271484375 + Enable Stereo Rendering: + Stereo Eye Separation: 0.05999999865889549 + Stereo Focal Distance: 1 + Swap Stereo Eyes: false + Value: false + Focal Point: + X: -4.982542037963867 + Y: -15.83572006225586 + Z: -3.063523054122925 + Focal Shape Fixed Size: true + Focal Shape Size: 0.05000000074505806 + Invert Z Axis: false + Name: Current View + Near Clip Distance: 0.009999999776482582 + Pitch: 0.399796724319458 + Target Frame: global + Value: Orbit (rviz) + Yaw: 1.277182698249817 + Saved: ~ +Window Geometry: + Displays: + collapsed: false + Height: 1028 + Hide Left Dock: false + Hide Right Dock: true + QMainWindow State: 000000ff00000000fd0000000400000000000001c800000368fc020000000dfb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000002700000368000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261fb0000000a0049006d0061006700650000000297000001dc0000000000000000fb0000000a0049006d0061006700650000000394000001600000000000000000fb0000000a0049006d00610067006501000002c5000000c70000000000000000fb0000000a0049006d00610067006501000002c5000000c70000000000000000fb0000000a0049006d00610067006501000002c5000000c700000000000000000000000100000152000004b7fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003d000004b7000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e100000197000000030000061f00000052fc0100000002fb0000000800540069006d006501000000000000061f000002eb00fffffffb0000000800540069006d00650100000000000004500000000000000000000004510000036800000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000 + Selection: + collapsed: false + Time: + collapsed: false + Tool Properties: + collapsed: false + Views: + collapsed: true + Width: 1567 + X: 67 + Y: 24 diff --git a/FAST_LIO/src/IMU_Processing.hpp b/FAST_LIO/src/IMU_Processing.hpp new file mode 100644 index 0000000..f35378f --- /dev/null +++ b/FAST_LIO/src/IMU_Processing.hpp @@ -0,0 +1,379 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "use-ikfom.hpp" + +/// *************Preconfiguration + +#define MAX_INI_COUNT (10) + +const bool time_list(PointType &x, PointType &y) {return (x.curvature < y.curvature);}; + +/// *************IMU Process and undistortion +class ImuProcess +{ + public: + EIGEN_MAKE_ALIGNED_OPERATOR_NEW + + ImuProcess(); + ~ImuProcess(); + + void Reset(); + // void Reset(double start_timestamp, const sensor_msgs::ImuConstPtr &lastimu); + void Reset(double start_timestamp, const sensor_msgs::msg::Imu::ConstSharedPtr &lastimu); + void set_extrinsic(const V3D &transl, const M3D &rot); + void set_extrinsic(const V3D &transl); + void set_extrinsic(const MD(4,4) &T); + void set_gyr_cov(const V3D &scaler); + void set_acc_cov(const V3D &scaler); + void set_gyr_bias_cov(const V3D &b_g); + void set_acc_bias_cov(const V3D &b_a); + Eigen::Matrix Q; + void Process(const MeasureGroup &meas, esekfom::esekf &kf_state, PointCloudXYZI::Ptr pcl_un_); + + ofstream fout_imu; + V3D cov_acc; + V3D cov_gyr; + V3D cov_acc_scale; + V3D cov_gyr_scale; + V3D cov_bias_gyr; + V3D cov_bias_acc; + double first_lidar_time; + + private: + void IMU_init(const MeasureGroup &meas, esekfom::esekf &kf_state, int &N); + void UndistortPcl(const MeasureGroup &meas, esekfom::esekf &kf_state, PointCloudXYZI &pcl_in_out); + + PointCloudXYZI::Ptr cur_pcl_un_; + // sensor_msgs::ImuConstPtr last_imu_; + sensor_msgs::msg::Imu::ConstSharedPtr last_imu_; + deque v_imu_; + vector IMUpose; + vector v_rot_pcl_; + M3D Lidar_R_wrt_IMU; + V3D Lidar_T_wrt_IMU; + V3D mean_acc; + V3D mean_gyr; + V3D angvel_last; + V3D acc_s_last; + double start_timestamp_; + double last_lidar_end_time_; + int init_iter_num = 1; + bool b_first_frame_ = true; + bool imu_need_init_ = true; +}; + +ImuProcess::ImuProcess() + : b_first_frame_(true), imu_need_init_(true), start_timestamp_(-1) +{ + init_iter_num = 1; + Q = process_noise_cov(); + cov_acc = V3D(0.1, 0.1, 0.1); + cov_gyr = V3D(0.1, 0.1, 0.1); + cov_bias_gyr = V3D(0.0001, 0.0001, 0.0001); + cov_bias_acc = V3D(0.0001, 0.0001, 0.0001); + mean_acc = V3D(0, 0, -1.0); + mean_gyr = V3D(0, 0, 0); + angvel_last = Zero3d; + Lidar_T_wrt_IMU = Zero3d; + Lidar_R_wrt_IMU = Eye3d; + last_imu_.reset(new sensor_msgs::msg::Imu()); +} + +ImuProcess::~ImuProcess() {} + +void ImuProcess::Reset() +{ + // ROS_WARN("Reset ImuProcess"); + mean_acc = V3D(0, 0, -1.0); + mean_gyr = V3D(0, 0, 0); + angvel_last = Zero3d; + imu_need_init_ = true; + start_timestamp_ = -1; + init_iter_num = 1; + v_imu_.clear(); + IMUpose.clear(); + last_imu_.reset(new sensor_msgs::msg::Imu()); + cur_pcl_un_.reset(new PointCloudXYZI()); +} + +void ImuProcess::set_extrinsic(const MD(4,4) &T) +{ + Lidar_T_wrt_IMU = T.block<3,1>(0,3); + Lidar_R_wrt_IMU = T.block<3,3>(0,0); +} + +void ImuProcess::set_extrinsic(const V3D &transl) +{ + Lidar_T_wrt_IMU = transl; + Lidar_R_wrt_IMU.setIdentity(); +} + +void ImuProcess::set_extrinsic(const V3D &transl, const M3D &rot) +{ + Lidar_T_wrt_IMU = transl; + Lidar_R_wrt_IMU = rot; +} + +void ImuProcess::set_gyr_cov(const V3D &scaler) +{ + cov_gyr_scale = scaler; +} + +void ImuProcess::set_acc_cov(const V3D &scaler) +{ + cov_acc_scale = scaler; +} + +void ImuProcess::set_gyr_bias_cov(const V3D &b_g) +{ + cov_bias_gyr = b_g; +} + +void ImuProcess::set_acc_bias_cov(const V3D &b_a) +{ + cov_bias_acc = b_a; +} + +void ImuProcess::IMU_init(const MeasureGroup &meas, esekfom::esekf &kf_state, int &N) +{ + /** 1. initializing the gravity, gyro bias, acc and gyro covariance + ** 2. normalize the acceleration measurenments to unit gravity **/ + + V3D cur_acc, cur_gyr; + + if (b_first_frame_) + { + Reset(); + N = 1; + b_first_frame_ = false; + const auto &imu_acc = meas.imu.front()->linear_acceleration; + const auto &gyr_acc = meas.imu.front()->angular_velocity; + mean_acc << imu_acc.x, imu_acc.y, imu_acc.z; + mean_gyr << gyr_acc.x, gyr_acc.y, gyr_acc.z; + first_lidar_time = meas.lidar_beg_time; + } + + for (const auto &imu : meas.imu) + { + const auto &imu_acc = imu->linear_acceleration; + const auto &gyr_acc = imu->angular_velocity; + cur_acc << imu_acc.x, imu_acc.y, imu_acc.z; + cur_gyr << gyr_acc.x, gyr_acc.y, gyr_acc.z; + + mean_acc += (cur_acc - mean_acc) / N; + mean_gyr += (cur_gyr - mean_gyr) / N; + + cov_acc = cov_acc * (N - 1.0) / N + (cur_acc - mean_acc).cwiseProduct(cur_acc - mean_acc) * (N - 1.0) / (N * N); + cov_gyr = cov_gyr * (N - 1.0) / N + (cur_gyr - mean_gyr).cwiseProduct(cur_gyr - mean_gyr) * (N - 1.0) / (N * N); + + // cout<<"acc norm: "<::cov init_P = kf_state.get_P(); + init_P.setIdentity(); + init_P(6,6) = init_P(7,7) = init_P(8,8) = 0.00001; + init_P(9,9) = init_P(10,10) = init_P(11,11) = 0.00001; + init_P(15,15) = init_P(16,16) = init_P(17,17) = 0.0001; + init_P(18,18) = init_P(19,19) = init_P(20,20) = 0.001; + init_P(21,21) = init_P(22,22) = 0.00001; + kf_state.change_P(init_P); + last_imu_ = meas.imu.back(); + +} + +void ImuProcess::UndistortPcl(const MeasureGroup &meas, esekfom::esekf &kf_state, PointCloudXYZI &pcl_out) +{ + /*** add the imu of the last frame-tail to the of current frame-head ***/ + auto v_imu = meas.imu; + v_imu.push_front(last_imu_); + const double &imu_beg_time = rclcpp::Time(v_imu.front()->header.stamp).seconds(); + const double &imu_end_time = rclcpp::Time(v_imu.back()->header.stamp).seconds(); + const double &pcl_beg_time = meas.lidar_beg_time; + const double &pcl_end_time = meas.lidar_end_time; + + /*** sort point clouds by offset time ***/ + pcl_out = *(meas.lidar); + sort(pcl_out.points.begin(), pcl_out.points.end(), time_list); + // cout<<"[ IMU Process ]: Process lidar from "<header.stamp).seconds(); + double head_stamp = rclcpp::Time(head->header.stamp).seconds(); + + if (tail_stamp < last_lidar_end_time_) continue; + + angvel_avr<<0.5 * (head->angular_velocity.x + tail->angular_velocity.x), + 0.5 * (head->angular_velocity.y + tail->angular_velocity.y), + 0.5 * (head->angular_velocity.z + tail->angular_velocity.z); + acc_avr <<0.5 * (head->linear_acceleration.x + tail->linear_acceleration.x), + 0.5 * (head->linear_acceleration.y + tail->linear_acceleration.y), + 0.5 * (head->linear_acceleration.z + tail->linear_acceleration.z); + + // fout_imu << setw(10) << head->header.stamp.toSec() - first_lidar_time << " " << angvel_avr.transpose() << " " << acc_avr.transpose() << endl; + + acc_avr = acc_avr * G_m_s2 / mean_acc.norm(); // - state_inout.ba; + + if(head_stamp < last_lidar_end_time_) + { + dt = tail_stamp - last_lidar_end_time_; + // dt = tail->header.stamp.toSec() - pcl_beg_time; + } + else + { + dt = tail_stamp - head_stamp; + } + + in.acc = acc_avr; + in.gyro = angvel_avr; + Q.block<3, 3>(0, 0).diagonal() = cov_gyr; + Q.block<3, 3>(3, 3).diagonal() = cov_acc; + Q.block<3, 3>(6, 6).diagonal() = cov_bias_gyr; + Q.block<3, 3>(9, 9).diagonal() = cov_bias_acc; + kf_state.predict(dt, Q, in); + + /* save the poses at each IMU measurements */ + imu_state = kf_state.get_x(); + angvel_last = angvel_avr - imu_state.bg; + acc_s_last = imu_state.rot * (acc_avr - imu_state.ba); + for(int i=0; i<3; i++) + { + acc_s_last[i] += imu_state.grav[i]; + } + double &&offs_t = tail_stamp - pcl_beg_time; + IMUpose.push_back(set_pose6d(offs_t, acc_s_last, angvel_last, imu_state.vel, imu_state.pos, imu_state.rot.toRotationMatrix())); + } + + /*** calculated the pos and attitude prediction at the frame-end ***/ + double note = pcl_end_time > imu_end_time ? 1.0 : -1.0; + dt = note * (pcl_end_time - imu_end_time); + kf_state.predict(dt, Q, in); + + imu_state = kf_state.get_x(); + last_imu_ = meas.imu.back(); + last_lidar_end_time_ = pcl_end_time; + + /*** undistort each lidar point (backward propagation) ***/ + if (pcl_out.points.begin() == pcl_out.points.end()) return; + auto it_pcl = pcl_out.points.end() - 1; + for (auto it_kp = IMUpose.end() - 1; it_kp != IMUpose.begin(); it_kp--) + { + auto head = it_kp - 1; + auto tail = it_kp; + R_imu<rot); + // cout<<"head imu acc: "<vel); + pos_imu<pos); + acc_imu<acc); + angvel_avr<gyr); + + for(; it_pcl->curvature / double(1000) > head->offset_time; it_pcl --) + { + dt = it_pcl->curvature / double(1000) - head->offset_time; + + /* Transform to the 'end' frame, using only the rotation + * Note: Compensation direction is INVERSE of Frame's moving direction + * So if we want to compensate a point at timestamp-i to the frame-e + * P_compensate = R_imu_e ^ T * (R_i * P_i + T_ei) where T_ei is represented in global frame */ + M3D R_i(R_imu * Exp(angvel_avr, dt)); + + V3D P_i(it_pcl->x, it_pcl->y, it_pcl->z); + V3D T_ei(pos_imu + vel_imu * dt + 0.5 * acc_imu * dt * dt - imu_state.pos); + V3D P_compensate = imu_state.offset_R_L_I.conjugate() * (imu_state.rot.conjugate() * (R_i * (imu_state.offset_R_L_I * P_i + imu_state.offset_T_L_I) + T_ei) - imu_state.offset_T_L_I);// not accurate! + + // save Undistorted points and their rotation + it_pcl->x = P_compensate(0); + it_pcl->y = P_compensate(1); + it_pcl->z = P_compensate(2); + + if (it_pcl == pcl_out.points.begin()) break; + } + } +} + +void ImuProcess::Process(const MeasureGroup &meas, esekfom::esekf &kf_state, PointCloudXYZI::Ptr cur_pcl_un_) +{ + double t1,t2,t3; + t1 = omp_get_wtime(); + + if(meas.imu.empty()) {return;}; + assert(meas.lidar != nullptr); + + if (imu_need_init_) + { + /// The very first lidar frame + IMU_init(meas, kf_state, init_iter_num); + + imu_need_init_ = true; + + last_imu_ = meas.imu.back(); + + state_ikfom imu_state = kf_state.get_x(); + if (init_iter_num > MAX_INI_COUNT) + { + cov_acc *= pow(G_m_s2 / mean_acc.norm(), 2); + imu_need_init_ = false; + + cov_acc = cov_acc_scale; + cov_gyr = cov_gyr_scale; + std::cout << "IMU Initial Done" << std::endl; + // ROS_INFO("IMU Initial Done: Gravity: %.4f %.4f %.4f %.4f; state.bias_g: %.4f %.4f %.4f; acc covarience: %.8f %.8f %.8f; gry covarience: %.8f %.8f %.8f",\ + // imu_state.grav[0], imu_state.grav[1], imu_state.grav[2], mean_acc.norm(), cov_bias_gyr[0], cov_bias_gyr[1], cov_bias_gyr[2], cov_acc[0], cov_acc[1], cov_acc[2], cov_gyr[0], cov_gyr[1], cov_gyr[2]); + fout_imu.open(DEBUG_FILE_DIR("imu.txt"),ios::out); + } + + return; + } + + UndistortPcl(meas, kf_state, *cur_pcl_un_); + + t2 = omp_get_wtime(); + t3 = omp_get_wtime(); + + // cout<<"[ IMU Process ]: Time: "< +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "IMU_Processing.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "preprocess.h" +#include + +#define INIT_TIME (0.1) +#define LASER_POINT_COV (0.001) +#define MAXN (720000) +#define PUBFRAME_PERIOD (20) + +/*** Time Log Variables ***/ +double kdtree_incremental_time = 0.0, kdtree_search_time = 0.0, kdtree_delete_time = 0.0; +double T1[MAXN], s_plot[MAXN], s_plot2[MAXN], s_plot3[MAXN], s_plot4[MAXN], s_plot5[MAXN], s_plot6[MAXN], s_plot7[MAXN], s_plot8[MAXN], s_plot9[MAXN], s_plot10[MAXN], s_plot11[MAXN]; +double match_time = 0, solve_time = 0, solve_const_H_time = 0; +int kdtree_size_st = 0, kdtree_size_end = 0, add_point_size = 0, kdtree_delete_counter = 0; +bool runtime_pos_log = false, pcd_save_en = false, time_sync_en = false, extrinsic_est_en = true, path_en = true; +/**************************/ + +float res_last[100000] = {0.0}; +float DET_RANGE = 300.0f; +const float MOV_THRESHOLD = 1.5f; +double time_diff_lidar_to_imu = 0.0; + +mutex mtx_buffer; +condition_variable sig_buffer; + +string root_dir = ROOT_DIR; +string map_file_path, lid_topic, imu_topic; + +double res_mean_last = 0.05, total_residual = 0.0; +double last_timestamp_lidar = 0, last_timestamp_imu = -1.0; +double gyr_cov = 0.1, acc_cov = 0.1, b_gyr_cov = 0.0001, b_acc_cov = 0.0001; +double filter_size_corner_min = 0, filter_size_surf_min = 0, filter_size_map_min = 0, fov_deg = 0; +double cube_len = 0, HALF_FOV_COS = 0, FOV_DEG = 0, total_distance = 0, lidar_end_time = 0, first_lidar_time = 0.0; +int effct_feat_num = 0, time_log_counter = 0, scan_count = 0, publish_count = 0; +int iterCount = 0, feats_down_size = 0, NUM_MAX_ITERATIONS = 0, laserCloudValidNum = 0, pcd_save_interval = -1, pcd_index = 0; +bool point_selected_surf[100000] = {0}; +bool lidar_pushed, flg_first_scan = true, flg_exit = false, flg_EKF_inited; +bool scan_pub_en = false, dense_pub_en = false, scan_body_pub_en = false; +bool is_first_lidar = true; + +vector> pointSearchInd_surf; +vector cub_needrm; +vector Nearest_Points; +vector extrinT(3, 0.0); +vector extrinR(9, 0.0); +deque time_buffer; +deque lidar_buffer; +deque imu_buffer; + +PointCloudXYZI::Ptr featsFromMap(new PointCloudXYZI()); +PointCloudXYZI::Ptr feats_undistort(new PointCloudXYZI()); +PointCloudXYZI::Ptr feats_down_body(new PointCloudXYZI()); +PointCloudXYZI::Ptr feats_down_world(new PointCloudXYZI()); +PointCloudXYZI::Ptr normvec(new PointCloudXYZI(100000, 1)); +PointCloudXYZI::Ptr laserCloudOri(new PointCloudXYZI(100000, 1)); +PointCloudXYZI::Ptr corr_normvect(new PointCloudXYZI(100000, 1)); +PointCloudXYZI::Ptr _featsArray; + +pcl::VoxelGrid downSizeFilterSurf; +pcl::VoxelGrid downSizeFilterMap; + +KD_TREE ikdtree; + +V3F XAxisPoint_body(LIDAR_SP_LEN, 0.0, 0.0); +V3F XAxisPoint_world(LIDAR_SP_LEN, 0.0, 0.0); +V3D euler_cur; +V3D position_last(Zero3d); +V3D Lidar_T_wrt_IMU(Zero3d); +M3D Lidar_R_wrt_IMU(Eye3d); + +/*** EKF inputs and output ***/ +MeasureGroup Measures; +esekfom::esekf kf; +state_ikfom state_point; +vect3 pos_lid; + +nav_msgs::msg::Path path; +nav_msgs::msg::Odometry odomAftMapped; +geometry_msgs::msg::Quaternion geoQuat; +geometry_msgs::msg::PoseStamped msg_body_pose; + +shared_ptr p_pre(new Preprocess()); +shared_ptr p_imu(new ImuProcess()); + +void SigHandle(int sig) +{ + flg_exit = true; + std::cout << "catch sig %d" << sig << std::endl; + sig_buffer.notify_all(); + rclcpp::shutdown(); +} + +inline void dump_lio_state_to_log(FILE *fp) +{ + V3D rot_ang(Log(state_point.rot.toRotationMatrix())); + fprintf(fp, "%lf ", Measures.lidar_beg_time - first_lidar_time); + fprintf(fp, "%lf %lf %lf ", rot_ang(0), rot_ang(1), rot_ang(2)); // Angle + fprintf(fp, "%lf %lf %lf ", state_point.pos(0), state_point.pos(1), state_point.pos(2)); // Pos + fprintf(fp, "%lf %lf %lf ", 0.0, 0.0, 0.0); // omega + fprintf(fp, "%lf %lf %lf ", state_point.vel(0), state_point.vel(1), state_point.vel(2)); // Vel + fprintf(fp, "%lf %lf %lf ", 0.0, 0.0, 0.0); // Acc + fprintf(fp, "%lf %lf %lf ", state_point.bg(0), state_point.bg(1), state_point.bg(2)); // Bias_g + fprintf(fp, "%lf %lf %lf ", state_point.ba(0), state_point.ba(1), state_point.ba(2)); // Bias_a + fprintf(fp, "%lf %lf %lf ", state_point.grav[0], state_point.grav[1], state_point.grav[2]); // Bias_a + fprintf(fp, "\r\n"); + fflush(fp); +} + +void pointBodyToWorld_ikfom(PointType const * const pi, PointType * const po, state_ikfom &s) +{ + V3D p_body(pi->x, pi->y, pi->z); + V3D p_global(s.rot * (s.offset_R_L_I*p_body + s.offset_T_L_I) + s.pos); + + po->x = p_global(0); + po->y = p_global(1); + po->z = p_global(2); + po->intensity = pi->intensity; +} + + +void pointBodyToWorld(PointType const * const pi, PointType * const po) +{ + V3D p_body(pi->x, pi->y, pi->z); + V3D p_global(state_point.rot * (state_point.offset_R_L_I*p_body + state_point.offset_T_L_I) + state_point.pos); + + po->x = p_global(0); + po->y = p_global(1); + po->z = p_global(2); + po->intensity = pi->intensity; +} + +template +void pointBodyToWorld(const Matrix &pi, Matrix &po) +{ + V3D p_body(pi[0], pi[1], pi[2]); + V3D p_global(state_point.rot * (state_point.offset_R_L_I*p_body + state_point.offset_T_L_I) + state_point.pos); + + po[0] = p_global(0); + po[1] = p_global(1); + po[2] = p_global(2); +} + +void RGBpointBodyToWorld(PointType const * const pi, PointType * const po) +{ + V3D p_body(pi->x, pi->y, pi->z); + V3D p_global(state_point.rot * (state_point.offset_R_L_I*p_body + state_point.offset_T_L_I) + state_point.pos); + + po->x = p_global(0); + po->y = p_global(1); + po->z = p_global(2); + po->intensity = pi->intensity; +} + +void RGBpointBodyLidarToIMU(PointType const * const pi, PointType * const po) +{ + V3D p_body_lidar(pi->x, pi->y, pi->z); + V3D p_body_imu(state_point.offset_R_L_I*p_body_lidar + state_point.offset_T_L_I); + + po->x = p_body_imu(0); + po->y = p_body_imu(1); + po->z = p_body_imu(2); + po->intensity = pi->intensity; +} + +void points_cache_collect() +{ + PointVector points_history; + ikdtree.acquire_removed_points(points_history); + // for (int i = 0; i < points_history.size(); i++) _featsArray->push_back(points_history[i]); +} + +BoxPointType LocalMap_Points; +bool Localmap_Initialized = false; +void lasermap_fov_segment() +{ + cub_needrm.clear(); + kdtree_delete_counter = 0; + kdtree_delete_time = 0.0; + pointBodyToWorld(XAxisPoint_body, XAxisPoint_world); + V3D pos_LiD = pos_lid; + if (!Localmap_Initialized){ + for (int i = 0; i < 3; i++){ + LocalMap_Points.vertex_min[i] = pos_LiD(i) - cube_len / 2.0; + LocalMap_Points.vertex_max[i] = pos_LiD(i) + cube_len / 2.0; + } + Localmap_Initialized = true; + return; + } + float dist_to_map_edge[3][2]; + bool need_move = false; + for (int i = 0; i < 3; i++){ + dist_to_map_edge[i][0] = fabs(pos_LiD(i) - LocalMap_Points.vertex_min[i]); + dist_to_map_edge[i][1] = fabs(pos_LiD(i) - LocalMap_Points.vertex_max[i]); + if (dist_to_map_edge[i][0] <= MOV_THRESHOLD * DET_RANGE || dist_to_map_edge[i][1] <= MOV_THRESHOLD * DET_RANGE) need_move = true; + } + if (!need_move) return; + BoxPointType New_LocalMap_Points, tmp_boxpoints; + New_LocalMap_Points = LocalMap_Points; + float mov_dist = max((cube_len - 2.0 * MOV_THRESHOLD * DET_RANGE) * 0.5 * 0.9, double(DET_RANGE * (MOV_THRESHOLD -1))); + for (int i = 0; i < 3; i++){ + tmp_boxpoints = LocalMap_Points; + if (dist_to_map_edge[i][0] <= MOV_THRESHOLD * DET_RANGE){ + New_LocalMap_Points.vertex_max[i] -= mov_dist; + New_LocalMap_Points.vertex_min[i] -= mov_dist; + tmp_boxpoints.vertex_min[i] = LocalMap_Points.vertex_max[i] - mov_dist; + cub_needrm.push_back(tmp_boxpoints); + } else if (dist_to_map_edge[i][1] <= MOV_THRESHOLD * DET_RANGE){ + New_LocalMap_Points.vertex_max[i] += mov_dist; + New_LocalMap_Points.vertex_min[i] += mov_dist; + tmp_boxpoints.vertex_max[i] = LocalMap_Points.vertex_min[i] + mov_dist; + cub_needrm.push_back(tmp_boxpoints); + } + } + LocalMap_Points = New_LocalMap_Points; + + points_cache_collect(); + double delete_begin = omp_get_wtime(); + if(cub_needrm.size() > 0) kdtree_delete_counter = ikdtree.Delete_Point_Boxes(cub_needrm); + kdtree_delete_time = omp_get_wtime() - delete_begin; +} + +void standard_pcl_cbk(const sensor_msgs::msg::PointCloud2::UniquePtr msg) +{ + mtx_buffer.lock(); + scan_count ++; + double cur_time = get_time_sec(msg->header.stamp); + double preprocess_start_time = omp_get_wtime(); + if (!is_first_lidar && cur_time < last_timestamp_lidar) + { + std::cerr << "lidar loop back, clear buffer" << std::endl; + lidar_buffer.clear(); + } + if (is_first_lidar) + { + is_first_lidar = false; + } + + PointCloudXYZI::Ptr ptr(new PointCloudXYZI()); + p_pre->process(msg, ptr); + lidar_buffer.push_back(ptr); + time_buffer.push_back(cur_time); + last_timestamp_lidar = cur_time; + s_plot11[scan_count] = omp_get_wtime() - preprocess_start_time; + mtx_buffer.unlock(); + sig_buffer.notify_all(); +} + +double timediff_lidar_wrt_imu = 0.0; +bool timediff_set_flg = false; +void livox_pcl_cbk(const livox_ros_driver2::msg::CustomMsg::UniquePtr msg) +{ + mtx_buffer.lock(); + double cur_time = get_time_sec(msg->header.stamp); + double preprocess_start_time = omp_get_wtime(); + scan_count ++; + if (!is_first_lidar && cur_time < last_timestamp_lidar) + { + std::cerr << "lidar loop back, clear buffer" << std::endl; + lidar_buffer.clear(); + } + if(is_first_lidar) + { + is_first_lidar = false; + } + last_timestamp_lidar = cur_time; + + if (!time_sync_en && abs(last_timestamp_imu - last_timestamp_lidar) > 10.0 && !imu_buffer.empty() && !lidar_buffer.empty() ) + { + printf("IMU and LiDAR not Synced, IMU time: %lf, lidar header time: %lf \n",last_timestamp_imu, last_timestamp_lidar); + } + + if (time_sync_en && !timediff_set_flg && abs(last_timestamp_lidar - last_timestamp_imu) > 1 && !imu_buffer.empty()) + { + timediff_set_flg = true; + timediff_lidar_wrt_imu = last_timestamp_lidar + 0.1 - last_timestamp_imu; + printf("Self sync IMU and LiDAR, time diff is %.10lf \n", timediff_lidar_wrt_imu); + } + + PointCloudXYZI::Ptr ptr(new PointCloudXYZI()); + p_pre->process(msg, ptr); + lidar_buffer.push_back(ptr); + time_buffer.push_back(last_timestamp_lidar); + + s_plot11[scan_count] = omp_get_wtime() - preprocess_start_time; + mtx_buffer.unlock(); + sig_buffer.notify_all(); +} + +void imu_cbk(const sensor_msgs::msg::Imu::UniquePtr msg_in) +{ + publish_count ++; + // cout<<"IMU got at: "<header.stamp.toSec()<header.stamp = get_ros_time(get_time_sec(msg_in->header.stamp) - time_diff_lidar_to_imu); + if (abs(timediff_lidar_wrt_imu) > 0.1 && time_sync_en) + { + msg->header.stamp = \ + rclcpp::Time(timediff_lidar_wrt_imu + get_time_sec(msg_in->header.stamp)); + } + + double timestamp = get_time_sec(msg->header.stamp); + + mtx_buffer.lock(); + + if (timestamp < last_timestamp_imu) + { + std::cerr << "lidar loop back, clear buffer" << std::endl; + imu_buffer.clear(); + } + + last_timestamp_imu = timestamp; + + imu_buffer.push_back(msg); + mtx_buffer.unlock(); + sig_buffer.notify_all(); +} + +double lidar_mean_scantime = 0.0; +int scan_num = 0; +bool sync_packages(MeasureGroup &meas) +{ + if (lidar_buffer.empty() || imu_buffer.empty()) { + return false; + } + + /*** push a lidar scan ***/ + if(!lidar_pushed) + { + meas.lidar = lidar_buffer.front(); + meas.lidar_beg_time = time_buffer.front(); + if (meas.lidar->points.size() <= 1) // time too little + { + lidar_end_time = meas.lidar_beg_time + lidar_mean_scantime; + std::cerr << "Too few input point cloud!\n"; + } + else if (meas.lidar->points.back().curvature / double(1000) < 0.5 * lidar_mean_scantime) + { + lidar_end_time = meas.lidar_beg_time + lidar_mean_scantime; + } + else + { + scan_num ++; + lidar_end_time = meas.lidar_beg_time + meas.lidar->points.back().curvature / double(1000); + lidar_mean_scantime += (meas.lidar->points.back().curvature / double(1000) - lidar_mean_scantime) / scan_num; + } + + meas.lidar_end_time = lidar_end_time; + + lidar_pushed = true; + } + + if (last_timestamp_imu < lidar_end_time) + { + return false; + } + + /*** push imu data, and pop from imu buffer ***/ + double imu_time = get_time_sec(imu_buffer.front()->header.stamp); + meas.imu.clear(); + while ((!imu_buffer.empty()) && (imu_time < lidar_end_time)) + { + imu_time = get_time_sec(imu_buffer.front()->header.stamp); + if(imu_time > lidar_end_time) break; + meas.imu.push_back(imu_buffer.front()); + imu_buffer.pop_front(); + } + + lidar_buffer.pop_front(); + time_buffer.pop_front(); + lidar_pushed = false; + return true; +} + +int process_increments = 0; +void map_incremental() +{ + PointVector PointToAdd; + PointVector PointNoNeedDownsample; + PointToAdd.reserve(feats_down_size); + PointNoNeedDownsample.reserve(feats_down_size); + for (int i = 0; i < feats_down_size; i++) + { + /* transform to world frame */ + pointBodyToWorld(&(feats_down_body->points[i]), &(feats_down_world->points[i])); + /* decide if need add to map */ + if (!Nearest_Points[i].empty() && flg_EKF_inited) + { + const PointVector &points_near = Nearest_Points[i]; + bool need_add = true; + BoxPointType Box_of_Point; + PointType downsample_result, mid_point; + mid_point.x = floor(feats_down_world->points[i].x/filter_size_map_min)*filter_size_map_min + 0.5 * filter_size_map_min; + mid_point.y = floor(feats_down_world->points[i].y/filter_size_map_min)*filter_size_map_min + 0.5 * filter_size_map_min; + mid_point.z = floor(feats_down_world->points[i].z/filter_size_map_min)*filter_size_map_min + 0.5 * filter_size_map_min; + float dist = calc_dist(feats_down_world->points[i],mid_point); + if (fabs(points_near[0].x - mid_point.x) > 0.5 * filter_size_map_min && fabs(points_near[0].y - mid_point.y) > 0.5 * filter_size_map_min && fabs(points_near[0].z - mid_point.z) > 0.5 * filter_size_map_min){ + PointNoNeedDownsample.push_back(feats_down_world->points[i]); + continue; + } + for (int readd_i = 0; readd_i < NUM_MATCH_POINTS; readd_i ++) + { + if (points_near.size() < NUM_MATCH_POINTS) break; + if (calc_dist(points_near[readd_i], mid_point) < dist) + { + need_add = false; + break; + } + } + if (need_add) PointToAdd.push_back(feats_down_world->points[i]); + } + else + { + PointToAdd.push_back(feats_down_world->points[i]); + } + } + + double st_time = omp_get_wtime(); + add_point_size = ikdtree.Add_Points(PointToAdd, true); + ikdtree.Add_Points(PointNoNeedDownsample, false); + add_point_size = PointToAdd.size() + PointNoNeedDownsample.size(); + kdtree_incremental_time = omp_get_wtime() - st_time; +} + +PointCloudXYZI::Ptr pcl_wait_pub(new PointCloudXYZI()); +PointCloudXYZI::Ptr pcl_wait_save(new PointCloudXYZI()); +void publish_frame_world(rclcpp::Publisher::SharedPtr pubLaserCloudFull) +{ + if(scan_pub_en) + { + PointCloudXYZI::Ptr laserCloudFullRes(dense_pub_en ? feats_undistort : feats_down_body); + int size = laserCloudFullRes->points.size(); + PointCloudXYZI::Ptr laserCloudWorld( \ + new PointCloudXYZI(size, 1)); + + for (int i = 0; i < size; i++) + { + RGBpointBodyToWorld(&laserCloudFullRes->points[i], \ + &laserCloudWorld->points[i]); + } + + sensor_msgs::msg::PointCloud2 laserCloudmsg; + pcl::toROSMsg(*laserCloudWorld, laserCloudmsg); + // laserCloudmsg.header.stamp = ros::Time().fromSec(lidar_end_time); + laserCloudmsg.header.stamp = get_ros_time(lidar_end_time); + laserCloudmsg.header.frame_id = "camera_init"; + pubLaserCloudFull->publish(laserCloudmsg); + publish_count -= PUBFRAME_PERIOD; + } + + if (pcd_save_en) + { + int size = feats_undistort->points.size(); + PointCloudXYZI::Ptr laserCloudWorld( \ + new PointCloudXYZI(size, 1)); + + for (int i = 0; i < size; i++) + { + RGBpointBodyToWorld(&feats_undistort->points[i], \ + &laserCloudWorld->points[i]); + } + *pcl_wait_save += *laserCloudWorld; + + static int scan_wait_num = 0; + scan_wait_num ++; + if (pcl_wait_save->size() > 0 && pcd_save_interval > 0 && scan_wait_num >= pcd_save_interval) + { + pcd_index ++; + string all_points_dir(string(string(ROOT_DIR) + "PCD/scans_") + to_string(pcd_index) + string(".pcd")); + pcl::PCDWriter pcd_writer; + cout << "current scan saved to /PCD/" << all_points_dir << endl; + pcd_writer.writeBinary(all_points_dir, *pcl_wait_save); + pcl_wait_save->clear(); + scan_wait_num = 0; + } + } + +} + +void publish_frame_body(rclcpp::Publisher::SharedPtr pubLaserCloudFull_body) +{ + int size = feats_undistort->points.size(); + PointCloudXYZI::Ptr laserCloudIMUBody(new PointCloudXYZI(size, 1)); + + for (int i = 0; i < size; i++) + { + RGBpointBodyLidarToIMU(&feats_undistort->points[i], \ + &laserCloudIMUBody->points[i]); + } + + sensor_msgs::msg::PointCloud2 laserCloudmsg; + pcl::toROSMsg(*laserCloudIMUBody, laserCloudmsg); + laserCloudmsg.header.stamp = get_ros_time(lidar_end_time); + laserCloudmsg.header.frame_id = "body"; + pubLaserCloudFull_body->publish(laserCloudmsg); + publish_count -= PUBFRAME_PERIOD; +} + +void publish_effect_world(rclcpp::Publisher::SharedPtr pubLaserCloudEffect) +{ + PointCloudXYZI::Ptr laserCloudWorld( \ + new PointCloudXYZI(effct_feat_num, 1)); + for (int i = 0; i < effct_feat_num; i++) + { + RGBpointBodyToWorld(&laserCloudOri->points[i], \ + &laserCloudWorld->points[i]); + } + sensor_msgs::msg::PointCloud2 laserCloudFullRes3; + pcl::toROSMsg(*laserCloudWorld, laserCloudFullRes3); + laserCloudFullRes3.header.stamp = get_ros_time(lidar_end_time); + laserCloudFullRes3.header.frame_id = "camera_init"; + pubLaserCloudEffect->publish(laserCloudFullRes3); +} + +void publish_map(rclcpp::Publisher::SharedPtr pubLaserCloudMap) +{ + PointCloudXYZI::Ptr laserCloudFullRes(dense_pub_en ? feats_undistort : feats_down_body); + int size = laserCloudFullRes->points.size(); + PointCloudXYZI::Ptr laserCloudWorld( \ + new PointCloudXYZI(size, 1)); + + for (int i = 0; i < size; i++) + { + RGBpointBodyToWorld(&laserCloudFullRes->points[i], \ + &laserCloudWorld->points[i]); + } + *pcl_wait_pub += *laserCloudWorld; + + sensor_msgs::msg::PointCloud2 laserCloudmsg; + pcl::toROSMsg(*pcl_wait_pub, laserCloudmsg); + // laserCloudmsg.header.stamp = ros::Time().fromSec(lidar_end_time); + laserCloudmsg.header.stamp = get_ros_time(lidar_end_time); + laserCloudmsg.header.frame_id = "camera_init"; + pubLaserCloudMap->publish(laserCloudmsg); + + // sensor_msgs::msg::PointCloud2 laserCloudMap; + // pcl::toROSMsg(*featsFromMap, laserCloudMap); + // laserCloudMap.header.stamp = get_ros_time(lidar_end_time); + // laserCloudMap.header.frame_id = "camera_init"; + // pubLaserCloudMap->publish(laserCloudMap); +} + +void save_to_pcd() +{ + pcl::PCDWriter pcd_writer; + pcd_writer.writeBinary(map_file_path, *pcl_wait_pub); +} + +template +void set_posestamp(T & out) +{ + out.pose.position.x = state_point.pos(0); + out.pose.position.y = state_point.pos(1); + out.pose.position.z = state_point.pos(2); + out.pose.orientation.x = geoQuat.x; + out.pose.orientation.y = geoQuat.y; + out.pose.orientation.z = geoQuat.z; + out.pose.orientation.w = geoQuat.w; + +} + +void publish_odometry(const rclcpp::Publisher::SharedPtr pubOdomAftMapped, std::unique_ptr & tf_br) +{ + odomAftMapped.header.frame_id = "camera_init"; + odomAftMapped.child_frame_id = "body"; + odomAftMapped.header.stamp = get_ros_time(lidar_end_time); + set_posestamp(odomAftMapped.pose); + pubOdomAftMapped->publish(odomAftMapped); + auto P = kf.get_P(); + for (int i = 0; i < 6; i ++) + { + int k = i < 3 ? i + 3 : i - 3; + odomAftMapped.pose.covariance[i*6 + 0] = P(k, 3); + odomAftMapped.pose.covariance[i*6 + 1] = P(k, 4); + odomAftMapped.pose.covariance[i*6 + 2] = P(k, 5); + odomAftMapped.pose.covariance[i*6 + 3] = P(k, 0); + odomAftMapped.pose.covariance[i*6 + 4] = P(k, 1); + odomAftMapped.pose.covariance[i*6 + 5] = P(k, 2); + } + + geometry_msgs::msg::TransformStamped trans; + trans.header.frame_id = "camera_init"; + trans.header.stamp = odomAftMapped.header.stamp; + trans.child_frame_id = "body"; + trans.transform.translation.x = odomAftMapped.pose.pose.position.x; + trans.transform.translation.y = odomAftMapped.pose.pose.position.y; + trans.transform.translation.z = odomAftMapped.pose.pose.position.z; + trans.transform.rotation.w = odomAftMapped.pose.pose.orientation.w; + trans.transform.rotation.x = odomAftMapped.pose.pose.orientation.x; + trans.transform.rotation.y = odomAftMapped.pose.pose.orientation.y; + trans.transform.rotation.z = odomAftMapped.pose.pose.orientation.z; + tf_br->sendTransform(trans); +} + +void publish_path(rclcpp::Publisher::SharedPtr pubPath) +{ + set_posestamp(msg_body_pose); + msg_body_pose.header.stamp = get_ros_time(lidar_end_time); // ros::Time().fromSec(lidar_end_time); + msg_body_pose.header.frame_id = "camera_init"; + + /*** if path is too large, the rvis will crash ***/ + static int jjj = 0; + jjj++; + if (jjj % 10 == 0) + { + path.poses.push_back(msg_body_pose); + pubPath->publish(path); + } +} + +void h_share_model(state_ikfom &s, esekfom::dyn_share_datastruct &ekfom_data) +{ + double match_start = omp_get_wtime(); + laserCloudOri->clear(); + corr_normvect->clear(); + total_residual = 0.0; + + /** closest surface search and residual computation **/ + #ifdef MP_EN + omp_set_num_threads(MP_PROC_NUM); + #pragma omp parallel for + #endif + for (int i = 0; i < feats_down_size; i++) + { + PointType &point_body = feats_down_body->points[i]; + PointType &point_world = feats_down_world->points[i]; + + /* transform to world frame */ + V3D p_body(point_body.x, point_body.y, point_body.z); + V3D p_global(s.rot * (s.offset_R_L_I*p_body + s.offset_T_L_I) + s.pos); + point_world.x = p_global(0); + point_world.y = p_global(1); + point_world.z = p_global(2); + point_world.intensity = point_body.intensity; + + vector pointSearchSqDis(NUM_MATCH_POINTS); + + auto &points_near = Nearest_Points[i]; + + if (ekfom_data.converge) + { + /** Find the closest surfaces in the map **/ + ikdtree.Nearest_Search(point_world, NUM_MATCH_POINTS, points_near, pointSearchSqDis); + point_selected_surf[i] = points_near.size() < NUM_MATCH_POINTS ? false : pointSearchSqDis[NUM_MATCH_POINTS - 1] > 5 ? false : true; + } + + if (!point_selected_surf[i]) continue; + + VF(4) pabcd; + point_selected_surf[i] = false; + if (esti_plane(pabcd, points_near, 0.1f)) + { + float pd2 = pabcd(0) * point_world.x + pabcd(1) * point_world.y + pabcd(2) * point_world.z + pabcd(3); + float s = 1 - 0.9 * fabs(pd2) / sqrt(p_body.norm()); + + if (s > 0.9) + { + point_selected_surf[i] = true; + normvec->points[i].x = pabcd(0); + normvec->points[i].y = pabcd(1); + normvec->points[i].z = pabcd(2); + normvec->points[i].intensity = pd2; + res_last[i] = abs(pd2); + } + } + } + + effct_feat_num = 0; + + for (int i = 0; i < feats_down_size; i++) + { + if (point_selected_surf[i]) + { + laserCloudOri->points[effct_feat_num] = feats_down_body->points[i]; + corr_normvect->points[effct_feat_num] = normvec->points[i]; + total_residual += res_last[i]; + effct_feat_num ++; + } + } + + if (effct_feat_num < 1) + { + ekfom_data.valid = false; + std::cerr << "No Effective Points!" << std::endl; + // ROS_WARN("No Effective Points! \n"); + return; + } + + res_mean_last = total_residual / effct_feat_num; + match_time += omp_get_wtime() - match_start; + double solve_start_ = omp_get_wtime(); + + /*** Computation of Measuremnt Jacobian matrix H and measurents vector ***/ + ekfom_data.h_x = MatrixXd::Zero(effct_feat_num, 12); //23 + ekfom_data.h.resize(effct_feat_num); + + for (int i = 0; i < effct_feat_num; i++) + { + const PointType &laser_p = laserCloudOri->points[i]; + V3D point_this_be(laser_p.x, laser_p.y, laser_p.z); + M3D point_be_crossmat; + point_be_crossmat << SKEW_SYM_MATRX(point_this_be); + V3D point_this = s.offset_R_L_I * point_this_be + s.offset_T_L_I; + M3D point_crossmat; + point_crossmat<points[i]; + V3D norm_vec(norm_p.x, norm_p.y, norm_p.z); + + /*** calculate the Measuremnt Jacobian matrix H ***/ + V3D C(s.rot.conjugate() *norm_vec); + V3D A(point_crossmat * C); + if (extrinsic_est_en) + { + V3D B(point_be_crossmat * s.offset_R_L_I.conjugate() * C); //s.rot.conjugate()*norm_vec); + ekfom_data.h_x.block<1, 12>(i,0) << norm_p.x, norm_p.y, norm_p.z, VEC_FROM_ARRAY(A), VEC_FROM_ARRAY(B), VEC_FROM_ARRAY(C); + } + else + { + ekfom_data.h_x.block<1, 12>(i,0) << norm_p.x, norm_p.y, norm_p.z, VEC_FROM_ARRAY(A), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0; + } + + /*** Measuremnt: distance to the closest surface/corner ***/ + ekfom_data.h(i) = -norm_p.intensity; + } + solve_time += omp_get_wtime() - solve_start_; +} + +class LaserMappingNode : public rclcpp::Node +{ +public: + LaserMappingNode(const rclcpp::NodeOptions& options = rclcpp::NodeOptions()) : Node("laser_mapping", options) + { + this->declare_parameter("publish.path_en", true); + this->declare_parameter("publish.effect_map_en", false); + this->declare_parameter("publish.map_en", false); + this->declare_parameter("publish.scan_publish_en", true); + this->declare_parameter("publish.dense_publish_en", true); + this->declare_parameter("publish.scan_bodyframe_pub_en", true); + this->declare_parameter("max_iteration", 4); + this->declare_parameter("map_file_path", ""); + this->declare_parameter("common.lid_topic", "/livox/lidar"); + this->declare_parameter("common.imu_topic", "/livox/imu"); + this->declare_parameter("common.time_sync_en", false); + this->declare_parameter("common.time_offset_lidar_to_imu", 0.0); + this->declare_parameter("filter_size_corner", 0.5); + this->declare_parameter("filter_size_surf", 0.5); + this->declare_parameter("filter_size_map", 0.5); + this->declare_parameter("cube_side_length", 200.); + this->declare_parameter("mapping.det_range", 300.); + this->declare_parameter("mapping.fov_degree", 180.); + this->declare_parameter("mapping.gyr_cov", 0.1); + this->declare_parameter("mapping.acc_cov", 0.1); + this->declare_parameter("mapping.b_gyr_cov", 0.0001); + this->declare_parameter("mapping.b_acc_cov", 0.0001); + this->declare_parameter("preprocess.blind", 0.01); + this->declare_parameter("preprocess.lidar_type", AVIA); + this->declare_parameter("preprocess.scan_line", 16); + this->declare_parameter("preprocess.timestamp_unit", US); + this->declare_parameter("preprocess.scan_rate", 10); + this->declare_parameter("point_filter_num", 2); + this->declare_parameter("feature_extract_enable", false); + this->declare_parameter("runtime_pos_log_enable", false); + this->declare_parameter("mapping.extrinsic_est_en", true); + this->declare_parameter("pcd_save.pcd_save_en", false); + this->declare_parameter("pcd_save.interval", -1); + this->declare_parameter>("mapping.extrinsic_T", vector()); + this->declare_parameter>("mapping.extrinsic_R", vector()); + + this->get_parameter_or("publish.path_en", path_en, true); + this->get_parameter_or("publish.effect_map_en", effect_pub_en, false); + this->get_parameter_or("publish.map_en", map_pub_en, false); + this->get_parameter_or("publish.scan_publish_en", scan_pub_en, true); + this->get_parameter_or("publish.dense_publish_en", dense_pub_en, true); + this->get_parameter_or("publish.scan_bodyframe_pub_en", scan_body_pub_en, true); + this->get_parameter_or("max_iteration", NUM_MAX_ITERATIONS, 4); + this->get_parameter_or("map_file_path", map_file_path, ""); + this->get_parameter_or("common.lid_topic", lid_topic, "/livox/lidar"); + this->get_parameter_or("common.imu_topic", imu_topic,"/livox/imu"); + this->get_parameter_or("common.time_sync_en", time_sync_en, false); + this->get_parameter_or("common.time_offset_lidar_to_imu", time_diff_lidar_to_imu, 0.0); + this->get_parameter_or("filter_size_corner",filter_size_corner_min,0.5); + this->get_parameter_or("filter_size_surf",filter_size_surf_min,0.5); + this->get_parameter_or("filter_size_map",filter_size_map_min,0.5); + this->get_parameter_or("cube_side_length",cube_len,200.f); + this->get_parameter_or("mapping.det_range",DET_RANGE,300.f); + this->get_parameter_or("mapping.fov_degree",fov_deg,180.f); + this->get_parameter_or("mapping.gyr_cov",gyr_cov,0.1); + this->get_parameter_or("mapping.acc_cov",acc_cov,0.1); + this->get_parameter_or("mapping.b_gyr_cov",b_gyr_cov,0.0001); + this->get_parameter_or("mapping.b_acc_cov",b_acc_cov,0.0001); + this->get_parameter_or("preprocess.blind", p_pre->blind, 0.01); + this->get_parameter_or("preprocess.lidar_type", p_pre->lidar_type, AVIA); + this->get_parameter_or("preprocess.scan_line", p_pre->N_SCANS, 16); + this->get_parameter_or("preprocess.timestamp_unit", p_pre->time_unit, US); + this->get_parameter_or("preprocess.scan_rate", p_pre->SCAN_RATE, 10); + this->get_parameter_or("point_filter_num", p_pre->point_filter_num, 2); + this->get_parameter_or("feature_extract_enable", p_pre->feature_enabled, false); + this->get_parameter_or("runtime_pos_log_enable", runtime_pos_log, 0); + this->get_parameter_or("mapping.extrinsic_est_en", extrinsic_est_en, true); + this->get_parameter_or("pcd_save.pcd_save_en", pcd_save_en, false); + this->get_parameter_or("pcd_save.interval", pcd_save_interval, -1); + this->get_parameter_or>("mapping.extrinsic_T", extrinT, vector()); + this->get_parameter_or>("mapping.extrinsic_R", extrinR, vector()); + + RCLCPP_INFO(this->get_logger(), "p_pre->lidar_type %d", p_pre->lidar_type); + + path.header.stamp = this->get_clock()->now(); + path.header.frame_id ="camera_init"; + + // /*** variables definition ***/ + // int effect_feat_num = 0, frame_num = 0; + // double deltaT, deltaR, aver_time_consu = 0, aver_time_icp = 0, aver_time_match = 0, aver_time_incre = 0, aver_time_solve = 0, aver_time_const_H_time = 0; + // bool flg_EKF_converged, EKF_stop_flg = 0; + + FOV_DEG = (fov_deg + 10.0) > 179.9 ? 179.9 : (fov_deg + 10.0); + HALF_FOV_COS = cos((FOV_DEG) * 0.5 * PI_M / 180.0); + + _featsArray.reset(new PointCloudXYZI()); + + memset(point_selected_surf, true, sizeof(point_selected_surf)); + memset(res_last, -1000.0f, sizeof(res_last)); + downSizeFilterSurf.setLeafSize(filter_size_surf_min, filter_size_surf_min, filter_size_surf_min); + downSizeFilterMap.setLeafSize(filter_size_map_min, filter_size_map_min, filter_size_map_min); + memset(point_selected_surf, true, sizeof(point_selected_surf)); + memset(res_last, -1000.0f, sizeof(res_last)); + + Lidar_T_wrt_IMU<set_extrinsic(Lidar_T_wrt_IMU, Lidar_R_wrt_IMU); + p_imu->set_gyr_cov(V3D(gyr_cov, gyr_cov, gyr_cov)); + p_imu->set_acc_cov(V3D(acc_cov, acc_cov, acc_cov)); + p_imu->set_gyr_bias_cov(V3D(b_gyr_cov, b_gyr_cov, b_gyr_cov)); + p_imu->set_acc_bias_cov(V3D(b_acc_cov, b_acc_cov, b_acc_cov)); + + fill(epsi, epsi+23, 0.001); + kf.init_dyn_share(get_f, df_dx, df_dw, h_share_model, NUM_MAX_ITERATIONS, epsi); + + /*** debug record ***/ + // FILE *fp; + string pos_log_dir = root_dir + "/Log/pos_log.txt"; + fp = fopen(pos_log_dir.c_str(),"w"); + + // ofstream fout_pre, fout_out, fout_dbg; + fout_pre.open(DEBUG_FILE_DIR("mat_pre.txt"),ios::out); + fout_out.open(DEBUG_FILE_DIR("mat_out.txt"),ios::out); + fout_dbg.open(DEBUG_FILE_DIR("dbg.txt"),ios::out); + if (fout_pre && fout_out) + cout << "~~~~"<lidar_type == AVIA) + { + sub_pcl_livox_ = this->create_subscription(lid_topic, 20, livox_pcl_cbk); + } + else + { + sub_pcl_pc_ = this->create_subscription(lid_topic, rclcpp::SensorDataQoS(), standard_pcl_cbk); + } + sub_imu_ = this->create_subscription(imu_topic, 10, imu_cbk); + pubLaserCloudFull_ = this->create_publisher("/cloud_registered", 20); + pubLaserCloudFull_body_ = this->create_publisher("/cloud_registered_body", 20); + pubLaserCloudEffect_ = this->create_publisher("/cloud_effected", 20); + pubLaserCloudMap_ = this->create_publisher("/Laser_map", 20); + pubOdomAftMapped_ = this->create_publisher("/Odometry", 20); + pubPath_ = this->create_publisher("/path", 20); + tf_broadcaster_ = std::make_unique(*this); + + //------------------------------------------------------------------------------------------------------ + auto period_ms = std::chrono::milliseconds(static_cast(1000.0 / 100.0)); + timer_ = rclcpp::create_timer(this, this->get_clock(), period_ms, std::bind(&LaserMappingNode::timer_callback, this)); + + auto map_period_ms = std::chrono::milliseconds(static_cast(1000.0)); + map_pub_timer_ = rclcpp::create_timer(this, this->get_clock(), map_period_ms, std::bind(&LaserMappingNode::map_publish_callback, this)); + + map_save_srv_ = this->create_service("map_save", std::bind(&LaserMappingNode::map_save_callback, this, std::placeholders::_1, std::placeholders::_2)); + + RCLCPP_INFO(this->get_logger(), "Node init finished."); + } + + ~LaserMappingNode() + { + fout_out.close(); + fout_pre.close(); + fclose(fp); + } + +private: + void timer_callback() + { + if(sync_packages(Measures)) + { + if (flg_first_scan) + { + first_lidar_time = Measures.lidar_beg_time; + p_imu->first_lidar_time = first_lidar_time; + flg_first_scan = false; + return; + } + + double t0,t1,t2,t3,t4,t5,match_start, solve_start, svd_time; + + match_time = 0; + kdtree_search_time = 0.0; + solve_time = 0; + solve_const_H_time = 0; + svd_time = 0; + t0 = omp_get_wtime(); + + p_imu->Process(Measures, kf, feats_undistort); + state_point = kf.get_x(); + pos_lid = state_point.pos + state_point.rot * state_point.offset_T_L_I; + + if (feats_undistort->empty() || (feats_undistort == NULL)) + { + RCLCPP_WARN(this->get_logger(), "No point, skip this scan!\n"); + return; + } + + flg_EKF_inited = (Measures.lidar_beg_time - first_lidar_time) < INIT_TIME ? \ + false : true; + /*** Segment the map in lidar FOV ***/ + lasermap_fov_segment(); + + /*** downsample the feature points in a scan ***/ + downSizeFilterSurf.setInputCloud(feats_undistort); + downSizeFilterSurf.filter(*feats_down_body); + t1 = omp_get_wtime(); + feats_down_size = feats_down_body->points.size(); + /*** initialize the map kdtree ***/ + if(ikdtree.Root_Node == nullptr) + { + RCLCPP_INFO(this->get_logger(), "Initialize the map kdtree"); + if(feats_down_size > 5) + { + ikdtree.set_downsample_param(filter_size_map_min); + feats_down_world->resize(feats_down_size); + for(int i = 0; i < feats_down_size; i++) + { + pointBodyToWorld(&(feats_down_body->points[i]), &(feats_down_world->points[i])); + } + ikdtree.Build(feats_down_world->points); + } + return; + } + int featsFromMapNum = ikdtree.validnum(); + kdtree_size_st = ikdtree.size(); + + // cout<<"[ mapping ]: In num: "<points.size()<<" downsamp "<get_logger(), "No point, skip this scan!\n"); + return; + } + + normvec->resize(feats_down_size); + feats_down_world->resize(feats_down_size); + + V3D ext_euler = SO3ToEuler(state_point.offset_R_L_I); + fout_pre<clear(); + featsFromMap->points = ikdtree.PCL_Storage; + } + + pointSearchInd_surf.resize(feats_down_size); + Nearest_Points.resize(feats_down_size); + int rematch_num = 0; + bool nearest_search_en = true; // + + t2 = omp_get_wtime(); + + /*** iterated state estimation ***/ + double t_update_start = omp_get_wtime(); + double solve_H_time = 0; + kf.update_iterated_dyn_share_modified(LASER_POINT_COV, solve_H_time); + state_point = kf.get_x(); + euler_cur = SO3ToEuler(state_point.rot); + pos_lid = state_point.pos + state_point.rot * state_point.offset_T_L_I; + geoQuat.x = state_point.rot.coeffs()[0]; + geoQuat.y = state_point.rot.coeffs()[1]; + geoQuat.z = state_point.rot.coeffs()[2]; + geoQuat.w = state_point.rot.coeffs()[3]; + + double t_update_end = omp_get_wtime(); + + /******* Publish odometry *******/ + publish_odometry(pubOdomAftMapped_, tf_broadcaster_); + + /*** add the feature points to map kdtree ***/ + t3 = omp_get_wtime(); + map_incremental(); + t5 = omp_get_wtime(); + + /******* Publish points *******/ + if (path_en) publish_path(pubPath_); + if (scan_pub_en) publish_frame_world(pubLaserCloudFull_); + if (scan_pub_en && scan_body_pub_en) publish_frame_body(pubLaserCloudFull_body_); + if (effect_pub_en) publish_effect_world(pubLaserCloudEffect_); + // if (map_pub_en) publish_map(pubLaserCloudMap_); + + /*** Debug variables ***/ + if (runtime_pos_log) + { + frame_num ++; + kdtree_size_end = ikdtree.size(); + aver_time_consu = aver_time_consu * (frame_num - 1) / frame_num + (t5 - t0) / frame_num; + aver_time_icp = aver_time_icp * (frame_num - 1)/frame_num + (t_update_end - t_update_start) / frame_num; + aver_time_match = aver_time_match * (frame_num - 1)/frame_num + (match_time)/frame_num; + aver_time_incre = aver_time_incre * (frame_num - 1)/frame_num + (kdtree_incremental_time)/frame_num; + aver_time_solve = aver_time_solve * (frame_num - 1)/frame_num + (solve_time + solve_H_time)/frame_num; + aver_time_const_H_time = aver_time_const_H_time * (frame_num - 1)/frame_num + solve_time / frame_num; + T1[time_log_counter] = Measures.lidar_beg_time; + s_plot[time_log_counter] = t5 - t0; + s_plot2[time_log_counter] = feats_undistort->points.size(); + s_plot3[time_log_counter] = kdtree_incremental_time; + s_plot4[time_log_counter] = kdtree_search_time; + s_plot5[time_log_counter] = kdtree_delete_counter; + s_plot6[time_log_counter] = kdtree_delete_time; + s_plot7[time_log_counter] = kdtree_size_st; + s_plot8[time_log_counter] = kdtree_size_end; + s_plot9[time_log_counter] = aver_time_consu; + s_plot10[time_log_counter] = add_point_size; + time_log_counter ++; + printf("[ mapping ]: time: IMU + Map + Input Downsample: %0.6f ave match: %0.6f ave solve: %0.6f ave ICP: %0.6f map incre: %0.6f ave total: %0.6f icp: %0.6f construct H: %0.6f \n",t1-t0,aver_time_match,aver_time_solve,t3-t1,t5-t3,aver_time_consu,aver_time_icp, aver_time_const_H_time); + ext_euler = SO3ToEuler(state_point.offset_R_L_I); + fout_out << setw(20) << Measures.lidar_beg_time - first_lidar_time << " " << euler_cur.transpose() << " " << state_point.pos.transpose()<< " " << ext_euler.transpose() << " "<points.size()<get_logger(), "Saving map to %s...", map_file_path.c_str()); + if (pcd_save_en) + { + save_to_pcd(); + res->success = true; + res->message = "Map saved."; + } + else + { + res->success = false; + res->message = "Map save disabled."; + } + } + +private: + rclcpp::Publisher::SharedPtr pubLaserCloudFull_; + rclcpp::Publisher::SharedPtr pubLaserCloudFull_body_; + rclcpp::Publisher::SharedPtr pubLaserCloudEffect_; + rclcpp::Publisher::SharedPtr pubLaserCloudMap_; + rclcpp::Publisher::SharedPtr pubOdomAftMapped_; + rclcpp::Publisher::SharedPtr pubPath_; + rclcpp::Subscription::SharedPtr sub_imu_; + rclcpp::Subscription::SharedPtr sub_pcl_pc_; + rclcpp::Subscription::SharedPtr sub_pcl_livox_; + + std::unique_ptr tf_broadcaster_; + rclcpp::TimerBase::SharedPtr timer_; + rclcpp::TimerBase::SharedPtr map_pub_timer_; + rclcpp::Service::SharedPtr map_save_srv_; + + bool effect_pub_en = false, map_pub_en = false; + int effect_feat_num = 0, frame_num = 0; + double deltaT, deltaR, aver_time_consu = 0, aver_time_icp = 0, aver_time_match = 0, aver_time_incre = 0, aver_time_solve = 0, aver_time_const_H_time = 0; + bool flg_EKF_converged, EKF_stop_flg = 0; + double epsi[23] = {0.001}; + + FILE *fp; + ofstream fout_pre, fout_out, fout_dbg; +}; + +int main(int argc, char** argv) +{ + rclcpp::init(argc, argv); + + signal(SIGINT, SigHandle); + + rclcpp::spin(std::make_shared()); + + if (rclcpp::ok()) + rclcpp::shutdown(); + /**************** save map ****************/ + /* 1. make sure you have enough memories + /* 2. pcd save will largely influence the real-time performences **/ + if (pcl_wait_save->size() > 0 && pcd_save_en) + { + string file_name = string("scans.pcd"); + string all_points_dir(string(string(ROOT_DIR) + "PCD/") + file_name); + pcl::PCDWriter pcd_writer; + cout << "current scan saved to /PCD/" << file_name< t, s_vec, s_vec2, s_vec3, s_vec4, s_vec5, s_vec6, s_vec7; + FILE *fp2; + string log_dir = root_dir + "/Log/fast_lio_time_log.csv"; + fp2 = fopen(log_dir.c_str(),"w"); + fprintf(fp2,"time_stamp, total time, scan point size, incremental time, search time, delete size, delete time, tree size st, tree size end, add point size, preprocess time\n"); + for (int i = 0;i + +#define RETURN0 0x00 +#define RETURN0AND1 0x10 + +Preprocess::Preprocess() : feature_enabled(0), lidar_type(AVIA), blind(0.01), point_filter_num(1) +{ + inf_bound = 10; + N_SCANS = 6; + SCAN_RATE = 10; + group_size = 8; + disA = 0.01; + disA = 0.1; // B? + p2l_ratio = 225; + limit_maxmid = 6.25; + limit_midmin = 6.25; + limit_maxmin = 3.24; + jump_up_limit = 170.0; + jump_down_limit = 8.0; + cos160 = 160.0; + edgea = 2; + edgeb = 0.1; + smallp_intersect = 172.5; + smallp_ratio = 1.2; + given_offset_time = false; + + jump_up_limit = cos(jump_up_limit / 180 * M_PI); + jump_down_limit = cos(jump_down_limit / 180 * M_PI); + cos160 = cos(cos160 / 180 * M_PI); + smallp_intersect = cos(smallp_intersect / 180 * M_PI); +} + +Preprocess::~Preprocess() +{ +} + +void Preprocess::set(bool feat_en, int lid_type, double bld, int pfilt_num) +{ + feature_enabled = feat_en; + lidar_type = lid_type; + blind = bld; + point_filter_num = pfilt_num; +} + +void Preprocess::process(const livox_ros_driver2::msg::CustomMsg::UniquePtr &msg, PointCloudXYZI::Ptr& pcl_out) +{ + avia_handler(msg); + *pcl_out = pl_surf; +} + +void Preprocess::process(const sensor_msgs::msg::PointCloud2::UniquePtr &msg, PointCloudXYZI::Ptr& pcl_out) +{ + switch (time_unit) + { + case SEC: + time_unit_scale = 1.e3f; + break; + case MS: + time_unit_scale = 1.f; + break; + case US: + time_unit_scale = 1.e-3f; + break; + case NS: + time_unit_scale = 1.e-6f; + break; + default: + time_unit_scale = 1.f; + break; + } + + switch (lidar_type) + { + case OUST64: + oust64_handler(msg); + break; + + case VELO16: + velodyne_handler(msg); + break; + + case MID360: + mid360_handler(msg); + break; + + default: + default_handler(msg); + break; + } + *pcl_out = pl_surf; +} + +void Preprocess::avia_handler(const livox_ros_driver2::msg::CustomMsg::UniquePtr &msg) +{ + pl_surf.clear(); + pl_corn.clear(); + pl_full.clear(); + double t1 = omp_get_wtime(); + int plsize = msg->point_num; + // cout<<"plsie: "<points[i].line < N_SCANS) && + ((msg->points[i].tag & 0x30) == 0x10 || (msg->points[i].tag & 0x30) == 0x00)) + { + pl_full[i].x = msg->points[i].x; + pl_full[i].y = msg->points[i].y; + pl_full[i].z = msg->points[i].z; + pl_full[i].intensity = msg->points[i].reflectivity; + pl_full[i].curvature = + msg->points[i].offset_time / float(1000000); // use curvature as time of each laser points + + bool is_new = false; + if ((abs(pl_full[i].x - pl_full[i - 1].x) > 1e-7) || (abs(pl_full[i].y - pl_full[i - 1].y) > 1e-7) || + (abs(pl_full[i].z - pl_full[i - 1].z) > 1e-7)) + { + pl_buff[msg->points[i].line].push_back(pl_full[i]); + } + } + } + static int count = 0; + static double time = 0.0; + count++; + double t0 = omp_get_wtime(); + for (int j = 0; j < N_SCANS; j++) + { + if (pl_buff[j].size() <= 5) + continue; + pcl::PointCloud& pl = pl_buff[j]; + plsize = pl.size(); + vector& types = typess[j]; + types.clear(); + types.resize(plsize); + plsize--; + for (uint i = 0; i < plsize; i++) + { + types[i].range = sqrt(pl[i].x * pl[i].x + pl[i].y * pl[i].y); + vx = pl[i].x - pl[i + 1].x; + vy = pl[i].y - pl[i + 1].y; + vz = pl[i].z - pl[i + 1].z; + types[i].dista = sqrt(vx * vx + vy * vy + vz * vz); + } + types[plsize].range = sqrt(pl[plsize].x * pl[plsize].x + pl[plsize].y * pl[plsize].y); + give_feature(pl, types); + // pl_surf += pl; + } + time += omp_get_wtime() - t0; + printf("Feature extraction time: %lf \n", time / count); + } + else + { + for (uint i = 1; i < plsize; i++) + { + if ((msg->points[i].line < N_SCANS) && + ((msg->points[i].tag & 0x30) == 0x10 || (msg->points[i].tag & 0x30) == 0x00)) + { + valid_num++; + if (valid_num % point_filter_num == 0) + { + pl_full[i].x = msg->points[i].x; + pl_full[i].y = msg->points[i].y; + pl_full[i].z = msg->points[i].z; + pl_full[i].intensity = msg->points[i].reflectivity; + pl_full[i].curvature = msg->points[i].offset_time / + float(1000000); // use curvature as time of each laser points, curvature unit: ms + + if(((abs(pl_full[i].x - pl_full[i-1].x) > 1e-7) + || (abs(pl_full[i].y - pl_full[i-1].y) > 1e-7) + || (abs(pl_full[i].z - pl_full[i-1].z) > 1e-7)) + && (pl_full[i].x * pl_full[i].x + pl_full[i].y * pl_full[i].y + pl_full[i].z * pl_full[i].z > (blind * blind))) + { + pl_surf.push_back(pl_full[i]); + } + } + } + } + } +} + +void Preprocess::oust64_handler(const sensor_msgs::msg::PointCloud2::UniquePtr &msg) +{ + pl_surf.clear(); + pl_corn.clear(); + pl_full.clear(); + pcl::PointCloud pl_orig; + pcl::fromROSMsg(*msg, pl_orig); + int plsize = pl_orig.size(); + pl_corn.reserve(plsize); + pl_surf.reserve(plsize); + if (feature_enabled) + { + for (int i = 0; i < N_SCANS; i++) + { + pl_buff[i].clear(); + pl_buff[i].reserve(plsize); + } + + for (uint i = 0; i < plsize; i++) + { + double range = pl_orig.points[i].x * pl_orig.points[i].x + pl_orig.points[i].y * pl_orig.points[i].y + + pl_orig.points[i].z * pl_orig.points[i].z; + if (range < (blind * blind)) + continue; + Eigen::Vector3d pt_vec; + PointType added_pt; + added_pt.x = pl_orig.points[i].x; + added_pt.y = pl_orig.points[i].y; + added_pt.z = pl_orig.points[i].z; + added_pt.intensity = pl_orig.points[i].intensity; + added_pt.normal_x = 0; + added_pt.normal_y = 0; + added_pt.normal_z = 0; + double yaw_angle = atan2(added_pt.y, added_pt.x) * 57.3; + if (yaw_angle >= 180.0) + yaw_angle -= 360.0; + if (yaw_angle <= -180.0) + yaw_angle += 360.0; + + added_pt.curvature = pl_orig.points[i].t * time_unit_scale; + if (pl_orig.points[i].ring < N_SCANS) + { + pl_buff[pl_orig.points[i].ring].push_back(added_pt); + } + } + + for (int j = 0; j < N_SCANS; j++) + { + PointCloudXYZI& pl = pl_buff[j]; + int linesize = pl.size(); + vector& types = typess[j]; + types.clear(); + types.resize(linesize); + linesize--; + for (uint i = 0; i < linesize; i++) + { + types[i].range = sqrt(pl[i].x * pl[i].x + pl[i].y * pl[i].y); + vx = pl[i].x - pl[i + 1].x; + vy = pl[i].y - pl[i + 1].y; + vz = pl[i].z - pl[i + 1].z; + types[i].dista = vx * vx + vy * vy + vz * vz; + } + types[linesize].range = sqrt(pl[linesize].x * pl[linesize].x + pl[linesize].y * pl[linesize].y); + give_feature(pl, types); + } + } + else + { + double time_stamp = rclcpp::Time(msg->header.stamp).seconds(); + // cout << "===================================" << endl; + // printf("Pt size = %d, N_SCANS = %d\r\n", plsize, N_SCANS); + for (int i = 0; i < pl_orig.points.size(); i++) + { + if (i % point_filter_num != 0) + continue; + + double range = pl_orig.points[i].x * pl_orig.points[i].x + pl_orig.points[i].y * pl_orig.points[i].y + + pl_orig.points[i].z * pl_orig.points[i].z; + + if (range < (blind * blind)) + continue; + + Eigen::Vector3d pt_vec; + PointType added_pt; + added_pt.x = pl_orig.points[i].x; + added_pt.y = pl_orig.points[i].y; + added_pt.z = pl_orig.points[i].z; + added_pt.intensity = pl_orig.points[i].intensity; + added_pt.normal_x = 0; + added_pt.normal_y = 0; + added_pt.normal_z = 0; + added_pt.curvature = pl_orig.points[i].t * time_unit_scale; // curvature unit: ms + + pl_surf.points.push_back(added_pt); + } + } + // pub_func(pl_surf, pub_full, msg->header.stamp); + // pub_func(pl_surf, pub_corn, msg->header.stamp); +} + +void Preprocess::velodyne_handler(const sensor_msgs::msg::PointCloud2::UniquePtr &msg) +{ + pl_surf.clear(); + pl_corn.clear(); + pl_full.clear(); + + pcl::PointCloud pl_orig; + pcl::fromROSMsg(*msg, pl_orig); + int plsize = pl_orig.points.size(); + if (plsize == 0) + return; + pl_surf.reserve(plsize); + + /*** These variables only works when no point timestamps given ***/ + double omega_l = 0.361 * SCAN_RATE; // scan angular velocity + std::vector is_first(N_SCANS, true); + std::vector yaw_fp(N_SCANS, 0.0); // yaw of first scan point + std::vector yaw_last(N_SCANS, 0.0); // yaw of last scan point + std::vector time_last(N_SCANS, 0.0); // last offset time + /*****************************************************************/ + + if (pl_orig.points[plsize - 1].time > 0) + { + given_offset_time = true; + } + else + { + given_offset_time = false; + double yaw_first = atan2(pl_orig.points[0].y, pl_orig.points[0].x) * 57.29578; + double yaw_end = yaw_first; + int layer_first = pl_orig.points[0].ring; + for (uint i = plsize - 1; i > 0; i--) + { + if (pl_orig.points[i].ring == layer_first) + { + yaw_end = atan2(pl_orig.points[i].y, pl_orig.points[i].x) * 57.29578; + break; + } + } + } + + if (feature_enabled) + { + for (int i = 0; i < N_SCANS; i++) + { + pl_buff[i].clear(); + pl_buff[i].reserve(plsize); + } + + for (int i = 0; i < plsize; i++) + { + PointType added_pt; + added_pt.normal_x = 0; + added_pt.normal_y = 0; + added_pt.normal_z = 0; + int layer = pl_orig.points[i].ring; + if (layer >= N_SCANS) + continue; + added_pt.x = pl_orig.points[i].x; + added_pt.y = pl_orig.points[i].y; + added_pt.z = pl_orig.points[i].z; + added_pt.intensity = pl_orig.points[i].intensity; + added_pt.curvature = pl_orig.points[i].time * time_unit_scale; // units: ms + + if (!given_offset_time) + { + double yaw_angle = atan2(added_pt.y, added_pt.x) * 57.2957; + if (is_first[layer]) + { + // printf("layer: %d; is first: %d", layer, is_first[layer]); + yaw_fp[layer] = yaw_angle; + is_first[layer] = false; + added_pt.curvature = 0.0; + yaw_last[layer] = yaw_angle; + time_last[layer] = added_pt.curvature; + continue; + } + + if (yaw_angle <= yaw_fp[layer]) + { + added_pt.curvature = (yaw_fp[layer] - yaw_angle) / omega_l; + } + else + { + added_pt.curvature = (yaw_fp[layer] - yaw_angle + 360.0) / omega_l; + } + + if (added_pt.curvature < time_last[layer]) + added_pt.curvature += 360.0 / omega_l; + + yaw_last[layer] = yaw_angle; + time_last[layer] = added_pt.curvature; + } + + pl_buff[layer].points.push_back(added_pt); + } + + for (int j = 0; j < N_SCANS; j++) + { + PointCloudXYZI& pl = pl_buff[j]; + int linesize = pl.size(); + if (linesize < 2) + continue; + vector& types = typess[j]; + types.clear(); + types.resize(linesize); + linesize--; + for (uint i = 0; i < linesize; i++) + { + types[i].range = sqrt(pl[i].x * pl[i].x + pl[i].y * pl[i].y); + vx = pl[i].x - pl[i + 1].x; + vy = pl[i].y - pl[i + 1].y; + vz = pl[i].z - pl[i + 1].z; + types[i].dista = vx * vx + vy * vy + vz * vz; + } + types[linesize].range = sqrt(pl[linesize].x * pl[linesize].x + pl[linesize].y * pl[linesize].y); + give_feature(pl, types); + } + } + else + { + for (int i = 0; i < plsize; i++) + { + PointType added_pt; + // cout<<"!!!!!!"< (blind * blind)) + { + pl_surf.points.push_back(added_pt); + } + } + } + } +} + +void Preprocess::mid360_handler(const sensor_msgs::msg::PointCloud2::UniquePtr &msg) +{ + pl_surf.clear(); + pl_corn.clear(); + pl_full.clear(); + + pcl::PointCloud pl_orig; + pcl::fromROSMsg(*msg, pl_orig); + int plsize = pl_orig.points.size(); + if (plsize == 0) + return; + pl_surf.reserve(plsize); + + /*** These variables only works when no point timestamps given ***/ + double omega_l = 0.361 * SCAN_RATE; // scan angular velocity + std::vector is_first(N_SCANS, true); + std::vector yaw_fp(N_SCANS, 0.0); // yaw of first scan point + std::vector yaw_last(N_SCANS, 0.0); // yaw of last scan point + std::vector time_last(N_SCANS, 0.0); // last offset time + /*****************************************************************/ + + given_offset_time = false; + double yaw_first = atan2(pl_orig.points[0].y, pl_orig.points[0].x) * 57.29578; + double yaw_end = yaw_first; + int layer_first = pl_orig.points[0].line; + for (uint i = plsize - 1; i > 0; i--) + { + if (pl_orig.points[i].line == layer_first) + { + yaw_end = atan2(pl_orig.points[i].y, pl_orig.points[i].x) * 57.29578; + break; + } + } + + for (uint i = 0; i < plsize; ++i) + { + PointType added_pt; + added_pt.normal_x = 0; + added_pt.normal_y = 0; + added_pt.normal_z = 0; + added_pt.x = pl_orig.points[i].x; + added_pt.y = pl_orig.points[i].y; + added_pt.z = pl_orig.points[i].z; + added_pt.intensity = pl_orig.points[i].intensity; + added_pt.curvature = 0.; + + int layer = pl_orig.points[i].line; + double yaw_angle = atan2(added_pt.y, added_pt.x) * 57.2957; + + if (is_first[layer]) + { + // printf("layer: %d; is first: %d", layer, is_first[layer]); + yaw_fp[layer] = yaw_angle; + is_first[layer] = false; + added_pt.curvature = 0.0; + yaw_last[layer] = yaw_angle; + time_last[layer] = added_pt.curvature; + continue; + } + + // compute offset time + if (yaw_angle <= yaw_fp[layer]) + { + added_pt.curvature = (yaw_fp[layer] - yaw_angle) / omega_l; + } + else + { + added_pt.curvature = (yaw_fp[layer] - yaw_angle + 360.0) / omega_l; + } + + if (added_pt.curvature < time_last[layer]) + added_pt.curvature += 360.0 / omega_l; + + yaw_last[layer] = yaw_angle; + time_last[layer] = added_pt.curvature; + + if (added_pt.x * added_pt.x + added_pt.y * added_pt.y + added_pt.z * added_pt.z > (blind * blind)) + { + pl_surf.push_back(std::move(added_pt)); + } + } +} + +void Preprocess::default_handler(const sensor_msgs::msg::PointCloud2::UniquePtr &msg) +{ + pl_surf.clear(); + pl_corn.clear(); + pl_full.clear(); + + pcl::PointCloud pl_orig; + pcl::fromROSMsg(*msg, pl_orig); + int plsize = pl_orig.points.size(); + if (plsize == 0) + return; + pl_surf.reserve(plsize); + + for(uint i = 0; i < plsize; ++i) + { + PointType added_pt; + added_pt.normal_x = 0; + added_pt.normal_y = 0; + added_pt.normal_z = 0; + added_pt.x = pl_orig.points[i].x; + added_pt.y = pl_orig.points[i].y; + added_pt.z = pl_orig.points[i].z; + added_pt.intensity = pl_orig.points[i].intensity; + added_pt.curvature = 0.; + + if (added_pt.x * added_pt.x + added_pt.y * added_pt.y + added_pt.z * added_pt.z > (blind * blind)) + { + pl_surf.push_back(std::move(added_pt)); + } + } +} + +void Preprocess::give_feature(pcl::PointCloud& pl, vector& types) +{ + int plsize = pl.size(); + int plsize2; + if (plsize == 0) + { + printf("something wrong\n"); + return; + } + uint head = 0; + + while (types[head].range < blind) + { + head++; + } + + // Surf + plsize2 = (plsize > group_size) ? (plsize - group_size) : 0; + + Eigen::Vector3d curr_direct(Eigen::Vector3d::Zero()); + Eigen::Vector3d last_direct(Eigen::Vector3d::Zero()); + + uint i_nex = 0, i2; + uint last_i = 0; + uint last_i_nex = 0; + int last_state = 0; + int plane_type; + + for (uint i = head; i < plsize2; i++) + { + if (types[i].range < blind) + { + continue; + } + + i2 = i; + + plane_type = plane_judge(pl, types, i, i_nex, curr_direct); + + if (plane_type == 1) + { + for (uint j = i; j <= i_nex; j++) + { + if (j != i && j != i_nex) + { + types[j].ftype = Real_Plane; + } + else + { + types[j].ftype = Poss_Plane; + } + } + + // if(last_state==1 && fabs(last_direct.sum())>0.5) + if (last_state == 1 && last_direct.norm() > 0.1) + { + double mod = last_direct.transpose() * curr_direct; + if (mod > -0.707 && mod < 0.707) + { + types[i].ftype = Edge_Plane; + } + else + { + types[i].ftype = Real_Plane; + } + } + + i = i_nex - 1; + last_state = 1; + } + else // if(plane_type == 2) + { + i = i_nex; + last_state = 0; + } + // else if(plane_type == 0) + // { + // if(last_state == 1) + // { + // uint i_nex_tem; + // uint j; + // for(j=last_i+1; j<=last_i_nex; j++) + // { + // uint i_nex_tem2 = i_nex_tem; + // Eigen::Vector3d curr_direct2; + + // uint ttem = plane_judge(pl, types, j, i_nex_tem, curr_direct2); + + // if(ttem != 1) + // { + // i_nex_tem = i_nex_tem2; + // break; + // } + // curr_direct = curr_direct2; + // } + + // if(j == last_i+1) + // { + // last_state = 0; + // } + // else + // { + // for(uint k=last_i_nex; k<=i_nex_tem; k++) + // { + // if(k != i_nex_tem) + // { + // types[k].ftype = Real_Plane; + // } + // else + // { + // types[k].ftype = Poss_Plane; + // } + // } + // i = i_nex_tem-1; + // i_nex = i_nex_tem; + // i2 = j-1; + // last_state = 1; + // } + + // } + // } + + last_i = i2; + last_i_nex = i_nex; + last_direct = curr_direct; + } + + plsize2 = plsize > 3 ? plsize - 3 : 0; + for (uint i = head + 3; i < plsize2; i++) + { + if (types[i].range < blind || types[i].ftype >= Real_Plane) + { + continue; + } + + if (types[i - 1].dista < 1e-16 || types[i].dista < 1e-16) + { + continue; + } + + Eigen::Vector3d vec_a(pl[i].x, pl[i].y, pl[i].z); + Eigen::Vector3d vecs[2]; + + for (int j = 0; j < 2; j++) + { + int m = -1; + if (j == 1) + { + m = 1; + } + + if (types[i + m].range < blind) + { + if (types[i].range > inf_bound) + { + types[i].edj[j] = Nr_inf; + } + else + { + types[i].edj[j] = Nr_blind; + } + continue; + } + + vecs[j] = Eigen::Vector3d(pl[i + m].x, pl[i + m].y, pl[i + m].z); + vecs[j] = vecs[j] - vec_a; + + types[i].angle[j] = vec_a.dot(vecs[j]) / vec_a.norm() / vecs[j].norm(); + if (types[i].angle[j] < jump_up_limit) + { + types[i].edj[j] = Nr_180; + } + else if (types[i].angle[j] > jump_down_limit) + { + types[i].edj[j] = Nr_zero; + } + } + + types[i].intersect = vecs[Prev].dot(vecs[Next]) / vecs[Prev].norm() / vecs[Next].norm(); + if (types[i].edj[Prev] == Nr_nor && types[i].edj[Next] == Nr_zero && types[i].dista > 0.0225 && + types[i].dista > 4 * types[i - 1].dista) + { + if (types[i].intersect > cos160) + { + if (edge_jump_judge(pl, types, i, Prev)) + { + types[i].ftype = Edge_Jump; + } + } + } + else if (types[i].edj[Prev] == Nr_zero && types[i].edj[Next] == Nr_nor && types[i - 1].dista > 0.0225 && + types[i - 1].dista > 4 * types[i].dista) + { + if (types[i].intersect > cos160) + { + if (edge_jump_judge(pl, types, i, Next)) + { + types[i].ftype = Edge_Jump; + } + } + } + else if (types[i].edj[Prev] == Nr_nor && types[i].edj[Next] == Nr_inf) + { + if (edge_jump_judge(pl, types, i, Prev)) + { + types[i].ftype = Edge_Jump; + } + } + else if (types[i].edj[Prev] == Nr_inf && types[i].edj[Next] == Nr_nor) + { + if (edge_jump_judge(pl, types, i, Next)) + { + types[i].ftype = Edge_Jump; + } + } + else if (types[i].edj[Prev] > Nr_nor && types[i].edj[Next] > Nr_nor) + { + if (types[i].ftype == Nor) + { + types[i].ftype = Wire; + } + } + } + + plsize2 = plsize - 1; + double ratio; + for (uint i = head + 1; i < plsize2; i++) + { + if (types[i].range < blind || types[i - 1].range < blind || types[i + 1].range < blind) + { + continue; + } + + if (types[i - 1].dista < 1e-8 || types[i].dista < 1e-8) + { + continue; + } + + if (types[i].ftype == Nor) + { + if (types[i - 1].dista > types[i].dista) + { + ratio = types[i - 1].dista / types[i].dista; + } + else + { + ratio = types[i].dista / types[i - 1].dista; + } + + if (types[i].intersect < smallp_intersect && ratio < smallp_ratio) + { + if (types[i - 1].ftype == Nor) + { + types[i - 1].ftype = Real_Plane; + } + if (types[i + 1].ftype == Nor) + { + types[i + 1].ftype = Real_Plane; + } + types[i].ftype = Real_Plane; + } + } + } + + int last_surface = -1; + for (uint j = head; j < plsize; j++) + { + if (types[j].ftype == Poss_Plane || types[j].ftype == Real_Plane) + { + if (last_surface == -1) + { + last_surface = j; + } + + if (j == uint(last_surface + point_filter_num - 1)) + { + PointType ap; + ap.x = pl[j].x; + ap.y = pl[j].y; + ap.z = pl[j].z; + ap.intensity = pl[j].intensity; + ap.curvature = pl[j].curvature; + pl_surf.push_back(ap); + + last_surface = -1; + } + } + else + { + if (types[j].ftype == Edge_Jump || types[j].ftype == Edge_Plane) + { + pl_corn.push_back(pl[j]); + } + if (last_surface != -1) + { + PointType ap; + for (uint k = last_surface; k < j; k++) + { + ap.x += pl[k].x; + ap.y += pl[k].y; + ap.z += pl[k].z; + ap.intensity += pl[k].intensity; + ap.curvature += pl[k].curvature; + } + ap.x /= (j - last_surface); + ap.y /= (j - last_surface); + ap.z /= (j - last_surface); + ap.intensity /= (j - last_surface); + ap.curvature /= (j - last_surface); + pl_surf.push_back(ap); + } + last_surface = -1; + } + } +} + +void Preprocess::pub_func(PointCloudXYZI& pl, const rclcpp::Time& ct) +{ + pl.height = 1; + pl.width = pl.size(); + sensor_msgs::msg::PointCloud2 output; + pcl::toROSMsg(pl, output); + output.header.frame_id = "livox"; + output.header.stamp = ct; +} + +int Preprocess::plane_judge(const PointCloudXYZI& pl, vector& types, uint i_cur, uint& i_nex, + Eigen::Vector3d& curr_direct) +{ + double group_dis = disA * types[i_cur].range + disB; + group_dis = group_dis * group_dis; + // i_nex = i_cur; + + double two_dis; + vector disarr; + disarr.reserve(20); + + for (i_nex = i_cur; i_nex < i_cur + group_size; i_nex++) + { + if (types[i_nex].range < blind) + { + curr_direct.setZero(); + return 2; + } + disarr.push_back(types[i_nex].dista); + } + + for (;;) + { + if ((i_cur >= pl.size()) || (i_nex >= pl.size())) + break; + + if (types[i_nex].range < blind) + { + curr_direct.setZero(); + return 2; + } + vx = pl[i_nex].x - pl[i_cur].x; + vy = pl[i_nex].y - pl[i_cur].y; + vz = pl[i_nex].z - pl[i_cur].z; + two_dis = vx * vx + vy * vy + vz * vz; + if (two_dis >= group_dis) + { + break; + } + disarr.push_back(types[i_nex].dista); + i_nex++; + } + + double leng_wid = 0; + double v1[3], v2[3]; + for (uint j = i_cur + 1; j < i_nex; j++) + { + if ((j >= pl.size()) || (i_cur >= pl.size())) + break; + v1[0] = pl[j].x - pl[i_cur].x; + v1[1] = pl[j].y - pl[i_cur].y; + v1[2] = pl[j].z - pl[i_cur].z; + + v2[0] = v1[1] * vz - vy * v1[2]; + v2[1] = v1[2] * vx - v1[0] * vz; + v2[2] = v1[0] * vy - vx * v1[1]; + + double lw = v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]; + if (lw > leng_wid) + { + leng_wid = lw; + } + } + + if ((two_dis * two_dis / leng_wid) < p2l_ratio) + { + curr_direct.setZero(); + return 0; + } + + uint disarrsize = disarr.size(); + for (uint j = 0; j < disarrsize - 1; j++) + { + for (uint k = j + 1; k < disarrsize; k++) + { + if (disarr[j] < disarr[k]) + { + leng_wid = disarr[j]; + disarr[j] = disarr[k]; + disarr[k] = leng_wid; + } + } + } + + if (disarr[disarr.size() - 2] < 1e-16) + { + curr_direct.setZero(); + return 0; + } + + if (lidar_type == AVIA) + { + double dismax_mid = disarr[0] / disarr[disarrsize / 2]; + double dismid_min = disarr[disarrsize / 2] / disarr[disarrsize - 2]; + + if (dismax_mid >= limit_maxmid || dismid_min >= limit_midmin) + { + curr_direct.setZero(); + return 0; + } + } + else + { + double dismax_min = disarr[0] / disarr[disarrsize - 2]; + if (dismax_min >= limit_maxmin) + { + curr_direct.setZero(); + return 0; + } + } + + curr_direct << vx, vy, vz; + curr_direct.normalize(); + return 1; +} + +bool Preprocess::edge_jump_judge(const PointCloudXYZI& pl, vector& types, uint i, Surround nor_dir) +{ + if (nor_dir == 0) + { + if (types[i - 1].range < blind || types[i - 2].range < blind) + { + return false; + } + } + else if (nor_dir == 1) + { + if (types[i + 1].range < blind || types[i + 2].range < blind) + { + return false; + } + } + double d1 = types[i + nor_dir - 1].dista; + double d2 = types[i + 3 * nor_dir - 2].dista; + double d; + + if (d1 < d2) + { + d = d1; + d1 = d2; + d2 = d; + } + + d1 = sqrt(d1); + d2 = sqrt(d2); + + if (d1 > edgea * d2 || (d1 - d2) > edgeb) + { + return false; + } + + return true; +} diff --git a/FAST_LIO/src/preprocess.h b/FAST_LIO/src/preprocess.h new file mode 100644 index 0000000..7f7d7a1 --- /dev/null +++ b/FAST_LIO/src/preprocess.h @@ -0,0 +1,196 @@ +// #include +#include +#include +#include +#include + +using namespace std; + +#define IS_VALID(a) ((abs(a) > 1e8) ? true : false) + +typedef pcl::PointXYZINormal PointType; +typedef pcl::PointCloud PointCloudXYZI; + +enum LID_TYPE +{ + AVIA = 1, + VELO16, + OUST64, + MID360 +}; //{1, 2, 3} +enum TIME_UNIT +{ + SEC = 0, + MS = 1, + US = 2, + NS = 3 +}; +enum Feature +{ + Nor, + Poss_Plane, + Real_Plane, + Edge_Jump, + Edge_Plane, + Wire, + ZeroPoint +}; +enum Surround +{ + Prev, + Next +}; +enum E_jump +{ + Nr_nor, + Nr_zero, + Nr_180, + Nr_inf, + Nr_blind +}; + +struct orgtype +{ + double range; + double dista; + double angle[2]; + double intersect; + E_jump edj[2]; + Feature ftype; + orgtype() + { + range = 0; + edj[Prev] = Nr_nor; + edj[Next] = Nr_nor; + ftype = Nor; + intersect = 2; + } +}; + +namespace velodyne_ros +{ +struct EIGEN_ALIGN16 Point +{ + PCL_ADD_POINT4D; + float intensity; + float time; + uint16_t ring; + EIGEN_MAKE_ALIGNED_OPERATOR_NEW +}; +} // namespace velodyne_ros +POINT_CLOUD_REGISTER_POINT_STRUCT(velodyne_ros::Point, + (float, x, x)(float, y, y)(float, z, z)(float, intensity, + intensity)(float, time, time)(uint16_t, ring, + ring)) + +namespace ouster_ros +{ +struct EIGEN_ALIGN16 Point +{ + PCL_ADD_POINT4D; + float intensity; + uint32_t t; + uint16_t reflectivity; + uint8_t ring; + uint16_t ambient; + uint32_t range; + EIGEN_MAKE_ALIGNED_OPERATOR_NEW +}; +} // namespace ouster_ros + +// clang-format off +POINT_CLOUD_REGISTER_POINT_STRUCT(ouster_ros::Point, + (float, x, x) + (float, y, y) + (float, z, z) + (float, intensity, intensity) + // use std::uint32_t to avoid conflicting with pcl::uint32_t + (std::uint32_t, t, t) + (std::uint16_t, reflectivity, reflectivity) + (std::uint8_t, ring, ring) + (std::uint16_t, ambient, ambient) + (std::uint32_t, range, range) +) + +namespace livox_ros +{ +typedef struct { + float x; /**< X axis, Unit:m */ + float y; /**< Y axis, Unit:m */ + float z; /**< Z axis, Unit:m */ + float reflectivity; /**< Reflectivity */ + uint8_t tag; /**< Livox point tag */ + uint8_t line; /**< Laser line id */ +} LivoxPointXyzrtl; + +typedef struct { + float x; /**< X axis, Unit:m */ + float y; /**< Y axis, Unit:m */ + float z; /**< Z axis, Unit:m */ + float intensity; /**< Intensity */ + uint8_t tag; /**< Livox point tag */ + uint8_t line; /**< Laser line id */ +} LivoxPointXyzitl; +} +POINT_CLOUD_REGISTER_POINT_STRUCT(livox_ros::LivoxPointXyzrtl, + (float, x, x) + (float, y, y) + (float, z, z) + (float, reflectivity, reflectivity) + (uint8_t, tag, tag) + (uint8_t, line, line) +) + +POINT_CLOUD_REGISTER_POINT_STRUCT(livox_ros::LivoxPointXyzitl, + (float, x, x) + (float, y, y) + (float, z, z) + (float, intensity, intensity) + (uint8_t, tag, tag) + (uint8_t, line, line) +) + +class Preprocess +{ + public: +// EIGEN_MAKE_ALIGNED_OPERATOR_NEW + + Preprocess(); + ~Preprocess(); + + void process(const livox_ros_driver2::msg::CustomMsg::UniquePtr &msg, PointCloudXYZI::Ptr &pcl_out); + void process(const sensor_msgs::msg::PointCloud2::UniquePtr &msg, PointCloudXYZI::Ptr &pcl_out); + void set(bool feat_en, int lid_type, double bld, int pfilt_num); + + // sensor_msgs::PointCloud2::ConstPtr pointcloud; + PointCloudXYZI pl_full, pl_corn, pl_surf; + PointCloudXYZI pl_buff[128]; //maximum 128 line lidar + vector typess[128]; //maximum 128 line lidar + float time_unit_scale; + int lidar_type, point_filter_num, N_SCANS, SCAN_RATE, time_unit; + double blind; + bool feature_enabled, given_offset_time; + // ros::Publisher pub_full, pub_surf, pub_corn; + +private: + void avia_handler(const livox_ros_driver2::msg::CustomMsg::UniquePtr &msg); + void oust64_handler(const sensor_msgs::msg::PointCloud2::UniquePtr &msg); + void velodyne_handler(const sensor_msgs::msg::PointCloud2::UniquePtr &msg); + void mid360_handler(const sensor_msgs::msg::PointCloud2::UniquePtr &msg); + void default_handler(const sensor_msgs::msg::PointCloud2::UniquePtr &msg); + void give_feature(PointCloudXYZI &pl, vector &types); + void pub_func(PointCloudXYZI &pl, const rclcpp::Time &ct); + int plane_judge(const PointCloudXYZI &pl, vector &types, uint i, uint &i_nex, Eigen::Vector3d &curr_direct); + bool small_plane(const PointCloudXYZI &pl, vector &types, uint i_cur, uint &i_nex, Eigen::Vector3d &curr_direct); + bool edge_jump_judge(const PointCloudXYZI &pl, vector &types, uint i, Surround nor_dir); + + int group_size; + double disA, disB, inf_bound; + double limit_maxmid, limit_midmin, limit_maxmin; + double p2l_ratio; + double jump_up_limit, jump_down_limit; + double cos160; + double edgea, edgeb; + double smallp_intersect, smallp_ratio; + double vx, vy, vz; +}; diff --git a/pcd2pgm/.clang-format b/pcd2pgm/.clang-format new file mode 100644 index 0000000..aea802f --- /dev/null +++ b/pcd2pgm/.clang-format @@ -0,0 +1,18 @@ +--- +Language: Cpp +BasedOnStyle: Google + +AccessModifierOffset: -2 +AlignAfterOpenBracket: AlwaysBreak +BraceWrapping: + AfterClass: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true +BreakBeforeBraces: Custom +ColumnLimit: 100 +ConstructorInitializerIndentWidth: 0 +ContinuationIndentWidth: 2 +DerivePointerAlignment: false +PointerAlignment: Middle +ReflowComments: false diff --git a/pcd2pgm/.clang-tidy b/pcd2pgm/.clang-tidy new file mode 100644 index 0000000..d805018 --- /dev/null +++ b/pcd2pgm/.clang-tidy @@ -0,0 +1,62 @@ +--- +Checks: '-*, + performance-*, + -performance-unnecessary-value-param, + llvm-namespace-comment, + modernize-redundant-void-arg, + modernize-use-nullptr, + modernize-use-default, + modernize-use-override, + modernize-loop-convert, + modernize-make-shared, + modernize-make-unique, + misc-unused-parameters, + readability-named-parameter, + readability-redundant-smartptr-get, + readability-redundant-string-cstr, + readability-simplify-boolean-expr, + readability-container-size-empty, + readability-identifier-naming, + ' +HeaderFilterRegex: '' +CheckOptions: + - key: llvm-namespace-comment.ShortNamespaceLines + value: '10' + - key: llvm-namespace-comment.SpacesBeforeComments + value: '2' + - key: misc-unused-parameters.StrictMode + value: '1' + - key: readability-braces-around-statements.ShortStatementLines + value: '2' + # type names + - key: readability-identifier-naming.ClassCase + value: CamelCase + - key: readability-identifier-naming.EnumCase + value: CamelCase + - key: readability-identifier-naming.UnionCase + value: CamelCase + # method names + - key: readability-identifier-naming.MethodCase + value: camelBack + # variable names + - key: readability-identifier-naming.VariableCase + value: lower_case + # class member names + - key: readability-identifier-naming.PrivateMemberCase + value: lower_case + - key: readability-identifier-naming.PrivateMemberSuffix + value: '_' + - key: readability-identifier-naming.ProtectedMemberCase + value: lower_case + - key: readability-identifier-naming.ProtectedMemberSuffix + value: '_' + # const static or global variables are UPPER_CASE + - key: readability-identifier-naming.EnumConstantCase + value: UPPER_CASE + - key: readability-identifier-naming.StaticConstantCase + value: UPPER_CASE + - key: readability-identifier-naming.ClassConstantCase + value: UPPER_CASE + - key: readability-identifier-naming.GlobalVariableCase + value: UPPER_CASE +... diff --git a/pcd2pgm/.docs/pcd.png b/pcd2pgm/.docs/pcd.png new file mode 100644 index 0000000000000000000000000000000000000000..2ac39fa128f7cf088d331d67f9a6cded42274e19 GIT binary patch literal 1401655 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

S69AHxVy*Qu_Y8&y(F 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�J0F~1?U@~Ql@7vtUGwNDoW?KZ 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�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

@;--WAN(3_ujoo&KC0MHW|VuJ&P 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

S+YGf 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

)6?I%LyjhF?6Ni;PCS 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

  • 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
      P}tdP(#hm&dRm<(a+=|7^$rdu%j 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
      QQPCN(|o5?DzNkRrPziyE}%{NqpCD6068CDn{th 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 SKmlz)xF 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

      Hje}*9(|ZaL|VHoZApk^I0WM{)$KR&C?j{ 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

      cQs-Z&7x(j4jmD6kS2NR^mC#Z0k_(Emyk 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%0DIo8_&6w3$uVR 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%0D(k#3NZ78Inr zX6O_-l(a!NNC+xj5<~OtdB5xT*E!cP&OFb3?|bjH*IN4-XC7(sjrj29^);#4ITYPA zvv24JpJ#z?-+9fJlV(E4j|}u9f=Gw5B%UN=`Lv9MyU|KD*EO~78H9UULhyj z967NtofU0ej8Y~^`^uTdnI`VCc>~cwO||u=k_Q7)*N^nnSkHzPl|PNr>}uBtWJCh7 zPp7M&x@3u6IcE01b!F`}?Y}3TGO!qJ@~6@;2ocO99jwIY zQLmE{>B$uO0wG@gV#guD1F58)M?t;F)DhBA9Y?~pl!5<`ZdM}QWxInd@jU*9=;|88 zV$G3xOAccv@%{g_rs+VOHWmVMST%*Z>wnpzchwe;3)m*NT4>uB(14Uud5 z6=l7cJosH`$LXGU$}J!Bo7;$MYkZ+Rc&1$BT^kBJxO0;<k+##cJ@7Nv8^toN{2}l{pr(iC(Oj;s@?{yf5Elf;1j4bDXz^?%SC#bM9nPj+H`56yC32A4*1;XV-bO>FsVCw0)8v!gg30 z!>=tcX_3?=wXhvbuCrM&cORe-I7D7wUBq;PmM0f9+ zFfD8X3GHTkbLw=W(4sq3bsM^J(*}K{wYXEH%Hmb|(49@gON+wyYA!YmwqH!-m`Gn< zr?&5e_a|RyW@@Bm^%<)3KGix4eZlL#a}fS-?>Q&!)AL!>=l}Bp9QvwOT^$eLZtIpC z{j3*RS0-?7&9Rd=FHK`Y@_(_jS+}Tlnl{MYnNC<~;C}if7t5;oEN|r6@zii$;-221lHP+=0^a=PruDY&O*%o>ST445+IA6JZ$ z391Ln%T&f;(^75yBXLKCzg?;)TPn(J$ejr-!)^NOru`E0z8R9DMb4dP&)|=_-i*SR zk7?vw%7bS_MaH?6?#y=PnY{B8{^OcE@JqVLs7$=;mZm|+H9HQ23Ub3ZW7i!0AZ|*Rfe@bf#h7%XzX_RkyY=Z$oGwsNT$q0%@(JN zB$H9$W5HQX>tEbg$*B!GSxMQmfqun`Z#V@V3)hVE6uZ;eFWs2WuEz$*oQ;r@g?}84z736ug)okHxnLOnLI6`z?FQM!OlJt#N)fK#!fT7@{QLl z@)st`J(X((ZDy!F5qSBd%s8F zzXFDBKxGh`p=7>KDpaEcUmgrj-=Ylm%{wQVkw{OlY{a3uuW!Os{MD);KYC1<{|6nT z?5L+9=>>B5LUu& z1djb;``<=<28@EfT#XO(9bYwxqjfXW$nA69ZEI^|;s}p*m{GxfKwxXUf8}q!tRVI< zL#NsT(B!K29!jKT4iMR6Q(Hm6lVT@pPcqIA_~J6>*=}xjRSU*2O#a=0bcn~Rk;)s# z@oSGWlO6*>g0ydb8(SL14_ROLpK{oj(nxNu(O;+1{(s|b?oQ6Kd^zU3Jxtvch9mhd zIVBRpSV?o>-vd{^#?Ar+tTYoSqqQ?x&y8j+!NIoV`IFa_Iqx%GBy$C=Ci_3AKa6;jT^;(=A z8jvXb_)M7HK6%SZ&_VOupUCBj{b_kr5(Q!H6%?ZC&1LvJdC-! zKR3+lt(x4Dv%HLyOM}H)?etFD}k;2ZZbpqxFyiLGKnX+%)o=)XJm=zFT$dZz% zyUcEY!56h{MQ#hDi+Qpx`8d&gO(_|ioIE5=_bxLdg$8Uc7SxRV+;*|hm*ZF5Ly0w1 zX7G$;0CoWC=2Rn+n$Xq!7y>@Ao%sT1@*WnV))a`knjJangl?%-lM{mFJaal_mn4mW zD4l^>zxhVw6xQ_ntc*W$sBYi#0O!cn)U^rS_R8Wej7d}H$4DjGgr_&kBpznGW_Jq} zyZ70!p;ou#L9_}XHzCPb=Q9AtP!Z5E4!y#nJt3dIhR)bY{UKt6_14k53Uwat=^9bZ z35QY{<7zR@RRP1cPuS=Jg))qFeRJ^9&XP~N@6cneru;1(W&HRw46t#H7ylMSBrkm< zp^&J*SEP~hr}{6SOP+4!wRZ(Ib!|(lSSZB7UN;LeL9DLmTM;SZxq|oC0M1e|yN8cT z_f^zWK_i7DJzqN7sdtS5AL zCA_H(iC+`;`M&PIHy1ha-G#0(znwe$(kDCcSzo4VS<52jRF0A~d<)_@SV@hI++=$S z;!N&d&YbFb_rSTT!VUX+u6HI+fLAN}^>TOM$ZYTKK~M>0eYvPSn|7k#_IZb}&Mwu8 z+HTI&a?4#tjlDK#*3|3~Dzn9`fA!^kwOvDJ}Kvn@y!rWXl`!Kvf zhg1j7m{wrn#IkF_v~FM}bBf!HEZ0KVj*P(194EtN(o_G9%CT>O&*B*05b)_fBEG#I z?JZb)&!Z#M@R=7k`f#(?!P$S)V_m~Bkcy$GM1i#X_UFG1kw8s9k$NiuX>rxndR;Rb zR@tC4yv0oJQsm6ONZzkurMlOG0y6w9zql7&UTPS(roRNS*vAv=C07 zcc)?isaXt0a(CqH(Tv$zO0XH82kPt&v#~K<^)>iR$KQMDsww%Y8Zkiek@@?z1A8`x4Eg)y zK!PIOb`RSa{KKA05{WO0N3TrjG1|_GZtwNcrQZLCq+KJ`({Lb=)OqkRg4E#8`-XT5 zY6^q$Hl66P45Qp=B^R5Vu9jJrjFJ&^8hu}F9d`le=M8V4B>D`(Spy7+|Hm>X`!0F! zzyoLw?u?YU%S(`4rn8rva@9Yq{bFlnwLG=v4}h2K$#+N=fZNCx^+~k>vA;H#cm@Bg z{c>4Sn%$}lTgBJZ=1`p_)5m%~beo=)nJ0SuS1id@O5ff?{k(LI^6su+{Ra{I(Q>cN zUu6~PQY6gC&$w51jFFPr;McNc67Nvw5z8_; zi8y6@yTUn#)Cg{0T$DWAE8ux5EX4Io+4t2iokFqpGNp;IamWFoGunmPrxGy~+I~(t zxHUU^GaUX7qj3(UAD^X(A~{RF^9FIF4ilsFTBuOrS=ZzZidad5w%6+P2v`iFuJu?H zFwrWt>FJp;j8zrHut=9@9jI##_%NK|h7hyKN;`1051i!XU+9fqUr^SyQ7HVvKYcrj z_(HM?QO9KG>nqvH(NxZ6Iz_yG7+Mr)?^O*39+& z>T(CeNMB-ru#`_+wjVX|=jM+bc+H}k1nYSU$j8ne7h|wEzVt+G5IHi$?nmbRQmfGn zyr;K~%DK3&-)o3PfTbsJkz8=@p_Dl+h^DSx}@D)7uG+Xi37$M(s_^1&vX=);U zNUJv0)*w?qyHk2*=DgF{Aov2Q%iuA|yDpOfr4dr%v+TdrOhn1^8Wy$x33B(o(+Dg( z^E#E(Z*z8c-2SY#iullL`H}xYzlghN@wRQVtMmAzkZ|s=*jxKgY5-Xe&riP*)OU&( zJcYduQ>m65O?ZrS_q3QqTmd>!|KJ5HeFOR|+}HL~T9#1UtGakK0(_`l2C#`|9BhlV?j!5gk!uw0Qn%j`SX`v~-*n5qV>qZ0v|>{E z>5=8=n&#`WbD5&kfhLMC7pGY9n;XKVt`j@<&rAAI3l0l z?JxeZ-ZxBCq+y?(=6HL9)g8L^r$9mcB7A;t=)mydy$8tk(Op}EjFU5LWt&Qs;@6u8 zGJxS-%Imd-ige6e_m)1Khe#S!XNhkd(7m9P8{QS+Az8FS#m2)=GGS+PRH^Y8ZN<6LL@GERYa`^u3k`O4 z0w0P}Y9l_Gi$7kDnYE z6kY(q@r)kfSkfSmQx2qOZpW`XqrHO_Sm}RIW0HA?didqHxws>{bh*0q4|1J26RUDw zgbcj{N+C=~y&QvQpi&;X7I8JrD9t8Ag+PnbMzJ! z3HVg&-&!)?0&CK2!PTatO|jjbo$iyQH_g~T@I)y2)qX$m6cQEkk3~H<oHf@Wh zJ(o)UO!$70JKd^E&zb?W*+1%%1S-8{?@}TcLaeiuS#!8P=T>r^N){5ghkg*n7U*Z^ z`|0X@$HptCuY8_Zz3}`#Cl4Q^!IbFyszhY?SagKm!oxy`G4;Ea@(~-i$i?RqStXvd z5&?@aEV0d@G;!CwQ1o;Q*4<8`hQ^}OIc#KSp!wyk{kF5hs&m&m&xYHyQU}F)^hKih z9PQ+Y0uyHx5q)|ai@jH@nC%-5M*T@IQp#}~0a>N=-p~)@7aO#^XfA;0s}b8-m+NM^`>H9$`X8AlLu2LEA?57p)uQAZW~3lUXS5$+Hr*Q!hX_+bwE1ZKNlu9e`(g z^p_EcD1@|7UZ0n2lDdsz*6p+Sovx<-g-1Xxx;Z+pvU2Gzd{@Mk<-6zy{wlO@C)PQz zttj8|C9$ho*{37-bqXEddP(206_j&)qE7tgZT{DvN6Oy36*}b0-T&#j3{CN4=-<_% zG#>&w*4pA%`W|Eq%)`q^I#}#Kxh+kzqoA!JV|ZSb*N{ugv!(v<4+;*h+JW}HZRsT~ zZNKC(LBRfRph>R+s@U%s_G$?p1N0Gp%fi&QR?G@!^y3uS(7y zuwL&Ch%t!0S}Oi4Y~8r)?IiAnoMA7J(~hOZM<$E};jua2u5Hat7iReJg`*)v?g6Vm zM(5t>X9U~{r~VmS^usG0>aQG79Hpq%hKy1x*87M0+{+~nkpXWs6y;;tEwVST5uS|` zh=`jF)sl*eg_gtb4eTrtde`1By;sYQz7d~PfP39b5XuX1vG|VxRE%}zdW6a|qBD$w zaH{^SRxFTLP+RU*-Cnh&vWo^%IRo)Jzr2cxUCnTqJqXO&oZKaZSx z8gQm{_Zlw+F}`iA26H=aE#^|Ks+9dp^`hqD6m~1u)1$Wf8)Ar(G~ZFuWHBE8jyPk- zDyo}*VQeIAXs1zjM`louW`-R?=43RVXLna7{yFWkXwQyPc@C zrEl+^okJSWf%|}^c$S4_ZVi0hb=4JWybo}6&}e`$49{v81PZ^o(V=RA=CI076JaEqot^-V&~_T@)y{qwBqwP+riT?i+(oBe%79 zfY1B>FuYFw(G@q(aLxl4;kvGNLT;0Ko_;CJ=B4!V2u`=IM`d{$?+)q78`#vU{TJc zq|zBJPPu()Lkv!3iX=Bpm~O>#UU)huxJtiN^DuMXM{1(@XvqI-N`8OoJRY!6Z=req zPDG>lJM&YeEAxXAFSR?8SWs9Z6-#=&t|6}0E613A&;<`!Mf`k!JsR{LQfW@QdZHD` zhTM)cAfjO1E3}g}9>zL7!~O+LPtnn~Y^!d`CHy;DitXw2SN}#kr+@_*Xdf#DLXu3S z9R$r?$P8Lqb(l|%@PK`%#1Du58fFI5i1O>E(^ea@PB3iBzw5{rov217SYa#U_rAr)_bhh*9S9NtitgDKf7ZP0c&) zqe2Bfezhw->`lKE^tT%~Vj&?Hw{Xj(!76hsxg~2dH%Puz^b3fKrL(#^(a41dDzAj` zJKy{p-{IL~S6LJ^)cg2E$1f3~RZvog0l5t&#GhH>D7I6*vJmgVfTHogns&Dmgs%#1 z-Gxu7X;?oPXc^wEHldsoJCqRKxzjj2j_nu}qkswSc3qhXnx^!JWdhT03giD<6J!%X3A=EaFH|qtsFE<<>N7+|kFSzRx zr*S@vj7$2|UYdl+-rANfX#AU2(sy9@Ynv>3UE1z8GVH1qDk2?IZ{)#mZgOdiNz4)2 z)gpt!4Fdxgy$o~O%mdI4!5SBB+~$5FILOuyRY>|Iet>}=}&$( z#}#4j7N&x?&~0!ETLAb{uw4SA9QH=3+`<;)B^1=vFG|jxoXUaO4ERh5k3;mx&4|5a z<4lEV6jeg9{+5f*NF7CvdzRXLE4=c4r7PQuB50>D(&H%J?xp^1>n@9Rv*5bk%cuI* zze3{s7u+7`ag7@DRM;Kt`mPIBzll~>WsOj-?AzEoI~Rw#nqyU#;W@$!5HB=MzOcwj zAWW$Cr{tF069KC6rMH!{jn4e|sy+-AzNg2-*?Sv#V_Lm=D*n$X8-ZXmdf}D2sgE!N zZ4QkbKp|J(v4g%y)f_YP?|nE~QR_ALKb*86129;dIOB+M2*x)CKp&$p!~vPg3K|F| zi}KNTs}i9%LQBW^3%=^TufULEx1cV|1ce4dPVK-PaI5Mo{Ge4k0gj^l7c^>5+a^Tx ze2I#7=MC&5ML9X#Z@%KuK8ruQw&)*2gIO5k`*m}l>>aE5U5?xqnu})Hu5hBmtt8f< zqyY>?6e(RwDc>t zyOvkykzV+B_t6YtHJx4o9Ujk*m%?Exjv8;<`}t^wt@MaLXO)PtPudBnKC%~orxh;Z zntBsCKgvX}FAUo_^<3YVg6 z$?*=V!?S{wf<39y3hnv7ID=L7MB{Xq0)(B%QU=R9hxagcE}NR3@3*dd9x{EJH?r2f z3*?o$n>~{M{z(915 zM~Bjv&7Y4BT*(?-DICMV81=GBAM-#?YA@dcGziF_Z%rpQ+9Ne9>?=2*gtBqYEr#g7 zevX(Aqc!d#fl?!4d3wYOrzEdpj|r&EdtqH>@k)f+yG0e^}d z4z;g>;w!U(=Q7W=?@A4->%+d^N(kA#9H4%Wxnj*f*kY$wY@Y+A{)x@1I!ZUgk(+1CqA$ zWn^li+2#Q6(uswzv+w9dmQ72l#p-ci^K55@^A*D;DO#A&?l&z=qb1Sh;y<+G=VJT< zm5ISbL+aIPG-jJEo-u832;s*Y5{wcQq0dH*jN72@0VtIJEdtJz5>sk3X#lj)UN%v+ zr$#pnJRg0oz^`dQfYcw8dP}NJNkbP6E$8$r)t~=e=Xh0KPYSXc8kB;9GbU^y4-SxB zh6o%*_oJ$HRv%s~~$`?Pb1jKt9UJzMzW@ zlM}v0R+IPPnmR!f%UZ%Xohw^0m}^F!BWXyURF!`{Mz`gC8um& zZ??X;`>%y80m-WS-zc3q714*x4$OlqY8?hM-C#48q{#J}91jaF4y z&_ zZHo0x5*;I5RCe!^j>mtst;)$66?`Ml*obmq!{v^fsI0!_8%!@s@wBD1jbBv2$cfJr zwPf9wcvk9-w1}YiC6xD?{O>Fa%_w=t<6{2HM-y~R&HB30s&33CDHqB@X!{bMxSrm} z)FEr6@yWyW7O!vt>KB8SW3p8VDo1s((s;FAl%MA2_U_X7vf@7( z>pKtBHTG;vH;|KKgS%?9#ViL;-@^lG zIP9s3|E++J*=z*S%h5{BKreK#Kl(k<_<{;DF!Ru09H2lr%497g$w#bvJn-UjH^;t> z8Ts9B1slN3*#rU!)Kit)`cTs{u+SjN6Fw9C2|Qul+&33LN6Apvk0_fesap)RJ&^tH z1-7NV<3UsoOFHq8KDPWqrma#93&!7v4Uk969D#{vrTAbHBTw-;pn?bVUg$c1-^kzI zTBnKFh@o^m0Zk7?wq0Q#BPOb(Je4w9Z{?Bp)cagqr z?Xgr%+nsbV5mM-t_+)y*Ms(@F@2G0}#~iPI#oN7m6QiWr3kNRvh0}kWLt8-ei7CeP z=;jwMZO=*mJJYpQ%)|HZf@7kKExWhXIt(MG-{Z)Yu$pf&434kf_=ns2wC_h< z)*U#2)9;;Vk)@z*=Dp3k)bC04WTE5M` z602Ta55c(+zEJf*>f^hpgMz{ofnV2e5aV^nnp&bIP^kU5eAq49 zRW2#&@=sK@7ye5s@iX`z((=hpZh6X`?9hZ<&BckW^yB%{=_$`LlEHgF9z&}lb&Dd7 zA&{9`=2bg`o0)TGca!T2yU#JdE*UXy*dD_Bsl}{FAV^%!j(DKU9&%|R!ot0A8nSRU z=@Ppgvvo&cDjY(M+xz=_yX_}6`~%qX;yqpm8|Aa2+TOo}G%|U*4{zV~3Y;`y(bVYW z{T2`otBr{<>FnmE#|dNm291Ht@bUaVulUUzo!;4(+#=_{3GJ7cx53TU7bQJgv!Z(! z3LE@C{zibHhF$=*I8C$%3hKtM(JPrq*lKI1*S9V&|C5#LJv8w1dnO5HD!v!(RzI6u zb!Te8PV&QxRXt$9xa!t|WgXqJwHfuYT05e)@ObZArkJ_+ohR`Mi&JYCUcTR7Z%RKC z^M^Hm{8&Y#Vqx_`(9WwE@1>Wi3w5xaccu;Evu`F<9kU^aPRrIK@iKI0v4s% zUU>WYt1vld!-=8FM`MXn;UsRlMfHdD_bMh*9Cftri=ECs?D)2_}K=M-v z0xzE*Zq4;;&ed)j_dDpKAL#efaHsCGX3Al)~ z$=}A7mgkS)=GX^?Z8`|4>6bfzRIq8$Kf5}Oy$OtB-?577kFLMMSNJP$htZn*rgR;p zbp}3g>&gpYPZ(;m49t))<=kkogO%!VHe!(B4xsu@b=jW3FkavM>gsWPb$J|SJKk6U z8&5*D0u;}j)9At9`^`m8aA1r4bL;bI>@EE1eTix0en1OtmX9pDQ^|YDn8Ccn=hnvu zObE@+j*0zx_Se0yjWcHP5c0Y33FzKU#Qg@s<82Uo$#uGkp2T0ew*pIqmYVxYim?bP<(yJ5gR(5We0Ubl3vl5yTY zxF;JZMAh$T=(4iS^CPVZqZ8|)74Z#dfCiUmEF_$rEcMI41Prs?hyX$mJeLi>P-9qv)ef^z) z_+4~}Kl#GE2bb`|u7!KK8ChgDZ?k@&khfLTRttxP87LjKJLzvh7~_K-MW+H-XQix+ zIAru6G4}=vQ2FydZ*iU;tVJ`1gy+FhVmvs{y-GL=H%q^q91;KA=yq}~&4hP(vGV9? zf9Vc0w-*a~PvHV~$5s&nBBqiRzjoTr$gxjxti2xK;T+Jv4Q+gxa`24oVR*#ycdqRG zhRe3$6Mf0^@as&FY=1kN21DME;(uKx<@tPO<5hSsli-&7|3cNfKak1$wM54o#ig-n zodPx*TOwN6QhvjnF#{5 zsX}D(JN!z+dzZo9-#h%I%e%`-l6w>VRP-E61P@REbOX!C8w+(Vo;GIKJQOzs#n65#MxlK%2xGh=Tsqmcwnor&n0^b=-Q< zvwW0*&a3Fm1G#~kJShl57m8Ev5C0rb|GpEP2S=-b|7=>W#{`UK%R)3I^PUGE)2o+% zv{65L4t)qZ11=ROWt|$$G`Q&V4`jHS;`BrJRWpISK#QldpPZK_GSgpg7p%FG@J)P! z!pWW1@-sisd*U~Bj%>l{>n3NuoT~@#HQg>Ac6NlQBaI$Pq806aZVpG!K?GCR= z{C}Q14DFs`{~F47XEYC@!GUzbQU?pHVMr%>Qc-z6o(^R>>JMSyBLC!A!0-kA+*myv zajoVnsfx3beD`3RoNCVq+2 z+N^^G`f0D{SoY3}+I+DlJ*21qP(yj;>bG2iQ?oq1 z$7?mz&e#}`kA+V1%M*sjM+a?R+A%{&1f+gGaP5|gF82+5JDSwXFD^r~HEFun)mKeT zx+H&gXz(FZ`r67{F^8*Z+2u;hV@Y(M=Q^uD6@HqRyGF>;B^@EN8j^i?E*Q=hB+QV_ zkj@MGPBbX#8*=_tu5OHWM)9iq(m>nJKO>H5X>npU1Jkxj0M9%=o^#QCiWfSOMT}CR zankW+-l5UuKVlZrXOM+5P^ys>te=ydIN955r(**r(+(tS3Mdi~j`52I6upp!I?Zg&Wp@t09 znkTQwv;F8E;mndON}44KnWckwzWbOupYOe+w0nczgtj}+FDX3~ZWd4Z1l_izV#By^ z#%(})`OXUg=o56ldKlRGF_y~aZq}Y!8X|B9iZ;rVMj@F<-4cxq(3gbvTSI|aiXZh# z-gHvGQia}qpZRRRN>K@+c%&$7puavtR|n)AVv3DdLf91QhM@i;vWGK*!Z7^R^V$w< zJ|r`+Q9sEIg^259rFy6meZ(#OZnTV_yT$rO8-r}nlMI-cF?6J{QM z-BqTFdJ%#xj#9hG4}P}375FVlkg~wA0bb{{cQ4>u7V%urM(b=-XlM}jc4oj>CJ= zVfImR{9t`kT};>JW-DS$9}O4H>Qra0Q7^BnCEW%IvKrPRav=D^>cxAb4Y3TMsbHC4 z1xbl=z~Jx0Fs9@BG)$uwSo2tQcX++E_`k-p;BCw@g4oDAJKCv6zzk=l>b1adPE7^I z0|j>)16${HN?RYeaPU-`1b95DAOwjRZo(QgO^AMLuxfY@Vqnu`)>@S-=gfX!^il+^{FWn7+LcPkE5l6i%Mm@BN1eAM3#cz1^K%|C-E#Sv^!3^#24+ksGGQ z-P(w2#RI`6`q?C+L=eX@(H_e8b|q(BwP#<^!Iy%z4!RUO+N=S8#psdfK&f46C^D?h z$b%J{Qr>ppP5o~Dbv$+Am0US*yOu*yP z^i^nw@>}+HGyl>&9*{0J8Gm28-}Wa+x<$+&Y&+@Gy^;gGj@Jv7gyjBj(4{49@MON{ z@_$ULcyyPv>}Rdp0YPt7g>osA!2EQU{l8zq_dk@Mio;Rly0zlX5F?iCQ+o0&%%jNr z(ZOrAk|LRSl^sMHvQtS_^@q?}E}|%pdEB!TRh;kmc2zfFinAl$SI{3nr}XtK9mQX{ z;y#i6vxBq7WG_K3Z7-(nu|d$mQ~k`{FL$Ru(+$U)OR!NvTn zoYk%}Gc>|%+}WfC z>y>O7^a;Jbg?oJnEp*QH&SGNXgiizkLGJJb7n&u#Lc1 zLl(B0|KZRqW+MY*H_zJQz-$VpV|aNnKZL&T0x$y_`=fQQ|H(@)Ilf|0fAB}stO3{y z;xBz8U;l$sJ2Y6aswRQ{LK5looy@Jz7B2@s7r(N+57Aye0u&zpM!1A65L@VR1u$RK z#p&d`gOTOoSCtRdP4{t6r`0!@CMokSV=wvq%7EuXFK@{!%>9`r(5KLR<)C7d{I=?W zERAHX$$P55OlVQ zMzVy|8%*aaKmX%7L|u{%s~`in`ss!VFTH1()zN8QG}AKad7+@qp}4RWlJ-|043w~T zv*ni88jDaTS!UpJIEBJX=zbP*z_s|F>etW8>L@@$si`i#IoqS(y^F%{0LDR~Q<=D9m(Fgt14abhRDs(^hv)0Zc=I(pEGUwL25>s&*2{FXW&Rr2p)n1cK7YJ><5Tx)As~I!Twh(DNlid@!-~s%WEmQtEg$l73xf*UH9b-YucT z8lCSG12-Ry>k&nP_azOxW4gFt1LH^2og3@x!BpFFaOC9eLv}*tSQ|nvkSId&pXD#` zVa7vyR%=U6cGYpS^yz;XYBMp&JvuZw&rsNqqJjSjoJi!-prqUYR|TZqfE-_p$?F7k zqi!=rpzXu-M_1#Ek9fCB2UoUs5wyKjD8H6K8g6zd926smN@6$%1&v7_k#SBSqzl9< zAEJVC#~0Pr0u-}m3#M}_{;V76)bpb!FWokQ->QcGpX~3fJXPF+e*KI^h5$X}zvL|~ zcQQRrj)qyKKEq|0rs}ONVzd39Lfo4BoKhIq0(=%(*oHFFZEC4UB>Gk-on3BltPdSMi)RO|u1&{B43TPeek?*xpR9LuF{bKW=X#U3$3< ziCOrNaZpBRfPY>PYPryDOlFS$ldePMxkm`~j%?T*9^pb*;{%mJ8X7vTZZ?PtjvECo zTg%28D9n?){ud2-5A@bT)+V)yN%?m63s81D4r@o|iFSsmEn9>r3#3qTz`05NJ~@_QES0 zFsPB|4dT`)1bmU}o1|8T_naA6P_Y*tRl2VYjj-{u&sdo(BM#BCMna1=l9K8!iQw3f zD&zk2$^aX>p5^;0e|8B_?9D>g_JQ_)Md%D|J#jZ znL^xEmDK%n>*cj^`WRPMv{G6mvx17+=juj1_~f4ZPqk$yNn! zjU@mPM|1jlUTu=&TtZ!T)}Q?OpI)!p2$%R{)fz=*$dj=tt?jGVJ_mVL=;8d-FE+6h z^CrnfOiF;`^W+Y3G8hL*SJd7y$ip1bn~z+#JoWeXhH4?W94N}Rv72sUjLDTCIYjkQ znov&wF!_kx1^ZG*Z>fRPztorqeNMXL+*S@BK=p8W5E+!$UWlB1fUD}hgpnT=InK)& zQMX;Se)9=PlM5ffxz=KEQ(A3eN^hn9ibm`V{4RZf^b$+ZLY~+}SQKWboOP8_Ca>Ka zd1*7(jM5^y=lUyJvKXV7+XIlLR0SS;o~K}sgvpO@poDO!%k;>v*)2YlZWQF`2r8xx z`in~4{Ocd-l@~I&bKthPB8|8wFD)*urT*di^*R`!gK;UUF6P+>ic=*l3R-t!k)(pI5@3hQN2N;xTdw@f+$uEhOpozczM($3z)Acv4&|odfnc5lSABg z0q^4Uv>$~xl?-qHO(Vl@;UCz@A``fAx}Q4USvBK?<4d#n*OvNt>pu0r2x{%_(@P)l z>Gt4F#y~}~cuzk6!_It9#3^zYJ!y-!(MiPU-~kR``jD()%U@w4e_@ZqiYl!!6rYLy>o z1IpSRX1>CO_h0#0wT>;6>Sr^D<97&t(B$m`Qu$fBL@i8{n`ZH)!XU8t-t(yVrGDaV zb*BCYG}*o27S8kjeuh99^sif-`Y6kJvnE4r-#?Ctdi)F{arxaD@|1g%*?s4ir1h7m zG_~h%Uc;#4jixrvPln|P;7tJ6vnV^35;#=&+c8Bh{JAreup)9&38e{aH1oeTM;H2e z&8+|N2UWaLzDD5gI8G>7_LncZulZ!F%lx=>m<~?W zy4RFI^!tfuDRyjtMzOc*>1rTb-dpfrDP{Kl9t4Be2(p+JQF z2@BMXwuT=a|JuES?5^_}iET5SRif9OEJ2pse+0RMf^ok|jg@p-mO}=AIWM+ez(-FC zHb}wOHhNVy@pHJVmtvNw5jV(7`Ct^L5P!9!E4-1?jy_%BGF$}7sj%{MQMJ-EpyKMC z07!DW2^grg_t|tkpbC8!9aMd$rA^+vJ}+mEg89U6sIe>8_`_r&ovR*K>_LZn+jFny z3!JEUU?lDO%$zZ_8IfOySC+HT_TVS{#+fb31e$u%+81Rw544O9M!$M=JUa!!7wu;2 zgULlQl#}?vT5?uK7~0Ew)^sX(f#ZD1G~^!lSH_l-xk`oX&?9y%n$(A!O&c}p{B2D7 zEJ6C`k&^EJMgl>Rp&V~}3{xqQ&ht^d!qC?W)mw<@Z^`h#<}On6LesC^aZ;i{D(_D6 zo@d@8J_YJl(PxD0XNxbci#C3vFY0E%zhCJ6ekXj(RLECcqRpP$2={OQ z4`|`99kurk@?pR%oyVMrX9_erJ3Acrm~Uk ze6gadrc`y=@2uwCO1X7*XlvS%QY_DRfdYM9TEgey4ooyiy#b)77f*x5n)}>0R zYbg1nchPN&2BB9Q*;LUD$tdCy5uxtuxahqjP3a z4>lswTT(j5O($w_3i;N)vc%xIbyarS+ zm*>;rE1z4SJ_+0eGuGapq`|%S#0&B!dAYUqz}XtMki=DH#q6-!yp|9cwfIhW;WUX*7k{Z+}T{DPqwT z(Y<4G^aVC$2owa?IQ30~{cs<~vGe7Xqq|%bvE|6<9zleU_xXJuSjj9^B?a9L8|-78 ze9i1uYB~}EUn^>rtJ0}Di)4^^HRDs`fSJ9wU|3)0HOE12f!4%AaU`qG|IoJ&vXL-9 zY6}CxY2>D}tLtk&vd5v1@!PIuO_QT>et@WXyg_xTQFqon4MEYej_GnmO-dVvvGB|5 z$v3~Bt*+!iN?Hir^xpd0Pzs`-!nUzt+VP^56g1Cjn0_1X|0CT3*Fa_0iUucprSwO`_DPNsyZ z9U?)|7lg$|BhLXHXFd>AgoOMtA@AhfaRI63&5OfT-_)6kmWYN98ajI)5j$<;m-HrU zJecOE*{5{5aiT|8UDc5($G`U*{m)n{L_|~kNXNf*!YQR|{k!021!D6-4q`H#NlK=Hm`Fb1(pabYhti%#$^ z(AA_Mk|%yjBq8S?DEN*Vsr$Is(-nD*=l{F_;U^Z^ys%+FZ5}I34}y#N@j0#ukjo$v zM1cA7N8KdY6qqk)|GY)hzo5YF9VP!MvQ^VGdGjSC{Ar)n?H)05`JEk5)|F*1Knqnz zrCt1d_&(VV7^akyO{wOSZKhGPp#`EzwbNy_BD7rkXAYj)5Dgz~<9E?H5-7L&3KxB~ zfuhbt;b*eXM=}eO30FEG_ZfY1;CdV$K$feBMgS=nBslPbfi1Mx+i7 zJc8l|uHIigE3rl?C2&}XB6UB*9Y50X=Q>w8n?(ZxHcM(DMM7458Dwrqc~f{m5|f%K1F5MUA_ zKwmK3vDnQflok9VFS`Rh?!Xh=S8>#_aGL0Rs(;dBJ|e7cUN`KUZFne?fBGLX6E3*&vro>2XXgt&5EiAkeMo;>nLQ@T%%-uh;=trY%?kU&3H=~0FtCOk(V9v)Soe)Dc=)(y6r==`*C?K<$D zvpW5qPf@{qp`Ub^!@2D48Y&Mqeb#Xq;#%+JNa&t(@|tddO|<&7I{H~$ww8H;r3G8SO<9pZF zDx$V;ked@(>0JS@l6u@^e;bLm?f?TDXOxD;iXuUl(i$$M?wMpCrcqXF%BQZ*~@?mjS$m#hQqRPkF4;P>X@RA|mf+vk) zb}kW2)2Pg0=7cU<3#?v`K6OO3rInbN+spai=aMFFH+hs>QrBLfIdOYb*s|GJQ-Xb+ zdim0>Q1_v=>;~n=sj&OOtsw=)>u!}i#}Q02WkPIY?vWI9V|mQTnOT!B8#L^pbICLJ zn-JqMK)xfK%z>1Z)7r}_`^y$3FU&-VxL#P1KjxUni)q9x2UDZ(;L&35>_LPGGYHks zSr-<+iIJa|ebHU5Dqm7j|L~x+BC{Tc zw!sFIM#2hG7U`;OFHjgICHLRE$5Gamt%KULBe&IUXDZWX!oLpas-?DjUFZUyP?5&;D%5kwkALZqd;L+S2DhHj+c+jF1i`*rW-4m0zf zvtzBb*Ev*wFIUL?b!ZOvK)n6$zy(4c_Pr?Y0am@C?n`^?FO!i-X7jHPNfi6C5(`it z)oC}9=l+}xw}K-*>6vD)4wuXrI*@s=SI7$TE1Yosx>-FmyIgQDRv&P zkq}rGp*)FOQGyTiCC6IC)y=e~5AR-x6X$pbRg`@=)0$b+-GZ|glOv-O)8GA41vS1@ ztNh5a5?C5uiNB1$AZ^TPSt1ja)CfA6_O&Q1xf_b?<<+T<=T;WFQQ+ z1_;=Pn@I&AWzHz*z6Jy zHO7a0g#kAdKJYUl$Jas@XmBJS#)@%Q3m1zNHf@Vya2jwYrK_(6oM|Ak+|MK&*0S-+3x%=<}_{;@sxJcs+9M~}6>Pq+y`Llcu zecgHx%P4+hUz^nudEp3UEPP~0DAk=rd-KqZBgYA+M0fV={O4~i;&)0q*diM`sCi6t4g5}x6|133c-BCPGz~0=gVrMDZ zx9-0q(pO9z96ZF}6hZoGuy=3DLeoqZMzjZw=d4auaDo2;#h8vWtAPj?tWqZv1JoX- z%i1WinwH?OSJAo})Zifp?;BU2?z@9B3&&k8?*(jE6S!Ual37|N#!59T{ zK4b27KkIajCdv^@wt+%>$((UZtGe(pvTH(={z=FGdL>{4Zjb(F_{Ri~8|p6|);CRF zUOvYKesex2WWn+QCi#5qmr5Pr=fEJ55-7nNgFoq z^pwKYMs)WMt-M}*eGmRha0jW+RD)&nDcC_l1qE;%fHG&?F?W%vFlS{;|U3S`Unhv#jpQ4`CR?ImWnmQe>ZWl3v>}f!3mhv zso-1_7*~y~Nn<~S!na?tIHcE|!+6fCf|0xhsiq*A zI;b#TeyXN_c@6$Ua&F^~c?u8Gk>`Yv(6)~`<6mWY@nBqM66~MZ*-#D=PAgvXOlUA) zkLD)vyzGAlkca2o$CeqXb`^|Z?DJxoD~!xcM$`9o`<0|6c{b4@s0Oje(Oq=z0nIn+q(8= z329XX>VYwG2xN#ytP$JI$NOw4*h)3k3ukq(}L@Z8Cxx%wAR;;8&mBHkonr8vK;dFYkJl#=Q9;z zm+}|ZM*&)f3Py|cDoG+$l#|}$j(G@fF=a#^u|()Uo%KUsJODsL{3&g)tdl1Cad2+O}$T>Y3Gr4!xQ`? z;@DfqLU$IBWfVneWE#St(iOqNtEK#qzVLPNEbDc&ZXf>UC2zRE;c#bc?(n?% z^6uZw-o23-T_RfXi6#8+sh2<>Up=`e79Lk(%poh9)(qZh=Hm2pBTY==BYWfkNqQ)- zT($R-D0+bh%rEqCu{)zw8leUeh4vfHpqQv00-%L-7sc2yey$%Is#XL1|LVn{{6gS!RHtmREgk*=mvSGZ3zsgND5nabRF@^J{zanLchDD za#B5ti}L3HG!>*~3Ad=InGBGVEj0sY?guX`#0K(?AcC`bD@F0e@2pEzK@&pGy%7Vw z*}El1HXY75IYRTZ5#XLiTCl-Y{&n3{*zfSH0cmJQx*e6TucAEu7S4ihXt@|OfIzbR z@KCRI^s>uB@7Z?nRU>_EQ2K=SlBAGEI#4bP@&v(ief;Q|t-dC5*A~FUnvS&ggM4Z? zR~3q2y}VzbvB$#cc7BfflzvxT+=frn!mSOy@HkIC3G$bC)53aeymrBVvRyMr^8}x_TKxJV zBLC$5wN7wkQa+J?|ID>?kM>>}u8-?kn(^=twaTL*&XePUj)T6sHxDIGBt-1W(=+MA z{l!iM)to1#y(Wr_acF&Z71wN%uG$J2#t&#;TZ)>ko%t*sRqPR*=k8uObA?o5V87jho=#pteh<7;)K6dSgYF=UcHMc z`uX-`etGc6z5FL`D;iT~{Jlq~qcQtCIzy!2L|xF`w}UgRTJjkB^);B1?0?#kg`3Q_ zgx7jDV@XM*4KL#-+l$}V3~HKHq35d`b)`_i`5n)1d%Juqm&8VoPMybD%;8z(?eP>> zgduhnO=05=v}k3tT(6LvImePamw~o|1H3qp6gY zVwWd-^*Wg{dA4qN4t3A8f4`J_*1O}%N|;+-x*Cb)geepec;8$w?A_gwJM)PZX1_1^ zgPC{MOgG-Mz!tN6gKKQ0o05?_if>RzVc?iZBYnU4>C5U9J1ha`%+t@!uO|=6OgBUkYokubm4N%3auT?1i}euFC4uLl9se zr(gBLA23kBL8q-2{jJh%r5N)%QTs$c`$AHbW=ZqGpyB(o>gbKVr_5ZTg@JV`%^L`& zO}hD7-8!K~vQ3FixuWCh`M;v#tTBU$!=7|LWNZ(7A>0^eM7<=eZ2Yr1KbPr+v1|T1 z^MhaBUFnU(y}n?lEpWNP?lqE3411cB{MYlK#3xR8hr>~)8oOe+mifYDc%X|cmT}yB zM!ootMZds@GgfgWGZ%$x#B7i3t)M-XMbcLccd4(e7W3B5S@0N5y`lf{DZ_TJTc~8KYYwpb8 zt9EZjNvbw6$;%H*0qD(=&3gi4;|^^KT=7?5PJIx1sA z#U8!%sn=n`2!4A_F`kZR2l{9O)8AAOwl)Q>oA*Y~oV%*UNomte-70;OC0ep&Dz8@> zlzUk&MW3=uaB?J$-H+3+^m;0ip|s#Vc>JSJ_{L|lg&!-3L@qW`3x5BHzJI2FSntjq z)8f+&@T+)ac%+^aV17&yz9U`{NRB=CdB<~l!1-op^2b2wF`pSBILSJv#G)?Bq#Hr|S zN7P6OvitmSz3N2Rrf_IC3`X&MCzjbs^rpApw#oZ(sN)kP;*X+3e9-SK8UhO||5QGX zzk6=q=UctqnjPP<$ngEZg{zRcal-ZqMY&eizgKU4)HXYf>MDsk(6NeMUQyz|JAXy> zrQ3+H+Nz_SWgz$v{m0l3`%v9h-`d&Zp*e;^nk}Zwi6?Ws_(40ey|%j^>VoDfoyDth zqQ_5o)C9-BDW)l%Q=p{#(0-_j8cLbiJSn`F|4I1gkyW1f6L!zR3&p+Oj)DW#Pu}Y> zL_?gBol9Nv>Q>Scx4#i(^9sRY1R9@5u$_@5#8lMDAa_KO7v}C0QIqh>|69wk*|zu*r6JySwPqzn3l* z7cHWYELt9lE)_`=Dp2;Ccfdn|UYVCt(M9hnhGnUoxLmn|vG>A&R7Bk^3BTS#xmCH7 zLs{3B>?1dNf*X$6!SVE0dkET5(l)Vzoaz~#&h4HQ+f&Z*sZcg*RGyPsQWPB7ptI_~ z;z|8lBHz9S-^JkwuFq8aX!l53k|Uv^9Zgg!lq}Erj8oM4!6%|m9CLl0NvxrF>(TRT zYO6|^cV+72J=B{Cb`4OYd!9HxPFSt##t}v$)K*%Nt@|ty7A$+*1r4rc@JOz@qEcL=|=lc&zOJfZRMFE zh1h+zSrq$F#lsE=b#h4o%?l1pCT)2>!g{ukJP^I?2@SGe$8mkTxXHJp62IWT?no?z zIA_wS^vk4uud>+;@yw+5MVKDTx`NaMLU-A#)`=jCpcB#CoBSYP|H+(scVanq;DTSk z35CjD(^{Q4K_DmAGw3BB1|NjkL6kP>sxV^ z04Ebd?#>xO@*Kn!wQY)uKtg%6we8j@L)capw})N5bA8%XlSFYB1l0%Ks545E8V262 zp)rX~v2QcO-k2PFsVT>8$0L&C7I@yBRhhO)^_bim(tlMB<~`==aD5e-8<$iLq}N!) zZ<(9O_{C`=Fug?`#T*{_FtOkf=_{zUi4C4)3axX34AVTG;?{Oo}|=W(%1VKf7R($HQqEa)zlO8PK<=HegDMP*nhD!2kV*e zUFCPt5!+=8r%QSf`6qChCci|)X-K5_i39u*jno1DAD{h>l^K51zp;_ z{x_jAw8CRU>6KXtq5|v_3dH~-;Zt(>r9EvQQ5_^8#q+_k*5uAK7(V)qUN=Ci4jNM?%G%Yu5ze8#tRDQY}2+gfkr z2W?>$4+;L60I)H|THN}w+7(}nM(QQfCXk$}v-8j;0LOJ2o**tAmpbsGG}PcixxjPP^RoMaSRl&@4K&2E&di=Yb%qa+A2;_OlVgRi4n~+k-gEm-y6Z0 zOYFhnMEXp?)+iWCbKLw9fWk#Sr8Hi$8iMnIK{wgTv_BsNJL^7@8AFrAK63ruU%~z% zHxP68aF!;6#R9_ejWIXDyK~rqmc7QurLN`k%_Gk%uZ>Zl=|Vw89XU!`P)TARZ(qA_ zw`_6Rn#1_-0NPb&V*LB?VFmJsBDW#i6l?N{E9CSn!u|>-KK#I&97KYWqjc6MFOM4S zo-9mnp^b`|(==&r-@e=v&(5wa_WS#cZr^7^!7&__%^$68bK3YzSj;LNN7Z-Jy%H({ zs-irFS#-xwWm0mij@QMMo8#j_5ZFA>Gc~>)Tve{T*UM>cTyYR619+5N=h8|l>M1)b z)@4zgs)r|h%L6}fqI&3Es25AOl|r2UZO zm#Cge21o_haA825;MnO(5*7V$S3zri&(i{;{f5?{T>EFYMOB`*04 zrRr<#n=iNuVjDbfU9G^D;bGzBioIuq4i|YRX0zMQrl9Ob#5vYEd+2!kif+!?*v1g#?O%< zoU^~|2oirz{WaLHv#k5`GN1De&!vt;!;DuBAc8l0kg^2PsJC#V@Cau<|9Uk;6K21{ zR4g?0j%}0Dpr))d?#r*ruk5B#_%xh!`_m#OruAm~xf3{ZLlBH>cD!i`7zEX#9gzo* z!VJ)6?tfJ+z^;?K$4S2Uz>Gd*CHcnYR@5l-q?}{6XAyJ=*o^4;r=J#MfIAkuS*wu{ zq|Y2|cr#*!B=no8h0Jc)Opz&sY`9yUJsjQBCJnghEA(#Ick&uNuPI^utVdnn6mx)& zHbJtg6k$TOEM81Aid7sWUJ!O5j|zA)gzJ22V)_9nZYwE?A;4gCfu=O zW=_FZ8HQLFdQ((A2ARQT#8F97JG5bVe~QkF=Fn)V^8W7y5ct;B*V$(AV$<2?bkpnR z1arn4dL!$hf0~sJN3kagiGs3W6d6NfH~+aYh_^*#t%s;4u2PbHG5b^=Lw!p%cU9a; zjJlvEBDpflMKC7ec$FN$b6=CB)&^eE>$GQ887wgMA+ZP^7wx zknbP;HS#5YNLScS?L~6mU8EGN zo5`_>B=ClL4#$PnDojW@>3-(Q_onZM%Y8q`JxK)$8hgjS5$eLPf)gb`YqwRNohd!s zU->=zy|{`LP{h8stzZ<^E!<=Kpawf$AmmRMl)OGn4F=;$e|jt3BSa%aS3iz~c%u_< zhrGSndH6^)*gMUxp@5k zqyB`qd@C&CwF$yve61HS0<@9EA*;KeQ-nv4<9}H`B((vn>vv^)@=jZykY0pk zt@1wfW8^oQ+md_{c-dja4f}zl9aQ0K&sR(@pI%EXc7>o0>}oyA_!QL7%M@ebJ`4Sdp!pSG@AmOwUMGdfylf%FEV;7eMSY}!X`#mzv2!5u8G@Y zByppo>UJhMi(?obix9TYnsU=x?Tha>Yi?9(<>t;0qyn_qC>D>%;(p@{GQ?Olrx|o4 zAWddCMAmX~DOteq0U$a48@#PB>{Rl#!vac8dC=d+XS?sMLvilC_=w(1jUn==`IaU} z-g>!cZ!Ca4{Wa`ykxObpJ?6c2zHEM_8?PXd)HIXDQv1fn^}}q>9|VheR4$g@=C1L9 zTufilH*?NkicdT^aePVVGxlq5d4)AK-g@4#y68=3vJ*p1mQU>0>gR9THxp47vCzum zQMKuKSvD6LFA}$Br;CdfL;_c86Cwd_P4cNKTcR*WFOZTrM5g>`*_f8zN2I=;6ecrA_$veaYNfgDz3T30@nf!ngG!rgg&# zgeBpp4W7;xX0UQ<7C_sAo*7lhd`Wz{Btouj(4d38pyMhDEqYT6Aji02Scmo9rprjn zbMj8XU~8%KPW>fwwHvRXPb-=R2}F-vv2zX{=OEt1)InwakhShM@!s-Mfqt{dlk?JM z5-Y=AQzM#K=4Ia!LCW~6qT*E2ndP3XEL&7DgvQKIReV?VxsnkVE>U$WvqBkAW}c%FfT`o@vxZ^<%;E>fHM&5lkip7j1=S)rHg zdcWO&6A%BJ3MFbIaDOCT0yv0FX$6MAUbS&54@!!JpngMYr~4PFrUuU_%k}Xa%VhR_ z>PDmM_lt!B@N$cVnF*)wZYcba3^t-+ux4(jTfNg4QXY5_FKy>R5logeC$~K!tU1R&(`%tUv<+j($vv& z1{4_c6={dc;hiDzLRD_fFP@>irNw)s>&fr_Atk>5WnMJ{$=h2VL=U+6g{2&VCVCpp zus47*h85^-sqdjnqlufzvMvH@jl0Qxn*HV*uEmpCLY24g>|voi6!l5(VVfQfnxN7- z2tey&s{E8r^~jVTy~sz_MC(ozbKf0*`wwofC!!B5iON?x67f_60eLM|@*w*$bCp6z zW00OFiHUnJAep!q9uYTttdSTA0uWC^GK$B8O4OY^*AQb z_N+9$+;$9hrVY8pU@6ang7(USOli4F30ueax|Y$gk%D_Q4+cy5{Ele|*D`Q(*qlf`g} zr%ZI724CM$V6#q#<6w*fNxGr+NrPZ2;(nS|RCYbVx>Mcu+SKaHuy;NK4g7sg#`q?U zCwYfSl`pW1-66IDsE4`Dz4CZjmqR48zjdBa6XMh+7+@sg$w`e`PBp$MqIOBJr0qr+ zGz@b2d{>dsVpsXNfE(Dj98AahllpqzLFT|c;b0=@qD-_m=pYh7u&ZtR(DYOyxkBH5 z*{CFNW)_5fz{V|uX_G8gGclm8IYd1w-5M;P5Hq@g>+BTk>sT$Z&~ra%YFL7vuqQb4 zi1JuuIcrhmSFZfn7>gXI=g8sl+2yWh&nayop|tbK`mu?HXpdv@l)c1HRWv%>CxaKM zXX7a=p>Oeq&jt?zEjyIu#beTx=PK&mMg51ib#R1V39{_-MBbbbH-xZVkFAkl;fL9LxJ`_f-=RWBw(0AA;kxRUB>Y7gMLY;tC+d9*=pL#MqiRnny!|?Q> z08!udX=PjKfvRqI{2S`&jhM>zAu7bVZ%njG&h69IpwG4{BaX4qjG$o!+YW9%@pqe166$6E#&tKW;DJTbkm$4XXohjNkHn;Y@uE z=FV6iq+1>ZEQ&;7NU{abDnO?^vIW%pF?S_S#Y(GIt3{uD3KOa>Ydtzg^(Qh9F>MqB z`f|Tl7hfj{!+Ux4er?2+KPS%;9 zJ%KO%r-C8By)*O1ul*JHcouQ-q__6H@K(9nqk(FZ85DK(>K4(g+iibj8)E4&wat9|$4Z zQdN@W5a(yFd*Eh)j z=K)rR=_yDZkan#FYW}b5kYFtnPgjZ&ARv?GO4jfxdffKCm<_x~BvcPW*UA7w>mKSt z_ye?;iDCkXaJ2ZeON_h28}J~o?vHgJgySF>750e?wWSgt2H??ICEq{X*cAC_+Ei<4 zpdjA<1ij{iyXalHdt<=;Ut419Jt*(t#2}?4vU_@d!$&f!Pxk5|W>iiXs3T6-!!>{v zVaQ-#b?gx!x&C;2VRN1Xs2bpS>IzEn#bed-lh!w9o?_B(~`==%c|6x~1Wzru_AQF+DG=N&EhI79Lft5~w zt0P>c6)=+%wX)_{+rP$@w9x2~KsJu+UdQ2m=U}r31N^rjqnUVK=s$bMMjg$>gJ+M_ zIHs-Ou>&00*k<1Z>>5l=75q4)zfVsAS}f&y{e!ts;48+U7THW`-A{>MrWvc&NV9+% z021S(=!-FX(pVC=z+VSX$*fCOzg2!!!Y!{#g<)DS6t}R*%uNZZ`^M31e$qroO% z`VB^*=}YFh7|o31Q};Pq#Z;UzP@?A_L&QT=kv_3%o)^hErX{M>vryX4=qp2Ky_#9HjyT^ z7&A@jty*HcK$R_s5{{cD0jt6;rdq?37G&r<_fwa$JR{zGGY9<+ zt#pu+aR14Qb|hZto0)q%TPPY27gQ&X&t}Dc-UCK=N{Z*vaqjOA^b8wWaA7NeEI%Hbz%I14p5bBPy{D}^JT!xYnGv{Z&vo*(n7 ztlkY*UA{wpD&gKt?_R0mbmFn9rA@(|-dhK=mRLP=)uXx(yX0OsyR176*Ts50F72nP&063L+&*MytG&Co zedH9~A=?vlFPRxG^ok&!=~Ca%;~5K&cGem0JrPGMy74J@Lokd}7zQ0Mwo3n$uB&A5 z96>M->apXP6MI1{$HqTnmZTUW+IGQlI19yd=8-hz9sdc4J za-tqo)~k)S*4~?HJ|JKfZi^4dLYprZ!QqGT*l}myk#k0NCB|e_2dy|<#zS&u2+Ebq z)~fX?c`Kv`Os6|_S$&%zXXRBLzvp?N_Zo`41u2(Kyp02+Dm;`uS?4VWzda0~$w19) z4u+xB*UT;axNf6BATtVH#Wj*ZYe7_j;jm-=1~1G?f{DX|aiAu|ADD~47_V#A2|56~ z(KF8ao|EDnunhWMV%9S)@4$0W$=N zQJ7As_d^zax}osgwI=h~$G(myoNgJb{HYszx)d?x(-+nCdN^s`8(P$NFGdw;%KEBw{l|7Gn6d0KiJ<9t2ZO=U5+s}2FisOi_tsg;&QyBSX@R5Vj zRef29982c;2jS%t{S+)VYf~^FU!3HynSki2!;cSI*)O|kZr>G8j z+?Wi`&fL>n2Xb1kMO^(fVqbjAq^H8bXf|d|`2mFpxi_HK(m2`UM?4IaPzg9zp3*{! zxK?-Pno_*!@pj(a;)QjwWiz0l8@xrf^M%{(O&R0+TdpaR#!Xu+2_CZROn^k-R~l~Q zyUGxlyynXh-tmMT4s*^4yg7N>d|y{9>N$+i003GzChEBUQRy8CdvA)v>AEce8`G|S`9JQYL&CrA~v_at0AJ<`T`85KGnrdlI5 zV>s1d&B~0CI;Rsel+@F+z%yU&ky3y1iv)op#dJinCFo$gcf}X`TumlY!*Roro4ESX zOAZ%M(SJ*YgtJT#hVlDAN7u)Mw-@X_UxU# zqZUM1c64McKWEatJ?rj84DRIhS9I^+HPA-I?=d(Vt(I?AT1E~tK|A)5jaR4RB@mKG z7EHwZvq`#CYYE(QOBnLa3YPGXoS<-@fYDCINzsxd&;WZoxvCI61|AhNfY zNZw|=v?u+}8~If<*@Hc7^-U+uM+CRY@x3!D_-dd-6Kg8*n7gF6GJD+Imj==ADOQZi zY}F8p+>DXmiyOaXS<79VA|+J8%|$XBZH61N+5k?BN@p&no#3lK+bw=D0C`k&ECK+j zSvfgc1ZTVSx0;tDl>WRQ;jNz2mNbuNLs!#($E8b<+8S1RJ@}Q)ITs4dNhYe-^P$1N zJ1|)q9H1)Zh@L|xKSafMFk_7xLYN5?gneLeTS7tl`3&M>KZZlS9uOQRu9aJVX8fb% z%iNl8v4P_%ut-QZ+hRtfQDVF0>V0y?*k2)0n#{$w*ctWZ3V{AdZ%Mi>lyv^+uTXM{ zdH2d~^5B!VVF&N)sLkr9%B7@WFDkw-jnO}+HD({jfG;|55i$Jv>>-B;h1|<8w<+qy zw(ECeB#wvfF(#`s?&sWIoEofjH0#^pqp4US`YQb(fmN^4rZj#Ut6C)0wvXkXEl@V- zFO1`5l!8ffaO^bmr_5b0%+xpZN+vIqr$JS`Ng>P%O9Q?SOc+Oj69D5pp1c%rH!w-5 zf{wcZSU#OyYEvh-V7N|dV&L(*p*NIn(9DoQ&Dp0Mf5)Dy?JTm%N^4GGB!QxkQ zfzviffus@)xTiNdQ!-N8sP86y+}Qhrd8zgnIY6cDbVv&r@88fm8vrza=X11`+lv%3 zGHK_>ABp7(g?;N`?%x!?vUjReA1{W#>^(I7T%?F9s->xxEK;tZ!+K4guG=urk=NA- z%#gzZ^^Dy3Q0H22|J_k4K<#PjSn8yB#F{X^vYa?j-Lot??=ytsxZWz~iC}TRdGr!8 zezzx7YFp!5*PBp3RrnURhyv>Ckkf)gU*SDb)KO_&G4_oG2h(RtsRXR_?%K6;!ZUX} z5(2WKaD5vc#|+|<3!yJii&9nPTnGhS+*p~WuNNllVZDK$|0T+bi|^PFz&{MJ)aj?d zfww;cV^j~2>_G|z0AJ>yAzUYQCJb6f&UOmFZM4kszThJ!?pEcWqq%4HqN|d`?sJjX zvd*T_VG45(15vV6W&FcBPzb3rgz*911kE)qFAmqLZZ^UV98At?w5l|;F>EkD4*!mz zOy3qB_ojxZUmUaKRBQgTb|b)(ojdkTRN0FjcdCu!vl>A#@nZZ$E_#_K-!BQeCD^=7a8aZGqP zWV-jpDeqpE!LkL|MSk5XyBt2YpA^1|3{Vs`?9e8%zY+~yp$FYuuRYvM-oO%(y=y?6 z@YXqDZp}Tnc zqjFr#<~2i8IrsEczPwv=zF9f(px^84toVZoMF%L#B!C1=krtb&tg2#Q0u0t^1}djI z5(`fkMYz~z>H2s8>+SloPe+iL$W#hahz|HH1ZlHcFkkmLJNTu6B>;mR92tMbAGS-W zF!Z1*o@boiLba$DT_>leP2cX{7+?PJod%80Ta!iga8mFzv3pT-+vJC&CvDcplF(^O zmh0TL@9TYKwiO3a{9H7?q9~D9vh3UP>l*9sXDx2WSvv!k*Q**q!Z353^37ed9=O$B zeYF!KR$yNcIE`gHNshtc%21?t5Jt1mI*{`q|n_wFSgU?y_aW1&=@_&pROcG|TY zI!2LBCckRu7rEUheon<%KNk+9Sg9)^bmh7b2O=1$qwyK}5Xkk8E*%x-HLBWOWA~8F zwZyr4b00^A6@zCd%lw=h6v29d^Sd5bRb;zOSPiXh$4RKtZw0~-`OWrz2lW3g59XF= z{}DLaPS^O8`JW!MWtLrx)OsSlm;{m+{G>jf!u5uGxQ2U5Efp`WI9O_&qoenE2cJ)C zgBkMfpDX)|6+v3lb~3~Q+w9n0RbTad&n519{q^;Hl|@?1!#=UF29N9;iipCdF~kKe zc@j5GKK1nnK-JAD+fClt$KV-zk-GNxP_nu1+?Nd) zu2p$>81Ybca|!(JH()WS%;NR=uY3y>7~R(qqv*AlQ2E{WZ{hq}{dkxq<4vdNWqZ0S zIlq<0u*ZAw%oAUG!GvG3@or&5gnj;nUU%|8O3sU^>-Hr7Guvr@2Z9vIt8c;ni>C;~ z##4XM&^4or2dVzs7+vllyY9O?KBk!UxU|)&i1oMf!Gc}tnv0%4tYA-@5D!FTYVDp5 z!|d{uz-9V%8|;bW$uf>uEe~G5b4ylVcHJTS3MF^8cd|>7VPaM{U1Bm>{$|dR{0#`3Y<@xRA40yrA+c zKJsnmCaN%9uTXBKO*1a-&0QDnm;xj5kvMwgvp~=gv{Qd>JD>^QzcV$K>$um9?P)Ie zWtdT0uIE9&&z`uxPXmSI*2aG;;IsYk`@qz(*);VDMXL8dVfK@Krz*n(xEZXwJZ~xx zc6f0nYlj|2c)hgOgb%ap-Wgq=a3h-{+{8R6_RDEyui5=iWhP(&F8BYC>W^UqC`Lt)lNGG6B2o#RVE3f@_mci*xniPo=dh&TS7s#n>xtV+Ogn0tc?NbqAJigO&rS**R_NnS!~C9X z&wKcw`Gk*wVLO71V9rcu-lIYeG_A;*9-s&AOx^z#`StP1{*p5hBP+ z;F`pXi83IuX#K)7DL*duVoJN|*xKradpus%Zi)|VV4{gA9iNA6|jKj#yl^{#tULU)alE^qGHi}+ti zi5+x5JgM-Pj2iLhH`+dGA@Gktr25_hwJZH<^_I`cLg8Mp z+(W$U!TmlE$cT~KZ7E#Rf4W5bhq4B08n3#ctm~yYa_|SL$i*t_b>y!_`_M~|-LP|y zl>`f<+nX)b@^$?Q&7Thq!A2MBh?8jx1MQ;}&-n9>w((NmI}#VWW5@$6vi~xCUaJ1- zs8ODask$~Dqz!4%fMX-wCyQcyR5PLFy|iCp`pz`}d7pQ7@~m2H17hLt39^_$@!E4b zqczd(RXV+R*ym5mm8seuU2+76Mw-(aiti{2Dz(6Wdho0fIP6`*Uu9S<%v4N2UG$EZ z$V7R5^;$&YSciXY?D$)+I5c#@-}PVLN_?&~6dKwpTzUjKBDIz7#74bJ2Ys9sSc%be>Kc<0=0Y(DJM zdx)j=DC~eG1j{J(jMC4oLe9ny-fSF(b5KYiQX~3&M}r5_?lK-9w{O@Ze*nYhSJ%ew zbI<~$;HA7qS*rIRfj`J}=w#=Rq+-?IcC6<-a<_-GWhNkv-do)-ws-W&T>IfSA=*O^ z*J+!!!BcDGb}b@L6lwF?mvt*}3}utd6BwnwO`E>DJz99URB@7jLKe|;TmB$j*nU2( zZ}|6Y7Ko?Ga#MAi3a8*C(!cWaZZks0Xj_!u{tgUc!>j!DZA1l6#hkAz$ze+80SAPl zS1B!ozr>86hQbdjhy89Lqvg>C&dZA?rs7@FLG zng@~*$3FpYbqT|sq$u=`>)Wtbss-mMDRZT@=gnGQ8V}StXHUAg^k&%_(jZQdJ7%bK zhECGsiEhC~9g+CG&?Aff;^6VcLf3ODTLkoH_Nzf;I`3@iGx~qwI;V9!4o7g(`o5gH zsA2Ih_j&j!Mt!gOAgx$=ymt4(BE5YL)S&6rdY1E(h3$c()01=gFQeiLd^{}1?Wp(8 zcCLLFuG^5!+)(Lh36=A8lXy5KKQ1iTz8JFhn5t9y9W`-rIKD?}%B~j(AZZN9pF}5< z+@JRSmte8CSjp#M_@^x5`NevmQ92x#YPgsuBM(*spUfrU^ zE{4&Wh@Fd()I|HlFF7P4t1sKPSF7Ljr!zU!hT~~yeTs!420N7#A7KAOwwJFG&z0-a z2KEB68Y-iZbrPa5YUf&!+K}pt-GKdjRaqAcXzd?U7vsd8WdC%LPT6JSdF(uDtwrkx3Z_9#6u3?ttPzsX=o3YV*s_t1<9;3MZDD1`yzluJ-ar#5%_DMl38RozD0oLz%s+kT3H(&F)BBoOKH@Fg)(T3I4I zV}n1i=D8hHA8`Bh^3IF3gtUoESuL|)nhE|0i_;9Nw=*i$*0>?1ZEz|}4NgFT;|jx# z9z5PKCi=8)#Q{wK*XE5+)`RwwbI`c09;gKWm1n~qu+B9_N9)Wgrf_mvjM zom{W3?TYHe^`-SJn2nujux8wYF^rnf0!eQP_U}X2wd$b}#YF3fjo&am%Hv86`<%MX z*H>iBr;TCtVO#&f&(2~OZp&514}MYANkQY2BnA{OR`osr&tezq6SD((vg3o1Z$8Mi z0TS~EMSr@){ymku5!V-#BLdc57kMyIm#*Tx=-3lKBKW89nY`+!wr3hh2LNoO4aRWN zKUwR$yG?4|5!R&qYjJ8rkLaFr=457OV!Ti9IXaA?|;#C`H5%(|#XqNREKRbSKBAOuCZK`R!0;gpcJBl&{3 z#Hps*@1STwdE%y-J0~l-M5JEcUY)~{21yzvbDS-CLC^ewpk{^Mp|szNAfd@*Be!ZR zp=OI=he-V?SkhmSn};_MmPHlMAH0ScAVfW>t3UXasQjvPBgH|5ip3s2p8FaKuL&?79@ZX6^@t|46PnK&1F9bbnpt|T=FGccSc&9`GP=S zP{}Z}JAbey^wl25te*>YBU7zI*83ldR=Q|%e6w}wK&eXLRcHO}-EY=AH>tTNvPLtL zW1gyt_swBErTOW)w!xoG2jRMkjsXI1^{ZjyN=b7;0u($YDo^_H{N>gb3*0$k6h&5? zv2JAjbd%q(nVG2ow>5o$d-W}_a$N8?_h}*sg!U(_E(?#63q1|Od;@7<@jrTIefOXKpCXhIfHi}s**1(;_GX*)F zfT=K%x5N7M;w8~lgudz~(GvfO|NiTZ-W>4FJ$2Xc`k+T>T1ji3O-2}Clma8-Gpuu_ z&=yBdm;gg2WWaE*M{jWJdriqWh6bFpTVw%cBVnwTvjJ&&``1HqrUF_R(J*>CF3N4u zhrns!bdY@eySX*a2cUK7bWKYQ(m3t3`*MPbL&_#kmjC`ChYTouuWX%tKc&9q&SoL_ zl(NMm>MLk##Jpt8aJzqpKe*f)uqh0n<)*CMEI0Z(3snYo=;M$QynhjwRa$!`rKomF zYs!k_X8fW!+JHA}P2_?6rupl%tQv0$!BeKz-(1)C_J2^zG_cK>s??8$jCWyY4~O`q zn^x%Xo|?8tDYt=5H|}PDL?o3OAX7Lj8VDb^5LxBS^^%7h#@X6x6gcnTpxFEV7Ti~u zQRJ)OwSQu}B&tRzRoeg(EotCaoHd1)*wRFLpfJI)i3c#Oby!%xk31X&He?t;V7n(G zlLMx`CNS_!|42dC1t&Uywkafo>r(U^xN*U3L1MuH)1$3rkaFQT%QuAEv*f!Xe#p5Z zn;1_nm%jLseC>@^m-1Z9;`98OhO~@ne{RAU`!!1<1K%uWYtz)=jAR8?YHi873OO`I zFI!6n*PA#UbdLZ_C(N;Ep*ybqkEpMX=lc!&)rM(P6Jv5ZrfXt;nw4&2!^HH|n4a#o ziJ6#YrrS){beryO=lVX+Ij{5IjIU4J_f_w>xk;!9sL)9qOPwKvtaf09`mfL_8iSm^ z_iyJxIWYQK(fG=Whm(}2+754%>KvS((3@CV86?0{g8wIMv1OncjY&7?Uk14PK>P|0 z7bW^40HokaUX0m31@shfU@*d9zytODOqT@!j=QGV5zP)5E+YLU>oo4PFT*X%#)VSu z_C9g!dfq#-CU{z(q@>VLtU!z7`{zPz<%*jTkS%xzQ!YjrpUG1Po6Su;Qh2E>lI~|{ zWug|79MrzCDg8R9OZWO%w7iuLli>B#k^2G@e{&p~?ar2Q)YwyOUa=~_?F&jVZ!ux8 zRUq<_TYUp2?rGK>0P^prKQe4brg@M|8BKEX{Zgd99%v#$@pTRFKsRpeU9GG_tnY7Ip{t`?Ot!fk^~Mirkqde2?h2u=GfwA%)MQr8=;O zlG3Pz%$9&wL9RxKFE@m9#eD}%44|I`+cgWWuEb44M*z@dboQeCg#py8Wg$|= zNWsX9((!XRAgZZnR}L1i0A(X?&+K=3Li6lkCqdbTNDG z5GKIsHi1~3Y8c$bSL_)KF~Bc*-?10gc8x%=hlt!H9S;=5FIAT{40z|ydI&-0V&!@f z`wQPxJf;-(&|cXGCB308Mg1X&ys49yfYSW8Doppc^2QQ2w0=qE5VMC(MYmM;9=(+b z4P?AHa!t@P0B)_}oF^^1f{IEXLD36QI@{wA zMOx6?=?G!?1kHTKt(YQv%ktdIwq++7p^HX1@wx;%RJF({t>$FsGRC+&^MLBsne3C@ zUKK6^dEI-e&Z!CoD3wITR}2jC{YTZ$^cyEi!5gH{e|j3!79W)j89BeL2LpnhwsO>k|Cm$#L>7~a@zH_TpVk{X(gd;PpOrs7R z4#UJG?61czDw$di#BkLJp=ekGMQ)-X>oSTGhK0H`kY9WSrrR+U>|mxKJh$(A{KP5K zDpikbNO%MRaR3F?ZJ%Y?;O%LXMr9QFwU4$$s1x$*IB4X7@I*k^6sWb2+%SmO%y_?4 zfwdC!f(V4j zTl=T~a?G|$sBu!*;&H0}Q2xMAe)EG?1`cM4U&1RMOxwzv4;TeSTAhl{Z;meK%cp{$ zwlY=_A;v67C}pN<_wb%l^{;_ot;2foYa%egiJo!&1c6WJ#Gsdo4`~3P z3_P8j&Rv{A?Mug6&>D6UHMwB(LO#`6X#;;ybfF#5D_@DXU-eC&sWN|Kz54}~AoH!! z?{Iu(o_4g@+2vEP0n{Ic4CM#TXb+~n)k`TfK{RQ=T17p0eXc63`PG&c0tI1$M0;@L z-U!EVK<(vd{s#jH(6=-Q-w3405@#zy*tmwf_oQ107I`H&@234 z6&R}vaj@XPY$JXbi7SrNkx4+ytl1Qy^FWZ)n&KIvpzM2Y`(Erk)!dg2w024O3&xPA zA~PPhEtKc1aL~Pwq!C)H7REnuhFAHg+G>i}qi z{UXttos-4=_hZ+Yst_GA8|0ET*&fYXv)tmZ{T7on)JX4h-3EpT;<4SF(+H@W z!`sqK+c&^Yy)pHFbqR>ZyvFoe(L0tp^T*J|%P9(sb7fJB+{PmZd+)Yo>{I0{RTr~% zC3QC?y?A=k9|;wSRsN=V=PGZkw){+uF(iC`fB3n%C9o|>JYHcThMy7jL|Z@fyA!D= zsll*n>Xt$Fp$!FsiuLVc1aiE>A2w&PdVrgD-GdPsw7OraAG9dsoSMQB zG9;#J?g;M|YXuSwsX3@}fy5_~0iOub{b7i+u6;x&8IOD-M^K?5W!B%-qO;MbgPv0Z zv@MBG;!MktF2cKVGzc;xjj@@k;-M+Clj~qF8t2g;=@jyh zmtTMOeiBErD3N+n?VwIA1)@BBPeI%_wCObLcdnwcTrQhR<@4T?abTHzme}%t6RswW zwoKnS5NaV^SJ^`xZo|e=OHF@|Zw!6N*Ke6Y4UHZzo5{xfSr0?u7VTCmygm(pSX9Z4 z36btF;LxEaaIqw8hSH`yIvs-=h7d}Ea0;|g2oeth82bq`0j^UMUI6%#{pXXY1ttey zrPSKe0hy^)6P~9CUGAObFF_4*f<^S_g z9wd-9f2;-_3*u@|ghf1oPeywb{)C>%zV}q>j1|Kf)*~zQ1awqY0~~%ohBmd8yyE+- zLONL$@)lB+$%#GnMOsujmXcXw>@-1~_n*llRyyq?S&*$NsYk@+TL;^2T0emiI{l^Q z2&zmZ2Z+x=pJbiaW0FJWUF-FaV4Ci0+?^B)34A&qp;t_FMKjfr@W%&(^-(^z?K9XH zL*E1dY8D`Cko)P!mg4qJ7;CUf&6)iKO&KM2{i)SNs#|auq|R(czziFDO0l)==%>cJ zt6)pde=a7d6Qwev?h>b;8#m*yKkdh`n#L zX$?8mk!sPGP3!h_)5%r#Oh>Y&4)0z#ksC)sSqF69K`X5?f{n?ImtcLeq8z6pW9!eG ze47L$U(!RZB3$abl{le8t3j0ukZ~fDQ|XomsGf%#Llw=DiA=eMWXz$iMpA@>!R|Ik zGsGmAuAl2a;Z(oQ*D5_Sfc|z$e_>v*eM?&g2Z#)5JO#UyVu@d*e1#kgfAOl! zxX8*u3P>7NlA;cl)0y!Zy`(6uvtZLZkWQ`#~h=d~BNsvEK zF-J-IT!~*fO1|&4GvgGsZOHKHbS)z5z=f;}+TZqX^))l#tmdSvIhXv2a``axo>SV6 zP$$`{6#8+rEZ8i7@?~PKC%m2OP{=rR#T_p6caU=N#B~+ci;egK#yMRH`aaZ+D?qz?w=p%A_QdH~NmzV(=>d ziGjRVyxNYBDZkZZ=642?+g|sc|I*CX+Z62>>7WQgAwQUa6bQ|z9Jqox^~C-4;4nkP ztPd~+a4bZZ2qh`QFLH~)_U2{Q9boneJP~KP3=~}nveH)vE?P7Zh`EEspuZH3*ghfrUEy9m(Lpv^qdrXIG*k}<wgk-3n?R;|h5**~PB^IgKZ-1!<qn;P;jhcvzU%1;4fp6BVoIDRN$$G+d=%WQp4``IQ zd!QlgK3|3I^+_h^)9hhh!D``t5SzaE6eet{pTJnyi-8nsQ3z@vypH7WmXlCTCQ5i& z#L0Jl&TF9(SVa2Z$5<(Kdz+WNt(ML`Jf&l8&yJjN2jvfOXVSg&!dJM*PThLhtqQ@9 zZJ<-v2xh|2fITb=vHbc6B8^5D4iE_3-C6(0^eI;LNuFz87@ky;v;?te@No|$*Jn8( z@nzInqFids*;XF;mW(CVH0kq|&8LgGjRBiZKJOB$K3ciq;RrPHAO)+)21}%3q-w;il9J7I{Ohl&F`(tz|RWhWH&Y1-STTYqXC<@*=wLlFVfF(|Gn ze!>%hgW*xLVm%q}XS{LYf_`lv3=kF$$%qfLMXs$Rxw~Csnci8#2PPApTJF5HNY-%0 z^?{L71RX<_SV5>0QFa-AYH{!(vcP{X<%!Gzb5cX}3VoKus(2;8pWNI;7_z8N*JtZK z@!EYjq9_Dft=Btm#0$qLQ0trpQl(SOoi8^|pBPB#znOm_X3h*W15Xq!OyFnrcWk1W z$HPTKh$7fFG_LctR(T}H1{$}xDfvVO2T6I}nmJpqJCsWWvru2u#s`!z(si~G_2+ta zfrlxFoZzFK9CDOB;OT`xWuoX8$;_8pA+n_`Pp6;A7I`bs-_ z@qf)gfX!kF4Mn}y44zGN5PusuR8$afAGOwM=oc?4$-b=2%pPTvdIAbt$a&#%`_QT4 z&?%g}foK~QBB4P+oVpZ>T2OsdsXd6(M5JXpU@8<&663AYgY-DVN+_7Z=5B=@dj-%n zcY(EmDM6mFW)fZBu_<85Yt?{dGA7|!RE-;af)NlC^)5a-{LFe?ZJ}q%Gr^c&%tqp-+=DR-5W+*nrW!EA0 z)LXqsC1Db*#6t>j^uCTv=g6zsSQ%pq-<6=QwcP+l z9M7prt!`cx(d;HZJ2JZBx$cxHs>f1_(p=O1tXQG<-l2U+z<#B>cO9+xQ)k)HZ>m~C z#VWW@5zEM$1Kj?5Wry&834%a#3ISd!~-=bqkHP}$~3dPx%h+rJ7-HyQrb zfLLapA~Z;j8hlBA0cM1p1*f19z?2oz-(Tc?@r<2*;3S+{4B9K-r>(w}7n`xLdI(V< zyau$iTmbW6epJA;0~DgIx`)0EM7y8UhBiN6D9H>w&nO>nv9bMjOiKKoB+MB_>$(KO z4?1$vogZ2^PB5vyBg}p(Gt~ZLQee$J?+}wgLh9PuxqouvK?7!OTMg;OIy((t%&v}O zs`Qk=d;fh`=RMKwC&C8b@XdGjx1!%}nY)vSE2R~k#yDr5cWm#FxgMEC=+`mN?*3Y# zkxwk4ic*URWq=dBo->LFVclib`7uw?gNC#_(Tr29XMiaKPm$7HVT{m)pla|7uJk# zek5ty`fsl)6rrN&y2=^d!G01GY}FaCR0ho}4u3>I>PXAuFT_vxqt(9==Px`(5>wvN z`$@Iio5o?45XqtAxaV`}C)E^M)gnh#O7I^}rJW zQTB1hytEJE&dQdE{^@URrE%`xc`1$)}}M5+cc4SDAgUjb?Txzx81R)bQ8X zR4V<{s&gOpAiPUYgz_j}h*9=ZgI9=LUdW?tkjxvM`q$*<$TYWwdeczsgZ7- zGw&ElD|x4bV9V#mR7|#&rmUOQK{}iv5Jr7q595yEw6HQM;%C(>KzIAU@;QvWY=znf z$79{ecJsr0Ljh&Kf+2xFlpiO)%jLz3sE5Hk^cIDN>z$D05%xAgRDzdVoqkx`u}@_O z8SLrw2K~JrgRT;cgBQ54OScibS`UXhAVkdZdtI$2+SO$FK zpPj>}3Unqx`tKEX-&RC^VoR^T5sDU0&Tk5EirI*%!7bWeW4vz0>U|t??07z zmd=yVyu2x|&0BlXv6O$VPl_>|3jNpssk9;vDz5X)f6ggV+hQBS?=*!?F_P9;rk+F! zVNpM#wjTK4i>&QT&D&LHYWkccn`t+r#wS<=Nh5Clt_fd>O+pjX7Ro0V=X<#|L-BE= zU~7RRt;C~#by` z^Vgci2qy@Ke|)S(rsQquEi02IbZx+#oo6~;-{ww7^$3;l$TZ-~dC_OXW`=mYzGVIJ z5q#yN_kATpr!a90eyw1gB}xcQN+LI&_ve0;EYrDlXW?}D#ZXCra$B+h>PHUJdSWy- z)ONk%mFwiC-6I=EskW;$&i6*mD4pF3_=%&1BtLX3ye-oMYeq+KkFX?F>E70bH_bijP^UBfDW$iVk~wvySthU;f=P;pvn+tPsAp zn@EJS@=mD5sjX6+N|lodH^~u|;GgDOW2C_%Q`M=bOj+y9X<#_0p(FJulgOZ9%Pn1k z)%)J0-b`>BTZ)aR{FQT5q?c1&@v_~i1?j=OUJ%jd1(R7R-Xqa-jJtPJ)K9-9n)aW1 zueB9@KhN|utnITAXS$lL;7~Q$A*|?|pR}KR$V;(re-@A-@D+C?Z8-v^^i(KgDp*yF zC)o7hMZ4nD3C7=Nf^)fE5*;ios=iP{%t%-u zT%NeMXb>Vtd2~)5VI10_C#m|u$6bSI?f1RDGki~}dhfq-UI=FuxMN}OYAEE<>HhKL ziy8fbJdPgcbhgbqw`RSrX8Q6Na!ndq6t|7 zWmK-=QxQa0Ku3w!tomjd$5V-;ixeq7|MjaQOz?>RouCh~1p*iZ3+Q+OSBg-)bszEp zbp%)xRs@|H$)EQyoGqUzGB{~%(;W3z7%El z1T8rn8U0SngS(~Q`06-$)oXYNddH)mCyvPeqS~Wkt&UBi>!U(uHIdb}=Xr+ooY4yJ zZlaa_$D`&@lsDFLYcvc|cxB5S(p-MD<9w$PD?g96N3C20@jD~d3f@yVozA-ds2sca z`?H~QH<#B3nI({jFJ@-q)AX}mP0Gj}$FDPE0ZZvJkJj44qE%C5JI&%s`$FS$ z>Ex9?neu%1C-QqSO_P29leqSWJQ-d1$Xa}{99}B z-Au<}xv|JaN}Z3n>e3QMYlf(?#g2yT&@sZYKKIhxORVf(8>MdGpMR5WXidYPUu~0E zNfG+S0KcfD&|vYVdrPnDKK)pk7*&a_*vIZlYmsH%EG6^p0as?Oa6i191&&`2&%{LN z?|lBZX^H=Fb676WABV|zn=_srW z;>5gCwT)nv$`j40mQVKm@onREZ53*B`4`CoS#%Krv&cdI0BcEnMWj%?CZk>3U1Ldn zB&YVHSoYA*&MY>+H|r(3^^8q$iA}=Y@gA*yDSUu#w4kJ3(W(0drnZG@)WDWdS;i+umYrX8sl~k_twFqd?W{p z)vVk`r6<`ap8}t^MDh%@I;H3?&)sIycj!DY7#DCW`9}O3jj-j>;}Cd6#g(sF|A}BH z{!*NJ$y|=n!`)K&pQ-=u`l0-Y)BA|{ON`F=?alRF>_#vJBt-N8`bw zqH{z?gQwhBWJVGnfBwzMMq_e2JE6J9c1ITm z$FfvBw%pI~9M7n&eD|_{&lilmvktT_u#x$FZkk|hjh%kL{z7-wZ*108*oa-hy#Ei6 z?dogvmu?qVQC}`HOgmiiWyBQj&|xTb$cft3kC8Qf{^_*(0S5)0ji@e-!%~0!nh!li zE02Dv-mK3Ohn>7r4WB&lPj;@jrQpfIq5UA1IN3KbtkWCC||-D-Y2I%%55oa>`EzSPIs)jnff1$Owcam&%G+GMp~ zUb4K1v9so43f5Ro&(t(mSg&4@o0D>pQdcqPbm!Y^ZMw^rhQz`^p4otAC0LMaHqf!` z{y@|DPxjqV3hLJj-!|^Ay{aq4vRBwh*B~?5?&vxh&$A zzTBgXkKF^8ue2T*u^vz<#|F-|y@rr4rUhZ)!v? z!Oifxz)HoJ3^`P3l-pQdcQrnJy4+(BPFpmChjg~j^>=Y4P>}mDC1OdmNKaYW6|I}h zrU?~a>|+br4AMtUOXqpr=c`M9e?-i0TQ`4?B23(Hr2Eh#B(~Qyrhb-rA8!A_dq;kn zjN>tKVH1*c9i1SJhYusq2F!X=tB{sV7x(`gdf|9n7bu*hw1@bo-XXm}htEFGKDmH3 zITMqZZ|AqyrptSSXJfa=kNWDL2j<3;E|k8VNQ~ycx7{ER8WF5%dQLs&!gJM3DD>eQ z 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 literal 0 HcmV?d00001 diff --git a/pcd2pgm/.docs/pgm.png b/pcd2pgm/.docs/pgm.png new file mode 100644 index 0000000000000000000000000000000000000000..d2f6f5b0b874a967cb70593364c135a890175eaf GIT binary patch literal 87161 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 literal 0 HcmV?d00001 diff --git a/pcd2pgm/.gitignore b/pcd2pgm/.gitignore new file mode 100644 index 0000000..b0a66c2 --- /dev/null +++ b/pcd2pgm/.gitignore @@ -0,0 +1,12 @@ +devel/ +build/ +install/ +log/ + +.vscode/ +.cache/ +__pycache__/ +.catkin_workspace +*.gv +*.pdf +*.pcd diff --git a/pcd2pgm/.pre-commit-config.yaml b/pcd2pgm/.pre-commit-config.yaml new file mode 100644 index 0000000..2badd49 --- /dev/null +++ b/pcd2pgm/.pre-commit-config.yaml @@ -0,0 +1,127 @@ +# To use: +# +# pre-commit run -a +# +# Or: +# +# pre-commit install # (runs every time you commit in git) +# +# To update this file: +# +# pre-commit autoupdate +# +# See https://github.com/pre-commit/pre-commit + +repos: + # Standard hooks + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-added-large-files + - id: check-ast + - id: check-case-conflict + - id: check-docstring-first + - id: check-merge-conflict + - id: check-symlinks + - id: check-xml + - id: check-yaml + - id: debug-statements + - id: end-of-file-fixer + - id: mixed-line-ending + - id: trailing-whitespace + exclude_types: [rst] + - id: fix-byte-order-marker + + # Python hooks + - repo: https://github.com/asottile/pyupgrade + rev: v3.19.1 + hooks: + - id: pyupgrade + args: [--py36-plus] + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.8.4 + hooks: + - id: ruff + args: [ --fix ] + - id: ruff-format + + # CPP hooks + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v14.0.3 + hooks: + - id: clang-format + args: ['-fallback-style=none', '-i'] + + - repo: local + hooks: + - id: ament_cppcheck + name: ament_cppcheck + description: Static code analysis of C/C++ files. + entry: env AMENT_CPPCHECK_ALLOW_SLOW_VERSIONS=1 ament_cppcheck + language: system + files: \.(h\+\+|h|hh|hxx|hpp|cuh|c|cc|cpp|cu|c\+\+|cxx|tpp|txx)$ + + - repo: local + hooks: + - id: ament_cpplint + name: ament_cpplint + description: Static code analysis of C/C++ files. + entry: ament_cpplint + language: system + files: \.(h\+\+|h|hh|hxx|hpp|cuh|c|cc|cpp|cu|c\+\+|cxx|tpp|txx)$ + args: ["--linelength=100", "--filter=-whitespace/newline"] + + # Cmake hooks + - repo: local + hooks: + - id: ament_lint_cmake + name: ament_lint_cmake + description: Check format of CMakeLists.txt files. + entry: ament_lint_cmake + language: system + files: CMakeLists\.txt$ + + # Copyright + - repo: local + hooks: + - id: ament_copyright + name: ament_copyright + description: Check if copyright notice is available in all files. + entry: ament_copyright + language: system + + # Docs - RestructuredText hooks + - repo: https://github.com/PyCQA/doc8 + rev: v1.1.2 + hooks: + - id: doc8 + args: ['--max-line-length=100', '--ignore=D001'] + exclude: CHANGELOG\.rst$ + + - repo: https://github.com/pre-commit/pygrep-hooks + rev: v1.10.0 + hooks: + - id: rst-backticks + exclude: CHANGELOG\.rst$ + - id: rst-directive-colons + - id: rst-inline-touching-normal + + # Spellcheck in comments and docs + # skipping of *.svg files is not working... + - repo: https://github.com/codespell-project/codespell + rev: v2.3.0 + hooks: + - id: codespell + args: ['--write-changes'] + exclude: CHANGELOG\.rst|\.(svg|pyc)$ + + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.30.0 + hooks: + - id: check-github-workflows + args: ["--verbose"] + - id: check-github-actions + args: ["--verbose"] + - id: check-dependabot + args: ["--verbose"] diff --git a/pcd2pgm/CMakeLists.txt b/pcd2pgm/CMakeLists.txt new file mode 100644 index 0000000..f07d404 --- /dev/null +++ b/pcd2pgm/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.8) +project(pcd2pgm) + +## Use C++14 +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +## Export compile commands for clangd +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +####################### +## Find dependencies ## +####################### + +find_package(ament_cmake_auto REQUIRED) +ament_auto_find_build_dependencies() + + +########### +## Build ## +########### + +ament_auto_add_library(${PROJECT_NAME} SHARED + DIRECTORY src +) + +rclcpp_components_register_node(${PROJECT_NAME} + PLUGIN pcd2pgm::Pcd2PgmNode + EXECUTABLE ${PROJECT_NAME}_node +) + +############# +## Testing ## +############# + +if(BUILD_TESTING) +set(ament_cmake_clang_format_CONFIG_FILE "${CMAKE_SOURCE_DIR}/.clang-format") +find_package(ament_lint_auto REQUIRED) + list(APPEND AMENT_LINT_AUTO_EXCLUDE + ament_cmake_uncrustify + ament_cmake_flake8 + ) + ament_lint_auto_find_test_dependencies() +endif() + +############# +## Install ## +############# + +ament_auto_package(INSTALL_TO_SHARE + config + launch + rviz +) diff --git a/pcd2pgm/CONTRIBUTING.md b/pcd2pgm/CONTRIBUTING.md new file mode 100644 index 0000000..331a805 --- /dev/null +++ b/pcd2pgm/CONTRIBUTING.md @@ -0,0 +1,63 @@ +# Contributing Guidelines + +Thank you for your interest in contributing to `pcd2pgm`. +Whether it's a bug report, new feature, correction, or additional +documentation, we greatly value feedback and contributions from our community. + +Please read through this document before submitting any issues or pull requests to ensure we have all the necessary +information to effectively respond to your bug report or contribution. + +## Reporting Bugs/Feature Requests + +We welcome you to use the GitHub issue tracker to report bugs or suggest features. + +When filing an issue, please check [existing open][issues], or [recently closed][closed-issues], issues to make sure + somebody else hasn't already reported the issue. +Please try to include as much information as you can. Details like these are incredibly useful: + +* A reproducible test case or series of steps +* The version of our code being used +* Any modifications you've made relevant to the bug +* Anything unusual about your environment or deployment + +## Contributing via Pull Requests + +To send us a pull request, please: + +1. Fork the repository. +2. Modify the source; please focus on the specific change you are contributing. + If you also reformat all the code, it will be hard for us to focus on your change. +3. Ensure local tests pass. (`colcon test` and `pre-commit run` (requires you to install pre-commit by `pip3 install pre-commit`) +4. Commit to your fork using clear commit messages. +5. Send a pull request, answering any default questions in the pull request interface. +6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. + +GitHub provides additional documentation on [forking a repository](https://help.github.com/articles/fork-a-repo/) and +[creating a pull request](https://help.github.com/articles/creating-a-pull-request/). + +## Finding contributions to work on + +Looking at the existing issues is a great way to find something to contribute on. +As this project, by default, uses the default GitHub issue labels + (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'][help-wanted] issues + is a great place to start. + +## Licensing + +Any contribution that you make to this repository will +be under the Apache 2 License, as dictated by that +[license](http://www.apache.org/licenses/LICENSE-2.0.html): + +~~~ +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. +~~~ + +[issues]:https://github.com/LihanChen2004/pcd2pgm/issues +[closed-issues]:https://github.com/LihanChen2004/pcd2pgm/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20 +[help-wanted]:https://github.com/LihanChen2004/pcd2pgm/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22 diff --git a/pcd2pgm/LICENSE b/pcd2pgm/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/pcd2pgm/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/pcd2pgm/README.md b/pcd2pgm/README.md new file mode 100644 index 0000000..4c2b978 --- /dev/null +++ b/pcd2pgm/README.md @@ -0,0 +1,79 @@ +# pcd2pgm + +基于 ROS2 和 PCL 库,用于将 `.pcd` 点云文件转换为用于 Navigation 的 `pgm` 栅格地图 + +|pcd|pgm| +|:-:|:-:| +|![pcd](.docs/pcd.png)|![pgm](.docs/pgm.png)| + +## 1. Overview + +- 读取指定的 `.pcd` 文件 + +- 使用 Pass Through 滤波器过滤点云 + +- 使用 Radius Outlier 滤波器进一步处理点云 + +- 将处理后的点云转换为占据栅格地图(Occupancy Grid Map) + +- 将转换后的地图发布到指定 ROS 话题上 + +## 2. Quick Start + +### 2.1 Setup Environment + +- Ubuntu 22.04 +- ROS: [Humble](https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debs.html) + +### 2.2 Create Workspace + +```bash +mkdir -p ~/ros_ws +cd ~/ros_ws +``` + +```bash +git clone https://github.com/LihanChen2004/pcd2pgm.git +``` + +### 2.3 Build + +```bash +rosdep install -r --from-paths src --ignore-src --rosdistro $ROS_DISTRO -y +``` + +```bash +colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=release +``` + +### 2.4 Running + +启动 pcd2pgm 节点,可在 RViz 中预览滤波后点云和栅格地图: + +```sh +ros2 launch pcd2pgm pcd2pgm_launch.py +``` + +保存栅格地图: + +```sh +ros2 run nav2_map_server map_saver_cli -f +``` + +## 三. Node Parameters + +可以通过修改 `pcd2pgm/pcd2pgm.yaml` 文件来配置节点的参数。 + + ```yaml + pcd2pgm: + ros__parameters: + pcd_file: /home/lihanchen/NAVIGATION_WS/pcd2pgm/rmuc_2025.pcd # pcd 文件所在目录 + odom_to_lidar_odom: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] # [x, y, z, r, p, y] 里程计到激光雷达的坐标变换(用于变换点云) + flag_pass_through: false # 是否使用 Pass Through 滤波器 + map_resolution: 0.05 # 地图分辨率 + map_topic_name: map # 发布地图的 ROS 话题名 + thre_radius: 0.1 # Radius Outlier 滤波器半径 + thre_z_max: 2.0 # Z轴最大值(用于 Pass Through 滤波器) + thre_z_min: 0.1 # Z轴最小值(用于 Pass Through 滤波器) + thres_point_count: 10 # 最小点数阈值(用于 Radius Outlier 滤波器) + ``` diff --git a/pcd2pgm/config/pcd2pgm.yaml b/pcd2pgm/config/pcd2pgm.yaml new file mode 100644 index 0000000..df02def --- /dev/null +++ b/pcd2pgm/config/pcd2pgm.yaml @@ -0,0 +1,12 @@ +pcd2pgm: + ros__parameters: + pcd_file: /home/elephant/agv_pro_ros2/src/point_lio_ros2/PCD/scans.pcd + odom_to_lidar_odom: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + # odom_to_lidar_odom: [-0.16, 0.0, -0.18, -0.523599, 0.0, -1.5707963] + flag_pass_through: false + map_resolution: 0.04 + map_topic_name: map + thre_radius: 0.1 + thre_z_max: 1.3 + thre_z_min: 0.3 + thres_point_count: 10 diff --git a/pcd2pgm/include/pcd2pgm/pcd2pgm.hpp b/pcd2pgm/include/pcd2pgm/pcd2pgm.hpp new file mode 100644 index 0000000..a35f515 --- /dev/null +++ b/pcd2pgm/include/pcd2pgm/pcd2pgm.hpp @@ -0,0 +1,72 @@ +// Copyright 2025 Lihan Chen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef PCD2PGM__PCD2PGM_HPP_ +#define PCD2PGM__PCD2PGM_HPP_ + +#include +#include +#include + +#include "nav_msgs/msg/occupancy_grid.hpp" +#include "pcl/filters/passthrough.h" +#include "rclcpp/rclcpp.hpp" +#include "sensor_msgs/msg/point_cloud2.hpp" + +namespace pcd2pgm +{ +class Pcd2PgmNode : public rclcpp::Node +{ +public: + explicit Pcd2PgmNode(const rclcpp::NodeOptions & options); + +private: + void declareParameters(); + + void getParameters(); + + void passThroughFilter(double thre_low, double thre_high, bool flag_in); + + void radiusOutlierFilter( + const pcl::PointCloud::Ptr & pcd_cloud0, double radius, int thre_count); + + void setMapTopicMsg( + const pcl::PointCloud::Ptr cloud, nav_msgs::msg::OccupancyGrid & msg); + + void publishCallback(); + + void applyTransform(); + + float thre_z_min_; + float thre_z_max_; + float thre_radius_; + bool flag_pass_through_; + float map_resolution_; + int thres_point_count_; + std::string pcd_file_; + std::string map_topic_name_; + std::vector odom_to_lidar_odom_; + + std::shared_ptr> pcd_cloud_; + pcl::PointCloud::Ptr cloud_after_pass_through_; + pcl::PointCloud::Ptr cloud_after_radius_; + nav_msgs::msg::OccupancyGrid map_topic_msg_; + + rclcpp::Publisher::SharedPtr map_publisher_; + rclcpp::Publisher::SharedPtr pcd_publisher_; + rclcpp::TimerBase::SharedPtr timer_; +}; +} // namespace pcd2pgm + +#endif // PCD2PGM__PCD2PGM_HPP_ diff --git a/pcd2pgm/launch/pcd2pgm_launch.py b/pcd2pgm/launch/pcd2pgm_launch.py new file mode 100644 index 0000000..f378ccf --- /dev/null +++ b/pcd2pgm/launch/pcd2pgm_launch.py @@ -0,0 +1,88 @@ +# Copyright 2025 Lihan Chen +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +from ament_index_python.packages import get_package_share_directory +from launch_ros.actions import Node + +from launch import LaunchDescription +from launch.actions import ( + DeclareLaunchArgument, + SetEnvironmentVariable, +) +from launch.substitutions import LaunchConfiguration + + +def generate_launch_description(): + # Get the launch directory + bringup_dir = get_package_share_directory("pcd2pgm") + + # Create the launch configuration variables`` + params_file = LaunchConfiguration("params_file") + rviz_config_file = LaunchConfiguration("rviz_config_file") + + stdout_linebuf_envvar = SetEnvironmentVariable( + "RCUTILS_LOGGING_BUFFERED_STREAM", "1" + ) + + colorized_output_envvar = SetEnvironmentVariable("RCUTILS_COLORIZED_OUTPUT", "1") + + declare_params_file_cmd = DeclareLaunchArgument( + "params_file", + default_value=os.path.join(bringup_dir, "config", "pcd2pgm.yaml"), + description="Full path to the ROS2 parameters file to use for all launched nodes", + ) + + declare_rviz_config_file_cmd = DeclareLaunchArgument( + "rviz_config_file", + default_value=os.path.join(bringup_dir, "rviz", "pcd2pgm.rviz"), + description="Full path to the RVIZ config file to use", + ) + + start_pcd2pgm_cmd = Node( + package="pcd2pgm", + executable="pcd2pgm_node", + name="pcd2pgm", + output="screen", + parameters=[params_file], + ) + + start_rviz_cmd = Node( + package="rviz2", + executable="rviz2", + arguments=["-d", rviz_config_file], + output="screen", + remappings=[ + ("/tf", "tf"), + ("/tf_static", "tf_static"), + ], + ) + + # Create the launch description and populate + ld = LaunchDescription() + + # Set environment variables + ld.add_action(stdout_linebuf_envvar) + ld.add_action(colorized_output_envvar) + + # Declare the launch options + ld.add_action(declare_params_file_cmd) + ld.add_action(declare_rviz_config_file_cmd) + + # Add the actions to launch all of the navigation nodes + ld.add_action(start_pcd2pgm_cmd) + ld.add_action(start_rviz_cmd) + + return ld diff --git a/pcd2pgm/package.xml b/pcd2pgm/package.xml new file mode 100644 index 0000000..f0d2f7b --- /dev/null +++ b/pcd2pgm/package.xml @@ -0,0 +1,27 @@ + + + + pcd2pgm + 0.0.0 + Convert .pcd files to .pgm grid maps for navigation. + LihanChen + Apache-2.0 + LihanChen + + ament_cmake + + rclcpp + rclcpp_components + nav_msgs + sensor_msgs + pcl_ros + pcl_conversions + + ament_lint_auto + ament_lint_common + ament_cmake_clang_format + + + ament_cmake + + diff --git a/pcd2pgm/rviz/pcd2pgm.rviz b/pcd2pgm/rviz/pcd2pgm.rviz new file mode 100644 index 0000000..2f2d96f --- /dev/null +++ b/pcd2pgm/rviz/pcd2pgm.rviz @@ -0,0 +1,194 @@ +Panels: + - Class: rviz_common/Displays + Help Height: 0 + Name: Displays + Property Tree Widget: + Expanded: + - /Global Options1 + Splitter Ratio: 0.5 + Tree Height: 716 + - Class: rviz_common/Selection + Name: Selection + - Class: rviz_common/Tool Properties + Expanded: + - /2D Goal Pose1 + - /Publish Point1 + Name: Tool Properties + Splitter Ratio: 0.5886790156364441 + - Class: rviz_common/Views + Expanded: + - /Current View1 + Name: Views + Splitter Ratio: 0.5 + - Class: rviz_common/Time + Experimental: false + Name: Time + SyncMode: 0 + SyncSource: cloud_after_radius +Visualization Manager: + Class: "" + Displays: + - Class: rviz_default_plugins/Axes + Enabled: true + Length: 1 + Name: Axes + Radius: 0.10000000149011612 + Reference Frame: + Value: true + - Alpha: 0.5 + Cell Size: 1 + Class: rviz_default_plugins/Grid + Color: 160; 160; 164 + Enabled: true + Line Style: + Line Width: 0.029999999329447746 + Value: Lines + Name: Grid + Normal Cell Count: 0 + Offset: + X: 0 + Y: 0 + Z: 0 + Plane: XY + Plane Cell Count: 10 + Reference Frame: + Value: true + - Alpha: 0.699999988079071 + Class: rviz_default_plugins/Map + Color Scheme: map + Draw Behind: false + Enabled: true + Name: Map + Topic: + Depth: 5 + Durability Policy: Volatile + Filter size: 10 + History Policy: Keep Last + Reliability Policy: Reliable + Value: /map + Update Topic: + Depth: 5 + Durability Policy: Volatile + History Policy: Keep Last + Reliability Policy: Reliable + Value: /map_updates + Use Timestamp: false + Value: true + - Alpha: 1 + Autocompute Intensity Bounds: true + Autocompute Value Bounds: + Max Value: 10 + Min Value: -10 + Value: true + Axis: Z + Channel Name: intensity + Class: rviz_default_plugins/PointCloud2 + Color: 255; 255; 255 + Color Transformer: Intensity + Decay Time: 0 + Enabled: true + Invert Rainbow: false + Max Color: 255; 255; 255 + Max Intensity: 4096 + Min Color: 0; 0; 0 + Min Intensity: 0 + Name: cloud_after_radius + Position Transformer: XYZ + Selectable: true + Size (Pixels): 1 + Size (m): 0.009999999776482582 + Style: Points + Topic: + Depth: 5 + Durability Policy: Volatile + Filter size: 10 + History Policy: Keep Last + Reliability Policy: Reliable + Value: /pcd_cloud + Use Fixed Frame: true + Use rainbow: true + Value: true + Enabled: true + Global Options: + Background Color: 48; 48; 48 + Fixed Frame: map + Frame Rate: 30 + Name: root + Tools: + - Class: rviz_default_plugins/Interact + Hide Inactive Objects: true + - Class: rviz_default_plugins/MoveCamera + - Class: rviz_default_plugins/Select + - Class: rviz_default_plugins/FocusCamera + - Class: rviz_default_plugins/Measure + Line color: 128; 128; 0 + - Class: rviz_default_plugins/SetInitialPose + Covariance x: 0.25 + Covariance y: 0.25 + Covariance yaw: 0.06853891909122467 + Topic: + Depth: 5 + Durability Policy: Volatile + History Policy: Keep Last + Reliability Policy: Reliable + Value: /initialpose + - Class: rviz_default_plugins/SetGoal + Topic: + Depth: 5 + Durability Policy: Volatile + History Policy: Keep Last + Reliability Policy: Reliable + Value: /goal_pose + - Class: rviz_default_plugins/PublishPoint + Single click: true + Topic: + Depth: 5 + Durability Policy: Volatile + History Policy: Keep Last + Reliability Policy: Reliable + Value: /clicked_point + Transformation: + Current: + Class: rviz_default_plugins/TF + Value: true + Views: + Current: + Class: rviz_default_plugins/Orbit + Distance: 17.899526596069336 + Enable Stereo Rendering: + Stereo Eye Separation: 0.05999999865889549 + Stereo Focal Distance: 1 + Swap Stereo Eyes: false + Value: false + Focal Point: + X: -0.028435707092285156 + Y: 0.07508468627929688 + Z: 0.047394752502441406 + Focal Shape Fixed Size: true + Focal Shape Size: 0.05000000074505806 + Invert Z Axis: false + Name: Current View + Near Clip Distance: 0.009999999776482582 + Pitch: 0.6574800610542297 + Target Frame: + Value: Orbit (rviz) + Yaw: 2.4183316230773926 + Saved: ~ +Window Geometry: + Displays: + collapsed: false + Height: 982 + Hide Left Dock: false + Hide Right Dock: false + QMainWindow State: 000000ff00000000fd0000000400000000000001f70000033afc020000000afb0000001200530065006c0065006300740069006f006e00000001e10000009b000000b000fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000006e0000033a0000018200fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261fb0000000c00430061006d006500720061000000022f000000b60000000000000000fb0000001800440065006200750067002000430061006d00650072006100000002b8000000f00000000000000000000000010000010f000004c2fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003d000004c20000013200fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004380000003efc0100000002fb0000000800540069006d00650000000000000004380000058100fffffffb0000000800540069006d00650100000000000004500000000000000000000004c90000033a00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000 + Selection: + collapsed: false + Time: + collapsed: false + Tool Properties: + collapsed: false + Views: + collapsed: false + Width: 1740 + X: 1233 + Y: 54 diff --git a/pcd2pgm/src/pcd2pgm.cpp b/pcd2pgm/src/pcd2pgm.cpp new file mode 100644 index 0000000..666190d --- /dev/null +++ b/pcd2pgm/src/pcd2pgm.cpp @@ -0,0 +1,187 @@ +// Copyright 2025 Lihan Chen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "pcd2pgm/pcd2pgm.hpp" + +#include "pcl/common/transforms.h" +#include "pcl/filters/radius_outlier_removal.h" +#include "pcl/io/pcd_io.h" +#include "pcl_conversions/pcl_conversions.h" + +namespace pcd2pgm +{ +Pcd2PgmNode::Pcd2PgmNode(const rclcpp::NodeOptions & options) : Node("pcd2pgm", options) +{ + declareParameters(); + getParameters(); + + rclcpp::QoS map_qos(10); + map_qos.transient_local(); + map_qos.reliable(); + map_qos.keep_last(1); + + pcd_cloud_ = std::make_shared>(); + map_publisher_ = this->create_publisher(map_topic_name_, map_qos); + pcd_publisher_ = this->create_publisher("pcd_cloud", 10); + + if (pcl::io::loadPCDFile(pcd_file_, *pcd_cloud_) == -1) { + RCLCPP_ERROR(get_logger(), "Couldn't read file: %s", pcd_file_.c_str()); + return; + } + + RCLCPP_INFO(get_logger(), "Initial point cloud size: %lu", pcd_cloud_->points.size()); + + applyTransform(); + + passThroughFilter(thre_z_min_, thre_z_max_, flag_pass_through_); + radiusOutlierFilter(cloud_after_pass_through_, thre_radius_, thres_point_count_); + setMapTopicMsg(cloud_after_radius_, map_topic_msg_); + + timer_ = + create_wall_timer(std::chrono::seconds(1), std::bind(&Pcd2PgmNode::publishCallback, this)); +} + +void Pcd2PgmNode::publishCallback() +{ + sensor_msgs::msg::PointCloud2 output; + pcl::toROSMsg(*cloud_after_radius_, output); + output.header.frame_id = "map"; + pcd_publisher_->publish(output); + map_publisher_->publish(map_topic_msg_); +} + +void Pcd2PgmNode::declareParameters() +{ + declare_parameter("pcd_file", ""); + declare_parameter("thre_z_min", 0.5); + declare_parameter("thre_z_max", 2.0); + declare_parameter("flag_pass_through", false); + declare_parameter("thre_radius", 0.5); + declare_parameter("map_resolution", 0.05); + declare_parameter("thres_point_count", 10); + declare_parameter("map_topic_name", "map"); + declare_parameter( + "odom_to_lidar_odom", std::vector{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}); // 新增的参数 +} + +void Pcd2PgmNode::getParameters() +{ + get_parameter("pcd_file", pcd_file_); + get_parameter("thre_z_min", thre_z_min_); + get_parameter("thre_z_max", thre_z_max_); + get_parameter("flag_pass_through", flag_pass_through_); + get_parameter("thre_radius", thre_radius_); + get_parameter("map_resolution", map_resolution_); + get_parameter("thres_point_count", thres_point_count_); + get_parameter("map_topic_name", map_topic_name_); + get_parameter("odom_to_lidar_odom", odom_to_lidar_odom_); // 获取新的参数 +} + +void Pcd2PgmNode::passThroughFilter(double thre_low, double thre_high, bool flag_in) +{ + auto filtered_cloud = std::make_shared>(); + pcl::PassThrough passthrough; + passthrough.setInputCloud(pcd_cloud_); + passthrough.setFilterFieldName("z"); + passthrough.setFilterLimits(thre_low, thre_high); + passthrough.setNegative(flag_in); + passthrough.filter(*filtered_cloud); + + cloud_after_pass_through_ = filtered_cloud; + RCLCPP_INFO( + get_logger(), "After PassThrough filtering: %lu points", + cloud_after_pass_through_->points.size()); +} + +void Pcd2PgmNode::radiusOutlierFilter( + const pcl::PointCloud::Ptr & input_cloud, double radius, int thre_count) +{ + auto filtered_cloud = std::make_shared>(); + pcl::RadiusOutlierRemoval radius_outlier; + radius_outlier.setInputCloud(input_cloud); + radius_outlier.setRadiusSearch(radius); + radius_outlier.setMinNeighborsInRadius(thre_count); + radius_outlier.filter(*filtered_cloud); + + cloud_after_radius_ = filtered_cloud; + RCLCPP_INFO( + get_logger(), "After RadiusOutlier filtering: %lu points", cloud_after_radius_->points.size()); +} + +void Pcd2PgmNode::setMapTopicMsg( + const pcl::PointCloud::Ptr cloud, nav_msgs::msg::OccupancyGrid & msg) +{ + msg.header.stamp = now(); + msg.header.frame_id = "map"; + + msg.info.map_load_time = now(); + msg.info.resolution = map_resolution_; + + double x_min = std::numeric_limits::max(); + double x_max = std::numeric_limits::lowest(); + double y_min = std::numeric_limits::max(); + double y_max = std::numeric_limits::lowest(); + + if (cloud->points.empty()) { + RCLCPP_WARN(get_logger(), "Point cloud is empty!"); + return; + } + + for (const auto & point : cloud->points) { + x_min = std::min(x_min, static_cast(point.x)); + x_max = std::max(x_max, static_cast(point.x)); + y_min = std::min(y_min, static_cast(point.y)); + y_max = std::max(y_max, static_cast(point.y)); + } + + msg.info.origin.position.x = x_min; + msg.info.origin.position.y = y_min; + msg.info.origin.position.z = 0.0; + msg.info.origin.orientation.x = 0.0; + msg.info.origin.orientation.y = 0.0; + msg.info.origin.orientation.z = 0.0; + msg.info.origin.orientation.w = 1.0; + + msg.info.width = std::ceil((x_max - x_min) / map_resolution_); + msg.info.height = std::ceil((y_max - y_min) / map_resolution_); + msg.data.assign(msg.info.width * msg.info.height, 0); + + for (const auto & point : cloud->points) { + int i = std::floor((point.x - x_min) / map_resolution_); + int j = std::floor((point.y - y_min) / map_resolution_); + + if (i >= 0 && i < msg.info.width && j >= 0 && j < msg.info.height) { + msg.data[i + j * msg.info.width] = 100; + } + } + + RCLCPP_INFO(get_logger(), "Map data size: %lu", msg.data.size()); +} + +void Pcd2PgmNode::applyTransform() +{ + Eigen::Affine3f transform = Eigen::Affine3f::Identity(); + + transform.translation() << odom_to_lidar_odom_[0], odom_to_lidar_odom_[1], odom_to_lidar_odom_[2]; + transform.rotate(Eigen::AngleAxisf(odom_to_lidar_odom_[3], Eigen::Vector3f::UnitX())); + transform.rotate(Eigen::AngleAxisf(odom_to_lidar_odom_[4], Eigen::Vector3f::UnitY())); + transform.rotate(Eigen::AngleAxisf(odom_to_lidar_odom_[5], Eigen::Vector3f::UnitZ())); + + pcl::transformPointCloud(*pcd_cloud_, *pcd_cloud_, transform.inverse()); +} + +} // namespace pcd2pgm + +#include "rclcpp_components/register_node_macro.hpp" +RCLCPP_COMPONENTS_REGISTER_NODE(pcd2pgm::Pcd2PgmNode) diff --git a/point_lio_ros2/.gitignore b/point_lio_ros2/.gitignore new file mode 100644 index 0000000..f239d34 --- /dev/null +++ b/point_lio_ros2/.gitignore @@ -0,0 +1,4 @@ +/.idea/ +/cmake-build-debug/ +*.pcd +/Log/pos_log.csv diff --git a/point_lio_ros2/.gitmodules b/point_lio_ros2/.gitmodules new file mode 100644 index 0000000..dd6379e --- /dev/null +++ b/point_lio_ros2/.gitmodules @@ -0,0 +1,8 @@ +[submodule "ikd-Tree"] + path = ikd-Tree + url = https://github.com/hku-mars/ikd-Tree.git + branch = fast_lio +[submodule "include/IKFoM"] + path = include/IKFoM + url = https://github.com/hku-mars/IKFoM.git + branch = toolkit diff --git a/point_lio_ros2/CMakeLists.txt b/point_lio_ros2/CMakeLists.txt new file mode 100644 index 0000000..75e0b30 --- /dev/null +++ b/point_lio_ros2/CMakeLists.txt @@ -0,0 +1,112 @@ +cmake_minimum_required(VERSION 3.5) +project(point_lio) + +# Use C++14 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 14) +endif() +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions" ) + +# Compiler settings for performance and threading +add_definitions(-DROOT_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/\") +add_compile_options(-O3 -pthread -fexceptions) + +# Processor count and definitions +message(STATUS "Current CPU architecture: ${CMAKE_SYSTEM_PROCESSOR}") +if(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)" ) + include(ProcessorCount) + ProcessorCount(N) + message(STATUS "Processor number: ${N}") + if(N GREATER 5) + add_definitions(-DMP_EN) + add_definitions(-DMP_PROC_NUM=4) + message(STATUS "core for MP: 3") + elseif(N GREATER 3) + math(EXPR PROC_NUM "${N} - 2") + add_definitions(-DMP_EN) + add_definitions(-DMP_PROC_NUM="${PROC_NUM}") + message(STATUS "core for MP: ${PROC_NUM}") + else() + add_definitions(-DMP_PROC_NUM=1) + endif() +else() + add_definitions(-DMP_PROC_NUM=1) +endif() + +# Find packages +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(rclpy REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(nav_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(pcl_ros REQUIRED) +find_package(pcl_conversions REQUIRED) +find_package(tf2_ros REQUIRED) +find_package(visualization_msgs REQUIRED) +# find_package(livox_ros_driver2 REQUIRED) + +find_package(Eigen3 REQUIRED) + + +# OpenMP +find_package(OpenMP QUIET) +if(OPENMP_FOUND) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") +endif() + +find_package(PythonLibs REQUIRED) # Consider using Pybind11 for ROS2 +find_path(MATPLOTLIB_CPP_INCLUDE_DIRS "matplotlibcpp.h") + +include_directories( + include + ${EIGEN3_INCLUDE_DIR} + ${PYTHON_INCLUDE_DIRS} +) + +# Declare a ROS2 executable +add_executable(pointlio_mapping src/laserMapping.cpp include/ikd-Tree/ikd_Tree.cpp src/parameters.cpp src/preprocess.cpp src/Estimator.cpp) +ament_target_dependencies(pointlio_mapping + rclcpp + rclpy + geometry_msgs + nav_msgs + sensor_msgs + pcl_ros + pcl_conversions + tf2_ros + visualization_msgs + # livox_ros_driver2 +) +target_link_libraries(pointlio_mapping ${PYTHON_LIBRARIES}) +target_include_directories(pointlio_mapping PRIVATE ${PYTHON_INCLUDE_DIRS}) + +# Install the executable +install(TARGETS + pointlio_mapping + DESTINATION lib/${PROJECT_NAME} +) + +install( + DIRECTORY config launch rviz_cfg + DESTINATION share/${PROJECT_NAME} +) + +# Export dependencies +ament_export_dependencies(rclcpp + rclpy + geometry_msgs + nav_msgs + sensor_msgs + pcl_ros + pcl_conversions + tf2_ros + visualization_msgs + # livox_ros_driver2 + Eigen3 +) + +ament_package() diff --git a/point_lio_ros2/LICENSE b/point_lio_ros2/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/point_lio_ros2/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/point_lio_ros2/Log/guide.md b/point_lio_ros2/Log/guide.md new file mode 100644 index 0000000..883b3d4 --- /dev/null +++ b/point_lio_ros2/Log/guide.md @@ -0,0 +1 @@ +Here saved the debug records which can be drew by the ../log/plot.py. The record function can be found frm the MACRO: DEBUG_FILE_DIR(name) in common_lib.h. diff --git a/point_lio_ros2/Log/imu.txt b/point_lio_ros2/Log/imu.txt new file mode 100644 index 0000000..e69de29 diff --git a/point_lio_ros2/Log/imu_pbp.txt b/point_lio_ros2/Log/imu_pbp.txt new file mode 100644 index 0000000..e69de29 diff --git a/point_lio_ros2/Log/mat_out.txt b/point_lio_ros2/Log/mat_out.txt new file mode 100644 index 0000000..e69de29 diff --git a/point_lio_ros2/Log/plot.py b/point_lio_ros2/Log/plot.py new file mode 100644 index 0000000..b5d1c1a --- /dev/null +++ b/point_lio_ros2/Log/plot.py @@ -0,0 +1,46 @@ +# import matplotlib +# matplotlib.use('Agg') +import numpy as np +import matplotlib.pyplot as plt + +a_out=np.loadtxt('mat_out.txt') +#######for normal####### +fig, axs = plt.subplots(3,2) +lab_out = ['', 'out-x', 'out-y', 'out-z'] +plot_ind = range(7,10) +time=a_out[:,0] +axs[0,0].set_title('Attitude') +axs[1,0].set_title('Translation') +axs[2,0].set_title('Velocity') +axs[0,1].set_title('bg') +axs[1,1].set_title('ba') +axs[2,1].set_title('Gravity') +for i in range(1,4): + for j in range(6): + axs[j%3, j//3].plot(time, a_out[:,i+j*3],'.-', label=lab_out[i]) + for j in range(6): + axs[j%3, j//3].grid() + axs[j%3, j//3].legend() +plt.grid() + #######for normal####### + + +#### Draw IMU data +#fig, axs = plt.subplots(2) +#imu=np.loadtxt('imu_pbp.txt') +#time=imu[:,0] +#axs[0].set_title('Gyroscope') +#axs[1].set_title('Accelerameter') +#lab_1 = ['gyr-x', 'gyr-y', 'gyr-z'] +#lab_2 = ['acc-x', 'acc-y', 'acc-z'] +#for i in range(3): + #if i==1: +# axs[0].plot(time, imu[:,i+1],'.-', label=lab_1[i]) +# axs[1].plot(time, imu[:,i+4],'.-', label=lab_2[i]) +#for i in range(2): + #axs[i].set_xlim(386,389) +# axs[i].grid() +# axs[i].legend() +#plt.grid() + +plt.show() diff --git a/point_lio_ros2/Log/plot_imu.py b/point_lio_ros2/Log/plot_imu.py new file mode 100644 index 0000000..0177273 --- /dev/null +++ b/point_lio_ros2/Log/plot_imu.py @@ -0,0 +1,125 @@ +# import matplotlib +# matplotlib.use('Agg') +import numpy as np +import matplotlib.pyplot as plt + +#### Draw IMU data +fig, axs = plt.subplots(2) +imu=np.loadtxt('imu_pbp.txt') +time=imu[:,0] +axs[0].set_title('Gyroscope') +axs[1].set_title('Accelerameter') +lab_1 = ['gyr-x', 'gyr-y', 'gyr-z'] +lab_2 = ['acc-x', 'acc-y', 'acc-z'] +for i in range(3): + #if i==1: + axs[0].plot(time, imu[:,i+1],'.-', label=lab_1[i]) + axs[1].plot(time, imu[:,i+4],'.-', label=lab_2[i]) +for i in range(2): + #axs[i].set_xlim(386,389) + axs[i].grid() + axs[i].legend() +plt.grid() + +#fig, axs = plt.subplots(5) +#axs[0].set_title('miss') +#axs[1].set_title('miss') +#axs[2].set_title('miss') +#axs[3].set_title('miss') +#axs[4].set_title('miss') +#len_time1 = np.arange(0,1977) +#len_time2 = np.arange(1977, 3954) +#len_time3 = np.arange(3954,5931) +#len_time4 = np.arange(5931,7908) +#len_time5 = np.arange(7908,9885) + #if i==1: +#axs[0].plot(len_time1, time[0:1977],'.-', label='check') +#axs[1].plot(len_time2, time[1977:3954],'.-', label='check') +#axs[2].plot(len_time3, time[3954:5931],'.-', label='check') +#axs[3].plot(len_time4, time[5931:7908],'.-', label='check') +#axs[4].plot(len_time5, time[7908:9885],'.-', label='check') + #axs[i].set_xlim(386,389) +#axs[0].grid() +#axs[0].legend() +#axs[1].grid() +#axs[1].legend() +#axs[2].grid() +#axs[2].legend() +#axs[3].grid() +#axs[3].legend() +#axs[4].grid() +#axs[4].legend() +#plt.grid() + +#fig, axs = plt.subplots(5) +#axs[0].set_title('miss') +#axs[1].set_title('miss') +#axs[2].set_title('miss') +#axs[3].set_title('miss') +#axs[4].set_title('miss') +#len_time1 = np.arange(9885,9885+1977) +#len_time2 = np.arange(9885+1977,9885+3954) +#len_time3 = np.arange(9885+3954,9885+5931) +#len_time4 = np.arange(9885+5931,9885+7908) +#len_time5 = np.arange(9885+7908,9885+9885) + #if i==1: +#axs[0].plot(len_time1, time[9885+0:9885+1977],'.-', label='check') +#axs[1].plot(len_time2, time[9885+1977:9885+3954],'.-', label='check') +#axs[2].plot(len_time3, time[9885+3954:9885+5931],'.-', label='check') +#axs[3].plot(len_time4, time[9885+5931:9885+7908],'.-', label='check') +#axs[4].plot(len_time5, time[9885+7908:9885+9885],'.-', label='check') + #axs[i].set_xlim(386,389) +#axs[0].grid() +#axs[0].legend() +#axs[1].grid() +#axs[1].legend() +#axs[2].grid() +#axs[2].legend() +#axs[3].grid() +#axs[3].legend() +#axs[4].grid() +#axs[4].legend() +#plt.grid() + +# #### Draw time calculation +# plt.figure(3) +# fig = plt.figure() +# font1 = {'family' : 'Times New Roman', +# 'weight' : 'normal', +# 'size' : 12, +# } +# c="red" +# a_out1=np.loadtxt('Log/mat_out_time_indoor1.txt') +# a_out2=np.loadtxt('Log/mat_out_time_indoor2.txt') +# a_out3=np.loadtxt('Log/mat_out_time_outdoor.txt') +# # n = a_out[:,1].size +# # time_mean = a_out[:,1].mean() +# # time_se = a_out[:,1].std() / np.sqrt(n) +# # time_err = a_out[:,1] - time_mean +# # feat_mean = a_out[:,2].mean() +# # feat_err = a_out[:,2] - feat_mean +# # feat_se = a_out[:,2].std() / np.sqrt(n) +# ax1 = fig.add_subplot(111) +# ax1.set_ylabel('Effective Feature Numbers',font1) +# ax1.boxplot(a_out1[:,2], showfliers=False, positions=[0.9]) +# ax1.boxplot(a_out2[:,2], showfliers=False, positions=[1.9]) +# ax1.boxplot(a_out3[:,2], showfliers=False, positions=[2.9]) +# ax1.set_ylim([0, 3000]) + +# ax2 = ax1.twinx() +# ax2.spines['right'].set_color('red') +# ax2.set_ylabel('Compute Time (ms)',font1) +# ax2.yaxis.label.set_color('red') +# ax2.tick_params(axis='y', colors='red') +# ax2.boxplot(a_out1[:,1]*1000, showfliers=False, positions=[1.1],boxprops=dict(color=c),capprops=dict(color=c),whiskerprops=dict(color=c)) +# ax2.boxplot(a_out2[:,1]*1000, showfliers=False, positions=[2.1],boxprops=dict(color=c),capprops=dict(color=c),whiskerprops=dict(color=c)) +# ax2.boxplot(a_out3[:,1]*1000, showfliers=False, positions=[3.1],boxprops=dict(color=c),capprops=dict(color=c),whiskerprops=dict(color=c)) +# ax2.set_xlim([0.5, 3.5]) +# ax2.set_ylim([0, 100]) + +# plt.xticks([1,2,3], ('Outdoor Scene', 'Indoor Scene 1', 'Indoor Scene 2')) +# # # print(time_se) +# # # print(a_out3[:,2]) +# plt.grid() +# plt.savefig("time.pdf", dpi=1200) +plt.show() diff --git a/point_lio_ros2/Log/plot_out.py b/point_lio_ros2/Log/plot_out.py new file mode 100644 index 0000000..8dd80cb --- /dev/null +++ b/point_lio_ros2/Log/plot_out.py @@ -0,0 +1,178 @@ +# import matplotlib +# matplotlib.use('Agg') +import numpy as np +import matplotlib.pyplot as plt + +# a_pre=np.loadtxt('mat_pre.txt') +a_out=np.loadtxt('mat_out.txt') +if((a_out.shape[1] != 19) & (a_out.shape[1] != 20)): + ######for ikfom + fig, axs = plt.subplots(4,2) + #lab_pre = ['', 'pre-x', 'pre-y', 'pre-z'] + lab_out = ['', 'out-x', 'out-y', 'out-z'] + plot_ind = range(7,10) + time=a_out[:,0] + axs[0,0].set_title('Attitude') + axs[1,0].set_title('Translation') + axs[2,0].set_title('Velocity') + axs[3,0].set_title('Angular velocity') + axs[0,1].set_title('Acceleration') + axs[1,1].set_title('Gravity') + axs[2,1].set_title('bg') + axs[3,1].set_title('ba') + for i in range(1,4): + for j in range(8): + #axs[j%4, j//4].plot(time, a_pre[:,i+j*3],'.-', label=lab_pre[i]) + axs[j%4, j//4].plot(time, a_out[:,i+j*3],'.-', label=lab_out[i]) + for j in range(8): + # axs[j].set_xlim(386,389) + axs[j%4, j//4].grid() + axs[j%4, j//4].legend() + plt.grid() + ######for ikfom####### +else: + #######for normal####### + fig, axs = plt.subplots(3,2) + lab_pre = ['', 'pre-x', 'pre-y', 'pre-z'] + lab_out = ['', 'out-x', 'out-y', 'out-z'] + plot_ind = range(7,10) + time=a_out[:,0] + time1 = a_pre[:,0] + axs[0,0].set_title('Attitude') + axs[1,0].set_title('Translation') + axs[2,0].set_title('Velocity') + axs[0,1].set_title('bg') + axs[1,1].set_title('ba') + axs[2,1].set_title('Gravity') + for i in range(1,4): + for j in range(6): + axs[j%3, j/3].plot(time1, a_pre[:,i+j*3],'.-', label=lab_pre[i]) + axs[j%3, j/3].plot(time, a_out[:,i+j*3],'.-', label=lab_out[i]) + for j in range(6): + # axs[j].set_xlim(386,389) + axs[j%3, j//3].grid() + axs[j%3, j//3].legend() + plt.grid() + #######for normal####### + + +#### Draw IMU data +fig, axs = plt.subplots(2) +imu=np.loadtxt('imu_pbp.txt') +time=imu[:,0] +axs[0].set_title('Gyroscope') +axs[1].set_title('Accelerameter') +lab_1 = ['gyr-x', 'gyr-y', 'gyr-z'] +lab_2 = ['acc-x', 'acc-y', 'acc-z'] +for i in range(3): + #if i==1: + axs[0].plot(time, imu[:,i+1],'.-', label=lab_1[i]) + axs[1].plot(time, imu[:,i+4],'.-', label=lab_2[i]) +for i in range(2): + #axs[i].set_xlim(386,389) + axs[i].grid() + axs[i].legend() +plt.grid() + +#fig, axs = plt.subplots(5) +#axs[0].set_title('miss') +#axs[1].set_title('miss') +#axs[2].set_title('miss') +#axs[3].set_title('miss') +#axs[4].set_title('miss') +#len_time1 = np.arange(0,1977) +#len_time2 = np.arange(1977, 3954) +#len_time3 = np.arange(3954,5931) +#len_time4 = np.arange(5931,7908) +#len_time5 = np.arange(7908,9885) + #if i==1: +#axs[0].plot(len_time1, time[0:1977],'.-', label='check') +#axs[1].plot(len_time2, time[1977:3954],'.-', label='check') +#axs[2].plot(len_time3, time[3954:5931],'.-', label='check') +#axs[3].plot(len_time4, time[5931:7908],'.-', label='check') +#axs[4].plot(len_time5, time[7908:9885],'.-', label='check') + #axs[i].set_xlim(386,389) +#axs[0].grid() +#axs[0].legend() +#axs[1].grid() +#axs[1].legend() +#axs[2].grid() +#axs[2].legend() +#axs[3].grid() +#axs[3].legend() +#axs[4].grid() +#axs[4].legend() +#plt.grid() + +#fig, axs = plt.subplots(5) +#axs[0].set_title('miss') +#axs[1].set_title('miss') +#axs[2].set_title('miss') +#axs[3].set_title('miss') +#axs[4].set_title('miss') +#len_time1 = np.arange(9885,9885+1977) +#len_time2 = np.arange(9885+1977,9885+3954) +#len_time3 = np.arange(9885+3954,9885+5931) +#len_time4 = np.arange(9885+5931,9885+7908) +#len_time5 = np.arange(9885+7908,9885+9885) + #if i==1: +#axs[0].plot(len_time1, time[9885+0:9885+1977],'.-', label='check') +#axs[1].plot(len_time2, time[9885+1977:9885+3954],'.-', label='check') +#axs[2].plot(len_time3, time[9885+3954:9885+5931],'.-', label='check') +#axs[3].plot(len_time4, time[9885+5931:9885+7908],'.-', label='check') +#axs[4].plot(len_time5, time[9885+7908:9885+9885],'.-', label='check') + #axs[i].set_xlim(386,389) +#axs[0].grid() +#axs[0].legend() +#axs[1].grid() +#axs[1].legend() +#axs[2].grid() +#axs[2].legend() +#axs[3].grid() +#axs[3].legend() +#axs[4].grid() +#axs[4].legend() +#plt.grid() + +# #### Draw time calculation +# plt.figure(3) +# fig = plt.figure() +# font1 = {'family' : 'Times New Roman', +# 'weight' : 'normal', +# 'size' : 12, +# } +# c="red" +# a_out1=np.loadtxt('Log/mat_out_time_indoor1.txt') +# a_out2=np.loadtxt('Log/mat_out_time_indoor2.txt') +# a_out3=np.loadtxt('Log/mat_out_time_outdoor.txt') +# # n = a_out[:,1].size +# # time_mean = a_out[:,1].mean() +# # time_se = a_out[:,1].std() / np.sqrt(n) +# # time_err = a_out[:,1] - time_mean +# # feat_mean = a_out[:,2].mean() +# # feat_err = a_out[:,2] - feat_mean +# # feat_se = a_out[:,2].std() / np.sqrt(n) +# ax1 = fig.add_subplot(111) +# ax1.set_ylabel('Effective Feature Numbers',font1) +# ax1.boxplot(a_out1[:,2], showfliers=False, positions=[0.9]) +# ax1.boxplot(a_out2[:,2], showfliers=False, positions=[1.9]) +# ax1.boxplot(a_out3[:,2], showfliers=False, positions=[2.9]) +# ax1.set_ylim([0, 3000]) + +# ax2 = ax1.twinx() +# ax2.spines['right'].set_color('red') +# ax2.set_ylabel('Compute Time (ms)',font1) +# ax2.yaxis.label.set_color('red') +# ax2.tick_params(axis='y', colors='red') +# ax2.boxplot(a_out1[:,1]*1000, showfliers=False, positions=[1.1],boxprops=dict(color=c),capprops=dict(color=c),whiskerprops=dict(color=c)) +# ax2.boxplot(a_out2[:,1]*1000, showfliers=False, positions=[2.1],boxprops=dict(color=c),capprops=dict(color=c),whiskerprops=dict(color=c)) +# ax2.boxplot(a_out3[:,1]*1000, showfliers=False, positions=[3.1],boxprops=dict(color=c),capprops=dict(color=c),whiskerprops=dict(color=c)) +# ax2.set_xlim([0.5, 3.5]) +# ax2.set_ylim([0, 100]) + +# plt.xticks([1,2,3], ('Outdoor Scene', 'Indoor Scene 1', 'Indoor Scene 2')) +# # # print(time_se) +# # # print(a_out3[:,2]) +# plt.grid() +# plt.savefig("time.pdf", dpi=1200) +plt.show() diff --git a/point_lio_ros2/Log/pos_log.txt b/point_lio_ros2/Log/pos_log.txt new file mode 100644 index 0000000..e69de29 diff --git a/point_lio_ros2/PCD/temp.txt b/point_lio_ros2/PCD/temp.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/point_lio_ros2/PCD/temp.txt @@ -0,0 +1 @@ + diff --git a/point_lio_ros2/README.md b/point_lio_ros2/README.md new file mode 100644 index 0000000..4e7c83b --- /dev/null +++ b/point_lio_ros2/README.md @@ -0,0 +1,230 @@ +# Point-LIO-ROS2 (with Unitree Unilidar L1/L2 support) +## Point-LIO: Robust High-Bandwidth Lidar-Inertial Odometry + +*(Pay attention to modifying the parameters for IMU in .yaml file, according to the IMU you use.)* + +ROS2 port of [Point-LIO](https://github.com/hku-mars/Point-LIO) with support for the Unitree Unilidar L1/L2 as implemented on the ROS1 [point_lio_unilidar](https://github.com/unitreerobotics/point_lio_unilidar) package. + +## 1. Introduction + +`Point-LIO` is a robust and high-bandwidth lidar inertial odometry (LIO) with the capability to provide accurate, high-frequency odometry and reliable mapping under severe vibrations and aggressive motions. If you need further information about the `Point-LIO` algorithm, you can refer to their official website and paper: +- +- [Point‐LIO: Robust High‐Bandwidth Light Detection and Ranging Inertial Odometry](https://onlinelibrary.wiley.com/doi/epdf/10.1002/aisy.202200459) + +

      + +
      + +The codes of this repo are contributed by: +[Dongjiao He (贺东娇)](https://github.com/Joanna-HE) and [Wei Xu (徐威)](https://github.com/XW-HKU) as well as [Daniel Florea](https://github.com/dfloreaa) for the ROS2 port and Unitree LiDAR support. + +**Important notes:** + +A. Please make sure the IMU and LiDAR are **Synchronized**, that's important. + +B. Please obtain the saturation values of your used IMU (i.e., accelerator and gyroscope), and the units of the accelerator of your used IMU, then modify the .yaml file according to those settings, including values of 'satu_acc', 'satu_gyro', 'acc_norm'. That's improtant. + +C. The warning message "Failed to find match for field 'time'." means the timestamps of each LiDAR points are missed in the rosbag file. That is important because Point-LIO processes at the sampling time of each LiDAR point. + +D. We recommend to set the **extrinsic_est_en** to false if the extrinsic is given. As for the extrinsic initiallization, please refer to our recent work: [**Robust and Online LiDAR-inertial Initialization**](https://github.com/hku-mars/LiDAR_IMU_Init). + +E. If a high odometry output frequency without downsample is required, set `publish_odometry_without_downsample` as true. Then the warning message of tf `"TF_REPEATED_DATA"` will pop up in the terminal window, because the time interval between two publish odometery is too small. The following command could be used to suppress this warning to a smaller frequency: + +in your `catkin_ws/src`, + +```bash +git clone --branch throttle-tf-repeated-data-error git@github.com:BadgerTechnologies/geometry2.git +``` + +Then rebuild, source `setup.bash`, run and then it should be reduced down to once every 10 seconds. If 10 seconds is still too much log output then change the ros::Duration(10.0) to 10000 seconds or whatever you like. + +F. If you want to use Point-LIO without imu, set the `"imu_en"` as false, and provide a predefined value of gavity in `"gravity_init"` as true as possible in the yaml file, and keep the `"use_imu_as_input"` as 0. + +## **2. Videos** +An set of accompaning videos are available on **YouTube**. +### 2.1 Point-LIO original demo +Original video demostration, straight from the original repo +
      + +### 2.2 L1 LiDAR +Official demo by Unitree using their [`point_lio_unilidar`](https://github.com/unitreerobotics/point_lio_unilidar) implementation for the L1 LiDAR: +
      + +
      + +### 2.3 L2 LiDAR +Official demo by Unitree using their [`point_lio_unilidar`](https://github.com/unitreerobotics/point_lio_unilidar) implementation for the L2 LiDAR: +
      + +
      + +## **3. Prerequisites** + +### **3.1 Ubuntu and [ROS](https://www.ros.org/)** +We tested our code on Ubuntu 22.04 with Humble. Other versions may have problems of environments to support the Point-LIO, try to avoid using Point-LIO in those systems. + +Additional ROS package is required: + +- For ROS2 Humble: + ```bash + sudo apt-get install ros-humble-pcl-ros + sudo apt-get install ros-humble-pcl-conversions + sudo apt-get install ros-humble-visualization-msgs + ``` + +### **3.2 Eigen** +Following the official [Eigen installation](eigen.tuxfamily.org/index.php?title=Main_Page), or directly install Eigen by: +```bash +sudo apt-get install libeigen3-dev +``` + +### **3.3 `livox_ros_driver2`** +Follow [livox_ros_driver2 Installation](https://github.com/Livox-SDK/livox_ros_driver2). + +*Remarks:* +- Since the Point-LIO supports Livox serials LiDAR, so the **livox_ros_driver2** must be installed and **sourced** before run any Point-LIO launch file. +- How to source? The easiest way is add the line ``` source $Licox_ros_driver_dir$/install/setup.bash ``` to the end of file ``` ~/.bashrc ```, where ``` $Licox_ros_driver_dir$ ``` is the directory of the livox ros driver workspace (should be the ``` ws_livox ``` directory if you completely followed the livox official document). + +### 3.4 `unilidar_sdk` + +For using lidar `L1`, you should download and build [unilidar_sdk](https://github.com/unitreerobotics/unilidar_sdk) follwing these steps: + +```bash +git clone https://github.com/unitreerobotics/unilidar_sdk.git + +cd unilidar_sdk/unitree_lidar_ros2 + +colcon build +``` + +### 3.5 `unilidar_sdk2` + +For using lidar `L2`, you should download and build [unilidar_sdk2](https://github.com/unitreerobotics/unilidar_sdk2) follwing these steps: + +```bash +git clone https://github.com/unitreerobotics/unilidar_sdk2.git + +cd unilidar_sdk/unitree_lidar_ros2 + +colcon build +``` + +## 4. Build +Clone the repository and colcon build: + +```bash + mkdir -p catkin_point_lio_unilidar/src + cd catkin_point_lio_unilidar/src + git clone https://github.com/dfloreaa/point_lio_ros2.git + cd .. + colcon build --symlink-install + source install/setup.bash +``` +- Remember to source the livox_ros_driver before build (follow 3.3 `livox_ros_driver2`) +- If you want to use a custom build of PCL, add the following line to ~/.bashrc +```export PCL_ROOT={CUSTOM_PCL_PATH}``` + +## 5. Directly run + +### 5.1 For Avia +Connect to your PC to Livox Avia LiDAR by following [Livox-ros-driver installation](https://github.com/Livox-SDK/livox_ros_driver), then +``` + cd ~/$Point_LIO_ROS_DIR$ + source install/setup.bash + ros2 launch point_lio mapping_avia.launch.py + ros2 launch livox_ros_driver msg_HAP_launch.py +``` +- For livox serials, Point-LIO only support the data collected by the ``` msg_HAP_launch.py ``` since only its ``` livox_ros_driver/CustomMsg ``` data structure produces the timestamp of each LiDAR point which is very important for Point-LIO. ``` livox_lidar.launch.py ``` can not produce it right now. +- If you want to change the frame rate, please modify the **publish_freq** parameter in the [msg_HAP_launch.py](https://github.com/Livox-SDK/livox_ros_driver2/blob/master/launch_ROS2/msg_HAP_launch.py) of [Livox-ros-driver](https://github.com/Livox-SDK/livox_ros_driver) before make the livox_ros_driver pakage. + +### 5.2 For Livox serials with external IMU + +mapping_avia.launch theratically supports mid-70, mid-40 or other livox serial LiDAR, but need to setup some parameters befor run: + +Edit ``` config/avia.yaml ``` to set the below parameters: + +1. LiDAR point cloud topic name: ``` lid_topic ``` +2. IMU topic name: ``` imu_topic ``` +3. Translational extrinsic: ``` extrinsic_T ``` +4. Rotational extrinsic: ``` extrinsic_R ``` (only support rotation matrix) +- The extrinsic parameters in Point-LIO is defined as the LiDAR's pose (position and rotation matrix) in IMU body frame (i.e. the IMU is the base frame). They can be found in the official manual. +5. Saturation value of IMU's accelerator and gyroscope: ```satu_acc```, ```satu_gyro``` +6. The norm of IMU's acceleration according to unit of acceleration messages: ``` acc_norm ``` + +### 5.3 For Velodyne or Ouster (Velodyne as an example) + +Step A: Setup before run + +Edit ``` config/velodyne.yaml ``` to set the below parameters: + +1. LiDAR point cloud topic name: ``` lid_topic ``` +2. IMU topic name: ``` imu_topic ``` (both internal and external, 6-aixes or 9-axies are fine) +3. Set the parameter ```timestamp_unit``` based on the unit of **time** (Velodyne) or **t** (Ouster) field in PoindCloud2 rostopic +4. Line number (we tested 16, 32 and 64 line, but not tested 128 or above): ``` scan_line ``` +5. Translational extrinsic: ``` extrinsic_T ``` +6. Rotational extrinsic: ``` extrinsic_R ``` (only support rotation matrix) +- The extrinsic parameters in Point-LIO is defined as the LiDAR's pose (position and rotation matrix) in IMU body frame (i.e. the IMU is the base frame). +7. Saturation value of IMU's accelerator and gyroscope: ```satu_acc```, ```satu_gyro``` +8. The norm of IMU's acceleration according to unit of acceleration messages: ``` acc_norm ``` + +Step B: Run below +``` + cd ~/$Point_LIO_ROS_DIR$ + source install/setup.bash + ros2 launch point_lio mapping_velody16.launch.py +``` + +Step C: Run LiDAR's ros driver or play rosbag. + +### 5.4 For Unitree LiDAR (L1 as an example) + +Step A: Run below +``` + cd ~/catkin_point_lio_unilidar + source install/setup.bash + ros2 launch point_lio mapping_unilidar_l1.py +``` + +Step B: Run LiDAR's ros driver or play rosbag. + +### 5.5 PCD file save + +Set ``` pcd_save_enable ``` in launchfile to ``` 1 ```. All the scans (in global frame) will be accumulated and saved to the file ``` Point-LIO/PCD/scans.pcd ``` after the Point-LIO is terminated. ```pcl_viewer scans.pcd``` can visualize the point clouds. + +*Tips for pcl_viewer:* +- change what to visualize/color by pressing keyboard 1,2,3,4,5 when pcl_viewer is running. +``` + 1 is all random + 2 is X values + 3 is Y values + 4 is Z values + 5 is intensity +``` + +# **6. Examples** + +The example datasets could be downloaded through [onedrive](https://connecthkuhk-my.sharepoint.com/:f:/g/personal/hdj65822_connect_hku_hk/EmRJYy4ZfAlMiIJ786ogCPoBcGQ2BAchuXjE5oJQjrQu0Q?e=igu44W). Pay attention that if you want to test on racing_drone.bag, [0.0, 9.810, 0.0] should be input in 'mapping/gravity_init' in avia.yaml, and set the 'start_in_aggressive_motion' as true in the yaml. Because this bag start from a high speed motion. And for PULSAR.bag, we change the measuring range of the gyroscope of the built-in IMU to 17.5 rad/s. Therefore, when you test on this bag, please change 'satu_gyro' to 17.5 in avia.yaml. + +## **6.1. Example-1: SLAM on datasets with aggressive motions where IMU is saturated** +
      + + +
      + +## **6.2. Example-2: Application on FPV and PULSAR** +
      + + +
      + +PULSAR is a self-rotating UAV actuated by only one motor, [PULSAR](https://github.com/hku-mars/PULSAR) + +## 7. Contact us +If you have any questions about this work, please feel free to contact me via email. diff --git a/point_lio_ros2/config/avia.yaml b/point_lio_ros2/config/avia.yaml new file mode 100644 index 0000000..68a4da5 --- /dev/null +++ b/point_lio_ros2/config/avia.yaml @@ -0,0 +1,59 @@ +/**: + ros__parameters: + common: + lid_topic: "/livox/lidar" + imu_topic: "/livox/imu" + con_frame: false # true: if you need to combine several LiDAR frames into one + con_frame_num: 1 # the number of frames combined + cut_frame: false # true: if you need to cut one LiDAR frame into several subframes + cut_frame_time_interval: 0.1 # should be integral fraction of 1 / LiDAR frequency + time_lag_imu_to_lidar: 0.0 # Time offset between LiDAR and IMU calibrated by other algorithms, e.g., LI-Init (find in Readme) + # the timestamp of IMU is transferred from the current timeline to LiDAR's timeline by subtracting this value + + preprocess: + lidar_type: 1 + scan_line: 6 + timestamp_unit: 1 # the unit of time/t field in the PointCloud2 rostopic: 0-second, 1-milisecond, 2-microsecond, 3-nanosecond. + blind: 1.0 + + mapping: + imu_en: true + start_in_aggressive_motion: false # if true, a preknown gravity should be provided in following gravity_init + extrinsic_est_en: false # for aggressive motion, set this variable false + imu_time_inte: 0.005 # = 1 / frequency of IMU + satu_acc: 3.0 # the saturation value of IMU's acceleration. not related to the units + satu_gyro: 17.5 # the saturation value of IMU's angular velocity. not related to the units (default = 35 rad/s) + acc_norm: 1.0 # 1.0 for g as unit, 9.81 for m/s^2 as unit of the IMU's acceleration + lidar_meas_cov: 0.001 # 0.001; 0.01 + acc_cov_output: 500.0 + gyr_cov_output: 1000.0 + b_acc_cov: 0.0001 + b_gyr_cov: 0.0001 + imu_meas_acc_cov: 0.1 #0.1 # 0.1 + imu_meas_omg_cov: 0.1 #0.01 # 0.1 + gyr_cov_input: 0.01 # for IMU as input model + acc_cov_input: 0.1 # for IMU as input model + plane_thr: 0.1 # 0.05, the threshold for plane criteria, the smaller, the flatter a plane + match_s: 81.0 + fov_degree: 90.0 + det_range: 450.0 + gravity_align: true # true to align the z axis of world frame with the direction of gravity, and the gravity direction should be specified below + gravity: [ 0.0, 0.0, -9.810 ] # [0.0, 9.810, 0.0] # gravity to be aligned + gravity_init: [ 0.0, 0.0, -9.810 ] # [0.0, 9.810, 0.0] # # preknown gravity in the first IMU body frame, use when imu_en is false or start from a non-stationary state + extrinsic_T: [ 0.04165, 0.02326, -0.0284 ] + extrinsic_R: [ 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 ] + + odometry: + publish_odometry_without_downsample: false + + publish: + path_en: true # false: close the path output + scan_publish_en: true # false: close all the point cloud output + scan_bodyframe_pub_en: false # true: output the point cloud scans in IMU-body-frame + + pcd_save: + pcd_save_en: false + interval: -1 # how many LiDAR frames saved in each pcd file; + # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames. \ No newline at end of file diff --git a/point_lio_ros2/config/horizon.yaml b/point_lio_ros2/config/horizon.yaml new file mode 100644 index 0000000..b5320f6 --- /dev/null +++ b/point_lio_ros2/config/horizon.yaml @@ -0,0 +1,59 @@ +/**: + ros__parameters: + common: + lid_topic: "/livox/lidar" + imu_topic: "/livox/imu" + con_frame: false # true: if you need to combine several LiDAR frames into one + con_frame_num: 1 # the number of frames combined + cut_frame: false # true: if you need to cut one LiDAR frame into several subframes + cut_frame_time_interval: 0.1 # should be integral fraction of 1 / LiDAR frequency + time_lag_imu_to_lidar: 0.0 # Time offset between LiDAR and IMU calibrated by other algorithms, e.g., LI-Init (find in Readme), + # the timestamp of IMU is transferred from the current timeline to LiDAR's timeline by subtracting this value + + preprocess: + lidar_type: 1 + scan_line: 6 + timestamp_unit: 1 # the unit of time/t field in the PointCloud2 rostopic: 0-second, 1-milisecond, 2-microsecond, 3-nanosecond. + blind: 4.0 + + mapping: + imu_en: true + start_in_aggressive_motion: false # if true, a preknown gravity should be provided in following gravity_init + extrinsic_est_en: false # for aggressive motion, set this variable false + imu_time_inte: 0.005 # = 1 / frequency of IMU + satu_acc: 3.0 # the saturation value of IMU's acceleration. not related to the units + satu_gyro: 35.0 # the saturation value of IMU's angular velocity. not related to the units + acc_norm: 1.0 # 1.0 for g as unit, 9.81 for m/s^2 as unit of the IMU's acceleration + lidar_meas_cov: 0.01 # 0.001 + acc_cov_output: 500.0 + gyr_cov_output: 1000.0 + b_acc_cov: 0.0001 + b_gyr_cov: 0.0001 + imu_meas_acc_cov: 0.01 #0.1 # 2 + imu_meas_omg_cov: 0.01 #0.1 # 2 + gyr_cov_input: 0.01 # for IMU as input model + acc_cov_input: 0.1 # for IMU as input model + plane_thr: 0.1 # 0.05, the threshold for plane criteria, the smaller, the flatter a plane + match_s: 81.0 + fov_degree: 100.0 + det_range: 260.0 + gravity_align: true # true to align the z axis of world frame with the direction of gravity, and the gravity direction should be specified below + gravity: [ 0.0, 0.0, -9.810 ] # [0.0, 9.810, 0.0] # gravity to be aligned + gravity_init: [ 0.0, 0.0, -9.810 ] # [0.0, 9.810, 0.0] # # preknown gravity in the first IMU body frame, use when imu_en is false or start from a non-stationary state + extrinsic_T: [ 0.05512, 0.02226, -0.0297 ] + extrinsic_R: [ 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 ] + + odometry: + publish_odometry_without_downsample: false + + publish: + path_en: true # false: close the path output + scan_publish_en: true # false: close all the point cloud output + scan_bodyframe_pub_en: false # true: output the point cloud scans in IMU-body-frame + + pcd_save: + pcd_save_en: false + interval: -1 # how many LiDAR frames saved in each pcd file; + # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames. \ No newline at end of file diff --git a/point_lio_ros2/config/mid360.yaml b/point_lio_ros2/config/mid360.yaml new file mode 100644 index 0000000..0e38af0 --- /dev/null +++ b/point_lio_ros2/config/mid360.yaml @@ -0,0 +1,59 @@ +/**: + ros__parameters: + common: + lid_topic: "/livox/lidar" + imu_topic: "/livox/imu" + con_frame: false # true: if you need to combine several LiDAR frames into one + con_frame_num: 1 # the number of frames combined + cut_frame: false # true: if you need to cut one LiDAR frame into several subframes + cut_frame_time_interval: 0.1 # should be integral fraction of 1 / LiDAR frequency + time_lag_imu_to_lidar: 0.0 # Time offset between LiDAR and IMU calibrated by other algorithms, e.g., LI-Init (find in Readme), + # the timestamp of IMU is transferred from the current timeline to LiDAR's timeline by subtracting this value + + preprocess: + lidar_type: 1 # 1 for Livox serials LiDAR, 2 for Velodyne LiDAR, 3 for ouster LiDAR + scan_line: 4 + timestamp_unit: 3 # the unit of time/t field in the PointCloud2 rostopic: 0-second, 1-milisecond, 2-microsecond, 3-nanosecond. + blind: 0.5 + + mapping: + imu_en: true + start_in_aggressive_motion: false # if true, a preknown gravity should be provided in following gravity_init + extrinsic_est_en: false # for aggressive motion, set this variable false + imu_time_inte: 0.005 # = 1 / frequency of IMU + satu_acc: 3.0 # the saturation value of IMU's acceleration. not related to the units + satu_gyro: 35.0 # the saturation value of IMU's angular velocity. not related to the units + acc_norm: 1.0 # 1.0 for g as unit, 9.81 for m/s^2 as unit of the IMU's acceleration + lidar_meas_cov: 0.01 # 0.001 + acc_cov_output: 500.0 + gyr_cov_output: 1000.0 + b_acc_cov: 0.0001 + b_gyr_cov: 0.0001 + imu_meas_acc_cov: 0.01 #0.1 # 2 + imu_meas_omg_cov: 0.01 #0.1 # 2 + gyr_cov_input: 0.01 # for IMU as input model + acc_cov_input: 0.1 # for IMU as input model + plane_thr: 0.1 # 0.05, the threshold for plane criteria, the smaller, the flatter a plane + match_s: 81.0 + fov_degree: 360.0 + det_range: 100.0 + gravity_align: true # true to align the z axis of world frame with the direction of gravity, and the gravity direction should be specified below + gravity: [ 0.0, 0.0, -9.810 ] # [0.0, 9.810, 0.0] # gravity to be aligned + gravity_init: [ 0.0, 0.0, -9.810 ] # [0.0, 9.810, 0.0] # # preknown gravity in the first IMU body frame, use when imu_en is false or start from a non-stationary state + extrinsic_T: [ -0.011, -0.02329, 0.04412 ] + extrinsic_R: [ 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 ] + + odometry: + publish_odometry_without_downsample: false + + publish: + path_en: true # false: close the path output + scan_publish_en: true # false: close all the point cloud output + scan_bodyframe_pub_en: false # true: output the point cloud scans in IMU-body-frame + + pcd_save: + pcd_save_en: false + interval: -1 # how many LiDAR frames saved in each pcd file; + # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames. \ No newline at end of file diff --git a/point_lio_ros2/config/ouster64.yaml b/point_lio_ros2/config/ouster64.yaml new file mode 100644 index 0000000..612d8aa --- /dev/null +++ b/point_lio_ros2/config/ouster64.yaml @@ -0,0 +1,59 @@ +/**: + ros__parameters: + common: + lid_topic: "/os_cloud_node/points" + imu_topic: "/os_cloud_node/imu" + con_frame: false # true: if you need to combine several LiDAR frames into one + con_frame_num: 1 # the number of frames combined + cut_frame: false # true: if you need to cut one LiDAR frame into several subframes + cut_frame_time_interval: 0.1 # should be integral fraction of 1 / LiDAR frequency + time_lag_imu_to_lidar: 0.0 # Time offset between LiDAR and IMU calibrated by other algorithms, e.g., LI-Init (find in Readme) + # the timestamp of IMU is transferred from the current timeline to LiDAR's timeline by subtracting this value + + preprocess: + lidar_type: 3 # 1 for Livox serials LiDAR, 2 for Velodyne LiDAR, 3 for ouster LiDAR + scan_line: 32 # 32 #velodyne 6 avia + timestamp_unit: 3 # the unit of time/t field in the PointCloud2 rostopic: 0-second, 1-milisecond, 2-microsecond, 3-nanosecond. + blind: 0.20 + + mapping: + imu_en: true + start_in_aggressive_motion: false # if true, a preknown gravity should be provided in following gravity_init + extrinsic_est_en: false # for aggressive motion, set this variable false + imu_time_inte: 0.01 # = 1 / frequency of IMU + satu_acc: 30.0 # the saturation value of IMU's acceleration. not related to the units + satu_gyro: 35.0 # the saturation value of IMU's angular velocity. not related to the units + acc_norm: 9.81 # 1.0 for g as unit, 9.81 for m/s^2 as unit of the IMU's acceleration + lidar_meas_cov: 0.1 # 0.01 + acc_cov_output: 500.0 + gyr_cov_output: 1000.0 + b_acc_cov: 0.0001 + b_gyr_cov: 0.0001 + imu_meas_acc_cov: 0.1 #0.1 # 2 + imu_meas_omg_cov: 0.1 #0.1 # 2 + gyr_cov_input: 0.01 # for IMU as input model + acc_cov_input: 0.1 # for IMU as input model + plane_thr: 0.1 # 0.05, the threshold for plane criteria, the smaller, the flatter a plane + match_s: 81.0 + fov_degree: 180.0 + det_range: 150.0 + gravity_align: true # true to align the z axis of world frame with the direction of gravity, and the gravity direction should be specified below + gravity: [ 0.0, 0.0, -9.810 ] # [0.0, 9.810, 0.0] # gravity to be aligned + gravity_init: [ 0.0, 0.0, -9.810 ] # [0.0, 9.810, 0.0] # # preknown gravity in the first IMU body frame, use when imu_en is false or start from a non-stationary state + extrinsic_T: [ 0.0, 0.0, 0.0 ] + extrinsic_R: [ 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 ] + + odometry: + publish_odometry_without_downsample: false + + publish: + path_en: true # false: close the path output + scan_publish_en: true # false: close all the point cloud output + scan_bodyframe_pub_en: false # true: output the point cloud scans in IMU-body-frame + + pcd_save: + pcd_save_en: false + interval: -1 # how many LiDAR frames saved in each pcd file; + # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames. \ No newline at end of file diff --git a/point_lio_ros2/config/unilidar_l1.yaml b/point_lio_ros2/config/unilidar_l1.yaml new file mode 100644 index 0000000..3d868c5 --- /dev/null +++ b/point_lio_ros2/config/unilidar_l1.yaml @@ -0,0 +1,61 @@ +/**: + ros__parameters: + common: + lid_topic: "/unilidar/cloud" + imu_topic: "/unilidar/imu" + con_frame: false # true: if you need to combine several LiDAR frames into one + con_frame_num: 1 # the number of frames combined + cut_frame: false # true: if you need to cut one LiDAR frame into several subframes + cut_frame_time_interval: 0.1 # should be integral fraction of 1 / LiDAR frequency + time_lag_imu_to_lidar: 0.0 # Time offset between LiDAR and IMU calibrated by other algorithms, e.g., LI-Init (find in Readme) + # the timesample of IMU is transferred from the current timeline to LiDAR's timeline by subtracting this value + + preprocess: + lidar_type: 5 + scan_line: 18 + timestamp_unit: 0 # the unit of time/t field in the PointCloud2 rostopic: 0-second, 1-milisecond, 2-microsecond, 3-nanosecond. + blind: 0.5 + + mapping: + imu_en: true + start_in_aggressive_motion: false # if true, a preknown gravity should be provided in following gravity_init + extrinsic_est_en: false # for aggressive motion, set this variable false + imu_time_inte: 0.004 # = 1 / frequency of IMU + satu_acc: 30.0 # the saturation value of IMU's acceleration. not related to the units + satu_gyro: 35.0 # the saturation value of IMU's angular velocity. not related to the units + acc_norm: 9.81 # 1.0 for g as unit, 9.81 for m/s^2 as unit of the IMU's acceleration + lidar_meas_cov: 0.01 # 0.001 + acc_cov_output: 500.0 + gyr_cov_output: 1000.0 + b_acc_cov: 0.0001 + b_gyr_cov: 0.0001 + imu_meas_acc_cov: 0.1 #0.1 # 2 + imu_meas_omg_cov: 0.1 #0.1 # 2 + gyr_cov_input: 0.01 # for IMU as input model + acc_cov_input: 0.1 # for IMU as input model + plane_thr: 0.1 # 0.05, the threshold for plane criteria, the smaller, the flatter a plane + match_s: 81.0 + fov_degree: 180.0 + det_range: 100.0 + gravity_align: true # true to align the z axis of world frame with the direction of gravity, and the gravity direction should be specified below + gravity: [0.0, 0.0, -9.810] # [0.0, 9.810, 0.0] # gravity to be aligned + gravity_init: [0.0, 0.0, -9.810] # [0.0, 9.810, 0.0] # # preknown gravity in the first IMU body frame, use when imu_en is false or start from a non-stationary state + + # transform from imu to lidar + extrinsic_T: [ 0.007698, 0.014655, -0.00667] # ulhk # [-0.5, 1.4, 1.5] # utbm + extrinsic_R: [ 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 ] # ulhk 4 utbm 3 + + odometry: + publish_odometry_without_downsample: true + + publish: + path_en: true # false: close the path output + scan_publish_en: true # false: close all the point cloud output + scan_bodyframe_pub_en: false # true: output the point cloud scans in IMU-body-frame + + pcd_save: + pcd_save_en: true # save map to pcd file + interval: -1 # how many LiDAR frames saved in each pcd file; + # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames. \ No newline at end of file diff --git a/point_lio_ros2/config/unilidar_l2.yaml b/point_lio_ros2/config/unilidar_l2.yaml new file mode 100644 index 0000000..18485bc --- /dev/null +++ b/point_lio_ros2/config/unilidar_l2.yaml @@ -0,0 +1,61 @@ +/**: + ros__parameters: + common: + lid_topic: "/unilidar/cloud" + imu_topic: "/unilidar/imu" + con_frame: false # true: if you need to combine several LiDAR frames into one + con_frame_num: 1 # the number of frames combined + cut_frame: false # true: if you need to cut one LiDAR frame into several subframes + cut_frame_time_interval: 0.2 # should be integral fraction of 1 / LiDAR frequency + time_lag_imu_to_lidar: 0.0 # Time offset between LiDAR and IMU calibrated by other algorithms, e.g., LI-Init (find in Readme) + # the timesample of IMU is transferred from the current timeline to LiDAR's timeline by subtracting this value + + preprocess: + lidar_type: 5 + scan_line: 18 + timestamp_unit: 0 # the unit of time/t field in the PointCloud2 rostopic: 0-second, 1-milisecond, 2-microsecond, 3-nanosecond. + blind: 1.0 + + mapping: + imu_en: true + start_in_aggressive_motion: false # if true, a preknown gravity should be provided in following gravity_init + extrinsic_est_en: false # for aggressive motion, set this variable false + imu_time_inte: 0.005 # = 1 / frequency of IMU + satu_acc: 30.0 # the saturation value of IMU's acceleration. not related to the units + satu_gyro: 35.0 # the saturation value of IMU's angular velocity. not related to the units + acc_norm: 9.81 # 1.0 for g as unit, 9.81 for m/s^2 as unit of the IMU's acceleration + lidar_meas_cov: 0.05 + acc_cov_output: 500.0 + gyr_cov_output: 1000.0 + b_acc_cov: 0.0001 + b_gyr_cov: 0.0001 + imu_meas_acc_cov: 0.2 + imu_meas_omg_cov: 0.2 + gyr_cov_input: 0.05 + acc_cov_input: 0.2 + plane_thr: 0.2 # 0.05, the threshold for plane criteria, the smaller, the flatter a plane + match_s: 50.0 + fov_degree: 180.0 + det_range: 20.0 + gravity_align: true # true to align the z axis of world frame with the direction of gravity, and the gravity direction should be specified below + gravity: [0.0, 0.0, -9.810] # [0.0, 9.810, 0.0] # gravity to be aligned + gravity_init: [0.0, 0.0, -9.810] # [0.0, 9.810, 0.0] # # preknown gravity in the first IMU body frame, use when imu_en is false or start from a non-stationary state + + # transform from imu to lidar + extrinsic_T: [ 0.007698, 0.014655, -0.00667] # ulhk # [-0.5, 1.4, 1.5] # utbm + extrinsic_R: [ 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 ] # ulhk 4 utbm 3 + + odometry: + publish_odometry_without_downsample: false + + publish: + path_en: true # false: close the path output + scan_publish_en: true # false: close all the point cloud output + scan_bodyframe_pub_en: false # true: output the point cloud scans in IMU-body-frame + + pcd_save: + pcd_save_en: true # save map to pcd file + interval: -1 # how many LiDAR frames saved in each pcd file; + # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames. diff --git a/point_lio_ros2/config/velody16.yaml b/point_lio_ros2/config/velody16.yaml new file mode 100644 index 0000000..50ed7f3 --- /dev/null +++ b/point_lio_ros2/config/velody16.yaml @@ -0,0 +1,65 @@ +/**: + ros__parameters: + common: + lid_topic: "/velodyne_points" + imu_topic: "/imu/data" + con_frame: false # true: if you need to combine several LiDAR frames into one + con_frame_num: 1 # the number of frames combined + cut_frame: false # true: if you need to cut one LiDAR frame into several subframes + cut_frame_time_interval: 0.1 # should be integral fraction of 1 / LiDAR frequency + time_lag_imu_to_lidar: 0.0 # Time offset between LiDAR and IMU calibrated by other algorithms, e.g., LI-Init (find in Readme) + # the timestamp of IMU is transferred from the current timeline to LiDAR's timeline by subtracting this value + + preprocess: + lidar_type: 2 # 1 for Livox serials LiDAR, 2 for Velodyne LiDAR, 3 for ouster LiDAR + scan_line: 32 + timestamp_unit: 2 # the unit of time/t field in the PointCloud2 rostopic: 0-second, 1-milisecond, 2-microsecond, 3-nanosecond. + blind: 2.0 + + mapping: + imu_en: true + start_in_aggressive_motion: false # if true, a preknown gravity should be provided in following gravity_init + extrinsic_est_en: false # for aggressive motion, set this variable false + imu_time_inte: 0.01 # = 1 / frequency of IMU + satu_acc: 30.0 # the saturation value of IMU's acceleration. not related to the units + satu_gyro: 35.0 # the saturation value of IMU's angular velocity. not related to the units + acc_norm: 9.81 # 1.0 for g as unit, 9.81 for m/s^2 as unit of the IMU's acceleration + lidar_meas_cov: 0.01 # 0.001 + acc_cov_output: 500.0 + gyr_cov_output: 1000.0 + b_acc_cov: 0.0001 + b_gyr_cov: 0.0001 + imu_meas_acc_cov: 0.1 #0.1 # 2 + imu_meas_omg_cov: 0.1 #0.1 # 2 + gyr_cov_input: 0.01 # for IMU as input model + acc_cov_input: 0.1 # for IMU as input model + plane_thr: 0.1 # 0.05, the threshold for plane criteria, the smaller, the flatter a plane + match_s: 81.0 + fov_degree: 180.0 + det_range: 100.0 + gravity_align: true # true to align the z axis of world frame with the direction of gravity, and the gravity direction should be specified below + gravity: [ 0.0, 0.0, -9.810 ] # [0.0, 9.810, 0.0] # gravity to be aligned + gravity_init: [ 0.0, 0.0, -9.810 ] # [0.0, 9.810, 0.0] # # preknown gravity in the first IMU body frame, use when imu_en is false or start from a non-stationary state + extrinsic_T: [ 0.0, 0.0, 0.28 ] # ulhk # [-0.5, 1.4, 1.5] # utbm + # extrinsic_R: [ 0, 1, 0, + # -1, 0, 0, + # 0, 0, 1 ] # ulhk 5 6 + # extrinsic_R: [ 0, -1, 0, + # 1, 0, 0, + # 0, 0, 1 ] # utbm 1, 2 + extrinsic_R: [ 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 ] # ulhk 4 utbm 3 + + odometry: + publish_odometry_without_downsample: false + + publish: + path_en: true # false: close the path output + scan_publish_en: true # false: close all the point cloud output + scan_bodyframe_pub_en: false # true: output the point cloud scans in IMU-body-frame + + pcd_save: + pcd_save_en: false + interval: -1 # how many LiDAR frames saved in each pcd file; + # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames. \ No newline at end of file diff --git a/point_lio_ros2/include/FOV_Checker/FOV_Checker.cpp b/point_lio_ros2/include/FOV_Checker/FOV_Checker.cpp new file mode 100644 index 0000000..69032bf --- /dev/null +++ b/point_lio_ros2/include/FOV_Checker/FOV_Checker.cpp @@ -0,0 +1,472 @@ +#include "FOV_Checker.h" + +FOV_Checker::FOV_Checker(){ + // fp = fopen("/home/ecstasy/catkin_ws/fov_data.csv","w"); + // fprintf(fp,"cur_pose_x,cur_pose_y,cur_pose_z,axis_x,axis_y,axis_z,theta,depth\n"); + // fclose(fp); +} + +FOV_Checker::~FOV_Checker(){ + +} + +void FOV_Checker::Set_Env(BoxPointType env_param){ + env = env_param; +} + +void FOV_Checker::Set_BoxLength(double box_len_param){ + box_length = box_len_param; +} + +void round_v3d(Eigen::Vector3d &vec, int decimal){ + double tmp; + int t; + for (int i = 0; i < 3; i++){ + t = pow(10,decimal); + tmp = round(vec(i)*t); + vec(i) = tmp/t; + } + return; +} + +void FOV_Checker::check_fov(Eigen::Vector3d cur_pose, Eigen::Vector3d axis, double theta, double depth, vector &boxes){ + round_v3d(cur_pose,4); + round_v3d(axis,3); + axis = axis/axis.norm(); + // fp = fopen("/home/ecstasy/catkin_ws/fov_data.csv","a"); + // fprintf(fp,"%f,%f,%f,%f,%f,%f,%0.4f,%0.1f,",cur_pose(0),cur_pose(1),cur_pose(2),axis(0),axis(1),axis(2),theta,depth); + // fclose(fp); + // cout << "cur_pose: " << cur_pose.transpose() << endl; + // cout<< "axis: " << axis.transpose() << endl; + // cout<< "theta: " << theta << " depth: " << depth << endl; + // cout<< "env: " << env.vertex_min[0] << " " << env.vertex_max[0] << endl; + double axis_angle[6], min_angle, gap, plane_u_min, plane_u_max; + Eigen::Vector3d plane_w, plane_u, plane_v, center_point, start_point, box_p; + Eigen::Vector3d box_p_min, box_p_max; + int i, j, k, index, maxn, start_i, max_uN, max_vN, max_ulogN, u_min, u_max; + bool flag = false, box_found = false; + boxes.clear(); + BoxPointType box; + axis_angle[0] = acos(axis(0)); + axis_angle[1] = acos(axis(1)); + axis_angle[2] = acos(axis(2)); + axis_angle[3] = acos(-axis(0)); + axis_angle[4] = acos(-axis(1)); + axis_angle[5] = acos(-axis(2)); + index = 1; + min_angle = axis_angle[0]; + for (i=1;i<6;i++){ + if (axis_angle[i]=0){ + box_p = box_p_min + plane_u * box_length * (u_min + pow(2,k)) + plane_v * box_length + plane_w * box_length; + box.vertex_min[0] = box_p_min(0); + box.vertex_min[1] = box_p_min(1); + box.vertex_min[2] = box_p_min(2); + box.vertex_max[0] = box_p(0); + box.vertex_max[1] = box_p(1); + box.vertex_max[2] = box_p(2); + if (!check_box(cur_pose, axis, theta, depth, box)) u_min = u_min + pow(2,k); + k = k-1; + } + k = max_ulogN; + u_max = 0; + while (k>=0){ + box_p = box_p_max - plane_u * box_length * (u_max + pow(2,k)) - plane_v * box_length - plane_w * box_length; + box.vertex_min[0] = box_p(0); + box.vertex_min[1] = box_p(1); + box.vertex_min[2] = box_p(2); + box.vertex_max[0] = box_p_max(0); + box.vertex_max[1] = box_p_max(1); + box.vertex_max[2] = box_p_max(2); + if (!check_box(cur_pose, axis, theta, depth, box)) u_max = u_max + pow(2,k); + + k = k-1; + } + u_max = max(0, max_uN - u_max - 1); + box_found = false; + //printf("---- u_min -> u_max: %d->%d\n",u_min,u_max); + for (k = u_min; k <= u_max; k++){ + box_p = box_p_min + plane_u * box_length * k; + box.vertex_min[0] = box_p(0); + box.vertex_min[1] = box_p(1); + box.vertex_min[2] = box_p(2); + box.vertex_max[0] = box_p(0) + box_length; + box.vertex_max[1] = box_p(1) + box_length; + box.vertex_max[2] = box_p(2) + box_length; + if (check_box_in_env(box)){ + //printf("---- FOUND: (%0.3f,%0.3f,%0.3f),(%0.3f,%0.3f,%0.3f)\n",box.vertex_min[0],box.vertex_min[1],box.vertex_min[2],box.vertex_max[0],box.vertex_max[1],box.vertex_max[2]); + box_found = true; + boxes.push_back(box); + } + } + if (box_found) { + flag = true; + } else { + if (j>1) break; + } + } + for (j = 1; j <= max_vN; j++){ + k = max_ulogN; + u_min = 0; + box_p_min = start_point.cwiseProduct(plane_w + plane_v) + plane_u * plane_u_min - plane_v * box_length * j; + box_p_max = plane_u * plane_u_max + start_point.cwiseProduct(plane_w + plane_v) - plane_v * box_length * (j-1) + plane_w * box_length; + //printf("---- DOWNSIDE (%0.3f,%0.3f,%0.3f),(%0.3f,%0.3f,%0.3f)\n",box_p_min[0],box_p_min[1],box_p_min[2],box_p_max[0],box_p_max[1],box_p_max[2]); + + while (k>=0){ + box_p = box_p_min + plane_u * box_length * (u_min + pow(2,k)) + plane_v * box_length + plane_w * box_length; + box.vertex_min[0] = box_p_min(0); + box.vertex_min[1] = box_p_min(1); + box.vertex_min[2] = box_p_min(2); + box.vertex_max[0] = box_p(0); + box.vertex_max[1] = box_p(1); + box.vertex_max[2] = box_p(2); + if (!check_box(cur_pose, axis, theta, depth, box)) u_min = u_min + pow(2,k); + k = k-1; + } + k = max_ulogN; + u_max = 0; + while (k>=0){ + box_p = box_p_max - plane_u * box_length * (u_max + pow(2,k)) - plane_v * box_length - plane_w * box_length; + box.vertex_min[0] = box_p(0); + box.vertex_min[1] = box_p(1); + box.vertex_min[2] = box_p(2); + box.vertex_max[0] = box_p_max(0); + box.vertex_max[1] = box_p_max(1); + box.vertex_max[2] = box_p_max(2); + if (!check_box(cur_pose, axis, theta, depth, box)) { + u_max = u_max + pow(2,k); + // printf("-------- Not Included: (%0.3f,%0.3f,%0.3f),(%0.3f,%0.3f,%0.3f)\n",box.vertex_min[0],box.vertex_min[1],box.vertex_min[2],box.vertex_max[0],box.vertex_max[1],box.vertex_max[2]); + } + + k = k-1; + } + u_max = max(0, max_uN - u_max - 1); + //printf("---- u_min -> u_max: %d->%d\n",u_min,u_max); + box_found = 0; + for (k = u_min; k <= u_max; k++){ + box_p = box_p_min + plane_u * box_length * k; + box.vertex_min[0] = box_p(0); + box.vertex_min[1] = box_p(1); + box.vertex_min[2] = box_p(2); + box.vertex_max[0] = box_p(0) + box_length; + box.vertex_max[1] = box_p(1) + box_length; + box.vertex_max[2] = box_p(2) + box_length; + if (check_box_in_env(box)){ + //printf("---- FOUND: (%0.3f,%0.3f,%0.3f),(%0.3f,%0.3f,%0.3f)\n",box.vertex_min[0],box.vertex_min[1],box.vertex_min[2],box.vertex_max[0],box.vertex_max[1],box.vertex_max[2]); + box_found = 1; + boxes.push_back(box); + } + } + if (box_found) { + flag = true; + } else { + if (j>1) break; + } + } + if (!flag && i>0) break; + } +} + +bool FOV_Checker::check_box(Eigen::Vector3d cur_pose, Eigen::Vector3d axis, double theta, double depth, const BoxPointType box){ + Eigen::Vector3d vertex[8]; + bool s; + vertex[0] = Eigen::Vector3d(box.vertex_min[0], box.vertex_min[1], box.vertex_min[2]); + vertex[1] = Eigen::Vector3d(box.vertex_min[0], box.vertex_min[1], box.vertex_max[2]); + vertex[2] = Eigen::Vector3d(box.vertex_min[0], box.vertex_max[1], box.vertex_min[2]); + vertex[3] = Eigen::Vector3d(box.vertex_min[0], box.vertex_max[1], box.vertex_max[2]); + vertex[4] = Eigen::Vector3d(box.vertex_max[0], box.vertex_min[1], box.vertex_min[2]); + vertex[5] = Eigen::Vector3d(box.vertex_max[0], box.vertex_min[1], box.vertex_max[2]); + vertex[6] = Eigen::Vector3d(box.vertex_max[0], box.vertex_max[1], box.vertex_min[2]); + vertex[7] = Eigen::Vector3d(box.vertex_max[0], box.vertex_max[1], box.vertex_max[2]); + for (int i = 0; i < 8; i++){ + if (check_point(cur_pose, axis, theta, depth, vertex[i])){ + return true; + } + } + Eigen::Vector3d center_point = (vertex[7]+vertex[0])/2.0; + if (check_point(cur_pose, axis, theta, depth, center_point)){ + return true; + } + PlaneType plane[6]; + plane[0].p[0] = vertex[0]; + plane[0].p[1] = vertex[2]; + plane[0].p[2] = vertex[1]; + plane[0].p[3] = vertex[3]; + + plane[1].p[0] = vertex[0]; + plane[1].p[1] = vertex[4]; + plane[1].p[2] = vertex[2]; + plane[1].p[3] = vertex[6]; + + plane[2].p[0] = vertex[0]; + plane[2].p[1] = vertex[4]; + plane[2].p[2] = vertex[1]; + plane[2].p[3] = vertex[5]; + + plane[3].p[0] = vertex[4]; + plane[3].p[1] = vertex[6]; + plane[3].p[2] = vertex[5]; + plane[3].p[3] = vertex[7]; + + plane[4].p[0] = vertex[2]; + plane[4].p[1] = vertex[6]; + plane[4].p[2] = vertex[3]; + plane[4].p[3] = vertex[7]; + + plane[5].p[0] = vertex[1]; + plane[5].p[1] = vertex[5]; + plane[5].p[2] = vertex[3]; + plane[5].p[3] = vertex[7]; + if (check_surface(cur_pose, axis, theta, depth, plane[0]) || check_surface(cur_pose, axis, theta, depth, plane[1]) || check_surface(cur_pose, axis, theta, depth, plane[2]) || check_surface(cur_pose, axis, theta, depth, plane[3]) || check_surface(cur_pose, axis, theta, depth, plane[4]) || check_surface(cur_pose, axis, theta, depth, plane[5])) + s = 1; + else + s = 0; + return s; +} + +bool FOV_Checker::check_surface(Eigen::Vector3d cur_pose, Eigen::Vector3d axis, double theta, double depth, PlaneType plane){ + Eigen::Vector3d plane_p, plane_u, plane_v, plane_w, pc, p, vec; + bool s; + double t, vec_dot_u, vec_dot_v; + plane_p = plane.p[0]; + plane_u = plane.p[1] - plane_p; + plane_v = plane.p[2] - plane_p; + if (check_line(cur_pose, axis, theta, depth, plane_p, plane_u) || check_line(cur_pose, axis, theta, depth, plane_p, plane_v) || check_line(cur_pose, axis, theta, depth, plane_p + plane_u, plane_v) || check_line(cur_pose, axis, theta, depth, plane_p + plane_v, plane_u)){ + s = 1; + return s; + } + pc = plane_p + (plane.p[3]-plane.p[0])/2; + if (check_point(cur_pose, axis, theta, depth, pc)){ + s = 1; + return s; + } + plane_w = plane_u.cross(plane_v); + p = plane_p - cur_pose; + t = (p.dot(plane_w))/(axis.dot(plane_w)); + vec = cur_pose + t * axis - plane_p; + vec_dot_u = vec.dot(plane_u)/plane_u.norm(); + vec_dot_v = vec.dot(plane_v)/plane_v.norm(); + if (t>=-eps_value && t<=depth && vec_dot_u>=-eps_value && vec_dot_u<=plane_u.norm() && vec_dot_v>=-eps_value && vec_dot_v <= plane_v.norm()) + s = 1; + else + s = 0; + return s; +} + +bool FOV_Checker::check_line(Eigen::Vector3d cur_pose, Eigen::Vector3d axis, double theta, double depth, Eigen::Vector3d line_p, Eigen::Vector3d line_vec){ + Eigen::Vector3d p, vec_1, vec_2; + double xl, yl, zl, xn, yn, zn, dot_1, dot_2, ln, pn, pl, l2, p2; + double A, B, C, delta, t1, t2; + bool s; + p = line_p - cur_pose; + xl = line_vec(0); yl = line_vec(1); zl = line_vec(2); + xn = axis(0); yn = axis(1); zn = axis(2); + vec_1 = line_p - cur_pose; + vec_2 = line_p + line_vec - cur_pose; + dot_1 = vec_1.dot(axis); + dot_2 = vec_2.dot(axis); + //printf("xl yl zl: %0.4f, %0.4f, %0.4f\n", xl, yl, zl); + //printf("xn yn zn: %0.4f, %0.4f, %0.4f\n", xn, yn, zn); + //printf("dot_1, dot_2, %0.4f, %0.4f\n",dot_1, dot_2); + if ((dot_1<0 && dot_2<0) || (dot_1>depth && dot_2>depth)){ + s = false; + return s; + } + ln = xl*xn+yl*yn+zl*zn; + pn = p(0)*xn+p(1)*yn+p(2)*zn; + pl = p(0)*xl+p(1)*yl+p(2)*zl; + l2 = xl*xl+yl*yl+zl*zl; + p2 = p.norm()*p.norm(); + //printf("ln: %0.4f\n",ln); + //printf("pn:%0.4f\n",pn); + //printf("pl:%0.4f\n",pl); + //printf("l2:%0.4f\n",l2); + //printf("p2:%0.4f\n",p2); + //printf("theta, cos(theta):%0.4f %0.4f\n",theta,cos(theta)); + A = ln * ln - l2 * cos(theta) * cos(theta); + B = 2 * pn * ln - 2 * cos(theta) * cos(theta)*pl; + C = pn * pn - p2 * cos(theta) * cos(theta); + //printf("A:%0.4f, B:%0.4f, C:%0.4f\n", A,B,C); + if (!(fabs(A)<=eps_value)){ + delta = B*B - 4*A*C; + //printf("delta: %0.4f\n",delta); + if (delta <= eps_value){ + if (A < -eps_value){ + s = false; + return s; + } + else{ + s = true; + return s; + } + } else { + double sqrt_delta = sqrt(delta); + t1 = (-B - sqrt_delta)/(2*A); + t2 = (-B + sqrt_delta)/(2*A); + if (t1>t2) swap(t1,t2); + //printf("t1,t2: %0.4f,%0.4f\n",t1,t2); + // printf("%d\n",check_point(cur_pose, axis, theta, depth, line_p + line_vec * t1)); + if ((t1>=-eps_value && t1<=1+eps_value) && check_point(cur_pose, axis, theta, depth, line_p + line_vec * t1)){ + s = true; + return s; + } + // printf("%d\n",check_point(cur_pose, axis, theta, depth, line_p + line_vec * t2)); + if ((t2>=-eps_value && t2<=1+eps_value) && check_point(cur_pose, axis, theta, depth, line_p + line_vec * t2)){ + s = true; + return s; + } + if (A>-eps_value && (t21-eps_value)){ + s = true; + return s; + } + if (A1-eps_value){ + s = true; + return s; + } + s = false; + } + } else{ + if (!(fabs(B)<=eps_value)){ + s = (B>-eps_value && -C/B<=1+eps_value) || (B=-eps_value); + return s; + } + else { + s = C>=-eps_value; + return s; + } + } + return false; +} + +bool FOV_Checker::check_point(Eigen::Vector3d cur_pose, Eigen::Vector3d axis, double theta, double depth, Eigen::Vector3d point){ + Eigen::Vector3d vec; + double proj_len; + bool s; + vec = point-cur_pose; + if (vec.transpose()*vec < 0.4 * box_length * box_length){ + return true; + } + proj_len = vec.dot(axis); + if (proj_len > depth){ + s = false; + return s; + } + //printf("acos: %0.4f\n",acos(proj_len/vec.norm())); + if (fabs(vec.norm()) <= 1e-4 || acos(proj_len/vec.norm()) <= theta + 0.0175) + s = true; + else + s = false; + return s; +} + +bool FOV_Checker::check_box_in_env(BoxPointType box){ + if (box.vertex_min[0] >= env.vertex_min[0]-eps_value && box.vertex_min[1] >= env.vertex_min[1]-eps_value && box.vertex_min[2] >= env.vertex_min[2]-eps_value && box.vertex_max[0]<= env.vertex_max[0]+eps_value && box.vertex_max[1]<= env.vertex_max[1]+eps_value && box.vertex_max[2]<= env.vertex_max[2]+eps_value){ + return true; + } else { + return false; + } +} + diff --git a/point_lio_ros2/include/FOV_Checker/FOV_Checker.h b/point_lio_ros2/include/FOV_Checker/FOV_Checker.h new file mode 100644 index 0000000..e7db390 --- /dev/null +++ b/point_lio_ros2/include/FOV_Checker/FOV_Checker.h @@ -0,0 +1,33 @@ +// Include Files +#pragma once +#include +#include +#include "ikd-Tree/ikd_Tree.h" +#include +#include + +#define eps_value 1e-6 + +struct PlaneType{ + Eigen::Vector3d p[4]; +}; + +class FOV_Checker{ +public: + FOV_Checker(); + ~FOV_Checker(); + void Set_Env(BoxPointType env_param); + void Set_BoxLength(double box_len_param); + void check_fov(Eigen::Vector3d cur_pose, Eigen::Vector3d axis, double theta, double depth, vector &boxes); + bool check_box(Eigen::Vector3d cur_pose, Eigen::Vector3d axis, double theta, double depth, const BoxPointType box); + bool check_line(Eigen::Vector3d cur_pose, Eigen::Vector3d axis, double theta, double depth, Eigen::Vector3d line_p, Eigen::Vector3d line_vec); + bool check_surface(Eigen::Vector3d cur_pose, Eigen::Vector3d axis, double theta, double depth, PlaneType plane); + bool check_point(Eigen::Vector3d cur_pose, Eigen::Vector3d axis, double theta, double depth, Eigen::Vector3d point); + bool check_box_in_env(BoxPointType box); +private: + BoxPointType env; + double box_length; + FILE *fp; + +}; + diff --git a/point_lio_ros2/include/IKFoM/.gitignore b/point_lio_ros2/include/IKFoM/.gitignore new file mode 100644 index 0000000..259148f --- /dev/null +++ b/point_lio_ros2/include/IKFoM/.gitignore @@ -0,0 +1,32 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app diff --git a/point_lio_ros2/include/IKFoM/IKFoM_toolkit/esekfom/esekfom.hpp b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/esekfom/esekfom.hpp new file mode 100644 index 0000000..742e117 --- /dev/null +++ b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/esekfom/esekfom.hpp @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Author: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ESEKFOM_EKF_HPP +#define ESEKFOM_EKF_HPP + + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../mtk/types/vect.hpp" +#include "../mtk/types/SOn.hpp" +#include "../mtk/types/S2.hpp" +#include "../mtk/types/SEn.hpp" +#include "../mtk/startIdx.hpp" +#include "../mtk/build_manifold.hpp" +#include "util.hpp" + +namespace esekfom { + +using namespace Eigen; + +template +struct dyn_share_modified +{ + bool valid; + bool converge; + T M_Noise; + Eigen::Matrix z; + Eigen::Matrix h_x; + Eigen::Matrix z_IMU; + Eigen::Matrix R_IMU; + bool satu_check[6]; +}; + +template +class esekf{ + + typedef esekf self; + enum{ + n = state::DOF, m = state::DIM, l = measurement::DOF + }; + +public: + + typedef typename state::scalar scalar_type; + typedef Matrix cov; + typedef Matrix cov_; + typedef SparseMatrix spMt; + typedef Matrix vectorized_state; + typedef Matrix flatted_state; + typedef flatted_state processModel(state &, const input &); + typedef Eigen::Matrix processMatrix1(state &, const input &); + typedef Eigen::Matrix processMatrix2(state &, const input &); + typedef Eigen::Matrix processnoisecovariance; + + typedef void measurementModel_dyn_share_modified(state &, dyn_share_modified &); + typedef Eigen::Matrix measurementMatrix1(state &); + typedef Eigen::Matrix measurementMatrix1_dyn(state &); + typedef Eigen::Matrix measurementMatrix2(state &); + typedef Eigen::Matrix measurementMatrix2_dyn(state &); + typedef Eigen::Matrix measurementnoisecovariance; + typedef Eigen::Matrix measurementnoisecovariance_dyn; + + esekf(const state &x = state(), + const cov &P = cov::Identity()): x_(x), P_(P){}; + + void init_dyn_share_modified(processModel f_in, processMatrix1 f_x_in, measurementModel_dyn_share_modified h_dyn_share_in) + { + f = f_in; + f_x = f_x_in; + // f_w = f_w_in; + h_dyn_share_modified_1 = h_dyn_share_in; + maximum_iter = 1; + x_.build_S2_state(); + x_.build_SO3_state(); + x_.build_vect_state(); + x_.build_SEN_state(); + } + + void init_dyn_share_modified_2h(processModel f_in, processMatrix1 f_x_in, measurementModel_dyn_share_modified h_dyn_share_in1, measurementModel_dyn_share_modified h_dyn_share_in2) + { + f = f_in; + f_x = f_x_in; + // f_w = f_w_in; + h_dyn_share_modified_1 = h_dyn_share_in1; + h_dyn_share_modified_2 = h_dyn_share_in2; + maximum_iter = 1; + x_.build_S2_state(); + x_.build_SO3_state(); + x_.build_vect_state(); + x_.build_SEN_state(); + } + + // iterated error state EKF propogation + void predict(double &dt, processnoisecovariance &Q, const input &i_in, bool predict_state, bool prop_cov){ + if (predict_state) + { + flatted_state f_ = f(x_, i_in); + x_.oplus(f_, dt); + } + + if (prop_cov) + { + flatted_state f_ = f(x_, i_in); + // state x_before = x_; + + cov_ f_x_ = f_x(x_, i_in); + cov f_x_final; + F_x1 = cov::Identity(); + for (std::vector, int> >::iterator it = x_.vect_state.begin(); it != x_.vect_state.end(); it++) { + int idx = (*it).first.first; + int dim = (*it).first.second; + int dof = (*it).second; + for(int i = 0; i < n; i++){ + for(int j=0; j res_temp_SO3; + MTK::vect<3, scalar_type> seg_SO3; + for (std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + int idx = (*it).first; + int dim = (*it).second; + for(int i = 0; i < 3; i++){ + seg_SO3(i) = -1 * f_(dim + i) * dt; + } + MTK::SO3 res; + res.w() = MTK::exp(res.vec(), seg_SO3, scalar_type(1/2)); + F_x1.template block<3, 3>(idx, idx) = res.normalized().toRotationMatrix(); + res_temp_SO3 = MTK::A_matrix(seg_SO3); + for(int i = 0; i < n; i++){ + f_x_final. template block<3, 1>(idx, i) = res_temp_SO3 * (f_x_. template block<3, 1>(dim, i)); + } + } + + F_x1 += f_x_final * dt; + P_ = F_x1 * P_ * (F_x1).transpose() + Q * (dt * dt); + } + } + + bool update_iterated_dyn_share_modified() { + dyn_share_modified dyn_share; + state x_propagated = x_; + int dof_Measurement; + double m_noise; + for(int i=0; i z = dyn_share.z; + // Matrix R = dyn_share.R; + Matrix h_x = dyn_share.h_x; + // Matrix h_v = dyn_share.h_v; + dof_Measurement = h_x.rows(); + m_noise = dyn_share.M_Noise; + // dof_Measurement_noise = dyn_share.R.rows(); + // vectorized_state dx, dx_new; + // x_.boxminus(dx, x_propagated); + // dx_new = dx; + // P_ = P_propagated; + + Matrix PHT; + Matrix HPHT; + Matrix K_; + // if(n > dof_Measurement) + { + PHT = P_. template block(0, 0) * h_x.transpose(); + HPHT = h_x * PHT.topRows(12); + for (int m = 0; m < dof_Measurement; m++) + { + HPHT(m, m) += m_noise; + } + K_= PHT*HPHT.inverse(); + } + Matrix dx_ = K_ * z; // - h) + (K_x - Matrix::Identity()) * dx_new; + // state x_before = x_; + + x_.boxplus(dx_); + dyn_share.converge = true; + + // L_ = P_; + // Matrix res_temp_SO3; + // MTK::vect<3, scalar_type> seg_SO3; + // for(typename std::vector >::iterator it = x_.SO3_state.begin(); it != x_.SO3_state.end(); it++) { + // int idx = (*it).first; + // for(int i = 0; i < 3; i++){ + // seg_SO3(i) = dx_(i + idx); + // } + // res_temp_SO3 = A_matrix(seg_SO3).transpose(); + // for(int i = 0; i < n; i++){ + // L_. template block<3, 1>(idx, i) = res_temp_SO3 * (P_. template block<3, 1>(idx, i)); + // } + // { + // for(int i = 0; i < dof_Measurement; i++){ + // K_. template block<3, 1>(idx, i) = res_temp_SO3 * (K_. template block<3, 1>(idx, i)); + // } + // } + // for(int i = 0; i < n; i++){ + // L_. template block<1, 3>(i, idx) = (L_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + // // P_. template block<1, 3>(i, idx) = (P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + // } + // for(int i = 0; i < n; i++){ + // P_. template block<1, 3>(i, idx) = (P_. template block<1, 3>(i, idx)) * res_temp_SO3.transpose(); + // } + // } + // Matrix res_temp_S2; + // MTK::vect<2, scalar_type> seg_S2; + // for(typename std::vector >::iterator it = x_.S2_state.begin(); it != x_.S2_state.end(); it++) { + // int idx = (*it).first; + + // for(int i = 0; i < 2; i++){ + // seg_S2(i) = dx_(i + idx); + // } + + // Eigen::Matrix Nx; + // Eigen::Matrix Mx; + // x_.S2_Nx_yy(Nx, idx); + // x_propagated.S2_Mx(Mx, seg_S2, idx); + // res_temp_S2 = Nx * Mx; + + // for(int i = 0; i < n; i++){ + // L_. template block<2, 1>(idx, i) = res_temp_S2 * (P_. template block<2, 1>(idx, i)); + // } + + // { + // for(int i = 0; i < dof_Measurement; i++){ + // K_. template block<2, 1>(idx, i) = res_temp_S2 * (K_. template block<2, 1>(idx, i)); + // } + // } + // for(int i = 0; i < n; i++){ + // L_. template block<1, 2>(i, idx) = (L_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + // } + // for(int i = 0; i < n; i++){ + // P_. template block<1, 2>(i, idx) = (P_. template block<1, 2>(i, idx)) * res_temp_S2.transpose(); + // } + // } + // if(n > dof_Measurement) + { + P_ = P_ - K_*h_x*P_. template block<12, n>(0, 0); + } + } + return true; + } + + void update_iterated_dyn_share_IMU() { + + dyn_share_modified dyn_share; + for(int i=0; i z = dyn_share.z_IMU; + + Matrix PHT; + Matrix HP; + Matrix HPHT; + PHT.setZero(); + HP.setZero(); + HPHT.setZero(); + for (int l_ = 0; l_ < 6; l_++) + { + if (!dyn_share.satu_check[l_]) + { + PHT.col(l_) = P_.col(15+l_) + P_.col(24+l_); + HP.row(l_) = P_.row(15+l_) + P_.row(24+l_); + } + } + for (int l_ = 0; l_ < 6; l_++) + { + if (!dyn_share.satu_check[l_]) + { + HPHT.col(l_) = HP.col(15+l_) + HP.col(24+l_); + } + HPHT(l_, l_) += dyn_share.R_IMU(l_); //, l); + } + Eigen::Matrix K = PHT * HPHT.inverse(); + + Matrix dx_ = K * z; + + P_ -= K * HP; + x_.boxplus(dx_); + } + return; + } + + void change_x(state &input_state) + { + x_ = input_state; + + if((!x_.vect_state.size())&&(!x_.SO3_state.size())&&(!x_.S2_state.size())&&(!x_.SEN_state.size())) + { + x_.build_S2_state(); + x_.build_SO3_state(); + x_.build_vect_state(); + x_.build_SEN_state(); + } + } + + void change_P(cov &input_cov) + { + P_ = input_cov; + } + + const state& get_x() const { + return x_; + } + const cov& get_P() const { + return P_; + } + state x_; +private: + measurement m_; + cov P_; + spMt l_; + spMt f_x_1; + spMt f_x_2; + cov F_x1 = cov::Identity(); + cov F_x2 = cov::Identity(); + cov L_ = cov::Identity(); + + processModel *f; + processMatrix1 *f_x; + processMatrix2 *f_w; + + measurementMatrix1 *h_x; + measurementMatrix2 *h_v; + + measurementMatrix1_dyn *h_x_dyn; + measurementMatrix2_dyn *h_v_dyn; + + measurementModel_dyn_share_modified *h_dyn_share_modified_1; + + measurementModel_dyn_share_modified *h_dyn_share_modified_2; + + int maximum_iter = 0; + scalar_type limit[n]; + +public: + EIGEN_MAKE_ALIGNED_OPERATOR_NEW +}; + +} // namespace esekfom + +#endif // ESEKFOM_EKF_HPP diff --git a/point_lio_ros2/include/IKFoM/IKFoM_toolkit/esekfom/util.hpp b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/esekfom/util.hpp new file mode 100644 index 0000000..ab39fc4 --- /dev/null +++ b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/esekfom/util.hpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Author: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MEKFOM_UTIL_HPP__ +#define __MEKFOM_UTIL_HPP__ + +#include +#include "../mtk/src/mtkmath.hpp" +namespace esekfom { + +template +class is_same { +public: + operator bool() { + return false; + } +}; +template +class is_same { +public: + operator bool() { + return true; + } +}; + +template +class is_double { +public: + operator bool() { + return false; + } +}; + +template<> +class is_double { +public: + operator bool() { + return true; + } +}; + +template +static T +id(const T &x) +{ + return x; +} + +} // namespace esekfom + +#endif // __MEKFOM_UTIL_HPP__ diff --git a/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/build_manifold.hpp b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/build_manifold.hpp new file mode 100644 index 0000000..115ec7e --- /dev/null +++ b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/build_manifold.hpp @@ -0,0 +1,248 @@ +// This is an advanced implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/build_manifold.hpp + * @brief Macro to automatically construct compound manifolds. + * + */ +#ifndef MTK_AUTOCONSTRUCT_HPP_ +#define MTK_AUTOCONSTRUCT_HPP_ + +#include + +#include +#include +#include + +#include "src/SubManifold.hpp" +#include "startIdx.hpp" + +#ifndef PARSED_BY_DOXYGEN +//////// internals ////// + +#define MTK_APPLY_MACRO_ON_TUPLE(r, macro, tuple) macro tuple + +#define MTK_TRANSFORM_COMMA(macro, entries) BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM_S(1, MTK_APPLY_MACRO_ON_TUPLE, macro, entries)) + +#define MTK_TRANSFORM(macro, entries) BOOST_PP_SEQ_FOR_EACH_R(1, MTK_APPLY_MACRO_ON_TUPLE, macro, entries) + +#define MTK_CONSTRUCTOR_ARG( type, id) const type& id = type() +#define MTK_CONSTRUCTOR_COPY( type, id) id(id) +#define MTK_BOXPLUS( type, id) id.boxplus(MTK::subvector(__vec, &self::id), __scale); +#define MTK_OPLUS( type, id) id.oplus(MTK::subvector_(__vec, &self::id), __scale); +#define MTK_BOXMINUS( type, id) id.boxminus(MTK::subvector(__res, &self::id), __oth.id); +#define MTK_HAT( type, id) if(id.IDX == idx){id.hat(vec, res);} +#define MTK_JACOB_RIGHT_INV( type, id) if(id.IDX == idx){id.Jacob_right_inv(vec, res);} +#define MTK_JACOB_RIGHT( type, id) if(id.IDX == idx){id.Jacob_right(vec, res);} +#define MTK_S2_hat( type, id) if(id.IDX == idx){id.S2_hat(res);} +#define MTK_S2_Nx_yy( type, id) if(id.IDX == idx){id.S2_Nx_yy(res);} +#define MTK_S2_Mx( type, id) if(id.IDX == idx){id.S2_Mx(res, dx);} +#define MTK_OSTREAM( type, id) << __var.id << " " +#define MTK_ISTREAM( type, id) >> __var.id +#define MTK_S2_state( type, id) if(id.TYP == 1){S2_state.push_back(std::make_pair(id.IDX, id.DIM));} +#define MTK_SO3_state( type, id) if(id.TYP == 2){(SO3_state).push_back(std::make_pair(id.IDX, id.DIM));} +#define MTK_vect_state( type, id) if(id.TYP == 0){(vect_state).push_back(std::make_pair(std::make_pair(id.IDX, id.DIM), type::DOF));} +#define MTK_SEN_state( type, id) if(id.TYP == 4){(SEN_state).push_back(std::make_pair(std::make_pair(id.IDX, id.DIM), type::DOF));} + +#define MTK_SUBVARLIST(seq, S2state, SO3state, SENstate) \ +BOOST_PP_FOR_1( \ + ( \ + BOOST_PP_SEQ_SIZE(seq), \ + BOOST_PP_SEQ_HEAD(seq), \ + BOOST_PP_SEQ_TAIL(seq) (~), \ + 0,\ + 0,\ + S2state,\ + SO3state,\ + SENstate ),\ + MTK_ENTRIES_TEST, MTK_ENTRIES_NEXT, MTK_ENTRIES_OUTPUT) + +#define MTK_PUT_TYPE(type, id, dof, dim, S2state, SO3state, SENstate) \ + MTK::SubManifold id; +#define MTK_PUT_TYPE_AND_ENUM(type, id, dof, dim, S2state, SO3state, SENstate) \ + MTK_PUT_TYPE(type, id, dof, dim, S2state, SO3state, SENstate) \ + enum {DOF = type::DOF + dof}; \ + enum {DIM = type::DIM+dim}; \ + typedef type::scalar scalar; + +#define MTK_ENTRIES_OUTPUT(r, state) MTK_ENTRIES_OUTPUT_I state +#define MTK_ENTRIES_OUTPUT_I(s, head, seq, dof, dim, S2state, SO3state, SENstate) \ + MTK_APPLY_MACRO_ON_TUPLE(~, \ + BOOST_PP_IF(BOOST_PP_DEC(s), MTK_PUT_TYPE, MTK_PUT_TYPE_AND_ENUM), \ + ( BOOST_PP_TUPLE_REM_2 head, dof, dim, S2state, SO3state, SENstate)) + +#define MTK_ENTRIES_TEST(r, state) MTK_TUPLE_ELEM_4_0 state + +//! this used to be BOOST_PP_TUPLE_ELEM_4_0: +#define MTK_TUPLE_ELEM_4_0(a,b,c,d,e,f, g, h) a + +#define MTK_ENTRIES_NEXT(r, state) MTK_ENTRIES_NEXT_I state +#define MTK_ENTRIES_NEXT_I(len, head, seq, dof, dim, S2state, SO3state, SENstate) ( \ + BOOST_PP_DEC(len), \ + BOOST_PP_SEQ_HEAD(seq), \ + BOOST_PP_SEQ_TAIL(seq), \ + dof + BOOST_PP_TUPLE_ELEM_2_0 head::DOF,\ + dim + BOOST_PP_TUPLE_ELEM_2_0 head::DIM,\ + S2state,\ + SO3state,\ + SENstate ) + +#endif /* not PARSED_BY_DOXYGEN */ + + +/** + * Construct a manifold. + * @param name is the class-name of the manifold, + * @param entries is the list of sub manifolds + * + * Entries must be given in a list like this: + * @code + * typedef MTK::trafo > Pose; + * typedef MTK::vect Vec3; + * MTK_BUILD_MANIFOLD(imu_state, + * ((Pose, pose)) + * ((Vec3, vel)) + * ((Vec3, acc_bias)) + * ) + * @endcode + * Whitespace is optional, but the double parentheses are necessary. + * Construction is done entirely in preprocessor. + * After construction @a name is also a manifold. Its members can be + * accessed by names given in @a entries. + * + * @note Variable types are not allowed to have commas, thus types like + * @c vect need to be typedef'ed ahead. + */ +#define MTK_BUILD_MANIFOLD(name, entries) \ +struct name { \ + typedef name self; \ + std::vector > S2_state;\ + std::vector > SO3_state;\ + std::vector, int> > vect_state;\ + std::vector, int> > SEN_state;\ + MTK_SUBVARLIST(entries, S2_state, SO3_state, SEN_state) \ + name ( \ + MTK_TRANSFORM_COMMA(MTK_CONSTRUCTOR_ARG, entries) \ + ) : \ + MTK_TRANSFORM_COMMA(MTK_CONSTRUCTOR_COPY, entries) {}\ + int getDOF() const { return DOF; } \ + void boxplus(const MTK::vectview & __vec, scalar __scale = 1 ) { \ + MTK_TRANSFORM(MTK_BOXPLUS, entries)\ + } \ + void oplus(const MTK::vectview & __vec, scalar __scale = 1 ) { \ + MTK_TRANSFORM(MTK_OPLUS, entries)\ + } \ + void boxminus(MTK::vectview __res, const name& __oth) const { \ + MTK_TRANSFORM(MTK_BOXMINUS, entries)\ + } \ + friend std::ostream& operator<<(std::ostream& __os, const name& __var){ \ + return __os MTK_TRANSFORM(MTK_OSTREAM, entries); \ + } \ + void build_S2_state(){\ + MTK_TRANSFORM(MTK_S2_state, entries)\ + }\ + void build_vect_state(){\ + MTK_TRANSFORM(MTK_vect_state, entries)\ + }\ + void build_SO3_state(){\ + MTK_TRANSFORM(MTK_SO3_state, entries)\ + }\ + void build_SEN_state(){\ + MTK_TRANSFORM(MTK_SEN_state, entries)\ + }\ + void Lie_hat(Eigen::VectorXd &vec, Eigen::MatrixXd &res, int idx) {\ + MTK_TRANSFORM(MTK_HAT, entries)\ + }\ + void Lie_Jacob_Right_Inv(Eigen::VectorXd &vec, Eigen::MatrixXd &res, int idx) {\ + MTK_TRANSFORM(MTK_JACOB_RIGHT_INV, entries)\ + }\ + void Lie_Jacob_Right(Eigen::VectorXd &vec, Eigen::MatrixXd &res, int idx) {\ + MTK_TRANSFORM(MTK_JACOB_RIGHT, entries)\ + }\ + void S2_hat(Eigen::Matrix &res, int idx) {\ + MTK_TRANSFORM(MTK_S2_hat, entries)\ + }\ + void S2_Nx_yy(Eigen::Matrix &res, int idx) {\ + MTK_TRANSFORM(MTK_S2_Nx_yy, entries)\ + }\ + void S2_Mx(Eigen::Matrix &res, Eigen::Matrix dx, int idx) {\ + MTK_TRANSFORM(MTK_S2_Mx, entries)\ + }\ + friend std::istream& operator>>(std::istream& __is, name& __var){ \ + return __is MTK_TRANSFORM(MTK_ISTREAM, entries); \ + } \ +}; + + + +#endif /*MTK_AUTOCONSTRUCT_HPP_*/ diff --git a/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/src/SubManifold.hpp b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/src/SubManifold.hpp new file mode 100644 index 0000000..a1b13de --- /dev/null +++ b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/src/SubManifold.hpp @@ -0,0 +1,123 @@ +// This is an advanced implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/src/SubManifold.hpp + * @brief Defines the SubManifold class + */ + + +#ifndef SUBMANIFOLD_HPP_ +#define SUBMANIFOLD_HPP_ + + +#include "vectview.hpp" + + +namespace MTK { + +/** + * @ingroup SubManifolds + * Helper class for compound manifolds. + * This class wraps a manifold T and provides an enum IDX refering to the + * index of the SubManifold within the compound manifold. + * + * Memberpointers to a submanifold can be used for @ref SubManifolds "functions accessing submanifolds". + * + * @tparam T The manifold type of the sub-type + * @tparam idx The index of the sub-type within the compound manifold + */ +template +struct SubManifold : public T +{ + enum {IDX = idx, DIM = dim /*!< index of the sub-type within the compound manifold */ }; + //! manifold type + typedef T type; + + //! Construct from derived type + template + explicit + SubManifold(const X& t) : T(t) {}; + + //! Construct from internal type + //explicit + SubManifold(const T& t) : T(t) {}; + + //! inherit assignment operator + using T::operator=; + +}; + +} // namespace MTK + + +#endif /* SUBMANIFOLD_HPP_ */ diff --git a/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/src/mtkmath.hpp b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/src/mtkmath.hpp new file mode 100644 index 0000000..a8770e4 --- /dev/null +++ b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/src/mtkmath.hpp @@ -0,0 +1,294 @@ +// This is an advanced implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/src/mtkmath.hpp + * @brief several math utility functions. + */ + +#ifndef MTKMATH_H_ +#define MTKMATH_H_ + +#include + +#include + +#include "../types/vect.hpp" + +#ifndef M_PI +#define M_PI 3.1415926535897932384626433832795 +#endif + + +namespace MTK { + +namespace internal { + +template +struct traits { + typedef typename Manifold::scalar scalar; + enum {DOF = Manifold::DOF}; + typedef vect vectorized_type; + typedef Eigen::Matrix matrix_type; +}; + +template<> +struct traits : traits > {}; +template<> +struct traits : traits > {}; + +} // namespace internal + +/** + * \defgroup MTKMath Mathematical helper functions + */ +//@{ + +//! constant @f$ \pi @f$ +const double pi = M_PI; + +template inline scalar tolerance(); + +template<> inline float tolerance() { return 1e-5f; } +template<> inline double tolerance() { return 1e-11; } + + +/** + * normalize @a x to @f$[-bound, bound] @f$. + * + * result for @f$ x = bound + 2\cdot n\cdot bound @f$ is arbitrary @f$\pm bound @f$. + */ +template +inline scalar normalize(scalar x, scalar bound){ //not used + if(std::fabs(x) <= bound) return x; + int r = (int)(x *(scalar(1.0)/ bound)); + return x - ((r + (r>>31) + 1) & ~1)*bound; +} + +/** + * Calculate cosine and sinc of sqrt(x2). + * @param x2 the squared angle must be non-negative + * @return a pair containing cos and sinc of sqrt(x2) + */ +template +std::pair cos_sinc_sqrt(const scalar &x2){ + using std::sqrt; + using std::cos; + using std::sin; + static scalar const taylor_0_bound = boost::math::tools::epsilon(); + static scalar const taylor_2_bound = sqrt(taylor_0_bound); + static scalar const taylor_n_bound = sqrt(taylor_2_bound); + + assert(x2>=0 && "argument must be non-negative and must not be nan/-nan"); + + // FIXME check if bigger bounds are possible + if(x2>=taylor_n_bound) { + // slow fall-back solution + scalar x = sqrt(x2); + return std::make_pair(cos(x), sin(x)/x); // x is greater than 0. + } + + // FIXME Replace by Horner-Scheme (4 instead of 5 FLOP/term, numerically more stable, theoretically cos and sinc can be calculated in parallel using SSE2 mulpd/addpd) + // TODO Find optimal coefficients using Remez algorithm + static scalar const inv[] = {1/3., 1/4., 1/5., 1/6., 1/7., 1/8., 1/9.}; + scalar cosi = 1., sinc=1; + scalar term = -1/2. * x2; + for(int i=0; i<3; ++i) { + cosi += term; + term *= inv[2*i]; + sinc += term; + term *= -inv[2*i+1] * x2; + } + + return std::make_pair(cosi, sinc); + +} + +template +Eigen::Matrix hat(const Base& v) { + Eigen::Matrix res; + res << 0, -v[2], v[1], + v[2], 0, -v[0], + -v[1], v[0], 0; + return res; +} + +template +Eigen::Matrix A_inv_trans(const Base& v){ + Eigen::Matrix res; + if(v.norm() > MTK::tolerance()) + { + res = Eigen::Matrix::Identity() + 0.5 * hat(v) + (1 - v.norm() * std::cos(v.norm() / 2) / 2 / std::sin(v.norm() / 2)) * hat(v) * hat(v) / v.squaredNorm(); + + } + else + { + res = Eigen::Matrix::Identity(); + } + + return res; +} + +template +Eigen::Matrix A_inv(const Base& v){ + Eigen::Matrix res; + if(v.norm() > MTK::tolerance()) + { + res = Eigen::Matrix::Identity() - 0.5 * hat(v) + (1 - v.norm() * std::cos(v.norm() / 2) / 2 / std::sin(v.norm() / 2)) * hat(v) * hat(v) / v.squaredNorm(); + + } + else + { + res = Eigen::Matrix::Identity(); + } + + return res; +} + +template +Eigen::Matrix S2_w_expw_( Eigen::Matrix v, scalar length) + { + Eigen::Matrix res; + scalar norm = std::sqrt(v[0]*v[0] + v[1]*v[1]); + if(norm < MTK::tolerance()){ + res = Eigen::Matrix::Zero(); + res(0, 1) = 1; + res(1, 2) = 1; + res /= length; + } + else{ + res << -v[0]*(1/norm-1/std::tan(norm))/std::sin(norm), norm/std::sin(norm), 0, + -v[1]*(1/norm-1/std::tan(norm))/std::sin(norm), 0, norm/std::sin(norm); + res /= length; + } + } + +template +Eigen::Matrix A_matrix(const Base & v){ + Eigen::Matrix res; + double squaredNorm = v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; + double norm = std::sqrt(squaredNorm); + if(norm < MTK::tolerance()){ + res = Eigen::Matrix::Identity(); + } + else{ + res = Eigen::Matrix::Identity() + (1 - std::cos(norm)) / squaredNorm * hat(v) + (1 - std::sin(norm) / norm) / squaredNorm * hat(v) * hat(v); + } + return res; +} + +template +scalar exp(vectview result, vectview vec, const scalar& scale = 1) { + scalar norm2 = vec.squaredNorm(); + std::pair cos_sinc = cos_sinc_sqrt(scale*scale * norm2); + scalar mult = cos_sinc.second * scale; + result = mult * vec; + return cos_sinc.first; +} + + +/** + * Inverse function to @c exp. + * + * @param result @c vectview to the result + * @param w scalar part of input + * @param vec vector part of input + * @param scale scale result by this value + * @param plus_minus_periodicity if true values @f$[w, vec]@f$ and @f$[-w, -vec]@f$ give the same result + */ +template +void log(vectview result, + const scalar &w, const vectview vec, + const scalar &scale, bool plus_minus_periodicity) +{ + // FIXME implement optimized case for vec.squaredNorm() <= tolerance() * (w*w) via Rational Remez approximation ~> only one division + scalar nv = vec.norm(); + if(nv < tolerance()) { + if(!plus_minus_periodicity && w < 0) { + // find the maximal entry: + int i; + nv = vec.cwiseAbs().maxCoeff(&i); + result = scale * std::atan2(nv, w) * vect::Unit(i); + return; + } + nv = tolerance(); + } + scalar s = scale / nv * (plus_minus_periodicity ? std::atan(nv / w) : std::atan2(nv, w) ); + + result = s * vec; +} + + +} // namespace MTK + + +#endif /* MTKMATH_H_ */ diff --git a/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/src/vectview.hpp b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/src/vectview.hpp new file mode 100644 index 0000000..5025071 --- /dev/null +++ b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/src/vectview.hpp @@ -0,0 +1,168 @@ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/src/vectview.hpp + * @brief Wrapper class around a pointer used as interface for plain vectors. + */ + +#ifndef VECTVIEW_HPP_ +#define VECTVIEW_HPP_ + +#include + +namespace MTK { + +/** + * A view to a vector. + * Essentially, @c vectview is only a pointer to @c scalar but can be used directly in @c Eigen expressions. + * The dimension of the vector is given as template parameter and type-checked when used in expressions. + * Data has to be modifiable. + * + * @tparam scalar Scalar type of the vector. + * @tparam dim Dimension of the vector. + * + * @todo @c vectview can be replaced by simple inheritance of @c Eigen::Map, as soon as they get const-correct + */ +namespace internal { + template + struct CovBlock { + typedef typename Eigen::Block, T1::DOF, T2::DOF> Type; + typedef typename Eigen::Block, T1::DOF, T2::DOF> ConstType; + }; + + template + struct CovBlock_ { + typedef typename Eigen::Block, T1::DIM, T2::DIM> Type; + typedef typename Eigen::Block, T1::DIM, T2::DIM> ConstType; + }; + + template + struct CrossCovBlock { + typedef typename Eigen::Block, T1::DOF, T2::DOF> Type; + typedef typename Eigen::Block, T1::DOF, T2::DOF> ConstType; + }; + + template + struct CrossCovBlock_ { + typedef typename Eigen::Block, T1::DIM, T2::DIM> Type; + typedef typename Eigen::Block, T1::DIM, T2::DIM> ConstType; + }; + + template + struct VectviewBase { + typedef Eigen::Matrix matrix_type; + typedef typename matrix_type::MapType Type; + typedef typename matrix_type::ConstMapType ConstType; + }; + + template + struct UnalignedType { + typedef T type; + }; +} + +template +class vectview : public internal::VectviewBase::Type { + typedef internal::VectviewBase VectviewBase; +public: + //! plain matrix type + typedef typename VectviewBase::matrix_type matrix_type; + //! base type + typedef typename VectviewBase::Type base; + //! construct from pointer + explicit + vectview(scalar* data, int dim_=dim) : base(data, dim_) {} + //! construct from plain matrix + vectview(matrix_type& m) : base(m.data(), m.size()) {} + //! construct from another @c vectview + vectview(const vectview &v) : base(v) {} + //! construct from Eigen::Block: + template + vectview(Eigen::VectorBlock block) : base(&block.coeffRef(0), block.size()) {} + template + vectview(Eigen::Block block) : base(&block.coeffRef(0), block.size()) {} + + //! inherit assignment operator + using base::operator=; + //! data pointer + scalar* data() {return const_cast(base::data());} +}; + +/** + * @c const version of @c vectview. + * Compared to @c Eigen::Map this implementation is const correct, i.e., + * data will not be modifiable using this view. + * + * @tparam scalar Scalar type of the vector. + * @tparam dim Dimension of the vector. + * + * @sa vectview + */ +template +class vectview : public internal::VectviewBase::ConstType { + typedef internal::VectviewBase VectviewBase; +public: + //! plain matrix type + typedef typename VectviewBase::matrix_type matrix_type; + //! base type + typedef typename VectviewBase::ConstType base; + //! construct from const pointer + explicit + vectview(const scalar* data, int dim_ = dim) : base(data, dim_) {} + //! construct from column vector + template + vectview(const Eigen::Matrix& m) : base(m.data()) {} + //! construct from row vector + template + vectview(const Eigen::Matrix& m) : base(m.data()) {} + //! construct from another @c vectview + vectview(vectview x) : base(x.data()) {} + //! construct from base + vectview(const base &x) : base(x) {} + /** + * Construct from Block + * @todo adapt this, when Block gets const-correct + */ + template + vectview(Eigen::VectorBlock block) : base(&block.coeffRef(0)) {} + template + vectview(Eigen::Block block) : base(&block.coeffRef(0)) {} + +}; + + +} // namespace MTK + +#endif /* VECTVIEW_HPP_ */ diff --git a/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/startIdx.hpp b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/startIdx.hpp new file mode 100644 index 0000000..4dc2958 --- /dev/null +++ b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/startIdx.hpp @@ -0,0 +1,328 @@ +// This is an advanced implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/startIdx.hpp + * @brief Tools to access sub-elements of compound manifolds. + */ +#ifndef GET_START_INDEX_H_ +#define GET_START_INDEX_H_ + +#include + +#include "src/SubManifold.hpp" +#include "src/vectview.hpp" + +namespace MTK { + + +/** + * \defgroup SubManifolds Accessing Submanifolds + * For compound manifolds constructed using MTK_BUILD_MANIFOLD, member pointers + * can be used to get sub-vectors or matrix-blocks of a corresponding big matrix. + * E.g. for a type @a pose consisting of @a orient and @a trans the member pointers + * @c &pose::orient and @c &pose::trans give all required information and are still + * valid if the base type gets extended or the actual types of @a orient and @a trans + * change (e.g. from 2D to 3D). + * + * @todo Maybe require manifolds to typedef MatrixType and VectorType, etc. + */ +//@{ + +/** + * Determine the index of a sub-variable within a compound variable. + */ +template +int getStartIdx( MTK::SubManifold Base::*) +{ + return idx; +} + +template +int getStartIdx_( MTK::SubManifold Base::*) +{ + return dim; +} + +/** + * Determine the degrees of freedom of a sub-variable within a compound variable. + */ +template +int getDof( MTK::SubManifold Base::*) +{ + return T::DOF; +} +template +int getDim( MTK::SubManifold Base::*) +{ + return T::DIM; +} + +/** + * set the diagonal elements of a covariance matrix corresponding to a sub-variable + */ +template +void setDiagonal(Eigen::Matrix &cov, + MTK::SubManifold Base::*, const typename Base::scalar &val) +{ + cov.diagonal().template segment(idx).setConstant(val); +} + +template +void setDiagonal_(Eigen::Matrix &cov, + MTK::SubManifold Base::*, const typename Base::scalar &val) +{ + cov.diagonal().template segment(dim).setConstant(val); +} + +/** + * Get the subblock of corresponding to two members, i.e. + * \code + * Eigen::Matrix m; + * MTK::subblock(m, &Pose::orient, &Pose::trans) = some_expression; + * MTK::subblock(m, &Pose::trans, &Pose::orient) = some_expression.trans(); + * \endcode + * lets you modify mixed covariance entries in a bigger covariance matrix. + */ +template +typename MTK::internal::CovBlock::Type +subblock(Eigen::Matrix &cov, + MTK::SubManifold Base::*, MTK::SubManifold Base::*) +{ + return cov.template block(idx1, idx2); +} + +template +typename MTK::internal::CovBlock_::Type +subblock_(Eigen::Matrix &cov, + MTK::SubManifold Base::*, MTK::SubManifold Base::*) +{ + return cov.template block(dim1, dim2); +} + +template +typename MTK::internal::CrossCovBlock::Type +subblock(Eigen::Matrix &cov, MTK::SubManifold Base1::*, MTK::SubManifold Base2::*) +{ + return cov.template block(idx1, idx2); +} + +template +typename MTK::internal::CrossCovBlock_::Type +subblock_(Eigen::Matrix &cov, MTK::SubManifold Base1::*, MTK::SubManifold Base2::*) +{ + return cov.template block(dim1, dim2); +} +/** + * Get the subblock of corresponding to a member, i.e. + * \code + * Eigen::Matrix m; + * MTK::subblock(m, &Pose::orient) = some_expression; + * \endcode + * lets you modify covariance entries in a bigger covariance matrix. + */ +template +typename MTK::internal::CovBlock_::Type +subblock_(Eigen::Matrix &cov, + MTK::SubManifold Base::*) +{ + return cov.template block(dim, dim); +} + +template +typename MTK::internal::CovBlock::Type +subblock(Eigen::Matrix &cov, + MTK::SubManifold Base::*) +{ + return cov.template block(idx, idx); +} + +template +class get_cov { +public: + typedef Eigen::Matrix type; + typedef const Eigen::Matrix const_type; +}; + +template +class get_cov_ { +public: + typedef Eigen::Matrix type; + typedef const Eigen::Matrix const_type; +}; + +template +class get_cross_cov { +public: + typedef Eigen::Matrix type; + typedef const type const_type; +}; + +template +class get_cross_cov_ { +public: + typedef Eigen::Matrix type; + typedef const type const_type; +}; + + +template +vectview +subvector_impl_(vectview vec, SubManifold Base::*) +{ + return vec.template segment(dim); +} + +template +vectview +subvector_impl(vectview vec, SubManifold Base::*) +{ + return vec.template segment(idx); +} + +/** + * Get the subvector corresponding to a sub-manifold from a bigger vector. + */ + template +vectview +subvector_(vectview vec, SubManifold Base::* ptr) +{ + return subvector_impl_(vec, ptr); +} + +template +vectview +subvector(vectview vec, SubManifold Base::* ptr) +{ + return subvector_impl(vec, ptr); +} + +/** + * @todo This should be covered already by subvector(vectview vec,SubManifold Base::*) + */ +template +vectview +subvector(Eigen::Matrix& vec, SubManifold Base::* ptr) +{ + return subvector_impl(vectview(vec), ptr); +} + +template +vectview +subvector_(Eigen::Matrix& vec, SubManifold Base::* ptr) +{ + return subvector_impl_(vectview(vec), ptr); +} + +template +vectview +subvector_(const Eigen::Matrix& vec, SubManifold Base::* ptr) +{ + return subvector_impl_(vectview(vec), ptr); +} + +template +vectview +subvector(const Eigen::Matrix& vec, SubManifold Base::* ptr) +{ + return subvector_impl(vectview(vec), ptr); +} + + +/** + * const version of subvector(vectview vec,SubManifold Base::*) + */ +template +vectview +subvector_impl(const vectview cvec, SubManifold Base::*) +{ + return cvec.template segment(idx); +} + +template +vectview +subvector_impl_(const vectview cvec, SubManifold Base::*) +{ + return cvec.template segment(dim); +} + +template +vectview +subvector(const vectview cvec, SubManifold Base::* ptr) +{ + return subvector_impl(cvec, ptr); +} + + +} // namespace MTK + +#endif // GET_START_INDEX_H_ diff --git a/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/S2.hpp b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/S2.hpp new file mode 100644 index 0000000..730e664 --- /dev/null +++ b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/S2.hpp @@ -0,0 +1,326 @@ +// This is a NEW implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/types/S2.hpp + * @brief Unit vectors on the sphere, or directions in 3D. + */ +#ifndef S2_H_ +#define S2_H_ + + +#include "vect.hpp" + +#include "SOn.hpp" +#include "../src/mtkmath.hpp" + + + + +namespace MTK { + +/** + * Manifold representation of @f$ S^2 @f$. + * Used for unit vectors on the sphere or directions in 3D. + * + * @todo add conversions from/to polar angles? + */ +template +struct S2 { + + typedef _scalar scalar; + typedef vect<3, scalar> vect_type; + typedef SO3 SO3_type; + typedef typename vect_type::base vec3; + scalar length = scalar(den)/scalar(num); + enum {DOF=2, TYP = 1, DIM = 3}; + +//private: + /** + * Unit vector on the sphere, or vector pointing in a direction + */ + vect_type vec; + +public: + S2() { + if(S2_typ == 3) vec=length * vec3(0, 0, std::sqrt(1)); + if(S2_typ == 2) vec=length * vec3(0, std::sqrt(1), 0); + if(S2_typ == 1) vec=length * vec3(std::sqrt(1), 0, 0); + } + S2(const scalar &x, const scalar &y, const scalar &z) : vec(vec3(x, y, z)) { + vec.normalize(); + vec = vec * length; + } + + S2(const vect_type &_vec) : vec(_vec) { + vec.normalize(); + vec = vec * length; + } + + void oplus(MTK::vectview delta, scalar scale = 1) + { + SO3_type res; + res.w() = MTK::exp(res.vec(), delta, scalar(scale/2)); + vec = res.normalized().toRotationMatrix() * vec; + } + + void boxplus(MTK::vectview delta, scalar scale=1) { + Eigen::Matrix Bx; + S2_Bx(Bx); + vect_type Bu = Bx*delta;SO3_type res; + res.w() = MTK::exp(res.vec(), Bu, scalar(scale/2)); + vec = res.normalized().toRotationMatrix() * vec; + } + + void boxminus(MTK::vectview res, const S2& other) const { + scalar v_sin = (MTK::hat(vec)*other.vec).norm(); + scalar v_cos = vec.transpose() * other.vec; + scalar theta = std::atan2(v_sin, v_cos); + if(v_sin < MTK::tolerance()) + { + if(std::fabs(theta) > MTK::tolerance() ) + { + res[0] = 3.1415926; + res[1] = 0; + } + else{ + res[0] = 0; + res[1] = 0; + } + } + else + { + S2 other_copy = other; + Eigen::MatrixBx; + other_copy.S2_Bx(Bx); + res = theta/v_sin * Bx.transpose() * MTK::hat(other.vec)*vec; + } + } + + void hat(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + void Jacob_right_inv(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + void Jacob_right(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + + void S2_hat(Eigen::Matrix &res) + { + Eigen::Matrix skew_vec; + skew_vec << scalar(0), -vec[2], vec[1], + vec[2], scalar(0), -vec[0], + -vec[1], vec[0], scalar(0); + res = skew_vec; + } + + + void S2_Bx(Eigen::Matrix &res) + { + if(S2_typ == 3) + { + if(vec[2] + length > tolerance()) + { + + res << length - vec[0]*vec[0]/(length+vec[2]), -vec[0]*vec[1]/(length+vec[2]), + -vec[0]*vec[1]/(length+vec[2]), length-vec[1]*vec[1]/(length+vec[2]), + -vec[0], -vec[1]; + res /= length; + } + else + { + res = Eigen::Matrix::Zero(); + res(1, 1) = -1; + res(2, 0) = 1; + } + } + else if(S2_typ == 2) + { + if(vec[1] + length > tolerance()) + { + + res << length - vec[0]*vec[0]/(length+vec[1]), -vec[0]*vec[2]/(length+vec[1]), + -vec[0], -vec[2], + -vec[0]*vec[2]/(length+vec[1]), length-vec[2]*vec[2]/(length+vec[1]); + res /= length; + } + else + { + res = Eigen::Matrix::Zero(); + res(1, 1) = -1; + res(2, 0) = 1; + } + } + else + { + if(vec[0] + length > tolerance()) + { + + res << -vec[1], -vec[2], + length - vec[1]*vec[1]/(length+vec[0]), -vec[2]*vec[1]/(length+vec[0]), + -vec[2]*vec[1]/(length+vec[0]), length-vec[2]*vec[2]/(length+vec[0]); + res /= length; + } + else + { + res = Eigen::Matrix::Zero(); + res(1, 1) = -1; + res(2, 0) = 1; + } + } + } + + void S2_Nx(Eigen::Matrix &res, S2& subtrahend) + { + if((vec+subtrahend.vec).norm() > tolerance()) + { + Eigen::Matrix Bx; + S2_Bx(Bx); + if((vec-subtrahend.vec).norm() > tolerance()) + { + scalar v_sin = (MTK::hat(vec)*subtrahend.vec).norm(); + scalar v_cos = vec.transpose() * subtrahend.vec; + + res = Bx.transpose() * (std::atan2(v_sin, v_cos)/v_sin*MTK::hat(vec)+MTK::hat(vec)*subtrahend.vec*((-v_cos/v_sin/v_sin/length/length/length/length+std::atan2(v_sin, v_cos)/v_sin/v_sin/v_sin)*subtrahend.vec.transpose()*MTK::hat(vec)*MTK::hat(vec)-vec.transpose()/length/length/length/length)); + } + else + { + res = 1/length/length*Bx.transpose()*MTK::hat(vec); + } + } + else + { + std::cerr << "No N(x, y) for x=-y" << std::endl; + std::exit(100); + } + } + + void S2_Nx_yy(Eigen::Matrix &res) + { + Eigen::Matrix Bx; + S2_Bx(Bx); + res = 1/length/length*Bx.transpose()*MTK::hat(vec); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + Eigen::Matrix Bx; + S2_Bx(Bx); + if(delta.norm() < tolerance()) + { + res = -MTK::hat(vec)*Bx; + } + else{ + vect_type Bu = Bx*delta; + SO3_type exp_delta; + exp_delta.w() = MTK::exp(exp_delta.vec(), Bu, scalar(1/2)); + res = -exp_delta.normalized().toRotationMatrix()*MTK::hat(vec)*MTK::A_matrix(Bu).transpose()*Bx; + } + } + + operator const vect_type&() const{ + return vec; + } + + const vect_type& get_vect() const { + return vec; + } + + friend S2 operator*(const SO3& rot, const S2& dir) + { + S2 ret; + ret.vec = rot.normalized() * dir.vec; + return ret; + } + + scalar operator[](int idx) const {return vec[idx]; } + + friend std::ostream& operator<<(std::ostream &os, const S2& vec){ + return os << vec.vec.transpose() << " "; + } + friend std::istream& operator>>(std::istream &is, S2& vec){ + for(int i=0; i<3; ++i) + is >> vec.vec[i]; + vec.vec.normalize(); + vec.vec = vec.vec * vec.length; + return is; + + } +}; + + +} // namespace MTK + + +#endif /*S2_H_*/ diff --git a/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/SEn.hpp b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/SEn.hpp new file mode 100644 index 0000000..2270136 --- /dev/null +++ b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/SEn.hpp @@ -0,0 +1,334 @@ +// This is an advanced implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/types/SEn.hpp + * @brief Standard Orthogonal Groups i.e.\ rotatation groups. + */ +#ifndef SEN_H_ +#define SEN_H_ + +#include + +#include "SOn.hpp" +#include "vect.hpp" +#include "../src/mtkmath.hpp" + + +namespace MTK { + + +/** + * Three-dimensional orientations represented as Quaternion. + * It is assumed that the internal Quaternion always stays normalized, + * should this not be the case, call inherited member function @c normalize(). + */ +template +struct SEN { + enum {DOF = num_of_vec_plus1, DIM = num_of_vec_plus1, TYP = 4}; + typedef _scalar scalar; + typedef Eigen::Matrix base; + typedef SO3 SO3_type; + // typedef Eigen::Quaternion base; + // typedef Eigen::Quaternion Quaternion; + typedef vect vect_type; + SO3_type SO3_data; + base mat; + + /** + * Construct from real part and three imaginary parts. + * Quaternion is normalized after construction. + */ + // SEN(const base& src) : mat(src) { + // // base::normalize(); + // } + + /** + * Construct from Eigen::Quaternion. + * @note Non-normalized input may result result in spurious behavior. + */ + SEN(const base& src = base::Identity()) : mat(src) {} + + /** + * Construct from rotation matrix. + * @note Invalid rotation matrices may lead to spurious behavior. + */ + // template + // SO3(const Eigen::MatrixBase& matrix) : base(matrix) {} + + /** + * Construct from arbitrary rotation type. + * @note Invalid rotation matrices may lead to spurious behavior. + */ + // template + // SO3(const Eigen::RotationBase& rotation) : base(rotation.derived()) {} + + //! @name Manifold requirements + + void boxplus(MTK::vectview vec, scalar scale=1) { + SEN delta = exp(vec, scale); // ? + mat = mat * delta.mat; + } + void boxminus(MTK::vectview res, const SEN& other) const { + base error_mat = other.mat.inverse() * mat; + res = log(error_mat); + } + //} + + void oplus(MTK::vectview vec, scalar scale=1) { + SEN delta = exp(vec, scale); + mat = mat * delta.mat; + } + + // void hat(MTK::vectview& v, Eigen::Matrix &res) { + void hat(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + res = Eigen::Matrix::Zero(); + Eigen::Matrix psi; + psi << 0, -v[2], v[1], + v[2], 0, -v[0], + -v[1], v[0], 0; + res.block<3, 3>(0, 0) = psi; + for(int i = 3; i < v.size() / 3 + 2; i++) + { + res.block<3, 1>(0, i) = v.segment<3>(i + (i-3)*3); + } + // return res; + } + + // void Jacob_right_inv(MTK::vectview vec, Eigen::Matrix & res){ + void Jacob_right_inv(Eigen::VectorXd& vec, Eigen::MatrixXd &res){ + res = Eigen::Matrix::Zero(); + Eigen::Matrix M_v; + Eigen::VectorXd vec_psi, vec_ro; + Eigen::MatrixXd jac_v; + Eigen::MatrixXd hat_v, hat_ro; + vec_psi = vec.segment<3>(0); + // Eigen::Matrix ; + SO3_data.hat(vec_psi, hat_v); + SO3_data.Jacob_right_inv(vec_psi, jac_v); + double norm = vec_psi.norm(); + for(int i = 0; i < vec.size() / 3; i++) + { + res.block<3, 3>(i*3, i*3) = jac_v; + } + for(int i = 1; i < vec.size() / 3; i++) + { + vec_ro = vec.segment<3>(i * 3); + SO3_data.hat(vec_ro, hat_ro); + if(norm > MTK::tolerance()) + { + res.block<3,3>(i*3, 0) = 0.5 * hat_ro + (1 - norm * std::cos(norm / 2) / 2 / std::sin(norm / 2))/norm/norm * (hat_ro * hat_v + hat_v * hat_ro) + ((2 - norm * std::cos(norm / 2) / 2 / std::sin(norm / 2)) / 2 / norm / norm / norm / norm - 1 / 8 / norm / norm / std::sin(norm / 2) / std::sin(norm / 2)) * hat_v * (hat_ro * hat_v + hat_v * hat_ro) * hat_v; + } + else + { + res.block<3,3>(i*3, 0) = 0.5 * hat_ro; + } + + } + // return res; + } + + // void Jacob_right(MTK::vectview & vec, Eigen::Matrix &res){ + void Jacob_right(Eigen::VectorXd& vec, Eigen::MatrixXd &res){ + res = Eigen::Matrix::Zero(); + Eigen::MatrixXd hat_v, hat_ro; + Eigen::VectorXd vec_psi, vec_ro; + Eigen::MatrixXd jac_v; + vec_psi = vec.segment<3>(0); + // Eigen::Matrix ; + SO3_data.hat(vec_psi, hat_v); + SO3_data.Jacob_right(vec_psi, jac_v); + // double squaredNorm = v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; + // double norm = std::sqrt(squaredNorm); + double norm = vec_psi.norm(); + for(int i = 0; i < vec.size() / 3; i++) + { + res.block<3, 3>(i*3, i*3) = jac_v; + } + for(int i = 1; i < vec.size() / 3; i++) + { + vec_ro = vec.segment<3>(i * 3); + SO3_data.hat(vec_ro, hat_ro); + if(norm > MTK::tolerance()) + { + res.block<3,3>(i*3, 0) = -1 * jac_v * (0.5 * hat_ro + (1 - norm * std::cos(norm / 2) / 2 / std::sin(norm / 2))/norm/norm * (hat_ro * hat_v + hat_v * hat_ro) + ((2 - norm * std::cos(norm / 2) / 2 / std::sin(norm / 2)) / 2 / norm / norm / norm / norm - 1 / 8 / norm / norm / std::sin(norm / 2) / std::sin(norm / 2)) * hat_v * (hat_ro * hat_v + hat_v * hat_ro) * hat_v) * jac_v; + } + else + { + res.block<3,3>(i*3, 0) = -0.5 * jac_v * hat_ro * jac_v; + } + + } + // return res; + } + + void S2_hat(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + res = Eigen::Matrix::Zero(); + } + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + friend std::ostream& operator<<(std::ostream &os, const SEN& q){ + for(int i=0; i>(std::istream &is, SEN& q){ + // vect coeffs; + for(int i=0; i> q.mat(i, j); + } + } + // is >> q.mat; + // coeffs; + // q.coeffs() = coeffs.normalized(); + return is; + } + + //! @name Helper functions + //{ + /** + * Calculate the exponential map. In matrix terms this would correspond + * to the Rodrigues formula. + */ + // FIXME vectview<> can't be constructed from every MatrixBase<>, use const Vector3x& as workaround +// static SO3 exp(MTK::vectview dvec, scalar scale = 1){ + static SEN exp(const Eigen::Matrix& dvec, scalar scale = 1){ + SEN res; + res.mat = Eigen::Matrix::Identity(); + Eigen::Matrix exp_; //, jac; + Eigen::MatrixXd jac; + Eigen::Matrix psi; + Eigen::VectorXd minus_psi; + psi = dvec.template block<3,1>(0, 0); + minus_psi = -psi; + SO3_type SO3_temp; + exp_ = SO3_type::exp(psi); + SO3_temp.Jacob_right(minus_psi, jac); + res.mat.template block<3,3>(0, 0) = exp_; + for(int i = 3; i < DOF / 3 + 2; i++) + { + res.mat.template block<3, 1>(0, i) = jac * dvec.template block<3,1>(i + (i-3)*3,0); + } + return res; + } + /** + * Calculate the inverse of @c exp. + * Only guarantees that exp(log(x)) == x + */ + static Eigen::Matrix log(base &orient){ + Eigen::Matrix res; + Eigen::Matrix psi; + Eigen::VectorXd minus_psi; + Eigen::Matrix mat_psi; + Eigen::MatrixXd jac; + mat_psi = orient.template block<3, 3>(0, 0); + SO3_type SO3_temp; + SO3_type exp_psi(mat_psi); + psi = SO3_type::log(exp_psi); + minus_psi = -psi; + SO3_temp.Jacob_right_inv(minus_psi, jac); + for(int i = 3; i < dim_of_mat; i++) + { + res.template block<3,1>(i + (i-3)*3,0) = jac * orient.template block<3, 1>(0, i); + } + return res; + } +}; + + +} // namespace MTK + +#endif /*SON_H_*/ + diff --git a/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/SOn.hpp b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/SOn.hpp new file mode 100644 index 0000000..78f9eec --- /dev/null +++ b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/SOn.hpp @@ -0,0 +1,365 @@ +// This is an advanced implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/types/SOn.hpp + * @brief Standard Orthogonal Groups i.e.\ rotatation groups. + */ +#ifndef SON_H_ +#define SON_H_ + +#include + +#include "vect.hpp" +#include "../src/mtkmath.hpp" + + +namespace MTK { + + +/** + * Two-dimensional orientations represented as scalar. + * There is no guarantee that the representing scalar is within any interval, + * but the result of boxminus will always have magnitude @f$\le\pi @f$. + */ +template +struct SO2 : public Eigen::Rotation2D<_scalar> { + enum {DOF = 1, DIM = 2, TYP = 3}; + + typedef _scalar scalar; + typedef Eigen::Rotation2D base; + typedef vect vect_type; + + //! Construct from angle + SO2(const scalar& angle = 0) : base(angle) { } + + //! Construct from Eigen::Rotation2D + SO2(const base& src) : base(src) {} + + /** + * Construct from 2D vector. + * Resulting orientation will rotate the first unit vector to point to vec. + */ + SO2(const vect_type &vec) : base(atan2(vec[1], vec[0])) {}; + + + //! Calculate @c this->inverse() * @c r + SO2 operator%(const base &r) const { + return base::inverse() * r; + } + + //! Calculate @c this->inverse() * @c r + template + vect_type operator%(const Eigen::MatrixBase &vec) const { + return base::inverse() * vec; + } + + //! Calculate @c *this * @c r.inverse() + SO2 operator/(const SO2 &r) const { + return *this * r.inverse(); + } + + //! Gets the angle as scalar. + operator scalar() const { + return base::angle(); + } + void S2_hat(Eigen::Matrix &res) + { + res = Eigen::Matrix::Zero(); + } + //! @name Manifold requirements + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void oplus(MTK::vectview vec, scalar scale = 1) { + base::angle() += scale * vec[0]; + } + + void boxplus(MTK::vectview vec, scalar scale = 1) { + base::angle() += scale * vec[0]; + } + void boxminus(MTK::vectview res, const SO2& other) const { + res[0] = MTK::normalize(base::angle() - other.angle(), scalar(MTK::pi)); + } + + friend std::istream& operator>>(std::istream &is, SO2& ang){ + return is >> ang.angle(); + } + void hat(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + void Jacob_right_inv(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + void Jacob_right(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } +}; + + +/** + * Three-dimensional orientations represented as Quaternion. + * It is assumed that the internal Quaternion always stays normalized, + * should this not be the case, call inherited member function @c normalize(). + */ +template +struct SO3 : public Eigen::Quaternion<_scalar, Options> { + enum {DOF = 3, DIM = 3, TYP = 2}; + typedef _scalar scalar; + typedef Eigen::Quaternion base; + typedef Eigen::Quaternion Quaternion; + typedef vect vect_type; + + //! Calculate @c this->inverse() * @c r + template EIGEN_STRONG_INLINE + Quaternion operator%(const Eigen::QuaternionBase &r) const { + return base::conjugate() * r; + } + + //! Calculate @c this->inverse() * @c r + template + vect_type operator%(const Eigen::MatrixBase &vec) const { + return base::conjugate() * vec; + } + + //! Calculate @c this * @c r.conjugate() + template EIGEN_STRONG_INLINE + Quaternion operator/(const Eigen::QuaternionBase &r) const { + return *this * r.conjugate(); + } + + /** + * Construct from real part and three imaginary parts. + * Quaternion is normalized after construction. + */ + SO3(const scalar& w, const scalar& x, const scalar& y, const scalar& z) : base(w, x, y, z) { + base::normalize(); + } + + /** + * Construct from Eigen::Quaternion. + * @note Non-normalized input may result result in spurious behavior. + */ + SO3(const base& src = base::Identity()) : base(src) {} + + /** + * Construct from rotation matrix. + * @note Invalid rotation matrices may lead to spurious behavior. + */ + template + SO3(const Eigen::MatrixBase& matrix) : base(matrix) {} + + /** + * Construct from arbitrary rotation type. + * @note Invalid rotation matrices may lead to spurious behavior. + */ + template + SO3(const Eigen::RotationBase& rotation) : base(rotation.derived()) {} + + //! @name Manifold requirements + + void boxplus(MTK::vectview vec, scalar scale=1) { + SO3 delta = exp(vec, scale); + *this = *this * delta; + } + void boxminus(MTK::vectview res, const SO3& other) const { + res = SO3::log(other.conjugate() * *this); + } + //} + + void oplus(MTK::vectview vec, scalar scale=1) { + SO3 delta = exp(vec, scale); + *this = *this * delta; + } + + // void hat(MTK::vectview& v, Eigen::Matrix &res) { + void hat(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + // Eigen::Matrix res; + res << 0, -v[2], v[1], + v[2], 0, -v[0], + -v[1], v[0], 0; + // return res; + } + + // void Jacob_right_inv(MTK::vectview vec, Eigen::Matrix & res){ + void Jacob_right_inv(Eigen::VectorXd& vec, Eigen::MatrixXd &res){ + Eigen::MatrixXd hat_v; + hat(vec, hat_v); + if(vec.norm() > MTK::tolerance()) + { + res = Eigen::Matrix::Identity() + 0.5 * hat_v + (1 - vec.norm() * std::cos(vec.norm() / 2) / 2 / std::sin(vec.norm() / 2)) * hat_v * hat_v / vec.squaredNorm(); + } + else + { + res = Eigen::Matrix::Identity(); + } + // return res; + } + + // void Jacob_right(MTK::vectview & v, Eigen::Matrix &res){ + void Jacob_right(Eigen::VectorXd& v, Eigen::MatrixXd &res){ + Eigen::MatrixXd hat_v; + hat(v, hat_v); + double squaredNorm = v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; + double norm = std::sqrt(squaredNorm); + if(norm < MTK::tolerance()){ + res = Eigen::Matrix::Identity(); + } + else{ + res = Eigen::Matrix::Identity() - (1 - std::cos(norm)) / squaredNorm * hat_v + (1 - std::sin(norm) / norm) / squaredNorm * hat_v * hat_v; + } + // return res; + } + + + void S2_hat(Eigen::Matrix &res) + { + res = Eigen::Matrix::Zero(); + } + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + friend std::ostream& operator<<(std::ostream &os, const SO3& q){ + return os << q.coeffs().transpose() << " "; + } + + friend std::istream& operator>>(std::istream &is, SO3& q){ + vect<4,scalar> coeffs; + is >> coeffs; + q.coeffs() = coeffs.normalized(); + return is; + } + + //! @name Helper functions + //{ + /** + * Calculate the exponential map. In matrix terms this would correspond + * to the Rodrigues formula. + */ + // FIXME vectview<> can't be constructed from every MatrixBase<>, use const Vector3x& as workaround +// static SO3 exp(MTK::vectview dvec, scalar scale = 1){ + static SO3 exp(const Eigen::Matrix& dvec, scalar scale = 1){ + SO3 res; + res.w() = MTK::exp(res.vec(), dvec, scalar(scale/2)); + return res; + } + /** + * Calculate the inverse of @c exp. + * Only guarantees that exp(log(x)) == x + */ + static typename base::Vector3 log(const SO3 &orient){ + typename base::Vector3 res; + MTK::log(res, orient.w(), orient.vec(), scalar(2), true); + return res; + } +}; + +namespace internal { +template +struct UnalignedType >{ + typedef SO2 type; +}; + +template +struct UnalignedType >{ + typedef SO3 type; +}; + +} // namespace internal + + +} // namespace MTK + +#endif /*SON_H_*/ + diff --git a/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/vect.hpp b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/vect.hpp new file mode 100644 index 0000000..d75e6d7 --- /dev/null +++ b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/vect.hpp @@ -0,0 +1,511 @@ +// This is an advanced implementation of the algorithm described in the +// following paper: +// C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. +// CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119 + +/* + * Copyright (c) 2019--2023, The University of Hong Kong + * All rights reserved. + * + * Modifier: Dongjiao HE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008--2011, Universitaet Bremen + * All rights reserved. + * + * Author: Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file mtk/types/vect.hpp + * @brief Basic vectors interpreted as manifolds. + * + * This file also implements a simple wrapper for matrices, for arbitrary scalars + * and for positive scalars. + */ +#ifndef VECT_H_ +#define VECT_H_ + +#include +#include +#include + +#include "../src/vectview.hpp" + +namespace MTK { + +static const Eigen::IOFormat IO_no_spaces(Eigen::StreamPrecision, Eigen::DontAlignCols, ",", ",", "", "", "[", "]"); + + +/** + * A simple vector class. + * Implementation is basically a wrapper around Eigen::Matrix with manifold + * requirements added. + */ +template +struct vect : public Eigen::Matrix<_scalar, D, 1, _Options> { + typedef Eigen::Matrix<_scalar, D, 1, _Options> base; + enum {DOF = D, DIM = D, TYP = 0}; + typedef _scalar scalar; + + //using base::operator=; + + /** Standard constructor. Sets all values to zero. */ + vect(const base &src = base::Zero()) : base(src) {} + + /** Constructor copying the value of the expression \a other */ + template + EIGEN_STRONG_INLINE vect(const Eigen::DenseBase& other) : base(other) {} + + /** Construct from memory. */ + vect(const scalar* src, int size = DOF) : base(base::Map(src, size)) { } + + void boxplus(MTK::vectview vec, scalar scale=1) { + *this += scale * vec; + } + void boxminus(MTK::vectview res, const vect& other) const { + res = *this - other; + } + + void oplus(MTK::vectview vec, scalar scale=1) { + *this += scale * vec; + } + + void hat(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + void Jacob_right_inv(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + void Jacob_right(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + + void S2_hat(Eigen::Matrix &res) + { + res = Eigen::Matrix::Zero(); + } + + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + friend std::ostream& operator<<(std::ostream &os, const vect& v){ + // Eigen sometimes messes with the streams flags, so output manually: + for(int i=0; i>(std::istream &is, vect& v){ + char term=0; + is >> std::ws; // skip whitespace + switch(is.peek()) { + case '(': term=')'; is.ignore(1); break; + case '[': term=']'; is.ignore(1); break; + case '{': term='}'; is.ignore(1); break; + default: break; + } + if(D==Eigen::Dynamic) { + assert(term !=0 && "Dynamic vectors must be embraced"); + std::vector temp; + while(is.good() && is.peek() != term) { + scalar x; + is >> x; + temp.push_back(x); + if(is.peek()==',') is.ignore(1); + } + v = vect::Map(temp.data(), temp.size()); + } else + for(int i=0; i> v[i]; + if(is.peek()==',') { // ignore commas between values + is.ignore(1); + } + } + if(term!=0) { + char x; + is >> x; + if(x!=term) { + is.setstate(is.badbit); +// assert(x==term && "start and end bracket do not match!"); + } + } + return is; + } + + template + vectview tail(){ + BOOST_STATIC_ASSERT(0< dim && dim <= DOF); + return base::template tail(); + } + template + vectview tail() const{ + BOOST_STATIC_ASSERT(0< dim && dim <= DOF); + return base::template tail(); + } + template + vectview head(){ + BOOST_STATIC_ASSERT(0< dim && dim <= DOF); + return base::template head(); + } + template + vectview head() const{ + BOOST_STATIC_ASSERT(0< dim && dim <= DOF); + return base::template head(); + } +}; + + +/** + * A simple matrix class. + * Implementation is basically a wrapper around Eigen::Matrix with manifold + * requirements added, i.e., matrix is viewed as a plain vector for that. + */ +template::Options> +struct matrix : public Eigen::Matrix<_scalar, M, N, _Options> { + typedef Eigen::Matrix<_scalar, M, N, _Options> base; + enum {DOF = M * N, TYP = 4, DIM=0}; + typedef _scalar scalar; + + using base::operator=; + + /** Standard constructor. Sets all values to zero. */ + matrix() { + base::setZero(); + } + + /** Constructor copying the value of the expression \a other */ + template + EIGEN_STRONG_INLINE matrix(const Eigen::MatrixBase& other) : base(other) {} + + /** Construct from memory. */ + matrix(const scalar* src) : base(src) { } + + void boxplus(MTK::vectview vec, scalar scale = 1) { + *this += scale * base::Map(vec.data()); + } + void boxminus(MTK::vectview res, const matrix& other) const { + base::Map(res.data()) = *this - other; + } + + void hat(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + void Jacob_right_inv(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + void Jacob_right(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + + void S2_hat(Eigen::Matrix &res) + { + res = Eigen::Matrix::Zero(); + } + + void oplus(MTK::vectview vec, scalar scale = 1) { + *this += scale * base::Map(vec.data()); + } + + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + friend std::ostream& operator<<(std::ostream &os, const matrix& mat){ + for(int i=0; i>(std::istream &is, matrix& mat){ + for(int i=0; i> mat.data()[i]; + } + return is; + } +};// @todo What if M / N = Eigen::Dynamic? + + + +/** + * A simple scalar type. + */ +template +struct Scalar { + enum {DOF = 1, TYP = 5, DIM=0}; + typedef _scalar scalar; + + scalar value; + + Scalar(const scalar& value = scalar(0)) : value(value) {} + operator const scalar&() const { return value; } + operator scalar&() { return value; } + Scalar& operator=(const scalar& val) { value = val; return *this; } + + void S2_hat(Eigen::Matrix &res) + { + res = Eigen::Matrix::Zero(); + } + + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void oplus(MTK::vectview vec, scalar scale=1) { + value += scale * vec[0]; + } + + void boxplus(MTK::vectview vec, scalar scale=1) { + value += scale * vec[0]; + } + void boxminus(MTK::vectview res, const Scalar& other) const { + res[0] = *this - other; + } + + void hat(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + void Jacob_right_inv(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + void Jacob_right(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } +}; + +/** + * Positive scalars. + * Boxplus is implemented using multiplication by @f$x\boxplus\delta = x\cdot\exp(\delta) @f$. + */ +template +struct PositiveScalar { + enum {DOF = 1, TYP = 6, DIM=0}; + typedef _scalar scalar; + + scalar value; + + PositiveScalar(const scalar& value = scalar(1)) : value(value) { + assert(value > scalar(0)); + } + operator const scalar&() const { return value; } + PositiveScalar& operator=(const scalar& val) { assert(val>0); value = val; return *this; } + + void boxplus(MTK::vectview vec, scalar scale = 1) { + value *= std::exp(scale * vec[0]); + } + void boxminus(MTK::vectview res, const PositiveScalar& other) const { + res[0] = std::log(*this / other); + } + + void oplus(MTK::vectview vec, scalar scale = 1) { + value *= std::exp(scale * vec[0]); + } + + void hat(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + void Jacob_right_inv(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + void Jacob_right(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + + void S2_hat(Eigen::Matrix &res) + { + res = Eigen::Matrix::Zero(); + } + + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + + friend std::istream& operator>>(std::istream &is, PositiveScalar& s){ + is >> s.value; + assert(s.value > 0); + return is; + } +}; + +template +struct Complex : public std::complex<_scalar>{ + enum {DOF = 2, TYP = 7, DIM=0}; + typedef _scalar scalar; + + typedef std::complex Base; + + Complex(const Base& value) : Base(value) {} + Complex(const scalar& re = 0.0, const scalar& im = 0.0) : Base(re, im) {} + Complex(const MTK::vectview &in) : Base(in[0], in[1]) {} + template + Complex(const Eigen::DenseBase &in) : Base(in[0], in[1]) {} + + void boxplus(MTK::vectview vec, scalar scale = 1) { + Base::real() += scale * vec[0]; + Base::imag() += scale * vec[1]; + }; + void boxminus(MTK::vectview res, const Complex& other) const { + Complex diff = *this - other; + res << diff.real(), diff.imag(); + } + + void S2_hat(Eigen::Matrix &res) + { + res = Eigen::Matrix::Zero(); + } + + void hat(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + void Jacob_right_inv(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + void Jacob_right(Eigen::VectorXd& v, Eigen::MatrixXd &res) { + std::cout << "wrong idx" << std::endl; + } + + void oplus(MTK::vectview vec, scalar scale = 1) { + Base::real() += scale * vec[0]; + Base::imag() += scale * vec[1]; + }; + + void S2_Nx_yy(Eigen::Matrix &res) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + void S2_Mx(Eigen::Matrix &res, MTK::vectview delta) + { + std::cerr << "wrong idx for S2" << std::endl; + std::exit(100); + res = Eigen::Matrix::Zero(); + } + + scalar squaredNorm() const { + return std::pow(Base::real(),2) + std::pow(Base::imag(),2); + } + + const scalar& operator()(int i) const { + assert(0<=i && i<2 && "Index out of range"); + return i==0 ? Base::real() : Base::imag(); + } + scalar& operator()(int i){ + assert(0<=i && i<2 && "Index out of range"); + return i==0 ? Base::real() : Base::imag(); + } +}; + + +namespace internal { + +template +struct UnalignedType >{ + typedef vect type; +}; + +} // namespace internal + + +} // namespace MTK + + + + +#endif /*VECT_H_*/ diff --git a/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/wrapped_cv_mat.hpp b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/wrapped_cv_mat.hpp new file mode 100644 index 0000000..b6643f1 --- /dev/null +++ b/point_lio_ros2/include/IKFoM/IKFoM_toolkit/mtk/types/wrapped_cv_mat.hpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2010--2011, Universitaet Bremen and DFKI GmbH + * All rights reserved. + * + * Author: Rene Wagner + * Christoph Hertzberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Universitaet Bremen nor the DFKI GmbH + * nor the names of its contributors may be used to endorse or + * promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WRAPPED_CV_MAT_HPP_ +#define WRAPPED_CV_MAT_HPP_ + +#include +#include + +namespace MTK { + +template +struct cv_f_type; + +template<> +struct cv_f_type +{ + enum {value = CV_64F}; +}; + +template<> +struct cv_f_type +{ + enum {value = CV_32F}; +}; + +/** + * cv_mat wraps a CvMat around an Eigen Matrix + */ +template +class cv_mat : public matrix +{ + typedef matrix base_type; + enum {type_ = cv_f_type::value}; + CvMat cv_mat_; + +public: + cv_mat() + { + cv_mat_ = cvMat(rows, cols, type_, base_type::data()); + } + + cv_mat(const cv_mat& oth) : base_type(oth) + { + cv_mat_ = cvMat(rows, cols, type_, base_type::data()); + } + + template + cv_mat(const Eigen::MatrixBase &value) : base_type(value) + { + cv_mat_ = cvMat(rows, cols, type_, base_type::data()); + } + + template + cv_mat& operator=(const Eigen::MatrixBase &value) + { + base_type::operator=(value); + return *this; + } + + cv_mat& operator=(const cv_mat& value) + { + base_type::operator=(value); + return *this; + } + + // FIXME: Maybe overloading operator& is not a good idea ... + CvMat* operator&() + { + return &cv_mat_; + } + const CvMat* operator&() const + { + return &cv_mat_; + } +}; + +} // namespace MTK + +#endif /* WRAPPED_CV_MAT_HPP_ */ diff --git a/point_lio_ros2/include/IKFoM/LICENSE b/point_lio_ros2/include/IKFoM/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/point_lio_ros2/include/IKFoM/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/point_lio_ros2/include/IKFoM/README.md b/point_lio_ros2/include/IKFoM/README.md new file mode 100644 index 0000000..53a7dc5 --- /dev/null +++ b/point_lio_ros2/include/IKFoM/README.md @@ -0,0 +1,489 @@ +## IKFoM +**IKFoM** (Iterated Kalman Filters on Manifolds) is a computationally efficient and convenient toolkit for deploying iterated Kalman filters on various robotic systems, especially systems operating on high-dimension manifold. It implements a manifold-embedding Kalman filter which separates the manifold structures from system descriptions and is able to be used by only defining the system in a canonical form and calling the respective steps accordingly. The current implementation supports the full iterated Kalman filtering for systems on manifold and any of its sub-manifolds, and it is extendable to other types of manifold when necessary. + + +**Developers** + +[Dongjiao He](https://github.com/Joanna-HE) + +**Our related video**: https://youtu.be/sz_ZlDkl6fA + +## 1. Prerequisites + +### 1.1. **Eigen && Boost** +Eigen >= 3.3.4, Follow [Eigen Installation](http://eigen.tuxfamily.org/index.php?title=Main_Page). + +Boost >= 1.65. + +## 2. Usage when the measurement is of constant dimension and type. +Clone the repository: + +``` + git clone https://github.com/hku-mars/IKFoM.git +``` + +1. include the necessary head file: +``` +#include +``` +2. Select and instantiate the primitive manifolds: +``` + typedef MTK::SO3 SO3; // scalar type of variable: double + typedef MTK::vect<3, double> vect3; // dimension of the defined Euclidean variable: 3 + typedef MTK::S2 S2; // length of the S2 variable: 98/10; choose e1 as the original point of rotation: 1 +``` +3. Build system state, input and measurement as compound manifolds which are composed of the primitive manifolds: +``` +MTK_BUILD_MANIFOLD(state, // name of compound manifold: state +((vect3, pos)) // ((primitive manifold type, name of variable)) +((vect3, vel)) +((SO3, rot)) +((vect3, bg)) +((vect3, ba)) +((S2, grav)) +((SO3, offset_R_L_I)) +((vect3, offset_T_L_I)) +); +``` +4. Implement the vector field that is defined as , and its differentiation , , where w=0 could be left out: +``` +Eigen::Matrix f(state &s, const input &i) { + Eigen::Matrix res = Eigen::Matrix::Zero(); + res(0) = s.vel[0]; + res(1) = s.vel[1]; + res(2) = s.vel[2]; + return res; +} +Eigen::Matrix df_dx(state &s, const input &i) //notice S2 has length of 3 and dimension of 2 { + Eigen::Matrix cov = Eigen::Matrix::Zero(); + cov.template block<3, 3>(0, 12) = Eigen::Matrix3d::Identity(); + return cov; +} +Eigen::Matrix df_dw(state &s, const input &i) { + Eigen::Matrix cov = Eigen::Matrix::Zero(); + cov.template block<3, 3>(12, 3) = -s.rot.toRotationMatrix(); + return cov; +} +``` +Those functions would be called during the ekf state predict + +5. Implement the output equation and its differentiation , : +``` +measurement h(state &s, bool &valid) // the iteration stops before convergence whenever the user set valid as false +{ + if (condition){ valid = false; + } // other conditions could be used to stop the ekf update iteration before convergence, otherwise the iteration will not stop until the condition of convergence is satisfied. + measurement h_; + h_.position = s.pos; + return h_; +} +Eigen::Matrix dh_dx(state &s) {} +Eigen::Matrix dh_dv(state &s) {} +``` +Those functions would be called during the ekf state update + +6. Instantiate an **esekf** object **kf** and initialize it with initial or default state and covariance. + +(1) initial state and covariance: +``` +state init_state; +esekfom::esekf::cov init_P; +esekfom::esekf kf(init_state,init_P); +``` +(2) default state and covariance: +``` +esekfom::esekf kf; +``` +where **process_noise_dof** is the dimension of process noise, with the type of std int, and so for **measurement_noise_dof**. + +7. Deliver the defined models, std int maximum iteration numbers **Maximum_iter**, and the std array for testing convergence **epsi** into the **esekf** object: +``` +double epsi[state_dof] = {0.001}; +fill(epsi, epsi+state_dof, 0.001); // if the absolute of innovation of ekf update is smaller than epso, the update iteration is converged +kf.init(f, df_dx, df_dw, h, dh_dx, dh_dv, Maximum_iter, epsi); +``` +8. In the running time, once an input **in** is received with time interval **dt**, a propagation is executed: +``` +kf.predict(dt, Q, in); // process noise covariance: Q, an Eigen matrix +``` +9. Once a measurement **z** is received, an iterated update is executed: +``` +kf.update_iterated(z, R); // measurement noise covariance: R, an Eigen matrix +``` +*Remarks(1):* +- We also combine the output equation and its differentiation into an union function, whose usage is the same as the above steps 1-4, and steps 5-9 are shown as follows. + +5. Implement the output equation and its differentiation , : +``` +measurement h_share(state &s, esekfom::share_datastruct &share_data) +{ + if(share_data.converge) {} // this value is true means iteration is converged + if(condition) share_data.valid = false; // the iteration stops before convergence when this value is false if other conditions are satified + share_data.h_x = H_x; // H_x is the result matrix of the first differentiation + share_data.h_v = H_v; // H_v is the result matrix of the second differentiation + share_data.R = R; // R is the measurement noise covariance + share_data.z = z; // z is the obtained measurement + + measurement h_; + h_.position = s.pos; + return h_; +} +``` +This function would be called during ekf state update, and the output function and its derivatives, the measurement and the measurement noise would be obtained from this one union function + +6. Instantiate an **esekf** object **kf** and initialize it with initial or default state and covariance. + +(1) initial state and covariance: +``` +state init_state; +esekfom::esekf::cov init_P; +esekfom::esekf kf(init_state,init_P); +``` +(2) default state and covariance: +``` +esekfom::esekf kf; +``` +7. Deliver the defined models, std int maximum iteration numbers **Maximum_iter**, and the std array for testing convergence **epsi** into the **esekf** object: +``` +double epsi[state_dof] = {0.001}; +fill(epsi, epsi+state_dof, 0.001); // if the absolute of innovation of ekf update is smaller than epso, the update iteration is converged +kf.init_share(f, df_dx, df_dw, h_share, Maximum_iter, epsi); +``` +8. In the running time, once an input **in** is received with time interval **dt**, a propagation is executed: +``` +kf.predict(dt, Q, in); // process noise covariance: Q +``` +9. Once a measurement **z** is received, an iterated update is executed: +``` +kf.update_iterated_share(); +``` + +*Remarks(2):* +- The value of the state **x** and the covariance **P** are able to be changed by functions **change_x()** and **change_P()**: +``` +state set_x; +kf.change_x(set_x); +esekfom::esekf::cov set_P; +kf.change_P(set_P); +``` + +## 3. Usage when the measurement is an Eigen vector of changing dimension. + +Clone the repository: + +``` + git clone https://github.com/hku-mars/IKFoM.git +``` + +1. include the necessary head file: +``` +#include +``` +2. Select and instantiate the primitive manifolds: +``` + typedef MTK::SO3 SO3; // scalar type of variable: double + typedef MTK::vect<3, double> vect3; // dimension of the defined Euclidean variable: 3 + typedef MTK::S2 S2; // length of the S2 variable: 98/10; choose e1 as the original point of rotation: 1 +``` +3. Build system state and input as compound manifolds which are composed of the primitive manifolds: +``` +MTK_BUILD_MANIFOLD(state, // name of compound manifold: state +((vect3, pos)) // ((primitive manifold type, name of variable)) +((vect3, vel)) +((SO3, rot)) +((vect3, bg)) +((vect3, ba)) +((S2, grav)) +((SO3, offset_R_L_I)) +((vect3, offset_T_L_I)) +); +``` +4. Implement the vector field that is defined as , and its differentiation , , where w=0 could be left out: +``` +Eigen::Matrix f(state &s, const input &i) { + Eigen::Matrix res = Eigen::Matrix::Zero(); + res(0) = s.vel[0]; + res(1) = s.vel[1]; + res(2) = s.vel[2]; + return res; +} +Eigen::Matrix df_dx(state &s, const input &i) //notice S2 has length of 3 and dimension of 2 { + Eigen::Matrix cov = Eigen::Matrix::Zero(); + cov.template block<3, 3>(0, 12) = Eigen::Matrix3d::Identity(); + return cov; +} +Eigen::Matrix df_dw(state &s, const input &i) { + Eigen::Matrix cov = Eigen::Matrix::Zero(); + cov.template block<3, 3>(12, 3) = -s.rot.toRotationMatrix(); + return cov; +} +``` +Those functions would be called during ekf state predict + +5. Implement the output equation and its differentiation , : +``` +Eigen::Matrix h(state &s, bool &valid) //the iteration stops before convergence when valid is false { + if (condition){ valid = false; + } // other conditions could be used to stop the ekf update iteration before convergence, otherwise the iteration will not stop until the condition of convergence is satisfied. + Eigen::Matrix h_; + h_(0) = s.pos[0]; + return h_; +} +Eigen::Matrix dh_dx(state &s) {} +Eigen::Matrix dh_dv(state &s) {} +``` +Those functions would be called during ekf state update + +6. Instantiate an **esekf** object **kf** and initialize it with initial or default state and covariance. + +(1) initial state and covariance: +``` +state init_state; +esekfom::esekf::cov init_P; +esekfom::esekf kf(init_state,init_P); +``` +(2) default state and covariance: +``` +esekfom::esekf kf; +``` +where **process_noise_dof** is the dimension of process noise, with the type of std int, and so for **measurement_noise_dof** + +7. Deliver the defined models, std int maximum iteration numbers **Maximum_iter**, and the std array for testing convergence **epsi** into the **esekf** object: +``` +double epsi[state_dof] = {0.001}; +fill(epsi, epsi+state_dof, 0.001); // if the absolute of innovation of ekf update is smaller than epso, the update iteration is converged +kf.init_dyn(f, df_dx, df_dw, h, dh_dx, dh_dv, Maximum_iter, epsi); +``` +8. In the running time, once an input **in** is received with time interval **dt**, a propagation is executed: +``` +kf.predict(dt, Q, in); // process noise covariance: Q, an Eigen matrix +``` +9. Once a measurement **z** is received, an iterated update is executed: +``` +kf.update_iterated_dyn(z, R); // measurement noise covariance: R, an Eigen matrix +``` +*Remarks(1):* +- We also combine the output equation and its differentiation into an union function, whose usage is the same as the above steps 1-4, and steps 5-9 are shown as follows. +5. Implement the output equation and its differentiation , : +``` +Eigen::Matrix h_dyn_share(state &s, esekfom::dyn_share_datastruct &dyn_share_data) +{ + if(dyn_share_data.converge) {} // this value is true means iteration is converged + if(condition) share_data.valid = false; // the iteration stops before convergence when this value is false if other conditions are satified + dyn_share_data.h_x = H_x; // H_x is the result matrix of the first differentiation + dyn_share_data.h_v = H_v; // H_v is the result matrix of the second differentiation + dyn_share_data.R = R; // R is the measurement noise covariance + dyn_share_data.z = z; // z is the obtained measurement + + Eigen::Matrix h_; + h_(0) = s.pos[0]; + return h_; +} +This function would be called during ekf state update, and the output function and its derivatives, the measurement and the measurement noise would be obtained from this one union function +``` +6. Instantiate an **esekf** object **kf** and initialize it with initial or default state and covariance. +(1) initial state and covariance: +``` +state init_state; +esekfom::esekf::cov init_P; +esekfom::esekf kf(init_state,init_P); +``` +(2) default state and covariance: +``` +esekfom::esekf kf; +``` +7. Deliver the defined models, std int maximum iteration numbers **Maximum_iter**, and the std array for testing convergence **epsi** into the **esekf** object: +``` +double epsi[state_dof] = {0.001}; +fill(epsi, epsi+state_dof, 0.001); // if the absolute of innovation of ekf update is smaller than epso, the update iteration is converged +kf.init_dyn_share(f, df_dx, df_dw, h_dyn_share, Maximum_iter, epsi); +``` +8. In the running time, once an input **in** is received with time interval **dt**, a propagation is executed: +``` +kf.predict(dt, Q, in); // process noise covariance: Q, an Eigen matrix +``` +9. Once a measurement **z** is received, an iterated update is executed: +``` +kf.update_iterated_dyn_share(); +``` + +*Remarks(2):* +- The value of the state **x** and the covariance **P** are able to be changed by functions **change_x()** and **change_P()**: +``` +state set_x; +kf.change_x(set_x); +esekfom::esekf::cov set_P; +kf.change_P(set_P); +``` + +## 4. Usage when the measurement is a changing manifold during the run time. + +Clone the repository: + +``` + git clone https://github.com/hku-mars/IKFoM.git +``` + +1. include the necessary head file: +``` +#include +``` +2. Select and instantiate the primitive manifolds: +``` + typedef MTK::SO3 SO3; // scalar type of variable: double + typedef MTK::vect<3, double> vect3; // dimension of the defined Euclidean variable: 3 + typedef MTK::S2 S2; // length of the S2 variable: 98/10; choose e1 as the original point of rotation: 1 +``` +3. Build system state and input as compound manifolds which are composed of the primitive manifolds: +``` +MTK_BUILD_MANIFOLD(state, // name of compound manifold: state +((vect3, pos)) // ((primitive manifold type, name of variable)) +((vect3, vel)) +((SO3, rot)) +((vect3, bg)) +((vect3, ba)) +((S2, grav)) +((SO3, offset_R_L_I)) +((vect3, offset_T_L_I)) +); +``` +4. Implement the vector field that is defined as , and its differentiation , , where w=0 could be left out: +``` +Eigen::Matrix f(state &s, const input &i) { + Eigen::Matrix res = Eigen::Matrix::Zero(); + res(0) = s.vel[0]; + res(1) = s.vel[1]; + res(2) = s.vel[2]; + return res; +} +Eigen::Matrix df_dx(state &s, const input &i) //notice S2 has length of 3 and dimension of 2 { + Eigen::Matrix cov = Eigen::Matrix::Zero(); + cov.template block<3, 3>(0, 12) = Eigen::Matrix3d::Identity(); + return cov; +} +Eigen::Matrix df_dw(state &s, const input &i) { + Eigen::Matrix cov = Eigen::Matrix::Zero(); + cov.template block<3, 3>(12, 3) = -s.rot.toRotationMatrix(); + return cov; +} +``` +Those functions would be called during ekf state predict + +5. Implement the differentiation of the output equation , : +``` +Eigen::Matrix dh_dx(state &s, bool &valid) {} //the iteration stops before convergence when valid is false +Eigen::Matrix dh_dv(state &s, bool &valid) {} +``` +Those functions would be called during ekf state update + +6. Instantiate an **esekf** object **kf** and initialize it with initial or default state and covariance. + +(1) initial state and covariance: +``` +state init_state; +esekfom::esekf::cov init_P; +esekfom::esekf kf(init_state,init_P); +``` +(2) +``` +esekfom::esekf kf; +``` +Where **process_noise_dof** is the dimension of process noise, of type of std int + +7. Deliver the defined models, std int maximum iteration numbers **Maximum_iter**, and the std array for testing convergence **epsi** into the **esekf** object: +``` +double epsi[state_dof] = {0.001}; +fill(epsi, epsi+state_dof, 0.001); // if the absolute of innovation of ekf update is smaller than epso, the update iteration is converged +kf.init_dyn_runtime(f, df_dx, df_dw, dh_dx, dh_dv, Maximum_iter, epsi); +``` +8. In the running time, once an input **in** is received with time interval **dt**, a propagation is executed: +``` +kf.predict(dt, Q, in); // process noise covariance: Q +``` +9. Once a measurement **z** is received, build system measurement as compound manifolds following step 3 and implement the output equation : +``` +measurement h(state &s, bool &valid) //the iteration stops before convergence when valid is false +{ + if (condition) valid = false; // the update iteration could be stopped when the condition other than convergence is satisfied + measurement h_; + h_.pos = s.pos; + return h_; +} +``` +then an iterated update is executed: +``` +kf.update_iterated_dyn_runtime(z, R, h); // measurement noise covariance: R, an Eigen matrix +``` +*Remarks(1):* +- We also combine the output equation and its differentiation into an union function, whose usage is the same as the above steps 1-4, and steps 5-9 are shown as follows. +5. Instantiate an **esekf** object **kf** and initialize it with initial or default state and covariance. + +(1) initial state and covariance: +``` +state init_state; +esekfom::esekf::cov init_P; +esekfom::esekf kf(init_state,init_P); +``` +(2) default state and covariance: +``` +esekfom::esekf kf; +``` +6. Deliver the defined models, std int maximum iteration numbers **Maximum_iter**, and the std array for testing convergence **epsi** into the **esekf** object: +``` +double epsi[state_dof] = {0.001}; +fill(epsi, epsi+state_dof, 0.001); // if the absolute of innovation of ekf update is smaller than epso, the update iteration is converged +kf.init_dyn_runtime_share(f, df_dx, df_dw, Maximum_iter, epsi); +``` +7. In the running time, once an input **in** is received with time interval **dt**, a propagation is executed: +``` +kf.predict(dt, Q, in); // process noise covariance: Q. an Eigen matrix +``` +8. Once a measurement **z** is received, build system measurement as compound manifolds following step 3 and implement the output equation and its differentiation , : +``` +measurement h_dyn_runtime_share(state &s, esekfom::dyn_runtime_share_datastruct &dyn_runtime_share_data) +{ + if(dyn_runtime_share_data.converge) {} // this value is true means iteration is converged + if(condition) dyn_runtime_share_data.valid = false; // the iteration stops before convergence when this value is false, if conditions other than convergence is satisfied + dyn_runtime_share_data.h_x = H_x; // H_x is the result matrix of the first differentiation + dyn_runtime_share_data.h_v = H_v; // H_v is the result matrix of the second differentiation + dyn_runtime_share_data.R = R; // R is the measurement noise covariance + + measurement h_; + h_.pos = s.pos; + return h_; +} +``` +This function would be called during ekf state update, and the output function and its derivatives, the measurement and the measurement noise would be obtained from this one union function + +then an iterated update is executed: +``` +kf.update_iterated_dyn_runtime_share(z, h_dyn_runtime_share); +``` + +*Remarks(2):* +- The value of the state **x** and the covariance **P** are able to be changed by functions **change_x()** and **change_P()**: +``` +state set_x; +kf.change_x(set_x); +esekfom::esekf::cov set_P; +kf.change_P(set_P); +``` + +## 5. Run the sample +Clone the repository: + +``` + git clone https://github.com/hku-mars/IKFoM.git +``` +In the **Samples** file folder, there is the scource code that applys the **IKFoM** on the original source code from [FAST LIO](https://github.com/hku-mars/FAST_LIO). Please follow the README.md shown in that repository excepting the step **2. Build**, which is modified as: +``` +cd ~/catkin_ws/src +cp -r ~/IKFoM/Samples/FAST_LIO-stable FAST_LIO-stable +cd .. +catkin_make +source devel/setup.bash +``` + +## 6.Acknowledgments +Thanks for C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds. + diff --git a/point_lio_ros2/include/common_lib.h b/point_lio_ros2/include/common_lib.h new file mode 100644 index 0000000..a3ef8e5 --- /dev/null +++ b/point_lio_ros2/include/common_lib.h @@ -0,0 +1,189 @@ +#ifndef COMMON_LIB_H +#define COMMON_LIB_H + +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; +using namespace Eigen; + +#define PI_M (3.14159265358) +#define G_m_s2 (9.81) // Gravity const in GuangDong/China +#define DIM_STATE (18) // Dimension of states (Let Dim(SO(3)) = 3) +#define DIM_PROC_N (12) // Dimension of process noise (Let Dim(SO(3)) = 3) +#define CUBE_LEN (6.0) +#define LIDAR_SP_LEN (2) +#define INIT_COV (0.0001) +#define NUM_MATCH_POINTS (5) +#define MAX_MEAS_DIM (10000) + +#define VEC_FROM_ARRAY(v) v[0],v[1],v[2] +#define VEC_FROM_ARRAY_SIX(v) v[0],v[1],v[2],v[3],v[4],v[5] +#define MAT_FROM_ARRAY(v) v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8] +#define CONSTRAIN(v,min,max) ((v>min)?((v (mat.data(), mat.data() + mat.rows() * mat.cols()) +#define DEBUG_FILE_DIR(name) (string(string(ROOT_DIR) + "Log/"+ name)) + +typedef pcl::PointXYZINormal PointType; +typedef pcl::PointXYZRGB PointTypeRGB; +typedef pcl::PointCloud PointCloudXYZI; +typedef pcl::PointCloud PointCloudXYZRGB; +typedef vector> PointVector; +typedef Vector3d V3D; +typedef Matrix3d M3D; +typedef Vector3f V3F; +typedef Matrix3f M3F; + +#define MD(a,b) Matrix +#define VD(a) Matrix +#define MF(a,b) Matrix +#define VF(a) Matrix + +const M3D Eye3d(M3D::Identity()); +const M3F Eye3f(M3F::Identity()); +const V3D Zero3d(0, 0, 0); +const V3F Zero3f(0, 0, 0); + +struct MeasureGroup // Lidar data and imu dates for the curent process +{ + MeasureGroup() + { + lidar_beg_time = 0.0; + lidar_last_time = 0.0; + this->lidar.reset(new PointCloudXYZI()); + }; + double lidar_beg_time; + double lidar_last_time; + PointCloudXYZI::Ptr lidar; + deque imu{}; +}; + +template +T calc_dist(PointType p1, PointType p2){ + T d = (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z); + return d; +} + +template +T calc_dist(Eigen::Vector3d p1, PointType p2){ + T d = (p1(0) - p2.x) * (p1(0) - p2.x) + (p1(1) - p2.y) * (p1(1) - p2.y) + (p1(2) - p2.z) * (p1(2) - p2.z); + return d; +} + +template +std::vector time_compressing(const PointCloudXYZI::Ptr &point_cloud) +{ + int points_size = point_cloud->points.size(); + int j = 0; + std::vector time_seq; + // time_seq.clear(); + time_seq.reserve(points_size); + for(int i = 0; i < points_size - 1; i++) + { + j++; + if (point_cloud->points[i+1].curvature > point_cloud->points[i].curvature) + { + time_seq.emplace_back(j); + j = 0; + } + } + if (j == 0) + { + time_seq.emplace_back(1); + } + else + { + time_seq.emplace_back(j+1); + } + return time_seq; +} + +/* comment +plane equation: Ax + By + Cz + D = 0 +convert to: A/D*x + B/D*y + C/D*z = -1 +solve: A0*x0 = b0 +where A0_i = [x_i, y_i, z_i], x0 = [A/D, B/D, C/D]^T, b0 = [-1, ..., -1]^T +normvec: normalized x0 +*/ +template +bool esti_normvector(Matrix &normvec, const PointVector &point, const T &threshold, const int &point_num) +{ + MatrixXf A(point_num, 3); + MatrixXf b(point_num, 1); + b.setOnes(); + b *= -1.0f; + + for (int j = 0; j < point_num; j++) + { + A(j,0) = point[j].x; + A(j,1) = point[j].y; + A(j,2) = point[j].z; + } + normvec = A.colPivHouseholderQr().solve(b); + + for (int j = 0; j < point_num; j++) + { + if (fabs(normvec(0) * point[j].x + normvec(1) * point[j].y + normvec(2) * point[j].z + 1.0f) > threshold) + { + return false; + } + } + + normvec.normalize(); + return true; +} + +template +bool esti_plane(Matrix &pca_result, const PointVector &point, const T &threshold) +{ + Matrix A; + Matrix b; + A.setZero(); + b.setOnes(); + b *= -1.0f; + + for (int j = 0; j < NUM_MATCH_POINTS; j++) + { + A(j,0) = point[j].x; + A(j,1) = point[j].y; + A(j,2) = point[j].z; + } + + Matrix normvec = A.colPivHouseholderQr().solve(b); + + T n = normvec.norm(); + pca_result(0) = normvec(0) / n; + pca_result(1) = normvec(1) / n; + pca_result(2) = normvec(2) / n; + pca_result(3) = 1.0 / n; + + for (int j = 0; j < NUM_MATCH_POINTS; j++) + { + if (fabs(pca_result(0) * point[j].x + pca_result(1) * point[j].y + pca_result(2) * point[j].z + pca_result(3)) > threshold) + { + return false; + } + } + return true; +} + +inline double get_time_sec(const builtin_interfaces::msg::Time &time) +{ + return rclcpp::Time(time).seconds(); +} + +inline rclcpp::Time get_ros_time(double timestamp) +{ + int32_t sec = std::floor(timestamp); + auto nanosec_d = (timestamp - std::floor(timestamp)) * 1e9; + uint32_t nanosec = nanosec_d; + return rclcpp::Time(sec, nanosec); +} + +#endif \ No newline at end of file diff --git a/point_lio_ros2/include/ikd-Tree/README.md b/point_lio_ros2/include/ikd-Tree/README.md new file mode 100644 index 0000000..e113a91 --- /dev/null +++ b/point_lio_ros2/include/ikd-Tree/README.md @@ -0,0 +1,2 @@ +# ikd-Tree +ikd-Tree is an incremental k-d tree for robotic applications. diff --git a/point_lio_ros2/include/ikd-Tree/ikd_Tree.cpp b/point_lio_ros2/include/ikd-Tree/ikd_Tree.cpp new file mode 100644 index 0000000..e8c4e86 --- /dev/null +++ b/point_lio_ros2/include/ikd-Tree/ikd_Tree.cpp @@ -0,0 +1,1728 @@ +#include "ikd_Tree.h" + +/* +Description: ikd-Tree: an incremental k-d tree for robotic applications +Author: Yixi Cai +email: yixicai@connect.hku.hk +*/ + +template +KD_TREE::KD_TREE(float delete_param, float balance_param, float box_length) +{ + delete_criterion_param = delete_param; + balance_criterion_param = balance_param; + downsample_size = box_length; + Rebuild_Logger.clear(); + termination_flag = false; + start_thread(); +} + +template +KD_TREE::~KD_TREE() +{ + stop_thread(); + Delete_Storage_Disabled = true; + delete_tree_nodes(&Root_Node); + PointVector().swap(PCL_Storage); + Rebuild_Logger.clear(); +} + + + +template +void KD_TREE::InitializeKDTree(float delete_param, float balance_param, float box_length) +{ + Set_delete_criterion_param(delete_param); + Set_balance_criterion_param(balance_param); + set_downsample_param(box_length); +} + +template +void KD_TREE::InitTreeNode(KD_TREE_NODE *root) +{ + root->point.x = 0.0f; + root->point.y = 0.0f; + root->point.z = 0.0f; + root->node_range_x[0] = 0.0f; + root->node_range_x[1] = 0.0f; + root->node_range_y[0] = 0.0f; + root->node_range_y[1] = 0.0f; + root->node_range_z[0] = 0.0f; + root->node_range_z[1] = 0.0f; + root->radius_sq = 0.0f; + root->division_axis = 0; + root->father_ptr = nullptr; + root->left_son_ptr = nullptr; + root->right_son_ptr = nullptr; + root->TreeSize = 0; + root->invalid_point_num = 0; + root->down_del_num = 0; + root->point_deleted = false; + root->tree_deleted = false; + root->need_push_down_to_left = false; + root->need_push_down_to_right = false; + root->point_downsample_deleted = false; + root->working_flag = false; + pthread_mutex_init(&(root->push_down_mutex_lock), NULL); +} + +template +int KD_TREE::size() +{ + int s = 0; + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + if (Root_Node != nullptr) + { + return Root_Node->TreeSize; + } + else + { + return 0; + } + } + else + { + if (!pthread_mutex_trylock(&working_flag_mutex)) + { + s = Root_Node->TreeSize; + pthread_mutex_unlock(&working_flag_mutex); + return s; + } + else + { + return Treesize_tmp; + } + } +} + +template +BoxPointType KD_TREE::tree_range() +{ + BoxPointType range; + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + if (Root_Node != nullptr) + { + range.vertex_min[0] = Root_Node->node_range_x[0]; + range.vertex_min[1] = Root_Node->node_range_y[0]; + range.vertex_min[2] = Root_Node->node_range_z[0]; + range.vertex_max[0] = Root_Node->node_range_x[1]; + range.vertex_max[1] = Root_Node->node_range_y[1]; + range.vertex_max[2] = Root_Node->node_range_z[1]; + } + else + { + memset(&range, 0, sizeof(range)); + } + } + else + { + if (!pthread_mutex_trylock(&working_flag_mutex)) + { + range.vertex_min[0] = Root_Node->node_range_x[0]; + range.vertex_min[1] = Root_Node->node_range_y[0]; + range.vertex_min[2] = Root_Node->node_range_z[0]; + range.vertex_max[0] = Root_Node->node_range_x[1]; + range.vertex_max[1] = Root_Node->node_range_y[1]; + range.vertex_max[2] = Root_Node->node_range_z[1]; + pthread_mutex_unlock(&working_flag_mutex); + } + else + { + memset(&range, 0, sizeof(range)); + } + } + return range; +} + +template +int KD_TREE::validnum() +{ + int s = 0; + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + if (Root_Node != nullptr) + return (Root_Node->TreeSize - Root_Node->invalid_point_num); + else + return 0; + } + else + { + if (!pthread_mutex_trylock(&working_flag_mutex)) + { + s = Root_Node->TreeSize - Root_Node->invalid_point_num; + pthread_mutex_unlock(&working_flag_mutex); + return s; + } + else + { + return -1; + } + } +} + +template +void KD_TREE::root_alpha(float &alpha_bal, float &alpha_del) +{ + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + alpha_bal = Root_Node->alpha_bal; + alpha_del = Root_Node->alpha_del; + return; + } + else + { + if (!pthread_mutex_trylock(&working_flag_mutex)) + { + alpha_bal = Root_Node->alpha_bal; + alpha_del = Root_Node->alpha_del; + pthread_mutex_unlock(&working_flag_mutex); + return; + } + else + { + alpha_bal = alpha_bal_tmp; + alpha_del = alpha_del_tmp; + return; + } + } +} + +template +void KD_TREE::start_thread() +{ + pthread_mutex_init(&termination_flag_mutex_lock, NULL); + pthread_mutex_init(&rebuild_ptr_mutex_lock, NULL); + pthread_mutex_init(&rebuild_logger_mutex_lock, NULL); + pthread_mutex_init(&points_deleted_rebuild_mutex_lock, NULL); + pthread_mutex_init(&working_flag_mutex, NULL); + pthread_mutex_init(&search_flag_mutex, NULL); + pthread_create(&rebuild_thread, NULL, multi_thread_ptr, (void *)this); + printf("Multi thread started \n"); +} + +template +void KD_TREE::stop_thread() +{ + pthread_mutex_lock(&termination_flag_mutex_lock); + termination_flag = true; + pthread_mutex_unlock(&termination_flag_mutex_lock); + if (rebuild_thread) + pthread_join(rebuild_thread, NULL); + pthread_mutex_destroy(&termination_flag_mutex_lock); + pthread_mutex_destroy(&rebuild_logger_mutex_lock); + pthread_mutex_destroy(&rebuild_ptr_mutex_lock); + pthread_mutex_destroy(&points_deleted_rebuild_mutex_lock); + pthread_mutex_destroy(&working_flag_mutex); + pthread_mutex_destroy(&search_flag_mutex); +} + +template +void *KD_TREE::multi_thread_ptr(void *arg) +{ + KD_TREE *handle = (KD_TREE *)arg; + handle->multi_thread_rebuild(); + return nullptr; +} + +template +void KD_TREE::multi_thread_rebuild() +{ + bool terminated = false; + KD_TREE_NODE *father_ptr, **new_node_ptr; + pthread_mutex_lock(&termination_flag_mutex_lock); + terminated = termination_flag; + pthread_mutex_unlock(&termination_flag_mutex_lock); + while (!terminated) + { + pthread_mutex_lock(&rebuild_ptr_mutex_lock); + pthread_mutex_lock(&working_flag_mutex); + if (Rebuild_Ptr != nullptr) + { + /* Traverse and copy */ + if (!Rebuild_Logger.empty()) + { + printf("\n\n\n\n\n\n\n\n\n\n\n ERROR!!! \n\n\n\n\n\n\n\n\n"); + } + rebuild_flag = true; + if (*Rebuild_Ptr == Root_Node) + { + Treesize_tmp = Root_Node->TreeSize; + Validnum_tmp = Root_Node->TreeSize - Root_Node->invalid_point_num; + alpha_bal_tmp = Root_Node->alpha_bal; + alpha_del_tmp = Root_Node->alpha_del; + } + KD_TREE_NODE *old_root_node = (*Rebuild_Ptr); + father_ptr = (*Rebuild_Ptr)->father_ptr; + PointVector().swap(Rebuild_PCL_Storage); + // Lock Search + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter != 0) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter = -1; + pthread_mutex_unlock(&search_flag_mutex); + // Lock deleted points cache + pthread_mutex_lock(&points_deleted_rebuild_mutex_lock); + flatten(*Rebuild_Ptr, Rebuild_PCL_Storage, MULTI_THREAD_REC); + // Unlock deleted points cache + pthread_mutex_unlock(&points_deleted_rebuild_mutex_lock); + // Unlock Search + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter = 0; + pthread_mutex_unlock(&search_flag_mutex); + pthread_mutex_unlock(&working_flag_mutex); + /* Rebuild and update missed operations*/ + Operation_Logger_Type Operation; + KD_TREE_NODE *new_root_node = nullptr; + if (int(Rebuild_PCL_Storage.size()) > 0) + { + BuildTree(&new_root_node, 0, Rebuild_PCL_Storage.size() - 1, Rebuild_PCL_Storage); + // Rebuild has been done. Updates the blocked operations into the new tree + pthread_mutex_lock(&working_flag_mutex); + pthread_mutex_lock(&rebuild_logger_mutex_lock); + int tmp_counter = 0; + while (!Rebuild_Logger.empty()) + { + Operation = Rebuild_Logger.front(); + max_queue_size = max(max_queue_size, Rebuild_Logger.size()); + Rebuild_Logger.pop(); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + pthread_mutex_unlock(&working_flag_mutex); + run_operation(&new_root_node, Operation); + tmp_counter++; + if (tmp_counter % 10 == 0) + usleep(1); + pthread_mutex_lock(&working_flag_mutex); + pthread_mutex_lock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + /* Replace to original tree*/ + // pthread_mutex_lock(&working_flag_mutex); + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter != 0) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter = -1; + pthread_mutex_unlock(&search_flag_mutex); + if (father_ptr->left_son_ptr == *Rebuild_Ptr) + { + father_ptr->left_son_ptr = new_root_node; + } + else if (father_ptr->right_son_ptr == *Rebuild_Ptr) + { + father_ptr->right_son_ptr = new_root_node; + } + else + { + throw "Error: Father ptr incompatible with current node\n"; + } + if (new_root_node != nullptr) + new_root_node->father_ptr = father_ptr; + (*Rebuild_Ptr) = new_root_node; + int valid_old = old_root_node->TreeSize - old_root_node->invalid_point_num; + int valid_new = new_root_node->TreeSize - new_root_node->invalid_point_num; + if (father_ptr == STATIC_ROOT_NODE) + Root_Node = STATIC_ROOT_NODE->left_son_ptr; + KD_TREE_NODE *update_root = *Rebuild_Ptr; + while (update_root != nullptr && update_root != Root_Node) + { + update_root = update_root->father_ptr; + if (update_root->working_flag) + break; + if (update_root == update_root->father_ptr->left_son_ptr && update_root->father_ptr->need_push_down_to_left) + break; + if (update_root == update_root->father_ptr->right_son_ptr && update_root->father_ptr->need_push_down_to_right) + break; + Update(update_root); + } + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter = 0; + pthread_mutex_unlock(&search_flag_mutex); + Rebuild_Ptr = nullptr; + pthread_mutex_unlock(&working_flag_mutex); + rebuild_flag = false; + /* Delete discarded tree nodes */ + delete_tree_nodes(&old_root_node); + } + else + { + pthread_mutex_unlock(&working_flag_mutex); + } + pthread_mutex_unlock(&rebuild_ptr_mutex_lock); + pthread_mutex_lock(&termination_flag_mutex_lock); + terminated = termination_flag; + pthread_mutex_unlock(&termination_flag_mutex_lock); + usleep(100); + } + printf("Rebuild thread terminated normally\n"); +} + +template +void KD_TREE::run_operation(KD_TREE_NODE **root, Operation_Logger_Type operation) +{ + switch (operation.op) + { + case ADD_POINT: + Add_by_point(root, operation.point, false, (*root)->division_axis); + break; + case ADD_BOX: + Add_by_range(root, operation.boxpoint, false); + break; + case DELETE_POINT: + Delete_by_point(root, operation.point, false); + break; + case DELETE_BOX: + Delete_by_range(root, operation.boxpoint, false, false); + break; + case DOWNSAMPLE_DELETE: + Delete_by_range(root, operation.boxpoint, false, true); + break; + case PUSH_DOWN: + (*root)->tree_downsample_deleted |= operation.tree_downsample_deleted; + (*root)->point_downsample_deleted |= operation.tree_downsample_deleted; + (*root)->tree_deleted = operation.tree_deleted || (*root)->tree_downsample_deleted; + (*root)->point_deleted = (*root)->tree_deleted || (*root)->point_downsample_deleted; + if (operation.tree_downsample_deleted) + (*root)->down_del_num = (*root)->TreeSize; + if (operation.tree_deleted) + (*root)->invalid_point_num = (*root)->TreeSize; + else + (*root)->invalid_point_num = (*root)->down_del_num; + (*root)->need_push_down_to_left = true; + (*root)->need_push_down_to_right = true; + break; + default: + break; + } +} + +template +void KD_TREE::Build(PointVector point_cloud) +{ + if (Root_Node != nullptr) + { + delete_tree_nodes(&Root_Node); + } + if (point_cloud.size() == 0) + return; + STATIC_ROOT_NODE = new KD_TREE_NODE; + InitTreeNode(STATIC_ROOT_NODE); + BuildTree(&STATIC_ROOT_NODE->left_son_ptr, 0, point_cloud.size() - 1, point_cloud); + Update(STATIC_ROOT_NODE); + STATIC_ROOT_NODE->TreeSize = 0; + Root_Node = STATIC_ROOT_NODE->left_son_ptr; +} + +template +void KD_TREE::Nearest_Search(PointType point, int k_nearest, PointVector &Nearest_Points, vector &Point_Distance, float max_dist) +{ + MANUAL_HEAP q(2 * k_nearest); + q.clear(); + vector().swap(Point_Distance); + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + Search(Root_Node, k_nearest, point, q, max_dist); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter == -1) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter += 1; + pthread_mutex_unlock(&search_flag_mutex); + Search(Root_Node, k_nearest, point, q, max_dist); + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter -= 1; + pthread_mutex_unlock(&search_flag_mutex); + } + int k_found = min(k_nearest, int(q.size())); + PointVector().swap(Nearest_Points); + vector().swap(Point_Distance); + for (int i = 0; i < k_found; i++) + { + Nearest_Points.insert(Nearest_Points.begin(), q.top().point); + Point_Distance.insert(Point_Distance.begin(), q.top().dist); + q.pop(); + } + return; +} + +template +void KD_TREE::Box_Search(const BoxPointType &Box_of_Point, PointVector &Storage) +{ + Storage.clear(); + Search_by_range(Root_Node, Box_of_Point, Storage); +} + +template +void KD_TREE::Radius_Search(PointType point, const float radius, PointVector &Storage) +{ + Storage.clear(); + Search_by_radius(Root_Node, point, radius, Storage); +} + +template +int KD_TREE::Add_Points(PointVector &PointToAdd, bool downsample_on) +{ + int NewPointSize = PointToAdd.size(); + int tree_size = size(); + BoxPointType Box_of_Point; + PointType downsample_result, mid_point; + bool downsample_switch = downsample_on && DOWNSAMPLE_SWITCH; + float min_dist, tmp_dist; + int tmp_counter = 0; + for (int i = 0; i < PointToAdd.size(); i++) + { + if (downsample_switch) + { + Box_of_Point.vertex_min[0] = floor(PointToAdd[i].x / downsample_size) * downsample_size; + Box_of_Point.vertex_max[0] = Box_of_Point.vertex_min[0] + downsample_size; + Box_of_Point.vertex_min[1] = floor(PointToAdd[i].y / downsample_size) * downsample_size; + Box_of_Point.vertex_max[1] = Box_of_Point.vertex_min[1] + downsample_size; + Box_of_Point.vertex_min[2] = floor(PointToAdd[i].z / downsample_size) * downsample_size; + Box_of_Point.vertex_max[2] = Box_of_Point.vertex_min[2] + downsample_size; + mid_point.x = Box_of_Point.vertex_min[0] + (Box_of_Point.vertex_max[0] - Box_of_Point.vertex_min[0]) / 2.0; + mid_point.y = Box_of_Point.vertex_min[1] + (Box_of_Point.vertex_max[1] - Box_of_Point.vertex_min[1]) / 2.0; + mid_point.z = Box_of_Point.vertex_min[2] + (Box_of_Point.vertex_max[2] - Box_of_Point.vertex_min[2]) / 2.0; + PointVector().swap(Downsample_Storage); + Search_by_range(Root_Node, Box_of_Point, Downsample_Storage); + min_dist = calc_dist(PointToAdd[i], mid_point); + downsample_result = PointToAdd[i]; + for (int index = 0; index < Downsample_Storage.size(); index++) + { + tmp_dist = calc_dist(Downsample_Storage[index], mid_point); + if (tmp_dist < min_dist) + { + min_dist = tmp_dist; + downsample_result = Downsample_Storage[index]; + } + } + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + if (Downsample_Storage.size() > 1 || same_point(PointToAdd[i], downsample_result)) + { + if (Downsample_Storage.size() > 0) + Delete_by_range(&Root_Node, Box_of_Point, true, true); + Add_by_point(&Root_Node, downsample_result, true, Root_Node->division_axis); + tmp_counter++; + } + } + else + { + if (Downsample_Storage.size() > 1 || same_point(PointToAdd[i], downsample_result)) + { + Operation_Logger_Type operation_delete, operation; + operation_delete.boxpoint = Box_of_Point; + operation_delete.op = DOWNSAMPLE_DELETE; + operation.point = downsample_result; + operation.op = ADD_POINT; + pthread_mutex_lock(&working_flag_mutex); + if (Downsample_Storage.size() > 0) + Delete_by_range(&Root_Node, Box_of_Point, false, true); + Add_by_point(&Root_Node, downsample_result, false, Root_Node->division_axis); + tmp_counter++; + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + if (Downsample_Storage.size() > 0) + Rebuild_Logger.push(operation_delete); + Rebuild_Logger.push(operation); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + }; + } + } + else + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + Add_by_point(&Root_Node, PointToAdd[i], true, Root_Node->division_axis); + } + else + { + Operation_Logger_Type operation; + operation.point = PointToAdd[i]; + operation.op = ADD_POINT; + pthread_mutex_lock(&working_flag_mutex); + Add_by_point(&Root_Node, PointToAdd[i], false, Root_Node->division_axis); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(operation); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + } + return tmp_counter; +} + +template +void KD_TREE::Add_Point_Boxes(vector &BoxPoints) +{ + for (int i = 0; i < BoxPoints.size(); i++) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + Add_by_range(&Root_Node, BoxPoints[i], true); + } + else + { + Operation_Logger_Type operation; + operation.boxpoint = BoxPoints[i]; + operation.op = ADD_BOX; + pthread_mutex_lock(&working_flag_mutex); + Add_by_range(&Root_Node, BoxPoints[i], false); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(operation); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + return; +} + +template +void KD_TREE::Delete_Points(PointVector &PointToDel) +{ + for (int i = 0; i < PointToDel.size(); i++) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + Delete_by_point(&Root_Node, PointToDel[i], true); + } + else + { + Operation_Logger_Type operation; + operation.point = PointToDel[i]; + operation.op = DELETE_POINT; + pthread_mutex_lock(&working_flag_mutex); + Delete_by_point(&Root_Node, PointToDel[i], false); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(operation); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + return; +} + +template +int KD_TREE::Delete_Point_Boxes(vector &BoxPoints) +{ + int tmp_counter = 0; + for (int i = 0; i < BoxPoints.size(); i++) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != Root_Node) + { + tmp_counter += Delete_by_range(&Root_Node, BoxPoints[i], true, false); + } + else + { + Operation_Logger_Type operation; + operation.boxpoint = BoxPoints[i]; + operation.op = DELETE_BOX; + pthread_mutex_lock(&working_flag_mutex); + tmp_counter += Delete_by_range(&Root_Node, BoxPoints[i], false, false); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(operation); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + return tmp_counter; +} + +template +void KD_TREE::acquire_removed_points(PointVector &removed_points) +{ + pthread_mutex_lock(&points_deleted_rebuild_mutex_lock); + for (int i = 0; i < Points_deleted.size(); i++) + { + removed_points.push_back(Points_deleted[i]); + } + for (int i = 0; i < Multithread_Points_deleted.size(); i++) + { + removed_points.push_back(Multithread_Points_deleted[i]); + } + Points_deleted.clear(); + Multithread_Points_deleted.clear(); + pthread_mutex_unlock(&points_deleted_rebuild_mutex_lock); + return; +} + +template +void KD_TREE::BuildTree(KD_TREE_NODE **root, int l, int r, PointVector &Storage) +{ + if (l > r) + return; + *root = new KD_TREE_NODE; + InitTreeNode(*root); + int mid = (l + r) >> 1; + int div_axis = 0; + int i; + // Find the best division Axis + float min_value[3] = {INFINITY, INFINITY, INFINITY}; + float max_value[3] = {-INFINITY, -INFINITY, -INFINITY}; + float dim_range[3] = {0, 0, 0}; + for (i = l; i <= r; i++) + { + min_value[0] = min(min_value[0], Storage[i].x); + min_value[1] = min(min_value[1], Storage[i].y); + min_value[2] = min(min_value[2], Storage[i].z); + max_value[0] = max(max_value[0], Storage[i].x); + max_value[1] = max(max_value[1], Storage[i].y); + max_value[2] = max(max_value[2], Storage[i].z); + } + // Select the longest dimension as division axis + for (i = 0; i < 3; i++) + dim_range[i] = max_value[i] - min_value[i]; + for (i = 1; i < 3; i++) + if (dim_range[i] > dim_range[div_axis]) + div_axis = i; + // Divide by the division axis and recursively build. + + (*root)->division_axis = div_axis; + switch (div_axis) + { + case 0: + nth_element(begin(Storage) + l, begin(Storage) + mid, begin(Storage) + r + 1, point_cmp_x); + break; + case 1: + nth_element(begin(Storage) + l, begin(Storage) + mid, begin(Storage) + r + 1, point_cmp_y); + break; + case 2: + nth_element(begin(Storage) + l, begin(Storage) + mid, begin(Storage) + r + 1, point_cmp_z); + break; + default: + nth_element(begin(Storage) + l, begin(Storage) + mid, begin(Storage) + r + 1, point_cmp_x); + break; + } + (*root)->point = Storage[mid]; + KD_TREE_NODE *left_son = nullptr, *right_son = nullptr; + BuildTree(&left_son, l, mid - 1, Storage); + BuildTree(&right_son, mid + 1, r, Storage); + (*root)->left_son_ptr = left_son; + (*root)->right_son_ptr = right_son; + Update((*root)); + return; +} + +template +void KD_TREE::Rebuild(KD_TREE_NODE **root) +{ + KD_TREE_NODE *father_ptr; + if ((*root)->TreeSize >= Multi_Thread_Rebuild_Point_Num) + { + if (!pthread_mutex_trylock(&rebuild_ptr_mutex_lock)) + { + if (Rebuild_Ptr == nullptr || ((*root)->TreeSize > (*Rebuild_Ptr)->TreeSize)) + { + Rebuild_Ptr = root; + } + pthread_mutex_unlock(&rebuild_ptr_mutex_lock); + } + } + else + { + father_ptr = (*root)->father_ptr; + int size_rec = (*root)->TreeSize; + PCL_Storage.clear(); + flatten(*root, PCL_Storage, DELETE_POINTS_REC); + delete_tree_nodes(root); + BuildTree(root, 0, PCL_Storage.size() - 1, PCL_Storage); + if (*root != nullptr) + (*root)->father_ptr = father_ptr; + if (*root == Root_Node) + STATIC_ROOT_NODE->left_son_ptr = *root; + } + return; +} + +template +int KD_TREE::Delete_by_range(KD_TREE_NODE **root, BoxPointType boxpoint, bool allow_rebuild, bool is_downsample) +{ + if ((*root) == nullptr || (*root)->tree_deleted) + return 0; + (*root)->working_flag = true; + Push_Down(*root); + int tmp_counter = 0; + if (boxpoint.vertex_max[0] <= (*root)->node_range_x[0] || boxpoint.vertex_min[0] > (*root)->node_range_x[1]) + return 0; + if (boxpoint.vertex_max[1] <= (*root)->node_range_y[0] || boxpoint.vertex_min[1] > (*root)->node_range_y[1]) + return 0; + if (boxpoint.vertex_max[2] <= (*root)->node_range_z[0] || boxpoint.vertex_min[2] > (*root)->node_range_z[1]) + return 0; + if (boxpoint.vertex_min[0] <= (*root)->node_range_x[0] && boxpoint.vertex_max[0] > (*root)->node_range_x[1] && boxpoint.vertex_min[1] <= (*root)->node_range_y[0] && boxpoint.vertex_max[1] > (*root)->node_range_y[1] && boxpoint.vertex_min[2] <= (*root)->node_range_z[0] && boxpoint.vertex_max[2] > (*root)->node_range_z[1]) + { + (*root)->tree_deleted = true; + (*root)->point_deleted = true; + (*root)->need_push_down_to_left = true; + (*root)->need_push_down_to_right = true; + tmp_counter = (*root)->TreeSize - (*root)->invalid_point_num; + (*root)->invalid_point_num = (*root)->TreeSize; + if (is_downsample) + { + (*root)->tree_downsample_deleted = true; + (*root)->point_downsample_deleted = true; + (*root)->down_del_num = (*root)->TreeSize; + } + return tmp_counter; + } + if (!(*root)->point_deleted && boxpoint.vertex_min[0] <= (*root)->point.x && boxpoint.vertex_max[0] > (*root)->point.x && boxpoint.vertex_min[1] <= (*root)->point.y && boxpoint.vertex_max[1] > (*root)->point.y && boxpoint.vertex_min[2] <= (*root)->point.z && boxpoint.vertex_max[2] > (*root)->point.z) + { + (*root)->point_deleted = true; + tmp_counter += 1; + if (is_downsample) + (*root)->point_downsample_deleted = true; + } + Operation_Logger_Type delete_box_log; + struct timespec Timeout; + if (is_downsample) + delete_box_log.op = DOWNSAMPLE_DELETE; + else + delete_box_log.op = DELETE_BOX; + delete_box_log.boxpoint = boxpoint; + if ((Rebuild_Ptr == nullptr) || (*root)->left_son_ptr != *Rebuild_Ptr) + { + tmp_counter += Delete_by_range(&((*root)->left_son_ptr), boxpoint, allow_rebuild, is_downsample); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + tmp_counter += Delete_by_range(&((*root)->left_son_ptr), boxpoint, false, is_downsample); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(delete_box_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + if ((Rebuild_Ptr == nullptr) || (*root)->right_son_ptr != *Rebuild_Ptr) + { + tmp_counter += Delete_by_range(&((*root)->right_son_ptr), boxpoint, allow_rebuild, is_downsample); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + tmp_counter += Delete_by_range(&((*root)->right_son_ptr), boxpoint, false, is_downsample); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(delete_box_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + Update(*root); + if (Rebuild_Ptr != nullptr && *Rebuild_Ptr == *root && (*root)->TreeSize < Multi_Thread_Rebuild_Point_Num) + Rebuild_Ptr = nullptr; + bool need_rebuild = allow_rebuild & Criterion_Check((*root)); + if (need_rebuild) + Rebuild(root); + if ((*root) != nullptr) + (*root)->working_flag = false; + return tmp_counter; +} + +template +void KD_TREE::Delete_by_point(KD_TREE_NODE **root, PointType point, bool allow_rebuild) +{ + if ((*root) == nullptr || (*root)->tree_deleted) + return; + (*root)->working_flag = true; + Push_Down(*root); + if (same_point((*root)->point, point) && !(*root)->point_deleted) + { + (*root)->point_deleted = true; + (*root)->invalid_point_num += 1; + if ((*root)->invalid_point_num == (*root)->TreeSize) + (*root)->tree_deleted = true; + return; + } + Operation_Logger_Type delete_log; + struct timespec Timeout; + delete_log.op = DELETE_POINT; + delete_log.point = point; + if (((*root)->division_axis == 0 && point.x < (*root)->point.x) || ((*root)->division_axis == 1 && point.y < (*root)->point.y) || ((*root)->division_axis == 2 && point.z < (*root)->point.z)) + { + if ((Rebuild_Ptr == nullptr) || (*root)->left_son_ptr != *Rebuild_Ptr) + { + Delete_by_point(&(*root)->left_son_ptr, point, allow_rebuild); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + Delete_by_point(&(*root)->left_son_ptr, point, false); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(delete_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + else + { + if ((Rebuild_Ptr == nullptr) || (*root)->right_son_ptr != *Rebuild_Ptr) + { + Delete_by_point(&(*root)->right_son_ptr, point, allow_rebuild); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + Delete_by_point(&(*root)->right_son_ptr, point, false); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(delete_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + Update(*root); + if (Rebuild_Ptr != nullptr && *Rebuild_Ptr == *root && (*root)->TreeSize < Multi_Thread_Rebuild_Point_Num) + Rebuild_Ptr = nullptr; + bool need_rebuild = allow_rebuild & Criterion_Check((*root)); + if (need_rebuild) + Rebuild(root); + if ((*root) != nullptr) + (*root)->working_flag = false; + return; +} + +template +void KD_TREE::Add_by_range(KD_TREE_NODE **root, BoxPointType boxpoint, bool allow_rebuild) +{ + if ((*root) == nullptr) + return; + (*root)->working_flag = true; + Push_Down(*root); + if (boxpoint.vertex_max[0] <= (*root)->node_range_x[0] || boxpoint.vertex_min[0] > (*root)->node_range_x[1]) + return; + if (boxpoint.vertex_max[1] <= (*root)->node_range_y[0] || boxpoint.vertex_min[1] > (*root)->node_range_y[1]) + return; + if (boxpoint.vertex_max[2] <= (*root)->node_range_z[0] || boxpoint.vertex_min[2] > (*root)->node_range_z[1]) + return; + if (boxpoint.vertex_min[0] <= (*root)->node_range_x[0] && boxpoint.vertex_max[0] > (*root)->node_range_x[1] && boxpoint.vertex_min[1] <= (*root)->node_range_y[0] && boxpoint.vertex_max[1] > (*root)->node_range_y[1] && boxpoint.vertex_min[2] <= (*root)->node_range_z[0] && boxpoint.vertex_max[2] > (*root)->node_range_z[1]) + { + (*root)->tree_deleted = false || (*root)->tree_downsample_deleted; + (*root)->point_deleted = false || (*root)->point_downsample_deleted; + (*root)->need_push_down_to_left = true; + (*root)->need_push_down_to_right = true; + (*root)->invalid_point_num = (*root)->down_del_num; + return; + } + if (boxpoint.vertex_min[0] <= (*root)->point.x && boxpoint.vertex_max[0] > (*root)->point.x && boxpoint.vertex_min[1] <= (*root)->point.y && boxpoint.vertex_max[1] > (*root)->point.y && boxpoint.vertex_min[2] <= (*root)->point.z && boxpoint.vertex_max[2] > (*root)->point.z) + { + (*root)->point_deleted = (*root)->point_downsample_deleted; + } + Operation_Logger_Type add_box_log; + struct timespec Timeout; + add_box_log.op = ADD_BOX; + add_box_log.boxpoint = boxpoint; + if ((Rebuild_Ptr == nullptr) || (*root)->left_son_ptr != *Rebuild_Ptr) + { + Add_by_range(&((*root)->left_son_ptr), boxpoint, allow_rebuild); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + Add_by_range(&((*root)->left_son_ptr), boxpoint, false); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(add_box_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + if ((Rebuild_Ptr == nullptr) || (*root)->right_son_ptr != *Rebuild_Ptr) + { + Add_by_range(&((*root)->right_son_ptr), boxpoint, allow_rebuild); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + Add_by_range(&((*root)->right_son_ptr), boxpoint, false); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(add_box_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + Update(*root); + if (Rebuild_Ptr != nullptr && *Rebuild_Ptr == *root && (*root)->TreeSize < Multi_Thread_Rebuild_Point_Num) + Rebuild_Ptr = nullptr; + bool need_rebuild = allow_rebuild & Criterion_Check((*root)); + if (need_rebuild) + Rebuild(root); + if ((*root) != nullptr) + (*root)->working_flag = false; + return; +} + +template +void KD_TREE::Add_by_point(KD_TREE_NODE **root, PointType point, bool allow_rebuild, int father_axis) +{ + if (*root == nullptr) + { + *root = new KD_TREE_NODE; + InitTreeNode(*root); + (*root)->point = point; + (*root)->division_axis = (father_axis + 1) % 3; + Update(*root); + return; + } + (*root)->working_flag = true; + Operation_Logger_Type add_log; + struct timespec Timeout; + add_log.op = ADD_POINT; + add_log.point = point; + Push_Down(*root); + if (((*root)->division_axis == 0 && point.x < (*root)->point.x) || ((*root)->division_axis == 1 && point.y < (*root)->point.y) || ((*root)->division_axis == 2 && point.z < (*root)->point.z)) + { + if ((Rebuild_Ptr == nullptr) || (*root)->left_son_ptr != *Rebuild_Ptr) + { + Add_by_point(&(*root)->left_son_ptr, point, allow_rebuild, (*root)->division_axis); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + Add_by_point(&(*root)->left_son_ptr, point, false, (*root)->division_axis); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(add_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + else + { + if ((Rebuild_Ptr == nullptr) || (*root)->right_son_ptr != *Rebuild_Ptr) + { + Add_by_point(&(*root)->right_son_ptr, point, allow_rebuild, (*root)->division_axis); + } + else + { + pthread_mutex_lock(&working_flag_mutex); + Add_by_point(&(*root)->right_son_ptr, point, false, (*root)->division_axis); + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(add_log); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + pthread_mutex_unlock(&working_flag_mutex); + } + } + Update(*root); + if (Rebuild_Ptr != nullptr && *Rebuild_Ptr == *root && (*root)->TreeSize < Multi_Thread_Rebuild_Point_Num) + Rebuild_Ptr = nullptr; + bool need_rebuild = allow_rebuild & Criterion_Check((*root)); + if (need_rebuild) + Rebuild(root); + if ((*root) != nullptr) + (*root)->working_flag = false; + return; +} + +template +void KD_TREE::Search(KD_TREE_NODE *root, int k_nearest, PointType point, MANUAL_HEAP &q, float max_dist) +{ + if (root == nullptr || root->tree_deleted) + return; + float cur_dist = calc_box_dist(root, point); + float max_dist_sqr = max_dist * max_dist; + if (cur_dist > max_dist_sqr) + return; + int retval; + if (root->need_push_down_to_left || root->need_push_down_to_right) + { + retval = pthread_mutex_trylock(&(root->push_down_mutex_lock)); + if (retval == 0) + { + Push_Down(root); + pthread_mutex_unlock(&(root->push_down_mutex_lock)); + } + else + { + pthread_mutex_lock(&(root->push_down_mutex_lock)); + pthread_mutex_unlock(&(root->push_down_mutex_lock)); + } + } + if (!root->point_deleted) + { + float dist = calc_dist(point, root->point); + if (dist <= max_dist_sqr && (q.size() < k_nearest || dist < q.top().dist)) + { + if (q.size() >= k_nearest) + q.pop(); + PointType_CMP current_point{root->point, dist}; + q.push(current_point); + } + } + int cur_search_counter; + float dist_left_node = calc_box_dist(root->left_son_ptr, point); + float dist_right_node = calc_box_dist(root->right_son_ptr, point); + if (q.size() < k_nearest || dist_left_node < q.top().dist && dist_right_node < q.top().dist) + { + if (dist_left_node <= dist_right_node) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->left_son_ptr) + { + Search(root->left_son_ptr, k_nearest, point, q, max_dist); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter == -1) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter += 1; + pthread_mutex_unlock(&search_flag_mutex); + Search(root->left_son_ptr, k_nearest, point, q, max_dist); + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter -= 1; + pthread_mutex_unlock(&search_flag_mutex); + } + if (q.size() < k_nearest || dist_right_node < q.top().dist) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->right_son_ptr) + { + Search(root->right_son_ptr, k_nearest, point, q, max_dist); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter == -1) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter += 1; + pthread_mutex_unlock(&search_flag_mutex); + Search(root->right_son_ptr, k_nearest, point, q, max_dist); + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter -= 1; + pthread_mutex_unlock(&search_flag_mutex); + } + } + } + else + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->right_son_ptr) + { + Search(root->right_son_ptr, k_nearest, point, q, max_dist); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter == -1) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter += 1; + pthread_mutex_unlock(&search_flag_mutex); + Search(root->right_son_ptr, k_nearest, point, q, max_dist); + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter -= 1; + pthread_mutex_unlock(&search_flag_mutex); + } + if (q.size() < k_nearest || dist_left_node < q.top().dist) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->left_son_ptr) + { + Search(root->left_son_ptr, k_nearest, point, q, max_dist); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter == -1) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter += 1; + pthread_mutex_unlock(&search_flag_mutex); + Search(root->left_son_ptr, k_nearest, point, q, max_dist); + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter -= 1; + pthread_mutex_unlock(&search_flag_mutex); + } + } + } + } + else + { + if (dist_left_node < q.top().dist) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->left_son_ptr) + { + Search(root->left_son_ptr, k_nearest, point, q, max_dist); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter == -1) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter += 1; + pthread_mutex_unlock(&search_flag_mutex); + Search(root->left_son_ptr, k_nearest, point, q, max_dist); + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter -= 1; + pthread_mutex_unlock(&search_flag_mutex); + } + } + if (dist_right_node < q.top().dist) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->right_son_ptr) + { + Search(root->right_son_ptr, k_nearest, point, q, max_dist); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + while (search_mutex_counter == -1) + { + pthread_mutex_unlock(&search_flag_mutex); + usleep(1); + pthread_mutex_lock(&search_flag_mutex); + } + search_mutex_counter += 1; + pthread_mutex_unlock(&search_flag_mutex); + Search(root->right_son_ptr, k_nearest, point, q, max_dist); + pthread_mutex_lock(&search_flag_mutex); + search_mutex_counter -= 1; + pthread_mutex_unlock(&search_flag_mutex); + } + } + } + return; +} + +template +void KD_TREE::Search_by_range(KD_TREE_NODE *root, BoxPointType boxpoint, PointVector &Storage) +{ + if (root == nullptr) + return; + Push_Down(root); + if (boxpoint.vertex_max[0] <= root->node_range_x[0] || boxpoint.vertex_min[0] > root->node_range_x[1]) + return; + if (boxpoint.vertex_max[1] <= root->node_range_y[0] || boxpoint.vertex_min[1] > root->node_range_y[1]) + return; + if (boxpoint.vertex_max[2] <= root->node_range_z[0] || boxpoint.vertex_min[2] > root->node_range_z[1]) + return; + if (boxpoint.vertex_min[0] <= root->node_range_x[0] && boxpoint.vertex_max[0] > root->node_range_x[1] && boxpoint.vertex_min[1] <= root->node_range_y[0] && boxpoint.vertex_max[1] > root->node_range_y[1] && boxpoint.vertex_min[2] <= root->node_range_z[0] && boxpoint.vertex_max[2] > root->node_range_z[1]) + { + flatten(root, Storage, NOT_RECORD); + return; + } + if (boxpoint.vertex_min[0] <= root->point.x && boxpoint.vertex_max[0] > root->point.x && boxpoint.vertex_min[1] <= root->point.y && boxpoint.vertex_max[1] > root->point.y && boxpoint.vertex_min[2] <= root->point.z && boxpoint.vertex_max[2] > root->point.z) + { + if (!root->point_deleted) + Storage.push_back(root->point); + } + if ((Rebuild_Ptr == nullptr) || root->left_son_ptr != *Rebuild_Ptr) + { + Search_by_range(root->left_son_ptr, boxpoint, Storage); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + Search_by_range(root->left_son_ptr, boxpoint, Storage); + pthread_mutex_unlock(&search_flag_mutex); + } + if ((Rebuild_Ptr == nullptr) || root->right_son_ptr != *Rebuild_Ptr) + { + Search_by_range(root->right_son_ptr, boxpoint, Storage); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + Search_by_range(root->right_son_ptr, boxpoint, Storage); + pthread_mutex_unlock(&search_flag_mutex); + } + return; +} + +template +void KD_TREE::Search_by_radius(KD_TREE_NODE *root, PointType point, float radius, PointVector &Storage) +{ + if (root == nullptr) + return; + Push_Down(root); + PointType range_center; + range_center.x = (root->node_range_x[0] + root->node_range_x[1]) * 0.5; + range_center.y = (root->node_range_y[0] + root->node_range_y[1]) * 0.5; + range_center.z = (root->node_range_z[0] + root->node_range_z[1]) * 0.5; + float dist = sqrt(calc_dist(range_center, point)); + if (dist > radius + sqrt(root->radius_sq)) return; + if (dist <= radius - sqrt(root->radius_sq)) + { + flatten(root, Storage, NOT_RECORD); + return; + } + if (!root->point_deleted && calc_dist(root->point, point) <= radius * radius){ + Storage.push_back(root->point); + } + if ((Rebuild_Ptr == nullptr) || root->left_son_ptr != *Rebuild_Ptr) + { + Search_by_radius(root->left_son_ptr, point, radius, Storage); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + Search_by_radius(root->left_son_ptr, point, radius, Storage); + pthread_mutex_unlock(&search_flag_mutex); + } + if ((Rebuild_Ptr == nullptr) || root->right_son_ptr != *Rebuild_Ptr) + { + Search_by_radius(root->right_son_ptr, point, radius, Storage); + } + else + { + pthread_mutex_lock(&search_flag_mutex); + Search_by_radius(root->right_son_ptr, point, radius, Storage); + pthread_mutex_unlock(&search_flag_mutex); + } + return; +} + +template +bool KD_TREE::Criterion_Check(KD_TREE_NODE *root) +{ + if (root->TreeSize <= Minimal_Unbalanced_Tree_Size) + { + return false; + } + float balance_evaluation = 0.0f; + float delete_evaluation = 0.0f; + KD_TREE_NODE *son_ptr = root->left_son_ptr; + if (son_ptr == nullptr) + son_ptr = root->right_son_ptr; + delete_evaluation = float(root->invalid_point_num) / root->TreeSize; + balance_evaluation = float(son_ptr->TreeSize) / (root->TreeSize - 1); + if (delete_evaluation > delete_criterion_param) + { + return true; + } + if (balance_evaluation > balance_criterion_param || balance_evaluation < 1 - balance_criterion_param) + { + return true; + } + return false; +} + +template +void KD_TREE::Push_Down(KD_TREE_NODE *root) +{ + if (root == nullptr) + return; + Operation_Logger_Type operation; + operation.op = PUSH_DOWN; + operation.tree_deleted = root->tree_deleted; + operation.tree_downsample_deleted = root->tree_downsample_deleted; + if (root->need_push_down_to_left && root->left_son_ptr != nullptr) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->left_son_ptr) + { + root->left_son_ptr->tree_downsample_deleted |= root->tree_downsample_deleted; + root->left_son_ptr->point_downsample_deleted |= root->tree_downsample_deleted; + root->left_son_ptr->tree_deleted = root->tree_deleted || root->left_son_ptr->tree_downsample_deleted; + root->left_son_ptr->point_deleted = root->left_son_ptr->tree_deleted || root->left_son_ptr->point_downsample_deleted; + if (root->tree_downsample_deleted) + root->left_son_ptr->down_del_num = root->left_son_ptr->TreeSize; + if (root->tree_deleted) + root->left_son_ptr->invalid_point_num = root->left_son_ptr->TreeSize; + else + root->left_son_ptr->invalid_point_num = root->left_son_ptr->down_del_num; + root->left_son_ptr->need_push_down_to_left = true; + root->left_son_ptr->need_push_down_to_right = true; + root->need_push_down_to_left = false; + } + else + { + pthread_mutex_lock(&working_flag_mutex); + root->left_son_ptr->tree_downsample_deleted |= root->tree_downsample_deleted; + root->left_son_ptr->point_downsample_deleted |= root->tree_downsample_deleted; + root->left_son_ptr->tree_deleted = root->tree_deleted || root->left_son_ptr->tree_downsample_deleted; + root->left_son_ptr->point_deleted = root->left_son_ptr->tree_deleted || root->left_son_ptr->point_downsample_deleted; + if (root->tree_downsample_deleted) + root->left_son_ptr->down_del_num = root->left_son_ptr->TreeSize; + if (root->tree_deleted) + root->left_son_ptr->invalid_point_num = root->left_son_ptr->TreeSize; + else + root->left_son_ptr->invalid_point_num = root->left_son_ptr->down_del_num; + root->left_son_ptr->need_push_down_to_left = true; + root->left_son_ptr->need_push_down_to_right = true; + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(operation); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + root->need_push_down_to_left = false; + pthread_mutex_unlock(&working_flag_mutex); + } + } + if (root->need_push_down_to_right && root->right_son_ptr != nullptr) + { + if (Rebuild_Ptr == nullptr || *Rebuild_Ptr != root->right_son_ptr) + { + root->right_son_ptr->tree_downsample_deleted |= root->tree_downsample_deleted; + root->right_son_ptr->point_downsample_deleted |= root->tree_downsample_deleted; + root->right_son_ptr->tree_deleted = root->tree_deleted || root->right_son_ptr->tree_downsample_deleted; + root->right_son_ptr->point_deleted = root->right_son_ptr->tree_deleted || root->right_son_ptr->point_downsample_deleted; + if (root->tree_downsample_deleted) + root->right_son_ptr->down_del_num = root->right_son_ptr->TreeSize; + if (root->tree_deleted) + root->right_son_ptr->invalid_point_num = root->right_son_ptr->TreeSize; + else + root->right_son_ptr->invalid_point_num = root->right_son_ptr->down_del_num; + root->right_son_ptr->need_push_down_to_left = true; + root->right_son_ptr->need_push_down_to_right = true; + root->need_push_down_to_right = false; + } + else + { + pthread_mutex_lock(&working_flag_mutex); + root->right_son_ptr->tree_downsample_deleted |= root->tree_downsample_deleted; + root->right_son_ptr->point_downsample_deleted |= root->tree_downsample_deleted; + root->right_son_ptr->tree_deleted = root->tree_deleted || root->right_son_ptr->tree_downsample_deleted; + root->right_son_ptr->point_deleted = root->right_son_ptr->tree_deleted || root->right_son_ptr->point_downsample_deleted; + if (root->tree_downsample_deleted) + root->right_son_ptr->down_del_num = root->right_son_ptr->TreeSize; + if (root->tree_deleted) + root->right_son_ptr->invalid_point_num = root->right_son_ptr->TreeSize; + else + root->right_son_ptr->invalid_point_num = root->right_son_ptr->down_del_num; + root->right_son_ptr->need_push_down_to_left = true; + root->right_son_ptr->need_push_down_to_right = true; + if (rebuild_flag) + { + pthread_mutex_lock(&rebuild_logger_mutex_lock); + Rebuild_Logger.push(operation); + pthread_mutex_unlock(&rebuild_logger_mutex_lock); + } + root->need_push_down_to_right = false; + pthread_mutex_unlock(&working_flag_mutex); + } + } + return; +} + +template +void KD_TREE::Update(KD_TREE_NODE *root) +{ + KD_TREE_NODE *left_son_ptr = root->left_son_ptr; + KD_TREE_NODE *right_son_ptr = root->right_son_ptr; + float tmp_range_x[2] = {INFINITY, -INFINITY}; + float tmp_range_y[2] = {INFINITY, -INFINITY}; + float tmp_range_z[2] = {INFINITY, -INFINITY}; + // Update Tree Size + if (left_son_ptr != nullptr && right_son_ptr != nullptr) + { + root->TreeSize = left_son_ptr->TreeSize + right_son_ptr->TreeSize + 1; + root->invalid_point_num = left_son_ptr->invalid_point_num + right_son_ptr->invalid_point_num + (root->point_deleted ? 1 : 0); + root->down_del_num = left_son_ptr->down_del_num + right_son_ptr->down_del_num + (root->point_downsample_deleted ? 1 : 0); + root->tree_downsample_deleted = left_son_ptr->tree_downsample_deleted & right_son_ptr->tree_downsample_deleted & root->point_downsample_deleted; + root->tree_deleted = left_son_ptr->tree_deleted && right_son_ptr->tree_deleted && root->point_deleted; + if (root->tree_deleted || (!left_son_ptr->tree_deleted && !right_son_ptr->tree_deleted && !root->point_deleted)) + { + tmp_range_x[0] = min(min(left_son_ptr->node_range_x[0], right_son_ptr->node_range_x[0]), root->point.x); + tmp_range_x[1] = max(max(left_son_ptr->node_range_x[1], right_son_ptr->node_range_x[1]), root->point.x); + tmp_range_y[0] = min(min(left_son_ptr->node_range_y[0], right_son_ptr->node_range_y[0]), root->point.y); + tmp_range_y[1] = max(max(left_son_ptr->node_range_y[1], right_son_ptr->node_range_y[1]), root->point.y); + tmp_range_z[0] = min(min(left_son_ptr->node_range_z[0], right_son_ptr->node_range_z[0]), root->point.z); + tmp_range_z[1] = max(max(left_son_ptr->node_range_z[1], right_son_ptr->node_range_z[1]), root->point.z); + } + else + { + if (!left_son_ptr->tree_deleted) + { + tmp_range_x[0] = min(tmp_range_x[0], left_son_ptr->node_range_x[0]); + tmp_range_x[1] = max(tmp_range_x[1], left_son_ptr->node_range_x[1]); + tmp_range_y[0] = min(tmp_range_y[0], left_son_ptr->node_range_y[0]); + tmp_range_y[1] = max(tmp_range_y[1], left_son_ptr->node_range_y[1]); + tmp_range_z[0] = min(tmp_range_z[0], left_son_ptr->node_range_z[0]); + tmp_range_z[1] = max(tmp_range_z[1], left_son_ptr->node_range_z[1]); + } + if (!right_son_ptr->tree_deleted) + { + tmp_range_x[0] = min(tmp_range_x[0], right_son_ptr->node_range_x[0]); + tmp_range_x[1] = max(tmp_range_x[1], right_son_ptr->node_range_x[1]); + tmp_range_y[0] = min(tmp_range_y[0], right_son_ptr->node_range_y[0]); + tmp_range_y[1] = max(tmp_range_y[1], right_son_ptr->node_range_y[1]); + tmp_range_z[0] = min(tmp_range_z[0], right_son_ptr->node_range_z[0]); + tmp_range_z[1] = max(tmp_range_z[1], right_son_ptr->node_range_z[1]); + } + if (!root->point_deleted) + { + tmp_range_x[0] = min(tmp_range_x[0], root->point.x); + tmp_range_x[1] = max(tmp_range_x[1], root->point.x); + tmp_range_y[0] = min(tmp_range_y[0], root->point.y); + tmp_range_y[1] = max(tmp_range_y[1], root->point.y); + tmp_range_z[0] = min(tmp_range_z[0], root->point.z); + tmp_range_z[1] = max(tmp_range_z[1], root->point.z); + } + } + } + else if (left_son_ptr != nullptr) + { + root->TreeSize = left_son_ptr->TreeSize + 1; + root->invalid_point_num = left_son_ptr->invalid_point_num + (root->point_deleted ? 1 : 0); + root->down_del_num = left_son_ptr->down_del_num + (root->point_downsample_deleted ? 1 : 0); + root->tree_downsample_deleted = left_son_ptr->tree_downsample_deleted & root->point_downsample_deleted; + root->tree_deleted = left_son_ptr->tree_deleted && root->point_deleted; + if (root->tree_deleted || (!left_son_ptr->tree_deleted && !root->point_deleted)) + { + tmp_range_x[0] = min(left_son_ptr->node_range_x[0], root->point.x); + tmp_range_x[1] = max(left_son_ptr->node_range_x[1], root->point.x); + tmp_range_y[0] = min(left_son_ptr->node_range_y[0], root->point.y); + tmp_range_y[1] = max(left_son_ptr->node_range_y[1], root->point.y); + tmp_range_z[0] = min(left_son_ptr->node_range_z[0], root->point.z); + tmp_range_z[1] = max(left_son_ptr->node_range_z[1], root->point.z); + } + else + { + if (!left_son_ptr->tree_deleted) + { + tmp_range_x[0] = min(tmp_range_x[0], left_son_ptr->node_range_x[0]); + tmp_range_x[1] = max(tmp_range_x[1], left_son_ptr->node_range_x[1]); + tmp_range_y[0] = min(tmp_range_y[0], left_son_ptr->node_range_y[0]); + tmp_range_y[1] = max(tmp_range_y[1], left_son_ptr->node_range_y[1]); + tmp_range_z[0] = min(tmp_range_z[0], left_son_ptr->node_range_z[0]); + tmp_range_z[1] = max(tmp_range_z[1], left_son_ptr->node_range_z[1]); + } + if (!root->point_deleted) + { + tmp_range_x[0] = min(tmp_range_x[0], root->point.x); + tmp_range_x[1] = max(tmp_range_x[1], root->point.x); + tmp_range_y[0] = min(tmp_range_y[0], root->point.y); + tmp_range_y[1] = max(tmp_range_y[1], root->point.y); + tmp_range_z[0] = min(tmp_range_z[0], root->point.z); + tmp_range_z[1] = max(tmp_range_z[1], root->point.z); + } + } + } + else if (right_son_ptr != nullptr) + { + root->TreeSize = right_son_ptr->TreeSize + 1; + root->invalid_point_num = right_son_ptr->invalid_point_num + (root->point_deleted ? 1 : 0); + root->down_del_num = right_son_ptr->down_del_num + (root->point_downsample_deleted ? 1 : 0); + root->tree_downsample_deleted = right_son_ptr->tree_downsample_deleted & root->point_downsample_deleted; + root->tree_deleted = right_son_ptr->tree_deleted && root->point_deleted; + if (root->tree_deleted || (!right_son_ptr->tree_deleted && !root->point_deleted)) + { + tmp_range_x[0] = min(right_son_ptr->node_range_x[0], root->point.x); + tmp_range_x[1] = max(right_son_ptr->node_range_x[1], root->point.x); + tmp_range_y[0] = min(right_son_ptr->node_range_y[0], root->point.y); + tmp_range_y[1] = max(right_son_ptr->node_range_y[1], root->point.y); + tmp_range_z[0] = min(right_son_ptr->node_range_z[0], root->point.z); + tmp_range_z[1] = max(right_son_ptr->node_range_z[1], root->point.z); + } + else + { + if (!right_son_ptr->tree_deleted) + { + tmp_range_x[0] = min(tmp_range_x[0], right_son_ptr->node_range_x[0]); + tmp_range_x[1] = max(tmp_range_x[1], right_son_ptr->node_range_x[1]); + tmp_range_y[0] = min(tmp_range_y[0], right_son_ptr->node_range_y[0]); + tmp_range_y[1] = max(tmp_range_y[1], right_son_ptr->node_range_y[1]); + tmp_range_z[0] = min(tmp_range_z[0], right_son_ptr->node_range_z[0]); + tmp_range_z[1] = max(tmp_range_z[1], right_son_ptr->node_range_z[1]); + } + if (!root->point_deleted) + { + tmp_range_x[0] = min(tmp_range_x[0], root->point.x); + tmp_range_x[1] = max(tmp_range_x[1], root->point.x); + tmp_range_y[0] = min(tmp_range_y[0], root->point.y); + tmp_range_y[1] = max(tmp_range_y[1], root->point.y); + tmp_range_z[0] = min(tmp_range_z[0], root->point.z); + tmp_range_z[1] = max(tmp_range_z[1], root->point.z); + } + } + } + else + { + root->TreeSize = 1; + root->invalid_point_num = (root->point_deleted ? 1 : 0); + root->down_del_num = (root->point_downsample_deleted ? 1 : 0); + root->tree_downsample_deleted = root->point_downsample_deleted; + root->tree_deleted = root->point_deleted; + tmp_range_x[0] = root->point.x; + tmp_range_x[1] = root->point.x; + tmp_range_y[0] = root->point.y; + tmp_range_y[1] = root->point.y; + tmp_range_z[0] = root->point.z; + tmp_range_z[1] = root->point.z; + } + memcpy(root->node_range_x, tmp_range_x, sizeof(tmp_range_x)); + memcpy(root->node_range_y, tmp_range_y, sizeof(tmp_range_y)); + memcpy(root->node_range_z, tmp_range_z, sizeof(tmp_range_z)); + float x_L = (root->node_range_x[1] - root->node_range_x[0]) * 0.5; + float y_L = (root->node_range_y[1] - root->node_range_y[0]) * 0.5; + float z_L = (root->node_range_z[1] - root->node_range_z[0]) * 0.5; + root->radius_sq = x_L*x_L + y_L * y_L + z_L * z_L; + if (left_son_ptr != nullptr) + left_son_ptr->father_ptr = root; + if (right_son_ptr != nullptr) + right_son_ptr->father_ptr = root; + if (root == Root_Node && root->TreeSize > 3) + { + KD_TREE_NODE *son_ptr = root->left_son_ptr; + if (son_ptr == nullptr) + son_ptr = root->right_son_ptr; + float tmp_bal = float(son_ptr->TreeSize) / (root->TreeSize - 1); + root->alpha_del = float(root->invalid_point_num) / root->TreeSize; + root->alpha_bal = (tmp_bal >= 0.5 - EPSS) ? tmp_bal : 1 - tmp_bal; + } + return; +} + +template +void KD_TREE::flatten(KD_TREE_NODE *root, PointVector &Storage, delete_point_storage_set storage_type) +{ + if (root == nullptr) + return; + Push_Down(root); + if (!root->point_deleted) + { + Storage.push_back(root->point); + } + flatten(root->left_son_ptr, Storage, storage_type); + flatten(root->right_son_ptr, Storage, storage_type); + switch (storage_type) + { + case NOT_RECORD: + break; + case DELETE_POINTS_REC: + if (root->point_deleted && !root->point_downsample_deleted) + { + Points_deleted.push_back(root->point); + } + break; + case MULTI_THREAD_REC: + if (root->point_deleted && !root->point_downsample_deleted) + { + Multithread_Points_deleted.push_back(root->point); + } + break; + default: + break; + } + return; +} + +template +void KD_TREE::delete_tree_nodes(KD_TREE_NODE **root) +{ + if (*root == nullptr) + return; + Push_Down(*root); + delete_tree_nodes(&(*root)->left_son_ptr); + delete_tree_nodes(&(*root)->right_son_ptr); + + pthread_mutex_destroy(&(*root)->push_down_mutex_lock); + delete *root; + *root = nullptr; + + return; +} + +template +bool KD_TREE::same_point(PointType a, PointType b) +{ + return (fabs(a.x - b.x) < EPSS && fabs(a.y - b.y) < EPSS && fabs(a.z - b.z) < EPSS); +} + +template +float KD_TREE::calc_dist(PointType a, PointType b) +{ + float dist = 0.0f; + dist = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z); + return dist; +} + +template +float KD_TREE::calc_box_dist(KD_TREE_NODE *node, PointType point) +{ + if (node == nullptr) + return INFINITY; + float min_dist = 0.0; + if (point.x < node->node_range_x[0]) + min_dist += (point.x - node->node_range_x[0]) * (point.x - node->node_range_x[0]); + if (point.x > node->node_range_x[1]) + min_dist += (point.x - node->node_range_x[1]) * (point.x - node->node_range_x[1]); + if (point.y < node->node_range_y[0]) + min_dist += (point.y - node->node_range_y[0]) * (point.y - node->node_range_y[0]); + if (point.y > node->node_range_y[1]) + min_dist += (point.y - node->node_range_y[1]) * (point.y - node->node_range_y[1]); + if (point.z < node->node_range_z[0]) + min_dist += (point.z - node->node_range_z[0]) * (point.z - node->node_range_z[0]); + if (point.z > node->node_range_z[1]) + min_dist += (point.z - node->node_range_z[1]) * (point.z - node->node_range_z[1]); + return min_dist; +} +template +bool KD_TREE::point_cmp_x(PointType a, PointType b) { return a.x < b.x; } +template +bool KD_TREE::point_cmp_y(PointType a, PointType b) { return a.y < b.y; } +template +bool KD_TREE::point_cmp_z(PointType a, PointType b) { return a.z < b.z; } + +// Manual heap + + + +// manual queue + + +// Manual Instatiations +template class KD_TREE; +template class KD_TREE; +template class KD_TREE; + diff --git a/point_lio_ros2/include/ikd-Tree/ikd_Tree.h b/point_lio_ros2/include/ikd-Tree/ikd_Tree.h new file mode 100644 index 0000000..d4b302e --- /dev/null +++ b/point_lio_ros2/include/ikd-Tree/ikd_Tree.h @@ -0,0 +1,344 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EPSS 1e-6 +#define Minimal_Unbalanced_Tree_Size 10 +#define Multi_Thread_Rebuild_Point_Num 1500 +#define DOWNSAMPLE_SWITCH true +#define ForceRebuildPercentage 0.2 +#define Q_LEN 1000000 + +using namespace std; + +// typedef pcl::PointXYZINormal PointType; +// typedef vector> PointVector; + +struct BoxPointType +{ + float vertex_min[3]; + float vertex_max[3]; +}; + +enum operation_set +{ + ADD_POINT, + DELETE_POINT, + DELETE_BOX, + ADD_BOX, + DOWNSAMPLE_DELETE, + PUSH_DOWN +}; + +enum delete_point_storage_set +{ + NOT_RECORD, + DELETE_POINTS_REC, + MULTI_THREAD_REC +}; + +template +class KD_TREE +{ + // using MANUAL_Q_ = MANUAL_Q; + // using PointVector = std::vector; + + // using MANUAL_Q_ = MANUAL_Q; +public: + using PointVector = std::vector>; + using Ptr = std::shared_ptr>; + + struct KD_TREE_NODE + { + PointType point; + int division_axis; + int TreeSize = 1; + int invalid_point_num = 0; + int down_del_num = 0; + bool point_deleted = false; + bool tree_deleted = false; + bool point_downsample_deleted = false; + bool tree_downsample_deleted = false; + bool need_push_down_to_left = false; + bool need_push_down_to_right = false; + bool working_flag = false; + pthread_mutex_t push_down_mutex_lock; + float node_range_x[2], node_range_y[2], node_range_z[2]; + float radius_sq; + KD_TREE_NODE *left_son_ptr = nullptr; + KD_TREE_NODE *right_son_ptr = nullptr; + KD_TREE_NODE *father_ptr = nullptr; + // For paper data record + float alpha_del; + float alpha_bal; + }; + + struct Operation_Logger_Type + { + PointType point; + BoxPointType boxpoint; + bool tree_deleted, tree_downsample_deleted; + operation_set op; + }; + // static const PointType zeroP; + + struct PointType_CMP + { + PointType point; + float dist = 0.0; + PointType_CMP(PointType p = PointType(), float d = INFINITY) + { + this->point = p; + this->dist = d; + }; + bool operator<(const PointType_CMP &a) const + { + if (fabs(dist - a.dist) < 1e-10) + return point.x < a.point.x; + else + return dist < a.dist; + } + }; + + class MANUAL_HEAP + { + + public: + MANUAL_HEAP(int max_capacity = 100) + + { + cap = max_capacity; + heap = new PointType_CMP[max_capacity]; + heap_size = 0; + } + + ~MANUAL_HEAP() + { + delete[] heap; + } + void pop() + { + if (heap_size == 0) + return; + heap[0] = heap[heap_size - 1]; + heap_size--; + MoveDown(0); + return; + } + PointType_CMP top() + { + return heap[0]; + } + void push(PointType_CMP point) + { + if (heap_size >= cap) + return; + heap[heap_size] = point; + FloatUp(heap_size); + heap_size++; + return; + } + int size() + { + return heap_size; + } + void clear() + { + heap_size = 0; + return; + } + + private: + PointType_CMP *heap; + void MoveDown(int heap_index) + { + int l = heap_index * 2 + 1; + PointType_CMP tmp = heap[heap_index]; + while (l < heap_size) + { + if (l + 1 < heap_size && heap[l] < heap[l + 1]) + l++; + if (tmp < heap[l]) + { + heap[heap_index] = heap[l]; + heap_index = l; + l = heap_index * 2 + 1; + } + else + break; + } + heap[heap_index] = tmp; + return; + } + void FloatUp(int heap_index) + { + int ancestor = (heap_index - 1) / 2; + PointType_CMP tmp = heap[heap_index]; + while (heap_index > 0) + { + if (heap[ancestor] < tmp) + { + heap[heap_index] = heap[ancestor]; + heap_index = ancestor; + ancestor = (heap_index - 1) / 2; + } + else + break; + } + heap[heap_index] = tmp; + return; + } + int heap_size = 0; + int cap = 0; + }; + + class MANUAL_Q + { + private: + int head = 0, tail = 0, counter = 0; + Operation_Logger_Type q[Q_LEN]; + bool is_empty; + + public: + void pop() + { + if (counter == 0) + return; + head++; + head %= Q_LEN; + counter--; + if (counter == 0) + is_empty = true; + return; + } + Operation_Logger_Type front() + { + return q[head]; + } + Operation_Logger_Type back() + { + return q[tail]; + } + void clear() + { + head = 0; + tail = 0; + counter = 0; + is_empty = true; + return; + } + void push(Operation_Logger_Type op) + { + q[tail] = op; + counter++; + if (is_empty) + is_empty = false; + tail++; + tail %= Q_LEN; + } + bool empty() + { + return is_empty; + } + int size() + { + return counter; + } + }; + +private: + // Multi-thread Tree Rebuild + bool termination_flag = false; + bool rebuild_flag = false; + pthread_t rebuild_thread; + pthread_mutex_t termination_flag_mutex_lock, rebuild_ptr_mutex_lock, working_flag_mutex, search_flag_mutex; + pthread_mutex_t rebuild_logger_mutex_lock, points_deleted_rebuild_mutex_lock; + // queue Rebuild_Logger; + MANUAL_Q Rebuild_Logger; + PointVector Rebuild_PCL_Storage; + KD_TREE_NODE **Rebuild_Ptr = nullptr; + int search_mutex_counter = 0; + static void *multi_thread_ptr(void *arg); + void multi_thread_rebuild(); + void start_thread(); + void stop_thread(); + void run_operation(KD_TREE_NODE **root, Operation_Logger_Type operation); + // KD Tree Functions and augmented variables + int Treesize_tmp = 0, Validnum_tmp = 0; + float alpha_bal_tmp = 0.5, alpha_del_tmp = 0.0; + float delete_criterion_param = 0.5f; + float balance_criterion_param = 0.7f; + float downsample_size = 0.2f; + bool Delete_Storage_Disabled = false; + KD_TREE_NODE *STATIC_ROOT_NODE = nullptr; + PointVector Points_deleted; + PointVector Downsample_Storage; + PointVector Multithread_Points_deleted; + void InitTreeNode(KD_TREE_NODE *root); + void Test_Lock_States(KD_TREE_NODE *root); + void BuildTree(KD_TREE_NODE **root, int l, int r, PointVector &Storage); + void Rebuild(KD_TREE_NODE **root); + int Delete_by_range(KD_TREE_NODE **root, BoxPointType boxpoint, bool allow_rebuild, bool is_downsample); + void Delete_by_point(KD_TREE_NODE **root, PointType point, bool allow_rebuild); + void Add_by_point(KD_TREE_NODE **root, PointType point, bool allow_rebuild, int father_axis); + void Add_by_range(KD_TREE_NODE **root, BoxPointType boxpoint, bool allow_rebuild); + void Search(KD_TREE_NODE *root, int k_nearest, PointType point, MANUAL_HEAP &q, float max_dist); //priority_queue + void Search_by_range(KD_TREE_NODE *root, BoxPointType boxpoint, PointVector &Storage); + void Search_by_radius(KD_TREE_NODE *root, PointType point, float radius, PointVector &Storage); + bool Criterion_Check(KD_TREE_NODE *root); + void Push_Down(KD_TREE_NODE *root); + void Update(KD_TREE_NODE *root); + void delete_tree_nodes(KD_TREE_NODE **root); + void downsample(KD_TREE_NODE **root); + bool same_point(PointType a, PointType b); + float calc_dist(PointType a, PointType b); + float calc_box_dist(KD_TREE_NODE *node, PointType point); + static bool point_cmp_x(PointType a, PointType b); + static bool point_cmp_y(PointType a, PointType b); + static bool point_cmp_z(PointType a, PointType b); + +public: + KD_TREE(float delete_param = 0.5, float balance_param = 0.6, float box_length = 0.2); + ~KD_TREE(); + void Set_delete_criterion_param(float delete_param) + { + delete_criterion_param = delete_param; + } + void Set_balance_criterion_param(float balance_param) + { + balance_criterion_param = balance_param; + } + void set_downsample_param(float downsample_param) + { + downsample_size = downsample_param; + } + void InitializeKDTree(float delete_param = 0.5, float balance_param = 0.7, float box_length = 0.2); + int size(); + int validnum(); + void root_alpha(float &alpha_bal, float &alpha_del); + void Build(PointVector point_cloud); + void Nearest_Search(PointType point, int k_nearest, PointVector &Nearest_Points, vector &Point_Distance, float max_dist = INFINITY); + void Box_Search(const BoxPointType &Box_of_Point, PointVector &Storage); + void Radius_Search(PointType point, const float radius, PointVector &Storage); + int Add_Points(PointVector &PointToAdd, bool downsample_on); + void Add_Point_Boxes(vector &BoxPoints); + void Delete_Points(PointVector &PointToDel); + int Delete_Point_Boxes(vector &BoxPoints); + void flatten(KD_TREE_NODE *root, PointVector &Storage, delete_point_storage_set storage_type); + void acquire_removed_points(PointVector &removed_points); + BoxPointType tree_range(); + PointVector PCL_Storage; + KD_TREE_NODE *Root_Node = nullptr; + int max_queue_size = 0; +}; + +// template +// PointType KD_TREE::zeroP = PointType(0,0,0); diff --git a/point_lio_ros2/include/so3_math.h b/point_lio_ros2/include/so3_math.h new file mode 100644 index 0000000..d289aed --- /dev/null +++ b/point_lio_ros2/include/so3_math.h @@ -0,0 +1,113 @@ +#ifndef SO3_MATH_H +#define SO3_MATH_H + +#include +#include + +// #include + +#define SKEW_SYM_MATRX(v) 0.0,-v[2],v[1],v[2],0.0,-v[0],-v[1],v[0],0.0 + +template +Eigen::Matrix skew_sym_mat(const Eigen::Matrix &v) +{ + Eigen::Matrix skew_sym_mat; + skew_sym_mat<<0.0,-v[2],v[1],v[2],0.0,-v[0],-v[1],v[0],0.0; + return skew_sym_mat; +} + +template +Eigen::Matrix Exp(const Eigen::Matrix &&ang) +{ + T ang_norm = ang.norm(); + Eigen::Matrix Eye3 = Eigen::Matrix::Identity(); + if (ang_norm > 0.0000001) + { + Eigen::Matrix r_axis = ang / ang_norm; + Eigen::Matrix K; + K << SKEW_SYM_MATRX(r_axis); + /// Roderigous Tranformation + return Eye3 + std::sin(ang_norm) * K + (1.0 - std::cos(ang_norm)) * K * K; + } + else + { + return Eye3; + } +} + +template +Eigen::Matrix Exp(const Eigen::Matrix &ang_vel, const Ts &dt) +{ + T ang_vel_norm = ang_vel.norm(); + Eigen::Matrix Eye3 = Eigen::Matrix::Identity(); + + if (ang_vel_norm > 0.0000001) + { + Eigen::Matrix r_axis = ang_vel / ang_vel_norm; + Eigen::Matrix K; + + K << SKEW_SYM_MATRX(r_axis); + + T r_ang = ang_vel_norm * dt; + + /// Roderigous Tranformation + return Eye3 + std::sin(r_ang) * K + (1.0 - std::cos(r_ang)) * K * K; + } + else + { + return Eye3; + } +} + +template +Eigen::Matrix Exp(const T &v1, const T &v2, const T &v3) +{ + T &&norm = sqrt(v1 * v1 + v2 * v2 + v3 * v3); + Eigen::Matrix Eye3 = Eigen::Matrix::Identity(); + if (norm > 0.00001) + { + T r_ang[3] = {v1 / norm, v2 / norm, v3 / norm}; + Eigen::Matrix K; + K << SKEW_SYM_MATRX(r_ang); + + /// Roderigous Tranformation + return Eye3 + std::sin(norm) * K + (1.0 - std::cos(norm)) * K * K; + } + else + { + return Eye3; + } +} + +/* Logrithm of a Rotation Matrix */ +template +Eigen::Matrix Log(const Eigen::Matrix &R) +{ + T theta = (R.trace() > 3.0 - 1e-6) ? 0.0 : std::acos(0.5 * (R.trace() - 1)); + Eigen::Matrix K(R(2,1) - R(1,2), R(0,2) - R(2,0), R(1,0) - R(0,1)); + return (std::abs(theta) < 0.001) ? (0.5 * K) : (0.5 * theta / std::sin(theta) * K); +} + +template +Eigen::Matrix RotMtoEuler(const Eigen::Matrix &rot) +{ + T sy = sqrt(rot(0,0)*rot(0,0) + rot(1,0)*rot(1,0)); + bool singular = sy < 1e-6; + T x, y, z; + if(!singular) + { + x = atan2(rot(2, 1), rot(2, 2)); + y = atan2(-rot(2, 0), sy); + z = atan2(rot(1, 0), rot(0, 0)); + } + else + { + x = atan2(-rot(1, 2), rot(1, 1)); + y = atan2(-rot(2, 0), sy); + z = 0; + } + Eigen::Matrix ang(x, y, z); + return ang; +} + +#endif diff --git a/point_lio_ros2/launch/correct_odom_unilidar_l1.launch.py b/point_lio_ros2/launch/correct_odom_unilidar_l1.launch.py new file mode 100644 index 0000000..934d187 --- /dev/null +++ b/point_lio_ros2/launch/correct_odom_unilidar_l1.launch.py @@ -0,0 +1,48 @@ +from launch import LaunchDescription +from launch.actions import GroupAction, DeclareLaunchArgument +from launch.conditions import IfCondition +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution +from launch_ros.actions import Node +from launch_ros.substitutions import FindPackageShare + + +def generate_launch_description(): + # Node parameters, including those from the YAML configuration file + laser_mapping_params = [ + PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'config', 'unilidar_l1.yaml' + ]), + { + 'use_imu_as_input': False, # Change to True to use IMU as input of Point-LIO + 'prop_at_freq_of_imu': True, + 'check_satu': True, + 'init_map_size': 10, + 'point_filter_num': 1, # Options: 1, 3 + 'space_down_sample': True, + 'filter_size_surf': 0.1, # Options: 0.5, 0.3, 0.2, 0.15, 0.1 + 'filter_size_map': 0.1, # Options: 0.5, 0.3, 0.15, 0.1 + 'cube_side_length': 1000.0, # Option: 1000 + 'runtime_pos_log_enable': False, # Option: True + 'odom_only': True, # Option: False + 'odom_header_frame_id': "odom", # Default: "camera_init" + 'odom_child_frame_id': "base_link", # Default: "aft_mapped" + } + ] + + # Node definition for laserMapping with Point-LIO + laser_mapping_node = Node( + package='point_lio', + executable='pointlio_mapping', + name='laserMapping', + output='screen', + parameters=laser_mapping_params, + # prefix='gdb -ex run --args' + ) + + # Assemble the launch description + ld = LaunchDescription([ + laser_mapping_node, + ]) + + return ld diff --git a/point_lio_ros2/launch/correct_odom_unilidar_l2.launch.py b/point_lio_ros2/launch/correct_odom_unilidar_l2.launch.py new file mode 100644 index 0000000..0d6501e --- /dev/null +++ b/point_lio_ros2/launch/correct_odom_unilidar_l2.launch.py @@ -0,0 +1,48 @@ +from launch import LaunchDescription +from launch.actions import GroupAction, DeclareLaunchArgument +from launch.conditions import IfCondition +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution +from launch_ros.actions import Node +from launch_ros.substitutions import FindPackageShare + + +def generate_launch_description(): + # Node parameters, including those from the YAML configuration file + laser_mapping_params = [ + PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'config', 'unilidar_l2.yaml' + ]), + { + 'use_imu_as_input': False, # Change to True to use IMU as input of Point-LIO + 'prop_at_freq_of_imu': True, + 'check_satu': True, + 'init_map_size': 10, + 'point_filter_num': 1, # Options: 1, 3 + 'space_down_sample': True, + 'filter_size_surf': 0.1, # Options: 0.5, 0.3, 0.2, 0.15, 0.1 + 'filter_size_map': 0.1, # Options: 0.5, 0.3, 0.15, 0.1 + 'cube_side_length': 1000.0, # Option: 1000 + 'runtime_pos_log_enable': False, # Option: True + 'odom_only': True, # Option: False + 'odom_header_frame_id': "odom", # Default: "camera_init" + 'odom_child_frame_id': "base_link", # Default: "aft_mapped" + } + ] + + # Node definition for laserMapping with Point-LIO + laser_mapping_node = Node( + package='point_lio', + executable='pointlio_mapping', + name='laserMapping', + output='screen', + parameters=laser_mapping_params, + # prefix='gdb -ex run --args' + ) + + # Assemble the launch description + ld = LaunchDescription([ + laser_mapping_node, + ]) + + return ld diff --git a/point_lio_ros2/launch/gdb_debug_example.launch.py b/point_lio_ros2/launch/gdb_debug_example.launch.py new file mode 100644 index 0000000..a452b76 --- /dev/null +++ b/point_lio_ros2/launch/gdb_debug_example.launch.py @@ -0,0 +1,68 @@ +from launch import LaunchDescription +from launch.actions import GroupAction, DeclareLaunchArgument +from launch.conditions import IfCondition +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution +from launch_ros.actions import Node +from launch_ros.substitutions import FindPackageShare + + +def generate_launch_description(): + # Declare the RViz argument + rviz_arg = DeclareLaunchArgument( + 'rviz', default_value='true', + description='Flag to launch RViz.') + + # Node parameters, including those from the YAML configuration file + laser_mapping_params = [ + { + 'use_imu_as_input': False, # Change to True to use IMU as input of Point-LIO + 'prop_at_freq_of_imu': True, + 'check_satu': True, + 'init_map_size': 10, + 'point_filter_num': 1, # Options: 1, 3 + 'space_down_sample': True, + 'filter_size_surf': 0.3, # Options: 0.5, 0.3, 0.2, 0.15, 0.1 + 'filter_size_map': 0.2, # Options: 0.5, 0.3, 0.15, 0.1 + 'cube_side_length': 1000.0, # Option: 1000, 2000 + 'runtime_pos_log_enable': False # Option: True + }, + # PathJoinSubstitution([ + # FindPackageShare('point_lio'), + # 'config', 'horizon.yaml' + # ]) + ] + + # Node definition for laserMapping with Point-LIO + laser_mapping_node = Node( + package='point_lio', + executable='pointlio_mapping', + name='laserMapping', + output='screen', + parameters=laser_mapping_params, + prefix='gdb -ex run --args' + ) + + # Conditional RViz node launch + rviz_node = Node( + package='rviz2', + executable='rviz2', + name='rviz', + arguments=['-d', PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'rviz_cfg', 'loam_livox.rviz' + ])], + condition=IfCondition(LaunchConfiguration('rviz')), + prefix='nice' + ) + + # Assemble the launch description + ld = LaunchDescription([ + rviz_arg, + laser_mapping_node, + GroupAction( + actions=[rviz_node], + condition=IfCondition(LaunchConfiguration('rviz')) + ), + ]) + + return ld diff --git a/point_lio_ros2/launch/mapping_avia.launch.py b/point_lio_ros2/launch/mapping_avia.launch.py new file mode 100644 index 0000000..dc067f7 --- /dev/null +++ b/point_lio_ros2/launch/mapping_avia.launch.py @@ -0,0 +1,68 @@ +from launch import LaunchDescription +from launch.actions import GroupAction, DeclareLaunchArgument +from launch.conditions import IfCondition +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution +from launch_ros.actions import Node +from launch_ros.substitutions import FindPackageShare + + +def generate_launch_description(): + # Declare the RViz argument + rviz_arg = DeclareLaunchArgument( + 'rviz', default_value='true', + description='Flag to launch RViz.') + + # Node parameters, including those from the YAML configuration file + laser_mapping_params = [ + PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'config', 'avia.yaml' + ]), + { + 'use_imu_as_input': False, # Change to True to use IMU as input of Point-LIO + 'prop_at_freq_of_imu': True, + 'check_satu': True, + 'init_map_size': 10, + 'point_filter_num': 1, # options: 4, 3 + 'space_down_sample': True, + 'filter_size_surf': 0.3, # options: 0.5, 0.3, 0.2, 0.15, 0.1 + 'filter_size_map': 0.2, # options: 0.5, 0.3, 0.15, 0.1 + 'cube_side_length': 2000.0, # option: 1000 + 'runtime_pos_log_enable': False, # option: True + }, + ] + + # Node definition for laserMapping with Point-LIO + laser_mapping_node = Node( + package='point_lio', + executable='pointlio_mapping', + name='laserMapping', + output='screen', + parameters=laser_mapping_params, + # prefix='gdb -ex run --args' + ) + + # Conditional RViz node launch + rviz_node = Node( + package='rviz2', + executable='rviz2', + name='rviz', + arguments=['-d', PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'rviz_cfg', 'loam_livox.rviz' + ])], + condition=IfCondition(LaunchConfiguration('rviz')), + prefix='nice' + ) + + # Assemble the launch description + ld = LaunchDescription([ + rviz_arg, + laser_mapping_node, + GroupAction( + actions=[rviz_node], + condition=IfCondition(LaunchConfiguration('rviz')) + ), + ]) + + return ld diff --git a/point_lio_ros2/launch/mapping_horizon.launch.py b/point_lio_ros2/launch/mapping_horizon.launch.py new file mode 100644 index 0000000..8b3374b --- /dev/null +++ b/point_lio_ros2/launch/mapping_horizon.launch.py @@ -0,0 +1,68 @@ +from launch import LaunchDescription +from launch.actions import GroupAction, DeclareLaunchArgument +from launch.conditions import IfCondition +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution +from launch_ros.actions import Node +from launch_ros.substitutions import FindPackageShare + + +def generate_launch_description(): + # Declare the RViz argument + rviz_arg = DeclareLaunchArgument( + 'rviz', default_value='true', + description='Flag to launch RViz.') + + # Node parameters, including those from the YAML configuration file + laser_mapping_params = [ + PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'config', 'horizon.yaml' + ]), + { + 'use_imu_as_input': False, # Change to True to use IMU as input of Point-LIO + 'prop_at_freq_of_imu': True, + 'check_satu': True, + 'init_map_size': 10, + 'point_filter_num': 3, # Options: 1, 3 + 'space_down_sample': True, + 'filter_size_surf': 0.5, # Options: 0.5, 0.3, 0.2, 0.15, 0.1 + 'filter_size_map': 0.5, # Options: 0.5, 0.3, 0.15, 0.1 + 'cube_side_length': 1000.0, # Option: 1000 + 'runtime_pos_log_enable': False, # Option: True + } + ] + + # Node definition for laserMapping with Point-LIO + laser_mapping_node = Node( + package='point_lio', + executable='pointlio_mapping', + name='laserMapping', + output='screen', + parameters=laser_mapping_params, + # prefix='gdb -ex run --args' + ) + + # Conditional RViz node launch + rviz_node = Node( + package='rviz2', + executable='rviz2', + name='rviz', + arguments=['-d', PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'rviz_cfg', 'loam_livox.rviz' + ])], + condition=IfCondition(LaunchConfiguration('rviz')), + prefix='nice' + ) + + # Assemble the launch description + ld = LaunchDescription([ + rviz_arg, + laser_mapping_node, + GroupAction( + actions=[rviz_node], + condition=IfCondition(LaunchConfiguration('rviz')) + ), + ]) + + return ld diff --git a/point_lio_ros2/launch/mapping_mid360.launch.py b/point_lio_ros2/launch/mapping_mid360.launch.py new file mode 100644 index 0000000..dbf6ee4 --- /dev/null +++ b/point_lio_ros2/launch/mapping_mid360.launch.py @@ -0,0 +1,68 @@ +from launch import LaunchDescription +from launch.actions import GroupAction, DeclareLaunchArgument +from launch.conditions import IfCondition +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution +from launch_ros.actions import Node +from launch_ros.substitutions import FindPackageShare + + +def generate_launch_description(): + # Declare the RViz argument + rviz_arg = DeclareLaunchArgument( + 'rviz', default_value='true', + description='Flag to launch RViz.') + + # Node parameters, including those from the YAML configuration file + laser_mapping_params = [ + PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'config', 'mid360.yaml' + ]), + { + 'use_imu_as_input': False, # Change to True to use IMU as input of Point-LIO + 'prop_at_freq_of_imu': True, + 'check_satu': True, + 'init_map_size': 10, + 'point_filter_num': 3, # Options: 1, 3 + 'space_down_sample': True, + 'filter_size_surf': 0.5, # Options: 0.5, 0.3, 0.2, 0.15, 0.1 + 'filter_size_map': 0.5, # Options: 0.5, 0.3, 0.15, 0.1 + 'cube_side_length': 1000.0, # Option: 1000 + 'runtime_pos_log_enable': False, # Option: True + } + ] + + # Node definition for laserMapping with Point-LIO + laser_mapping_node = Node( + package='point_lio', + executable='pointlio_mapping', + name='laserMapping', + output='screen', + parameters=laser_mapping_params, + # prefix='gdb -ex run --args' + ) + + # Conditional RViz node launch + rviz_node = Node( + package='rviz2', + executable='rviz2', + name='rviz', + arguments=['-d', PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'rviz_cfg', 'loam_livox.rviz' + ])], + condition=IfCondition(LaunchConfiguration('rviz')), + prefix='nice' + ) + + # Assemble the launch description + ld = LaunchDescription([ + rviz_arg, + laser_mapping_node, + GroupAction( + actions=[rviz_node], + condition=IfCondition(LaunchConfiguration('rviz')) + ), + ]) + + return ld diff --git a/point_lio_ros2/launch/mapping_ouster64.launch.py b/point_lio_ros2/launch/mapping_ouster64.launch.py new file mode 100644 index 0000000..5577693 --- /dev/null +++ b/point_lio_ros2/launch/mapping_ouster64.launch.py @@ -0,0 +1,68 @@ +from launch import LaunchDescription +from launch.actions import GroupAction, DeclareLaunchArgument +from launch.conditions import IfCondition +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution +from launch_ros.actions import Node +from launch_ros.substitutions import FindPackageShare + + +def generate_launch_description(): + # Declare the RViz argument + rviz_arg = DeclareLaunchArgument( + 'rviz', default_value='true', + description='Flag to launch RViz.') + + # Node parameters, including those from the YAML configuration file + laser_mapping_params = [ + PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'config', 'ouster64.yaml' + ]), + { + 'use_imu_as_input': False, # Change to True to use IMU as input of Point-LIO + 'prop_at_freq_of_imu': True, + 'check_satu': True, + 'init_map_size': 10, + 'point_filter_num': 4, # Options: 4, 3 + 'space_down_sample': True, + 'filter_size_surf': 0.5, # Options: 0.5, 0.3, 0.2, 0.15, 0.1 + 'filter_size_map': 0.5, # Options: 0.5, 0.3, 0.15, 0.1 + 'cube_side_length': 1000.0, # Option: 1000 (changed from 2000) + 'runtime_pos_log_enable': False, # Option: True + } + ] + + # Node definition for laserMapping with Point-LIO + laser_mapping_node = Node( + package='point_lio', + executable='pointlio_mapping', + name='laserMapping', + output='screen', + parameters=laser_mapping_params, + # prefix='gdb -ex run --args' + ) + + # Conditional RViz node launch + rviz_node = Node( + package='rviz2', + executable='rviz2', + name='rviz', + arguments=['-d', PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'rviz_cfg', 'loam_livox.rviz' + ])], + condition=IfCondition(LaunchConfiguration('rviz')), + prefix='nice' + ) + + # Assemble the launch description + ld = LaunchDescription([ + rviz_arg, + laser_mapping_node, + GroupAction( + actions=[rviz_node], + condition=IfCondition(LaunchConfiguration('rviz')) + ), + ]) + + return ld diff --git a/point_lio_ros2/launch/mapping_unilidar_l1.launch.py b/point_lio_ros2/launch/mapping_unilidar_l1.launch.py new file mode 100644 index 0000000..14aa43f --- /dev/null +++ b/point_lio_ros2/launch/mapping_unilidar_l1.launch.py @@ -0,0 +1,68 @@ +from launch import LaunchDescription +from launch.actions import GroupAction, DeclareLaunchArgument +from launch.conditions import IfCondition +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution +from launch_ros.actions import Node +from launch_ros.substitutions import FindPackageShare + + +def generate_launch_description(): + # Declare the RViz argument + rviz_arg = DeclareLaunchArgument( + 'rviz', default_value='true', + description='Flag to launch RViz.') + + # Node parameters, including those from the YAML configuration file + laser_mapping_params = [ + PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'config', 'unilidar_l1.yaml' + ]), + { + 'use_imu_as_input': False, # Change to True to use IMU as input of Point-LIO + 'prop_at_freq_of_imu': True, + 'check_satu': True, + 'init_map_size': 10, + 'point_filter_num': 1, # Options: 1, 3 + 'space_down_sample': True, + 'filter_size_surf': 0.1, # Options: 0.5, 0.3, 0.2, 0.15, 0.1 + 'filter_size_map': 0.1, # Options: 0.5, 0.3, 0.15, 0.1 + 'cube_side_length': 1000.0, # Option: 1000 + 'runtime_pos_log_enable': False, # Option: True + } + ] + + # Node definition for laserMapping with Point-LIO + laser_mapping_node = Node( + package='point_lio', + executable='pointlio_mapping', + name='laserMapping', + output='screen', + parameters=laser_mapping_params, + # prefix='gdb -ex run --args' + ) + + # Conditional RViz node launch + rviz_node = Node( + package='rviz2', + executable='rviz2', + name='rviz', + arguments=['-d', PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'rviz_cfg', 'loam_livox.rviz' + ])], + condition=IfCondition(LaunchConfiguration('rviz')), + prefix='nice' + ) + + # Assemble the launch description + ld = LaunchDescription([ + rviz_arg, + laser_mapping_node, + GroupAction( + actions=[rviz_node], + condition=IfCondition(LaunchConfiguration('rviz')) + ), + ]) + + return ld diff --git a/point_lio_ros2/launch/mapping_unilidar_l2.launch.py b/point_lio_ros2/launch/mapping_unilidar_l2.launch.py new file mode 100644 index 0000000..a2db249 --- /dev/null +++ b/point_lio_ros2/launch/mapping_unilidar_l2.launch.py @@ -0,0 +1,70 @@ +from launch import LaunchDescription +from launch.actions import GroupAction, DeclareLaunchArgument +from launch.conditions import IfCondition +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution +from launch_ros.actions import Node +from launch_ros.substitutions import FindPackageShare + + +def generate_launch_description(): + # Declare the RViz argument + rviz_arg = DeclareLaunchArgument( + 'rviz', default_value='true', + description='Flag to launch RViz.') + + # Node parameters, including those from the YAML configuration file + laser_mapping_params = [ + PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'config', 'unilidar_l2.yaml' + ]), + { + 'use_imu_as_input': True, # Change to True to use IMU as input of Point-LIO + 'prop_at_freq_of_imu': True, + 'check_satu': True, + 'init_map_size': 10, + 'point_filter_num': 3, # Options: 1, 3 + 'space_down_sample': True, + 'filter_size_surf': 0.1, # Options: 0.5, 0.3, 0.2, 0.15, 0.1 + 'filter_size_map': 0.1, # Options: 0.5, 0.3, 0.15, 0.1 + 'cube_side_length': 500.0, # Option: 1000 + 'runtime_pos_log_enable': False, # Option: True + } + ] + + # Node definition for laserMapping with Point-LIO + laser_mapping_node = Node( + package='point_lio', + executable='pointlio_mapping', + name='laserMapping', + output='screen', + parameters=laser_mapping_params, + # prefix='gdb -ex run --args' + ) + + # Conditional RViz node launch + rviz_node = Node( + package='rviz2', + executable='rviz2', + name='rviz', + arguments=['-d', PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'rviz_cfg', 'loam_livox.rviz' + ])], + condition=IfCondition(LaunchConfiguration('rviz')), + prefix='nice' + ) + + # Assemble the launch description + ld = LaunchDescription([ + rviz_arg, + laser_mapping_node, + GroupAction( + actions=[rviz_node], + condition=IfCondition(LaunchConfiguration('rviz')) + ), + ]) + + return ld + + diff --git a/point_lio_ros2/launch/mapping_velody16.launch.py b/point_lio_ros2/launch/mapping_velody16.launch.py new file mode 100644 index 0000000..21cd90b --- /dev/null +++ b/point_lio_ros2/launch/mapping_velody16.launch.py @@ -0,0 +1,68 @@ +from launch import LaunchDescription +from launch.actions import GroupAction, DeclareLaunchArgument +from launch.conditions import IfCondition +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution +from launch_ros.actions import Node +from launch_ros.substitutions import FindPackageShare + + +def generate_launch_description(): + # Declare the RViz argument + rviz_arg = DeclareLaunchArgument( + 'rviz', default_value='true', + description='Flag to launch RViz.') + + # Node parameters, including those from the YAML configuration file + laser_mapping_params = [ + PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'config', 'velody16.yaml' + ]), + { + 'use_imu_as_input': False, # Change to True to use IMU as input of Point-LIO + 'prop_at_freq_of_imu': True, + 'check_satu': True, + 'init_map_size': 10, + 'point_filter_num': 4, # Options: 4, 3 + 'space_down_sample': True, + 'filter_size_surf': 0.5, # Options: 0.5, 0.3, 0.2, 0.15, 0.1 + 'filter_size_map': 0.5, # Options: 0.5, 0.3, 0.15, 0.1 + 'cube_side_length': 1000.0, # Option: 1000 (changed from 2000) + 'runtime_pos_log_enable': False, # Option: True + } + ] + + # Node definition for laserMapping with Point-LIO + laser_mapping_node = Node( + package='point_lio', + executable='pointlio_mapping', + name='laserMapping', + output='screen', + parameters=laser_mapping_params, + # prefix='gdb -ex run --args' + ) + + # Conditional RViz node launch + rviz_node = Node( + package='rviz2', + executable='rviz2', + name='rviz', + arguments=['-d', PathJoinSubstitution([ + FindPackageShare('point_lio'), + 'rviz_cfg', 'loam_livox.rviz' + ])], + condition=IfCondition(LaunchConfiguration('rviz')), + prefix='nice' + ) + + # Assemble the launch description + ld = LaunchDescription([ + rviz_arg, + laser_mapping_node, + GroupAction( + actions=[rviz_node], + condition=IfCondition(LaunchConfiguration('rviz')) + ), + ]) + + return ld diff --git a/point_lio_ros2/package.xml b/point_lio_ros2/package.xml new file mode 100644 index 0000000..01ba0ff --- /dev/null +++ b/point_lio_ros2/package.xml @@ -0,0 +1,40 @@ + + + point_lio + 0.0.0 + + This is a modified version of LOAM which is original algorithm + is described in the following paper: + J. Zhang and S. Singh. LOAM: Lidar Odometry and Mapping in Real-time. + Robotics: Science and Systems Conference (RSS). Berkeley, CA, July 2014. + + + Daniel Florea + + BSD + + Daniel Florea + + + ament_cmake + + + rclcpp + rclpy + sensor_msgs + geometry_msgs + nav_msgs + tf2_ros + pcl_ros + pcl_conversions + visualization_msgs + + + + ament_lint_auto + ament_lint_common + + + ament_cmake + + diff --git a/point_lio_ros2/rviz_cfg/loam_livox.rviz b/point_lio_ros2/rviz_cfg/loam_livox.rviz new file mode 100644 index 0000000..b6f0986 --- /dev/null +++ b/point_lio_ros2/rviz_cfg/loam_livox.rviz @@ -0,0 +1,326 @@ +Panels: + - Class: rviz_common/Displays + Help Height: 78 + Name: Displays + Property Tree Widget: + Expanded: + - /Global Options1 + - /Status1 + Splitter Ratio: 0.5 + Tree Height: 549 + - Class: rviz_common/Selection + Name: Selection + - Class: rviz_common/Tool Properties + Expanded: + - /2D Goal Pose1 + - /Publish Point1 + Name: Tool Properties + Splitter Ratio: 0.5886790156364441 + - Class: rviz_common/Views + Expanded: + - /Current View1 + Name: Views + Splitter Ratio: 0.5 + - Class: rviz_common/Time + Experimental: false + Name: Time + SyncMode: 0 + SyncSource: CloudRegistered +Visualization Manager: + Class: "" + Displays: + - Class: rviz_default_plugins/TF + Enabled: true + Frame Timeout: 15 + Frames: + All Enabled: true + aft_mapped: + Value: true + base_footprint: + Value: true + base_link: + Value: true + camera_init: + Value: true + camera_link: + Value: true + gyro_link: + Value: true + laser: + Value: true + left_front_link: + Value: true + left_wheel_link: + Value: true + map: + Value: true + odom_combined: + Value: true + right_front_link: + Value: true + right_wheel_link: + Value: true + Marker Scale: 1 + Name: TF + Show Arrows: true + Show Axes: true + Show Names: false + Tree: + camera_init: + aft_mapped: + {} + Update Interval: 0 + Value: true + - Angle Tolerance: 0.10000000149011612 + Class: rviz_default_plugins/Odometry + Covariance: + Orientation: + Alpha: 0.5 + Color: 255; 255; 127 + Color Style: Unique + Frame: Local + Offset: 1 + Scale: 1 + Value: true + Position: + Alpha: 0.30000001192092896 + Color: 204; 51; 204 + Scale: 1 + Value: true + Value: true + Enabled: true + Keep: 100 + Name: Odometry + Position Tolerance: 0.10000000149011612 + Shape: + Alpha: 1 + Axes Length: 1 + Axes Radius: 0.10000000149011612 + Color: 255; 25; 0 + Head Length: 0.30000001192092896 + Head Radius: 0.10000000149011612 + Shaft Length: 1 + Shaft Radius: 0.05000000074505806 + Value: Arrow + Topic: + Depth: 5 + Durability Policy: Volatile + Filter size: 10 + History Policy: Keep Last + Reliability Policy: Reliable + Value: /Odometry + Value: true + - Alpha: 1 + Buffer Length: 1 + Class: rviz_default_plugins/Path + Color: 25; 255; 0 + Enabled: true + Head Diameter: 0.30000001192092896 + Head Length: 0.20000000298023224 + Length: 0.30000001192092896 + Line Style: Lines + Line Width: 0.029999999329447746 + Name: Path + Offset: + X: 0 + Y: 0 + Z: 0 + Pose Color: 255; 85; 255 + Pose Style: None + Radius: 0.029999999329447746 + Shaft Diameter: 0.10000000149011612 + Shaft Length: 0.10000000149011612 + Topic: + Depth: 5 + Durability Policy: Volatile + Filter size: 10 + History Policy: Keep Last + Reliability Policy: Reliable + Value: /path + Value: true + - Alpha: 1 + Autocompute Intensity Bounds: true + Autocompute Value Bounds: + Max Value: 1.8584054708480835 + Min Value: -0.10289539396762848 + Value: true + Axis: Z + Channel Name: intensity + Class: rviz_default_plugins/PointCloud2 + Color: 255; 255; 255 + Color Transformer: AxisColor + Decay Time: 30 + Enabled: true + Invert Rainbow: false + Max Color: 255; 255; 255 + Max Intensity: 186 + Min Color: 0; 0; 0 + Min Intensity: 0 + Name: CloudRegistered + Position Transformer: XYZ + Selectable: true + Size (Pixels): 3 + Size (m): 0.009999999776482582 + Style: Flat Squares + Topic: + Depth: 5 + Durability Policy: Volatile + Filter size: 10 + History Policy: Keep Last + Reliability Policy: Reliable + Value: /cloud_registered + Use Fixed Frame: true + Use rainbow: true + Value: true + - Alpha: 1 + Autocompute Intensity Bounds: true + Autocompute Value Bounds: + Max Value: 10 + Min Value: -10 + Value: true + Axis: Z + Channel Name: intensity + Class: rviz_default_plugins/PointCloud2 + Color: 255; 255; 255 + Color Transformer: Intensity + Decay Time: 0 + Enabled: true + Invert Rainbow: false + Max Color: 255; 255; 255 + Max Intensity: 184 + Min Color: 0; 0; 0 + Min Intensity: 0 + Name: CloudEffected + Position Transformer: XYZ + Selectable: true + Size (Pixels): 3 + Size (m): 0.019999999552965164 + Style: Flat Squares + Topic: + Depth: 5 + Durability Policy: Volatile + Filter size: 10 + History Policy: Keep Last + Reliability Policy: Reliable + Value: /cloud_effected + Use Fixed Frame: true + Use rainbow: true + Value: true + - Alpha: 1 + Autocompute Intensity Bounds: true + Autocompute Value Bounds: + Max Value: 2.036320447921753 + Min Value: -0.09378375858068466 + Value: true + Axis: Z + Channel Name: intensity + Class: rviz_default_plugins/PointCloud2 + Color: 255; 255; 255 + Color Transformer: AxisColor + Decay Time: 0 + Enabled: true + Invert Rainbow: false + Max Color: 255; 255; 255 + Max Intensity: 255 + Min Color: 0; 0; 0 + Min Intensity: 0 + Name: CloudMap + Position Transformer: XYZ + Selectable: true + Size (Pixels): 3 + Size (m): 0.019999999552965164 + Style: Flat Squares + Topic: + Depth: 5 + Durability Policy: Volatile + Filter size: 10 + History Policy: Keep Last + Reliability Policy: Reliable + Value: /Laser_map + Use Fixed Frame: true + Use rainbow: true + Value: true + Enabled: true + Global Options: + Background Color: 0; 0; 0 + Fixed Frame: camera_init + Frame Rate: 30 + Name: root + Tools: + - Class: rviz_default_plugins/Interact + Hide Inactive Objects: true + - Class: rviz_default_plugins/MoveCamera + - Class: rviz_default_plugins/Select + - Class: rviz_default_plugins/FocusCamera + - Class: rviz_default_plugins/Measure + Line color: 128; 128; 0 + - Class: rviz_default_plugins/SetInitialPose + Covariance x: 0.25 + Covariance y: 0.25 + Covariance yaw: 0.06853891909122467 + Topic: + Depth: 5 + Durability Policy: Volatile + History Policy: Keep Last + Reliability Policy: Reliable + Value: /initialpose + - Class: rviz_default_plugins/SetGoal + Topic: + Depth: 5 + Durability Policy: Volatile + History Policy: Keep Last + Reliability Policy: Reliable + Value: /goal_pose + - Class: rviz_default_plugins/PublishPoint + Single click: true + Topic: + Depth: 5 + Durability Policy: Volatile + History Policy: Keep Last + Reliability Policy: Reliable + Value: /clicked_point + Transformation: + Current: + Class: rviz_default_plugins/TF + Value: true + Views: + Current: + Class: rviz_default_plugins/Orbit + Distance: 28.403661727905273 + Enable Stereo Rendering: + Stereo Eye Separation: 0.05999999865889549 + Stereo Focal Distance: 1 + Swap Stereo Eyes: false + Value: false + Focal Point: + X: -2.2604103088378906 + Y: -0.3224470913410187 + Z: 0.9725424647331238 + Focal Shape Fixed Size: true + Focal Shape Size: 0.05000000074505806 + Invert Z Axis: false + Name: Current View + Near Clip Distance: 0.009999999776482582 + Pitch: 0.7497965693473816 + Target Frame: + Value: Orbit (rviz_default_plugins) + Yaw: 1.7503817081451416 + Saved: ~ +Window Geometry: + Displays: + collapsed: false + Height: 846 + Hide Left Dock: false + Hide Right Dock: false + QMainWindow State: 000000ff00000000fd000000040000000000000156000002b0fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d000002b0000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f000002b0fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003d000002b0000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000005ad0000003efc0100000002fb0000000800540069006d00650100000000000005ad000002eb00fffffffb0000000800540069006d0065010000000000000450000000000000000000000451000002b000000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000 + Selection: + collapsed: false + Time: + collapsed: false + Tool Properties: + collapsed: false + Views: + collapsed: false + Width: 1453 + X: 2404 + Y: 218 diff --git a/point_lio_ros2/src/Estimator.cpp b/point_lio_ros2/src/Estimator.cpp new file mode 100644 index 0000000..912e98b --- /dev/null +++ b/point_lio_ros2/src/Estimator.cpp @@ -0,0 +1,435 @@ +// #include <../include/IKFoM/IKFoM_toolkit/esekfom/esekfom.hpp> +#include "Estimator.h" + +PointCloudXYZI::Ptr normvec(new PointCloudXYZI(100000, 1)); +std::vector time_seq; +PointCloudXYZI::Ptr feats_down_body(new PointCloudXYZI()); +PointCloudXYZI::Ptr feats_down_world(new PointCloudXYZI()); +std::vector pbody_list; +std::vector Nearest_Points; +KD_TREE ikdtree; +std::vector pointSearchSqDis(NUM_MATCH_POINTS); +bool point_selected_surf[100000] = {0}; +std::vector crossmat_list; +int effct_feat_num = 0; +int k; +int idx; +esekfom::esekf kf_input; +esekfom::esekf kf_output; +state_input state_in; +state_output state_out; +input_ikfom input_in; +V3D angvel_avr, acc_avr; + +V3D Lidar_T_wrt_IMU(Zero3d); +M3D Lidar_R_wrt_IMU(Eye3d); + +typedef MTK::vect<3, double> vect3; +typedef MTK::SO3 SO3; +typedef MTK::S2 S2; +typedef MTK::vect<1, double> vect1; +typedef MTK::vect<2, double> vect2; + +Eigen::Matrix process_noise_cov_input() +{ + Eigen::Matrix cov; + cov.setZero(); + cov.block<3, 3>(3, 3).diagonal() << gyr_cov_input, gyr_cov_input, gyr_cov_input; + cov.block<3, 3>(12, 12).diagonal() << acc_cov_input, acc_cov_input, acc_cov_input; + cov.block<3, 3>(15, 15).diagonal() << b_gyr_cov, b_gyr_cov, b_gyr_cov; + cov.block<3, 3>(18, 18).diagonal() << b_acc_cov, b_acc_cov, b_acc_cov; + // MTK::get_cov::type cov = MTK::get_cov::type::Zero(); + // MTK::setDiagonal(cov, &process_noise_input::ng, gyr_cov_input);// 0.03 + // MTK::setDiagonal(cov, &process_noise_input::na, acc_cov_input); // *dt 0.01 0.01 * dt * dt 0.05 + // MTK::setDiagonal(cov, &process_noise_input::nbg, b_gyr_cov); // *dt 0.00001 0.00001 * dt *dt 0.3 //0.001 0.0001 0.01 + // MTK::setDiagonal(cov, &process_noise_input::nba, b_acc_cov); //0.001 0.05 0.0001/out 0.01 + return cov; +} + +Eigen::Matrix process_noise_cov_output() +{ + Eigen::Matrix cov; + cov.setZero(); + cov.block<3, 3>(12, 12).diagonal() << vel_cov, vel_cov, vel_cov; + cov.block<3, 3>(15, 15).diagonal() << gyr_cov_output, gyr_cov_output, gyr_cov_output; + cov.block<3, 3>(18, 18).diagonal() << acc_cov_output, acc_cov_output, acc_cov_output; + cov.block<3, 3>(24, 24).diagonal() << b_gyr_cov, b_gyr_cov, b_gyr_cov; + cov.block<3, 3>(27, 27).diagonal() << b_acc_cov, b_acc_cov, b_acc_cov; + // MTK::get_cov::type cov = MTK::get_cov::type::Zero(); + // MTK::setDiagonal(cov, &process_noise_output::vel, vel_cov);// 0.03 + // MTK::setDiagonal(cov, &process_noise_output::ng, gyr_cov_output); // *dt 0.01 0.01 * dt * dt 0.05 + // MTK::setDiagonal(cov, &process_noise_output::na, acc_cov_output); // *dt 0.00001 0.00001 * dt *dt 0.3 //0.001 0.0001 0.01 + // MTK::setDiagonal(cov, &process_noise_output::nbg, b_gyr_cov); //0.001 0.05 0.0001/out 0.01 + // MTK::setDiagonal(cov, &process_noise_output::nba, b_acc_cov); //0.001 0.05 0.0001/out 0.01 + return cov; +} + +Eigen::Matrix get_f_input(state_input &s, const input_ikfom &in) +{ + Eigen::Matrix res = Eigen::Matrix::Zero(); + vect3 omega; + in.gyro.boxminus(omega, s.bg); + vect3 a_inertial = s.rot.normalized() * (in.acc-s.ba); + for(int i = 0; i < 3; i++ ){ + res(i) = s.vel[i]; + res(i + 3) = omega[i]; + res(i + 12) = a_inertial[i] + s.gravity[i]; + } + return res; +} + +Eigen::Matrix get_f_output(state_output &s, const input_ikfom &in) +{ + Eigen::Matrix res = Eigen::Matrix::Zero(); + vect3 a_inertial = s.rot.normalized() * s.acc; + for(int i = 0; i < 3; i++ ){ + res(i) = s.vel[i]; + res(i + 3) = s.omg[i]; + res(i + 12) = a_inertial[i] + s.gravity[i]; + } + return res; +} + +Eigen::Matrix df_dx_input(state_input &s, const input_ikfom &in) +{ + Eigen::Matrix cov = Eigen::Matrix::Zero(); + cov.template block<3, 3>(0, 12) = Eigen::Matrix3d::Identity(); + vect3 acc_; + in.acc.boxminus(acc_, s.ba); + vect3 omega; + in.gyro.boxminus(omega, s.bg); + cov.template block<3, 3>(12, 3) = -s.rot.normalized().toRotationMatrix()*MTK::hat(acc_); + cov.template block<3, 3>(12, 18) = -s.rot.normalized().toRotationMatrix(); + // Eigen::Matrix vec = Eigen::Matrix::Zero(); + // Eigen::Matrix grav_matrix; + // s.S2_Mx(grav_matrix, vec, 21); + cov.template block<3, 3>(12, 21) = Eigen::Matrix3d::Identity(); // grav_matrix; + cov.template block<3, 3>(3, 15) = -Eigen::Matrix3d::Identity(); + return cov; +} + +// Eigen::Matrix df_dw_input(state_input &s, const input_ikfom &in) +// { +// Eigen::Matrix cov = Eigen::Matrix::Zero(); +// cov.template block<3, 3>(12, 3) = -s.rot.normalized().toRotationMatrix(); +// cov.template block<3, 3>(3, 0) = -Eigen::Matrix3d::Identity(); +// cov.template block<3, 3>(15, 6) = Eigen::Matrix3d::Identity(); +// cov.template block<3, 3>(18, 9) = Eigen::Matrix3d::Identity(); +// return cov; +// } + +Eigen::Matrix df_dx_output(state_output &s, const input_ikfom &in) +{ + Eigen::Matrix cov = Eigen::Matrix::Zero(); + cov.template block<3, 3>(0, 12) = Eigen::Matrix3d::Identity(); + cov.template block<3, 3>(12, 3) = -s.rot.normalized().toRotationMatrix()*MTK::hat(s.acc); + cov.template block<3, 3>(12, 18) = s.rot.normalized().toRotationMatrix(); + // Eigen::Matrix vec = Eigen::Matrix::Zero(); + // Eigen::Matrix grav_matrix; + // s.S2_Mx(grav_matrix, vec, 21); + cov.template block<3, 3>(12, 21) = Eigen::Matrix3d::Identity(); // grav_matrix; + cov.template block<3, 3>(3, 15) = Eigen::Matrix3d::Identity(); + return cov; +} + +// Eigen::Matrix df_dw_output(state_output &s) +// { +// Eigen::Matrix cov = Eigen::Matrix::Zero(); +// cov.template block<3, 3>(12, 0) = Eigen::Matrix3d::Identity(); +// cov.template block<3, 3>(15, 3) = Eigen::Matrix3d::Identity(); +// cov.template block<3, 3>(18, 6) = Eigen::Matrix3d::Identity(); +// cov.template block<3, 3>(24, 9) = Eigen::Matrix3d::Identity(); +// cov.template block<3, 3>(27, 12) = Eigen::Matrix3d::Identity(); +// return cov; +// } + +vect3 SO3ToEuler(const SO3 &orient) +{ + Eigen::Matrix _ang; + Eigen::Vector4d q_data = orient.coeffs().transpose(); + //scalar w=orient.coeffs[3], x=orient.coeffs[0], y=orient.coeffs[1], z=orient.coeffs[2]; + double sqw = q_data[3]*q_data[3]; + double sqx = q_data[0]*q_data[0]; + double sqy = q_data[1]*q_data[1]; + double sqz = q_data[2]*q_data[2]; + double unit = sqx + sqy + sqz + sqw; // if normalized is one, otherwise is correction factor + double test = q_data[3]*q_data[1] - q_data[2]*q_data[0]; + + if (test > 0.49999*unit) { // singularity at north pole + + _ang << 2 * std::atan2(q_data[0], q_data[3]), M_PI/2, 0; + double temp[3] = {_ang[0] * 57.3, _ang[1] * 57.3, _ang[2] * 57.3}; + vect3 euler_ang(temp, 3); + return euler_ang; + } + if (test < -0.49999*unit) { // singularity at south pole + _ang << -2 * std::atan2(q_data[0], q_data[3]), -M_PI/2, 0; + double temp[3] = {_ang[0] * 57.3, _ang[1] * 57.3, _ang[2] * 57.3}; + vect3 euler_ang(temp, 3); + return euler_ang; + } + + _ang << + std::atan2(2*q_data[0]*q_data[3]+2*q_data[1]*q_data[2] , -sqx - sqy + sqz + sqw), + std::asin (2*test/unit), + std::atan2(2*q_data[2]*q_data[3]+2*q_data[1]*q_data[0] , sqx - sqy - sqz + sqw); + double temp[3] = {_ang[0] * 57.3, _ang[1] * 57.3, _ang[2] * 57.3}; + vect3 euler_ang(temp, 3); + return euler_ang; +} + +void h_model_input(state_input &s, esekfom::dyn_share_modified &ekfom_data) +{ + bool match_in_map = false; + VF(4) pabcd; + pabcd.setZero(); + normvec->resize(time_seq[k]); + int effect_num_k = 0; + for (int j = 0; j < time_seq[k]; j++) + { + PointType &point_body_j = feats_down_body->points[idx+j+1]; + PointType &point_world_j = feats_down_world->points[idx+j+1]; + pointBodyToWorld(&point_body_j, &point_world_j); + V3D p_body = pbody_list[idx+j+1]; + V3D p_world; + p_world << point_world_j.x, point_world_j.y, point_world_j.z; + + { + auto &points_near = Nearest_Points[idx+j+1]; + + ikdtree.Nearest_Search(point_world_j, NUM_MATCH_POINTS, points_near, pointSearchSqDis, 2.236); //1.0); //, 3.0); // 2.236; + + if ((points_near.size() < NUM_MATCH_POINTS) || pointSearchSqDis[NUM_MATCH_POINTS - 1] > 5) // 5) + { + point_selected_surf[idx+j+1] = false; + } + else + { + point_selected_surf[idx+j+1] = false; + if (esti_plane(pabcd, points_near, plane_thr)) //(planeValid) + { + float pd2 = pabcd(0) * point_world_j.x + pabcd(1) * point_world_j.y + pabcd(2) * point_world_j.z + pabcd(3); + + if (p_body.norm() > match_s * pd2 * pd2) + { + point_selected_surf[idx+j+1] = true; + normvec->points[j].x = pabcd(0); + normvec->points[j].y = pabcd(1); + normvec->points[j].z = pabcd(2); + normvec->points[j].intensity = pabcd(3); + effect_num_k ++; + } + } + } + } + } + if (effect_num_k == 0) + { + ekfom_data.valid = false; + return; + } + ekfom_data.M_Noise = laser_point_cov; + ekfom_data.h_x = Eigen::MatrixXd::Zero(effect_num_k, 12); + ekfom_data.z.resize(effect_num_k); + int m = 0; + for (int j = 0; j < time_seq[k]; j++) + { + if(point_selected_surf[idx+j+1]) + { + V3D norm_vec(normvec->points[j].x, normvec->points[j].y, normvec->points[j].z); + + if (extrinsic_est_en) + { + V3D p_body = pbody_list[idx+j+1]; + M3D p_crossmat, p_imu_crossmat; + p_crossmat << SKEW_SYM_MATRX(p_body); + V3D point_imu = s.offset_R_L_I.normalized() * p_body + s.offset_T_L_I; + p_imu_crossmat << SKEW_SYM_MATRX(point_imu); + V3D C(s.rot.conjugate().normalized() * norm_vec); + V3D A(p_imu_crossmat * C); + V3D B(p_crossmat * s.offset_R_L_I.conjugate().normalized() * C); + ekfom_data.h_x.block<1, 12>(m, 0) << norm_vec(0), norm_vec(1), norm_vec(2), VEC_FROM_ARRAY(A), VEC_FROM_ARRAY(B), VEC_FROM_ARRAY(C); + } + else + { + M3D point_crossmat = crossmat_list[idx+j+1]; + V3D C(s.rot.conjugate().normalized() * norm_vec); + V3D A(point_crossmat * C); + ekfom_data.h_x.block<1, 12>(m, 0) << norm_vec(0), norm_vec(1), norm_vec(2), VEC_FROM_ARRAY(A), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0; + } + ekfom_data.z(m) = -norm_vec(0) * feats_down_world->points[idx+j+1].x -norm_vec(1) * feats_down_world->points[idx+j+1].y -norm_vec(2) * feats_down_world->points[idx+j+1].z-normvec->points[j].intensity; + m++; + } + } + effct_feat_num += effect_num_k; +} + +void h_model_output(state_output &s, esekfom::dyn_share_modified &ekfom_data) +{ + bool match_in_map = false; + VF(4) pabcd; + pabcd.setZero(); + + normvec->resize(time_seq[k]); + int effect_num_k = 0; + for (int j = 0; j < time_seq[k]; j++) + { + PointType &point_body_j = feats_down_body->points[idx+j+1]; + PointType &point_world_j = feats_down_world->points[idx+j+1]; + pointBodyToWorld(&point_body_j, &point_world_j); + V3D p_body = pbody_list[idx+j+1]; + V3D p_world; + p_world << point_world_j.x, point_world_j.y, point_world_j.z; + { + auto &points_near = Nearest_Points[idx+j+1]; + + ikdtree.Nearest_Search(point_world_j, NUM_MATCH_POINTS, points_near, pointSearchSqDis, 2.236); + + if ((points_near.size() < NUM_MATCH_POINTS) || pointSearchSqDis[NUM_MATCH_POINTS - 1] > 5) + { + point_selected_surf[idx+j+1] = false; + } + else + { + point_selected_surf[idx+j+1] = false; + if (esti_plane(pabcd, points_near, plane_thr)) //(planeValid) + { + float pd2 = pabcd(0) * point_world_j.x + pabcd(1) * point_world_j.y + pabcd(2) * point_world_j.z + pabcd(3); + + if (p_body.norm() > match_s * pd2 * pd2) + { + // point_selected_surf[i] = true; + point_selected_surf[idx+j+1] = true; + normvec->points[j].x = pabcd(0); + normvec->points[j].y = pabcd(1); + normvec->points[j].z = pabcd(2); + normvec->points[j].intensity = pabcd(3); + effect_num_k ++; + } + } + } + } + } + if (effect_num_k == 0) + { + ekfom_data.valid = false; + return; + } + ekfom_data.M_Noise = laser_point_cov; + ekfom_data.h_x = Eigen::MatrixXd::Zero(effect_num_k, 12); + ekfom_data.z.resize(effect_num_k); + int m = 0; + for (int j = 0; j < time_seq[k]; j++) + { + if(point_selected_surf[idx+j+1]) + { + V3D norm_vec(normvec->points[j].x, normvec->points[j].y, normvec->points[j].z); + + if (extrinsic_est_en) + { + V3D p_body = pbody_list[idx+j+1]; + M3D p_crossmat, p_imu_crossmat; + p_crossmat << SKEW_SYM_MATRX(p_body); + V3D point_imu = s.offset_R_L_I.normalized() * p_body + s.offset_T_L_I; + p_imu_crossmat << SKEW_SYM_MATRX(point_imu); + V3D C(s.rot.conjugate().normalized() * norm_vec); + V3D A(p_imu_crossmat * C); + V3D B(p_crossmat * s.offset_R_L_I.conjugate().normalized() * C); + ekfom_data.h_x.block<1, 12>(m, 0) << norm_vec(0), norm_vec(1), norm_vec(2), VEC_FROM_ARRAY(A), VEC_FROM_ARRAY(B), VEC_FROM_ARRAY(C); + } + else + { + M3D point_crossmat = crossmat_list[idx+j+1]; + V3D C(s.rot.conjugate().normalized() * norm_vec); + V3D A(point_crossmat * C); + // V3D A(point_crossmat * state.rot_end.transpose() * norm_vec); + ekfom_data.h_x.block<1, 12>(m, 0) << norm_vec(0), norm_vec(1), norm_vec(2), VEC_FROM_ARRAY(A), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0; + } + ekfom_data.z(m) = -norm_vec(0) * feats_down_world->points[idx+j+1].x -norm_vec(1) * feats_down_world->points[idx+j+1].y -norm_vec(2) * feats_down_world->points[idx+j+1].z-normvec->points[j].intensity; + m++; + } + } + effct_feat_num += effect_num_k; +} + +void h_model_IMU_output(state_output &s, esekfom::dyn_share_modified &ekfom_data) +{ + std::memset(ekfom_data.satu_check, false, 6); + ekfom_data.z_IMU.block<3,1>(0, 0) = angvel_avr - s.omg - s.bg; + ekfom_data.z_IMU.block<3,1>(3, 0) = acc_avr * G_m_s2 / acc_norm - s.acc - s.ba; + ekfom_data.R_IMU << imu_meas_omg_cov, imu_meas_omg_cov, imu_meas_omg_cov, imu_meas_acc_cov, imu_meas_acc_cov, imu_meas_acc_cov; + if(check_satu) + { + if(fabs(angvel_avr(0)) >= 0.99 * satu_gyro) + { + ekfom_data.satu_check[0] = true; + ekfom_data.z_IMU(0) = 0.0; + } + + if(fabs(angvel_avr(1)) >= 0.99 * satu_gyro) + { + ekfom_data.satu_check[1] = true; + ekfom_data.z_IMU(1) = 0.0; + } + + if(fabs(angvel_avr(2)) >= 0.99 * satu_gyro) + { + ekfom_data.satu_check[2] = true; + ekfom_data.z_IMU(2) = 0.0; + } + + if(fabs(acc_avr(0)) >= 0.99 * satu_acc) + { + ekfom_data.satu_check[3] = true; + ekfom_data.z_IMU(3) = 0.0; + } + + if(fabs(acc_avr(1)) >= 0.99 * satu_acc) + { + ekfom_data.satu_check[4] = true; + ekfom_data.z_IMU(4) = 0.0; + } + + if(fabs(acc_avr(2)) >= 0.99 * satu_acc) + { + ekfom_data.satu_check[5] = true; + ekfom_data.z_IMU(5) = 0.0; + } + } +} + +void pointBodyToWorld(PointType const * const pi, PointType * const po) +{ + V3D p_body(pi->x, pi->y, pi->z); + + V3D p_global; + if (extrinsic_est_en) + { + if (!use_imu_as_input) + { + p_global = kf_output.x_.rot.normalized() * (kf_output.x_.offset_R_L_I.normalized() * p_body + kf_output.x_.offset_T_L_I) + kf_output.x_.pos; + } + else + { + p_global = kf_input.x_.rot.normalized() * (kf_input.x_.offset_R_L_I.normalized() * p_body + kf_input.x_.offset_T_L_I) + kf_input.x_.pos; + } + } + else + { + if (!use_imu_as_input) + { + p_global = kf_output.x_.rot.normalized() * (Lidar_R_wrt_IMU * p_body + Lidar_T_wrt_IMU) + kf_output.x_.pos; + } + else + { + p_global = kf_input.x_.rot.normalized() * (Lidar_R_wrt_IMU * p_body + Lidar_T_wrt_IMU) + kf_input.x_.pos; + } + } + + po->x = p_global(0); + po->y = p_global(1); + po->z = p_global(2); + po->intensity = pi->intensity; +} + +const bool time_list(PointType &x, PointType &y) {return (x.curvature < y.curvature);}; \ No newline at end of file diff --git a/point_lio_ros2/src/Estimator.h b/point_lio_ros2/src/Estimator.h new file mode 100644 index 0000000..6e0c552 --- /dev/null +++ b/point_lio_ros2/src/Estimator.h @@ -0,0 +1,118 @@ +#ifndef Estimator_H +#define Estimator_H + +#include <../include/IKFoM/IKFoM_toolkit/esekfom/esekfom.hpp> +#include "common_lib.h" +#include "parameters.h" +#include +#include +#include +#include +#include +#include + +extern PointCloudXYZI::Ptr normvec; //(new PointCloudXYZI(100000, 1)); +extern std::vector time_seq; +extern PointCloudXYZI::Ptr feats_down_body; //(new PointCloudXYZI()); +extern PointCloudXYZI::Ptr feats_down_world; //(new PointCloudXYZI()); +extern std::vector pbody_list; +extern std::vector Nearest_Points; +extern KD_TREE ikdtree; +extern std::vector pointSearchSqDis; +extern bool point_selected_surf[100000]; // = {0}; +extern std::vector crossmat_list; +extern int effct_feat_num; +extern int k; +extern int idx; +extern V3D angvel_avr, acc_avr; + +extern V3D Lidar_T_wrt_IMU; //(Zero3d); +extern M3D Lidar_R_wrt_IMU; //(Eye3d); + +typedef MTK::vect<3, double> vect3; +typedef MTK::SO3 SO3; +typedef MTK::S2 S2; +typedef MTK::vect<1, double> vect1; +typedef MTK::vect<2, double> vect2; + +MTK_BUILD_MANIFOLD(state_input, +((vect3, pos)) +((SO3, rot)) +((SO3, offset_R_L_I)) +((vect3, offset_T_L_I)) +((vect3, vel)) +((vect3, bg)) +((vect3, ba)) +((vect3, gravity)) +); + +MTK_BUILD_MANIFOLD(state_output, +((vect3, pos)) +((SO3, rot)) +((SO3, offset_R_L_I)) +((vect3, offset_T_L_I)) +((vect3, vel)) +((vect3, omg)) +((vect3, acc)) +((vect3, gravity)) +((vect3, bg)) +((vect3, ba)) +); + +MTK_BUILD_MANIFOLD(input_ikfom, +((vect3, acc)) +((vect3, gyro)) +); + +MTK_BUILD_MANIFOLD(process_noise_input, +((vect3, ng)) +((vect3, na)) +((vect3, nbg)) +((vect3, nba)) +); + +MTK_BUILD_MANIFOLD(process_noise_output, +((vect3, vel)) +((vect3, ng)) +((vect3, na)) +((vect3, nbg)) +((vect3, nba)) +); + +extern esekfom::esekf kf_input; +extern esekfom::esekf kf_output; +extern state_input state_in; +extern state_output state_out; +extern input_ikfom input_in; + +Eigen::Matrix process_noise_cov_input(); + +Eigen::Matrix process_noise_cov_output(); + +//double L_offset_to_I[3] = {0.04165, 0.02326, -0.0284}; // Avia +//vect3 Lidar_offset_to_IMU(L_offset_to_I, 3); +Eigen::Matrix get_f_input(state_input &s, const input_ikfom &in); + +Eigen::Matrix get_f_output(state_output &s, const input_ikfom &in); + +Eigen::Matrix df_dx_input(state_input &s, const input_ikfom &in); + +// Eigen::Matrix df_dw_input(state_input &s, const input_ikfom &in); + +Eigen::Matrix df_dx_output(state_output &s, const input_ikfom &in); + +// Eigen::Matrix df_dw_output(state_output &s); + +vect3 SO3ToEuler(const SO3 &orient); + +void h_model_input(state_input &s, esekfom::dyn_share_modified &ekfom_data); + +void h_model_output(state_output &s, esekfom::dyn_share_modified &ekfom_data); + +void h_model_IMU_output(state_output &s, esekfom::dyn_share_modified &ekfom_data); + +void pointBodyToWorld(PointType const *const pi, PointType *const po); + +const bool time_list(PointType &x, PointType &y); // {return (x.curvature < y.curvature);}; + +#endif \ No newline at end of file diff --git a/point_lio_ros2/src/IMU_Processing.hpp b/point_lio_ros2/src/IMU_Processing.hpp new file mode 100644 index 0000000..898a451 --- /dev/null +++ b/point_lio_ros2/src/IMU_Processing.hpp @@ -0,0 +1,164 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/// *************Preconfiguration + +#define MAX_INI_COUNT (100) + +/// *************IMU Process and undistortion +class ImuProcess { +public: + EIGEN_MAKE_ALIGNED_OPERATOR_NEW + + ImuProcess(); + + ~ImuProcess(); + + void Reset(); + + //void Reset(double start_timestamp, const sensor_msgs::msg::Imu::ConstSharedPtr &lastimu); + + void Process(const MeasureGroup &meas, const PointCloudXYZI::Ptr &pcl_un_); + + void Set_init(Eigen::Vector3d &tmp_gravity, Eigen::Matrix3d &rot); + + ofstream fout_imu; + // double first_lidar_time; + int lidar_type; + bool imu_en; + V3D mean_acc, gravity_; + bool imu_need_init_ = true; + bool b_first_frame_ = true; + bool gravity_align_ = false; + +private: + void IMU_init(const MeasureGroup &meas, int &N); + + V3D mean_gyr; + int init_iter_num = 1; + rclcpp::Logger logger; +}; + +ImuProcess::ImuProcess() + : b_first_frame_(true), imu_need_init_(true), gravity_align_(false), + logger(rclcpp::get_logger("laserMapping")) { + imu_en = true; + init_iter_num = 1; + mean_acc = V3D(0, 0, -1.0); + mean_gyr = V3D(0, 0, 0); +} + +ImuProcess::~ImuProcess() {} + +void ImuProcess::Reset() { + RCLCPP_WARN(logger, "Reset ImuProcess"); + mean_acc = V3D(0, 0, -1.0); + mean_gyr = V3D(0, 0, 0); + imu_need_init_ = true; + init_iter_num = 1; +} + +void ImuProcess::IMU_init(const MeasureGroup &meas, int &N) { + /** 1. initializing the gravity, gyro bias, acc and gyro covariance + ** 2. normalize the acceleration measurenments to unit gravity **/ + RCLCPP_INFO(logger, "IMU Initializing: %.1f %%", double(N) / MAX_INI_COUNT * 100); + V3D cur_acc, cur_gyr; + + if (b_first_frame_) { + Reset(); + N = 1; + b_first_frame_ = false; + const auto &imu_acc = meas.imu.front()->linear_acceleration; + const auto &gyr_acc = meas.imu.front()->angular_velocity; + mean_acc << imu_acc.x, imu_acc.y, imu_acc.z; + mean_gyr << gyr_acc.x, gyr_acc.y, gyr_acc.z; + } + + for (const auto &imu: meas.imu) { + const auto &imu_acc = imu->linear_acceleration; + const auto &gyr_acc = imu->angular_velocity; + cur_acc << imu_acc.x, imu_acc.y, imu_acc.z; + cur_gyr << gyr_acc.x, gyr_acc.y, gyr_acc.z; + + mean_acc += (cur_acc - mean_acc) / N; + mean_gyr += (cur_gyr - mean_gyr) / N; + + N++; + } +} + +void ImuProcess::Process(const MeasureGroup &meas, const PointCloudXYZI::Ptr &cur_pcl_un_) { + if (imu_en) { + if (meas.imu.empty()) return; + assert(meas.lidar != nullptr); + + if (imu_need_init_) { + /// The very first lidar frame + IMU_init(meas, init_iter_num); + + imu_need_init_ = true; + + if (init_iter_num > MAX_INI_COUNT) { + RCLCPP_INFO(logger, "IMU Initializing: %.1f %%", 100.0); + imu_need_init_ = false; + *cur_pcl_un_ = *(meas.lidar); + } + return; + } + if (!gravity_align_) gravity_align_ = true; + *cur_pcl_un_ = *(meas.lidar); + return; + } else { + if (!b_first_frame_) { if (!gravity_align_) gravity_align_ = true; } + else { + b_first_frame_ = false; + return; + } + *cur_pcl_un_ = *(meas.lidar); + return; + } +} + +void ImuProcess::Set_init(Eigen::Vector3d &tmp_gravity, Eigen::Matrix3d &rot) { + /** 1. initializing the gravity, gyro bias, acc and gyro covariance + ** 2. normalize the acceleration measurenments to unit gravity **/ + // V3D tmp_gravity = - mean_acc / mean_acc.norm() * G_m_s2; // state_gravity; + M3D hat_grav; + hat_grav << 0.0, gravity_(2), -gravity_(1), + -gravity_(2), 0.0, gravity_(0), + gravity_(1), -gravity_(0), 0.0; + double align_norm = (hat_grav * tmp_gravity).norm() / tmp_gravity.norm() / gravity_.norm(); + double align_cos = gravity_.transpose() * tmp_gravity; + align_cos = align_cos / gravity_.norm() / tmp_gravity.norm(); + if (align_norm < 1e-6) { + if (align_cos > 1e-6) { + rot = Eye3d; + } else { + rot = -Eye3d; + } + } else { + V3D align_angle = hat_grav * tmp_gravity / (hat_grav * tmp_gravity).norm() * acos(align_cos); + rot = Exp(align_angle(0), align_angle(1), align_angle(2)); + } +} \ No newline at end of file diff --git a/point_lio_ros2/src/laserMapping.cpp b/point_lio_ros2/src/laserMapping.cpp new file mode 100644 index 0000000..b6d5f4a --- /dev/null +++ b/point_lio_ros2/src/laserMapping.cpp @@ -0,0 +1,1322 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "IMU_Processing.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include + +#include "parameters.h" +#include "Estimator.h" + + +#define MAXN (720000) +#define PUBFRAME_PERIOD (20) + +const float MOV_THRESHOLD = 1.5f; + +mutex mtx_buffer; +condition_variable sig_buffer; + +string root_dir = ROOT_DIR; + +int feats_down_size = 0, time_log_counter = 0, scan_count = 0, publish_count = 0; + +int frame_ct = 0; +double time_update_last = 0.0, time_current = 0.0, time_predict_last_const = 0.0, t_last = 0.0; + +shared_ptr p_imu(new ImuProcess()); +bool init_map = false, flg_first_scan = true; +PointCloudXYZI::Ptr ptr_con(new PointCloudXYZI()); + +// Time Log Variables +double T1[MAXN], s_plot[MAXN], s_plot2[MAXN], s_plot3[MAXN], s_plot11[MAXN]; +double match_time = 0, solve_time = 0, propag_time = 0, update_time = 0; + +bool lidar_pushed = false, flg_reset = false, flg_exit = false; + +vector cub_needrm; + +deque lidar_buffer; +deque time_buffer; +deque imu_deque; + +//surf feature in map +PointCloudXYZI::Ptr feats_undistort(new PointCloudXYZI()); +PointCloudXYZI::Ptr feats_down_body_space(new PointCloudXYZI()); +PointCloudXYZI::Ptr init_feats_world(new PointCloudXYZI()); + +pcl::VoxelGrid downSizeFilterSurf; +pcl::VoxelGrid downSizeFilterMap; + +V3D euler_cur; + +MeasureGroup Measures; + +sensor_msgs::msg::Imu imu_last, imu_next; +sensor_msgs::msg::Imu::ConstSharedPtr imu_last_ptr; +nav_msgs::msg::Path path; +nav_msgs::msg::Odometry odomAftMapped; +geometry_msgs::msg::PoseStamped msg_body_pose; + +auto logger = rclcpp::get_logger("laserMapping"); + +void SigHandle(int sig) { + flg_exit = true; + RCLCPP_WARN(logger, "catch sig %d", sig); + sig_buffer.notify_all(); +} + +inline void dump_lio_state_to_log(FILE *fp) { + V3D rot_ang; + if (!use_imu_as_input) { + rot_ang = SO3ToEuler(kf_output.x_.rot); + } else { + rot_ang = SO3ToEuler(kf_input.x_.rot); + } + + fprintf(fp, "%lf ", Measures.lidar_beg_time - first_lidar_time); + fprintf(fp, "%lf %lf %lf ", rot_ang(0), rot_ang(1), rot_ang(2)); // Angle + if (use_imu_as_input) { + fprintf(fp, "%lf %lf %lf ", kf_input.x_.pos(0), kf_input.x_.pos(1), kf_input.x_.pos(2)); // Pos + fprintf(fp, "%lf %lf %lf ", 0.0, 0.0, 0.0); // omega + fprintf(fp, "%lf %lf %lf ", kf_input.x_.vel(0), kf_input.x_.vel(1), kf_input.x_.vel(2)); // Vel + fprintf(fp, "%lf %lf %lf ", 0.0, 0.0, 0.0); // Acc + fprintf(fp, "%lf %lf %lf ", kf_input.x_.bg(0), kf_input.x_.bg(1), kf_input.x_.bg(2)); // Bias_g + fprintf(fp, "%lf %lf %lf ", kf_input.x_.ba(0), kf_input.x_.ba(1), kf_input.x_.ba(2)); // Bias_a + fprintf(fp, "%lf %lf %lf ", kf_input.x_.gravity(0), kf_input.x_.gravity(1), kf_input.x_.gravity(2)); // Bias_a + } else { + fprintf(fp, "%lf %lf %lf ", kf_output.x_.pos(0), kf_output.x_.pos(1), kf_output.x_.pos(2)); // Pos + fprintf(fp, "%lf %lf %lf ", 0.0, 0.0, 0.0); // omega + fprintf(fp, "%lf %lf %lf ", kf_output.x_.vel(0), kf_output.x_.vel(1), kf_output.x_.vel(2)); // Vel + fprintf(fp, "%lf %lf %lf ", 0.0, 0.0, 0.0); // Acc + fprintf(fp, "%lf %lf %lf ", kf_output.x_.bg(0), kf_output.x_.bg(1), kf_output.x_.bg(2)); // Bias_g + fprintf(fp, "%lf %lf %lf ", kf_output.x_.ba(0), kf_output.x_.ba(1), kf_output.x_.ba(2)); // Bias_a + fprintf(fp, "%lf %lf %lf ", kf_output.x_.gravity(0), kf_output.x_.gravity(1), + kf_output.x_.gravity(2)); // Bias_a + } + fprintf(fp, "\r\n"); + fflush(fp); +} + +void pointBodyLidarToIMU(PointType const *const pi, PointType *const po) { + V3D p_body_lidar(pi->x, pi->y, pi->z); + V3D p_body_imu; + if (extrinsic_est_en) { + if (!use_imu_as_input) { + p_body_imu = kf_output.x_.offset_R_L_I.normalized() * p_body_lidar + kf_output.x_.offset_T_L_I; + } else { + p_body_imu = kf_input.x_.offset_R_L_I.normalized() * p_body_lidar + kf_input.x_.offset_T_L_I; + } + } else { + p_body_imu = Lidar_R_wrt_IMU * p_body_lidar + Lidar_T_wrt_IMU; + } + po->x = p_body_imu(0); + po->y = p_body_imu(1); + po->z = p_body_imu(2); + po->intensity = pi->intensity; +} + +int points_cache_size = 0; + +void points_cache_collect() // seems for debug +{ + PointVector points_history; + ikdtree.acquire_removed_points(points_history); + points_cache_size = points_history.size(); +} + +BoxPointType LocalMap_Points; +bool Localmap_Initialized = false; + +void lasermap_fov_segment() { + cub_needrm.shrink_to_fit(); + + V3D pos_LiD; + if (use_imu_as_input) { + pos_LiD = kf_input.x_.pos + kf_input.x_.rot.normalized() * Lidar_T_wrt_IMU; + } else { + pos_LiD = kf_output.x_.pos + kf_output.x_.rot.normalized() * Lidar_T_wrt_IMU; + } + if (!Localmap_Initialized) { + for (int i = 0; i < 3; i++) { + LocalMap_Points.vertex_min[i] = pos_LiD(i) - cube_len / 2.0; + LocalMap_Points.vertex_max[i] = pos_LiD(i) + cube_len / 2.0; + } + Localmap_Initialized = true; + return; + } + float dist_to_map_edge[3][2]; + bool need_move = false; + for (int i = 0; i < 3; i++) { + dist_to_map_edge[i][0] = fabs(pos_LiD(i) - LocalMap_Points.vertex_min[i]); + dist_to_map_edge[i][1] = fabs(pos_LiD(i) - LocalMap_Points.vertex_max[i]); + if (dist_to_map_edge[i][0] <= MOV_THRESHOLD * DET_RANGE || + dist_to_map_edge[i][1] <= MOV_THRESHOLD * DET_RANGE) + need_move = true; + } + if (!need_move) return; + BoxPointType New_LocalMap_Points, tmp_boxpoints; + New_LocalMap_Points = LocalMap_Points; + float mov_dist = max((cube_len - 2.0 * MOV_THRESHOLD * DET_RANGE) * 0.5 * 0.9, + double(DET_RANGE * (MOV_THRESHOLD - 1))); + for (int i = 0; i < 3; i++) { + tmp_boxpoints = LocalMap_Points; + if (dist_to_map_edge[i][0] <= MOV_THRESHOLD * DET_RANGE) { + New_LocalMap_Points.vertex_max[i] -= mov_dist; + New_LocalMap_Points.vertex_min[i] -= mov_dist; + tmp_boxpoints.vertex_min[i] = LocalMap_Points.vertex_max[i] - mov_dist; + cub_needrm.emplace_back(tmp_boxpoints); + } else if (dist_to_map_edge[i][1] <= MOV_THRESHOLD * DET_RANGE) { + New_LocalMap_Points.vertex_max[i] += mov_dist; + New_LocalMap_Points.vertex_min[i] += mov_dist; + tmp_boxpoints.vertex_max[i] = LocalMap_Points.vertex_min[i] + mov_dist; + cub_needrm.emplace_back(tmp_boxpoints); + } + } + LocalMap_Points = New_LocalMap_Points; + + points_cache_collect(); + if (cub_needrm.size() > 0) int kdtree_delete_counter = ikdtree.Delete_Point_Boxes(cub_needrm); +} + +void standard_pcl_cbk(const sensor_msgs::msg::PointCloud2::SharedPtr msg) { + mtx_buffer.lock(); + scan_count++; + double preprocess_start_time = omp_get_wtime(); + if (get_time_sec(msg->header.stamp) < last_timestamp_lidar) { + RCLCPP_ERROR(logger, "lidar loop back, clear buffer"); + // lidar_buffer.shrink_to_fit(); + + mtx_buffer.unlock(); + sig_buffer.notify_all(); + return; + } + + last_timestamp_lidar = msg->header.stamp.sec; + + PointCloudXYZI::Ptr ptr(new PointCloudXYZI()); + PointCloudXYZI::Ptr ptr_div(new PointCloudXYZI()); + double time_div = get_time_sec(msg->header.stamp); + p_pre->process(msg, ptr); + if (cut_frame) { + sort(ptr->points.begin(), ptr->points.end(), time_list); + + for (int i = 0; i < ptr->size(); i++) { + ptr_div->push_back(ptr->points[i]); + // cout << "check time:" << ptr->points[i].curvature << endl; + if (ptr->points[i].curvature / double(1000) + get_time_sec(msg->header.stamp) - time_div > + cut_frame_time_interval) { + if (ptr_div->size() < 1) continue; + PointCloudXYZI::Ptr ptr_div_i(new PointCloudXYZI()); + *ptr_div_i = *ptr_div; + lidar_buffer.push_back(ptr_div_i); + time_buffer.push_back(time_div); + time_div += ptr->points[i].curvature / double(1000); + ptr_div->clear(); + } + } + if (!ptr_div->empty()) { + lidar_buffer.push_back(ptr_div); + // ptr_div->clear(); + time_buffer.push_back(time_div); + } + } else if (con_frame) { + if (frame_ct == 0) { + time_con = last_timestamp_lidar; //get_time_sec(msg->header.stamp); + } + if (frame_ct < con_frame_num) { + for (int i = 0; i < ptr->size(); i++) { + ptr->points[i].curvature += (last_timestamp_lidar - time_con) * 1000; + ptr_con->push_back(ptr->points[i]); + } + frame_ct++; + } else { + PointCloudXYZI::Ptr ptr_con_i(new PointCloudXYZI()); + *ptr_con_i = *ptr_con; + lidar_buffer.push_back(ptr_con_i); + double time_con_i = time_con; + time_buffer.push_back(time_con_i); + ptr_con->clear(); + frame_ct = 0; + } + } else { + lidar_buffer.emplace_back(ptr); + time_buffer.emplace_back(get_time_sec(msg->header.stamp)); + } + s_plot11[scan_count] = omp_get_wtime() - preprocess_start_time; + mtx_buffer.unlock(); + sig_buffer.notify_all(); +} + +// void livox_pcl_cbk(const livox_ros_driver2::msg::CustomMsg::SharedPtr msg) { +// mtx_buffer.lock(); +// double preprocess_start_time = omp_get_wtime(); +// scan_count++; +// if (get_time_sec(msg->header.stamp) < last_timestamp_lidar) { +// RCLCPP_ERROR(logger, "lidar loop back, clear buffer"); + +// mtx_buffer.unlock(); +// sig_buffer.notify_all(); +// return; +// } + +// last_timestamp_lidar = get_time_sec(msg->header.stamp); + +// PointCloudXYZI::Ptr ptr(new PointCloudXYZI()); +// PointCloudXYZI::Ptr ptr_div(new PointCloudXYZI()); +// p_pre->process(msg, ptr); +// double time_div = get_time_sec(msg->header.stamp); +// if (cut_frame) { +// sort(ptr->points.begin(), ptr->points.end(), time_list); + +// for (int i = 0; i < ptr->size(); i++) { +// ptr_div->push_back(ptr->points[i]); +// if (ptr->points[i].curvature / double(1000) + get_time_sec(msg->header.stamp) - time_div > +// cut_frame_time_interval) { +// if (ptr_div->size() < 1) continue; +// PointCloudXYZI::Ptr ptr_div_i(new PointCloudXYZI()); +// // cout << "ptr div num:" << ptr_div->size() << endl; +// *ptr_div_i = *ptr_div; +// // cout << "ptr div i num:" << ptr_div_i->size() << endl; +// lidar_buffer.push_back(ptr_div_i); +// time_buffer.push_back(time_div); +// time_div += ptr->points[i].curvature / double(1000); +// ptr_div->clear(); +// } +// } +// if (!ptr_div->empty()) { +// lidar_buffer.push_back(ptr_div); +// // ptr_div->clear(); +// time_buffer.push_back(time_div); +// } +// } else if (con_frame) { +// if (frame_ct == 0) { +// time_con = last_timestamp_lidar; //get_time_sec(msg->header.stamp); +// } +// if (frame_ct < con_frame_num) { +// for (int i = 0; i < ptr->size(); i++) { +// ptr->points[i].curvature += (last_timestamp_lidar - time_con) * 1000; +// ptr_con->push_back(ptr->points[i]); +// } +// frame_ct++; +// } else { +// PointCloudXYZI::Ptr ptr_con_i(new PointCloudXYZI()); +// *ptr_con_i = *ptr_con; +// double time_con_i = time_con; +// lidar_buffer.push_back(ptr_con_i); +// time_buffer.push_back(time_con_i); +// ptr_con->clear(); +// frame_ct = 0; +// } +// } else { +// lidar_buffer.emplace_back(ptr); +// time_buffer.emplace_back(get_time_sec(msg->header.stamp)); +// } +// s_plot11[scan_count] = omp_get_wtime() - preprocess_start_time; +// mtx_buffer.unlock(); +// sig_buffer.notify_all(); +// } + +void imu_cbk(const sensor_msgs::msg::Imu::SharedPtr msg_in) { + publish_count++; + sensor_msgs::msg::Imu::SharedPtr msg(new sensor_msgs::msg::Imu(*msg_in)); + + msg->header.stamp = get_ros_time(get_time_sec(msg_in->header.stamp) - time_lag_imu_to_lidar); + double timestamp = get_time_sec(msg->header.stamp); + + mtx_buffer.lock(); + + if (timestamp < last_timestamp_imu) { + RCLCPP_ERROR(logger, "imu loop back, clear deque"); + // imu_deque.shrink_to_fit(); + mtx_buffer.unlock(); + sig_buffer.notify_all(); + return; + } + + imu_deque.emplace_back(msg); + last_timestamp_imu = timestamp; + mtx_buffer.unlock(); + sig_buffer.notify_all(); +} + +bool sync_packages(MeasureGroup &meas) { + if (!imu_en) { + if (!lidar_buffer.empty()) { + meas.lidar = lidar_buffer.front(); + meas.lidar_beg_time = time_buffer.front(); + time_buffer.pop_front(); + lidar_buffer.pop_front(); + if (meas.lidar->points.size() < 1) { + cout << "lose lidar" << std::endl; + return false; + } + double end_time = meas.lidar->points.back().curvature; + for (auto pt: meas.lidar->points) { + if (pt.curvature > end_time) { + end_time = pt.curvature; + } + } + lidar_end_time = meas.lidar_beg_time + end_time / double(1000); + meas.lidar_last_time = lidar_end_time; + return true; + } + return false; + } + + if (lidar_buffer.empty() || imu_deque.empty()) { + return false; + } + + /*** push a lidar scan ***/ + if (!lidar_pushed) { + meas.lidar = lidar_buffer.front(); + if (meas.lidar->points.size() < 1) { + cout << "lose lidar" << endl; + lidar_buffer.pop_front(); + time_buffer.pop_front(); + return false; + } + meas.lidar_beg_time = time_buffer.front(); + double end_time = meas.lidar->points.back().curvature; + for (auto pt: meas.lidar->points) { + if (pt.curvature > end_time) { + end_time = pt.curvature; + } + } + lidar_end_time = meas.lidar_beg_time + end_time / double(1000); + + meas.lidar_last_time = lidar_end_time; + lidar_pushed = true; + } + + if (last_timestamp_imu < lidar_end_time) { + return false; + } + /*** push imu data, and pop from imu buffer ***/ + if (p_imu->imu_need_init_) { + double imu_time = get_time_sec(imu_deque.front()->header.stamp); + meas.imu.shrink_to_fit(); + while ((!imu_deque.empty()) && (imu_time < lidar_end_time)) { + imu_time = get_time_sec(imu_deque.front()->header.stamp); + if (imu_time > lidar_end_time) break; + meas.imu.emplace_back(imu_deque.front()); + imu_last = imu_next; + imu_last_ptr = imu_deque.front(); + imu_next = *(imu_deque.front()); + imu_deque.pop_front(); + } + } else if (!init_map) { + double imu_time = get_time_sec(imu_deque.front()->header.stamp); + meas.imu.shrink_to_fit(); + meas.imu.emplace_back(imu_last_ptr); + + while ((!imu_deque.empty()) && (imu_time < lidar_end_time)) { + imu_time = get_time_sec(imu_deque.front()->header.stamp); + if (imu_time > lidar_end_time) break; + meas.imu.emplace_back(imu_deque.front()); + imu_last = imu_next; + imu_last_ptr = imu_deque.front(); + imu_next = *(imu_deque.front()); + imu_deque.pop_front(); + } + } + + lidar_buffer.pop_front(); + time_buffer.pop_front(); + lidar_pushed = false; + return true; +} + +int process_increments = 0; + +void map_incremental() { + PointVector PointToAdd; + PointVector PointNoNeedDownsample; + PointToAdd.reserve(feats_down_size); + PointNoNeedDownsample.reserve(feats_down_size); + + for (int i = 0; i < feats_down_size; i++) { + if (!Nearest_Points[i].empty()) { + const PointVector &points_near = Nearest_Points[i]; + bool need_add = true; + PointType downsample_result, mid_point; + mid_point.x = floor(feats_down_world->points[i].x / filter_size_map_min) * filter_size_map_min + + 0.5 * filter_size_map_min; + mid_point.y = floor(feats_down_world->points[i].y / filter_size_map_min) * filter_size_map_min + + 0.5 * filter_size_map_min; + mid_point.z = floor(feats_down_world->points[i].z / filter_size_map_min) * filter_size_map_min + + 0.5 * filter_size_map_min; + /* If the nearest points is definitely outside the downsample box */ + if (fabs(points_near[0].x - mid_point.x) > 1.732 * filter_size_map_min || + fabs(points_near[0].y - mid_point.y) > 1.732 * filter_size_map_min || + fabs(points_near[0].z - mid_point.z) > 1.732 * filter_size_map_min) { + PointNoNeedDownsample.emplace_back(feats_down_world->points[i]); + continue; + } + /* Check if there is a point already in the downsample box */ + float dist = calc_dist(feats_down_world->points[i], mid_point); + for (int readd_i = 0; readd_i < points_near.size(); readd_i++) { + /* Those points which are outside the downsample box should not be considered. */ + if (fabs(points_near[readd_i].x - mid_point.x) < 0.5 * filter_size_map_min && + fabs(points_near[readd_i].y - mid_point.y) < 0.5 * filter_size_map_min && + fabs(points_near[readd_i].z - mid_point.z) < 0.5 * filter_size_map_min) { + need_add = false; + break; + } + } + if (need_add) PointToAdd.emplace_back(feats_down_world->points[i]); + } else { + // PointToAdd.emplace_back(feats_down_world->points[i]); + PointNoNeedDownsample.emplace_back(feats_down_world->points[i]); + } + } + int add_point_size = ikdtree.Add_Points(PointToAdd, true); + ikdtree.Add_Points(PointNoNeedDownsample, false); +} + +void publish_init_kdtree(const rclcpp::Publisher::SharedPtr &pubLaserCloudFullRes) { + + if (odom_only) {return;} + + int size_init_ikdtree = ikdtree.size(); + PointCloudXYZI::Ptr laserCloudInit(new PointCloudXYZI(size_init_ikdtree, 1)); + + sensor_msgs::msg::PointCloud2 laserCloudmsg; + PointVector().swap(ikdtree.PCL_Storage); + ikdtree.flatten(ikdtree.Root_Node, ikdtree.PCL_Storage, NOT_RECORD); + + laserCloudInit->points = ikdtree.PCL_Storage; + pcl::toROSMsg(*laserCloudInit, laserCloudmsg); + + laserCloudmsg.header.stamp = get_ros_time(lidar_end_time); + laserCloudmsg.header.frame_id = odom_header_frame_id; + if (!odom_only) { + pubLaserCloudFullRes->publish(laserCloudmsg); + } +} + +PointCloudXYZI::Ptr pcl_wait_pub(new PointCloudXYZI(500000, 1)); +PointCloudXYZI::Ptr pcl_wait_save(new PointCloudXYZI()); + +void publish_frame_world(const rclcpp::Publisher::SharedPtr &pubLaserCloudFullRes) { + + if (odom_only) {return;} + + if (scan_pub_en) { + PointCloudXYZI::Ptr laserCloudFullRes(feats_down_body); + int size = laserCloudFullRes->points.size(); + + PointCloudXYZI::Ptr laserCloudWorld(new PointCloudXYZI(size, 1)); + + for (int i = 0; i < size; i++) { + // if (i % 3 == 0) + // { + laserCloudWorld->points[i].x = feats_down_world->points[i].x; + laserCloudWorld->points[i].y = feats_down_world->points[i].y; + laserCloudWorld->points[i].z = feats_down_world->points[i].z; + laserCloudWorld->points[i].intensity = feats_down_world->points[i].intensity; // feats_down_world->points[i].y; // + // } + } + sensor_msgs::msg::PointCloud2 laserCloudmsg; + pcl::toROSMsg(*laserCloudWorld, laserCloudmsg); + + laserCloudmsg.header.stamp = get_ros_time(lidar_end_time); + laserCloudmsg.header.frame_id = odom_header_frame_id; + pubLaserCloudFullRes->publish(laserCloudmsg); + publish_count -= PUBFRAME_PERIOD; + } + + /**************** save map ****************/ + /* 1. make sure you have enough memories + /* 2. noted that pcd save will influence the real-time performences **/ + if (pcd_save_en) { + int size = feats_down_world->points.size(); + PointCloudXYZI::Ptr laserCloudWorld(new PointCloudXYZI(size, 1)); + + for (int i = 0; i < size; i++) { + laserCloudWorld->points[i].x = feats_down_world->points[i].x; + laserCloudWorld->points[i].y = feats_down_world->points[i].y; + laserCloudWorld->points[i].z = feats_down_world->points[i].z; + laserCloudWorld->points[i].intensity = feats_down_world->points[i].intensity; + } + + *pcl_wait_save += *laserCloudWorld; + + static int scan_wait_num = 0; + scan_wait_num++; + if (pcl_wait_save->size() > 0 && pcd_save_interval > 0 && scan_wait_num >= pcd_save_interval) { + pcd_index++; + string all_points_dir(string(string(ROOT_DIR) + "PCD/scans_") + to_string(pcd_index) + string(".pcd")); + pcl::PCDWriter pcd_writer; + cout << "current scan saved to /PCD/" << all_points_dir << endl; + pcd_writer.writeBinary(all_points_dir, *pcl_wait_save); + pcl_wait_save->clear(); + scan_wait_num = 0; + } + } +} + +void publish_frame_body(const rclcpp::Publisher::SharedPtr &pubLaserCloudFull_body) { + + if (odom_only) {return;} + + int size = feats_undistort->points.size(); + PointCloudXYZI::Ptr laserCloudIMUBody(new PointCloudXYZI(size, 1)); + + for (int i = 0; i < size; i++) { + pointBodyLidarToIMU(&feats_undistort->points[i], \ + &laserCloudIMUBody->points[i]); + } + + sensor_msgs::msg::PointCloud2 laserCloudmsg; + pcl::toROSMsg(*laserCloudIMUBody, laserCloudmsg); + laserCloudmsg.header.stamp = get_ros_time(lidar_end_time); + laserCloudmsg.header.frame_id = "body"; + pubLaserCloudFull_body->publish(laserCloudmsg); + publish_count -= PUBFRAME_PERIOD; +} + +template +void set_posestamp(T &out) { + if (!use_imu_as_input) { + out.position.x = kf_output.x_.pos(0); + out.position.y = kf_output.x_.pos(1); + out.position.z = kf_output.x_.pos(2); + out.orientation.x = kf_output.x_.rot.coeffs()[0]; + out.orientation.y = kf_output.x_.rot.coeffs()[1]; + out.orientation.z = kf_output.x_.rot.coeffs()[2]; + out.orientation.w = kf_output.x_.rot.coeffs()[3]; + } else { + out.position.x = kf_input.x_.pos(0); + out.position.y = kf_input.x_.pos(1); + out.position.z = kf_input.x_.pos(2); + out.orientation.x = kf_input.x_.rot.coeffs()[0]; + out.orientation.y = kf_input.x_.rot.coeffs()[1]; + out.orientation.z = kf_input.x_.rot.coeffs()[2]; + out.orientation.w = kf_input.x_.rot.coeffs()[3]; + } +} + +template +void set_twist(T &out) { + if (!use_imu_as_input) { + out.linear.x = kf_output.x_.vel(0); + out.linear.y = kf_output.x_.vel(1); + out.linear.z = kf_output.x_.vel(2); + out.angular.x = kf_output.x_.omg(0); + out.angular.y = kf_output.x_.omg(1); + out.angular.z = kf_output.x_.omg(2); + } else { + out.linear.x = kf_input.x_.vel(0); + out.linear.y = kf_input.x_.vel(1); + out.linear.z = kf_input.x_.vel(2); + out.angular.x = imu_last.angular_velocity.x; + out.angular.y = imu_last.angular_velocity.y; + out.angular.z = imu_last.angular_velocity.z; + } +} + +void publish_odometry(const rclcpp::Publisher::SharedPtr &pubOdomAftMapped, + std::shared_ptr &tf_br) { + + odomAftMapped.header.frame_id = odom_header_frame_id; + odomAftMapped.child_frame_id = odom_child_frame_id; + + if (publish_odometry_without_downsample) { + odomAftMapped.header.stamp = get_ros_time(time_current); + } else { + odomAftMapped.header.stamp = get_ros_time(lidar_end_time); + } + set_posestamp(odomAftMapped.pose.pose); + set_twist(odomAftMapped.twist.twist); + + if (odom_only){ + Matrix3d cov = kf_output.get_P().block<3, 3>(0, 0); + + // Get the position components (first 3x3) + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + odomAftMapped.pose.covariance[6 * i + j] = cov(i, j); + } + } + + odomAftMapped.pose.covariance[21] = 0.0; // Covariance for roll + odomAftMapped.pose.covariance[28] = 0.0; // Covariance for pitch + odomAftMapped.pose.covariance[35] = 0.05; // Covariance for yaw + + odomAftMapped.twist.covariance[0] = 0.1; // Covariance for linear velocity on x + odomAftMapped.twist.covariance[7] = 0.1; // Covariance for linear velocity on y + odomAftMapped.twist.covariance[14] = 0.0; // Covariance for linear velocity on z + odomAftMapped.twist.covariance[21] = 0.0; // Covariance for angular velocity (roll) + odomAftMapped.twist.covariance[28] = 0.0; // Covariance for angular velocity (pitch) + odomAftMapped.twist.covariance[35] = 0.05; // Covariance for angular velocity (yaw) + } + + pubOdomAftMapped->publish(odomAftMapped); + + //static tf2_ros::TransformBroadcaster br = std::make_shared(*this); + geometry_msgs::msg::TransformStamped transform; + transform.header.frame_id = odom_header_frame_id; + transform.child_frame_id = odom_child_frame_id; + + transform.transform.translation.x = odomAftMapped.pose.pose.position.x; + transform.transform.translation.y = odomAftMapped.pose.pose.position.y; + transform.transform.translation.z = odomAftMapped.pose.pose.position.z; + + transform.transform.rotation.w = odomAftMapped.pose.pose.orientation.w; + transform.transform.rotation.x = odomAftMapped.pose.pose.orientation.x; + transform.transform.rotation.y = odomAftMapped.pose.pose.orientation.y; + transform.transform.rotation.z = odomAftMapped.pose.pose.orientation.z; + + transform.header.stamp = odomAftMapped.header.stamp; + + tf_br->sendTransform(transform); +} + +void publish_path(const rclcpp::Publisher::SharedPtr &pubPath) { + + if (odom_only) {return;} + + set_posestamp(msg_body_pose.pose); + // msg_body_pose.header.stamp = ros::Time::now(); + msg_body_pose.header.stamp = get_ros_time(lidar_end_time); + msg_body_pose.header.frame_id = odom_header_frame_id; + static int jjj = 0; + jjj++; + // if (jjj % 2 == 0) // if path is too large, the rvis will crash + { + path.poses.emplace_back(msg_body_pose); + pubPath->publish(path); + } +} + +int main(int argc, char **argv) { + rclcpp::init(argc, argv); + auto nh = std::make_shared("laserMapping"); + readParameters(nh); + cout << "lidar_type: " << lidar_type << endl; + + path.header.stamp = get_ros_time(lidar_end_time); + path.header.frame_id = odom_header_frame_id; + + /*** variables definition for counting ***/ + int frame_num = 0; + double aver_time_consu = 0, aver_time_icp = 0, aver_time_match = 0, aver_time_incre = 0, aver_time_solve = 0, aver_time_propag = 0; + std::time_t startTime, endTime; + + /*** initialize variables ***/ + double FOV_DEG = (fov_deg + 10.0) > 179.9 ? 179.9 : (fov_deg + 10.0); + double HALF_FOV_COS = cos((FOV_DEG) * 0.5 * PI_M / 180.0); + + memset(point_selected_surf, true, sizeof(point_selected_surf)); + downSizeFilterSurf.setLeafSize(filter_size_surf_min, filter_size_surf_min, filter_size_surf_min); + downSizeFilterMap.setLeafSize(filter_size_map_min, filter_size_map_min, filter_size_map_min); + Lidar_T_wrt_IMU << VEC_FROM_ARRAY(extrinT); + Lidar_R_wrt_IMU << MAT_FROM_ARRAY(extrinR); + if (extrinsic_est_en) { + if (!use_imu_as_input) { + kf_output.x_.offset_R_L_I = Lidar_R_wrt_IMU; + kf_output.x_.offset_T_L_I = Lidar_T_wrt_IMU; + } else { + kf_input.x_.offset_R_L_I = Lidar_R_wrt_IMU; + kf_input.x_.offset_T_L_I = Lidar_T_wrt_IMU; + } + } + p_imu->lidar_type = p_pre->lidar_type = lidar_type; + p_imu->imu_en = imu_en; + + kf_input.init_dyn_share_modified(get_f_input, df_dx_input, h_model_input); + kf_output.init_dyn_share_modified_2h(get_f_output, df_dx_output, h_model_output, h_model_IMU_output); + Eigen::Matrix P_init = MD(24, 24)::Identity() * 0.01; + P_init.block<3, 3>(21, 21) = MD(3, 3)::Identity() * 0.0001; + P_init.block<6, 6>(15, 15) = MD(6, 6)::Identity() * 0.001; + P_init.block<6, 6>(6, 6) = MD(6, 6)::Identity() * 0.0001; + kf_input.change_P(P_init); + Eigen::Matrix P_init_output = MD(30, 30)::Identity() * 0.01; + P_init_output.block<3, 3>(21, 21) = MD(3, 3)::Identity() * 0.0001; + P_init_output.block<6, 6>(6, 6) = MD(6, 6)::Identity() * 0.0001; + P_init_output.block<6, 6>(24, 24) = MD(6, 6)::Identity() * 0.001; + kf_input.change_P(P_init); + kf_output.change_P(P_init_output); + Eigen::Matrix Q_input = process_noise_cov_input(); + Eigen::Matrix Q_output = process_noise_cov_output(); + /*** debug record ***/ + FILE *fp; + string pos_log_dir = root_dir + "/Log/pos_log.txt"; + fp = fopen(pos_log_dir.c_str(), "w"); + + ofstream fout_out, fout_imu_pbp; + fout_out.open(DEBUG_FILE_DIR("mat_out.txt"), ios::out); + fout_imu_pbp.open(DEBUG_FILE_DIR("imu_pbp.txt"), ios::out); + if (fout_out && fout_imu_pbp) + cout << "~~~~" << ROOT_DIR << " file opened" << endl; + else + cout << "~~~~" << ROOT_DIR << " doesn't exist" << endl; + + /*** ROS subscribe initialization ***/ + rclcpp::Subscription::SharedPtr sub_pcl; + // rclcpp::Subscription::SharedPtr sub_pcl_livox_; + // if (p_pre->lidar_type == AVIA) { + // sub_pcl_livox_ = nh->create_subscription(lid_topic, 20, livox_pcl_cbk); + // } else { + sub_pcl = nh->create_subscription(lid_topic, rclcpp::SensorDataQoS(), standard_pcl_cbk); + // } + auto sub_imu = nh->create_subscription(imu_topic, 200000, imu_cbk); + + rclcpp::Publisher::SharedPtr pubLaserCloudFullRes; + rclcpp::Publisher::SharedPtr pubLaserCloudFullRes_body; + rclcpp::Publisher::SharedPtr pubLaserCloudEffect; + rclcpp::Publisher::SharedPtr pubLaserCloudMap; + rclcpp::Publisher::SharedPtr pubPath; + + if (!odom_only){ + pubLaserCloudFullRes = nh->create_publisher + ("/cloud_registered", 100000); + pubLaserCloudFullRes_body = nh->create_publisher + ("/cloud_registered_body", 100000); + pubLaserCloudEffect = nh->create_publisher + ("/cloud_effected", 100000); + pubLaserCloudMap = nh->create_publisher + ("/Laser_map", 100000); + pubPath = nh->create_publisher + ("/path", 100000); + } + + // Choose topic name depending on odom_only value + rclcpp::Publisher::SharedPtr pubOdomAftMapped; + if (odom_only){ + pubOdomAftMapped = nh->create_publisher + ("/odom_corrected", 100000); + } else { + pubOdomAftMapped = nh->create_publisher + ("/aft_mapped_to_init", 100000); + } + + //auto plane_pub = nh->create_publisher + // ("/planner_normal", 1000); + auto tf_broadcaster = std::make_shared(nh); +//------------------------------------------------------------------------------------------------------ + signal(SIGINT, SigHandle); + rclcpp::Rate rate(5000); + while (rclcpp::ok()) { + if (flg_exit) break; + //ros::spinOnce(); + rclcpp::executors::SingleThreadedExecutor executor; + executor.add_node(nh); + executor.spin_some(); // 处理当前可用的回调 + + if (sync_packages(Measures)) { + if (flg_first_scan) { + first_lidar_time = Measures.lidar_beg_time; + flg_first_scan = false; + cout << "first lidar time" << first_lidar_time << endl; + } + + if (flg_reset) { + RCLCPP_WARN(logger, "reset when rosbag play back"); + p_imu->Reset(); + flg_reset = false; + continue; + } + double t0, t1, t2, t3, t4, t5, match_start, solve_start; + match_time = 0; + solve_time = 0; + propag_time = 0; + update_time = 0; + t0 = omp_get_wtime(); + + p_imu->Process(Measures, feats_undistort); + + if (feats_undistort->empty() || feats_undistort == nullptr) { + continue; + } + if (imu_en) { + if (!p_imu->gravity_align_) { + while (Measures.lidar_beg_time > get_time_sec(imu_next.header.stamp)) { + imu_last = imu_next; + imu_next = *(imu_deque.front()); + imu_deque.pop_front(); + // imu_deque.pop(); + } + if (non_station_start) { + state_in.gravity << VEC_FROM_ARRAY(gravity_init); + state_out.gravity << VEC_FROM_ARRAY(gravity_init); + state_out.acc << VEC_FROM_ARRAY(gravity_init); + state_out.acc *= -1; + } else { + state_in.gravity = -1 * p_imu->mean_acc * G_m_s2 / acc_norm; + state_out.gravity = -1 * p_imu->mean_acc * G_m_s2 / acc_norm; + state_out.acc = p_imu->mean_acc * G_m_s2 / acc_norm; + } + if (gravity_align) { + Eigen::Matrix3d rot_init; + p_imu->gravity_ << VEC_FROM_ARRAY(gravity); + p_imu->Set_init(state_in.gravity, rot_init); + state_in.gravity = state_out.gravity = p_imu->gravity_; + state_in.rot = state_out.rot = rot_init; + state_in.rot.normalize(); + state_out.rot.normalize(); + state_out.acc = -rot_init.transpose() * state_out.gravity; + } + kf_input.change_x(state_in); + kf_output.change_x(state_out); + } + } else { + if (!p_imu->gravity_align_) { + state_in.gravity << VEC_FROM_ARRAY(gravity_init); + state_out.gravity << VEC_FROM_ARRAY(gravity_init); + state_out.acc << VEC_FROM_ARRAY(gravity_init); + state_out.acc *= -1; + } + } + /*** Segment the map in lidar FOV ***/ + lasermap_fov_segment(); + /*** downsample the feature points in a scan ***/ + t1 = omp_get_wtime(); + if (space_down_sample) { + downSizeFilterSurf.setInputCloud(feats_undistort); + downSizeFilterSurf.filter(*feats_down_body); + sort(feats_down_body->points.begin(), feats_down_body->points.end(), time_list); + } else { + feats_down_body = Measures.lidar; + sort(feats_down_body->points.begin(), feats_down_body->points.end(), time_list); + } + time_seq = time_compressing(feats_down_body); + feats_down_size = feats_down_body->points.size(); + + /*** initialize the map kdtree ***/ + if (!init_map) { + if (ikdtree.Root_Node == nullptr) // + // if(feats_down_size > 5) + { + ikdtree.set_downsample_param(filter_size_map_min); + } + + feats_down_world->resize(feats_down_size); + for (int i = 0; i < feats_down_size; i++) { + pointBodyToWorld(&(feats_down_body->points[i]), &(feats_down_world->points[i])); + } + for (size_t i = 0; i < feats_down_world->size(); i++) { + init_feats_world->points.emplace_back(feats_down_world->points[i]); + } + if (init_feats_world->size() < init_map_size) continue; + ikdtree.Build(init_feats_world->points); + init_map = true; + publish_init_kdtree(pubLaserCloudMap); //(pubLaserCloudFullRes); + continue; + } + /*** ICP and Kalman filter update ***/ + normvec->resize(feats_down_size); + feats_down_world->resize(feats_down_size); + + Nearest_Points.resize(feats_down_size); + + t2 = omp_get_wtime(); + + /*** iterated state estimation ***/ + crossmat_list.reserve(feats_down_size); + pbody_list.reserve(feats_down_size); + // pbody_ext_list.reserve(feats_down_size); + + for (size_t i = 0; i < feats_down_body->size(); i++) { + V3D point_this(feats_down_body->points[i].x, + feats_down_body->points[i].y, + feats_down_body->points[i].z); + pbody_list[i] = point_this; + if (extrinsic_est_en) { + if (!use_imu_as_input) { + point_this = kf_output.x_.offset_R_L_I.normalized() * point_this + kf_output.x_.offset_T_L_I; + } else { + point_this = kf_input.x_.offset_R_L_I.normalized() * point_this + kf_input.x_.offset_T_L_I; + } + } else { + point_this = Lidar_R_wrt_IMU * point_this + Lidar_T_wrt_IMU; + } + M3D point_crossmat; + point_crossmat << SKEW_SYM_MATRX(point_this); + crossmat_list[i] = point_crossmat; + } + + if (!use_imu_as_input) { + bool imu_upda_cov = false; + effct_feat_num = 0; + /**** point by point update ****/ + + double pcl_beg_time = Measures.lidar_beg_time; + idx = -1; + for (k = 0; k < time_seq.size(); k++) { + PointType &point_body = feats_down_body->points[idx + time_seq[k]]; + + time_current = point_body.curvature / 1000.0 + pcl_beg_time; + + if (is_first_frame) { + if (imu_en) { + while (time_current > get_time_sec(imu_next.header.stamp)) { + imu_last = imu_next; + imu_next = *(imu_deque.front()); + imu_deque.pop_front(); + // imu_deque.pop(); + } + + angvel_avr + << imu_last.angular_velocity.x, imu_last.angular_velocity.y, imu_last.angular_velocity.z; + acc_avr + << imu_last.linear_acceleration.x, imu_last.linear_acceleration.y, imu_last.linear_acceleration.z; + } + is_first_frame = false; + imu_upda_cov = true; + time_update_last = time_current; + time_predict_last_const = time_current; + } + if (imu_en) { + bool imu_comes = time_current > get_time_sec(imu_next.header.stamp); + while (imu_comes) { + imu_upda_cov = true; + angvel_avr + << imu_next.angular_velocity.x, imu_next.angular_velocity.y, imu_next.angular_velocity.z; + acc_avr + << imu_next.linear_acceleration.x, imu_next.linear_acceleration.y, imu_next.linear_acceleration.z; + + /*** covariance update ***/ + imu_last = imu_next; + imu_next = *(imu_deque.front()); + imu_deque.pop_front(); + double dt = get_time_sec(imu_last.header.stamp) - time_predict_last_const; + kf_output.predict(dt, Q_output, input_in, true, false); + time_predict_last_const = get_time_sec(imu_last.header.stamp); // big problem + imu_comes = time_current > get_time_sec(imu_next.header.stamp); + // if (!imu_comes) + { + double dt_cov = get_time_sec(imu_last.header.stamp) - time_update_last; + + if (dt_cov > 0.0) { + time_update_last = get_time_sec(imu_last.header.stamp); + double propag_imu_start = omp_get_wtime(); + + kf_output.predict(dt_cov, Q_output, input_in, false, true); + + propag_time += omp_get_wtime() - propag_imu_start; + double solve_imu_start = omp_get_wtime(); + kf_output.update_iterated_dyn_share_IMU(); + solve_time += omp_get_wtime() - solve_imu_start; + } + } + } + } + + double dt = time_current - time_predict_last_const; + double propag_state_start = omp_get_wtime(); + if (!prop_at_freq_of_imu) { + double dt_cov = time_current - time_update_last; + if (dt_cov > 0.0) { + kf_output.predict(dt_cov, Q_output, input_in, false, true); + time_update_last = time_current; + } + } + kf_output.predict(dt, Q_output, input_in, true, false); + propag_time += omp_get_wtime() - propag_state_start; + time_predict_last_const = time_current; + // if(k == 0) + // { + // fout_imu_pbp << Measures.lidar_last_time - first_lidar_time << " " << imu_last.angular_velocity.x << " " << imu_last.angular_velocity.y << " " << imu_last.angular_velocity.z \ + // << " " << imu_last.linear_acceleration.x << " " << imu_last.linear_acceleration.y << " " << imu_last.linear_acceleration.z << endl; + // } + + double t_update_start = omp_get_wtime(); + + if (feats_down_size < 1) { + RCLCPP_WARN(logger, "No point, skip this scan!\n"); + idx += time_seq[k]; + continue; + } + if (!kf_output.update_iterated_dyn_share_modified()) { + idx = idx + time_seq[k]; + continue; + } + + if (prop_at_freq_of_imu) { + double dt_cov = time_current - time_update_last; + if (!imu_en && (dt_cov >= imu_time_inte)) // (point_cov_not_prop && imu_prop_cov) + { + double propag_cov_start = omp_get_wtime(); + kf_output.predict(dt_cov, Q_output, input_in, false, true); + imu_upda_cov = false; + time_update_last = time_current; + propag_time += omp_get_wtime() - propag_cov_start; + } + } + + solve_start = omp_get_wtime(); + + if (publish_odometry_without_downsample) { + /******* Publish odometry *******/ + + publish_odometry(pubOdomAftMapped, tf_broadcaster); + if (runtime_pos_log) { + state_out = kf_output.x_; + euler_cur = SO3ToEuler(state_out.rot); + fout_out << setw(20) << Measures.lidar_beg_time - first_lidar_time << " " + << euler_cur.transpose() << " " << state_out.pos.transpose() << " " + << state_out.vel.transpose() << " " << state_out.omg.transpose() << " " + << state_out.acc.transpose() << " " << state_out.gravity.transpose() << " " + << state_out.bg.transpose() << " " << state_out.ba.transpose() << " " + << feats_undistort->points.size() << endl; + } + } + + for (int j = 0; j < time_seq[k]; j++) { + PointType &point_body_j = feats_down_body->points[idx + j + 1]; + PointType &point_world_j = feats_down_world->points[idx + j + 1]; + pointBodyToWorld(&point_body_j, &point_world_j); + } + + solve_time += omp_get_wtime() - solve_start; + + update_time += omp_get_wtime() - t_update_start; + idx += time_seq[k]; + // cout << "pbp output effect feat num:" << effct_feat_num << endl; + } + } else { + bool imu_prop_cov = false; + effct_feat_num = 0; + + double pcl_beg_time = Measures.lidar_beg_time; + idx = -1; + for (k = 0; k < time_seq.size(); k++) { + PointType &point_body = feats_down_body->points[idx + time_seq[k]]; + time_current = point_body.curvature / 1000.0 + pcl_beg_time; + if (is_first_frame) { + while (time_current > get_time_sec(imu_next.header.stamp)) { + imu_last = imu_next; + imu_next = *(imu_deque.front()); + imu_deque.pop_front(); + // imu_deque.pop(); + } + imu_prop_cov = true; + // imu_upda_cov = true; + + is_first_frame = false; + t_last = time_current; + time_update_last = time_current; + // if(prop_at_freq_of_imu) + { + input_in.gyro << imu_last.angular_velocity.x, + imu_last.angular_velocity.y, + imu_last.angular_velocity.z; + + input_in.acc << imu_last.linear_acceleration.x, + imu_last.linear_acceleration.y, + imu_last.linear_acceleration.z; + // angvel_avr<<0.5 * (imu_last.angular_velocity.x + imu_next.angular_velocity.x), + // 0.5 * (imu_last.angular_velocity.y + imu_next.angular_velocity.y), + // 0.5 * (imu_last.angular_velocity.z + imu_next.angular_velocity.z); + + // acc_avr <<0.5 * (imu_last.linear_acceleration.x + imu_next.linear_acceleration.x), + // 0.5 * (imu_last.linear_acceleration.y + imu_next.linear_acceleration.y), + // 0.5 * (imu_last.linear_acceleration.z + imu_next.linear_acceleration.z); + + // angvel_avr -= state.bias_g; + input_in.acc = input_in.acc * G_m_s2 / acc_norm; + } + } + + while (time_current > get_time_sec(imu_next.header.stamp)) // && !imu_deque.empty()) + { + imu_last = imu_next; + imu_next = *(imu_deque.front()); + imu_deque.pop_front(); + input_in.gyro + << imu_last.angular_velocity.x, imu_last.angular_velocity.y, imu_last.angular_velocity.z; + input_in.acc + << imu_last.linear_acceleration.x, imu_last.linear_acceleration.y, imu_last.linear_acceleration.z; + + // angvel_avr<<0.5 * (imu_last.angular_velocity.x + imu_next.angular_velocity.x), + // 0.5 * (imu_last.angular_velocity.y + imu_next.angular_velocity.y), + // 0.5 * (imu_last.angular_velocity.z + imu_next.angular_velocity.z); + + // acc_avr <<0.5 * (imu_last.linear_acceleration.x + imu_next.linear_acceleration.x), + // 0.5 * (imu_last.linear_acceleration.y + imu_next.linear_acceleration.y), + // 0.5 * (imu_last.linear_acceleration.z + imu_next.linear_acceleration.z); + input_in.acc = input_in.acc * G_m_s2 / acc_norm; + double dt = get_time_sec(imu_last.header.stamp) - t_last; + + // if(!prop_at_freq_of_imu) + // { + double dt_cov = get_time_sec(imu_last.header.stamp) - time_update_last; + if (dt_cov > 0.0) { + kf_input.predict(dt_cov, Q_input, input_in, false, true); + time_update_last = get_time_sec(imu_last.header.stamp); //time_current; + } + kf_input.predict(dt, Q_input, input_in, true, false); + t_last = get_time_sec(imu_last.header.stamp); + imu_prop_cov = true; + // imu_upda_cov = true; + } + + double dt = time_current - t_last; + t_last = time_current; + double propag_start = omp_get_wtime(); + + if (!prop_at_freq_of_imu) { + double dt_cov = time_current - time_update_last; + if (dt_cov > 0.0) { + kf_input.predict(dt_cov, Q_input, input_in, false, true); + time_update_last = time_current; + } + } + kf_input.predict(dt, Q_input, input_in, true, false); + + propag_time += omp_get_wtime() - propag_start; + + // if(k == 0) + // { + // fout_imu_pbp << Measures.lidar_last_time - first_lidar_time << " " << imu_last.angular_velocity.x << " " << imu_last.angular_velocity.y << " " << imu_last.angular_velocity.z \ + // << " " << imu_last.linear_acceleration.x << " " << imu_last.linear_acceleration.y << " " << imu_last.linear_acceleration.z << endl; + // } + + double t_update_start = omp_get_wtime(); + + if (feats_down_size < 1) { + RCLCPP_WARN(logger, "No point, skip this scan!\n"); + + idx += time_seq[k]; + continue; + } + if (!kf_input.update_iterated_dyn_share_modified()) { + idx = idx + time_seq[k]; + continue; + } + + solve_start = omp_get_wtime(); + + // if(prop_at_freq_of_imu) + // { + // double dt_cov = time_current - time_update_last; + // if ((imu_prop_cov && dt_cov > 0.0) || (dt_cov >= imu_time_inte * 1.2)) + // { + // double propag_cov_start = omp_get_wtime(); + // kf_input.predict(dt_cov, Q_input, input_in, false, true); + // propag_time += omp_get_wtime() - propag_cov_start; + // time_update_last = time_current; + // imu_prop_cov = false; + // } + // } + if (publish_odometry_without_downsample) { + /******* Publish odometry *******/ + + publish_odometry(pubOdomAftMapped, tf_broadcaster); + if (runtime_pos_log) { + state_in = kf_input.x_; + euler_cur = SO3ToEuler(state_in.rot); + fout_out << setw(20) << Measures.lidar_beg_time - first_lidar_time << " " + << euler_cur.transpose() << " " << state_in.pos.transpose() << " " + << state_in.vel.transpose() << " " << state_in.bg.transpose() << " " + << state_in.ba.transpose() << " " << state_in.gravity.transpose() << " " + << feats_undistort->points.size() << endl; + } + } + + for (int j = 0; j < time_seq[k]; j++) { + PointType &point_body_j = feats_down_body->points[idx + j + 1]; + PointType &point_world_j = feats_down_world->points[idx + j + 1]; + pointBodyToWorld(&point_body_j, &point_world_j); + } + solve_time += omp_get_wtime() - solve_start; + + update_time += omp_get_wtime() - t_update_start; + idx = idx + time_seq[k]; + } + } + + /******* Publish odometry downsample *******/ + if (!publish_odometry_without_downsample) { + publish_odometry(pubOdomAftMapped, tf_broadcaster); + } + + /*** add the feature points to map kdtree ***/ + t3 = omp_get_wtime(); + + if (feats_down_size > 4) { + map_incremental(); + } + + t5 = omp_get_wtime(); + /******* Publish points *******/ + if (path_en) publish_path(pubPath); + if (scan_pub_en || pcd_save_en) publish_frame_world(pubLaserCloudFullRes); + if (scan_pub_en && scan_body_pub_en) publish_frame_body(pubLaserCloudFullRes_body); + + /*** Debug variables Logging ***/ + if (runtime_pos_log) { + frame_num++; + aver_time_consu = aver_time_consu * (frame_num - 1) / frame_num + (t5 - t0) / frame_num; + { aver_time_icp = aver_time_icp * (frame_num - 1) / frame_num + update_time / frame_num; } + aver_time_match = aver_time_match * (frame_num - 1) / frame_num + (match_time) / frame_num; + aver_time_solve = aver_time_solve * (frame_num - 1) / frame_num + solve_time / frame_num; + aver_time_propag = aver_time_propag * (frame_num - 1) / frame_num + propag_time / frame_num; + T1[time_log_counter] = Measures.lidar_beg_time; + s_plot[time_log_counter] = t5 - t0; + s_plot2[time_log_counter] = feats_undistort->points.size(); + s_plot3[time_log_counter] = aver_time_consu; + time_log_counter++; + printf("[ mapping ]: time: IMU + Map + Input Downsample: %0.6f ave match: %0.6f ave solve: %0.6f ave ICP: %0.6f map incre: %0.6f ave total: %0.6f icp: %0.6f propogate: %0.6f \n", + t1 - t0, aver_time_match, aver_time_solve, t3 - t1, t5 - t3, aver_time_consu, aver_time_icp, + aver_time_propag); + if (!publish_odometry_without_downsample) { + if (!use_imu_as_input) { + state_out = kf_output.x_; + euler_cur = SO3ToEuler(state_out.rot); + fout_out << setw(20) << Measures.lidar_beg_time - first_lidar_time << " " + << euler_cur.transpose() << " " << state_out.pos.transpose() << " " + << state_out.vel.transpose() << " " << state_out.omg.transpose() << " " + << state_out.acc.transpose() << " " << state_out.gravity.transpose() << " " + << state_out.bg.transpose() << " " << state_out.ba.transpose() << " " + << feats_undistort->points.size() << endl; + } else { + state_in = kf_input.x_; + euler_cur = SO3ToEuler(state_in.rot); + fout_out << setw(20) << Measures.lidar_beg_time - first_lidar_time << " " + << euler_cur.transpose() << " " << state_in.pos.transpose() << " " + << state_in.vel.transpose() << " " << state_in.bg.transpose() << " " + << state_in.ba.transpose() << " " << state_in.gravity.transpose() << " " + << feats_undistort->points.size() << endl; + } + } + dump_lio_state_to_log(fp); + } + } + rate.sleep(); + } + //--------------------------save map----------------------------------- + /* 1. make sure you have enough memories + 2. noted that pcd save will influence the real-time performences **/ + if (pcl_wait_save->size() > 0 && pcd_save_en) { + string file_name = string("scans.pcd"); + string all_points_dir(string(string(ROOT_DIR) + "PCD/") + file_name); + pcl::PCDWriter pcd_writer; + pcd_writer.writeBinary(all_points_dir, *pcl_wait_save); + } + fout_out.close(); + fout_imu_pbp.close(); + + return 0; +} diff --git a/point_lio_ros2/src/parameters.cpp b/point_lio_ros2/src/parameters.cpp new file mode 100644 index 0000000..6ab2795 --- /dev/null +++ b/point_lio_ros2/src/parameters.cpp @@ -0,0 +1,157 @@ +#include "parameters.h" + +bool odom_only; +std::string odom_header_frame_id, odom_child_frame_id; + +bool is_first_frame = true; +double lidar_end_time = 0.0, first_lidar_time = 0.0, time_con = 0.0; +double last_timestamp_lidar = -1.0, last_timestamp_imu = -1.0; +int pcd_index = 0; + +std::string lid_topic, imu_topic; +bool prop_at_freq_of_imu, check_satu, con_frame, cut_frame; +bool use_imu_as_input, space_down_sample, publish_odometry_without_downsample; +int init_map_size, con_frame_num; +double match_s, satu_acc, satu_gyro, cut_frame_time_interval; +float plane_thr; +double filter_size_surf_min, filter_size_map_min, fov_deg; +double cube_len; +float DET_RANGE; +bool imu_en, gravity_align, non_station_start; +double imu_time_inte; +double laser_point_cov, acc_norm; +double vel_cov, acc_cov_input, gyr_cov_input; +double gyr_cov_output, acc_cov_output, b_gyr_cov, b_acc_cov; +double imu_meas_acc_cov, imu_meas_omg_cov; +int lidar_type, pcd_save_interval; +std::vector gravity_init, gravity; +std::vector extrinT; +std::vector extrinR; +bool runtime_pos_log, pcd_save_en, path_en, extrinsic_est_en = true; +bool scan_pub_en, scan_body_pub_en; +shared_ptr p_pre; +double time_lag_imu_to_lidar = 0.0; + +void readParameters(shared_ptr &nh) { + p_pre.reset(new Preprocess()); + + nh->declare_parameter("odom_only", false); + nh->declare_parameter("odom_header_frame_id", "camera_init"); + nh->declare_parameter("odom_child_frame_id", "aft_mapped"); + + nh->declare_parameter("prop_at_freq_of_imu", true); + nh->declare_parameter("use_imu_as_input", true); + nh->declare_parameter("check_satu", true); + nh->declare_parameter("init_map_size", 100); + nh->declare_parameter("space_down_sample", true); + nh->declare_parameter("mapping.satu_acc", 3.0); + nh->declare_parameter("mapping.satu_gyro", 35.0); + nh->declare_parameter("mapping.acc_norm", 1.0); + nh->declare_parameter("mapping.plane_thr", 0.05f); + nh->declare_parameter("point_filter_num", 2); + nh->declare_parameter("common.lid_topic", "/livox/lidar"); + nh->declare_parameter("common.imu_topic", "/livox/imu"); + nh->declare_parameter("common.con_frame", false); + nh->declare_parameter("common.con_frame_num", 1); + nh->declare_parameter("common.cut_frame", false); + nh->declare_parameter("common.cut_frame_time_interval", 0.1); + nh->declare_parameter("common.time_lag_imu_to_lidar", 0.0); + nh->declare_parameter("filter_size_surf", 0.5); + nh->declare_parameter("filter_size_map", 0.5); + nh->declare_parameter("cube_side_length", 200); + nh->declare_parameter("mapping.det_range", 300.f); + nh->declare_parameter("mapping.fov_degree", 180); + nh->declare_parameter("mapping.imu_en", true); + nh->declare_parameter("mapping.start_in_aggressive_motion", false); + nh->declare_parameter("mapping.extrinsic_est_en", true); + nh->declare_parameter("mapping.imu_time_inte", 0.005); + nh->declare_parameter("mapping.lidar_meas_cov", 0.1); + nh->declare_parameter("mapping.acc_cov_input", 0.1); + nh->declare_parameter("mapping.vel_cov", 20); + nh->declare_parameter("mapping.gyr_cov_input", 0.1); + nh->declare_parameter("mapping.gyr_cov_output", 0.1); + nh->declare_parameter("mapping.acc_cov_output", 0.1); + nh->declare_parameter("mapping.b_gyr_cov", 0.0001); + nh->declare_parameter("mapping.b_acc_cov", 0.0001); + nh->declare_parameter("mapping.imu_meas_acc_cov", 0.1); + nh->declare_parameter("mapping.imu_meas_omg_cov", 0.1); + nh->declare_parameter("preprocess.blind", 1.0); + nh->declare_parameter("preprocess.lidar_type", 1); + nh->declare_parameter("preprocess.scan_line", 16); + nh->declare_parameter("preprocess.scan_rate", 10); + nh->declare_parameter("preprocess.timestamp_unit", 1); + nh->declare_parameter("mapping.match_s", 81); + nh->declare_parameter("mapping.gravity_align", true); + nh->declare_parameter>("mapping.gravity", {0, 0, -9.810}); + nh->declare_parameter>("mapping.gravity_init", {0, 0, -9.810}); + nh->declare_parameter>("mapping.extrinsic_T", {0, 0, 0}); + nh->declare_parameter>("mapping.extrinsic_R", {1, 0, 0, 0, 1, 0, 0, 0, 1}); + nh->declare_parameter("odometry.publish_odometry_without_downsample", false); + nh->declare_parameter("publish.path_en", true); + nh->declare_parameter("publish.scan_publish_en", true); + nh->declare_parameter("publish.scan_bodyframe_pub_en", true); + nh->declare_parameter("runtime_pos_log_enable", false); + nh->declare_parameter("pcd_save.pcd_save_en", false); + nh->declare_parameter("pcd_save.interval", -1); + + // 使用get_parameter方法获取参数值 + nh->get_parameter("odom_only", odom_only); + nh->get_parameter("odom_header_frame_id", odom_header_frame_id); + nh->get_parameter("odom_child_frame_id", odom_child_frame_id); + + nh->get_parameter("prop_at_freq_of_imu", prop_at_freq_of_imu); + nh->get_parameter("use_imu_as_input", use_imu_as_input); + nh->get_parameter("check_satu", check_satu); + nh->get_parameter("init_map_size", init_map_size); + nh->get_parameter("space_down_sample", space_down_sample); + nh->get_parameter("mapping.satu_acc", satu_acc); + nh->get_parameter("mapping.satu_gyro", satu_gyro); + nh->get_parameter("mapping.acc_norm", acc_norm); + nh->get_parameter("mapping.plane_thr", plane_thr); + nh->get_parameter("point_filter_num", p_pre->point_filter_num); + nh->get_parameter("common.lid_topic", lid_topic); + nh->get_parameter("common.imu_topic", imu_topic); + nh->get_parameter("common.con_frame", con_frame); + nh->get_parameter("common.con_frame_num", con_frame_num); + nh->get_parameter("common.cut_frame", cut_frame); + nh->get_parameter("common.cut_frame_time_interval", cut_frame_time_interval); + nh->get_parameter("common.time_lag_imu_to_lidar", time_lag_imu_to_lidar); + nh->get_parameter("filter_size_surf", filter_size_surf_min); + nh->get_parameter("filter_size_map", filter_size_map_min); + nh->get_parameter("cube_side_length", cube_len); + nh->get_parameter("mapping.det_range", DET_RANGE); + nh->get_parameter("mapping.fov_degree", fov_deg); + nh->get_parameter("mapping.imu_en", imu_en); + nh->get_parameter("mapping.start_in_aggressive_motion", non_station_start); + nh->get_parameter("mapping.extrinsic_est_en", extrinsic_est_en); + nh->get_parameter("mapping.imu_time_inte", imu_time_inte); + nh->get_parameter("mapping.lidar_meas_cov", laser_point_cov); + nh->get_parameter("mapping.acc_cov_input", acc_cov_input); + nh->get_parameter("mapping.vel_cov", vel_cov); + nh->get_parameter("mapping.gyr_cov_input", gyr_cov_input); + nh->get_parameter("mapping.gyr_cov_output", gyr_cov_output); + nh->get_parameter("mapping.acc_cov_output", acc_cov_output); + nh->get_parameter("mapping.b_gyr_cov", b_gyr_cov); + nh->get_parameter("mapping.b_acc_cov", b_acc_cov); + nh->get_parameter("mapping.imu_meas_acc_cov", imu_meas_acc_cov); + nh->get_parameter("mapping.imu_meas_omg_cov", imu_meas_omg_cov); + nh->get_parameter("preprocess.blind", p_pre->blind); + nh->get_parameter("preprocess.lidar_type", lidar_type); + nh->get_parameter("preprocess.scan_line", p_pre->N_SCANS); + nh->get_parameter("preprocess.scan_rate", p_pre->SCAN_RATE); + nh->get_parameter("preprocess.timestamp_unit", p_pre->time_unit); + nh->get_parameter("mapping.match_s", match_s); + nh->get_parameter("mapping.gravity_align", gravity_align); + nh->get_parameter("mapping.gravity", gravity); + nh->get_parameter("mapping.gravity_init", gravity_init); + nh->get_parameter("mapping.extrinsic_T", extrinT); + nh->get_parameter("mapping.extrinsic_R", extrinR); + nh->get_parameter("odometry.publish_odometry_without_downsample", publish_odometry_without_downsample); + nh->get_parameter("publish.path_en", path_en); + nh->get_parameter("publish.scan_publish_en", scan_pub_en); + nh->get_parameter("publish.scan_bodyframe_pub_en", scan_body_pub_en); + nh->get_parameter("runtime_pos_log_enable", runtime_pos_log); + nh->get_parameter("pcd_save.pcd_save_en", pcd_save_en); + nh->get_parameter("pcd_save.interval", pcd_save_interval); +} + diff --git a/point_lio_ros2/src/parameters.h b/point_lio_ros2/src/parameters.h new file mode 100644 index 0000000..03e0c96 --- /dev/null +++ b/point_lio_ros2/src/parameters.h @@ -0,0 +1,46 @@ +// #ifndef PARAM_H +// #define PARAM_H +#pragma once + +#include +#include +#include +#include +#include +#include "preprocess.h" + +extern bool odom_only; +extern std::string odom_header_frame_id; +extern std::string odom_child_frame_id; + +extern bool is_first_frame; +extern double lidar_end_time, first_lidar_time, time_con; +extern double last_timestamp_lidar, last_timestamp_imu; +extern int pcd_index; + +extern std::string lid_topic, imu_topic; +extern bool prop_at_freq_of_imu, check_satu, con_frame, cut_frame; +extern bool use_imu_as_input, space_down_sample; +extern bool extrinsic_est_en, publish_odometry_without_downsample; +extern int init_map_size, con_frame_num; +extern double match_s, satu_acc, satu_gyro, cut_frame_time_interval; +extern float plane_thr; +extern double filter_size_surf_min, filter_size_map_min, fov_deg; +extern double cube_len; +extern float DET_RANGE; +extern bool imu_en, gravity_align, non_station_start; +extern double imu_time_inte; +extern double laser_point_cov, acc_norm; +extern double acc_cov_input, gyr_cov_input, vel_cov; +extern double gyr_cov_output, acc_cov_output, b_gyr_cov, b_acc_cov; +extern double imu_meas_acc_cov, imu_meas_omg_cov; +extern int lidar_type, pcd_save_interval; +extern std::vector gravity_init, gravity; +extern std::vector extrinT; +extern std::vector extrinR; +extern bool runtime_pos_log, pcd_save_en, path_en; +extern bool scan_pub_en, scan_body_pub_en; +extern shared_ptr p_pre; +extern double time_lag_imu_to_lidar; + +void readParameters(shared_ptr &nh); diff --git a/point_lio_ros2/src/preprocess.cpp b/point_lio_ros2/src/preprocess.cpp new file mode 100644 index 0000000..da017ac --- /dev/null +++ b/point_lio_ros2/src/preprocess.cpp @@ -0,0 +1,732 @@ +#include "preprocess.h" + +#define RETURN0 0x00 +#define RETURN0AND1 0x10 + +Preprocess::Preprocess() + : lidar_type(AVIA), blind(0.01), point_filter_num(1) { + inf_bound = 10; + N_SCANS = 6; + SCAN_RATE = 10; + group_size = 8; + disA = 0.01; + disA = 0.1; // B? + p2l_ratio = 225; + limit_maxmid = 6.25; + limit_midmin = 6.25; + limit_maxmin = 3.24; + jump_up_limit = 170.0; + jump_down_limit = 8.0; + cos160 = 160.0; + edgea = 2; + edgeb = 0.1; + smallp_intersect = 172.5; + smallp_ratio = 1.2; + given_offset_time = false; + + jump_up_limit = cos(jump_up_limit / 180 * M_PI); + jump_down_limit = cos(jump_down_limit / 180 * M_PI); + cos160 = cos(cos160 / 180 * M_PI); + smallp_intersect = cos(smallp_intersect / 180 * M_PI); +} + +Preprocess::~Preprocess() {} + +void Preprocess::set(bool feat_en, int lid_type, double bld, int pfilt_num) { + lidar_type = lid_type; + blind = bld; + point_filter_num = pfilt_num; +} + +// void Preprocess::process(const livox_ros_driver2::msg::CustomMsg::SharedPtr &msg, PointCloudXYZI::Ptr &pcl_out) { +// avia_handler(msg); +// *pcl_out = pl_surf; +// } + +void Preprocess::process(const sensor_msgs::msg::PointCloud2::SharedPtr &msg, PointCloudXYZI::Ptr &pcl_out) { + switch (time_unit) { + case SEC: + time_unit_scale = 1.e3f; + break; + case MS: + time_unit_scale = 1.f; + break; + case US: + time_unit_scale = 1.e-3f; + break; + case NS: + time_unit_scale = 1.e-6f; + break; + default: + time_unit_scale = 1.f; + break; + } + + switch (lidar_type) { + case OUST64: + oust64_handler(msg); + break; + + case VELO16: + velodyne_handler(msg); + break; + + case HESAIxt32: + hesai_handler(msg); + break; + + case UNILIDAR: + unilidar_handler(msg); + break; + + default: + printf("Error LiDAR Type"); + break; + } + *pcl_out = pl_surf; +} + +// void Preprocess::avia_handler(const livox_ros_driver2::msg::CustomMsg::SharedPtr &msg) { +// pl_surf.clear(); +// pl_corn.clear(); +// pl_full.clear(); +// double t1 = omp_get_wtime(); +// int plsize = msg->point_num; + +// pl_corn.reserve(plsize); +// pl_surf.reserve(plsize); +// pl_full.resize(plsize); + +// uint valid_num = 0; + +// for (uint i = 1; i < plsize; i++) { +// if ((msg->points[i].line < N_SCANS) && +// ((msg->points[i].tag & 0x30) == 0x10 || (msg->points[i].tag & 0x30) == 0x00)) { +// valid_num++; +// if (valid_num % point_filter_num == 0) { +// pl_full[i].x = msg->points[i].x; +// pl_full[i].y = msg->points[i].y; +// pl_full[i].z = msg->points[i].z; +// pl_full[i].intensity = msg->points[i].reflectivity; +// pl_full[i].curvature = msg->points[i].offset_time / +// float(1000000); // use curvature as time of each laser points, curvature unit: ms + +// if (i == 0) pl_full[i].curvature = fabs(pl_full[i].curvature) < 1.0 ? pl_full[i].curvature : 0.0; +// else pl_full[i].curvature = +// fabs(pl_full[i].curvature - pl_full[i - 1].curvature) < 1.0 ? pl_full[i].curvature : +// pl_full[i - 1].curvature + 0.004166667f; + +// if ((abs(pl_full[i].x - pl_full[i - 1].x) > 1e-7) +// || (abs(pl_full[i].y - pl_full[i - 1].y) > 1e-7) +// || (abs(pl_full[i].z - pl_full[i - 1].z) > 1e-7) +// && (pl_full[i].x * pl_full[i].x + pl_full[i].y * pl_full[i].y + pl_full[i].z * pl_full[i].z > +// (blind * blind))) { +// pl_surf.push_back(pl_full[i]); +// } +// } +// } +// } + +// } + +void Preprocess::oust64_handler(const sensor_msgs::msg::PointCloud2::SharedPtr &msg) { + pl_surf.clear(); + pl_corn.clear(); + pl_full.clear(); + pcl::PointCloud pl_orig; + pcl::fromROSMsg(*msg, pl_orig); + int plsize = pl_orig.size(); + pl_corn.reserve(plsize); + pl_surf.reserve(plsize); + + + double time_stamp = rclcpp::Time(msg->header.stamp).seconds(); + // cout << "===================================" << endl; + // printf("Pt size = %d, N_SCANS = %d\r\n", plsize, N_SCANS); + for (int i = 0; i < pl_orig.points.size(); i++) { + if (i % point_filter_num != 0) continue; + + double range = pl_orig.points[i].x * pl_orig.points[i].x + pl_orig.points[i].y * pl_orig.points[i].y + + pl_orig.points[i].z * pl_orig.points[i].z; + + if (range < (blind * blind)) continue; + + Eigen::Vector3d pt_vec; + PointType added_pt; + added_pt.x = pl_orig.points[i].x; + added_pt.y = pl_orig.points[i].y; + added_pt.z = pl_orig.points[i].z; + added_pt.intensity = pl_orig.points[i].intensity; + added_pt.normal_x = 0; + added_pt.normal_y = 0; + added_pt.normal_z = 0; + added_pt.curvature = pl_orig.points[i].t * time_unit_scale; // curvature unit: ms + + pl_surf.points.push_back(added_pt); + } + + // pub_func(pl_surf, pub_full, msg->header.stamp); + // pub_func(pl_surf, pub_corn, msg->header.stamp); +} + +void Preprocess::velodyne_handler(const sensor_msgs::msg::PointCloud2::SharedPtr &msg) { + pl_surf.clear(); + pl_corn.clear(); + pl_full.clear(); + + pcl::PointCloud pl_orig; + pcl::fromROSMsg(*msg, pl_orig); + int plsize = pl_orig.points.size(); + if (plsize == 0) return; + pl_surf.reserve(plsize); + + /*** These variables only works when no point timestamps given ***/ + double omega_l = 0.361 * SCAN_RATE; // scan angular velocity + std::vector is_first(N_SCANS, true); + std::vector yaw_fp(N_SCANS, 0.0); // yaw of first scan point + std::vector yaw_last(N_SCANS, 0.0); // yaw of last scan point + std::vector time_last(N_SCANS, 0.0); // last offset time + /*****************************************************************/ + + if (pl_orig.points[plsize - 1].time > 0) { + given_offset_time = true; + } else { + given_offset_time = false; + double yaw_first = atan2(pl_orig.points[0].y, pl_orig.points[0].x) * 57.29578; + double yaw_end = yaw_first; + int layer_first = pl_orig.points[0].ring; + for (uint i = plsize - 1; i > 0; i--) { + if (pl_orig.points[i].ring == layer_first) { + yaw_end = atan2(pl_orig.points[i].y, pl_orig.points[i].x) * 57.29578; + break; + } + } + } + + for (int i = 0; i < plsize; i++) { + PointType added_pt; + // cout<<"!!!!!!"< (blind * blind)) + { + pl_surf.points.push_back(added_pt); + } + } + } + +} + +void Preprocess::unilidar_handler(const sensor_msgs::msg::PointCloud2::SharedPtr &msg) +{ + pl_surf.clear(); + pl_corn.clear(); + pl_full.clear(); + + pcl::PointCloud pl_orig; + pcl::fromROSMsg(*msg, pl_orig); + int plsize = pl_orig.points.size(); + if (plsize == 0) return; + + pl_surf.reserve(plsize); + + // std::cout << "plsize = " << plsize << ", given_offset_time = " << given_offset_time << std::endl; + int countElimnated = 0; + for (int i = 0; i < plsize; i++) + { + PointType added_pt; + + added_pt.normal_x = 0; + added_pt.normal_y = 0; + added_pt.normal_z = 0; + + added_pt.x = pl_orig.points[i].x; + added_pt.y = pl_orig.points[i].y; + added_pt.z = pl_orig.points[i].z; + + added_pt.intensity = pl_orig.points[i].intensity; + + added_pt.curvature = pl_orig.points[i].time * time_unit_scale; + + if (added_pt.x * added_pt.x + added_pt.y * added_pt.y + added_pt.z * added_pt.z > (blind * blind)) + { + pl_surf.points.push_back(added_pt); + } + else + { + countElimnated++; + } + } + + // std::cout << "pl_surf.size() = " << pl_surf.size() << ", countElimnated = " << countElimnated << std::endl; + +} + +void Preprocess::hesai_handler(const sensor_msgs::msg::PointCloud2::SharedPtr &msg) { + pl_surf.clear(); + pl_corn.clear(); + pl_full.clear(); + + pcl::PointCloud pl_orig; + pcl::fromROSMsg(*msg, pl_orig); + int plsize = pl_orig.points.size(); + if (plsize == 0) return; + pl_surf.reserve(plsize); + + /*** These variables only works when no point timestamps given ***/ + double omega_l = 0.361 * SCAN_RATE; // scan angular velocity + std::vector is_first(N_SCANS, true); + std::vector yaw_fp(N_SCANS, 0.0); // yaw of first scan point + std::vector yaw_last(N_SCANS, 0.0); // yaw of last scan point + std::vector time_last(N_SCANS, 0.0); // last offset time + /*****************************************************************/ + + if (pl_orig.points[plsize - 1].timestamp > 0) { + given_offset_time = true; + } else { + given_offset_time = false; + double yaw_first = atan2(pl_orig.points[0].y, pl_orig.points[0].x) * 57.29578; + double yaw_end = yaw_first; + int layer_first = pl_orig.points[0].ring; + for (uint i = plsize - 1; i > 0; i--) { + if (pl_orig.points[i].ring == layer_first) { + yaw_end = atan2(pl_orig.points[i].y, pl_orig.points[i].x) * 57.29578; + break; + } + } + } + + double time_head = pl_orig.points[0].timestamp; + + for (int i = 0; i < plsize; i++) { + PointType added_pt; + // cout<<"!!!!!!"< (blind * blind)) { + pl_surf.points.push_back(added_pt); + } + } + } + +} + +void Preprocess::give_feature(pcl::PointCloud &pl, vector &types) { + int plsize = pl.size(); + int plsize2; + if (plsize == 0) { + printf("something wrong\n"); + return; + } + uint head = 0; + + while (types[head].range < blind) { + head++; + } + + // Surf + plsize2 = (plsize > group_size) ? (plsize - group_size) : 0; + + Eigen::Vector3d curr_direct(Eigen::Vector3d::Zero()); + Eigen::Vector3d last_direct(Eigen::Vector3d::Zero()); + + uint i_nex = 0, i2; + uint last_i = 0; + uint last_i_nex = 0; + int last_state = 0; + int plane_type; + + for (uint i = head; i < plsize2; i++) { + if (types[i].range < blind) { + continue; + } + + i2 = i; + + plane_type = plane_judge(pl, types, i, i_nex, curr_direct); + + if (plane_type == 1) { + for (uint j = i; j <= i_nex; j++) { + if (j != i && j != i_nex) { + types[j].ftype = Real_Plane; + } else { + types[j].ftype = Poss_Plane; + } + } + + // if(last_state==1 && fabs(last_direct.sum())>0.5) + if (last_state == 1 && last_direct.norm() > 0.1) { + double mod = last_direct.transpose() * curr_direct; + if (mod > -0.707 && mod < 0.707) { + types[i].ftype = Edge_Plane; + } else { + types[i].ftype = Real_Plane; + } + } + + i = i_nex - 1; + last_state = 1; + } else // if(plane_type == 2) + { + i = i_nex; + last_state = 0; + } + + last_i = i2; + last_i_nex = i_nex; + last_direct = curr_direct; + } + + plsize2 = plsize > 3 ? plsize - 3 : 0; + for (uint i = head + 3; i < plsize2; i++) { + if (types[i].range < blind || types[i].ftype >= Real_Plane) { + continue; + } + + if (types[i - 1].dista < 1e-16 || types[i].dista < 1e-16) { + continue; + } + + Eigen::Vector3d vec_a(pl[i].x, pl[i].y, pl[i].z); + Eigen::Vector3d vecs[2]; + + for (int j = 0; j < 2; j++) { + int m = -1; + if (j == 1) { + m = 1; + } + + if (types[i + m].range < blind) { + if (types[i].range > inf_bound) { + types[i].edj[j] = Nr_inf; + } else { + types[i].edj[j] = Nr_blind; + } + continue; + } + + vecs[j] = Eigen::Vector3d(pl[i + m].x, pl[i + m].y, pl[i + m].z); + vecs[j] = vecs[j] - vec_a; + + types[i].angle[j] = vec_a.dot(vecs[j]) / vec_a.norm() / vecs[j].norm(); + if (types[i].angle[j] < jump_up_limit) { + types[i].edj[j] = Nr_180; + } else if (types[i].angle[j] > jump_down_limit) { + types[i].edj[j] = Nr_zero; + } + } + + types[i].intersect = vecs[Prev].dot(vecs[Next]) / vecs[Prev].norm() / vecs[Next].norm(); + if (types[i].edj[Prev] == Nr_nor && types[i].edj[Next] == Nr_zero && types[i].dista > 0.0225 && + types[i].dista > 4 * types[i - 1].dista) { + if (types[i].intersect > cos160) { + if (edge_jump_judge(pl, types, i, Prev)) { + types[i].ftype = Edge_Jump; + } + } + } else if (types[i].edj[Prev] == Nr_zero && types[i].edj[Next] == Nr_nor && types[i - 1].dista > 0.0225 && + types[i - 1].dista > 4 * types[i].dista) { + if (types[i].intersect > cos160) { + if (edge_jump_judge(pl, types, i, Next)) { + types[i].ftype = Edge_Jump; + } + } + } else if (types[i].edj[Prev] == Nr_nor && types[i].edj[Next] == Nr_inf) { + if (edge_jump_judge(pl, types, i, Prev)) { + types[i].ftype = Edge_Jump; + } + } else if (types[i].edj[Prev] == Nr_inf && types[i].edj[Next] == Nr_nor) { + if (edge_jump_judge(pl, types, i, Next)) { + types[i].ftype = Edge_Jump; + } + + } else if (types[i].edj[Prev] > Nr_nor && types[i].edj[Next] > Nr_nor) { + if (types[i].ftype == Nor) { + types[i].ftype = Wire; + } + } + } + + plsize2 = plsize - 1; + double ratio; + for (uint i = head + 1; i < plsize2; i++) { + if (types[i].range < blind || types[i - 1].range < blind || types[i + 1].range < blind) { + continue; + } + + if (types[i - 1].dista < 1e-8 || types[i].dista < 1e-8) { + continue; + } + + if (types[i].ftype == Nor) { + if (types[i - 1].dista > types[i].dista) { + ratio = types[i - 1].dista / types[i].dista; + } else { + ratio = types[i].dista / types[i - 1].dista; + } + + if (types[i].intersect < smallp_intersect && ratio < smallp_ratio) { + if (types[i - 1].ftype == Nor) { + types[i - 1].ftype = Real_Plane; + } + if (types[i + 1].ftype == Nor) { + types[i + 1].ftype = Real_Plane; + } + types[i].ftype = Real_Plane; + } + } + } + + int last_surface = -1; + for (uint j = head; j < plsize; j++) { + if (types[j].ftype == Poss_Plane || types[j].ftype == Real_Plane) { + if (last_surface == -1) { + last_surface = j; + } + + if (j == uint(last_surface + point_filter_num - 1)) { + PointType ap; + ap.x = pl[j].x; + ap.y = pl[j].y; + ap.z = pl[j].z; + ap.intensity = pl[j].intensity; + ap.curvature = pl[j].curvature; + pl_surf.push_back(ap); + + last_surface = -1; + } + } else { + if (types[j].ftype == Edge_Jump || types[j].ftype == Edge_Plane) { + pl_corn.push_back(pl[j]); + } + if (last_surface != -1) { + PointType ap; + for (uint k = last_surface; k < j; k++) { + ap.x += pl[k].x; + ap.y += pl[k].y; + ap.z += pl[k].z; + ap.intensity += pl[k].intensity; + ap.curvature += pl[k].curvature; + } + ap.x /= (j - last_surface); + ap.y /= (j - last_surface); + ap.z /= (j - last_surface); + ap.intensity /= (j - last_surface); + ap.curvature /= (j - last_surface); + pl_surf.push_back(ap); + } + last_surface = -1; + } + } +} + +void Preprocess::pub_func(PointCloudXYZI &pl, const rclcpp::Time &ct) { + pl.height = 1; + pl.width = pl.size(); + sensor_msgs::msg::PointCloud2 output; + pcl::toROSMsg(pl, output); + output.header.frame_id = "livox"; + output.header.stamp = ct; +} + +int Preprocess::plane_judge(const PointCloudXYZI &pl, vector &types, uint i_cur, uint &i_nex, + Eigen::Vector3d &curr_direct) { + double group_dis = disA * types[i_cur].range + disB; + group_dis = group_dis * group_dis; + // i_nex = i_cur; + + double two_dis; + vector disarr; + disarr.reserve(20); + + for (i_nex = i_cur; i_nex < i_cur + group_size; i_nex++) { + if (types[i_nex].range < blind) { + curr_direct.setZero(); + return 2; + } + disarr.push_back(types[i_nex].dista); + } + + for (;;) { + if ((i_cur >= pl.size()) || (i_nex >= pl.size())) break; + + if (types[i_nex].range < blind) { + curr_direct.setZero(); + return 2; + } + vx = pl[i_nex].x - pl[i_cur].x; + vy = pl[i_nex].y - pl[i_cur].y; + vz = pl[i_nex].z - pl[i_cur].z; + two_dis = vx * vx + vy * vy + vz * vz; + if (two_dis >= group_dis) { + break; + } + disarr.push_back(types[i_nex].dista); + i_nex++; + } + + double leng_wid = 0; + double v1[3], v2[3]; + for (uint j = i_cur + 1; j < i_nex; j++) { + if ((j >= pl.size()) || (i_cur >= pl.size())) break; + v1[0] = pl[j].x - pl[i_cur].x; + v1[1] = pl[j].y - pl[i_cur].y; + v1[2] = pl[j].z - pl[i_cur].z; + + v2[0] = v1[1] * vz - vy * v1[2]; + v2[1] = v1[2] * vx - v1[0] * vz; + v2[2] = v1[0] * vy - vx * v1[1]; + + double lw = v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]; + if (lw > leng_wid) { + leng_wid = lw; + } + } + + + if ((two_dis * two_dis / leng_wid) < p2l_ratio) { + curr_direct.setZero(); + return 0; + } + + uint disarrsize = disarr.size(); + for (uint j = 0; j < disarrsize - 1; j++) { + for (uint k = j + 1; k < disarrsize; k++) { + if (disarr[j] < disarr[k]) { + leng_wid = disarr[j]; + disarr[j] = disarr[k]; + disarr[k] = leng_wid; + } + } + } + + if (disarr[disarr.size() - 2] < 1e-16) { + curr_direct.setZero(); + return 0; + } + + if (lidar_type == AVIA) { + double dismax_mid = disarr[0] / disarr[disarrsize / 2]; + double dismid_min = disarr[disarrsize / 2] / disarr[disarrsize - 2]; + + if (dismax_mid >= limit_maxmid || dismid_min >= limit_midmin) { + curr_direct.setZero(); + return 0; + } + } else { + double dismax_min = disarr[0] / disarr[disarrsize - 2]; + if (dismax_min >= limit_maxmin) { + curr_direct.setZero(); + return 0; + } + } + + curr_direct << vx, vy, vz; + curr_direct.normalize(); + return 1; +} + +bool Preprocess::edge_jump_judge(const PointCloudXYZI &pl, vector &types, uint i, Surround nor_dir) { + if (nor_dir == 0) { + if (types[i - 1].range < blind || types[i - 2].range < blind) { + return false; + } + } else if (nor_dir == 1) { + if (types[i + 1].range < blind || types[i + 2].range < blind) { + return false; + } + } + double d1 = types[i + nor_dir - 1].dista; + double d2 = types[i + 3 * nor_dir - 2].dista; + double d; + + if (d1 < d2) { + d = d1; + d1 = d2; + d2 = d; + } + + d1 = sqrt(d1); + d2 = sqrt(d2); + + if (d1 > edgea * d2 || (d1 - d2) > edgeb) { + return false; + } + + return true; +} diff --git a/point_lio_ros2/src/preprocess.h b/point_lio_ros2/src/preprocess.h new file mode 100644 index 0000000..872104f --- /dev/null +++ b/point_lio_ros2/src/preprocess.h @@ -0,0 +1,193 @@ +#include +#include +#include +// #include + +using namespace std; + +#define IS_VALID(a) ((abs(a)>1e8) ? true : false) + +typedef pcl::PointXYZINormal PointType; +typedef pcl::PointCloud PointCloudXYZI; + +enum LID_TYPE { + AVIA = 1, VELO16, OUST64, HESAIxt32, UNILIDAR +}; //{1, 2, 3, 4} +enum TIME_UNIT { + SEC = 0, MS = 1, US = 2, NS = 3 +}; +enum Feature { + Nor, Poss_Plane, Real_Plane, Edge_Jump, Edge_Plane, Wire, ZeroPoint +}; +enum Surround { + Prev, Next +}; +enum E_jump { + Nr_nor, Nr_zero, Nr_180, Nr_inf, Nr_blind +}; + +const bool time_list_cut_frame(PointType &x, PointType &y); + +struct orgtype { + double range; + double dista; + double angle[2]; + double intersect; + E_jump edj[2]; + Feature ftype; + + orgtype() { + range = 0; + edj[Prev] = Nr_nor; + edj[Next] = Nr_nor; + ftype = Nor; + intersect = 2; + } +}; + +namespace velodyne_ros { + struct EIGEN_ALIGN16 Point { + PCL_ADD_POINT4D; + float intensity; + float time; + uint16_t ring; + + EIGEN_MAKE_ALIGNED_OPERATOR_NEW + }; +} // namespace velodyne_ros +POINT_CLOUD_REGISTER_POINT_STRUCT(velodyne_ros::Point, + (float, x, x) + (float, y, y) + (float, z, z) + (float, intensity, intensity) + (float, time, time) + (std::uint16_t, ring, ring) +) + +/** + * @brief Unilidar Point Type + */ +namespace unilidar_ros { + struct EIGEN_ALIGN16 Point { + PCL_ADD_POINT4D + PCL_ADD_INTENSITY + std::uint16_t ring; + float time; + + EIGEN_MAKE_ALIGNED_OPERATOR_NEW + }; +} // namespace unilidar_ros +POINT_CLOUD_REGISTER_POINT_STRUCT(unilidar_ros::Point, + (float, x, x) + (float, y, y) + (float, z, z) + (float, intensity, intensity) + (std::uint16_t, ring, ring) + (float, time, time) + ) + +namespace hesai_ros { + struct EIGEN_ALIGN16 Point { + PCL_ADD_POINT4D; + float intensity; + double timestamp; + uint16_t ring; + + EIGEN_MAKE_ALIGNED_OPERATOR_NEW + }; +} // namespace velodyne_ros +POINT_CLOUD_REGISTER_POINT_STRUCT(hesai_ros::Point, + (float, x, x) + (float, y, y) + (float, z, z) + (float, intensity, intensity) + (double, timestamp, timestamp) + (std::uint16_t, ring, ring) +) + +namespace ouster_ros { + struct EIGEN_ALIGN16 Point { + PCL_ADD_POINT4D; + float intensity; + uint32_t t; + uint16_t reflectivity; + uint8_t ring; + uint16_t ambient; + uint32_t range; + + EIGEN_MAKE_ALIGNED_OPERATOR_NEW + }; +} // namespace ouster_ros + +// clang-format off +POINT_CLOUD_REGISTER_POINT_STRUCT(ouster_ros::Point, + (float, x, x) + (float, y, y) + (float, z, z) + (float, intensity, intensity) + // use std::uint32_t to avoid conflicting with pcl::uint32_t + (std::uint32_t, t, t) + (std::uint16_t, reflectivity, reflectivity) + (std::uint8_t, ring, ring) + (std::uint16_t, ambient, ambient) + (std::uint32_t, range, range) +) + +class Preprocess { +public: +// EIGEN_MAKE_ALIGNED_OPERATOR_NEW + + Preprocess(); + + ~Preprocess(); + + // void process(const livox_ros_driver2::msg::CustomMsg::SharedPtr &msg, PointCloudXYZI::Ptr &pcl_out); + + void process(const sensor_msgs::msg::PointCloud2::SharedPtr &msg, PointCloudXYZI::Ptr &pcl_out); + + void set(bool feat_en, int lid_type, double bld, int pfilt_num); + + // sensor_msgs::msg::PointCloud2::ConstSharedPtr pointcloud; + PointCloudXYZI pl_full, pl_corn, pl_surf; + PointCloudXYZI pl_buff[128]; //maximum 128 line lidar + vector typess[128]; //maximum 128 line lidar + float time_unit_scale; + int lidar_type, point_filter_num, N_SCANS, SCAN_RATE, time_unit; + double blind; + bool given_offset_time; + //ros::Publisher pub_full, pub_surf, pub_corn; + + +private: + // void avia_handler(const livox_ros_driver2::msg::CustomMsg::SharedPtr &msg); + + void oust64_handler(const sensor_msgs::msg::PointCloud2::SharedPtr &msg); + + void velodyne_handler(const sensor_msgs::msg::PointCloud2::SharedPtr &msg); + + void unilidar_handler(const sensor_msgs::msg::PointCloud2::SharedPtr &msg); + + void hesai_handler(const sensor_msgs::msg::PointCloud2::SharedPtr &msg); + + void give_feature(PointCloudXYZI &pl, vector &types); + + void pub_func(PointCloudXYZI &pl, const rclcpp::Time &ct); + + int + plane_judge(const PointCloudXYZI &pl, vector &types, uint i, uint &i_nex, Eigen::Vector3d &curr_direct); + + bool small_plane(const PointCloudXYZI &pl, vector &types, uint i_cur, uint &i_nex, + Eigen::Vector3d &curr_direct); + + bool edge_jump_judge(const PointCloudXYZI &pl, vector &types, uint i, Surround nor_dir); + + int group_size; + double disA, disB, inf_bound; + double limit_maxmid, limit_midmin, limit_maxmin; + double p2l_ratio; + double jump_up_limit, jump_down_limit; + double cos160; + double edgea, edgeb; + double smallp_intersect, smallp_ratio; + double vx, vy, vz; +}; diff --git a/pointcloud_to_laserscan/CHANGELOG.rst b/pointcloud_to_laserscan/CHANGELOG.rst new file mode 100644 index 0000000..54374c3 --- /dev/null +++ b/pointcloud_to_laserscan/CHANGELOG.rst @@ -0,0 +1,95 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package pointcloud_to_laserscan +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +2.0.1 (2021-10-19) +------------------ +* Replace deprecated launch api (`#56 `_) +* Fix linting errors in the code (`#52 `_) +* Update README.md +* Contributors: Chris Lalancette, Daisuke Nishimatsu, Paul Bovbel + +2.0.0 (2020-02-10) +------------------ +* ROS 2 Migration (`#33 `_) + * ROS 2 Migration + Signed-off-by: Michel Hidalgo +* Contributors: Michel Hidalgo + +1.4.1 (2019-08-30) +------------------ +* LaserScan to PointCloud node + nodelet (`#28 `_) +* fix roslint (`#29 `_) +* Merge pull request `#20 `_ from ros-perception/range_max_check + Add check for range_max +* Add check for range_max +* Contributors: Paul Bovbel, Rein Appeldoorn + +1.4.0 (2017-11-14) +------------------ +* Added inf_epsilon parameter that determines the value added to max range when use_infs parameter is set to false +* Merge pull request `#11 `_ from ros-perception/mikaelarguedas-patch-1 + update to use non deprecated pluginlib macro +* Migrate to package format 2; add roslint +* Add sane parameter defaults; fixup lint warnings +* update to use non deprecated pluginlib macro +* Contributors: Mikael Arguedas, Paul Bovbel, Prasanna Kannappan + +1.3.1 (2017-04-26) +------------------ +* Merge pull request `#4 `_ from yoshimalucky/fix-miscalculation-in-angle-increment + Fixed miscalculation in angle_increment in the launch files. +* fixed miscalculation in angle_increment in the launchfiles. +* Contributors: Paul Bovbel, yoshimalucky + +1.3.0 (2015-06-09) +------------------ +* Fix pointcloud to laserscan transform tolerance issues +* Move pointcloud_to_laserscan to new repository +* Contributors: Paul Bovbel + +1.2.7 (2015-06-08) +------------------ + +* Cleanup pointcloud_to_laserscan launch files +* Contributors: Paul Bovbel + +1.2.6 (2015-02-04) +------------------ +* Fix default value for concurrency +* Fix multithreaded lazy pub sub +* Contributors: Paul Bovbel + +1.2.5 (2015-01-20) +------------------ +* Switch to tf_sensor_msgs for transform +* Set parameters in sample launch files to default +* Add tolerance parameter +* Contributors: Paul Bovbel + +1.2.4 (2015-01-15) +------------------ +* Remove stray dependencies +* Refactor with tf2 and message filters +* Remove roslaunch check +* Fix regressions +* Refactor to allow debug messages from node and nodelet +* Contributors: Paul Bovbel + +1.2.3 (2015-01-10) +------------------ +* add launch tests +* refactor naming and fix nodelet export +* set default target frame to empty +* clean up package.xml +* Contributors: Paul Bovbel + +1.2.2 (2014-10-25) +------------------ +* clean up package.xml +* Fix header reference +* Fix flow +* Fix pointer assertion +* Finalize pointcloud to laserscan +* Initial pointcloud to laserscan commit +* Contributors: Paul Bovbel diff --git a/pointcloud_to_laserscan/CMakeLists.txt b/pointcloud_to_laserscan/CMakeLists.txt new file mode 100644 index 0000000..b96516b --- /dev/null +++ b/pointcloud_to_laserscan/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.5) +project(pointcloud_to_laserscan) + +find_package(ament_cmake_auto REQUIRED) +ament_auto_find_build_dependencies() + +ament_auto_add_library(laserscan_to_pointcloud SHARED + src/laserscan_to_pointcloud_node.cpp) + +rclcpp_components_register_node(laserscan_to_pointcloud + PLUGIN "pointcloud_to_laserscan::LaserScanToPointCloudNode" + EXECUTABLE laserscan_to_pointcloud_node) + +ament_auto_add_library(pointcloud_to_laserscan SHARED + src/pointcloud_to_laserscan_node.cpp) + +rclcpp_components_register_node(pointcloud_to_laserscan + PLUGIN "pointcloud_to_laserscan::PointCloudToLaserScanNode" + EXECUTABLE pointcloud_to_laserscan_node) + +ament_auto_add_executable(dummy_pointcloud_publisher + src/dummy_pointcloud_publisher.cpp +) + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + ament_lint_auto_find_test_dependencies() +endif() + +ament_auto_package( + INSTALL_TO_SHARE + launch +) diff --git a/pointcloud_to_laserscan/LICENSE b/pointcloud_to_laserscan/LICENSE new file mode 100644 index 0000000..f05ef04 --- /dev/null +++ b/pointcloud_to_laserscan/LICENSE @@ -0,0 +1,12 @@ +Copyright (c) 2010-2012, Willow Garage, Inc. +Copyright (c) 2019, Eurotec, Netherlands + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pointcloud_to_laserscan/README.md b/pointcloud_to_laserscan/README.md new file mode 100644 index 0000000..dd8db4d --- /dev/null +++ b/pointcloud_to_laserscan/README.md @@ -0,0 +1,49 @@ +# ROS 2 pointcloud <-> laserscan converters + +This is a ROS 2 package that provides components to convert `sensor_msgs/msg/PointCloud2` messages to `sensor_msgs/msg/LaserScan` messages and back. +It is essentially a port of the original ROS 1 package. + +## pointcloud\_to\_laserscan::PointCloudToLaserScanNode + +This ROS 2 component projects `sensor_msgs/msg/PointCloud2` messages into `sensor_msgs/msg/LaserScan` messages. + +### Published Topics + +* `scan` (`sensor_msgs/msg/LaserScan`) - The output laser scan. + +### Subscribed Topics + +* `cloud_in` (`sensor_msgs/msg/PointCloud2`) - The input point cloud. No input will be processed if there isn't at least one subscriber to the `scan` topic. + +### Parameters + +* `min_height` (double, default: 2.2e-308) - The minimum height to sample in the point cloud in meters. +* `max_height` (double, default: 1.8e+308) - The maximum height to sample in the point cloud in meters. +* `angle_min` (double, default: -π) - The minimum scan angle in radians. +* `angle_max` (double, default: π) - The maximum scan angle in radians. +* `angle_increment` (double, default: π/180) - Resolution of laser scan in radians per ray. +* `queue_size` (double, default: detected number of cores) - Input point cloud queue size. +* `scan_time` (double, default: 1.0/30.0) - The scan rate in seconds. Only used to populate the scan_time field of the output laser scan message. +* `range_min` (double, default: 0.0) - The minimum ranges to return in meters. +* `range_max` (double, default: 1.8e+308) - The maximum ranges to return in meters. +* `target_frame` (str, default: none) - If provided, transform the pointcloud into this frame before converting to a laser scan. Otherwise, laser scan will be generated in the same frame as the input point cloud. +* `transform_tolerance` (double, default: 0.01) - Time tolerance for transform lookups. Only used if a `target_frame` is provided. +* `use_inf` (boolean, default: true) - If disabled, report infinite range (no obstacle) as range_max + 1. Otherwise report infinite range as +inf. + +## pointcloud\_to\_laserscan::LaserScanToPointCloudNode + +This ROS 2 component re-publishes `sensor_msgs/msg/LaserScan` messages as `sensor_msgs/msg/PointCloud2` messages. + +### Published Topics + +* `cloud` (`sensor_msgs/msg/PointCloud2`) - The output point cloud. + +### Subscribed Topics + +* `scan_in` (`sensor_msgs/msg/LaserScan`) - The input laser scan. No input will be processed if there isn't at least one subscriber to the `cloud` topic. + +### Parameters + +* `queue_size` (double, default: detected number of cores) - Input laser scan queue size. +* `target_frame` (str, default: none) - If provided, transform the pointcloud into this frame before converting to a laser scan. Otherwise, laser scan will be generated in the same frame as the input point cloud. +* `transform_tolerance` (double, default: 0.01) - Time tolerance for transform lookups. Only used if a `target_frame` is provided. diff --git a/pointcloud_to_laserscan/include/pointcloud_to_laserscan/laserscan_to_pointcloud_node.hpp b/pointcloud_to_laserscan/include/pointcloud_to_laserscan/laserscan_to_pointcloud_node.hpp new file mode 100644 index 0000000..8948af9 --- /dev/null +++ b/pointcloud_to_laserscan/include/pointcloud_to_laserscan/laserscan_to_pointcloud_node.hpp @@ -0,0 +1,98 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019, Eurotec, Netherlands + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +/* + * Author: Rein Appeldoorn + */ + +#ifndef POINTCLOUD_TO_LASERSCAN__LASERSCAN_TO_POINTCLOUD_NODE_HPP_ +#define POINTCLOUD_TO_LASERSCAN__LASERSCAN_TO_POINTCLOUD_NODE_HPP_ + +#include +#include +#include +#include + +#include "message_filters/subscriber.h" +#include "tf2_ros/buffer.h" +#include "tf2_ros/message_filter.h" +#include "tf2_ros/transform_listener.h" + +#include "laser_geometry/laser_geometry.hpp" +#include "rclcpp/rclcpp.hpp" +#include "sensor_msgs/msg/laser_scan.hpp" +#include "sensor_msgs/msg/point_cloud2.hpp" + +#include "pointcloud_to_laserscan/visibility_control.h" + +namespace pointcloud_to_laserscan +{ +typedef tf2_ros::MessageFilter MessageFilter; + +//! \brief The PointCloudToLaserScanNodelet class to process incoming laserscans into pointclouds. +//! +class LaserScanToPointCloudNode : public rclcpp::Node +{ +public: + POINTCLOUD_TO_LASERSCAN_PUBLIC + explicit LaserScanToPointCloudNode(const rclcpp::NodeOptions & options); + + ~LaserScanToPointCloudNode() override; + +private: + void scanCallback(sensor_msgs::msg::LaserScan::ConstSharedPtr scan_msg); + + void subscriptionListenerThreadLoop(); + + std::unique_ptr tf2_; + std::unique_ptr tf2_listener_; + message_filters::Subscriber sub_; + std::shared_ptr> pub_; + std::unique_ptr message_filter_; + std::thread subscription_listener_thread_; + std::atomic_bool alive_{true}; + + laser_geometry::LaserProjection projector_; + + // ROS Parameters + int input_queue_size_; + std::string target_frame_; + double tolerance_; +}; + +} // namespace pointcloud_to_laserscan + +#endif // POINTCLOUD_TO_LASERSCAN__LASERSCAN_TO_POINTCLOUD_NODE_HPP_ diff --git a/pointcloud_to_laserscan/include/pointcloud_to_laserscan/pointcloud_to_laserscan_node.hpp b/pointcloud_to_laserscan/include/pointcloud_to_laserscan/pointcloud_to_laserscan_node.hpp new file mode 100644 index 0000000..fe0aacd --- /dev/null +++ b/pointcloud_to_laserscan/include/pointcloud_to_laserscan/pointcloud_to_laserscan_node.hpp @@ -0,0 +1,102 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2010-2012, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +/* + * Author: Paul Bovbel + */ + +#ifndef POINTCLOUD_TO_LASERSCAN__POINTCLOUD_TO_LASERSCAN_NODE_HPP_ +#define POINTCLOUD_TO_LASERSCAN__POINTCLOUD_TO_LASERSCAN_NODE_HPP_ + +#include +#include +#include +#include + +#include "message_filters/subscriber.h" +#include "tf2_ros/buffer.h" +#include "tf2_ros/message_filter.h" +#include "tf2_ros/transform_listener.h" + +#include "rclcpp/rclcpp.hpp" +#include "sensor_msgs/msg/laser_scan.hpp" +#include "sensor_msgs/msg/point_cloud2.hpp" + +#include "pointcloud_to_laserscan/visibility_control.h" + +namespace pointcloud_to_laserscan +{ +typedef tf2_ros::MessageFilter MessageFilter; + +/** +* Class to process incoming pointclouds into laserscans. +* Some initial code was pulled from the defunct turtlebot pointcloud_to_laserscan implementation. +*/ +class PointCloudToLaserScanNode : public rclcpp::Node +{ +public: + POINTCLOUD_TO_LASERSCAN_PUBLIC + explicit PointCloudToLaserScanNode(const rclcpp::NodeOptions & options); + + ~PointCloudToLaserScanNode() override; + +private: + void cloudCallback(sensor_msgs::msg::PointCloud2::ConstSharedPtr cloud_msg); + + void subscriptionListenerThreadLoop(); + + std::unique_ptr tf2_; + std::unique_ptr tf2_listener_; + message_filters::Subscriber sub_; + std::shared_ptr> pub_; + std::unique_ptr message_filter_; + + std::thread subscription_listener_thread_; + std::atomic_bool alive_{true}; + + // ROS Parameters + int input_queue_size_; + std::string target_frame_; + double tolerance_; + double min_height_, max_height_, angle_min_, angle_max_, angle_increment_, scan_time_, range_min_, + range_max_; + bool use_inf_; + double inf_epsilon_; +}; + +} // namespace pointcloud_to_laserscan + +#endif // POINTCLOUD_TO_LASERSCAN__POINTCLOUD_TO_LASERSCAN_NODE_HPP_ diff --git a/pointcloud_to_laserscan/include/pointcloud_to_laserscan/visibility_control.h b/pointcloud_to_laserscan/include/pointcloud_to_laserscan/visibility_control.h new file mode 100644 index 0000000..7058490 --- /dev/null +++ b/pointcloud_to_laserscan/include/pointcloud_to_laserscan/visibility_control.h @@ -0,0 +1,80 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019, Eurotec, Netherlands + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +#ifndef POINTCLOUD_TO_LASERSCAN__VISIBILITY_CONTROL_H_ +#define POINTCLOUD_TO_LASERSCAN__VISIBILITY_CONTROL_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +// This logic was borrowed (then namespaced) from the examples on the gcc wiki: +// https://gcc.gnu.org/wiki/Visibility + +#if defined _WIN32 || defined __CYGWIN__ + #ifdef __GNUC__ + #define POINTCLOUD_TO_LASERSCAN_EXPORT __attribute__ ((dllexport)) + #define POINTCLOUD_TO_LASERSCAN_IMPORT __attribute__ ((dllimport)) + #else + #define POINTCLOUD_TO_LASERSCAN_EXPORT __declspec(dllexport) + #define POINTCLOUD_TO_LASERSCAN_IMPORT __declspec(dllimport) + #endif + #ifdef POINTCLOUD_TO_LASERSCAN_BUILDING_DLL + #define POINTCLOUD_TO_LASERSCAN_PUBLIC POINTCLOUD_TO_LASERSCAN_EXPORT + #else + #define POINTCLOUD_TO_LASERSCAN_PUBLIC POINTCLOUD_TO_LASERSCAN_IMPORT + #endif + #define POINTCLOUD_TO_LASERSCAN_PUBLIC_TYPE POINTCLOUD_TO_LASERSCAN_PUBLIC + #define POINTCLOUD_TO_LASERSCAN_LOCAL +#else + #define POINTCLOUD_TO_LASERSCAN_EXPORT __attribute__ ((visibility("default"))) + #define POINTCLOUD_TO_LASERSCAN_IMPORT + #if __GNUC__ >= 4 + #define POINTCLOUD_TO_LASERSCAN_PUBLIC __attribute__ ((visibility("default"))) + #define POINTCLOUD_TO_LASERSCAN_LOCAL __attribute__ ((visibility("hidden"))) + #else + #define POINTCLOUD_TO_LASERSCAN_PUBLIC + #define POINTCLOUD_TO_LASERSCAN_LOCAL + #endif + #define POINTCLOUD_TO_LASERSCAN_PUBLIC_TYPE +#endif + +#ifdef __cplusplus +} +#endif + +#endif // POINTCLOUD_TO_LASERSCAN__VISIBILITY_CONTROL_H_ diff --git a/pointcloud_to_laserscan/launch/pointcloud_to_laserscan_launch.py b/pointcloud_to_laserscan/launch/pointcloud_to_laserscan_launch.py new file mode 100644 index 0000000..4be5e32 --- /dev/null +++ b/pointcloud_to_laserscan/launch/pointcloud_to_laserscan_launch.py @@ -0,0 +1,43 @@ +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration +from launch_ros.actions import Node + + +def generate_launch_description(): + return LaunchDescription([ + + DeclareLaunchArgument( + name='scanner', default_value='unilidar', + description='Namespace for Unitree LiDAR topics, used to organize topic names' + ), + + # Make sure the Unitree LiDAR node is already running + # and publishing point cloud data to the /unilidar/cloud topic + + # ========== Unitree PointCloud to LaserScan Converter ========== + # Convert Unitree LiDAR 3D point cloud data into 2D LaserScan data + Node( + package='pointcloud_to_laserscan', + executable='pointcloud_to_laserscan_node', + + remappings=[ + ('cloud_in', '/unilidar/cloud'), # Input: Unitree LiDAR point cloud topic + ('scan', '/scan') # Output: standard LaserScan topic + ], + parameters=[{ + 'min_height': 0.35, # Minimum height: filter points below this height + 'max_height': 0.45, # Maximum height: keep obstacles, filter ceiling points + 'angle_min': -3.14159, # Minimum scan angle: -π radians (-180 degrees) + 'angle_max': 3.14159, # Maximum scan angle: π radians (180 degrees) + 'angle_increment': 0.00436, # Angular resolution: π/720 radians (~0.25 degrees) + 'scan_time': 0.1, # Scan time: 0.1s (10 Hz publishing rate, suitable for navigation) + 'range_min': 0.1, # Minimum valid range: avoid self-reflections + 'range_max': 100.0, # Maximum valid range: Unitree LiDAR effective range + 'use_inf': True, # Use infinity for missing readings (LaserScan standard) + 'inf_epsilon': 1.0 # Epsilon value for infinity handling + }], + name='unitree_pointcloud_to_laserscan' # Node name + ) + ]) + diff --git a/pointcloud_to_laserscan/launch/sample_laserscan_to_pointcloud_launch.py b/pointcloud_to_laserscan/launch/sample_laserscan_to_pointcloud_launch.py new file mode 100644 index 0000000..2f711d7 --- /dev/null +++ b/pointcloud_to_laserscan/launch/sample_laserscan_to_pointcloud_launch.py @@ -0,0 +1,47 @@ +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.actions import ExecuteProcess +from launch.substitutions import LaunchConfiguration +from launch_ros.actions import Node + +import yaml + + +def generate_launch_description(): + return LaunchDescription([ + DeclareLaunchArgument( + name='scanner', default_value='scanner', + description='Namespace for sample topics' + ), + ExecuteProcess( + cmd=[ + 'ros2', 'topic', 'pub', '-r', '10', + '--qos-profile', 'sensor_data', + [LaunchConfiguration(variable_name='scanner'), '/scan'], + 'sensor_msgs/msg/LaserScan', yaml.dump({ + 'header': {'frame_id': 'scan'}, 'angle_min': -1.0, + 'angle_max': 1.0, 'angle_increment': 0.1, 'range_max': 10.0, + 'ranges': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + }) + ], + name='scan_publisher' + ), + Node( + package='tf2_ros', + executable='static_transform_publisher', + name='static_transform_publisher', + arguments=[ + '--x', '0', '--y', '0', '--z', '0', + '--qx', '0', '--qy', '0', '--qz', '0', '--qw', '1', + '--frame-id', 'map', '--child-frame-id', 'scan' + ] + ), + Node( + package='pointcloud_to_laserscan', + executable='laserscan_to_pointcloud_node', + name='laserscan_to_pointcloud', + remappings=[('scan_in', [LaunchConfiguration(variable_name='scanner'), '/scan']), + ('cloud', [LaunchConfiguration(variable_name='scanner'), '/cloud'])], + parameters=[{'target_frame': 'scan', 'transform_tolerance': 0.01}] + ), + ]) diff --git a/pointcloud_to_laserscan/launch/sample_pointcloud_to_laserscan_launch.py b/pointcloud_to_laserscan/launch/sample_pointcloud_to_laserscan_launch.py new file mode 100644 index 0000000..b8ac473 --- /dev/null +++ b/pointcloud_to_laserscan/launch/sample_pointcloud_to_laserscan_launch.py @@ -0,0 +1,49 @@ +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration +from launch_ros.actions import Node + + +def generate_launch_description(): + return LaunchDescription([ + DeclareLaunchArgument( + name='scanner', default_value='scanner', + description='Namespace for sample topics' + ), + Node( + package='pointcloud_to_laserscan', executable='dummy_pointcloud_publisher', + remappings=[('cloud', [LaunchConfiguration(variable_name='scanner'), '/cloud'])], + parameters=[{'cloud_frame_id': 'cloud', 'cloud_extent': 2.0, 'cloud_size': 500}], + name='cloud_publisher' + ), + Node( + package='tf2_ros', + executable='static_transform_publisher', + name='static_transform_publisher', + arguments=[ + '--x', '0', '--y', '0', '--z', '0', + '--qx', '0', '--qy', '0', '--qz', '0', '--qw', '1', + '--frame-id', 'map', '--child-frame-id', 'cloud' + ] + ), + Node( + package='pointcloud_to_laserscan', executable='pointcloud_to_laserscan_node', + remappings=[('cloud_in', [LaunchConfiguration(variable_name='scanner'), '/cloud']), + ('scan', [LaunchConfiguration(variable_name='scanner'), '/scan'])], + parameters=[{ + 'target_frame': 'cloud', + 'transform_tolerance': 0.01, + 'min_height': 0.0, + 'max_height': 1.0, + 'angle_min': -1.5708, # -M_PI/2 + 'angle_max': 1.5708, # M_PI/2 + 'angle_increment': 0.0087, # M_PI/360.0 + 'scan_time': 0.3333, + 'range_min': 0.45, + 'range_max': 4.0, + 'use_inf': True, + 'inf_epsilon': 1.0 + }], + name='pointcloud_to_laserscan' + ) + ]) diff --git a/pointcloud_to_laserscan/package.xml b/pointcloud_to_laserscan/package.xml new file mode 100644 index 0000000..3d9ec2f --- /dev/null +++ b/pointcloud_to_laserscan/package.xml @@ -0,0 +1,46 @@ + + + pointcloud_to_laserscan + 2.0.1 + Converts a 3D Point Cloud into a 2D laser scan. This is useful for making devices like the Kinect appear like a laser scanner for 2D-based algorithms (e.g. laser-based SLAM). + + Paul Bovbel + Michel Hidalgo + Paul Bovbel + Michel Hidalgo + Tully Foote + + BSD + + http://ros.org/wiki/perception_pcl + https://github.com/ros-perception/perception_pcl/issues + https://github.com/ros-perception/perception_pcl + + ament_cmake_auto + + laser_geometry + message_filters + rclcpp + rclcpp_components + sensor_msgs + tf2 + tf2_ros + tf2_sensor_msgs + + launch + launch_ros + + ament_lint_auto + + ament_cmake_cppcheck + ament_cmake_cpplint + ament_cmake_flake8 + ament_cmake_lint_cmake + ament_cmake_pep257 + ament_cmake_uncrustify + ament_cmake_xmllint + + + ament_cmake + + diff --git a/pointcloud_to_laserscan/src/dummy_pointcloud_publisher.cpp b/pointcloud_to_laserscan/src/dummy_pointcloud_publisher.cpp new file mode 100644 index 0000000..c4b7349 --- /dev/null +++ b/pointcloud_to_laserscan/src/dummy_pointcloud_publisher.cpp @@ -0,0 +1,85 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2020, Open Source Robotics Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +#include +#include + +#include "rclcpp/rclcpp.hpp" +#include "sensor_msgs/msg/point_cloud2.hpp" +#include "sensor_msgs/point_cloud2_iterator.hpp" + +int main(int argc, char * argv[]) +{ + rclcpp::init(argc, argv); + + auto node = std::make_shared("dummy_pointcloud_publisher"); + auto pub = + node->create_publisher("cloud", rclcpp::SensorDataQoS()); + + sensor_msgs::msg::PointCloud2 dummy_cloud; + sensor_msgs::PointCloud2Modifier modifier(dummy_cloud); + modifier.setPointCloud2Fields( + 3, + "x", 1, sensor_msgs::msg::PointField::FLOAT32, + "y", 1, sensor_msgs::msg::PointField::FLOAT32, + "z", 1, sensor_msgs::msg::PointField::FLOAT32); + modifier.resize(node->declare_parameter("cloud_size", 100)); + std::mt19937 gen(node->declare_parameter("cloud_seed", 0)); + double extent = node->declare_parameter("cloud_extent", 10.0); + std::uniform_real_distribution distribution(-extent / 2, extent / 2); + sensor_msgs::PointCloud2Iterator it_x(dummy_cloud, "x"); + sensor_msgs::PointCloud2Iterator it_y(dummy_cloud, "y"); + sensor_msgs::PointCloud2Iterator it_z(dummy_cloud, "z"); + for (; it_x != it_x.end(); ++it_x, ++it_y, ++it_z) { + *it_x = distribution(gen); + *it_y = distribution(gen); + *it_z = distribution(gen); + } + dummy_cloud.header.frame_id = node->declare_parameter("cloud_frame_id", ""); + + rclcpp::executors::SingleThreadedExecutor executor; + executor.add_node(node); + rclcpp::Rate rate(1.0); + while (rclcpp::ok()) { + dummy_cloud.header.stamp = node->get_clock()->now(); + pub->publish(dummy_cloud); + executor.spin_some(); + rate.sleep(); + } + + rclcpp::shutdown(); + return 0; +} diff --git a/pointcloud_to_laserscan/src/laserscan_to_pointcloud_node.cpp b/pointcloud_to_laserscan/src/laserscan_to_pointcloud_node.cpp new file mode 100644 index 0000000..2d2726f --- /dev/null +++ b/pointcloud_to_laserscan/src/laserscan_to_pointcloud_node.cpp @@ -0,0 +1,150 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019, Eurotec, Netherlands + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +/* + * Author: Rein Appeldoorn + */ + +#include "pointcloud_to_laserscan/laserscan_to_pointcloud_node.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include "sensor_msgs/point_cloud2_iterator.hpp" +#include "tf2_sensor_msgs/tf2_sensor_msgs.hpp" +#include "tf2_ros/create_timer_ros.h" + +namespace pointcloud_to_laserscan +{ + +LaserScanToPointCloudNode::LaserScanToPointCloudNode(const rclcpp::NodeOptions & options) +: rclcpp::Node("laserscan_to_pointcloud", options) +{ + target_frame_ = this->declare_parameter("target_frame", ""); + tolerance_ = this->declare_parameter("transform_tolerance", 0.01); + // TODO(hidmic): adjust default input queue size based on actual concurrency levels + // achievable by the associated executor + input_queue_size_ = this->declare_parameter( + "queue_size", static_cast(std::thread::hardware_concurrency())); + + pub_ = this->create_publisher("cloud", rclcpp::SensorDataQoS()); + + using std::placeholders::_1; + // if pointcloud target frame specified, we need to filter by transform availability + if (!target_frame_.empty()) { + tf2_ = std::make_unique(this->get_clock()); + auto timer_interface = std::make_shared( + this->get_node_base_interface(), this->get_node_timers_interface()); + tf2_->setCreateTimerInterface(timer_interface); + tf2_listener_ = std::make_unique(*tf2_); + message_filter_ = std::make_unique( + sub_, *tf2_, target_frame_, input_queue_size_, + this->get_node_logging_interface(), + this->get_node_clock_interface()); + message_filter_->registerCallback( + std::bind( + &LaserScanToPointCloudNode::scanCallback, this, _1)); + } else { // otherwise setup direct subscription + sub_.registerCallback(std::bind(&LaserScanToPointCloudNode::scanCallback, this, _1)); + } + + subscription_listener_thread_ = std::thread( + std::bind(&LaserScanToPointCloudNode::subscriptionListenerThreadLoop, this)); +} + +LaserScanToPointCloudNode::~LaserScanToPointCloudNode() +{ + alive_.store(true); + subscription_listener_thread_.join(); +} + +void LaserScanToPointCloudNode::subscriptionListenerThreadLoop() +{ + rclcpp::Context::SharedPtr context = this->get_node_base_interface()->get_context(); + + const std::chrono::milliseconds timeout(100); + while (rclcpp::ok(context) && alive_.load()) { + int subscription_count = pub_->get_subscription_count() + + pub_->get_intra_process_subscription_count(); + if (subscription_count > 0) { + if (!sub_.getSubscriber()) { + RCLCPP_INFO( + this->get_logger(), + "Got a subscriber to pointcloud, starting laserscan subscriber"); + rclcpp::SensorDataQoS qos; + qos.keep_last(input_queue_size_); + sub_.subscribe(this, "scan_in", qos.get_rmw_qos_profile()); + } + } else if (sub_.getSubscriber()) { + RCLCPP_INFO( + this->get_logger(), + "No subscribers to pointcloud, shutting down laserscan subscriber"); + sub_.unsubscribe(); + } + rclcpp::Event::SharedPtr event = this->get_graph_event(); + this->wait_for_graph_change(event, timeout); + } + sub_.unsubscribe(); +} + +void LaserScanToPointCloudNode::scanCallback(sensor_msgs::msg::LaserScan::ConstSharedPtr scan_msg) +{ + auto cloud_msg = std::make_unique(); + + projector_.projectLaser(*scan_msg, *cloud_msg); + + // Transform cloud if necessary + if (!target_frame_.empty() && cloud_msg->header.frame_id != target_frame_) { + try { + *cloud_msg = tf2_->transform(*cloud_msg, target_frame_, tf2::durationFromSec(tolerance_)); + } catch (tf2::TransformException & ex) { + RCLCPP_ERROR_STREAM(this->get_logger(), "Transform failure: " << ex.what()); + return; + } + } + pub_->publish(std::move(cloud_msg)); +} + +} // namespace pointcloud_to_laserscan + +#include "rclcpp_components/register_node_macro.hpp" + +RCLCPP_COMPONENTS_REGISTER_NODE(pointcloud_to_laserscan::LaserScanToPointCloudNode) diff --git a/pointcloud_to_laserscan/src/pointcloud_to_laserscan_node.cpp b/pointcloud_to_laserscan/src/pointcloud_to_laserscan_node.cpp new file mode 100644 index 0000000..b95f1b5 --- /dev/null +++ b/pointcloud_to_laserscan/src/pointcloud_to_laserscan_node.cpp @@ -0,0 +1,242 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2010-2012, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +/* + * Author: Paul Bovbel + */ + +#include "pointcloud_to_laserscan/pointcloud_to_laserscan_node.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include "sensor_msgs/point_cloud2_iterator.hpp" +#include "tf2_sensor_msgs/tf2_sensor_msgs.hpp" +#include "tf2_ros/create_timer_ros.h" +#include "rmw/qos_profiles.h" + +namespace pointcloud_to_laserscan +{ + +PointCloudToLaserScanNode::PointCloudToLaserScanNode(const rclcpp::NodeOptions & options) +: rclcpp::Node("pointcloud_to_laserscan", options) +{ + target_frame_ = this->declare_parameter("target_frame", ""); + tolerance_ = this->declare_parameter("transform_tolerance", 0.01); + // TODO(hidmic): adjust default input queue size based on actual concurrency levels + // achievable by the associated executor + input_queue_size_ = this->declare_parameter( + "queue_size", static_cast(std::thread::hardware_concurrency())); + min_height_ = this->declare_parameter("min_height", std::numeric_limits::min()); + max_height_ = this->declare_parameter("max_height", std::numeric_limits::max()); + angle_min_ = this->declare_parameter("angle_min", -M_PI); + angle_max_ = this->declare_parameter("angle_max", M_PI); + angle_increment_ = this->declare_parameter("angle_increment", M_PI / 180.0); + scan_time_ = this->declare_parameter("scan_time", 1.0 / 30.0); + range_min_ = this->declare_parameter("range_min", 0.0); + range_max_ = this->declare_parameter("range_max", std::numeric_limits::max()); + inf_epsilon_ = this->declare_parameter("inf_epsilon", 1.0); + use_inf_ = this->declare_parameter("use_inf", true); + + // Create a laser scan publisher, using BEST_EFFORT QoS to accommodate more subscribers. + rclcpp::QoS qos_profile(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_sensor_data)); + qos_profile.reliability(RMW_QOS_POLICY_RELIABILITY_RELIABLE); + pub_ = this->create_publisher("scan", qos_profile); + + using std::placeholders::_1; + // if pointcloud target frame specified, we need to filter by transform availability + if (!target_frame_.empty()) { + tf2_ = std::make_unique(this->get_clock()); + auto timer_interface = std::make_shared( + this->get_node_base_interface(), this->get_node_timers_interface()); + tf2_->setCreateTimerInterface(timer_interface); + tf2_listener_ = std::make_unique(*tf2_); + message_filter_ = std::make_unique( + sub_, *tf2_, target_frame_, input_queue_size_, + this->get_node_logging_interface(), + this->get_node_clock_interface()); + message_filter_->registerCallback( + std::bind(&PointCloudToLaserScanNode::cloudCallback, this, _1)); + } else { // otherwise setup direct subscription + sub_.registerCallback(std::bind(&PointCloudToLaserScanNode::cloudCallback, this, _1)); + } + + subscription_listener_thread_ = std::thread( + std::bind(&PointCloudToLaserScanNode::subscriptionListenerThreadLoop, this)); +} + +PointCloudToLaserScanNode::~PointCloudToLaserScanNode() +{ + alive_.store(false); + subscription_listener_thread_.join(); +} + +void PointCloudToLaserScanNode::subscriptionListenerThreadLoop() +{ + rclcpp::Context::SharedPtr context = this->get_node_base_interface()->get_context(); + + const std::chrono::milliseconds timeout(100); + while (rclcpp::ok(context) && alive_.load()) { + int subscription_count = pub_->get_subscription_count() + + pub_->get_intra_process_subscription_count(); + if (subscription_count > 0) { + if (!sub_.getSubscriber()) { + RCLCPP_INFO( + this->get_logger(), + "Got a subscriber to laserscan, starting pointcloud subscriber"); + rclcpp::SensorDataQoS qos; + qos.keep_last(input_queue_size_); + sub_.subscribe(this, "cloud_in", qos.get_rmw_qos_profile()); + } + } else if (sub_.getSubscriber()) { + RCLCPP_INFO( + this->get_logger(), + "No subscribers to laserscan, shutting down pointcloud subscriber"); + sub_.unsubscribe(); + } + rclcpp::Event::SharedPtr event = this->get_graph_event(); + this->wait_for_graph_change(event, timeout); + } + sub_.unsubscribe(); +} + +void PointCloudToLaserScanNode::cloudCallback( + sensor_msgs::msg::PointCloud2::ConstSharedPtr cloud_msg) +{ + // build laserscan output + auto scan_msg = std::make_unique(); + scan_msg->header = cloud_msg->header; + if (!target_frame_.empty()) { + scan_msg->header.frame_id = target_frame_; + } + + scan_msg->angle_min = angle_min_; + scan_msg->angle_max = angle_max_; + scan_msg->angle_increment = angle_increment_; + scan_msg->time_increment = 0.0; + scan_msg->scan_time = scan_time_; + scan_msg->range_min = range_min_; + scan_msg->range_max = range_max_; + + // determine amount of rays to create + uint32_t ranges_size = std::ceil( + (scan_msg->angle_max - scan_msg->angle_min) / scan_msg->angle_increment); + + // determine if laserscan rays with no obstacle data will evaluate to infinity or max_range + if (use_inf_) { + scan_msg->ranges.assign(ranges_size, std::numeric_limits::infinity()); + } else { + scan_msg->ranges.assign(ranges_size, scan_msg->range_max + inf_epsilon_); + } + + // Transform cloud if necessary + if (scan_msg->header.frame_id != cloud_msg->header.frame_id) { + try { + auto cloud = std::make_shared(); + tf2_->transform(*cloud_msg, *cloud, target_frame_, tf2::durationFromSec(tolerance_)); + cloud_msg = cloud; + } catch (tf2::TransformException & ex) { + RCLCPP_ERROR_STREAM(this->get_logger(), "Transform failure: " << ex.what()); + return; + } + } + + // Iterate through pointcloud + for (sensor_msgs::PointCloud2ConstIterator iter_x(*cloud_msg, "x"), + iter_y(*cloud_msg, "y"), iter_z(*cloud_msg, "z"); + iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z) + { + if (std::isnan(*iter_x) || std::isnan(*iter_y) || std::isnan(*iter_z)) { + RCLCPP_DEBUG( + this->get_logger(), + "rejected for nan in point(%f, %f, %f)\n", + *iter_x, *iter_y, *iter_z); + continue; + } + + if (*iter_z > max_height_ || *iter_z < min_height_) { + RCLCPP_DEBUG( + this->get_logger(), + "rejected for height %f not in range (%f, %f)\n", + *iter_z, min_height_, max_height_); + continue; + } + + double range = hypot(*iter_x, *iter_y); + if (range < range_min_) { + RCLCPP_DEBUG( + this->get_logger(), + "rejected for range %f below minimum value %f. Point: (%f, %f, %f)", + range, range_min_, *iter_x, *iter_y, *iter_z); + continue; + } + if (range > range_max_) { + RCLCPP_DEBUG( + this->get_logger(), + "rejected for range %f above maximum value %f. Point: (%f, %f, %f)", + range, range_max_, *iter_x, *iter_y, *iter_z); + continue; + } + + double angle = atan2(*iter_y, *iter_x); + if (angle < scan_msg->angle_min || angle > scan_msg->angle_max) { + RCLCPP_DEBUG( + this->get_logger(), + "rejected for angle %f not in range (%f, %f)\n", + angle, scan_msg->angle_min, scan_msg->angle_max); + continue; + } + + // overwrite range at laserscan ray if new range is smaller + int index = (angle - scan_msg->angle_min) / scan_msg->angle_increment; + if (range < scan_msg->ranges[index]) { + scan_msg->ranges[index] = range; + } + } + pub_->publish(std::move(scan_msg)); +} + +} // namespace pointcloud_to_laserscan + +#include "rclcpp_components/register_node_macro.hpp" + +RCLCPP_COMPONENTS_REGISTER_NODE(pointcloud_to_laserscan::PointCloudToLaserScanNode) +

      H>J&=GpW!)y}iD1qLOFUxPgIJEi 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 z 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