Skip to content

Commit d3b256c

Browse files
author
ga58lar
committed
removed PCL dependency and combined scan and map loader
1 parent 9764336 commit d3b256c

File tree

9 files changed

+87
-92
lines changed

9 files changed

+87
-92
lines changed

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ RUN apt-get update && apt-get install -y -q --no-install-recommends \
3838
libgflags-dev \
3939
libatlas-base-dev \
4040
libsuitesparse-dev \
41-
libpcl-dev \
42-
python3-pip
41+
python3-pip \
42+
liblzf-dev
4343

4444
RUN pip install numpy ninja
4545

Dockerfile.dev

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ RUN apt-get update && apt-get install -y -q --no-install-recommends \
3838
libgflags-dev \
3939
libatlas-base-dev \
4040
libsuitesparse-dev \
41-
libpcl-dev \
42-
python3-pip
41+
python3-pip \
42+
liblzf-dev
4343

4444
RUN pip install numpy ninja
4545

cpp/CMakeLists.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
1414

1515
find_package(Eigen3 REQUIRED)
1616
find_package(Ceres REQUIRED)
17-
find_package(PCL REQUIRED)
1817
find_package(Iridescence REQUIRED)
1918

19+
find_path(LIBLZF_INCLUDE_DIR lzf.h PATH_SUFFIXES liblzf)
20+
find_library(LIBLZF_LIBRARY NAMES lzf liblzf)
21+
2022
# Fetch external dependencies
2123
include(FetchContent)
2224
FetchContent_Declare(small_gicp GIT_REPOSITORY https://github.com/ga58lar/small_gicp)
@@ -34,17 +36,15 @@ add_library(
3436
io/format/pcd.cpp
3537
io/format/ply.cpp
3638
io/loader_factory.cpp
37-
io/map_loader.cpp
3839
pipeline/openlidarmap.cpp
3940
utils/file_utils.cpp
4041
utils/pose_utils.cpp
4142
utils/helpers.cpp)
4243

43-
target_include_directories(openlidarmap_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${PCL_INCLUDE_DIRS}
44-
${small_gicp_INCLUDE_DIRS})
44+
target_include_directories(openlidarmap_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${small_gicp_INCLUDE_DIRS} ${LIBLZF_INCLUDE_DIR})
4545

46-
target_link_libraries(openlidarmap_lib PUBLIC Eigen3::Eigen small_gicp ${PCL_LIBRARIES} Ceres::ceres
47-
PRIVATE Iridescence::Iridescence stdc++fs)
46+
target_link_libraries(openlidarmap_lib PUBLIC Eigen3::Eigen small_gicp Ceres::ceres
47+
PRIVATE Iridescence::Iridescence stdc++fs ${LIBLZF_LIBRARY})
4848

4949
# Add executable
5050
add_executable(openlidarmap_cpp apps/main.cpp)

cpp/config/types.hpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,8 @@
44
#include <Eigen/Core>
55
#include <Eigen/Geometry>
66

7-
// PCL
8-
#include <pcl/point_cloud.h>
9-
#include <pcl/point_types.h>
10-
117
namespace openlidarmap {
128

13-
using PointT = pcl::PointXYZ;
14-
using PointCloudT = pcl::PointCloud<PointT>;
159
using Vector7d = Eigen::Matrix<double, 7, 1>;
1610

1711
} // namespace openlidarmap

cpp/io/format/pcd.cpp

Lines changed: 74 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <vector>
55
#include <cstring>
66
#include <iomanip>
7-
7+
#include <liblzf/lzf.h>
88

99
namespace openlidarmap::io {
1010

@@ -78,42 +78,6 @@ bool ParsePCDHeader(std::ifstream& file, PCDHeader& header) {
7878
return true;
7979
}
8080

81-
double UnpackBinary(const char* data_ptr, char type, int size) {
82-
switch (type) {
83-
case 'F': {
84-
if (size == 4) {
85-
float value;
86-
std::memcpy(&value, data_ptr, sizeof(float));
87-
return static_cast<double>(value);
88-
} else if (size == 8) {
89-
double value;
90-
std::memcpy(&value, data_ptr, sizeof(double));
91-
return value;
92-
}
93-
break;
94-
}
95-
case 'I': {
96-
switch (size) {
97-
case 1: return static_cast<double>(*reinterpret_cast<const int8_t*>(data_ptr));
98-
case 2: return static_cast<double>(*reinterpret_cast<const int16_t*>(data_ptr));
99-
case 4: return static_cast<double>(*reinterpret_cast<const int32_t*>(data_ptr));
100-
case 8: return static_cast<double>(*reinterpret_cast<const int64_t*>(data_ptr));
101-
}
102-
break;
103-
}
104-
case 'U': {
105-
switch (size) {
106-
case 1: return static_cast<double>(*reinterpret_cast<const uint8_t*>(data_ptr));
107-
case 2: return static_cast<double>(*reinterpret_cast<const uint16_t*>(data_ptr));
108-
case 4: return static_cast<double>(*reinterpret_cast<const uint32_t*>(data_ptr));
109-
case 8: return static_cast<double>(*reinterpret_cast<const uint64_t*>(data_ptr));
110-
}
111-
break;
112-
}
113-
}
114-
throw std::runtime_error("Unsupported PCD data type or size");
115-
}
116-
11781
small_gicp::PointCloud::Ptr PCDLoader::load(const std::string& file_path) {
11882
std::ifstream file(file_path, std::ios::binary);
11983
if (!file) {
@@ -140,7 +104,6 @@ small_gicp::PointCloud::Ptr PCDLoader::load(const std::string& file_path) {
140104
throw std::runtime_error("Missing XYZ fields in PCD file");
141105
}
142106

143-
// Reset file position and search for DATA line
144107
file.clear();
145108
file.seekg(0);
146109

@@ -182,6 +145,79 @@ small_gicp::PointCloud::Ptr PCDLoader::load(const std::string& file_path) {
182145
}
183146
points_read++;
184147
}
148+
} else if (header.is_compressed) {
149+
file.clear();
150+
file.seekg(0);
151+
152+
std::string line;
153+
while (std::getline(file, line)) {
154+
if (line.find("DATA binary_compressed") != std::string::npos) {
155+
break;
156+
}
157+
}
158+
159+
uint32_t compressed_size = 0, uncompressed_size = 0;
160+
if (!file.read(reinterpret_cast<char*>(&compressed_size), sizeof(compressed_size)) ||
161+
!file.read(reinterpret_cast<char*>(&uncompressed_size), sizeof(uncompressed_size))) {
162+
throw std::runtime_error("Failed to read size info");
163+
}
164+
165+
// Allocate buffers
166+
std::vector<char> compressed_data(compressed_size);
167+
std::vector<char> uncompressed_data(uncompressed_size);
168+
169+
// Read compressed data
170+
if (!file.read(compressed_data.data(), compressed_size)) {
171+
throw std::runtime_error("Failed to read compressed data");
172+
}
173+
174+
// Decompress using LZF
175+
int result = lzf_decompress(
176+
compressed_data.data(), compressed_size,
177+
uncompressed_data.data(), uncompressed_size
178+
);
179+
180+
if (result != uncompressed_size) {
181+
throw std::runtime_error("LZF decompression failed");
182+
}
183+
184+
// Points are stored field by field
185+
int strip_size = header.points;
186+
points.resize(header.points);
187+
188+
// Process each coordinate field
189+
for (const auto& field : header.fields) {
190+
const char* base_ptr = uncompressed_data.data() + field.offset * strip_size;
191+
192+
if (field.name == "x") {
193+
for (int i = 0; i < header.points; i++) {
194+
float value;
195+
std::memcpy(&value, base_ptr + i * field.size, sizeof(float));
196+
points[i][0] = value;
197+
}
198+
} else if (field.name == "y") {
199+
for (int i = 0; i < header.points; i++) {
200+
float value;
201+
std::memcpy(&value, base_ptr + i * field.size, sizeof(float));
202+
points[i][1] = value;
203+
}
204+
} else if (field.name == "z") {
205+
for (int i = 0; i < header.points; i++) {
206+
float value;
207+
std::memcpy(&value, base_ptr + i * field.size, sizeof(float));
208+
points[i][2] = value;
209+
points[i][3] = 1.0;
210+
}
211+
}
212+
}
213+
214+
// Apply range filtering
215+
auto it = std::remove_if(points.begin(), points.end(),
216+
[this](const Eigen::Vector4d& p) {
217+
const double norm = p.head<3>().norm();
218+
return norm < config_.preprocess_.min_range || norm > config_.preprocess_.max_range;
219+
});
220+
points.erase(it, points.end());
185221
} else {
186222
std::string line;
187223
while (std::getline(file, line) && points.size() < header.points) {

cpp/io/format/ply.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,6 @@ small_gicp::PointCloud::Ptr PLYLoader::load(const std::string& file_path) {
8080
throw std::runtime_error("Missing XYZ coordinates in PLY file");
8181
}
8282

83-
// Add debug output for first few points
84-
const int debug_points = 5;
85-
int points_output = 0;
86-
8783
if (header.is_binary) {
8884
// Read all properties per point
8985
std::vector<char> point_data(header.properties.size() * sizeof(float));

cpp/io/map_loader.cpp

Lines changed: 0 additions & 23 deletions
This file was deleted.

cpp/io/map_loader.hpp

Lines changed: 0 additions & 9 deletions
This file was deleted.

cpp/pipeline/openlidarmap.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include "pipeline/openlidarmap.hpp"
22
#include "utils/helpers.hpp"
33
#include "io/loader_factory.hpp"
4-
#include "io/map_loader.hpp"
54

65
#include <guik/viewer/async_light_viewer.hpp>
76
#include <guik/viewer/light_viewer.hpp>
@@ -14,6 +13,8 @@ Pipeline::Pipeline(const config::Config &config)
1413
preprocess_ = std::make_unique<Preprocess>(config_);
1514
scan2map_config_.registration_.removal_horizon = 1e9;
1615
scan2map_config_.registration_.max_num_points_in_cell = 100;
16+
scan2map_config_.preprocess_.min_range = -1e9;
17+
scan2map_config_.preprocess_.max_range = 1e9;
1718
scan2map_registration_ = std::make_unique<Registration>(scan2map_config_);
1819
scan2scan_registration_ = std::make_unique<Registration>(scan2scan_config_);
1920
pose_graph_ = std::make_unique<PoseGraph>(config_, poses_);
@@ -36,7 +37,7 @@ bool Pipeline::initialize(const std::string &map_path,
3637
output_path_ = output_path;
3738

3839
// Load and initialize map
39-
auto map_cloud = io::loadPCD_map(map_path);
40+
auto map_cloud = io::LoaderFactory::loadPointCloud(scan2map_config_, map_path);
4041
if (!scan2map_registration_->initialize(map_cloud, Eigen::Isometry3d::Identity())) {
4142
return false;
4243
}

0 commit comments

Comments
 (0)