Skip to content

Commit 707d44e

Browse files
author
Kenny Chen
committed
Add direct support for Livox xfer_format: 0
1 parent 07bf91e commit 707d44e

File tree

5 files changed

+42
-9
lines changed

5 files changed

+42
-9
lines changed

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ DLIO is a new lightweight LiDAR-inertial odometry algorithm with a novel coarse-
1212
## Instructions
1313

1414
### Sensor Setup & Compatibility
15-
DLIO has been extensively tested using a variety of sensor configurations and currently supports Ouster, Velodyne, Hesai, and Livox LiDARs. The point cloud should be of input type `sensor_msgs::PointCloud2` and the 6-axis IMU input type of `sensor_msgs::Imu`. For Livox sensors specifically, please use the `feature/livox-support` branch and the latest [`livox_ros_driver2`](https://github.com/Livox-SDK/livox_ros_driver2) package with `xfer_format: 1` and point cloud of input type `livox_ros_driver2::CustomMsg` (see [here](https://github.com/vectr-ucla/direct_lidar_inertial_odometry/issues/5) for more information).
15+
DLIO has been extensively tested using a variety of sensor configurations and currently supports Ouster, Velodyne, Hesai, and Livox LiDARs. The point cloud should be of input type `sensor_msgs::PointCloud2` and the 6-axis IMU input type of `sensor_msgs::Imu`.
16+
17+
For Livox sensors specifically, you can use the `master` branch directly if it is of type `sensor_msgs::PointCloud2` (`xfer_format: 0`), or the `feature/livox-support` branch and the latest [`livox_ros_driver2`](https://github.com/Livox-SDK/livox_ros_driver2) package if it is of type `livox_ros_driver2::CustomMsg` (`xfer_format: 1`) (see [here](https://github.com/vectr-ucla/direct_lidar_inertial_odometry/issues/5) for more information).
1618

1719
For best performance, extrinsic calibration between the LiDAR/IMU sensors and the robot's center-of-gravity should be inputted into `cfg/dlio.yaml`. If the exact values of these are unavailable, a rough LiDAR-to-IMU extrinsics can also be used (note however that performance will be degraded).
1820

@@ -56,7 +58,7 @@ roslaunch direct_lidar_inertial_odometry dlio.launch \
5658
imu_topic:=/robot/imu
5759
```
5860

59-
for Ouster, Velodyne, or Hesai sensors, or
61+
for Ouster, Velodyne, Hesai, or Livox (`xfer_format: 0`) sensors, or
6062

6163
```sh
6264
roslaunch direct_lidar_inertial_odometry dlio.launch \
@@ -65,7 +67,7 @@ roslaunch direct_lidar_inertial_odometry dlio.launch \
6567
imu_topic:=/robot/imu
6668
```
6769

68-
for Livox sensors.
70+
for Livox sensors (`xfer_format: 1`).
6971

7072
Be sure to change the topic names to your corresponding topics. Alternatively, edit the launch file directly if desired. If successful, you should see the following output in your terminal:
7173
<br>

cfg/params.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ dlio:
2828
odom:
2929

3030
gravity: 9.80665
31+
computeTimeOffset: true
3132

3233
imu:
3334
approximateGravity: false

include/dlio/dlio.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ std::string to_string_with_precision(const T a_value, const int n = 6)
7878
#include <direct_lidar_inertial_odometry/save_pcd.h>
7979

8080
namespace dlio {
81-
enum class SensorType { OUSTER, VELODYNE, HESAI, UNKNOWN };
81+
enum class SensorType { OUSTER, VELODYNE, HESAI, LIVOX, UNKNOWN };
8282

8383
class OdomNode;
8484
class MapNode;
@@ -89,9 +89,10 @@ namespace dlio {
8989
PCL_ADD_POINT4D;
9090
float intensity; // intensity
9191
union {
92-
std::uint32_t t; // time since beginning of scan in nanoseconds
93-
float time; // time since beginning of scan in seconds
94-
double timestamp; // absolute timestamp in seconds
92+
std::uint32_t t; // (Ouster) time since beginning of scan in nanoseconds
93+
float time; // (Velodyne) time since beginning of scan in seconds
94+
double timestamp; // (Hesai) absolute timestamp in seconds
95+
// (Livox) absolute timestamp in (seconds * 10e9)
9596
};
9697
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
9798
} EIGEN_ALIGN16;

include/dlio/odom.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,8 @@ class dlio::OdomNode {
286286

287287
double gravity_;
288288

289+
bool time_offset_;
290+
289291
bool adaptive_params_;
290292

291293
double obs_submap_thresh_;

src/dlio/odom.cc

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ void dlio::OdomNode::getParams() {
189189
// Gravity
190190
ros::param::param<double>("~dlio/odom/gravity", this->gravity_, 9.80665);
191191

192+
// Compute time offset between lidar and imu
193+
ros::param::param<bool>("~dlio/odom/computeTimeOffset", this->time_offset_, false);
194+
192195
// Keyframe Threshold
193196
ros::param::param<double>("~dlio/odom/keyframe/threshD", this->keyframe_thresh_dist_, 0.1);
194197
ros::param::param<double>("~dlio/odom/keyframe/threshR", this->keyframe_thresh_rot_, 1.0);
@@ -510,9 +513,12 @@ void dlio::OdomNode::getScanFromROS(const sensor_msgs::PointCloud2ConstPtr& pc)
510513
} else if (field.name == "time") {
511514
this->sensor = dlio::SensorType::VELODYNE;
512515
break;
513-
} else if (field.name == "timestamp") {
516+
} else if (field.name == "timestamp" && original_scan_->points[0].timestamp < 1e14) {
514517
this->sensor = dlio::SensorType::HESAI;
515518
break;
519+
} else if (field.name == "timestamp" && original_scan_->points[0].timestamp > 1e14) {
520+
this->sensor = dlio::SensorType::LIVOX;
521+
break;
516522
}
517523
}
518524

@@ -629,6 +635,14 @@ void dlio::OdomNode::deskewPointcloud() {
629635
extract_point_time = [&sweep_ref_time](boost::range::index_value<PointType&, long> pt)
630636
{ return pt.value().timestamp; };
631637

638+
} else if (this->sensor == dlio::SensorType::LIVOX) {
639+
point_time_cmp = [](const PointType& p1, const PointType& p2)
640+
{ return p1.timestamp < p2.timestamp; };
641+
point_time_neq = [](boost::range::index_value<PointType&, long> p1,
642+
boost::range::index_value<PointType&, long> p2)
643+
{ return p1.value().timestamp != p2.value().timestamp; };
644+
extract_point_time = [&sweep_ref_time](boost::range::index_value<PointType&, long> pt)
645+
{ return pt.value().timestamp * 1e-9f; };
632646
}
633647

634648
// copy points into deskewed_scan_ in order of timestamp
@@ -643,8 +657,16 @@ void dlio::OdomNode::deskewPointcloud() {
643657
// extract timestamps from points and put them in their own list
644658
std::vector<double> timestamps;
645659
std::vector<int> unique_time_indices;
660+
661+
// compute offset between sweep reference time and first point timestamp
662+
double offset = 0.0;
663+
if (this->time_offset_) {
664+
offset = sweep_ref_time - extract_point_time(*points_unique_timestamps.begin());
665+
}
666+
667+
// build list of unique timestamps and indices of first point with each timestamp
646668
for (auto it = points_unique_timestamps.begin(); it != points_unique_timestamps.end(); it++) {
647-
timestamps.push_back(extract_point_time(*it));
669+
timestamps.push_back(extract_point_time(*it) + offset);
648670
unique_time_indices.push_back(it->index());
649671
}
650672
unique_time_indices.push_back(deskewed_scan_->points.size());
@@ -1905,6 +1927,11 @@ void dlio::OdomNode::debug() {
19051927
<< "Sensor Rates: Hesai @ " + to_string_with_precision(avg_lidar_rate, 2)
19061928
+ " Hz, IMU @ " + to_string_with_precision(avg_imu_rate, 2) + " Hz"
19071929
<< "|" << std::endl;
1930+
} else if (this->sensor == dlio::SensorType::LIVOX) {
1931+
std::cout << "| " << std::left << std::setfill(' ') << std::setw(66)
1932+
<< "Sensor Rates: Livox @ " + to_string_with_precision(avg_lidar_rate, 2)
1933+
+ " Hz, IMU @ " + to_string_with_precision(avg_imu_rate, 2) + " Hz"
1934+
<< "|" << std::endl;
19081935
} else {
19091936
std::cout << "| " << std::left << std::setfill(' ') << std::setw(66)
19101937
<< "Sensor Rates: Unknown LiDAR @ " + to_string_with_precision(avg_lidar_rate, 2)

0 commit comments

Comments
 (0)