Fast-Lio/src/laserMapping.cpp

1322 lines
54 KiB
C++
Raw Normal View History

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>
2021-01-01 14:30:02 +08:00
#include <opencv2/core.hpp>
2020-11-01 00:17:32 +08:00
#include <common_lib.h>
2021-01-14 15:33:31 +08:00
2020-11-01 00:17:32 +08:00
#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 <opencv2/core/eigen.hpp>
#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/kdtree/kdtree_flann.h>
#include <pcl/io/pcd_io.h>
#include <sensor_msgs/PointCloud2.h>
#include <tf/transform_datatypes.h>
#include <tf/transform_broadcaster.h>
#include <fast_lio/States.h>
#include <geometry_msgs/Vector3.h>
2021-01-14 15:33:31 +08:00
#ifdef DEPLOY
2020-11-01 00:17:32 +08:00
#include "matplotlibcpp.h"
namespace plt = matplotlibcpp;
#endif
2021-01-14 15:33:31 +08:00
#define INIT_TIME (0)
2020-11-01 00:17:32 +08:00
#define LASER_POINT_COV (0.0015)
#define NUM_MATCH_POINTS (5)
std::string root_dir = ROOT_DIR;
int iterCount = 0;
int NUM_MAX_ITERATIONS = 0;
2021-01-14 15:33:31 +08:00
int FOV_RANGE = 3; // range of FOV = FOV_RANGE * cube_len
int laserCloudCenWidth = 24;
int laserCloudCenHeight = 24;
int laserCloudCenDepth = 24;
2020-11-01 00:17:32 +08:00
int laserCloudValidNum = 0;
int laserCloudSelNum = 0;
2020-11-01 00:17:32 +08:00
2021-01-14 15:33:31 +08:00
const int laserCloudWidth = 48;
const int laserCloudHeight = 48;
const int laserCloudDepth = 48;
const int laserCloudNum = laserCloudWidth * laserCloudHeight * laserCloudDepth;
std::vector<double> T1, T2, s_plot, s_plot2, s_plot3, s_plot4, s_plot5, s_plot6;
2020-11-01 00:17:32 +08:00
/// IMU relative variables
std::mutex mtx_buffer;
std::condition_variable sig_buffer;
bool lidar_pushed = false;
2021-01-14 15:33:31 +08:00
bool flg_exit = false;
bool flg_reset = false;
bool flg_map_inited = false;
2020-11-01 00:17:32 +08:00
/// Buffers for measurements
double cube_len = 0.0;
double lidar_end_time = 0.0;
double last_timestamp_lidar = -1;
double last_timestamp_imu = -1;
double HALF_FOV_COS = 0.0;
2021-01-14 15:33:31 +08:00
double res_mean_last = 0.05;
double total_distance = 0.0;
auto position_last = Zero3d;
double copy_time, readd_time;
2020-11-01 00:17:32 +08:00
std::deque<sensor_msgs::PointCloud2::ConstPtr> lidar_buffer;
std::deque<sensor_msgs::Imu::ConstPtr> imu_buffer;
//surf feature in map
PointCloudXYZI::Ptr featsFromMap(new PointCloudXYZI());
2021-01-14 15:33:31 +08:00
PointCloudXYZI::Ptr cube_points_add(new PointCloudXYZI());
2020-11-01 00:17:32 +08:00
//all points
PointCloudXYZI::Ptr laserCloudFullRes2(new PointCloudXYZI());
PointCloudXYZI::Ptr featsArray[laserCloudNum];
2021-01-14 15:33:31 +08:00
bool _last_inFOV[laserCloudNum];
bool cube_updated[laserCloudNum];
int laserCloudValidInd[laserCloudNum];
pcl::PointCloud<pcl::PointXYZI>::Ptr laserCloudFullResColor(new pcl::PointCloud<pcl::PointXYZI>());
#ifdef USE_ikdtree
KD_TREE ikdtree;
std::vector<BoxPointType> cub_needrm;
std::vector<BoxPointType> cub_needad;
#else
2020-11-01 00:17:32 +08:00
pcl::KdTreeFLANN<PointType>::Ptr kdtreeSurfFromMap(new pcl::KdTreeFLANN<PointType>());
2021-01-14 15:33:31 +08:00
#endif
Eigen::Vector3f XAxisPoint_body(LIDAR_SP_LEN, 0.0, 0.0);
Eigen::Vector3f XAxisPoint_world(LIDAR_SP_LEN, 0.0, 0.0);
2020-11-01 00:17:32 +08:00
//estimator inputs and output;
MeasureGroup Measures;
StatesGroup state;
void SigHandle(int sig)
{
2021-01-14 15:33:31 +08:00
flg_exit = true;
2020-11-01 00:17:32 +08:00
ROS_WARN("catch sig %d", sig);
sig_buffer.notify_all();
}
//project lidar frame to world
void pointBodyToWorld(PointType const * const pi, PointType * const po)
{
Eigen::Vector3d p_body(pi->x, pi->y, pi->z);
Eigen::Vector3d p_global(state.rot_end * (p_body + Lidar_offset_to_IMU) + state.pos_end);
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>
void pointBodyToWorld(const Eigen::Matrix<T, 3, 1> &pi, Eigen::Matrix<T, 3, 1> &po)
{
Eigen::Vector3d p_body(pi[0], pi[1], pi[2]);
Eigen::Vector3d p_global(state.rot_end * (p_body + Lidar_offset_to_IMU) + state.pos_end);
po[0] = p_global(0);
po[1] = p_global(1);
po[2] = p_global(2);
}
void RGBpointBodyToWorld(PointType const * const pi, pcl::PointXYZI * const po)
2020-11-01 00:17:32 +08:00
{
Eigen::Vector3d p_body(pi->x, pi->y, pi->z);
Eigen::Vector3d p_global(state.rot_end * (p_body + Lidar_offset_to_IMU) + state.pos_end);
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
float intensity = pi->intensity;
intensity = intensity - std::floor(intensity);
int reflection_map = intensity*10000;
2021-01-14 15:33:31 +08:00
// //std::cout<<"DEBUG reflection_map "<<reflection_map<<std::endl;
// if (reflection_map < 30)
// {
// int green = (reflection_map * 255 / 30);
// po->r = 0;
// po->g = green & 0xff;
// po->b = 0xff;
// }
// else if (reflection_map < 90)
// {
// int blue = (((90 - reflection_map) * 255) / 60);
// po->r = 0x0;
// po->g = 0xff;
// po->b = blue & 0xff;
// }
// else if (reflection_map < 150)
// {
// int red = ((reflection_map-90) * 255 / 60);
// po->r = red & 0xff;
// po->g = 0xff;
// po->b = 0x0;
// }
// else
// {
// int green = (((255-reflection_map) * 255) / (255-150));
// po->r = 0xff;
// po->g = green & 0xff;
// po->b = 0;
// }
}
2020-11-01 00:17:32 +08:00
2021-01-14 15:33:31 +08:00
int cube_ind(const int &i, const int &j, const int &k)
{
return (i + laserCloudWidth * j + laserCloudWidth * laserCloudHeight * k);
}
bool CenterinFOV(Eigen::Vector3f cube_p)
{
Eigen::Vector3f dis_vec = state.pos_end.cast<float>() - cube_p;
float squaredSide1 = dis_vec.transpose() * dis_vec;
if(squaredSide1 < 0.4 * cube_len * cube_len) return true;
dis_vec = XAxisPoint_world.cast<float>() - cube_p;
float squaredSide2 = dis_vec.transpose() * dis_vec;
float ang_cos = fabs(squaredSide1 <= 3) ? 1.0 :
(LIDAR_SP_LEN * LIDAR_SP_LEN + squaredSide1 - squaredSide2) / (2 * LIDAR_SP_LEN * sqrt(squaredSide1));
return ((ang_cos > HALF_FOV_COS)? true : false);
}
bool CornerinFOV(Eigen::Vector3f cube_p)
{
Eigen::Vector3f dis_vec = state.pos_end.cast<float>() - cube_p;
float squaredSide1 = dis_vec.transpose() * dis_vec;
dis_vec = XAxisPoint_world.cast<float>() - cube_p;
float squaredSide2 = dis_vec.transpose() * dis_vec;
float ang_cos = fabs(squaredSide1 <= 3) ? 1.0 :
(LIDAR_SP_LEN * LIDAR_SP_LEN + squaredSide1 - squaredSide2) / (2 * LIDAR_SP_LEN * sqrt(squaredSide1));
return ((ang_cos > HALF_FOV_COS)? true : false);
2020-11-01 00:17:32 +08:00
}
void lasermap_fov_segment()
{
2021-01-14 15:33:31 +08:00
laserCloudValidNum = 0;
pointBodyToWorld(XAxisPoint_body, XAxisPoint_world);
2020-11-01 00:17:32 +08:00
int centerCubeI = int((state.pos_end(0) + 0.5 * cube_len) / cube_len) + laserCloudCenWidth;
int centerCubeJ = int((state.pos_end(1) + 0.5 * cube_len) / cube_len) + laserCloudCenHeight;
int centerCubeK = int((state.pos_end(2) + 0.5 * cube_len) / cube_len) + laserCloudCenDepth;
if (state.pos_end(0) + 0.5 * cube_len < 0) centerCubeI--;
if (state.pos_end(1) + 0.5 * cube_len < 0) centerCubeJ--;
if (state.pos_end(2) + 0.5 * cube_len < 0) centerCubeK--;
2021-01-14 15:33:31 +08:00
bool last_inFOV_flag = 0;
int cube_index = 0;
T2.push_back(Measures.lidar_beg_time);
double t_begin = omp_get_wtime();
std::cout<<"centerCubeIJK: "<<centerCubeI<<" "<<centerCubeJ<<" "<<centerCubeK<<std::endl;
while (centerCubeI < FOV_RANGE + 1)
2020-11-01 00:17:32 +08:00
{
for (int j = 0; j < laserCloudHeight; j++)
{
for (int k = 0; k < laserCloudDepth; k++)
{
int i = laserCloudWidth - 1;
2021-01-14 15:33:31 +08:00
PointCloudXYZI::Ptr laserCloudCubeSurfPointer = featsArray[cube_ind(i, j, k)];
last_inFOV_flag = _last_inFOV[cube_index];
2020-11-01 00:17:32 +08:00
for (; i >= 1; i--) {
2021-01-14 15:33:31 +08:00
featsArray[cube_ind(i, j, k)] = featsArray[cube_ind(i-1, j, k)];
_last_inFOV[cube_ind(i, j, k)] = _last_inFOV[cube_ind(i-1, j, k)];
2020-11-01 00:17:32 +08:00
}
2021-01-14 15:33:31 +08:00
featsArray[cube_ind(i, j, k)] = laserCloudCubeSurfPointer;
_last_inFOV[cube_ind(i, j, k)] = last_inFOV_flag;
2020-11-01 00:17:32 +08:00
laserCloudCubeSurfPointer->clear();
}
}
centerCubeI++;
laserCloudCenWidth++;
}
2021-01-14 15:33:31 +08:00
while (centerCubeI >= laserCloudWidth - (FOV_RANGE + 1)) {
2020-11-01 00:17:32 +08:00
for (int j = 0; j < laserCloudHeight; j++) {
for (int k = 0; k < laserCloudDepth; k++) {
int i = 0;
2021-01-14 15:33:31 +08:00
PointCloudXYZI::Ptr laserCloudCubeSurfPointer = featsArray[cube_ind(i, j, k)];
last_inFOV_flag = _last_inFOV[cube_index];
for (; i >= 1; i--) {
featsArray[cube_ind(i, j, k)] = featsArray[cube_ind(i+1, j, k)];
_last_inFOV[cube_ind(i, j, k)] = _last_inFOV[cube_ind(i+1, j, k)];
2020-11-01 00:17:32 +08:00
}
2021-01-14 15:33:31 +08:00
featsArray[cube_ind(i, j, k)] = laserCloudCubeSurfPointer;
_last_inFOV[cube_ind(i, j, k)] = last_inFOV_flag;
2020-11-01 00:17:32 +08:00
laserCloudCubeSurfPointer->clear();
}
}
centerCubeI--;
laserCloudCenWidth--;
}
2021-01-14 15:33:31 +08:00
while (centerCubeJ < (FOV_RANGE + 1)) {
2020-11-01 00:17:32 +08:00
for (int i = 0; i < laserCloudWidth; i++) {
for (int k = 0; k < laserCloudDepth; k++) {
int j = laserCloudHeight - 1;
2021-01-14 15:33:31 +08:00
PointCloudXYZI::Ptr laserCloudCubeSurfPointer = featsArray[cube_ind(i, j, k)];
last_inFOV_flag = _last_inFOV[cube_index];
for (; i >= 1; i--) {
featsArray[cube_ind(i, j, k)] = featsArray[cube_ind(i, j-1, k)];
_last_inFOV[cube_ind(i, j, k)] = _last_inFOV[cube_ind(i, j-1, k)];
2020-11-01 00:17:32 +08:00
}
2021-01-14 15:33:31 +08:00
featsArray[cube_ind(i, j, k)] = laserCloudCubeSurfPointer;
_last_inFOV[cube_ind(i, j, k)] = last_inFOV_flag;
2020-11-01 00:17:32 +08:00
laserCloudCubeSurfPointer->clear();
}
}
centerCubeJ++;
laserCloudCenHeight++;
}
2021-01-14 15:33:31 +08:00
while (centerCubeJ >= laserCloudHeight - (FOV_RANGE + 1)) {
2020-11-01 00:17:32 +08:00
for (int i = 0; i < laserCloudWidth; i++) {
for (int k = 0; k < laserCloudDepth; k++) {
int j = 0;
2021-01-14 15:33:31 +08:00
PointCloudXYZI::Ptr laserCloudCubeSurfPointer = featsArray[cube_ind(i, j, k)];
last_inFOV_flag = _last_inFOV[cube_index];
2020-11-01 00:17:32 +08:00
2021-01-14 15:33:31 +08:00
for (; i >= 1; i--) {
featsArray[cube_ind(i, j, k)] = featsArray[cube_ind(i, j+1, k)];
_last_inFOV[cube_ind(i, j, k)] = _last_inFOV[cube_ind(i, j+1, k)];
2020-11-01 00:17:32 +08:00
}
2021-01-14 15:33:31 +08:00
featsArray[cube_ind(i, j, k)] = laserCloudCubeSurfPointer;
_last_inFOV[cube_ind(i, j, k)] = last_inFOV_flag;
2020-11-01 00:17:32 +08:00
laserCloudCubeSurfPointer->clear();
}
}
centerCubeJ--;
laserCloudCenHeight--;
}
2021-01-14 15:33:31 +08:00
while (centerCubeK < (FOV_RANGE + 1)) {
2020-11-01 00:17:32 +08:00
for (int i = 0; i < laserCloudWidth; i++) {
for (int j = 0; j < laserCloudHeight; j++) {
int k = laserCloudDepth - 1;
2021-01-14 15:33:31 +08:00
PointCloudXYZI::Ptr laserCloudCubeSurfPointer = featsArray[cube_ind(i, j, k)];
last_inFOV_flag = _last_inFOV[cube_index];
2020-11-01 00:17:32 +08:00
2021-01-14 15:33:31 +08:00
for (; i >= 1; i--) {
featsArray[cube_ind(i, j, k)] = featsArray[cube_ind(i, j, k-1)];
_last_inFOV[cube_ind(i, j, k)] = _last_inFOV[cube_ind(i, j, k-1)];
2020-11-01 00:17:32 +08:00
}
2021-01-14 15:33:31 +08:00
featsArray[cube_ind(i, j, k)] = laserCloudCubeSurfPointer;
_last_inFOV[cube_ind(i, j, k)] = last_inFOV_flag;
2020-11-01 00:17:32 +08:00
laserCloudCubeSurfPointer->clear();
}
}
centerCubeK++;
laserCloudCenDepth++;
}
2021-01-14 15:33:31 +08:00
while (centerCubeK >= laserCloudDepth - (FOV_RANGE + 1))
2020-11-01 00:17:32 +08:00
{
for (int i = 0; i < laserCloudWidth; i++)
{
for (int j = 0; j < laserCloudHeight; j++)
{
int k = 0;
2021-01-14 15:33:31 +08:00
PointCloudXYZI::Ptr laserCloudCubeSurfPointer = featsArray[cube_ind(i, j, k)];
last_inFOV_flag = _last_inFOV[cube_index];
for (; i >= 1; i--) {
featsArray[cube_ind(i, j, k)] = featsArray[cube_ind(i, j, k+1)];
_last_inFOV[cube_ind(i, j, k)] = _last_inFOV[cube_ind(i, j, k+1)];
2020-11-01 00:17:32 +08:00
}
2021-01-14 15:33:31 +08:00
featsArray[cube_ind(i, j, k)] = laserCloudCubeSurfPointer;
_last_inFOV[cube_ind(i, j, k)] = last_inFOV_flag;
2020-11-01 00:17:32 +08:00
laserCloudCubeSurfPointer->clear();
}
}
centerCubeK--;
laserCloudCenDepth--;
}
2021-01-14 15:33:31 +08:00
cube_points_add->clear();
featsFromMap->clear();
bool now_inFOV[laserCloudNum] = {false};
// std::cout<<"centerCubeIJK: "<<centerCubeI<<" "<<centerCubeJ<<" "<<centerCubeK<<std::endl;
// std::cout<<"laserCloudCen: "<<laserCloudCenWidth<<" "<<laserCloudCenHeight<<" "<<laserCloudCenDepth<<std::endl;
for (int i = centerCubeI - FOV_RANGE; i <= centerCubeI + FOV_RANGE; i++)
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
for (int j = centerCubeJ - FOV_RANGE; j <= centerCubeJ + FOV_RANGE; j++)
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
for (int k = centerCubeK - FOV_RANGE; k <= centerCubeK + FOV_RANGE; k++)
2020-11-01 00:17:32 +08:00
{
if (i >= 0 && i < laserCloudWidth &&
j >= 0 && j < laserCloudHeight &&
k >= 0 && k < laserCloudDepth)
{
2021-01-14 15:33:31 +08:00
Eigen::Vector3f center_p(cube_len * (i - laserCloudCenWidth), \
cube_len * (j - laserCloudCenHeight), \
cube_len * (k - laserCloudCenDepth));
2020-11-01 00:17:32 +08:00
float check1, check2;
float squaredSide1, squaredSide2;
float ang_cos = 1;
2021-01-14 15:33:31 +08:00
bool &last_inFOV = _last_inFOV[i + laserCloudWidth * j + laserCloudWidth * laserCloudHeight * k];
bool inFOV = CenterinFOV(center_p);
2020-11-01 00:17:32 +08:00
2021-01-14 15:33:31 +08:00
for (int ii = -1; (ii <= 1) && (!inFOV); ii += 2)
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
for (int jj = -1; (jj <= 1) && (!inFOV); jj += 2)
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
for (int kk = -1; (kk <= 1) && (!inFOV); kk += 2)
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
Eigen::Vector3f corner_p(cube_len * ii, cube_len * jj, cube_len * kk);
corner_p = center_p + 0.5 * corner_p;
2020-11-01 00:17:32 +08:00
2021-01-14 15:33:31 +08:00
inFOV = CornerinFOV(corner_p);
2020-11-01 00:17:32 +08:00
}
}
}
2021-01-14 15:33:31 +08:00
now_inFOV[i + laserCloudWidth * j + laserCloudWidth * laserCloudHeight * k] = inFOV;
#ifdef USE_ikdtree
/*** readd cubes and points ***/
if (inFOV)
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
int center_index = i + laserCloudWidth * j + laserCloudWidth * laserCloudHeight * k;
*cube_points_add += *featsArray[center_index];
featsArray[center_index]->clear();
if (!last_inFOV)
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
BoxPointType cub_points;
for(int i = 0; i < 3; i++)
{
cub_points.vertex_max[i] = center_p[i] + 0.5 * cube_len;
cub_points.vertex_min[i] = center_p[i] - 0.5 * cube_len;
}
cub_needad.push_back(cub_points);
laserCloudValidInd[laserCloudValidNum] = center_index;
laserCloudValidNum ++;
// std::cout<<"readd center: "<<center_p.transpose()<<std::endl;
2020-11-01 00:17:32 +08:00
}
}
2021-01-14 15:33:31 +08:00
#else
if (inFOV)
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
int center_index = i + laserCloudWidth * j + laserCloudWidth * laserCloudHeight * k;
*featsFromMap += *featsArray[center_index];
laserCloudValidInd[laserCloudValidNum] = center_index;
laserCloudValidNum++;
2020-11-01 00:17:32 +08:00
}
2021-01-14 15:33:31 +08:00
last_inFOV = inFOV;
#endif
2020-11-01 00:17:32 +08:00
}
}
}
}
2021-01-14 15:33:31 +08:00
#ifdef USE_ikdtree
cub_needrm.clear();
cub_needad.clear();
/*** delete cubes ***/
for (int i = 0; i < laserCloudWidth; i++)
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
for (int j = 0; j < laserCloudHeight; j++)
{
for (int k = 0; k < laserCloudDepth; k++)
{
int ind = i + laserCloudWidth * j + laserCloudWidth * laserCloudHeight * k;
if((!now_inFOV[ind]) && _last_inFOV[ind])
{
BoxPointType cub_points;
Eigen::Vector3f center_p(cube_len * (i - laserCloudCenWidth),\
cube_len * (j - laserCloudCenHeight),\
cube_len * (k - laserCloudCenDepth));
// std::cout<<"center_p: "<<center_p.transpose()<<std::endl;
for(int i = 0; i < 3; i++)
{
cub_points.vertex_max[i] = center_p[i] + 0.5 * cube_len;
cub_points.vertex_min[i] = center_p[i] - 0.5 * cube_len;
}
cub_needrm.push_back(cub_points);
}
_last_inFOV[ind] = now_inFOV[ind];
}
}
2020-11-01 00:17:32 +08:00
}
2021-01-14 15:33:31 +08:00
#endif
copy_time = omp_get_wtime() - t_begin;
#ifdef USE_ikdtree
if(cub_needrm.size() > 0) ikdtree.Delete_Point_Boxes(cub_needrm);
// s_plot4.push_back(omp_get_wtime() - t_begin); t_begin = omp_get_wtime();
if(cub_needad.size() > 0) ikdtree.Add_Point_Boxes(cub_needad);
// s_plot5.push_back(omp_get_wtime() - t_begin); t_begin = omp_get_wtime();
if(cube_points_add->points.size() > 0) ikdtree.Add_Points(cube_points_add->points, true);
#endif
s_plot6.push_back(omp_get_wtime() - t_begin);
readd_time = omp_get_wtime() - t_begin - copy_time;
2020-11-01 00:17:32 +08:00
}
void feat_points_cbk(const sensor_msgs::PointCloud2::ConstPtr &msg)
{
mtx_buffer.lock();
// std::cout<<"got feature"<<std::endl;
if (msg->header.stamp.toSec() < last_timestamp_lidar)
{
ROS_ERROR("lidar loop back, clear buffer");
lidar_buffer.clear();
}
// ROS_INFO("get point cloud at time: %.6f", msg->header.stamp.toSec());
lidar_buffer.push_back(msg);
last_timestamp_lidar = msg->header.stamp.toSec();
mtx_buffer.unlock();
sig_buffer.notify_all();
}
void imu_cbk(const sensor_msgs::Imu::ConstPtr &msg_in)
{
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);
// std::cout<<"got imu: "<<timestamp<<" imu size "<<imu_buffer.size()<<std::endl;
mtx_buffer.unlock();
sig_buffer.notify_all();
}
bool sync_packages(MeasureGroup &meas)
{
if (lidar_buffer.empty() || imu_buffer.empty()) {
return false;
}
/*** push lidar frame ***/
if(!lidar_pushed)
{
meas.lidar.reset(new PointCloudXYZI());
pcl::fromROSMsg(*(lidar_buffer.front()), *(meas.lidar));
meas.lidar_beg_time = lidar_buffer.front()->header.stamp.toSec();
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-01-14 15:33:31 +08:00
if(imu_time > lidar_end_time + 0.02) break;
2020-11-01 00:17:32 +08:00
meas.imu.push_back(imu_buffer.front());
imu_buffer.pop_front();
}
lidar_buffer.pop_front();
lidar_pushed = false;
2021-01-14 15:33:31 +08:00
// if (meas.imu.empty()) return false;
2020-11-01 00:17:32 +08:00
// std::cout<<"[IMU Sycned]: "<<imu_time<<" "<<lidar_end_time<<std::endl;
return true;
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "laserMapping");
ros::NodeHandle nh;
ros::Subscriber sub_pcl = nh.subscribe("/laser_cloud_flat", 20000, feat_points_cbk);
ros::Subscriber sub_imu = nh.subscribe("/livox/imu", 20000, imu_cbk);
ros::Publisher pubLaserCloudFullRes = nh.advertise<sensor_msgs::PointCloud2>
("/cloud_registered", 100);
ros::Publisher pubLaserCloudEffect = nh.advertise<sensor_msgs::PointCloud2>
("/cloud_effected", 100);
2020-11-01 00:17:32 +08:00
ros::Publisher pubLaserCloudMap = nh.advertise<sensor_msgs::PointCloud2>
("/Laser_map", 100);
ros::Publisher pubOdomAftMapped = nh.advertise<nav_msgs::Odometry>
("/aft_mapped_to_init", 10);
2021-01-14 15:33:31 +08:00
ros::Publisher pubPath = nh.advertise<nav_msgs::Path>
("/path", 10);
2020-11-01 00:17:32 +08:00
#ifdef DEPLOY
ros::Publisher mavros_pose_publisher = nh.advertise<geometry_msgs::PoseStamped>("/mavros/vision_pose/pose", 10);
#endif
2021-01-14 15:33:31 +08:00
geometry_msgs::PoseStamped msg_body_pose;
nav_msgs::Path path;
path.header.stamp = ros::Time::now();
path.header.frame_id ="/camera_init";
2020-11-01 00:17:32 +08:00
/*** variables definition ***/
2021-01-14 15:33:31 +08:00
bool dense_map_en, flg_EKF_inited = 0, flg_map_inited = 0, flg_EKF_converged = 0;
2020-11-01 00:17:32 +08:00
std::string map_file_path;
int effect_feat_num = 0, frame_num = 0;
double filter_size_corner_min, filter_size_surf_min, filter_size_map_min, fov_deg,\
deltaT, deltaR, aver_time_consu = 0, first_lidar_time = 0;
Eigen::Matrix<double,DIM_OF_STATES,DIM_OF_STATES> G, H_T_H, I_STATE;
G.setZero();
H_T_H.setZero();
I_STATE.setIdentity();
nav_msgs::Odometry odomAftMapped;
cv::Mat matA1(3, 3, CV_32F, cv::Scalar::all(0));
cv::Mat matD1(1, 3, CV_32F, cv::Scalar::all(0));
cv::Mat matV1(3, 3, CV_32F, cv::Scalar::all(0));
cv::Mat matP(6, 6, CV_32F, cv::Scalar::all(0));
PointType pointOri, pointSel, coeff;
PointCloudXYZI::Ptr feats_undistort(new PointCloudXYZI());
PointCloudXYZI::Ptr feats_down(new PointCloudXYZI());
PointCloudXYZI::Ptr laserCloudOri(new PointCloudXYZI());
PointCloudXYZI::Ptr coeffSel(new PointCloudXYZI());
pcl::VoxelGrid<PointType> downSizeFilterSurf;
pcl::VoxelGrid<PointType> downSizeFilterMap;
/*** variables initialize ***/
ros::param::get("~dense_map_enable",dense_map_en);
ros::param::get("~max_iteration",NUM_MAX_ITERATIONS);
ros::param::get("~map_file_path",map_file_path);
ros::param::get("~fov_degree",fov_deg);
ros::param::get("~filter_size_corner",filter_size_corner_min);
ros::param::get("~filter_size_surf",filter_size_surf_min);
ros::param::get("~filter_size_map",filter_size_map_min);
ros::param::get("~cube_side_length",cube_len);
HALF_FOV_COS = std::cos((fov_deg + 10.0) * 0.5 * PI_M / 180.0);
for (int i = 0; i < laserCloudNum; i++)
{
featsArray[i].reset(new PointCloudXYZI());
}
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);
std::shared_ptr<ImuProcess> p_imu(new ImuProcess());
/*** debug record ***/
std::ofstream fout_pre, fout_out;
fout_pre.open(DEBUG_FILE_DIR("mat_pre.txt"),std::ios::out);
fout_out.open(DEBUG_FILE_DIR("mat_out.txt"),std::ios::out);
if (fout_pre && fout_out)
std::cout << "~~~~"<<ROOT_DIR<<" file opened" << std::endl;
else
std::cout << "~~~~"<<ROOT_DIR<<" doesn't exist" << std::endl;
//------------------------------------------------------------------------------------------------------
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();
while(sync_packages(Measures))
{
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-01-14 15:33:31 +08:00
double t0,t1,t2,t3,t4,t5,match_start, match_time, solve_start, solve_time, pca_time, svd_time;
2020-11-01 00:17:32 +08:00
match_time = 0;
solve_time = 0;
pca_time = 0;
svd_time = 0;
2021-01-14 15:33:31 +08:00
t0 = omp_get_wtime();
2020-11-01 00:17:32 +08:00
p_imu->Process(Measures, state, feats_undistort);
2021-01-14 15:33:31 +08:00
StatesGroup state_propagat(state);
2020-11-01 00:17:32 +08:00
if (feats_undistort->empty() || (feats_undistort == NULL))
{
first_lidar_time = Measures.lidar_beg_time;
std::cout<<"not ready for odometry"<<std::endl;
continue;
}
if ((Measures.lidar_beg_time - first_lidar_time) < INIT_TIME)
{
2021-01-14 15:33:31 +08:00
flg_EKF_inited = false;
2020-11-01 00:17:32 +08:00
std::cout<<"||||||||||Initiallizing LiDar||||||||||"<<std::endl;
}
else
{
2021-01-14 15:33:31 +08:00
flg_EKF_inited = true;
2020-11-01 00:17:32 +08:00
}
/*** Compute the euler angle ***/
Eigen::Vector3d euler_cur = RotMtoEuler(state.rot_end);
fout_pre << std::setw(10) << Measures.lidar_beg_time << " " << euler_cur.transpose()*57.3 << " " << state.pos_end.transpose() << " " << state.vel_end.transpose() \
<<" "<<state.bias_g.transpose()<<" "<<state.bias_a.transpose()<< std::endl;
#ifdef DEBUG_PRINT
std::cout<<"current lidar time "<<Measures.lidar_beg_time<<" "<<"first lidar time "<<first_lidar_time<<std::endl;
std::cout<<"pre-integrated states: "<<euler_cur.transpose()*57.3<<" "<<state.pos_end.transpose()<<" "<<state.vel_end.transpose()<<" "<<state.bias_g.transpose()<<" "<<state.bias_a.transpose()<<std::endl;
#endif
/*** Segment the map in lidar FOV ***/
lasermap_fov_segment();
2021-01-14 15:33:31 +08:00
/*** downsample the features of new frame ***/
2020-11-01 00:17:32 +08:00
downSizeFilterSurf.setInputCloud(feats_undistort);
downSizeFilterSurf.filter(*feats_down);
2021-01-14 15:33:31 +08:00
#ifdef USE_ikdtree
/*** initialize the map kdtree ***/
if((feats_down->points.size() > 1) && (ikdtree.Root_Node == nullptr))
{
// std::vector<PointType> points_init = feats_down->points;
ikdtree.set_downsample_param(filter_size_map_min);
ikdtree.Build(feats_down->points);
flg_map_inited = true;
continue;
}
if(ikdtree.Root_Node == nullptr)
{
flg_map_inited = false;
std::cout<<"~~~~~~~Initiallize Map iKD-Tree Failed!"<<std::endl;
continue;
}
int featsFromMapNum = ikdtree.size();
#else
if(featsFromMap->points.empty())
{
downSizeFilterMap.setInputCloud(feats_down);
}
else
{
downSizeFilterMap.setInputCloud(featsFromMap);
}
downSizeFilterMap.filter(*featsFromMap);
2020-11-01 00:17:32 +08:00
int featsFromMapNum = featsFromMap->points.size();
2021-01-14 15:33:31 +08:00
#endif
2020-11-01 00:17:32 +08:00
int feats_down_size = feats_down->points.size();
std::cout<<"[ mapping ]: Raw feature num: "<<feats_undistort->points.size()<<" downsamp num "<<feats_down_size<<" Map num: "<<featsFromMapNum<<" laserCloudValidNum "<<laserCloudValidNum<<std::endl;
/*** ICP and iterated Kalman filter update ***/
PointCloudXYZI::Ptr coeffSel_tmpt (new PointCloudXYZI(*feats_down));
PointCloudXYZI::Ptr feats_down_updated (new PointCloudXYZI(*feats_down));
2021-01-14 15:33:31 +08:00
std::vector<double> res_last(feats_down_size, 1000.0); // initial
2020-11-01 00:17:32 +08:00
2021-01-14 15:33:31 +08:00
if (featsFromMapNum >= 5)
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
t1 = omp_get_wtime();
#ifdef USE_ikdtree
std::vector<PointVector> Nearest_Points(feats_down_size);
#else
2020-11-01 00:17:32 +08:00
kdtreeSurfFromMap->setInputCloud(featsFromMap);
2021-01-14 15:33:31 +08:00
#endif
2020-11-01 00:17:32 +08:00
std::vector<bool> point_selected_surf(feats_down_size, true);
std::vector<std::vector<int>> pointSearchInd_surf(feats_down_size);
int rematch_num = 0;
bool rematch_en = 0;
2021-01-14 15:33:31 +08:00
flg_EKF_converged = 0;
deltaR = 0.0;
deltaT = 0.0;
2020-11-01 00:17:32 +08:00
t2 = omp_get_wtime();
for (iterCount = 0; iterCount < NUM_MAX_ITERATIONS; iterCount++)
{
match_start = omp_get_wtime();
laserCloudOri->clear();
coeffSel->clear();
/** closest surface search and residual computation **/
omp_set_num_threads(4);
#pragma omp parallel for
for (int i = 0; i < feats_down_size; i++)
{
PointType &pointOri_tmpt = feats_down->points[i];
PointType &pointSel_tmpt = feats_down_updated->points[i];
/* transform to world frame */
pointBodyToWorld(&pointOri_tmpt, &pointSel_tmpt);
std::vector<float> pointSearchSqDis_surf;
2021-01-14 15:33:31 +08:00
#ifdef USE_ikdtree
auto &points_near = Nearest_Points[i];
#else
2020-11-01 00:17:32 +08:00
auto &points_near = pointSearchInd_surf[i];
2021-01-14 15:33:31 +08:00
#endif
2020-11-01 00:17:32 +08:00
if (iterCount == 0 || rematch_en)
{
2021-01-14 15:33:31 +08:00
point_selected_surf[i] = true;
/** Find the closest surfaces in the map **/
#ifdef USE_ikdtree
ikdtree.Nearest_Search(pointSel_tmpt, NUM_MATCH_POINTS, points_near, pointSearchSqDis_surf);
#else
2020-11-01 00:17:32 +08:00
kdtreeSurfFromMap->nearestKSearch(pointSel_tmpt, NUM_MATCH_POINTS, points_near, pointSearchSqDis_surf);
2021-01-14 15:33:31 +08:00
#endif
float max_distance = pointSearchSqDis_surf[NUM_MATCH_POINTS - 1];
if (max_distance > 3)
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
point_selected_surf[i] = false;
2020-11-01 00:17:32 +08:00
}
}
2021-01-14 15:33:31 +08:00
if (point_selected_surf[i] == false) continue;
// match_time += omp_get_wtime() - match_start;
2020-11-01 00:17:32 +08:00
double pca_start = omp_get_wtime();
/// PCA (using minimum square method)
cv::Mat matA0(NUM_MATCH_POINTS, 3, CV_32F, cv::Scalar::all(0));
cv::Mat matB0(NUM_MATCH_POINTS, 1, CV_32F, cv::Scalar::all(-1));
cv::Mat matX0(NUM_MATCH_POINTS, 1, CV_32F, cv::Scalar::all(0));
2021-01-14 15:33:31 +08:00
2020-11-01 00:17:32 +08:00
for (int j = 0; j < NUM_MATCH_POINTS; j++)
{
2021-01-14 15:33:31 +08:00
#ifdef USE_ikdtree
matA0.at<float>(j, 0) = points_near[j].x;
matA0.at<float>(j, 1) = points_near[j].y;
matA0.at<float>(j, 2) = points_near[j].z;
#else
2020-11-01 00:17:32 +08:00
matA0.at<float>(j, 0) = featsFromMap->points[points_near[j]].x;
matA0.at<float>(j, 1) = featsFromMap->points[points_near[j]].y;
matA0.at<float>(j, 2) = featsFromMap->points[points_near[j]].z;
2021-01-14 15:33:31 +08:00
#endif
2020-11-01 00:17:32 +08:00
}
//matA0*matX0=matB0
//AX+BY+CZ+D = 0 <=> AX+BY+CZ=-D <=> (A/D)X+(B/D)Y+(C/D)Z = -1
//(X,Y,Z)<=>mat_a0
//A/D, B/D, C/D <=> mat_x0
cv::solve(matA0, matB0, matX0, cv::DECOMP_QR); //TODO
float pa = matX0.at<float>(0, 0);
float pb = matX0.at<float>(1, 0);
float pc = matX0.at<float>(2, 0);
float pd = 1;
//ps is the norm of the plane norm_vec vector
//pd is the distance from point to plane
float ps = sqrt(pa * pa + pb * pb + pc * pc);
pa /= ps;
pb /= ps;
pc /= ps;
pd /= ps;
bool planeValid = true;
for (int j = 0; j < NUM_MATCH_POINTS; j++)
{
2021-01-14 15:33:31 +08:00
#ifdef USE_ikdtree
if (fabs(pa * points_near[j].x +
pb * points_near[j].y +
pc * points_near[j].z + pd) > 0.1)
#else
2020-11-01 00:17:32 +08:00
if (fabs(pa * featsFromMap->points[points_near[j]].x +
pb * featsFromMap->points[points_near[j]].y +
pc * featsFromMap->points[points_near[j]].z + pd) > 0.1)
2021-01-14 15:33:31 +08:00
#endif
2020-11-01 00:17:32 +08:00
{
planeValid = false;
point_selected_surf[i] = false;
break;
}
}
if (planeValid)
{
//loss fuction
float pd2 = pa * pointSel_tmpt.x + pb * pointSel_tmpt.y + pc * pointSel_tmpt.z + pd;
//if(fabs(pd2) > 0.1) continue;
float s = 1 - 0.9 * fabs(pd2) / sqrt(sqrt(pointSel_tmpt.x * pointSel_tmpt.x + pointSel_tmpt.y * pointSel_tmpt.y + pointSel_tmpt.z * pointSel_tmpt.z));
2021-01-14 15:33:31 +08:00
if ((s > 0.85))// && ((std::abs(pd2) - res_last[i]) < 3 * res_mean_last))
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
// if(std::abs(pd2) > 5 * res_mean_last)
// {
// point_selected_surf[i] = false;
// res_last[i] = 0.0;
// continue;
// }
2020-11-01 00:17:32 +08:00
point_selected_surf[i] = true;
coeffSel_tmpt->points[i].x = pa;
coeffSel_tmpt->points[i].y = pb;
coeffSel_tmpt->points[i].z = pc;
coeffSel_tmpt->points[i].intensity = pd2;
2021-01-14 15:33:31 +08:00
// if(i%50==0) std::cout<<"s: "<<s<<"last res: "<<res_last[i]<<" current res: "<<std::abs(pd2)<<std::endl;
res_last[i] = std::abs(pd2);
2020-11-01 00:17:32 +08:00
}
else
{
point_selected_surf[i] = false;
}
}
pca_time += omp_get_wtime() - pca_start;
}
double total_residual = 0.0;
2021-01-14 15:33:31 +08:00
laserCloudSelNum = 0;
2020-11-01 00:17:32 +08:00
for (int i = 0; i < coeffSel_tmpt->points.size(); i++)
{
2021-01-14 15:33:31 +08:00
if (point_selected_surf[i] && (res_last[i] <= 2.0))
2020-11-01 00:17:32 +08:00
{
laserCloudOri->push_back(feats_down->points[i]);
coeffSel->push_back(coeffSel_tmpt->points[i]);
2021-01-14 15:33:31 +08:00
total_residual += res_last[i];
laserCloudSelNum ++;
2020-11-01 00:17:32 +08:00
}
}
2021-01-14 15:33:31 +08:00
res_mean_last = total_residual / laserCloudSelNum;
std::cout << "[ mapping ]: Effective feature num: "<<laserCloudSelNum<<" res_mean_last "<<res_mean_last<<std::endl;
2020-11-01 00:17:32 +08:00
match_time += omp_get_wtime() - match_start;
solve_start = omp_get_wtime();
/*** Computation of Measuremnt Jacobian matrix H and measurents vector ***/
Eigen::MatrixXd Hsub(laserCloudSelNum, 6);
Eigen::VectorXd meas_vec(laserCloudSelNum);
Hsub.setZero();
2021-01-14 15:33:31 +08:00
// omp_set_num_threads(4);
// #pragma omp parallel for
2020-11-01 00:17:32 +08:00
for (int i = 0; i < laserCloudSelNum; i++)
{
const PointType &laser_p = laserCloudOri->points[i];
Eigen::Vector3d point_this(laser_p.x, laser_p.y, laser_p.z);
point_this += Lidar_offset_to_IMU;
Eigen::Matrix3d point_crossmat;
point_crossmat<<SKEW_SYM_MATRX(point_this);
/*** get the normal vector of closest surface/corner ***/
const PointType &norm_p = coeffSel->points[i];
Eigen::Vector3d norm_vec(norm_p.x, norm_p.y, norm_p.z);
/*** calculate the Measuremnt Jacobian matrix H ***/
Eigen::Vector3d A(point_crossmat * state.rot_end.transpose() * norm_vec);
Hsub.row(i) << VEC_FROM_ARRAY(A), norm_p.x, norm_p.y, norm_p.z;
/*** Measuremnt: distance to the closest surface/corner ***/
meas_vec(i) = - norm_p.intensity;
}
Eigen::Vector3d rot_add, t_add, v_add, bg_add, ba_add, g_add;
2021-01-14 15:33:31 +08:00
Eigen::Matrix<double, DIM_OF_STATES, 1> solution;
2020-11-01 00:17:32 +08:00
Eigen::MatrixXd K(DIM_OF_STATES, laserCloudSelNum);
/*** Iterative Kalman Filter Update ***/
2021-01-14 15:33:31 +08:00
if (!flg_EKF_inited)
2020-11-01 00:17:32 +08:00
{
/*** only run in initialization period ***/
Eigen::MatrixXd H_init(Eigen::Matrix<double, 9, DIM_OF_STATES>::Zero());
Eigen::MatrixXd z_init(Eigen::Matrix<double, 9, 1>::Zero());
H_init.block<3,3>(0,0) = Eigen::Matrix3d::Identity();
H_init.block<3,3>(3,3) = Eigen::Matrix3d::Identity();
H_init.block<3,3>(6,15) = Eigen::Matrix3d::Identity();
z_init.block<3,1>(0,0) = - Log(state.rot_end);
z_init.block<3,1>(0,0) = - state.pos_end;
auto H_init_T = H_init.transpose();
auto &&K_init = state.cov * H_init_T * (H_init * state.cov * H_init_T + 0.0001 * Eigen::Matrix<double,9,9>::Identity()).inverse();
solution = K_init * z_init;
solution.block<9,1>(0,0).setZero();
state += solution;
state.cov = (Eigen::MatrixXd::Identity(DIM_OF_STATES, DIM_OF_STATES) - K_init * H_init) * state.cov;
}
else
{
auto &&Hsub_T = Hsub.transpose();
H_T_H.block<6,6>(0,0) = Hsub_T * Hsub;
2021-01-14 15:33:31 +08:00
Eigen::Matrix<double, DIM_OF_STATES, DIM_OF_STATES> &&K_1 = \
(H_T_H + (state.cov / LASER_POINT_COV).inverse()).inverse();
2020-11-01 00:17:32 +08:00
K = K_1.block<DIM_OF_STATES,6>(0,0) * Hsub_T;
2021-01-14 15:33:31 +08:00
// solution = K * meas_vec;
// state += solution;
auto vec = state_propagat - state;
solution = K * (meas_vec - Hsub * vec.block<6,1>(0,0));
state = state_propagat + solution;
2020-11-01 00:17:32 +08:00
rot_add = solution.block<3,1>(0,0);
t_add = solution.block<3,1>(3,0);
2021-01-14 15:33:31 +08:00
flg_EKF_converged = false;
if (((rot_add.norm() * 57.3 - deltaR) < 0.01) \
&& ((t_add.norm() * 100 - deltaT) < 0.015))
{
flg_EKF_converged = true;
}
2020-11-01 00:17:32 +08:00
deltaR = rot_add.norm() * 57.3;
2021-01-14 15:33:31 +08:00
deltaT = t_add.norm() * 100;
2020-11-01 00:17:32 +08:00
}
euler_cur = RotMtoEuler(state.rot_end);
#ifdef DEBUG_PRINT
std::cout<<"update: R"<<euler_cur.transpose()*57.3<<" p "<<state.pos_end.transpose()<<" v "<<state.vel_end.transpose()<<" bg"<<state.bias_g.transpose()<<" ba"<<state.bias_a.transpose()<<std::endl;
2021-01-14 15:33:31 +08:00
std::cout<<"dR & dT: "<<deltaR<<" "<<deltaT<<" res norm:"<<res_mean_last<<std::endl;
2020-11-01 00:17:32 +08:00
#endif
/*** Rematch Judgement ***/
rematch_en = false;
2021-01-14 15:33:31 +08:00
if (flg_EKF_converged || ((rematch_num == 0) && (iterCount == (NUM_MAX_ITERATIONS - 2))))
2020-11-01 00:17:32 +08:00
{
rematch_en = true;
rematch_num ++;
2021-01-14 15:33:31 +08:00
std::cout<<"rematch_num: "<<rematch_num<<std::endl;
2020-11-01 00:17:32 +08:00
}
/*** Convergence Judgements and Covariance Update ***/
if (rematch_num >= 2 || (iterCount == NUM_MAX_ITERATIONS - 1))
{
2021-01-14 15:33:31 +08:00
if (flg_EKF_inited)
2020-11-01 00:17:32 +08:00
{
/*** Covariance Update ***/
G.block<DIM_OF_STATES,6>(0,0) = K * Hsub;
state.cov = (I_STATE - G) * state.cov;
2021-01-14 15:33:31 +08:00
total_distance += (state.pos_end - position_last).norm();
position_last = state.pos_end;
std::cout<<"position: "<<state.pos_end.transpose()<<" total distance: "<<total_distance<<std::endl;
2020-11-01 00:17:32 +08:00
}
solve_time += omp_get_wtime() - solve_start;
break;
}
solve_time += omp_get_wtime() - solve_start;
}
std::cout<<"[ mapping ]: iteration count: "<<iterCount+1<<std::endl;
2021-01-14 15:33:31 +08:00
t3 = omp_get_wtime();
/*** add new frame points to map ikdtree ***/
#ifdef USE_ikdtree
PointVector points_history;
ikdtree.acquire_removed_points(points_history);
memset(cube_updated, 0, sizeof(cube_updated));
for (int i = 0; i < points_history.size(); i++)
{
PointType &pointSel = points_history[i];
int cubeI = int((pointSel.x + 0.5 * cube_len) / cube_len) + laserCloudCenWidth;
int cubeJ = int((pointSel.y + 0.5 * cube_len) / cube_len) + laserCloudCenHeight;
int cubeK = int((pointSel.z + 0.5 * cube_len) / cube_len) + laserCloudCenDepth;
if (pointSel.x + 0.5 * cube_len < 0) cubeI--;
if (pointSel.y + 0.5 * cube_len < 0) cubeJ--;
if (pointSel.z + 0.5 * cube_len < 0) cubeK--;
if (cubeI >= 0 && cubeI < laserCloudWidth &&
cubeJ >= 0 && cubeJ < laserCloudHeight &&
cubeK >= 0 && cubeK < laserCloudDepth)
{
int cubeInd = cubeI + laserCloudWidth * cubeJ + laserCloudWidth * laserCloudHeight * cubeK;
featsArray[cubeInd]->push_back(pointSel);
}
2020-11-01 00:17:32 +08:00
}
2021-01-14 15:33:31 +08:00
// omp_set_num_threads(4);
// #pragma omp parallel for
for (int i = 0; i < feats_down_size; i++)
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
/* transform to world frame */
pointBodyToWorld(&(feats_down->points[i]), &(feats_down_updated->points[i]));
2020-11-01 00:17:32 +08:00
}
2021-01-14 15:33:31 +08:00
t4 = omp_get_wtime();
ikdtree.Add_Points(feats_down_updated->points, true);
#else
bool cube_updated[laserCloudNum] = {0};
for (int i = 0; i < feats_down_size; i++)
{
PointType &pointSel = feats_down_updated->points[i];
int cubeI = int((pointSel.x + 0.5 * cube_len) / cube_len) + laserCloudCenWidth;
int cubeJ = int((pointSel.y + 0.5 * cube_len) / cube_len) + laserCloudCenHeight;
int cubeK = int((pointSel.z + 0.5 * cube_len) / cube_len) + laserCloudCenDepth;
if (pointSel.x + 0.5 * cube_len < 0) cubeI--;
if (pointSel.y + 0.5 * cube_len < 0) cubeJ--;
if (pointSel.z + 0.5 * cube_len < 0) cubeK--;
if (cubeI >= 0 && cubeI < laserCloudWidth &&
cubeJ >= 0 && cubeJ < laserCloudHeight &&
cubeK >= 0 && cubeK < laserCloudDepth) {
int cubeInd = cubeI + laserCloudWidth * cubeJ + laserCloudWidth * laserCloudHeight * cubeK;
featsArray[cubeInd]->push_back(pointSel);
cube_updated[cubeInd] = true;
}
}
for (int i = 0; i < laserCloudValidNum; i++)
{
int ind = laserCloudValidInd[i];
2020-11-01 00:17:32 +08:00
2021-01-14 15:33:31 +08:00
if(cube_updated[ind])
{
downSizeFilterMap.setInputCloud(featsArray[ind]);
downSizeFilterMap.filter(*featsArray[ind]);
}
}
#endif
t5 = omp_get_wtime();
}
/******* Publish current frame points in world coordinates: *******/
2020-11-01 00:17:32 +08:00
laserCloudFullRes2->clear();
*laserCloudFullRes2 = dense_map_en ? (*feats_undistort) : (* feats_down);
int laserCloudFullResNum = laserCloudFullRes2->points.size();
2021-01-14 15:33:31 +08:00
pcl::PointXYZI temp_point;
2020-11-01 00:17:32 +08:00
laserCloudFullResColor->clear();
{
2020-11-01 00:17:32 +08:00
for (int i = 0; i < laserCloudFullResNum; i++)
{
RGBpointBodyToWorld(&laserCloudFullRes2->points[i], &temp_point);
laserCloudFullResColor->push_back(temp_point);
}
sensor_msgs::PointCloud2 laserCloudFullRes3;
pcl::toROSMsg(*laserCloudFullResColor, laserCloudFullRes3);
laserCloudFullRes3.header.stamp = ros::Time::now();//.fromSec(last_timestamp_lidar);
laserCloudFullRes3.header.frame_id = "/camera_init";
pubLaserCloudFullRes.publish(laserCloudFullRes3);
}
/******* Publish Effective points *******/
2021-01-14 15:33:31 +08:00
{
laserCloudFullResColor->clear();
pcl::PointXYZI temp_point;
for (int i = 0; i < laserCloudSelNum; i++)
{
RGBpointBodyToWorld(&laserCloudOri->points[i], &temp_point);
laserCloudFullResColor->push_back(temp_point);
}
sensor_msgs::PointCloud2 laserCloudFullRes3;
pcl::toROSMsg(*laserCloudFullResColor, laserCloudFullRes3);
laserCloudFullRes3.header.stamp = ros::Time::now();//.fromSec(last_timestamp_lidar);
laserCloudFullRes3.header.frame_id = "/camera_init";
pubLaserCloudEffect.publish(laserCloudFullRes3);
}
2020-11-01 00:17:32 +08:00
/******* Publish Maps: *******/
2021-01-14 15:33:31 +08:00
sensor_msgs::PointCloud2 laserCloudMap;
pcl::toROSMsg(*featsFromMap, laserCloudMap);
laserCloudMap.header.stamp = ros::Time::now();//ros::Time().fromSec(last_timestamp_lidar);
laserCloudMap.header.frame_id = "/camera_init";
pubLaserCloudMap.publish(laserCloudMap);
2020-11-01 00:17:32 +08:00
/******* Publish Odometry ******/
geometry_msgs::Quaternion geoQuat = tf::createQuaternionMsgFromRollPitchYaw
2021-01-14 15:33:31 +08:00
(euler_cur(0), euler_cur(1), euler_cur(2));
2020-11-01 00:17:32 +08:00
odomAftMapped.header.frame_id = "/camera_init";
odomAftMapped.child_frame_id = "/aft_mapped";
odomAftMapped.header.stamp = ros::Time::now();//ros::Time().fromSec(last_timestamp_lidar);
2021-01-14 15:33:31 +08:00
odomAftMapped.pose.pose.orientation.x = geoQuat.x;
odomAftMapped.pose.pose.orientation.y = geoQuat.y;
odomAftMapped.pose.pose.orientation.z = geoQuat.z;
2020-11-01 00:17:32 +08:00
odomAftMapped.pose.pose.orientation.w = geoQuat.w;
odomAftMapped.pose.pose.position.x = state.pos_end(0);
odomAftMapped.pose.pose.position.y = state.pos_end(1);
odomAftMapped.pose.pose.position.z = state.pos_end(2);
pubOdomAftMapped.publish(odomAftMapped);
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" ) );
2021-01-14 15:33:31 +08:00
2020-11-01 00:17:32 +08:00
msg_body_pose.header.stamp = ros::Time::now();
msg_body_pose.header.frame_id = "/camera_odom_frame";
msg_body_pose.pose.position.x = state.pos_end(0);
2021-01-14 15:33:31 +08:00
msg_body_pose.pose.position.y = state.pos_end(1);
msg_body_pose.pose.position.z = state.pos_end(2);
msg_body_pose.pose.orientation.x = geoQuat.x;
msg_body_pose.pose.orientation.y = geoQuat.y;
msg_body_pose.pose.orientation.z = geoQuat.z;
2020-11-01 00:17:32 +08:00
msg_body_pose.pose.orientation.w = geoQuat.w;
2021-01-14 15:33:31 +08:00
#ifdef DEPLOY
2020-11-01 00:17:32 +08:00
mavros_pose_publisher.publish(msg_body_pose);
#endif
2021-01-14 15:33:31 +08:00
/******* Publish Path ********/
msg_body_pose.header.frame_id = "/camera_init";
path.poses.push_back(msg_body_pose);
pubPath.publish(path);
2020-11-01 00:17:32 +08:00
/*** save debug variables ***/
frame_num ++;
2021-01-14 15:33:31 +08:00
aver_time_consu = aver_time_consu * (frame_num - 1) / frame_num + (t5 - t0) / frame_num;
// aver_time_consu = aver_time_consu * 0.8 + (t5 - t0) * 0.2;
2020-11-01 00:17:32 +08:00
T1.push_back(Measures.lidar_beg_time);
s_plot.push_back(aver_time_consu);
2021-01-14 15:33:31 +08:00
s_plot2.push_back(t5 - t3);
s_plot3.push_back(match_time);
s_plot4.push_back(float(feats_down_size/10000.0));
s_plot5.push_back(t5 - t0);
// std::cout<<"[ mapping ]: time: copy map "<<copy_time<<" readd: "<<readd_time<<" match "<<match_time<<" solve "<<solve_time<<"acquire: "<<t4-t3<<" map incre "<<t5-t4<<" total "<<aver_time_consu<<std::endl;
// fout_out << std::setw(10) << Measures.lidar_beg_time << " " << euler_cur.transpose()*57.3 << " " << state.pos_end.transpose() << " " << state.vel_end.transpose() \
// <<" "<<state.bias_g.transpose()<<" "<<state.bias_a.transpose()<< std::endl;
fout_out<<std::setw(8)<<laserCloudSelNum<<" "<<Measures.lidar_beg_time<<" "<<t2-t0<<" "<<match_time<<" "<<t5-t3<<" "<<t5-t0<<std::endl;
2020-11-01 00:17:32 +08:00
}
status = ros::ok();
rate.sleep();
}
//--------------------------save map---------------
2021-01-14 15:33:31 +08:00
// std::string surf_filename(map_file_path + "/surf.pcd");
// std::string corner_filename(map_file_path + "/corner.pcd");
// std::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)
// {
// pcl::PCDWriter pcd_writer;
// std::cout << "saving...";
// pcd_writer.writeBinary(surf_filename, surf_points);
// pcd_writer.writeBinary(corner_filename, corner_points);
// }
#ifdef DEPLOY
if (!T1.empty())
2020-11-01 00:17:32 +08:00
{
2021-01-14 15:33:31 +08:00
// plt::named_plot("add new frame",T1,s_plot2);
// plt::named_plot("search and pca",T1,s_plot3);
// plt::named_plot("newpoints number",T1,s_plot4);
plt::named_plot("total time",T1,s_plot5);
plt::named_plot("average time",T1,s_plot);
// plt::named_plot("readd",T2,s_plot6);
plt::legend();
plt::show();
plt::pause(0.5);
plt::close();
2020-11-01 00:17:32 +08:00
}
2021-01-14 15:33:31 +08:00
std::cout << "no points saved";
#endif
2020-11-01 00:17:32 +08:00
return 0;
}