Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pulling updates from developer #1

Open
wants to merge 36 commits into
base: lantegi
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
aa8a925
Added GPS odometry unavailability issue
pallavbhalla Dec 23, 2020
c4952e1
Merge pull request #176 from Pallav1299/doc
TixiaoShan Dec 23, 2020
e040db4
Add visualization_msgs as dependency, solves #157
Timple Jan 6, 2021
93f29f5
Merge pull request #185 from Timple/master
TixiaoShan Jan 6, 2021
affc9b5
add save_map service
zang09 Jan 28, 2021
ec78ce8
Update README.md
zang09 Jan 28, 2021
1e9d5e7
Merge pull request #196 from zang09/master
TixiaoShan Jan 30, 2021
944cda4
Update sample dataset download link
TixiaoShan Feb 2, 2021
10dc976
fix keyframe downsample bug in global visualization
SpriteLin-ZJU Feb 23, 2021
6a8168b
fix keyframe id downsample bug in function extractNeatby()
SpriteLin-ZJU Feb 23, 2021
9b8c3e9
remove resize before nearestKSearch
SpriteLin-ZJU Feb 23, 2021
2d6e50d
Merge pull request #205 from SpriteLin-ZJU/master
TixiaoShan Feb 23, 2021
3cdc8af
mention ros2 branch in README.md
grischi Jun 10, 2021
3a3d82f
Merge pull request #255 from grischi/master
TixiaoShan Jun 13, 2021
059372e
update GTSAM install instructions
TixiaoShan Jan 26, 2022
04d2e15
some typos
TixiaoShan Jan 26, 2022
af83648
add publishing unregistered keyframe cloud
TixiaoShan Jan 26, 2022
ab97ea3
publish slam info for 3rd-party usage
TixiaoShan Jan 27, 2022
20fdc6d
add publishing to 3rd-party packages
TixiaoShan Feb 4, 2022
4f2ccdb
adjust publishCloud()
TixiaoShan Feb 4, 2022
3cc124e
remove vscode folder
TixiaoShan Feb 4, 2022
0e7700c
add livox support (need customized driver from my repo)
TixiaoShan Feb 4, 2022
ad32c99
update readme for Livox Horizon support
TixiaoShan Feb 5, 2022
6665aa0
update readme
TixiaoShan Feb 5, 2022
0cdc9e8
Update readme for Noetic
TixiaoShan Apr 11, 2022
df05f8a
Give extrinsicRPY a clearer definition
inntoy Apr 27, 2022
e0b77a9
Merge pull request #339 from inntoy/extRPY_correct
TixiaoShan Apr 27, 2022
72d7dc9
Add Dockerfile
YanBC May 17, 2022
c4a4d5a
Set workdir
YanBC May 18, 2022
4238317
use compatible GTSAM version 4.0.2
TixiaoShan May 31, 2022
fda8c03
Update README.md
TixiaoShan May 31, 2022
4fc42fa
Update CMakeLists.txt
TixiaoShan May 31, 2022
9991daa
Merge pull request #345 from YanBC/feature/run_in_docker
TixiaoShan Jul 7, 2022
5c0eb4a
Update README.md
TixiaoShan Dec 10, 2022
4f22016
Update README.md
TixiaoShan Dec 10, 2022
0be1fbe
Update README.md
TixiaoShan Apr 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ find_package(catkin REQUIRED COMPONENTS
geometry_msgs
nav_msgs
message_generation
visualization_msgs
)

find_package(OpenMP REQUIRED)
Expand All @@ -31,6 +32,12 @@ add_message_files(
cloud_info.msg
)

add_service_files(
DIRECTORY srv
FILES
save_map.srv
)

