2020-11-01 00:17:32 +08:00
// This is an advanced implementation of the algorithm 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.
// Modifier: Livox dev@livoxtech.com
// Copyright 2013, Ji Zhang, Carnegie Mellon University
// Further contributions copyright (c) 2016, Southwest Research Institute
// All rights reserved.
//
// 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.
# include <omp.h>
# include <mutex>
# include <math.h>
# include <thread>
# include <fstream>
# include <csignal>
# include <unistd.h>
# include <Python.h>
2021-01-14 15:33:31 +08:00
# include <so3_math.h>
2020-11-01 00:17:32 +08:00
# include <ros/ros.h>
# include <Eigen/Core>
# include "IMU_Processing.hpp"
# include <nav_msgs/Odometry.h>
2021-01-14 15:33:31 +08:00
# include <nav_msgs/Path.h>
2020-11-01 00:17:32 +08:00
# include <visualization_msgs/Marker.h>
# include <pcl_conversions/pcl_conversions.h>
# include <pcl/point_cloud.h>
# include <pcl/point_types.h>
# include <pcl/filters/voxel_grid.h>
# include <pcl/io/pcd_io.h>
# include <sensor_msgs/PointCloud2.h>
# include <tf/transform_datatypes.h>
# include <tf/transform_broadcaster.h>
# include <geometry_msgs/Vector3.h>
2021-07-04 22:17:41 +08:00
# include <livox_ros_driver/CustomMsg.h>
# include "preprocess.h"
# include <ikd-Tree/ikd_Tree.h>
# 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 ;
/**************************/
float res_last [ 100000 ] = { 0.0 } ;
float DET_RANGE = 300.0f ;
const float MOV_THRESHOLD = 1.5f ;
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 ;
bool point_selected_surf [ 100000 ] = { 0 } ;
bool lidar_pushed , flg_reset , flg_exit = false , flg_EKF_inited ;
bool dense_map_en = true ;
vector < vector < int > > pointSearchInd_surf ;
vector < BoxPointType > cub_needrm ;
vector < PointVector > Nearest_Points ;
vector < double > extrinT ( 3 , 0.0 ) ;
vector < double > extrinR ( 9 , 0.0 ) ;
deque < double > time_buffer ;
deque < PointCloudXYZI : : Ptr > lidar_buffer ;
deque < sensor_msgs : : Imu : : ConstPtr > imu_buffer ;
2020-11-01 00:17:32 +08:00
PointCloudXYZI : : Ptr featsFromMap ( new PointCloudXYZI ( ) ) ;
2021-07-04 22:17:41 +08:00
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 ;
2020-11-01 00:17:32 +08:00
2021-07-04 22:17:41 +08:00
pcl : : VoxelGrid < PointType > downSizeFilterSurf ;
pcl : : VoxelGrid < PointType > downSizeFilterMap ;
2021-01-14 15:33:31 +08:00
KD_TREE ikdtree ;
2021-07-04 22:17:41 +08:00
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 ) ;
2020-11-01 00:17:32 +08:00
2021-07-04 22:17:41 +08:00
/*** EKF inputs and output ***/
2020-11-01 00:17:32 +08:00
MeasureGroup Measures ;
2021-07-04 22:17:41 +08:00
esekfom : : esekf < state_ikfom , 12 , input_ikfom > kf ;
state_ikfom state_point ;
vect3 pos_lid ;
nav_msgs : : Path path ;
nav_msgs : : Odometry odomAftMapped ;
geometry_msgs : : Quaternion geoQuat ;
geometry_msgs : : PoseStamped msg_body_pose ;
shared_ptr < Preprocess > p_pre ( new Preprocess ( ) ) ;
shared_ptr < ImuProcess > p_imu ( new ImuProcess ( ) ) ;
2020-11-01 00:17:32 +08:00
void SigHandle ( int sig )
{
2021-07-04 22:17:41 +08:00
flg_exit = true ;
ROS_WARN ( " catch sig %d " , sig ) ;
sig_buffer . notify_all ( ) ;
2020-11-01 00:17:32 +08:00
}
2021-07-04 22:17:41 +08:00
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 ;
}
2020-11-01 00:17:32 +08:00
void pointBodyToWorld ( PointType const * const pi , PointType * const po )
{
2021-07-04 22:17:41 +08:00
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 ) ;
2020-11-01 00:17:32 +08:00
po - > x = p_global ( 0 ) ;
po - > y = p_global ( 1 ) ;
po - > z = p_global ( 2 ) ;
po - > intensity = pi - > intensity ;
}
2021-01-14 15:33:31 +08:00
template < typename T >
2021-07-04 22:17:41 +08:00
void pointBodyToWorld ( const Matrix < T , 3 , 1 > & pi , Matrix < T , 3 , 1 > & po )
2021-01-14 15:33:31 +08:00
{
2021-07-04 22:17:41 +08:00
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 ) ;
2021-01-14 15:33:31 +08:00
po [ 0 ] = p_global ( 0 ) ;
po [ 1 ] = p_global ( 1 ) ;
po [ 2 ] = p_global ( 2 ) ;
}
2021-07-04 22:17:41 +08:00
void RGBpointBodyToWorld ( PointType const * const pi , PointType * const po )
2020-11-01 00:17:32 +08:00
{
2021-07-04 22:17:41 +08:00
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 ) ;
2020-11-01 00:17:32 +08:00
po - > x = p_global ( 0 ) ;
po - > y = p_global ( 1 ) ;
po - > z = p_global ( 2 ) ;
2021-01-14 15:33:31 +08:00
po - > intensity = pi - > intensity ;
}
2020-11-01 00:17:32 +08:00
2021-07-04 22:17:41 +08:00
void points_cache_collect ( )
2021-01-14 15:33:31 +08:00
{
2021-07-04 22:17:41 +08:00
PointVector points_history ;
ikdtree . acquire_removed_points ( points_history ) ;
for ( int i = 0 ; i < points_history . size ( ) ; i + + ) _featsArray - > push_back ( points_history [ i ] ) ;
2020-11-01 00:17:32 +08:00
}
2021-07-04 22:17:41 +08:00
BoxPointType LocalMap_Points ;
bool Localmap_Initialized = false ;
2020-11-01 00:17:32 +08:00
void lasermap_fov_segment ( )
{
2021-07-04 22:17:41 +08:00
cub_needrm . clear ( ) ;
kdtree_delete_counter = 0 ;
kdtree_delete_time = 0.0 ;
2021-01-14 15:33:31 +08:00
pointBodyToWorld ( XAxisPoint_body , XAxisPoint_world ) ;
2021-07-04 22:17:41 +08:00
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 ;
2020-11-01 00:17:32 +08:00
}
2021-07-04 22:17:41 +08:00
Localmap_Initialized = true ;
return ;
2020-11-01 00:17:32 +08:00
}
2021-07-04 22:17:41 +08:00
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 ;
2020-11-01 00:17:32 +08:00
}
2021-07-04 22:17:41 +08:00
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 ) ;
2020-11-01 00:17:32 +08:00
}
}
2021-07-04 22:17:41 +08:00
LocalMap_Points = New_LocalMap_Points ;
2020-11-01 00:17:32 +08:00
2021-07-04 22:17:41 +08:00
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 ;
}
2020-11-01 00:17:32 +08:00
2021-07-04 22:17:41 +08:00
void standard_pcl_cbk ( const sensor_msgs : : PointCloud2 : : ConstPtr & msg )
{
mtx_buffer . lock ( ) ;
scan_count + + ;
double preprocess_start_time = omp_get_wtime ( ) ;
if ( msg - > header . stamp . toSec ( ) < last_timestamp_lidar )
2020-11-01 00:17:32 +08:00
{
2021-07-04 22:17:41 +08:00
ROS_ERROR ( " lidar loop back, clear buffer " ) ;
lidar_buffer . clear ( ) ;
2020-11-01 00:17:32 +08:00
}
2021-01-14 15:33:31 +08:00
2021-07-04 22:17:41 +08:00
PointCloudXYZI : : Ptr ptr ( new PointCloudXYZI ( ) ) ;
p_pre - > process ( msg , ptr ) ;
lidar_buffer . push_back ( ptr ) ;
time_buffer . push_back ( msg - > header . stamp . toSec ( ) ) ;
last_timestamp_lidar = msg - > header . stamp . toSec ( ) ;
s_plot11 [ scan_count ] = omp_get_wtime ( ) - preprocess_start_time ;
mtx_buffer . unlock ( ) ;
sig_buffer . notify_all ( ) ;
2020-11-01 00:17:32 +08:00
}
2021-07-04 22:17:41 +08:00
void livox_pcl_cbk ( const livox_ros_driver : : CustomMsg : : ConstPtr & msg )
2020-11-01 00:17:32 +08:00
{
mtx_buffer . lock ( ) ;
2021-07-04 22:17:41 +08:00
scan_count + + ;
double preprocess_start_time = omp_get_wtime ( ) ;
2020-11-01 00:17:32 +08:00
if ( msg - > header . stamp . toSec ( ) < last_timestamp_lidar )
{
ROS_ERROR ( " lidar loop back, clear buffer " ) ;
lidar_buffer . clear ( ) ;
}
2021-07-04 22:17:41 +08:00
PointCloudXYZI : : Ptr ptr ( new PointCloudXYZI ( ) ) ;
p_pre - > process ( msg , ptr ) ;
lidar_buffer . push_back ( ptr ) ;
time_buffer . push_back ( msg - > header . stamp . toSec ( ) ) ;
2020-11-01 00:17:32 +08:00
last_timestamp_lidar = msg - > header . stamp . toSec ( ) ;
2021-07-04 22:17:41 +08:00
s_plot11 [ scan_count ] = omp_get_wtime ( ) - preprocess_start_time ;
2020-11-01 00:17:32 +08:00
mtx_buffer . unlock ( ) ;
sig_buffer . notify_all ( ) ;
}
void imu_cbk ( const sensor_msgs : : Imu : : ConstPtr & msg_in )
{
2021-07-04 22:17:41 +08:00
publish_count + + ;
2020-11-01 00:17:32 +08:00
sensor_msgs : : Imu : : Ptr msg ( new sensor_msgs : : Imu ( * msg_in ) ) ;
double timestamp = msg - > header . stamp . toSec ( ) ;
mtx_buffer . lock ( ) ;
if ( timestamp < last_timestamp_imu )
{
ROS_ERROR ( " imu loop back, clear buffer " ) ;
imu_buffer . clear ( ) ;
2021-01-14 15:33:31 +08:00
flg_reset = true ;
2020-11-01 00:17:32 +08:00
}
last_timestamp_imu = timestamp ;
imu_buffer . push_back ( msg ) ;
mtx_buffer . unlock ( ) ;
sig_buffer . notify_all ( ) ;
}
bool sync_packages ( MeasureGroup & meas )
{
if ( lidar_buffer . empty ( ) | | imu_buffer . empty ( ) ) {
return false ;
}
2021-07-04 22:17:41 +08:00
/*** push a lidar scan ***/
2020-11-01 00:17:32 +08:00
if ( ! lidar_pushed )
{
2021-07-04 22:17:41 +08:00
meas . lidar = lidar_buffer . front ( ) ;
if ( meas . lidar - > points . size ( ) < = 1 )
{
lidar_buffer . pop_front ( ) ;
return false ;
}
meas . lidar_beg_time = time_buffer . front ( ) ;
2020-11-01 00:17:32 +08:00
lidar_end_time = meas . lidar_beg_time + meas . lidar - > points . back ( ) . curvature / double ( 1000 ) ;
lidar_pushed = true ;
}
if ( last_timestamp_imu < lidar_end_time )
{
return false ;
}
2021-01-14 15:33:31 +08:00
/*** push imu data, and pop from imu buffer ***/
2020-11-01 00:17:32 +08:00
double imu_time = imu_buffer . front ( ) - > header . stamp . toSec ( ) ;
meas . imu . clear ( ) ;
while ( ( ! imu_buffer . empty ( ) ) & & ( imu_time < lidar_end_time ) )
{
imu_time = imu_buffer . front ( ) - > header . stamp . toSec ( ) ;
2021-07-04 22:17:41 +08:00
if ( imu_time > lidar_end_time ) break ;
2020-11-01 00:17:32 +08:00
meas . imu . push_back ( imu_buffer . front ( ) ) ;
imu_buffer . pop_front ( ) ;
}
lidar_buffer . pop_front ( ) ;
2021-07-04 22:17:41 +08:00
time_buffer . pop_front ( ) ;
2020-11-01 00:17:32 +08:00
lidar_pushed = false ;
return true ;
}
2021-07-04 22:17:41 +08:00
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 ( 500000 , 1 ) ) ;
void publish_frame_world ( const ros : : Publisher & pubLaserCloudFullRes )
{
PointCloudXYZI : : Ptr laserCloudFullRes ( dense_map_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 ;
if ( 1 )
{
sensor_msgs : : PointCloud2 laserCloudmsg ;
pcl : : toROSMsg ( * pcl_wait_pub , laserCloudmsg ) ;
laserCloudmsg . header . stamp = ros : : Time : : now ( ) ;
laserCloudmsg . header . frame_id = " camera_init " ;
pubLaserCloudFullRes . publish ( laserCloudmsg ) ;
publish_count - = PUBFRAME_PERIOD ;
pcl_wait_pub - > clear ( ) ;
}
}
void publish_effect_world ( const ros : : Publisher & 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 : : PointCloud2 laserCloudFullRes3 ;
pcl : : toROSMsg ( * laserCloudWorld , laserCloudFullRes3 ) ;
laserCloudFullRes3 . header . stamp = ros : : Time : : now ( ) ;
laserCloudFullRes3 . header . frame_id = " camera_init " ;
pubLaserCloudEffect . publish ( laserCloudFullRes3 ) ;
}
void publish_map ( const ros : : Publisher & pubLaserCloudMap )
{
sensor_msgs : : PointCloud2 laserCloudMap ;
pcl : : toROSMsg ( * featsFromMap , laserCloudMap ) ;
laserCloudMap . header . stamp = ros : : Time : : now ( ) ;
laserCloudMap . header . frame_id = " camera_init " ;
pubLaserCloudMap . publish ( laserCloudMap ) ;
}
template < typename T >
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 ros : : Publisher & pubOdomAftMapped )
{
odomAftMapped . header . frame_id = " camera_init " ;
odomAftMapped . child_frame_id = " aft_mapped " ;
odomAftMapped . header . stamp = ros : : Time : : now ( ) ; //ros::Time().fromSec(last_timestamp_lidar);
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 ) ;
}
static tf : : TransformBroadcaster br ;
tf : : Transform transform ;
tf : : Quaternion q ;
transform . setOrigin ( tf : : Vector3 ( odomAftMapped . pose . pose . position . x , \
odomAftMapped . pose . pose . position . y , \
odomAftMapped . pose . pose . position . z ) ) ;
q . setW ( odomAftMapped . pose . pose . orientation . w ) ;
q . setX ( odomAftMapped . pose . pose . orientation . x ) ;
q . setY ( odomAftMapped . pose . pose . orientation . y ) ;
q . setZ ( odomAftMapped . pose . pose . orientation . z ) ;
transform . setRotation ( q ) ;
br . sendTransform ( tf : : StampedTransform ( transform , odomAftMapped . header . stamp , " camera_init " , " aft_mapped " ) ) ;
}
void publish_path ( const ros : : Publisher pubPath )
{
set_posestamp ( msg_body_pose ) ;
msg_body_pose . header . stamp = ros : : Time : : now ( ) ;
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 < double > & 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 < float > 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 + + ;
}
}
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 < < SKEW_SYM_MATRX ( point_this ) ;
/*** get the normal vector of closest surface/corner ***/
const PointType & norm_p = corr_normvect - > 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 ) ;
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 ) ;
/*** Measuremnt: distance to the closest surface/corner ***/
ekfom_data . h ( i ) = - norm_p . intensity ;
}
solve_time + = omp_get_wtime ( ) - solve_start_ ;
}
2020-11-01 00:17:32 +08:00
int main ( int argc , char * * argv )
{
ros : : init ( argc , argv , " laserMapping " ) ;
ros : : NodeHandle nh ;
2021-07-04 22:17:41 +08:00
nh . param < bool > ( " dense_map_enable " , dense_map_en , 1 ) ;
nh . param < int > ( " max_iteration " , NUM_MAX_ITERATIONS , 4 ) ;
nh . param < string > ( " map_file_path " , map_file_path , " " ) ;
nh . param < string > ( " common/lid_topic " , lid_topic , " /livox/lidar " ) ;
nh . param < string > ( " common/imu_topic " , imu_topic , " /livox/imu " ) ;
nh . param < double > ( " filter_size_corner " , filter_size_corner_min , 0.5 ) ;
nh . param < double > ( " filter_size_surf " , filter_size_surf_min , 0.5 ) ;
nh . param < double > ( " filter_size_map " , filter_size_map_min , 0.5 ) ;
nh . param < double > ( " cube_side_length " , cube_len , 200 ) ;
nh . param < float > ( " mapping/det_range " , DET_RANGE , 300.f ) ;
nh . param < double > ( " mapping/fov_degree " , fov_deg , 180 ) ;
nh . param < double > ( " mapping/gyr_cov " , gyr_cov , 0.1 ) ;
nh . param < double > ( " mapping/acc_cov " , acc_cov , 0.1 ) ;
nh . param < double > ( " mapping/b_gyr_cov " , b_gyr_cov , 0.0001 ) ;
nh . param < double > ( " mapping/b_acc_cov " , b_acc_cov , 0.0001 ) ;
nh . param < double > ( " preprocess/blind " , p_pre - > blind , 0.01 ) ;
nh . param < int > ( " preprocess/lidar_type " , p_pre - > lidar_type , AVIA ) ;
nh . param < int > ( " preprocess/scan_line " , p_pre - > N_SCANS , 16 ) ;
nh . param < int > ( " point_filter_num " , p_pre - > point_filter_num , 2 ) ;
nh . param < bool > ( " feature_extract_enable " , p_pre - > feature_enabled , 0 ) ;
nh . param < bool > ( " runtime_pos_log_enable " , runtime_pos_log , 0 ) ;
nh . param < vector < double > > ( " mapping/extrinsic_T " , extrinT , vector < double > ( ) ) ;
nh . param < vector < double > > ( " mapping/extrinsic_R " , extrinR , vector < double > ( ) ) ;
cout < < " p_pre->lidar_type " < < p_pre - > lidar_type < < endl ;
2021-01-14 15:33:31 +08:00
path . header . stamp = ros : : Time : : now ( ) ;
2021-07-04 22:17:41 +08:00
path . header . frame_id = " camera_init " ;
2021-01-14 15:33:31 +08:00
2020-11-01 00:17:32 +08:00
/*** variables definition ***/
int effect_feat_num = 0 , frame_num = 0 ;
2021-07-04 22:17:41 +08:00
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 ( ) ) ;
2020-11-01 00:17:32 +08:00
2021-07-04 22:17:41 +08:00
memset ( point_selected_surf , true , sizeof ( point_selected_surf ) ) ;
memset ( res_last , - 1000.0f , sizeof ( res_last ) ) ;
2020-11-01 00:17:32 +08:00
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 ) ;
2021-07-04 22:17:41 +08:00
memset ( point_selected_surf , true , sizeof ( point_selected_surf ) ) ;
memset ( res_last , - 1000.0f , sizeof ( res_last ) ) ;
2020-11-01 00:17:32 +08:00
2021-07-04 22:17:41 +08:00
Lidar_T_wrt_IMU < < VEC_FROM_ARRAY ( extrinT ) ;
Lidar_R_wrt_IMU < < MAT_FROM_ARRAY ( extrinR ) ;
p_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 ) ) ;
double epsi [ 23 ] = { 0.001 } ;
fill ( epsi , epsi + 23 , 0.001 ) ;
kf . init_dyn_share ( get_f , df_dx , df_dw , h_share_model , NUM_MAX_ITERATIONS , epsi ) ;
2020-11-01 00:17:32 +08:00
/*** debug record ***/
2021-07-04 22:17:41 +08:00
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 ) ;
2020-11-01 00:17:32 +08:00
if ( fout_pre & & fout_out )
2021-07-04 22:17:41 +08:00
cout < < " ~~~~ " < < ROOT_DIR < < " file opened " < < endl ;
2020-11-01 00:17:32 +08:00
else
2021-07-04 22:17:41 +08:00
cout < < " ~~~~ " < < ROOT_DIR < < " doesn't exist " < < endl ;
2020-11-01 00:17:32 +08:00
2021-07-04 22:17:41 +08:00
/*** ROS subscribe initialization ***/
ros : : Subscriber sub_pcl = p_pre - > lidar_type = = AVIA ? \
nh . subscribe ( lid_topic , 200000 , livox_pcl_cbk ) : \
nh . subscribe ( lid_topic , 200000 , standard_pcl_cbk ) ;
ros : : Subscriber sub_imu = nh . subscribe ( imu_topic , 200000 , imu_cbk ) ;
ros : : Publisher pubLaserCloudFullRes = nh . advertise < sensor_msgs : : PointCloud2 >
( " /cloud_registered " , 100000 ) ;
ros : : Publisher pubLaserCloudEffect = nh . advertise < sensor_msgs : : PointCloud2 >
( " /cloud_effected " , 100000 ) ;
ros : : Publisher pubLaserCloudMap = nh . advertise < sensor_msgs : : PointCloud2 >
( " /Laser_map " , 100000 ) ;
ros : : Publisher pubOdomAftMapped = nh . advertise < nav_msgs : : Odometry >
( " /aft_mapped_to_init " , 100000 ) ;
ros : : Publisher pubPath = nh . advertise < nav_msgs : : Path >
( " /path " , 100000 ) ;
2020-11-01 00:17:32 +08:00
//------------------------------------------------------------------------------------------------------
signal ( SIGINT , SigHandle ) ;
ros : : Rate rate ( 5000 ) ;
bool status = ros : : ok ( ) ;
while ( status )
{
2021-01-14 15:33:31 +08:00
if ( flg_exit ) break ;
2020-11-01 00:17:32 +08:00
ros : : spinOnce ( ) ;
2021-07-04 22:17:41 +08:00
if ( sync_packages ( Measures ) )
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
if ( flg_reset )
2020-11-01 00:17:32 +08:00
{
ROS_WARN ( " reset when rosbag play back " ) ;
p_imu - > Reset ( ) ;
2021-01-14 15:33:31 +08:00
flg_reset = false ;
2020-11-01 00:17:32 +08:00
continue ;
}
2021-07-04 22:17:41 +08:00
double t0 , t1 , t2 , t3 , t4 , t5 , match_start , solve_start , svd_time ;
2020-11-01 00:17:32 +08:00
match_time = 0 ;
2021-07-04 22:17:41 +08:00
kdtree_search_time = 0.0 ;
2020-11-01 00:17:32 +08:00
solve_time = 0 ;
2021-07-04 22:17:41 +08:00
solve_const_H_time = 0 ;
2020-11-01 00:17:32 +08:00
svd_time = 0 ;
2021-01-14 15:33:31 +08:00
t0 = omp_get_wtime ( ) ;
2020-11-01 00:17:32 +08:00
2021-07-04 22:17:41 +08:00
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 ;
2020-11-01 00:17:32 +08:00
if ( feats_undistort - > empty ( ) | | ( feats_undistort = = NULL ) )
{
first_lidar_time = Measures . lidar_beg_time ;
2021-07-04 22:17:41 +08:00
p_imu - > first_lidar_time = first_lidar_time ;
cout < < " FAST-LIO not ready " < < endl ;
2020-11-01 00:17:32 +08:00
continue ;
}
2021-07-04 22:17:41 +08:00
flg_EKF_inited = ( Measures . lidar_beg_time - first_lidar_time ) < INIT_TIME ? \
false : true ;
2020-11-01 00:17:32 +08:00
/*** Segment the map in lidar FOV ***/
lasermap_fov_segment ( ) ;
2021-07-04 22:17:41 +08:00
/*** 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 ( ) ;
2021-01-14 15:33:31 +08:00
/*** initialize the map kdtree ***/
if ( ikdtree . Root_Node = = nullptr )
{
2021-07-04 22:17:41 +08:00
if ( feats_down_size > 5 )
2021-01-14 15:33:31 +08:00
{
2021-07-04 22:17:41 +08:00
ikdtree . set_downsample_param ( filter_size_map_min ) ;
feats_down_world - > resize ( feats_down_size ) ;
for ( int i = 0 ; i < feats_down_size ; i + + )
2021-01-14 15:33:31 +08:00
{
2021-07-04 22:17:41 +08:00
pointBodyToWorld ( & ( feats_down_body - > points [ i ] ) , & ( feats_down_world - > points [ i ] ) ) ;
2021-01-14 15:33:31 +08:00
}
2021-07-04 22:17:41 +08:00
ikdtree . Build ( feats_down_world - > points ) ;
2021-01-14 15:33:31 +08:00
}
2021-07-04 22:17:41 +08:00
continue ;
2021-01-14 15:33:31 +08:00
}
2021-07-04 22:17:41 +08:00
int featsFromMapNum = ikdtree . validnum ( ) ;
kdtree_size_st = ikdtree . size ( ) ;
// cout<<"[ mapping ]: In num: "<<feats_undistort->points.size()<<" downsamp "<<feats_down_size<<" Map num: "<<featsFromMapNum<<"effect num:"<<effct_feat_num<<endl;
2020-11-01 00:17:32 +08:00
2021-07-04 22:17:41 +08:00
/*** ICP and iterated Kalman filter update ***/
normvec - > resize ( feats_down_size ) ;
feats_down_world - > resize ( feats_down_size ) ;
2020-11-01 00:17:32 +08:00
2021-07-04 22:17:41 +08:00
V3D ext_euler = SO3ToEuler ( state_point . offset_R_L_I ) ;
fout_pre < < setw ( 20 ) < < Measures . lidar_beg_time - first_lidar_time < < " " < < euler_cur . transpose ( ) < < " " < < state_point . pos . transpose ( ) < < " " < < ext_euler . transpose ( ) < < " " < < state_point . offset_T_L_I . transpose ( ) < < " " < < state_point . vel . transpose ( ) \
< < " " < < state_point . bg . transpose ( ) < < " " < < state_point . ba . transpose ( ) < < " " < < state_point . grav < < endl ;
2020-11-12 14:52:34 +08:00
2021-07-04 22:17:41 +08:00
if ( 0 ) // If you need to see map point, change to "if(1)"
2021-01-14 15:33:31 +08:00
{
2021-07-04 22:17:41 +08:00
PointVector ( ) . swap ( ikdtree . PCL_Storage ) ;
ikdtree . flatten ( ikdtree . Root_Node , ikdtree . PCL_Storage , NOT_RECORD ) ;
featsFromMap - > clear ( ) ;
featsFromMap - > points = ikdtree . PCL_Storage ;
2021-01-14 15:33:31 +08:00
}
2020-11-01 00:17:32 +08:00
2021-07-04 22:17:41 +08:00
pointSearchInd_surf . resize ( feats_down_size ) ;
Nearest_Points . resize ( feats_down_size ) ;
int rematch_num = 0 ;
bool nearest_search_en = true ; //
2020-11-01 00:17:32 +08:00
2021-07-04 22:17:41 +08:00
t2 = omp_get_wtime ( ) ;
2021-01-14 15:33:31 +08:00
2021-07-04 22:17:41 +08:00
/*** 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 ) ;
/*** add the feature points to map kdtree ***/
t3 = omp_get_wtime ( ) ;
map_incremental ( ) ;
t5 = omp_get_wtime ( ) ;
/******* Publish points *******/
publish_frame_world ( pubLaserCloudFullRes ) ;
publish_path ( pubPath ) ;
// publish_effect_world(pubLaserCloudEffect);
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 ( ) < < " " < < state_point . offset_T_L_I . transpose ( ) < < " " < < state_point . vel . transpose ( ) \
< < " " < < state_point . bg . transpose ( ) < < " " < < state_point . ba . transpose ( ) < < " " < < state_point . grav < < " " < < feats_undistort - > points . size ( ) < < endl ;
dump_lio_state_to_log ( fp ) ;
}
2020-11-01 00:17:32 +08:00
}
status = ros : : ok ( ) ;
rate . sleep ( ) ;
}
2021-07-04 22:17:41 +08:00
/**************** save map ****************
string surf_filename ( map_file_path + " /surf.pcd " ) ;
string corner_filename ( map_file_path + " /corner.pcd " ) ;
string all_points_filename ( map_file_path + " /all_points.pcd " ) ;
PointCloudXYZI surf_points , corner_points ;
surf_points = * featsFromMap ;
fout_out . close ( ) ;
fout_pre . close ( ) ;
if ( surf_points . size ( ) > 0 & & corner_points . size ( ) > 0 )
2020-11-01 00:17:32 +08:00
{
2021-07-04 22:17:41 +08:00
pcl : : PCDWriter pcd_writer ;
cout < < " saving... " ;
pcd_writer . writeBinary ( surf_filename , surf_points ) ;
pcd_writer . writeBinary ( corner_filename , corner_points ) ;
}
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
if ( runtime_pos_log )
{
vector < double > 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 < time_log_counter ; i + + ) {
fprintf ( fp2 , " %0.8f,%0.8f,%d,%0.8f,%0.8f,%d,%0.8f,%d,%d,%d,%0.8f \n " , T1 [ i ] , s_plot [ i ] , int ( s_plot2 [ i ] ) , s_plot3 [ i ] , s_plot4 [ i ] , int ( s_plot5 [ i ] ) , s_plot6 [ i ] , int ( s_plot7 [ i ] ) , int ( s_plot8 [ i ] ) , int ( s_plot10 [ i ] ) , s_plot11 [ i ] ) ;
t . push_back ( T1 [ i ] ) ;
s_vec . push_back ( s_plot9 [ i ] ) ;
s_vec2 . push_back ( s_plot3 [ i ] + s_plot6 [ i ] ) ;
s_vec3 . push_back ( s_plot4 [ i ] ) ;
s_vec5 . push_back ( s_plot [ i ] ) ;
}
fclose ( fp2 ) ;
2020-11-01 00:17:32 +08:00
}
2021-01-14 15:33:31 +08:00
2020-11-01 00:17:32 +08:00
return 0 ;
}