generate_messages(
DEPENDENCIES
geometry_msgs
Expand All @@ -43,13 +50,14 @@ catkin_package(
INCLUDE_DIRS include
DEPENDS PCL GTSAM

CATKIN_DEPENDS
CATKIN_DEPENDS
std_msgs
nav_msgs
geometry_msgs
sensor_msgs
message_runtime
message_runtime
message_generation
visualization_msgs
)

# include directories
Expand Down Expand Up @@ -91,4 +99,4 @@ target_link_libraries(${PROJECT_NAME}_mapOptmization ${catkin_LIBRARIES} ${PCL_L

# IMU Preintegration
add_executable(${PROJECT_NAME}_imuPreintegration src/imuPreintegration.cpp)
target_link_libraries(${PROJECT_NAME}_imuPreintegration ${catkin_LIBRARIES} ${PCL_LIBRARIES} ${OpenCV_LIBRARIES} gtsam)
target_link_libraries(${PROJECT_NAME}_imuPreintegration ${catkin_LIBRARIES} ${PCL_LIBRARIES} ${OpenCV_LIBRARIES} gtsam)
63 changes: 44 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<img src="./config/doc/device-hand-2.png" alt="drawing" width="200"/>
<img src="./config/doc/device-hand.png" alt="drawing" width="200"/>
<img src="./config/doc/device-jackal.png" alt="drawing" width="200"/>
<img src="./config/doc/device-boat.png" alt="drawing" width="200"/>
<img src="./config/doc/device-livox-horizon.png" alt="drawing" width="200"/>
</p>

## Menu
Expand Down Expand Up @@ -53,20 +53,19 @@ We design a system that maintains two graphs and runs up to 10x faster than real

## Dependency

This is the original ROS1 implementation of LIO-SAM. For a ROS2 implementation see branch `ros2`.

- [ROS](http://wiki.ros.org/ROS/Installation) (tested with Kinetic and Melodic)
```
sudo apt-get install -y ros-kinetic-navigation
sudo apt-get install -y ros-kinetic-robot-localization
sudo apt-get install -y ros-kinetic-robot-state-publisher
```
- [gtsam](https://github.com/borglab/gtsam/releases) (Georgia Tech Smoothing and Mapping library)
- [gtsam](https://gtsam.org/get_started/) (Georgia Tech Smoothing and Mapping library)
```
wget -O ~/Downloads/gtsam.zip https://github.com/borglab/gtsam/archive/4.0.2.zip
cd ~/Downloads/ && unzip gtsam.zip -d ~/Downloads/
cd ~/Downloads/gtsam-4.0.2/
mkdir build && cd build
cmake -DGTSAM_BUILD_WITH_MARCH_NATIVE=OFF ..
sudo make install -j8
sudo add-apt-repository ppa:borglab/gtsam-release-4.0
sudo apt update
sudo apt install libgtsam-dev libgtsam-unstable-dev
```

## Install
Expand Down Expand Up @@ -106,23 +105,26 @@ The user needs to prepare the point cloud data in the correct format for cloud d

## Sample datasets

* Download some sample datasets to test the functionality of the package. The datasets below is configured to run using the default settings:
- **Walking dataset:** [[Google Drive](https://drive.google.com/file/d/1HN5fYPXEHbDq0E5JtbQPkCHIHUoTFFnN/view?usp=sharing)][[Dropbox](https://www.dropbox.com/s/jzql78speb1jbcc/casual_walk.bag.zip?dl=0)]
- **Park dataset:** [[Google Drive](https://drive.google.com/file/d/19PZieaJaVkXDs2ZromaHTxYoq0zkiHae/view?usp=sharing)][[Dropbox](https://www.dropbox.com/s/fnuxpdc4f9yyb55/park.bag.zip?dl=0)]
- **Garden dataset:** [[Google Drive](https://drive.google.com/file/d/1q6yuVhyJbkUBhut9yhfox2WdV4VZ9BZX/view?usp=sharing)]
* Download some sample datasets to test the functionality of the package. The datasets below are configured to run using the default settings:
- **Walking dataset:** [[Google Drive](https://drive.google.com/drive/folders/1gJHwfdHCRdjP7vuT556pv8atqrCJPbUq?usp=sharing)]
- **Park dataset:** [[Google Drive](https://drive.google.com/drive/folders/1gJHwfdHCRdjP7vuT556pv8atqrCJPbUq?usp=sharing)]
- **Garden dataset:** [[Google Drive](https://drive.google.com/drive/folders/1gJHwfdHCRdjP7vuT556pv8atqrCJPbUq?usp=sharing)]

* The datasets below need the parameters to be configured. In these datasets, the point cloud topic is "points_raw." The IMU topic is "imu_correct," which gives the IMU data in ROS REP105 standard. Because no IMU transformation is needed for this dataset, the following configurations need to be changed to run this dataset successfully:
- The "imuTopic" parameter in "config/params.yaml" needs to be set to "imu_correct".
- The "extrinsicRot" and "extrinsicRPY" in "config/params.yaml" needs to be set as identity matrices.
- **Rotation dataset:** [[Google Drive](https://drive.google.com/file/d/1V4ijY4PgLdjKmdzcQ18Xu7VdcHo2UaWI/view?usp=sharing)][[Dropbox](https://www.dropbox.com/s/xdwzjnqwr7x19cl/rotation.bag.zip?dl=0)]
- **Campus dataset (large):** [[Google Drive](https://drive.google.com/file/d/1q4Sf7s2veVc7bs08Qeha3stOiwsytopL/view?usp=sharing)][[Dropbox](https://www.dropbox.com/s/etgnfg39ha79b7a/big_loop.bag.zip?dl=0)]
- **Campus dataset (small):** [[Google Drive](https://drive.google.com/file/d/1_V-cFMTQ4RO-_16mU9YPUE8ozsPeddCv/view?usp=sharing)][[Dropbox](https://www.dropbox.com/s/33u6epkfu36i1fd/west.bag.zip?dl=0)]
- **Rotation dataset:** [[Google Drive](https://drive.google.com/drive/folders/1gJHwfdHCRdjP7vuT556pv8atqrCJPbUq?usp=sharing)]
- **Campus dataset (large):** [[Google Drive](https://drive.google.com/drive/folders/1gJHwfdHCRdjP7vuT556pv8atqrCJPbUq?usp=sharing)]
- **Campus dataset (small):** [[Google Drive](https://drive.google.com/drive/folders/1gJHwfdHCRdjP7vuT556pv8atqrCJPbUq?usp=sharing)]

* Ouster (OS1-128) dataset. No extrinsics need to be changed for this dataset if you are using the default settings. Please follow the Ouster notes below to configure the package to run with Ouster data. A video of the dataset can be found on [YouTube](https://youtu.be/O7fKgZQzkEo):
- **Rooftop dataset:** [[Google Drive](https://drive.google.com/file/d/1Qy2rZdPudFhDbATPpblioBb8fRtjDGQj/view?usp=sharing)]
- **Rooftop dataset:** [[Google Drive](https://drive.google.com/drive/folders/1gJHwfdHCRdjP7vuT556pv8atqrCJPbUq?usp=sharing)]

* Livox Horizon dataset. Please refer to the following notes section for paramater changes.
- **Livox Horizon:** [[Google Drive](https://drive.google.com/drive/folders/1gJHwfdHCRdjP7vuT556pv8atqrCJPbUq?usp=sharing)]

* KITTI dataset. The extrinsics can be found in the Notes KITTI section below. To generate more bags using other KITTI raw data, you can use the python script provided in "config/doc/kitti2bag".
- **2011_09_30_drive_0028:** [[Google Drive](https://drive.google.com/file/d/12h3ooRAZVTjoMrf3uv1_KriEXm33kHc7/view?usp=sharing)]
- **2011_09_30_drive_0028:** [[Google Drive](https://drive.google.com/drive/folders/1gJHwfdHCRdjP7vuT556pv8atqrCJPbUq?usp=sharing)]

## Run the package

Expand Down Expand Up @@ -164,7 +166,7 @@ rosbag play your-bag.bag -r 3
<img src="./config/doc/kitti-demo.gif" alt="drawing" width="300"/>
</p>

- **Ouster lidar:** To make LIO-SAM work with Ouster lidar, some preparations needs to be done on hardware and software level.
- **Ouster lidar:** To make LIO-SAM work with Ouster lidar, some preparations need to be done on hardware and software level.
- Hardware:
- Use an external IMU. LIO-SAM does not work with the internal 6-axis IMU of Ouster lidar. You need to attach a 9-axis IMU to the lidar and perform data-gathering.
- Configure the driver. Change "timestamp_mode" in your Ouster launch file to "TIME_FROM_PTP_1588" so you can have ROS format timestamp for the point clouds.
Expand All @@ -179,6 +181,28 @@ rosbag play your-bag.bag -r 3
<img src="./config/doc/ouster-demo.gif" alt="drawing" width="300"/>
</p>

- **Livox Horizon lidar:** Please note that solid-state lidar hasn't been extensively tested with LIO-SAM yet. An external IMU is also used here rather than the internal one. The support for such lidars is based on minimal change of the codebase from mechanical lidars. A customized [livox_ros_driver](https://github.com/TixiaoShan/livox_ros_driver) needs to be used to publish point cloud format that can be processed by LIO-SAM. Other SLAM solutions may offer better implementations. More studies and suggestions are welcome. Please change the following parameters to make LIO-SAM work with Livox Horizon lidar:
- sensor: livox
- N_SCAN: 6
- Horizon_SCAN: 4000
- edgeFeatureMinValidNum: 1
- Use [livox_ros_driver](https://github.com/TixiaoShan/livox_ros_driver) for data recording

<p align='center'>
<img src="./config/doc/livox-demo.gif" alt="drawing" width="600"/>
</p>

## Service
- /lio_sam/save_map
- save map as a PCD file.
``` bash
rosservice call [service] [resolution] [destination]
```
- Example:
``` bash
$ rosservice call /lio_sam/save_map 0.2 "/Downloads/LOAM/"
```

## Issues

- **Zigzag or jerking behavior**: if your lidar and IMU data formats are consistent with the requirement of LIO-SAM, this problem is likely caused by un-synced timestamp of lidar and IMU data.
Expand All @@ -187,6 +211,8 @@ rosbag play your-bag.bag -r 3

- **mapOptimization crash**: it is usually caused by GTSAM. Please install the GTSAM specified in the README.md. More similar issues can be found [here](https://github.com/TixiaoShan/LIO-SAM/issues).

- **gps odometry unavailable**: it is generally caused due to unavailable transform between message frame_ids and robot frame_id (for example: transform should be available from "imu_frame_id" and "gps_frame_id" to "base_link" frame. Please read the Robot Localization documentation found [here](http://docs.ros.org/en/melodic/api/robot_localization/html/preparing_sensor_data.html).

## Paper

Thank you for citing [LIO-SAM (IROS-2020)](./config/doc/paper.pdf) if you use any of this code.
Expand Down Expand Up @@ -220,7 +246,6 @@ Part of the code is adapted from [LeGO-LOAM](https://github.com/RobustFieldAuton
## Related Package

- [Lidar-IMU calibration](https://github.com/chennuo0125-HIT/lidar_imu_calib)
- [LIO-SAM with ROS2](https://github.com/CAKGOD/lio_sam_ros2)
- [LIO-SAM with Scan Context](https://github.com/gisbi-kim/SC-LIO-SAM)

## Acknowledgement
Expand Down
Binary file added config/doc/device-livox-horizon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added config/doc/livox-demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions config/params.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ lio_sam:
savePCDDirectory: "/Downloads/LOAM/" # in your home folder, starts and ends with "/". Warning: the code deletes "LOAM" folder then recreates it. See "mapOptimization" for implementation

# Sensor Settings
sensor: velodyne # lidar sensor type, either 'velodyne' or 'ouster'
N_SCAN: 16 # number of lidar channel (i.e., 16, 32, 64, 128)
Horizon_SCAN: 1800 # lidar horizontal resolution (Velodyne:1800, Ouster:512,1024,2048)
sensor: velodyne # lidar sensor type, 'velodyne' or 'ouster' or 'livox'
N_SCAN: 16 # number of lidar channel (i.e., Velodyne/Ouster: 16, 32, 64, 128, Livox Horizon: 6)
Horizon_SCAN: 1800 # lidar horizontal resolution (Velodyne:1800, Ouster:512,1024,2048, Livox Horizon: 4000)
downsampleRate: 1 # default: 1. Downsample your data if too many points. i.e., 16 = 64 / 4, 16 = 16 / 1
lidarMinRange: 1.0 # default: 1.0, minimum lidar range to be used
lidarMaxRange: 1000.0 # default: 1000.0, maximum lidar range to be used
Expand Down
17 changes: 11 additions & 6 deletions include/utility.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#ifndef _UTILITY_LIDAR_ODOMETRY_H_
#define _UTILITY_LIDAR_ODOMETRY_H_
#define PCL_NO_PRECOMPILE

#include <ros/ros.h>

Expand Down Expand Up @@ -57,7 +58,7 @@ using namespace std;

typedef pcl::PointXYZI PointType;

enum class SensorType { VELODYNE, OUSTER };
enum class SensorType { VELODYNE, OUSTER, LIVOX };

class ParamServer
{
Expand Down Expand Up @@ -182,10 +183,14 @@ class ParamServer
{
sensor = SensorType::OUSTER;
}
else if (sensorStr == "livox")
{
sensor = SensorType::LIVOX;
}
else
{
ROS_ERROR_STREAM(
"Invalid sensor type (must be either 'velodyne' or 'ouster'): " << sensorStr);
"Invalid sensor type (must be either 'velodyne' or 'ouster' or 'livox'): " << sensorStr);
ros::shutdown();
}

Expand Down Expand Up @@ -277,15 +282,15 @@ class ParamServer
}
};


sensor_msgs::PointCloud2 publishCloud(ros::Publisher *thisPub, pcl::PointCloud<PointType>::Ptr thisCloud, ros::Time thisStamp, std::string thisFrame)
template<typename T>
sensor_msgs::PointCloud2 publishCloud(const ros::Publisher& thisPub, const T& thisCloud, ros::Time thisStamp, std::string thisFrame)
{
sensor_msgs::PointCloud2 tempCloud;
pcl::toROSMsg(*thisCloud, tempCloud);
tempCloud.header.stamp = thisStamp;
tempCloud.header.frame_id = thisFrame;
if (thisPub->getNumSubscribers() != 0)
thisPub->publish(tempCloud);
if (thisPub.getNumSubscribers() != 0)
thisPub.publish(tempCloud);
return tempCloud;
}

Expand Down
8 changes: 7 additions & 1 deletion msg/cloud_info.msg
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,10 @@ float32 initialGuessYaw
# Point cloud messages
sensor_msgs/PointCloud2 cloud_deskewed # original cloud deskewed
sensor_msgs/PointCloud2 cloud_corner # extracted corner feature
sensor_msgs/PointCloud2 cloud_surface # extracted surface feature
sensor_msgs/PointCloud2 cloud_surface # extracted surface feature

# 3rd party messages
sensor_msgs/PointCloud2 key_frame_cloud
sensor_msgs/PointCloud2 key_frame_color
sensor_msgs/PointCloud2 key_frame_poses
sensor_msgs/PointCloud2 key_frame_map
4 changes: 3 additions & 1 deletion package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<run_depend>roscpp</run_depend>
<build_depend>rospy</build_depend>
<run_depend>rospy</run_depend>

<build_depend>tf</build_depend>
<run_depend>tf</run_depend>

Expand All @@ -34,6 +34,8 @@
<run_depend>geometry_msgs</run_depend>
<build_depend>nav_msgs</build_depend>
<run_depend>nav_msgs</run_depend>
<build_depend>visualization_msgs</build_depend>
<run_depend>visualization_msgs</run_depend>

<build_depend>message_generation</build_depend>
<run_depend>message_generation</run_depend>
Expand Down
4 changes: 2 additions & 2 deletions src/featureExtraction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ class FeatureExtraction : public ParamServer
// free cloud info memory
freeCloudInfoMemory();
// save newly extracted features
cloudInfo.cloud_corner = publishCloud(&pubCornerPoints, cornerCloud, cloudHeader.stamp, lidarFrame);
cloudInfo.cloud_surface = publishCloud(&pubSurfacePoints, surfaceCloud, cloudHeader.stamp, lidarFrame);
cloudInfo.cloud_corner = publishCloud(pubCornerPoints, cornerCloud, cloudHeader.stamp, lidarFrame);
cloudInfo.cloud_surface = publishCloud(pubSurfacePoints, surfaceCloud, cloudHeader.stamp, lidarFrame);
// publish to mapOptimization
pubLaserCloudInfo.publish(cloudInfo);
}
Expand Down
30 changes: 21 additions & 9 deletions src/imageProjection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ class ImageProjection : public ParamServer
double timeScanEnd;
std_msgs::Header cloudHeader;

vector<int> columnIdnCountVec;


public:
ImageProjection():
Expand Down Expand Up @@ -138,6 +140,8 @@ class ImageProjection : public ParamServer
imuRotY[i] = 0;
imuRotZ[i] = 0;
}

columnIdnCountVec.assign(N_SCAN, 0);
}

~ImageProjection(){}
Expand Down Expand Up @@ -200,7 +204,7 @@ class ImageProjection : public ParamServer
// convert cloud
currentCloudMsg = std::move(cloudQueue.front());
cloudQueue.pop_front();
if (sensor == SensorType::VELODYNE)
if (sensor == SensorType::VELODYNE || sensor == SensorType::LIVOX)
{
pcl::moveFromROSMsg(currentCloudMsg, *laserCloudIn);
}
Expand Down Expand Up @@ -537,13 +541,21 @@ class ImageProjection : public ParamServer
if (rowIdn % downsampleRate != 0)
continue;

float horizonAngle = atan2(thisPoint.x, thisPoint.y) * 180 / M_PI;

static float ang_res_x = 360.0/float(Horizon_SCAN);
int columnIdn = -round((horizonAngle-90.0)/ang_res_x) + Horizon_SCAN/2;
if (columnIdn >= Horizon_SCAN)
columnIdn -= Horizon_SCAN;

int columnIdn = -1;
if (sensor == SensorType::VELODYNE || sensor == SensorType::OUSTER)
{
float horizonAngle = atan2(thisPoint.x, thisPoint.y) * 180 / M_PI;
static float ang_res_x = 360.0/float(Horizon_SCAN);
columnIdn = -round((horizonAngle-90.0)/ang_res_x) + Horizon_SCAN/2;
if (columnIdn >= Horizon_SCAN)
columnIdn -= Horizon_SCAN;
}
else if (sensor == SensorType::LIVOX)
{
columnIdn = columnIdnCountVec[rowIdn];
columnIdnCountVec[rowIdn] += 1;
}

if (columnIdn < 0 || columnIdn >= Horizon_SCAN)
continue;

Expand Down Expand Up @@ -588,7 +600,7 @@ class ImageProjection : public ParamServer
void publishClouds()
{
cloudInfo.header = cloudHeader;
cloudInfo.cloud_deskewed = publishCloud(&pubExtractedCloud, extractedCloud, cloudHeader.stamp, lidarFrame);
cloudInfo.cloud_deskewed = publishCloud(pubExtractedCloud, extractedCloud, cloudHeader.stamp, lidarFrame);
pubLaserCloudInfo.publish(cloudInfo);
}
};
Expand Down
Loading